Skip to content

Commit

Permalink
Merge pull request #192 from oliver-oloughlin/kv-schema-docs
Browse files Browse the repository at this point in the history
chore: added jsdoc for zod kv schemas
  • Loading branch information
oliver-oloughlin authored Mar 8, 2024
2 parents e371839 + 1a5b215 commit 723e159
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 18 deletions.
5 changes: 3 additions & 2 deletions deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@olli/kvdex",
"version": "0.35.1",
"version": "0.35.2",
"exports": {
".": "./mod.ts",
"./ext/zod": "./ext/zod.ts",
Expand All @@ -10,7 +10,8 @@
"check": "deno check mod.ts src/*.ts ext/*.ts tests/*.ts tests/**/*.ts benchmarks/**/*ts",
"test": "deno test --allow-write --allow-read --unstable-kv --trace-ops",
"bench": "deno bench --unstable-kv",
"prep": "deno task check && deno fmt && deno lint && deno publish --dry-run && deno task test"
"prep": "deno task check && deno fmt && deno lint && deno publish --dry-run && deno task test",
"cache": "deno cache -r mod.ts && deno cache -r ext/zod.ts && deno cache -r ext/migrate.ts"
},
"fmt": {
"semiColons": false
Expand Down
22 changes: 21 additions & 1 deletion deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions ext/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ if (import.meta.main) {
})
}

