zodvex 0.2.2 → 0.2.3
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 +5 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +12 -12
- package/src/builders.ts +6 -6
- package/src/custom.ts +5 -1
- package/src/mapping/types.ts +65 -10
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ npm install zodvex zod@^4.1.0 convex convex-helpers
|
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
**Peer dependencies:**
|
|
29
|
+
|
|
29
30
|
- `zod` (^4.1.0 or later)
|
|
30
31
|
- `convex` (>= 1.27.0)
|
|
31
32
|
- `convex-helpers` (>= 0.1.104)
|
|
@@ -106,16 +107,16 @@ import { zodTable, zid } from 'zodvex'
|
|
|
106
107
|
export const Users = zodTable('users', {
|
|
107
108
|
name: z.string(),
|
|
108
109
|
email: z.string().email(),
|
|
109
|
-
age: z.number().optional(),
|
|
110
|
-
deletedAt: z.date().nullable(),
|
|
110
|
+
age: z.number().optional(), // → v.optional(v.float64())
|
|
111
|
+
deletedAt: z.date().nullable(), // → v.union(v.float64(), v.null())
|
|
111
112
|
teamId: zid('teams').optional()
|
|
112
113
|
})
|
|
113
114
|
|
|
114
115
|
// Access the underlying table
|
|
115
|
-
Users.table
|
|
116
|
-
Users.shape
|
|
117
|
-
Users.zDoc
|
|
118
|
-
Users.docArray
|
|
116
|
+
Users.table // Convex table definition
|
|
117
|
+
Users.shape // Original Zod shape
|
|
118
|
+
Users.zDoc // Zod schema with _id and _creationTime
|
|
119
|
+
Users.docArray // z.array(zDoc) for return types
|
|
119
120
|
```
|
|
120
121
|
|
|
121
122
|
## Building Your Schema
|
|
@@ -134,8 +135,7 @@ export default defineSchema({
|
|
|
134
135
|
.index('by_team', ['teamId'])
|
|
135
136
|
.searchIndex('search_name', { searchField: 'name' }),
|
|
136
137
|
|
|
137
|
-
teams: Teams.table
|
|
138
|
-
.index('by_created', ['_creationTime'])
|
|
138
|
+
teams: Teams.table.index('by_created', ['_creationTime'])
|
|
139
139
|
})
|
|
140
140
|
```
|
|
141
141
|
|
|
@@ -236,7 +236,11 @@ type CreateUserForm = z.infer<typeof CreateUserForm>
|
|
|
236
236
|
function UserForm() {
|
|
237
237
|
const createUser = useMutation(api.users.createUser)
|
|
238
238
|
|
|
239
|
-
const {
|
|
239
|
+
const {
|
|
240
|
+
register,
|
|
241
|
+
handleSubmit,
|
|
242
|
+
formState: { errors }
|
|
243
|
+
} = useForm<CreateUserForm>({
|
|
240
244
|
resolver: zodResolver(CreateUserForm)
|
|
241
245
|
})
|
|
242
246
|
|
|
@@ -263,19 +267,22 @@ function UserForm() {
|
|
|
263
267
|
### Builders
|
|
264
268
|
|
|
265
269
|
**Basic builders** - Create type-safe functions without auth:
|
|
270
|
+
|
|
266
271
|
```ts
|
|
267
|
-
zQueryBuilder(query)
|
|
272
|
+
zQueryBuilder(query) // Creates query builder
|
|
268
273
|
zMutationBuilder(mutation) // Creates mutation builder
|
|
269
|
-
zActionBuilder(action)
|
|
274
|
+
zActionBuilder(action) // Creates action builder
|
|
270
275
|
```
|
|
271
276
|
|
|
272
277
|
**Custom builders** - Add auth or custom context:
|
|
278
|
+
|
|
273
279
|
```ts
|
|
280
|
+
import { type QueryCtx } from './_generated/server'
|
|
274
281
|
import { customCtx } from 'zodvex'
|
|
275
282
|
|
|
276
283
|
const authQuery = zCustomQueryBuilder(
|
|
277
284
|
query,
|
|
278
|
-
customCtx(async (ctx) => {
|
|
285
|
+
customCtx(async (ctx: QueryCtx) => {
|
|
279
286
|
const user = await getUserOrThrow(ctx)
|
|
280
287
|
return { user }
|
|
281
288
|
})
|
|
@@ -337,28 +344,52 @@ const decoded = codec.decode(encoded)
|
|
|
337
344
|
|
|
338
345
|
### Supported Types
|
|
339
346
|
|
|
340
|
-
| Zod Type
|
|
341
|
-
|
|
|
342
|
-
| `z.string()`
|
|
343
|
-
| `z.number()`
|
|
344
|
-
| `z.bigint()`
|
|
345
|
-
| `z.boolean()`
|
|
346
|
-
| `z.date()`
|
|
347
|
-
| `z.null()`
|
|
348
|
-
| `z.array(T)`
|
|
349
|
-
| `z.object({...})`
|
|
350
|
-
| `z.record(T)`
|
|
351
|
-
| `z.union([...])`
|
|
352
|
-
| `z.literal(x)`
|
|
353
|
-
| `z.enum([
|
|
354
|
-
| `z.optional(T)`
|
|
355
|
-
| `z.nullable(T)`
|
|
347
|
+
| Zod Type | Convex Validator |
|
|
348
|
+
| -------------------- | ------------------------------------------- |
|
|
349
|
+
| `z.string()` | `v.string()` |
|
|
350
|
+
| `z.number()` | `v.float64()` |
|
|
351
|
+
| `z.bigint()` | `v.int64()` |
|
|
352
|
+
| `z.boolean()` | `v.boolean()` |
|
|
353
|
+
| `z.date()` | `v.float64()` (timestamp) |
|
|
354
|
+
| `z.null()` | `v.null()` |
|
|
355
|
+
| `z.array(T)` | `v.array(T)` |
|
|
356
|
+
| `z.object({...})` | `v.object({...})` |
|
|
357
|
+
| `z.record(T)` | `v.record(v.string(), T)` |
|
|
358
|
+
| `z.union([...])` | `v.union(...)` |
|
|
359
|
+
| `z.literal(x)` | `v.literal(x)` |
|
|
360
|
+
| `z.enum(['a', 'b'])` | `v.union(v.literal('a'), v.literal('b'))` ¹ |
|
|
361
|
+
| `z.optional(T)` | `v.optional(T)` |
|
|
362
|
+
| `z.nullable(T)` | `v.union(T, v.null())` |
|
|
363
|
+
|
|
364
|
+
**Zod v4 Enum Type Note:**
|
|
365
|
+
|
|
366
|
+
¹ Enum types in Zod v4 produce a slightly different TypeScript signature than manually created unions:
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
// Manual union (precise tuple type)
|
|
370
|
+
const manual = v.union(v.literal('a'), v.literal('b'))
|
|
371
|
+
// Type: VUnion<"a" | "b", [VLiteral<"a", "required">, VLiteral<"b", "required">], "required", never>
|
|
372
|
+
|
|
373
|
+
// From Zod enum (array type)
|
|
374
|
+
const fromZod = zodToConvex(z.enum(['a', 'b']))
|
|
375
|
+
// Type: VUnion<"a" | "b", Array<VLiteral<"a" | "b", "required">>, "required", never>
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**This difference is purely cosmetic with no functional impact:**
|
|
379
|
+
|
|
380
|
+
- ✅ Value types are identical (`"a" | "b"`)
|
|
381
|
+
- ✅ Runtime validation is identical
|
|
382
|
+
- ✅ Type safety for function arguments/returns is preserved
|
|
383
|
+
- ✅ Convex uses `T[number]` which works identically for both array and tuple types
|
|
384
|
+
|
|
385
|
+
This limitation exists because Zod v4 changed enum types from tuple-based to Record-based ([`ToEnum<T>`](https://github.com/colinhacks/zod/blob/v4/src/v4/core/util.ts#L83-L85)). TypeScript cannot convert a Record type to a specific tuple without knowing the keys at compile time. See [Zod v4 changelog](https://zod.dev/v4/changelog) and [enum evolution discussion](https://github.com/colinhacks/zod/discussions/2125) for more details.
|
|
356
386
|
|
|
357
387
|
**Convex IDs:**
|
|
388
|
+
|
|
358
389
|
```ts
|
|
359
390
|
import { zid } from 'zodvex'
|
|
360
391
|
|
|
361
|
-
zid('tableName')
|
|
392
|
+
zid('tableName') // → v.id('tableName')
|
|
362
393
|
zid('tableName').optional() // → v.optional(v.id('tableName'))
|
|
363
394
|
```
|
|
364
395
|
|
|
@@ -368,14 +399,16 @@ zid('tableName').optional() // → v.optional(v.id('tableName'))
|
|
|
368
399
|
|
|
369
400
|
Create builders with injected auth, permissions, or other context:
|
|
370
401
|
|
|
402
|
+
> **Best Practice:** Always add explicit type annotations to the `ctx` parameter in your `customCtx` functions. This improves TypeScript performance and prevents `ctx` from falling back to `any` in complex type scenarios. Import context types from `./_generated/server` (e.g., `QueryCtx`, `MutationCtx`, `ActionCtx`).
|
|
403
|
+
|
|
371
404
|
```ts
|
|
372
405
|
import { zCustomQueryBuilder, zCustomMutationBuilder, customCtx } from 'zodvex'
|
|
373
|
-
import { query, mutation } from './_generated/server'
|
|
406
|
+
import { type QueryCtx, type MutationCtx, query, mutation } from './_generated/server'
|
|
374
407
|
|
|
375
408
|
// Add user to all queries
|
|
376
409
|
export const authQuery = zCustomQueryBuilder(
|
|
377
410
|
query,
|
|
378
|
-
customCtx(async (ctx) => {
|
|
411
|
+
customCtx(async (ctx: QueryCtx) => {
|
|
379
412
|
const user = await getUserOrThrow(ctx)
|
|
380
413
|
return { user }
|
|
381
414
|
})
|
|
@@ -384,7 +417,7 @@ export const authQuery = zCustomQueryBuilder(
|
|
|
384
417
|
// Add user + permissions to mutations
|
|
385
418
|
export const authMutation = zCustomMutationBuilder(
|
|
386
419
|
mutation,
|
|
387
|
-
customCtx(async (ctx) => {
|
|
420
|
+
customCtx(async (ctx: MutationCtx) => {
|
|
388
421
|
const user = await getUserOrThrow(ctx)
|
|
389
422
|
const permissions = await getPermissions(ctx, user)
|
|
390
423
|
return { user, permissions }
|
|
@@ -461,7 +494,11 @@ const userShape = pickShape(User, ['email', 'firstName', 'lastName'])
|
|
|
461
494
|
const UserUpdate = z.object(userShape)
|
|
462
495
|
|
|
463
496
|
// Or use safePick (convenience wrapper that does the same thing)
|
|
464
|
-
const UserUpdate = safePick(User, {
|
|
497
|
+
const UserUpdate = safePick(User, {
|
|
498
|
+
email: true,
|
|
499
|
+
firstName: true,
|
|
500
|
+
lastName: true
|
|
501
|
+
})
|
|
465
502
|
```
|
|
466
503
|
|
|
467
504
|
## Why zodvex?
|
package/dist/index.d.mts
CHANGED
|
@@ -13,16 +13,29 @@ type IsZid<T> = T extends {
|
|
|
13
13
|
type ExtractTableName<T> = T extends {
|
|
14
14
|
_tableName: infer TableName;
|
|
15
15
|
} ? TableName : never;
|
|
16
|
+
type EnumToLiteralsTuple<T extends readonly [string, ...string[]]> = T['length'] extends 1 ? [VLiteral<T[0], 'required'>] : T['length'] extends 2 ? [VLiteral<T[0], 'required'>, VLiteral<T[1], 'required'>] : [
|
|
17
|
+
VLiteral<T[0], 'required'>,
|
|
18
|
+
VLiteral<T[1], 'required'>,
|
|
19
|
+
...{
|
|
20
|
+
[K in keyof T]: K extends '0' | '1' ? never : K extends keyof T ? VLiteral<T[K], 'required'> : never;
|
|
21
|
+
}[keyof T & number][]
|
|
22
|
+
];
|
|
16
23
|
type ZodValidator = Record<string, z.ZodTypeAny>;
|
|
17
24
|
type ConvexValidatorFromZodRequired<Z extends z.ZodTypeAny> = Z extends z.ZodOptional<infer T extends z.ZodTypeAny> ? VUnion<z.infer<T> | null, any[], 'required'> : ConvexValidatorFromZodBase<Z>;
|
|
18
|
-
type ConvexValidatorFromZodBase<Z extends z.ZodTypeAny> = IsZid<Z> extends true ? ExtractTableName<Z> extends infer TableName extends string ? VId<GenericId<TableName>, 'required'> : VAny<'required'> : Z extends z.ZodString ? VString<z.infer<Z>, 'required'> : Z extends z.ZodNumber ? VFloat64<z.infer<Z>, 'required'> : Z extends z.ZodDate ? VFloat64<number, 'required'> : Z extends z.ZodBigInt ? VInt64<z.infer<Z>, 'required'> : Z extends z.ZodBoolean ? VBoolean<z.infer<Z>, 'required'> : Z extends z.ZodNull ? VNull<null, 'required'> : Z extends z.ZodArray<infer T extends z.ZodTypeAny> ? VArray<z.infer<Z>, ConvexValidatorFromZodRequired<T>, 'required'> : Z extends z.ZodObject<infer T> ? VObject<z.infer<Z>, ConvexValidatorFromZodFieldsAuto<T>, 'required', string> : Z extends z.ZodUnion<infer T> ? T extends readonly [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]] ? VUnion<z.infer<Z>, any[], 'required'> : never : Z extends z.ZodLiteral<infer T> ? VLiteral<T, 'required'> : Z extends z.ZodEnum<infer T> ? T extends
|
|
25
|
+
type ConvexValidatorFromZodBase<Z extends z.ZodTypeAny> = IsZid<Z> extends true ? ExtractTableName<Z> extends infer TableName extends string ? VId<GenericId<TableName>, 'required'> : VAny<'required'> : Z extends z.ZodString ? VString<z.infer<Z>, 'required'> : Z extends z.ZodNumber ? VFloat64<z.infer<Z>, 'required'> : Z extends z.ZodDate ? VFloat64<number, 'required'> : Z extends z.ZodBigInt ? VInt64<z.infer<Z>, 'required'> : Z extends z.ZodBoolean ? VBoolean<z.infer<Z>, 'required'> : Z extends z.ZodNull ? VNull<null, 'required'> : Z extends z.ZodArray<infer T extends z.ZodTypeAny> ? VArray<z.infer<Z>, ConvexValidatorFromZodRequired<T>, 'required'> : Z extends z.ZodObject<infer T> ? VObject<z.infer<Z>, ConvexValidatorFromZodFieldsAuto<T>, 'required', string> : Z extends z.ZodUnion<infer T> ? T extends readonly [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]] ? VUnion<z.infer<Z>, any[], 'required'> : never : Z extends z.ZodLiteral<infer T> ? VLiteral<T, 'required'> : Z extends z.ZodEnum<infer T> ? T extends readonly [string, ...string[]] ? T['length'] extends 1 ? VLiteral<T[0], 'required'> : T['length'] extends 2 ? VUnion<T[number], [
|
|
26
|
+
VLiteral<T[0], 'required'>,
|
|
27
|
+
VLiteral<T[1], 'required'>
|
|
28
|
+
], 'required', never> : VUnion<T[number], EnumToLiteralsTuple<T>, 'required', never> : T extends Record<string, string | number> ? VUnion<T[keyof T], Array<VLiteral<T[keyof T], 'required'>>, 'required', never> : VUnion<string, any[], 'required', any> : Z extends z.ZodRecord<z.ZodString, infer V extends z.ZodTypeAny> ? VRecord<Record<string, z.infer<V>>, VString<string, 'required'>, ConvexValidatorFromZodRequired<V>, 'required', string> : Z extends z.ZodNullable<infer Inner extends z.ZodTypeAny> ? Inner extends z.ZodOptional<infer InnerInner extends z.ZodTypeAny> ? VOptional<VUnion<z.infer<InnerInner> | null, [
|
|
19
29
|
ConvexValidatorFromZodBase<InnerInner>,
|
|
20
30
|
VNull<null, 'required'>
|
|
21
31
|
], 'required'>> : VUnion<z.infer<Inner> | null, [
|
|
22
32
|
ConvexValidatorFromZodBase<Inner>,
|
|
23
33
|
VNull<null, 'required'>
|
|
24
34
|
], 'required'> : Z extends z.ZodAny ? VAny<'required'> : Z extends z.ZodUnknown ? VAny<'required'> : VAny<'required'>;
|
|
25
|
-
type ConvexValidatorFromZod<Z extends z.ZodTypeAny, Constraint extends 'required' | 'optional' = 'required'> = Z extends z.ZodAny ? VAny<'required'> : Z extends z.ZodUnknown ? VAny<'required'> : Z extends z.ZodDefault<infer T extends z.ZodTypeAny> ? ConvexValidatorFromZod<T, Constraint> : Z extends z.ZodOptional<infer T extends z.ZodTypeAny> ? T extends z.ZodNullable<infer Inner extends z.ZodTypeAny> ? VOptional<VUnion<z.infer<Inner> | null, any[], 'required'>> : Constraint extends 'required' ? VUnion<z.infer<T>, any[], 'required'> : VOptional<ConvexValidatorFromZod<T, 'required'>> : Z extends z.ZodNullable<infer T extends z.ZodTypeAny> ? VUnion<z.infer<T> | null, any[], Constraint> : IsZid<Z> extends true ? ExtractTableName<Z> extends infer TableName extends string ? VId<GenericId<TableName>, Constraint> : VAny<'required'> : Z extends z.ZodString ? VString<z.infer<Z>, Constraint> : Z extends z.ZodNumber ? VFloat64<z.infer<Z>, Constraint> : Z extends z.ZodDate ? VFloat64<number, Constraint> : Z extends z.ZodBigInt ? VInt64<z.infer<Z>, Constraint> : Z extends z.ZodBoolean ? VBoolean<z.infer<Z>, Constraint> : Z extends z.ZodNull ? VNull<null, Constraint> : Z extends z.ZodArray<infer T extends z.ZodTypeAny> ? VArray<z.infer<Z>, ConvexValidatorFromZodRequired<T>, Constraint> : Z extends z.ZodObject<infer T> ? VObject<z.infer<Z>, ConvexValidatorFromZodFields<T, 'required'>, Constraint, string> : Z extends z.ZodUnion<infer T> ? T extends readonly [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]] ? VUnion<z.infer<Z>, any[], Constraint> : never : Z extends z.ZodLiteral<infer T> ? VLiteral<T, Constraint> : Z extends z.ZodEnum<infer T> ? T extends
|
|
35
|
+
type ConvexValidatorFromZod<Z extends z.ZodTypeAny, Constraint extends 'required' | 'optional' = 'required'> = Z extends z.ZodAny ? VAny<'required'> : Z extends z.ZodUnknown ? VAny<'required'> : Z extends z.ZodDefault<infer T extends z.ZodTypeAny> ? ConvexValidatorFromZod<T, Constraint> : Z extends z.ZodOptional<infer T extends z.ZodTypeAny> ? T extends z.ZodNullable<infer Inner extends z.ZodTypeAny> ? VOptional<VUnion<z.infer<Inner> | null, any[], 'required'>> : Constraint extends 'required' ? VUnion<z.infer<T>, any[], 'required'> : VOptional<ConvexValidatorFromZod<T, 'required'>> : Z extends z.ZodNullable<infer T extends z.ZodTypeAny> ? VUnion<z.infer<T> | null, any[], Constraint> : IsZid<Z> extends true ? ExtractTableName<Z> extends infer TableName extends string ? VId<GenericId<TableName>, Constraint> : VAny<'required'> : Z extends z.ZodString ? VString<z.infer<Z>, Constraint> : Z extends z.ZodNumber ? VFloat64<z.infer<Z>, Constraint> : Z extends z.ZodDate ? VFloat64<number, Constraint> : Z extends z.ZodBigInt ? VInt64<z.infer<Z>, Constraint> : Z extends z.ZodBoolean ? VBoolean<z.infer<Z>, Constraint> : Z extends z.ZodNull ? VNull<null, Constraint> : Z extends z.ZodArray<infer T extends z.ZodTypeAny> ? VArray<z.infer<Z>, ConvexValidatorFromZodRequired<T>, Constraint> : Z extends z.ZodObject<infer T> ? VObject<z.infer<Z>, ConvexValidatorFromZodFields<T, 'required'>, Constraint, string> : Z extends z.ZodUnion<infer T> ? T extends readonly [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]] ? VUnion<z.infer<Z>, any[], Constraint> : never : Z extends z.ZodLiteral<infer T> ? VLiteral<T, Constraint> : Z extends z.ZodEnum<infer T> ? T extends readonly [string, ...string[]] ? T['length'] extends 1 ? VLiteral<T[0], Constraint> : T['length'] extends 2 ? VUnion<T[number], [
|
|
36
|
+
VLiteral<T[0], 'required'>,
|
|
37
|
+
VLiteral<T[1], 'required'>
|
|
38
|
+
], Constraint, never> : VUnion<T[number], EnumToLiteralsTuple<T>, Constraint, never> : T extends Record<string, string | number> ? VUnion<T[keyof T], Array<VLiteral<T[keyof T], 'required'>>, Constraint, never> : VUnion<string, any[], Constraint, any> : Z extends z.ZodRecord<z.ZodString, infer V extends z.ZodTypeAny> ? VRecord<Record<string, z.infer<V>>, VString<string, 'required'>, ConvexValidatorFromZodRequired<V>, Constraint, string> : VAny<'required'>;
|
|
26
39
|
type ConvexValidatorFromZodFields<T extends {
|
|
27
40
|
[key: string]: any;
|
|
28
41
|
}, Constraint extends 'required' | 'optional' = 'required'> = {
|
|
@@ -228,13 +241,13 @@ declare function zActionBuilder<Builder extends (fn: any) => any>(builder: Build
|
|
|
228
241
|
*
|
|
229
242
|
* @example
|
|
230
243
|
* ```ts
|
|
231
|
-
* import { query } from './_generated/server'
|
|
244
|
+
* import { type QueryCtx, query } from './_generated/server'
|
|
232
245
|
* import { zCustomQueryBuilder, customCtx } from 'zodvex'
|
|
233
246
|
*
|
|
234
247
|
* // Create a builder with auth context
|
|
235
248
|
* export const authQuery = zCustomQueryBuilder(
|
|
236
249
|
* query,
|
|
237
|
-
* customCtx(async (ctx) => {
|
|
250
|
+
* customCtx(async (ctx: QueryCtx) => {
|
|
238
251
|
* const user = await getUserOrThrow(ctx)
|
|
239
252
|
* return { user }
|
|
240
253
|
* })
|
|
@@ -257,13 +270,13 @@ declare function zCustomQueryBuilder<Builder extends (fn: any) => any, CustomArg
|
|
|
257
270
|
*
|
|
258
271
|
* @example
|
|
259
272
|
* ```ts
|
|
260
|
-
* import { mutation } from './_generated/server'
|
|
273
|
+
* import { type MutationCtx, mutation } from './_generated/server'
|
|
261
274
|
* import { zCustomMutationBuilder, customCtx } from 'zodvex'
|
|
262
275
|
*
|
|
263
276
|
* // Create a builder with auth context
|
|
264
277
|
* export const authMutation = zCustomMutationBuilder(
|
|
265
278
|
* mutation,
|
|
266
|
-
* customCtx(async (ctx) => {
|
|
279
|
+
* customCtx(async (ctx: MutationCtx) => {
|
|
267
280
|
* const user = await getUserOrThrow(ctx)
|
|
268
281
|
* return { user }
|
|
269
282
|
* })
|
|
@@ -286,13 +299,13 @@ declare function zCustomMutationBuilder<Builder extends (fn: any) => any, Custom
|
|
|
286
299
|
*
|
|
287
300
|
* @example
|
|
288
301
|
* ```ts
|
|
289
|
-
* import { action } from './_generated/server'
|
|
302
|
+
* import { type ActionCtx, action } from './_generated/server'
|
|
290
303
|
* import { zCustomActionBuilder, customCtx } from 'zodvex'
|
|
291
304
|
*
|
|
292
305
|
* // Create a builder with auth context
|
|
293
306
|
* export const authAction = zCustomActionBuilder(
|
|
294
307
|
* action,
|
|
295
|
-
* customCtx(async (ctx) => {
|
|
308
|
+
* customCtx(async (ctx: ActionCtx) => {
|
|
296
309
|
* const identity = await ctx.auth.getUserIdentity()
|
|
297
310
|
* if (!identity) throw new Error('Unauthorized')
|
|
298
311
|
* return { userId: identity.subject }
|
package/dist/index.d.ts
CHANGED
|
@@ -13,16 +13,29 @@ type IsZid<T> = T extends {
|
|
|
13
13
|
type ExtractTableName<T> = T extends {
|
|
14
14
|
_tableName: infer TableName;
|
|
15
15
|
} ? TableName : never;
|
|
16
|
+
type EnumToLiteralsTuple<T extends readonly [string, ...string[]]> = T['length'] extends 1 ? [VLiteral<T[0], 'required'>] : T['length'] extends 2 ? [VLiteral<T[0], 'required'>, VLiteral<T[1], 'required'>] : [
|
|
17
|
+
VLiteral<T[0], 'required'>,
|
|
18
|
+
VLiteral<T[1], 'required'>,
|
|
19
|
+
...{
|
|
20
|
+
[K in keyof T]: K extends '0' | '1' ? never : K extends keyof T ? VLiteral<T[K], 'required'> : never;
|
|
21
|
+
}[keyof T & number][]
|
|
22
|
+
];
|
|
16
23
|
type ZodValidator = Record<string, z.ZodTypeAny>;
|
|
17
24
|
type ConvexValidatorFromZodRequired<Z extends z.ZodTypeAny> = Z extends z.ZodOptional<infer T extends z.ZodTypeAny> ? VUnion<z.infer<T> | null, any[], 'required'> : ConvexValidatorFromZodBase<Z>;
|
|
18
|
-
type ConvexValidatorFromZodBase<Z extends z.ZodTypeAny> = IsZid<Z> extends true ? ExtractTableName<Z> extends infer TableName extends string ? VId<GenericId<TableName>, 'required'> : VAny<'required'> : Z extends z.ZodString ? VString<z.infer<Z>, 'required'> : Z extends z.ZodNumber ? VFloat64<z.infer<Z>, 'required'> : Z extends z.ZodDate ? VFloat64<number, 'required'> : Z extends z.ZodBigInt ? VInt64<z.infer<Z>, 'required'> : Z extends z.ZodBoolean ? VBoolean<z.infer<Z>, 'required'> : Z extends z.ZodNull ? VNull<null, 'required'> : Z extends z.ZodArray<infer T extends z.ZodTypeAny> ? VArray<z.infer<Z>, ConvexValidatorFromZodRequired<T>, 'required'> : Z extends z.ZodObject<infer T> ? VObject<z.infer<Z>, ConvexValidatorFromZodFieldsAuto<T>, 'required', string> : Z extends z.ZodUnion<infer T> ? T extends readonly [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]] ? VUnion<z.infer<Z>, any[], 'required'> : never : Z extends z.ZodLiteral<infer T> ? VLiteral<T, 'required'> : Z extends z.ZodEnum<infer T> ? T extends
|
|
25
|
+
type ConvexValidatorFromZodBase<Z extends z.ZodTypeAny> = IsZid<Z> extends true ? ExtractTableName<Z> extends infer TableName extends string ? VId<GenericId<TableName>, 'required'> : VAny<'required'> : Z extends z.ZodString ? VString<z.infer<Z>, 'required'> : Z extends z.ZodNumber ? VFloat64<z.infer<Z>, 'required'> : Z extends z.ZodDate ? VFloat64<number, 'required'> : Z extends z.ZodBigInt ? VInt64<z.infer<Z>, 'required'> : Z extends z.ZodBoolean ? VBoolean<z.infer<Z>, 'required'> : Z extends z.ZodNull ? VNull<null, 'required'> : Z extends z.ZodArray<infer T extends z.ZodTypeAny> ? VArray<z.infer<Z>, ConvexValidatorFromZodRequired<T>, 'required'> : Z extends z.ZodObject<infer T> ? VObject<z.infer<Z>, ConvexValidatorFromZodFieldsAuto<T>, 'required', string> : Z extends z.ZodUnion<infer T> ? T extends readonly [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]] ? VUnion<z.infer<Z>, any[], 'required'> : never : Z extends z.ZodLiteral<infer T> ? VLiteral<T, 'required'> : Z extends z.ZodEnum<infer T> ? T extends readonly [string, ...string[]] ? T['length'] extends 1 ? VLiteral<T[0], 'required'> : T['length'] extends 2 ? VUnion<T[number], [
|
|
26
|
+
VLiteral<T[0], 'required'>,
|
|
27
|
+
VLiteral<T[1], 'required'>
|
|
28
|
+
], 'required', never> : VUnion<T[number], EnumToLiteralsTuple<T>, 'required', never> : T extends Record<string, string | number> ? VUnion<T[keyof T], Array<VLiteral<T[keyof T], 'required'>>, 'required', never> : VUnion<string, any[], 'required', any> : Z extends z.ZodRecord<z.ZodString, infer V extends z.ZodTypeAny> ? VRecord<Record<string, z.infer<V>>, VString<string, 'required'>, ConvexValidatorFromZodRequired<V>, 'required', string> : Z extends z.ZodNullable<infer Inner extends z.ZodTypeAny> ? Inner extends z.ZodOptional<infer InnerInner extends z.ZodTypeAny> ? VOptional<VUnion<z.infer<InnerInner> | null, [
|
|
19
29
|
ConvexValidatorFromZodBase<InnerInner>,
|
|
20
30
|
VNull<null, 'required'>
|
|
21
31
|
], 'required'>> : VUnion<z.infer<Inner> | null, [
|
|
22
32
|
ConvexValidatorFromZodBase<Inner>,
|
|
23
33
|
VNull<null, 'required'>
|
|
24
34
|
], 'required'> : Z extends z.ZodAny ? VAny<'required'> : Z extends z.ZodUnknown ? VAny<'required'> : VAny<'required'>;
|
|
25
|
-
type ConvexValidatorFromZod<Z extends z.ZodTypeAny, Constraint extends 'required' | 'optional' = 'required'> = Z extends z.ZodAny ? VAny<'required'> : Z extends z.ZodUnknown ? VAny<'required'> : Z extends z.ZodDefault<infer T extends z.ZodTypeAny> ? ConvexValidatorFromZod<T, Constraint> : Z extends z.ZodOptional<infer T extends z.ZodTypeAny> ? T extends z.ZodNullable<infer Inner extends z.ZodTypeAny> ? VOptional<VUnion<z.infer<Inner> | null, any[], 'required'>> : Constraint extends 'required' ? VUnion<z.infer<T>, any[], 'required'> : VOptional<ConvexValidatorFromZod<T, 'required'>> : Z extends z.ZodNullable<infer T extends z.ZodTypeAny> ? VUnion<z.infer<T> | null, any[], Constraint> : IsZid<Z> extends true ? ExtractTableName<Z> extends infer TableName extends string ? VId<GenericId<TableName>, Constraint> : VAny<'required'> : Z extends z.ZodString ? VString<z.infer<Z>, Constraint> : Z extends z.ZodNumber ? VFloat64<z.infer<Z>, Constraint> : Z extends z.ZodDate ? VFloat64<number, Constraint> : Z extends z.ZodBigInt ? VInt64<z.infer<Z>, Constraint> : Z extends z.ZodBoolean ? VBoolean<z.infer<Z>, Constraint> : Z extends z.ZodNull ? VNull<null, Constraint> : Z extends z.ZodArray<infer T extends z.ZodTypeAny> ? VArray<z.infer<Z>, ConvexValidatorFromZodRequired<T>, Constraint> : Z extends z.ZodObject<infer T> ? VObject<z.infer<Z>, ConvexValidatorFromZodFields<T, 'required'>, Constraint, string> : Z extends z.ZodUnion<infer T> ? T extends readonly [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]] ? VUnion<z.infer<Z>, any[], Constraint> : never : Z extends z.ZodLiteral<infer T> ? VLiteral<T, Constraint> : Z extends z.ZodEnum<infer T> ? T extends
|
|
35
|
+
type ConvexValidatorFromZod<Z extends z.ZodTypeAny, Constraint extends 'required' | 'optional' = 'required'> = Z extends z.ZodAny ? VAny<'required'> : Z extends z.ZodUnknown ? VAny<'required'> : Z extends z.ZodDefault<infer T extends z.ZodTypeAny> ? ConvexValidatorFromZod<T, Constraint> : Z extends z.ZodOptional<infer T extends z.ZodTypeAny> ? T extends z.ZodNullable<infer Inner extends z.ZodTypeAny> ? VOptional<VUnion<z.infer<Inner> | null, any[], 'required'>> : Constraint extends 'required' ? VUnion<z.infer<T>, any[], 'required'> : VOptional<ConvexValidatorFromZod<T, 'required'>> : Z extends z.ZodNullable<infer T extends z.ZodTypeAny> ? VUnion<z.infer<T> | null, any[], Constraint> : IsZid<Z> extends true ? ExtractTableName<Z> extends infer TableName extends string ? VId<GenericId<TableName>, Constraint> : VAny<'required'> : Z extends z.ZodString ? VString<z.infer<Z>, Constraint> : Z extends z.ZodNumber ? VFloat64<z.infer<Z>, Constraint> : Z extends z.ZodDate ? VFloat64<number, Constraint> : Z extends z.ZodBigInt ? VInt64<z.infer<Z>, Constraint> : Z extends z.ZodBoolean ? VBoolean<z.infer<Z>, Constraint> : Z extends z.ZodNull ? VNull<null, Constraint> : Z extends z.ZodArray<infer T extends z.ZodTypeAny> ? VArray<z.infer<Z>, ConvexValidatorFromZodRequired<T>, Constraint> : Z extends z.ZodObject<infer T> ? VObject<z.infer<Z>, ConvexValidatorFromZodFields<T, 'required'>, Constraint, string> : Z extends z.ZodUnion<infer T> ? T extends readonly [z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]] ? VUnion<z.infer<Z>, any[], Constraint> : never : Z extends z.ZodLiteral<infer T> ? VLiteral<T, Constraint> : Z extends z.ZodEnum<infer T> ? T extends readonly [string, ...string[]] ? T['length'] extends 1 ? VLiteral<T[0], Constraint> : T['length'] extends 2 ? VUnion<T[number], [
|
|
36
|
+
VLiteral<T[0], 'required'>,
|
|
37
|
+
VLiteral<T[1], 'required'>
|
|
38
|
+
], Constraint, never> : VUnion<T[number], EnumToLiteralsTuple<T>, Constraint, never> : T extends Record<string, string | number> ? VUnion<T[keyof T], Array<VLiteral<T[keyof T], 'required'>>, Constraint, never> : VUnion<string, any[], Constraint, any> : Z extends z.ZodRecord<z.ZodString, infer V extends z.ZodTypeAny> ? VRecord<Record<string, z.infer<V>>, VString<string, 'required'>, ConvexValidatorFromZodRequired<V>, Constraint, string> : VAny<'required'>;
|
|
26
39
|
type ConvexValidatorFromZodFields<T extends {
|
|
27
40
|
[key: string]: any;
|
|
28
41
|
}, Constraint extends 'required' | 'optional' = 'required'> = {
|
|
@@ -228,13 +241,13 @@ declare function zActionBuilder<Builder extends (fn: any) => any>(builder: Build
|
|
|
228
241
|
*
|
|
229
242
|
* @example
|
|
230
243
|
* ```ts
|
|
231
|
-
* import { query } from './_generated/server'
|
|
244
|
+
* import { type QueryCtx, query } from './_generated/server'
|
|
232
245
|
* import { zCustomQueryBuilder, customCtx } from 'zodvex'
|
|
233
246
|
*
|
|
234
247
|
* // Create a builder with auth context
|
|
235
248
|
* export const authQuery = zCustomQueryBuilder(
|
|
236
249
|
* query,
|
|
237
|
-
* customCtx(async (ctx) => {
|
|
250
|
+
* customCtx(async (ctx: QueryCtx) => {
|
|
238
251
|
* const user = await getUserOrThrow(ctx)
|
|
239
252
|
* return { user }
|
|
240
253
|
* })
|
|
@@ -257,13 +270,13 @@ declare function zCustomQueryBuilder<Builder extends (fn: any) => any, CustomArg
|
|
|
257
270
|
*
|
|
258
271
|
* @example
|
|
259
272
|
* ```ts
|
|
260
|
-
* import { mutation } from './_generated/server'
|
|
273
|
+
* import { type MutationCtx, mutation } from './_generated/server'
|
|
261
274
|
* import { zCustomMutationBuilder, customCtx } from 'zodvex'
|
|
262
275
|
*
|
|
263
276
|
* // Create a builder with auth context
|
|
264
277
|
* export const authMutation = zCustomMutationBuilder(
|
|
265
278
|
* mutation,
|
|
266
|
-
* customCtx(async (ctx) => {
|
|
279
|
+
* customCtx(async (ctx: MutationCtx) => {
|
|
267
280
|
* const user = await getUserOrThrow(ctx)
|
|
268
281
|
* return { user }
|
|
269
282
|
* })
|
|
@@ -286,13 +299,13 @@ declare function zCustomMutationBuilder<Builder extends (fn: any) => any, Custom
|
|
|
286
299
|
*
|
|
287
300
|
* @example
|
|
288
301
|
* ```ts
|
|
289
|
-
* import { action } from './_generated/server'
|
|
302
|
+
* import { type ActionCtx, action } from './_generated/server'
|
|
290
303
|
* import { zCustomActionBuilder, customCtx } from 'zodvex'
|
|
291
304
|
*
|
|
292
305
|
* // Create a builder with auth context
|
|
293
306
|
* export const authAction = zCustomActionBuilder(
|
|
294
307
|
* action,
|
|
295
|
-
* customCtx(async (ctx) => {
|
|
308
|
+
* customCtx(async (ctx: ActionCtx) => {
|
|
296
309
|
* const identity = await ctx.auth.getUserIdentity()
|
|
297
310
|
* if (!identity) throw new Error('Unauthorized')
|
|
298
311
|
* return { userId: identity.subject }
|
package/dist/index.js
CHANGED
|
@@ -724,7 +724,11 @@ function customFnBuilder(builder, customization) {
|
|
|
724
724
|
handleZodValidationError(e, "returns");
|
|
725
725
|
}
|
|
726
726
|
if (added?.onSuccess) {
|
|
727
|
-
await added.onSuccess({
|
|
727
|
+
await added.onSuccess({
|
|
728
|
+
ctx,
|
|
729
|
+
args: parsed.data,
|
|
730
|
+
result: validated
|
|
731
|
+
});
|
|
728
732
|
}
|
|
729
733
|
return toConvexJS(returns, validated);
|
|
730
734
|
}
|