zodvex 0.7.7 → 0.7.8-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/internal/customization.d.ts +27 -1
- package/dist/internal/customization.d.ts.map +1 -1
- package/dist/internal/db.d.ts +18 -0
- package/dist/internal/db.d.ts.map +1 -1
- package/dist/internal/init.d.ts +15 -1
- package/dist/internal/init.d.ts.map +1 -1
- package/dist/mini/server/index.js +40 -5
- package/dist/mini/server/index.js.map +1 -1
- package/dist/public/server/index.d.ts +1 -1
- package/dist/public/server/index.d.ts.map +1 -1
- package/dist/server/index.js +40 -5
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
- package/src/internal/customization.ts +42 -3
- package/src/internal/db.ts +24 -0
- package/src/internal/init.ts +40 -5
- package/src/public/server/index.ts +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zodvex",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.8-beta.0",
|
|
4
4
|
"description": "Codec-first Zod v4 integration for Convex -- type-safe validation, encoding, DB wrapping, and codegen.",
|
|
5
5
|
"keywords": ["zod", "convex", "validators", "codec", "mapping", "schema", "validation"],
|
|
6
6
|
"homepage": "https://github.com/panzacoder/zodvex#readme",
|
|
@@ -1,11 +1,41 @@
|
|
|
1
|
+
import type { GenericDatabaseReader, GenericDatabaseWriter } from 'convex/server'
|
|
1
2
|
import { ZodvexDatabaseReader, ZodvexDatabaseWriter } from './db'
|
|
2
3
|
import type { ZodTableMap } from './schema'
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Resolvers for the database the codec wrapper delegates to (#92).
|
|
7
|
+
*
|
|
8
|
+
* Each resolver receives the raw Convex ctx (untouched by zodvex) and returns
|
|
9
|
+
* the db the codec reader/writer should wrap instead of `ctx.db`. This lets
|
|
10
|
+
* native-shape layers — e.g. `convex-helpers/server/triggers` — sit UNDER the
|
|
11
|
+
* codec layer: codec on top → triggers → real db. The trigger layer sees
|
|
12
|
+
* wire-format writes, exactly what it is written against.
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* const triggers = new Triggers<DataModel>()
|
|
16
|
+
* initZodvex(schema, server, {
|
|
17
|
+
* underlyingDb: { mutation: (ctx) => triggers.wrapDB(ctx).db }
|
|
18
|
+
* })
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export type ZodvexUnderlyingDb<
|
|
22
|
+
QueryCtx = any,
|
|
23
|
+
MutationCtx = any,
|
|
24
|
+
Reader extends GenericDatabaseReader<any> = GenericDatabaseReader<any>,
|
|
25
|
+
Writer extends GenericDatabaseWriter<any> = GenericDatabaseWriter<any>
|
|
26
|
+
> = {
|
|
27
|
+
query?: (ctx: QueryCtx) => Reader
|
|
28
|
+
mutation?: (ctx: MutationCtx) => Writer
|
|
29
|
+
}
|
|
30
|
+
|
|
4
31
|
/**
|
|
5
32
|
* Creates Convex Customization objects that wrap ctx.db with codec
|
|
6
33
|
* readers/writers. Returns { query, mutation } for use with
|
|
7
34
|
* zCustomQuery/zCustomMutation or manual composition.
|
|
8
35
|
*
|
|
36
|
+
* When `options.underlyingDb` is provided, the codec wrapper delegates to the
|
|
37
|
+
* resolved db instead of `ctx.db` (see {@link ZodvexUnderlyingDb}).
|
|
38
|
+
*
|
|
9
39
|
* @example
|
|
10
40
|
* ```typescript
|
|
11
41
|
* const codec = createZodvexCustomization(schema.__zodTableMap)
|
|
@@ -19,19 +49,28 @@ import type { ZodTableMap } from './schema'
|
|
|
19
49
|
* })
|
|
20
50
|
* ```
|
|
21
51
|
*/
|
|
22
|
-
export function createZodvexCustomization(
|
|
52
|
+
export function createZodvexCustomization(
|
|
53
|
+
tableMap: ZodTableMap,
|
|
54
|
+
options?: { underlyingDb?: ZodvexUnderlyingDb }
|
|
55
|
+
) {
|
|
56
|
+
const resolveReaderDb = options?.underlyingDb?.query
|
|
57
|
+
const resolveWriterDb = options?.underlyingDb?.mutation
|
|
23
58
|
return {
|
|
24
59
|
query: {
|
|
25
60
|
args: {} as Record<string, never>,
|
|
26
61
|
input: async (ctx: any, _args: any, _extra?: any) => ({
|
|
27
|
-
ctx: {
|
|
62
|
+
ctx: {
|
|
63
|
+
db: new ZodvexDatabaseReader(resolveReaderDb ? resolveReaderDb(ctx) : ctx.db, tableMap)
|
|
64
|
+
},
|
|
28
65
|
args: {}
|
|
29
66
|
})
|
|
30
67
|
},
|
|
31
68
|
mutation: {
|
|
32
69
|
args: {} as Record<string, never>,
|
|
33
70
|
input: async (ctx: any, _args: any, _extra?: any) => ({
|
|
34
|
-
ctx: {
|
|
71
|
+
ctx: {
|
|
72
|
+
db: new ZodvexDatabaseWriter(resolveWriterDb ? resolveWriterDb(ctx) : ctx.db, tableMap)
|
|
73
|
+
},
|
|
35
74
|
args: {}
|
|
36
75
|
})
|
|
37
76
|
}
|
package/src/internal/db.ts
CHANGED
|
@@ -484,6 +484,18 @@ export class ZodvexDatabaseReader<
|
|
|
484
484
|
return { db: this.db, tableMap: this.tableMap }
|
|
485
485
|
}
|
|
486
486
|
|
|
487
|
+
/**
|
|
488
|
+
* Escape hatch (#85/#92): returns the database this codec wrapper delegates
|
|
489
|
+
* to — the composed underlying stack when `underlyingDb` is configured (e.g.
|
|
490
|
+
* a trigger-wrapped writer), the bare Convex db otherwise.
|
|
491
|
+
*
|
|
492
|
+
* The returned db is native-shape: reads are undecoded wire documents and it
|
|
493
|
+
* bypasses codec, `.withRules()`, and `.audit()` layers entirely.
|
|
494
|
+
*/
|
|
495
|
+
unwrap(): GenericDatabaseReader<DataModel> {
|
|
496
|
+
return this.db
|
|
497
|
+
}
|
|
498
|
+
|
|
487
499
|
normalizeId<TableName extends TableNamesInDataModel<DataModel>>(
|
|
488
500
|
tableName: TableName,
|
|
489
501
|
id: string
|
|
@@ -600,6 +612,18 @@ export class ZodvexDatabaseWriter<
|
|
|
600
612
|
return { db: this.writerDb, tableMap: this.tableMap, reader: this }
|
|
601
613
|
}
|
|
602
614
|
|
|
615
|
+
/**
|
|
616
|
+
* Escape hatch (#85/#92): returns the writer this codec wrapper delegates
|
|
617
|
+
* to — the composed underlying stack when `underlyingDb` is configured (e.g.
|
|
618
|
+
* a trigger-wrapped writer), the bare Convex db otherwise.
|
|
619
|
+
*
|
|
620
|
+
* The returned db is native-shape: writes must be wire-format and it
|
|
621
|
+
* bypasses codec, `.withRules()`, and `.audit()` layers entirely.
|
|
622
|
+
*/
|
|
623
|
+
override unwrap(): GenericDatabaseWriter<DataModel> {
|
|
624
|
+
return this.writerDb
|
|
625
|
+
}
|
|
626
|
+
|
|
603
627
|
// --- Write methods: encode before delegating ---
|
|
604
628
|
|
|
605
629
|
insert<TableName extends TableNamesInDataModel<DataModel>>(
|
package/src/internal/init.ts
CHANGED
|
@@ -2,6 +2,8 @@ import type {
|
|
|
2
2
|
ActionBuilder,
|
|
3
3
|
FunctionVisibility,
|
|
4
4
|
GenericActionCtx,
|
|
5
|
+
GenericDatabaseReader,
|
|
6
|
+
GenericDatabaseWriter,
|
|
5
7
|
GenericDataModel,
|
|
6
8
|
GenericMutationCtx,
|
|
7
9
|
GenericQueryCtx,
|
|
@@ -13,7 +15,7 @@ import type { z } from 'zod'
|
|
|
13
15
|
import { createCodecCallOverrides } from './actionCtx'
|
|
14
16
|
import type { CustomBuilder } from './custom'
|
|
15
17
|
import { zCustomAction, zCustomMutation, zCustomQuery } from './custom'
|
|
16
|
-
import { createZodvexCustomization } from './customization'
|
|
18
|
+
import { createZodvexCustomization, type ZodvexUnderlyingDb } from './customization'
|
|
17
19
|
import type { ZodvexDatabaseReader, ZodvexDatabaseWriter } from './db'
|
|
18
20
|
import type { ZodValidator } from './mapping'
|
|
19
21
|
import type { ZodTableMap } from './schema'
|
|
@@ -255,7 +257,28 @@ export function initZodvex<
|
|
|
255
257
|
internalMutation: MutationBuilder<DM, 'internal'>
|
|
256
258
|
internalAction: ActionBuilder<DM, 'internal'>
|
|
257
259
|
},
|
|
258
|
-
options?: {
|
|
260
|
+
options?: {
|
|
261
|
+
wrapDb?: true
|
|
262
|
+
registry?: () => AnyRegistry
|
|
263
|
+
/**
|
|
264
|
+
* Resolve the database the codec wrapper delegates to, instead of `ctx.db`.
|
|
265
|
+
* Lets native-shape layers (e.g. convex-helpers triggers) sit under the
|
|
266
|
+
* codec layer — codec on top → triggers → real db. See #92.
|
|
267
|
+
*
|
|
268
|
+
* ```ts
|
|
269
|
+
* const triggers = new Triggers<DataModel>()
|
|
270
|
+
* initZodvex(schema, server, {
|
|
271
|
+
* underlyingDb: { mutation: (ctx) => triggers.wrapDB(ctx).db }
|
|
272
|
+
* })
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
underlyingDb?: ZodvexUnderlyingDb<
|
|
276
|
+
GenericQueryCtx<DM>,
|
|
277
|
+
GenericMutationCtx<DM>,
|
|
278
|
+
GenericDatabaseReader<DM>,
|
|
279
|
+
GenericDatabaseWriter<DM>
|
|
280
|
+
>
|
|
281
|
+
}
|
|
259
282
|
): {
|
|
260
283
|
zq: ZodvexBuilder<'query', { db: ZodvexDatabaseReader<DM, DD> }, GenericQueryCtx<DM>, 'public'>
|
|
261
284
|
zm: ZodvexBuilder<
|
|
@@ -279,11 +302,23 @@ export function initZodvex<
|
|
|
279
302
|
export function initZodvex(
|
|
280
303
|
schema: { __zodTableMap: ZodTableMap },
|
|
281
304
|
server: InitServerBuilders,
|
|
282
|
-
options?: {
|
|
305
|
+
options?: {
|
|
306
|
+
wrapDb?: boolean
|
|
307
|
+
registry?: () => AnyRegistry
|
|
308
|
+
underlyingDb?: ZodvexUnderlyingDb
|
|
309
|
+
}
|
|
283
310
|
) {
|
|
284
|
-
const codec = createZodvexCustomization(schema.__zodTableMap)
|
|
285
|
-
const noOp = createNoOpCustomization()
|
|
286
311
|
const wrap = options?.wrapDb !== false
|
|
312
|
+
if (!wrap && options?.underlyingDb) {
|
|
313
|
+
throw new Error(
|
|
314
|
+
'[zodvex] initZodvex: `underlyingDb` requires the codec db wrapper — ' +
|
|
315
|
+
'remove `wrapDb: false` or drop `underlyingDb`.'
|
|
316
|
+
)
|
|
317
|
+
}
|
|
318
|
+
const codec = createZodvexCustomization(schema.__zodTableMap, {
|
|
319
|
+
underlyingDb: options?.underlyingDb
|
|
320
|
+
})
|
|
321
|
+
const noOp = createNoOpCustomization()
|
|
287
322
|
|
|
288
323
|
const registryThunk = options?.registry
|
|
289
324
|
const actionCust = createActionCustomization(registryThunk, noOp)
|
|
@@ -31,7 +31,10 @@ export {
|
|
|
31
31
|
zCustomQuery
|
|
32
32
|
} from '../../internal/custom'
|
|
33
33
|
// Codec customization (manual composition escape hatch)
|
|
34
|
-
export {
|
|
34
|
+
export {
|
|
35
|
+
createZodvexCustomization,
|
|
36
|
+
type ZodvexUnderlyingDb
|
|
37
|
+
} from '../../internal/customization'
|
|
35
38
|
// Database wrappers (ZodvexDatabaseReader, ZodvexDatabaseWriter, etc.)
|
|
36
39
|
export {
|
|
37
40
|
createZodDbReader,
|