Skip to content

Commit 4dc1210

Browse files
Release/2.0 (#220)
* feat: refactored model to be compatible with native zod * feat: changed extension to be under root path instead of /ext * chore: updated dependencies * chore: renamed resultLimit option to take * Infer id type (#217) * Cancellable watchers (#218)
1 parent 7b0bf2f commit 4dc1210

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+626
-547
lines changed

README.md

+39-51
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,6 @@ _Supported Deno verisons:_ **^1.43.0**
9797
- [jsonParse()](#jsonparse)
9898
- [Extensions](#extensions)
9999
- [Zod](#zod)
100-
- [zodModel()](#zodmodel)
101100
- [Schemas](#schemas)
102101
- [Migrate](#migrate)
103102
- [Script](#script)
@@ -109,14 +108,13 @@ _Supported Deno verisons:_ **^1.43.0**
109108
## Models
110109

111110
Collections are typed using models. Standard models can be defined using the
112-
`model()` function. Alternatively, any object that implements the Model type can
113-
be used as a model. Zod is therefore compatible, without being a dependency (see
114-
[zodModel()](#zodmodel) for additional support). The standard model uses type
115-
casting only, and does not validate any data when parsing. Asymmetric models can
116-
be created by passing a transform function which maps from an input type to an
117-
output type. Asymmetric models are useful for storing derived values or filling
118-
default values. It is up to the developer to choose the strategy that fits their
119-
use case the best.
111+
`model()` function. Alternatively, any object that is compatible with the Model
112+
type can be used as a model. Zod is therefore supported, without being a
113+
dependency. The standard model uses type casting only, and does not validate any
114+
data when parsing. Asymmetric models can be created by passing a transform
115+
function which maps from an input type to an output type. Asymmetric models are
116+
useful for storing derived values or filling default values. It is up to the
117+
developer to choose the strategy that fits their use case the best.
120118

121119
**_NOTE_:** When using interfaces instead of types, they must extend the KvValue
122120
type.
@@ -957,6 +955,17 @@ db.numbers.watch("id", (doc) => {
957955
})
958956
```
959957

958+
Watchers can also be stopped.
959+
960+
```ts
961+
const { promise, cancel } = db.numbers.watch("id", (doc) => {
962+
// ...
963+
})
964+
965+
await cancel()
966+
await promise
967+
```
968+
960969
### watchMany()
961970

962971
Listen for live changes to an array of specified documents by id.
@@ -976,6 +985,20 @@ db.numbers.watchMany(["id1", "id2", "id3"], (docs) => {
976985
})
977986
```
978987

988+
Watchers can also be stopped.
989+
990+
```ts
991+
const { promise, cancel } = db.numbers.watchMany(
992+
["id1", "id2", "id3"],
993+
(docs) => {
994+
// ...
995+
},
996+
)
997+
998+
await cancel()
999+
await promise
1000+
```
1001+
9791002
## Database Methods
9801003

9811004
These are methods which can be found at the top level of your database object,
@@ -1317,57 +1340,22 @@ const value = jsonParse(str)
13171340
## Extensions
13181341

13191342
Additional features outside of the basic functionality provided by `kvdex`.
1320-
While the basic functions are dependency-free, extended features may rely on
1321-
some dependenices to enhance integration. All extensions are found in the
1322-
`kvdex/ext/` sub-path.
1343+
While the core functionalities are dependency-free, extended features may rely
1344+
on some dependenices to enhance integration.
13231345

13241346
### Zod
13251347

1326-
Extended support for Zod. Includes a model parser and schemas for some KV-types.
1327-
1328-
#### zodModel()
1329-
1330-
Provides additional compatibility when using zod schemas as models. While zod
1331-
schemas can be used as models directly, `zodModel()` properly parses a model
1332-
from a zod schema, recognizing default fields as optional.
1333-
1334-
```ts
1335-
import { z } from "npm:zod"
1336-
import { zodModel } from "jsr:@olli/kvdex/ext/zod"
1337-
import { collection, kvdex } from "jsr:@olli/kvdex"
1338-
1339-
const UserSchema = z.object({
1340-
username: z.string(),
1341-
gender: z.string().default("not given"),
1342-
})
1343-
1344-
const kv = await Deno.openKv()
1345-
1346-
const db = kvdex(kv, {
1347-
users_basic: collection(UserSchema),
1348-
users_zod: collection(zodModel(UserSchema)),
1349-
})
1350-
1351-
// Produces a type error for missing "gender" field.
1352-
const result = await db.users_basic.add({
1353-
username: "oliver",
1354-
})
1355-
1356-
// No type error for missing "gender" field.
1357-
const result = await db.users_zod.add({
1358-
username: "oliver",
1359-
})
1360-
```
1348+
Extended support for Zod. Includes schemas for some of the KV-types.
13611349

13621350
#### Schemas
13631351

1364-
The zod extension provides schemas for some of the Kv-types, such as KvId,
1352+
The zod extension provides schemas for some of the KV-types, such as KvId,
13651353
KvValue, KvObject and KvArray. This makes it easier to properly build your
13661354
schemas.
13671355

13681356
```ts
13691357
import { z } from "npm:zod"
1370-
import { KvIdSchema } from "jsr:@olli/kvdex/ext/zod"
1358+
import { KvIdSchema } from "jsr:@olli/kvdex/zod"
13711359

13721360
const UserSchema = z.object({
13731361
username: z.string(),
@@ -1392,7 +1380,7 @@ Run the migrate script and provide --source and --target arguments. Optionally
13921380
pass --all to migrate all entries.
13931381

13941382
```console
1395-
deno run -A --unstable-kv jsr:@olli/kvdex/ext/migrate --source=./source.sqlite3 --target=./target.sqlite3
1383+
deno run -A --unstable-kv jsr:@olli/kvdex/migrate --source=./source.sqlite3 --target=./target.sqlite3
13961384
```
13971385

13981386
#### Function
@@ -1401,7 +1389,7 @@ Use the migrate function and pass a source KV instance and a target KV instance.
14011389
Optionally pass `all: true` to migrate all entries.
14021390

14031391
```ts
1404-
import { migrate } from "jsr:@olli/kvdex/ext/migrate"
1392+
import { migrate } from "jsr:@olli/kvdex/migrate"
14051393

14061394
const source = await Deno.openKv("./source.sqlite3")
14071395
const target = await Deno.openKv("./target.sqlite3")

benchmarks/utils/deserialize.bench.ts

+12-9
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@ import {
99
const js = jsonSerialize(obj)
1010
const ds = v8Serialize(obj)
1111

12-
console.log("JSON size:", js.byteLength / 1024 / 1024, "MB")
13-
console.log("V8 size:", ds.byteLength / 1024 / 1024, "MB")
12+
Deno.bench(
13+
`utils - jsonDeserialize (${js.byteLength / 1024 / 1024} MB)`,
14+
() => {
15+
jsonDeserialize(js)
16+
},
17+
)
1418

15-
Deno.bench("utils - jsonDeserialize", () => {
16-
jsonDeserialize(js)
17-
})
18-
19-
Deno.bench("utils - v8Deserialize", () => {
20-
v8Deserialize(ds)
21-
})
19+
Deno.bench(
20+
`utils - v8Deserialize - (${ds.byteLength / 1024 / 1024} MS)`,
21+
() => {
22+
v8Deserialize(ds)
23+
},
24+
)

deno.json

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"name": "@olli/kvdex",
3-
"version": "1.0.2",
3+
"version": "2.0.0",
44
"exports": {
55
".": "./mod.ts",
6-
"./ext/zod": "./ext/zod.ts",
7-
"./ext/migrate": "./ext/migrate.ts"
6+
"./zod": "./ext/zod.ts",
7+
"./migrate": "./ext/migrate.ts"
88
},
99
"tasks": {
1010
"check": "deno check mod.ts src/*.ts ext/*.ts tests/*.ts tests/**/*.ts benchmarks/**/*ts",
@@ -18,7 +18,8 @@
1818
},
1919
"lint": {
2020
"rules": {
21-
"exclude": ["no-explicit-any"]
21+
"exclude": ["no-explicit-any"],
22+
"include": ["no-console"]
2223
}
2324
},
2425
"test": {

deno.lock

+20-42
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/migrate.ts

+15-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* pass --all to migrate all entries.
1212
*
1313
* ```console
14-
* deno run -A --unstable-kv jsr:@olli/kvdex/ext/migrate --source=./source.sqlite3 --target=./target.sqlite3
14+
* deno run -A --unstable-kv jsr:@olli/kvdex/migrate --source=./source.sqlite3 --target=./target.sqlite3
1515
* ```
1616
*
1717
* ## Function
@@ -20,7 +20,7 @@
2020
* Optionally pass `all: true` to migrate all entries.
2121
*
2222
* ```ts
23-
* import { migrate } from "jsr:@olli/kvdex/ext/migrate"
23+
* import { migrate } from "jsr:@olli/kvdex/migrate"
2424
*
2525
* const source = await Deno.openKv("./source.sqlite3")
2626
* const target = await Deno.openKv("./target.sqlite3")
@@ -35,24 +35,33 @@
3535
import { parseArgs } from "jsr:@std/cli@^0.217/parse_args"
3636
import { KVDEX_KEY_PREFIX } from "../src/constants.ts"
3737

38+
export class NoKvFoundError extends Error {
39+
name = "NoKvFoundError"
40+
41+
constructor(
42+
message?: string | undefined,
43+
options?: ErrorOptions | undefined,
44+
) {
45+
super(message, options)
46+
}
47+
}
48+
3849
if (import.meta.main) {
3950
const { source, target, all } = parseArgs(Deno.args, {
4051
string: ["source", "target"],
4152
boolean: ["all"],
4253
})
4354

4455
if (!source) {
45-
console.log(
56+
throw new NoKvFoundError(
4657
"A source KV path to export from must be provided using the --source argument",
4758
)
48-
Deno.exit()
4959
}
5060

5161
if (!target) {
52-
console.log(
62+
throw new NoKvFoundError(
5363
"A target KV path to export to must be provided using the --target argument",
5464
)
55-
Deno.exit()
5665
}
5766

5867
using sourceKv = await Deno.openKv(source)

0 commit comments

Comments
 (0)