/** Options for migrating entries from a source KV instance to a target KV instance */
export type MigrateOptions = {
/** Source KV. */
source: Deno.Kv
Expand All @@ -83,6 +84,19 @@ export type MigrateOptions = {
/**
* Migrate entries from a source KV instance to a target KV instance.
*
* @example
* ```ts
* import { migrate } from "jsr:@olli/kvdex/ext/migrate"
*
* const source = await Deno.openKv("./source.sqlite3")
* const target = await Deno.openKv("./target.sqlite3")
*
* await migrate({
* source,
* target,
* })
* ```
*
* @param options - Migrate options
*/
export async function migrate({
Expand Down
4 changes: 4 additions & 0 deletions ext/zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,14 @@ const LazyKvArraySchema = z.lazy(() => KvArraySchema)

const LazyKvObjectSchema = z.lazy(() => KvObjectSchema)

/** Zod schema for KvId type */
export const KvIdSchema: z.ZodType<KvId> = z.string()
.or(z.number())
.or(z.bigint())
.or(z.boolean())
.or(z.instanceof(Uint8Array))

/** Zod schema for KvValue type */
export const KvValueSchema: z.ZodType<KvValue> = z.undefined()
.or(z.null())
.or(z.string())
Expand Down Expand Up @@ -107,8 +109,10 @@ export const KvValueSchema: z.ZodType<KvValue> = z.undefined()
.or(z.instanceof(DataView))
.or(z.instanceof(Error))

/** Zod schema for KvArray type */
export const KvArraySchema: z.ZodType<KvArray> = z.array(KvValueSchema)

/** Zod schema for KvObject type */
export const KvObjectSchema: z.ZodType<KvObject> = z.record(
z.string().or(z.number()),
KvValueSchema,
Expand Down
5 changes: 2 additions & 3 deletions src/collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import type {
UpdateOneOptions,
UpdateOptions,
UpdateStrategy,
UpsertOptions,
WatchOptions,
} from "./types.ts"
import {
Expand Down Expand Up @@ -862,7 +861,7 @@ export class Collection<
* @returns A promise resolving to either CommitResult or CommitError.
*/
async upsert<
const TUpsertOptions extends UpsertOptions,
const TUpsertOptions extends UpdateOptions,
>(
input: IdUpsert<TInput, TOutput, TUpsertOptions["strategy"]>,
options?: TUpsertOptions,
Expand Down Expand Up @@ -910,7 +909,7 @@ export class Collection<
*/
async upsertByPrimaryIndex<
const TIndex extends PrimaryIndexKeys<TOutput, TOptions>,
const TUpsertOptions extends UpsertOptions,
const TUpsertOptions extends UpdateOptions,
>(
input: PrimaryIndexUpsert<
TInput,
Expand Down
15 changes: 6 additions & 9 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ export type ParseInputType<TInput, TOutput extends KvValue> = TInput extends

/**
* Model describing the input and output type of data.
* Contains a parse function, and optionally a __validate function used instead of parse upon reading data.
* Contains a parse function, and optionally a `__validate()` function used instead of parse upon reading data.
*/
export type Model<TInput, TOutput extends KvValue> = {
/** A parse function that takes an input type and returns an output type */
Expand Down Expand Up @@ -580,9 +580,6 @@ export type PrimaryIndexUpsert<
update: UpdateData<TOutput, TStrategy>
}

/** Options to upserting */
export type UpsertOptions = UpdateOptions

/********************/
/* */
/* SCHEMA TYPES */
Expand Down Expand Up @@ -678,21 +675,21 @@ export type KvEnqueueOptions = NonNullable<
/** Type of versionstamp */
export type KvVersionstamp<T extends KvValue> = Deno.KvEntry<T>["versionstamp"]

/** Entry key */
/** An entry or collection key */
export type KvKey = [Deno.KvKeyPart, ...Deno.KvKey]

/** Document id */
/** An entry ID */
export type KvId = Exclude<Deno.KvKeyPart, Exclude<Deno.KvKeyPart, KvValue>>

/** KV Object */
/** An object containing only KV values, and is itself a KV value. */
export type KvObject = {
[K: string | number]: KvValue
}

/** KV Array */
/** An array containing only KV values, and is itself a KV value. */
export type KvArray = KvValue[]

/** KV Value */
/** Defines all valid KV value types */
export type KvValue =
| undefined
| null
Expand Down
47 changes: 46 additions & 1 deletion tests/collection/properties.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { collection, Document, kvdex, model } from "../../mod.ts"
import { ID_KEY_PREFIX, KVDEX_KEY_PREFIX } from "../../src/constants.ts"
import { extendKey, keyEq } from "../../src/utils.ts"
import { assert } from "../test.deps.ts"
import { mockUser1 } from "../mocks.ts"
import { mockUser1, mockUser2, mockUser3 } from "../mocks.ts"
import { User } from "../models.ts"
import { generateUsers, useDb, useKv } from "../utils.ts"
import { sleep } from "../utils.ts"

Deno.test("collection - properties", async (t) => {
await t.step("Keys should have the correct prefixes", async () => {
Expand Down Expand Up @@ -210,6 +211,50 @@ Deno.test("collection - properties", async (t) => {
})
})

await t.step("Should select limited by database reads", async () => {
await useDb(async (db) => {
const cr1 = await db.users.add(mockUser1)
await sleep(10)
const cr2 = await db.users.add(mockUser2)
await sleep(10)
const cr3 = await db.users.add(mockUser3)

assert(cr1.ok)
assert(cr2.ok)
assert(cr3.ok)

const { result } = await db.users.getMany({
limit: 2,
filter: (doc) => doc.value.username !== mockUser1.username,
})

assert(result.every((doc) => doc.value.username === mockUser2.username))
})
})

await t.step("Should select limited by result count", async () => {
await useDb(async (db) => {
const cr1 = await db.users.add(mockUser1)
await sleep(10)
const cr2 = await db.users.add(mockUser2)
await sleep(10)
const cr3 = await db.users.add(mockUser3)

assert(cr1.ok)
assert(cr2.ok)
assert(cr3.ok)

const { result } = await db.users.getMany({
resultLimit: 2,
filter: (doc) => doc.value.username !== mockUser1.username,
})

assert(result.length === 2)
assert(result.some((doc) => doc.value.username === mockUser2.username))
assert(result.some((doc) => doc.value.username === mockUser3.username))
})
})

await t.step("Should correctly infer type of document", async () => {
await useDb(async (db) => {
const doc = await db.users.find("")
Expand Down
48 changes: 47 additions & 1 deletion tests/indexable_collection/properties.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import { extendKey, keyEq } from "../../src/utils.ts"
import { assert } from "../test.deps.ts"
import { mockUser1 } from "../mocks.ts"
import { User } from "../models.ts"
import { generateUsers, useDb, useKv } from "../utils.ts"
import { generateUsers, sleep, useDb, useKv } from "../utils.ts"
import { mockUser2 } from "../mocks.ts"
import { mockUser3 } from "../mocks.ts"

Deno.test("indexable_collection - properties", async (t) => {
await t.step("Keys should have the correct prefixes", async () => {
Expand Down Expand Up @@ -306,6 +308,50 @@ Deno.test("indexable_collection - properties", async (t) => {
})
})

await t.step("Should select limited by database reads", async () => {
await useDb(async (db) => {
const cr1 = await db.i_users.add(mockUser1)
await sleep(10)
const cr2 = await db.i_users.add(mockUser2)
await sleep(10)
const cr3 = await db.i_users.add(mockUser3)

assert(cr1.ok)
assert(cr2.ok)
assert(cr3.ok)

const { result } = await db.i_users.getMany({
limit: 2,
filter: (doc) => doc.value.username !== mockUser1.username,
})

assert(result.every((doc) => doc.value.username === mockUser2.username))
})
})

await t.step("Should select limited by result count", async () => {
await useDb(async (db) => {
const cr1 = await db.i_users.add(mockUser1)
await sleep(10)
const cr2 = await db.i_users.add(mockUser2)
await sleep(10)
const cr3 = await db.i_users.add(mockUser3)

assert(cr1.ok)
assert(cr2.ok)
assert(cr3.ok)

const { result } = await db.i_users.getMany({
resultLimit: 2,
filter: (doc) => doc.value.username !== mockUser1.username,
})

assert(result.length === 2)
assert(result.some((doc) => doc.value.username === mockUser2.username))
assert(result.some((doc) => doc.value.username === mockUser3.username))
})
})

await t.step("Should correctly infer type of document", async () => {
await useDb(async (db) => {
const doc = await db.i_users.find("")
Expand Down
48 changes: 47 additions & 1 deletion tests/serialized_collection/properties.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import {
} from "../../src/constants.ts"
import { extendKey, keyEq } from "../../src/utils.ts"
import { assert } from "../test.deps.ts"
import { mockUser1 } from "../mocks.ts"
import { mockUser1, mockUser2 } from "../mocks.ts"
import { User } from "../models.ts"
import { generateLargeUsers, useDb, useKv } from "../utils.ts"
import { mockUser3 } from "../mocks.ts"
import { sleep } from "../utils.ts"

Deno.test("serialized_collection - properties", async (t) => {
await t.step("Keys should have the correct prefixes", async () => {
Expand Down Expand Up @@ -215,6 +217,50 @@ Deno.test("serialized_collection - properties", async (t) => {
})
})

await t.step("Should select limited by database reads", async () => {
await useDb(async (db) => {
const cr1 = await db.s_users.add(mockUser1)
await sleep(10)
const cr2 = await db.s_users.add(mockUser2)
await sleep(10)
const cr3 = await db.s_users.add(mockUser3)

assert(cr1.ok)
assert(cr2.ok)
assert(cr3.ok)

const { result } = await db.s_users.getMany({
limit: 2,
filter: (doc) => doc.value.username !== mockUser1.username,
})

assert(result.every((doc) => doc.value.username === mockUser2.username))
})
})

await t.step("Should select limited by result count", async () => {
await useDb(async (db) => {
const cr1 = await db.s_users.add(mockUser1)
await sleep(10)
const cr2 = await db.s_users.add(mockUser2)
await sleep(10)
const cr3 = await db.s_users.add(mockUser3)

assert(cr1.ok)
assert(cr2.ok)
assert(cr3.ok)

const { result } = await db.s_users.getMany({
resultLimit: 2,
filter: (doc) => doc.value.username !== mockUser1.username,
})

assert(result.length === 2)
assert(result.some((doc) => doc.value.username === mockUser2.username))
assert(result.some((doc) => doc.value.username === mockUser3.username))
})
})

await t.step("Should correctly infer type of document", async () => {
await useDb(async (db) => {
const doc = await db.s_users.find("")
Expand Down
Loading

0 comments on commit 723e159

Please sign in to comment.