zodvex 0.2.2 → 0.2.4
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 +70 -33
- package/dist/index.d.mts +21 -8
- package/dist/index.d.ts +21 -8
- package/dist/index.js +13 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +13 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -13
- package/src/builders.ts +6 -6
- package/src/custom.ts +5 -1
- package/src/mapping/handlers/union.ts +15 -8
- package/src/mapping/types.ts +65 -10
package/src/builders.ts
CHANGED
|
@@ -155,13 +155,13 @@ export function zActionBuilder<Builder extends (fn: any) => any>(builder: Builde
|
|
|
155
155
|
*
|
|
156
156
|
* @example
|
|
157
157
|
* ```ts
|
|
158
|
-
* import { query } from './_generated/server'
|
|
158
|
+
* import { type QueryCtx, query } from './_generated/server'
|
|
159
159
|
* import { zCustomQueryBuilder, customCtx } from 'zodvex'
|
|
160
160
|
*
|
|
161
161
|
* // Create a builder with auth context
|
|
162
162
|
* export const authQuery = zCustomQueryBuilder(
|
|
163
163
|
* query,
|
|
164
|
-
* customCtx(async (ctx) => {
|
|
164
|
+
* customCtx(async (ctx: QueryCtx) => {
|
|
165
165
|
* const user = await getUserOrThrow(ctx)
|
|
166
166
|
* return { user }
|
|
167
167
|
* })
|
|
@@ -208,13 +208,13 @@ export function zCustomQueryBuilder<
|
|
|
208
208
|
*
|
|
209
209
|
* @example
|
|
210
210
|
* ```ts
|
|
211
|
-
* import { mutation } from './_generated/server'
|
|
211
|
+
* import { type MutationCtx, mutation } from './_generated/server'
|
|
212
212
|
* import { zCustomMutationBuilder, customCtx } from 'zodvex'
|
|
213
213
|
*
|
|
214
214
|
* // Create a builder with auth context
|
|
215
215
|
* export const authMutation = zCustomMutationBuilder(
|
|
216
216
|
* mutation,
|
|
217
|
-
* customCtx(async (ctx) => {
|
|
217
|
+
* customCtx(async (ctx: MutationCtx) => {
|
|
218
218
|
* const user = await getUserOrThrow(ctx)
|
|
219
219
|
* return { user }
|
|
220
220
|
* })
|
|
@@ -261,13 +261,13 @@ export function zCustomMutationBuilder<
|
|
|
261
261
|
*
|
|
262
262
|
* @example
|
|
263
263
|
* ```ts
|
|
264
|
-
* import { action } from './_generated/server'
|
|
264
|
+
* import { type ActionCtx, action } from './_generated/server'
|
|
265
265
|
* import { zCustomActionBuilder, customCtx } from 'zodvex'
|
|
266
266
|
*
|
|
267
267
|
* // Create a builder with auth context
|
|
268
268
|
* export const authAction = zCustomActionBuilder(
|
|
269
269
|
* action,
|
|
270
|
-
* customCtx(async (ctx) => {
|
|
270
|
+
* customCtx(async (ctx: ActionCtx) => {
|
|
271
271
|
* const identity = await ctx.auth.getUserIdentity()
|
|
272
272
|
* if (!identity) throw new Error('Unauthorized')
|
|
273
273
|
* return { userId: identity.subject }
|
package/src/custom.ts
CHANGED
|
@@ -232,7 +232,11 @@ export function customFnBuilder<
|
|
|
232
232
|
handleZodValidationError(e, 'returns')
|
|
233
233
|
}
|
|
234
234
|
if (added?.onSuccess) {
|
|
235
|
-
await added.onSuccess({
|
|
235
|
+
await added.onSuccess({
|
|
236
|
+
ctx,
|
|
237
|
+
args: parsed.data,
|
|
238
|
+
result: validated
|
|
239
|
+
})
|
|
236
240
|
}
|
|
237
241
|
return toConvexJS(returns as z.ZodTypeAny, validated)
|
|
238
242
|
}
|
|
@@ -13,11 +13,12 @@ export function convertDiscriminatedUnionType(
|
|
|
13
13
|
if (options) {
|
|
14
14
|
const opts = Array.isArray(options) ? options : Array.from(options)
|
|
15
15
|
if (opts.length >= 2) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
// IMPORTANT: Create a new visited set for each union member to prevent false circular
|
|
17
|
+
// reference detection. The same schema can legitimately appear in multiple union branches.
|
|
18
|
+
const convexOptions = opts.map((opt: any) => {
|
|
19
|
+
const branchVisited = new Set(visited)
|
|
20
|
+
return zodToConvexInternal(opt, branchVisited)
|
|
21
|
+
}) as Validator<any, 'required', any>[]
|
|
21
22
|
const [first, second, ...rest] = convexOptions
|
|
22
23
|
return v.union(
|
|
23
24
|
first as Validator<any, 'required', any>,
|
|
@@ -44,9 +45,15 @@ export function convertUnionType(
|
|
|
44
45
|
return zodToConvexInternal(options[0], visited)
|
|
45
46
|
} else {
|
|
46
47
|
// Convert each option recursively
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
// IMPORTANT: Create a new visited set for each union member to prevent false circular
|
|
49
|
+
// reference detection. The same schema can legitimately appear in multiple union branches.
|
|
50
|
+
// However, we do want to preserve the parent visited set to catch actual circular refs
|
|
51
|
+
// that involve the union itself.
|
|
52
|
+
const convexOptions = options.map((opt: any) => {
|
|
53
|
+
// Create a new Set that includes the parent's visited schemas but won't pollute it
|
|
54
|
+
const branchVisited = new Set(visited)
|
|
55
|
+
return zodToConvexInternal(opt, branchVisited)
|
|
56
|
+
}) as Validator<any, 'required', any>[]
|
|
50
57
|
if (convexOptions.length >= 2) {
|
|
51
58
|
const [first, second, ...rest] = convexOptions
|
|
52
59
|
return v.union(
|
package/src/mapping/types.ts
CHANGED
|
@@ -22,6 +22,25 @@ type IsZid<T> = T extends { _tableName: infer _TableName extends string } ? true
|
|
|
22
22
|
// Extract table name from zid type (via _tableName property)
|
|
23
23
|
type ExtractTableName<T> = T extends { _tableName: infer TableName } ? TableName : never
|
|
24
24
|
|
|
25
|
+
// Helper to map enum tuple to VLiteral validators tuple
|
|
26
|
+
// Based on convex-helpers approach which handles different lengths explicitly
|
|
27
|
+
// This avoids TypeScript recursion issues and provides better type inference
|
|
28
|
+
type EnumToLiteralsTuple<T extends readonly [string, ...string[]]> = T['length'] extends 1
|
|
29
|
+
? [VLiteral<T[0], 'required'>]
|
|
30
|
+
: T['length'] extends 2
|
|
31
|
+
? [VLiteral<T[0], 'required'>, VLiteral<T[1], 'required'>]
|
|
32
|
+
: [
|
|
33
|
+
VLiteral<T[0], 'required'>,
|
|
34
|
+
VLiteral<T[1], 'required'>,
|
|
35
|
+
...{
|
|
36
|
+
[K in keyof T]: K extends '0' | '1'
|
|
37
|
+
? never
|
|
38
|
+
: K extends keyof T
|
|
39
|
+
? VLiteral<T[K], 'required'>
|
|
40
|
+
: never
|
|
41
|
+
}[keyof T & number][]
|
|
42
|
+
]
|
|
43
|
+
|
|
25
44
|
export type ZodValidator = Record<string, z.ZodTypeAny>
|
|
26
45
|
|
|
27
46
|
// Helper type to convert optional types to union with null for container elements
|
|
@@ -62,11 +81,25 @@ type ConvexValidatorFromZodBase<Z extends z.ZodTypeAny> =
|
|
|
62
81
|
: Z extends z.ZodLiteral<infer T>
|
|
63
82
|
? VLiteral<T, 'required'>
|
|
64
83
|
: Z extends z.ZodEnum<infer T>
|
|
65
|
-
? T extends
|
|
66
|
-
? T[
|
|
67
|
-
?
|
|
68
|
-
:
|
|
69
|
-
|
|
84
|
+
? T extends readonly [string, ...string[]]
|
|
85
|
+
? T['length'] extends 1
|
|
86
|
+
? VLiteral<T[0], 'required'>
|
|
87
|
+
: T['length'] extends 2
|
|
88
|
+
? VUnion<
|
|
89
|
+
T[number],
|
|
90
|
+
[VLiteral<T[0], 'required'>, VLiteral<T[1], 'required'>],
|
|
91
|
+
'required',
|
|
92
|
+
never
|
|
93
|
+
>
|
|
94
|
+
: VUnion<T[number], EnumToLiteralsTuple<T>, 'required', never>
|
|
95
|
+
: T extends Record<string, string | number>
|
|
96
|
+
? VUnion<
|
|
97
|
+
T[keyof T],
|
|
98
|
+
Array<VLiteral<T[keyof T], 'required'>>,
|
|
99
|
+
'required',
|
|
100
|
+
never
|
|
101
|
+
>
|
|
102
|
+
: VUnion<string, any[], 'required', any>
|
|
70
103
|
: Z extends z.ZodRecord<z.ZodString, infer V extends z.ZodTypeAny>
|
|
71
104
|
? VRecord<
|
|
72
105
|
Record<string, z.infer<V>>,
|
|
@@ -148,11 +181,33 @@ export type ConvexValidatorFromZod<
|
|
|
148
181
|
: Z extends z.ZodLiteral<infer T>
|
|
149
182
|
? VLiteral<T, Constraint>
|
|
150
183
|
: Z extends z.ZodEnum<infer T>
|
|
151
|
-
? T extends
|
|
152
|
-
? T[
|
|
153
|
-
?
|
|
154
|
-
:
|
|
155
|
-
|
|
184
|
+
? T extends readonly [string, ...string[]]
|
|
185
|
+
? T['length'] extends 1
|
|
186
|
+
? VLiteral<T[0], Constraint>
|
|
187
|
+
: T['length'] extends 2
|
|
188
|
+
? VUnion<
|
|
189
|
+
T[number],
|
|
190
|
+
[
|
|
191
|
+
VLiteral<T[0], 'required'>,
|
|
192
|
+
VLiteral<T[1], 'required'>
|
|
193
|
+
],
|
|
194
|
+
Constraint,
|
|
195
|
+
never
|
|
196
|
+
>
|
|
197
|
+
: VUnion<
|
|
198
|
+
T[number],
|
|
199
|
+
EnumToLiteralsTuple<T>,
|
|
200
|
+
Constraint,
|
|
201
|
+
never
|
|
202
|
+
>
|
|
203
|
+
: T extends Record<string, string | number>
|
|
204
|
+
? VUnion<
|
|
205
|
+
T[keyof T],
|
|
206
|
+
Array<VLiteral<T[keyof T], 'required'>>,
|
|
207
|
+
Constraint,
|
|
208
|
+
never
|
|
209
|
+
>
|
|
210
|
+
: VUnion<string, any[], Constraint, any>
|
|
156
211
|
: Z extends z.ZodRecord<z.ZodString, infer V extends z.ZodTypeAny>
|
|
157
212
|
? VRecord<
|
|
158
213
|
Record<string, z.infer<V>>,
|