zodvex 0.7.2 → 0.7.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zodvex",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
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",
@@ -118,7 +118,11 @@ type Registration<
118
118
  */
119
119
  export type CustomBuilder<
120
120
  FuncType extends 'query' | 'mutation' | 'action',
121
- CustomArgsValidator extends PropertyValidators,
121
+ // The customization's caller-facing args as a resolved object type (the args
122
+ // the caller must supply so the customization's `input` can consume them).
123
+ // Resolved rather than a `PropertyValidators` slot so zodvex customizations
124
+ // (`.withContext({ args: <zod> })`) can express decoded-runtime arg types. #72
125
+ CustomArgs extends Record<string, any>,
122
126
  CustomCtx extends Record<string, any>,
123
127
  CustomMadeArgs extends Record<string, any>,
124
128
  InputCtx,
@@ -170,11 +174,11 @@ export type CustomBuilder<
170
174
  FuncType,
171
175
  Visibility,
172
176
  ArgsArrayToObject<
173
- CustomArgsValidator extends Record<string, never>
177
+ CustomArgs extends Record<string, never>
174
178
  ? ArgsInput<ArgsValidator>
175
179
  : ArgsInput<ArgsValidator> extends [infer A]
176
- ? [Expand<A & import('convex/values').ObjectType<CustomArgsValidator>>]
177
- : [import('convex/values').ObjectType<CustomArgsValidator>]
180
+ ? [Expand<A & CustomArgs>]
181
+ : [CustomArgs]
178
182
  >,
179
183
  ReturnsZodValidator extends void ? ReturnValue : ReturnValueOutput<ReturnsZodValidator>
180
184
  >
@@ -192,7 +196,22 @@ export function customFnBuilder<
192
196
  customization: Customization<Ctx, CustomArgsValidator, CustomCtx, CustomMadeArgs, ExtraArgs>
193
197
  ) {
194
198
  const customInput = customization.input ?? NoOp.input
195
- const inputArgs = customization.args ?? NoOp.args
199
+ const rawInputArgs = customization.args ?? NoOp.args
200
+
201
+ // #72: a customization may declare its args as zod (e.g. a codec-typed arg in
202
+ // `.withContext({ args: { token: myCodec } })`). Those must enter the same
203
+ // pipeline as consumer args — converted to Convex validators for registration
204
+ // and codec-decoded before `input` runs. Pre-built Convex validators (the
205
+ // legacy shape) are passed through unchanged for back-compat.
206
+ const customArgEntries = Object.entries(rawInputArgs)
207
+ const customArgsAreZod =
208
+ customArgEntries.length > 0 && customArgEntries.every(([, v]) => v instanceof $ZodType)
209
+ const inputArgs = customArgsAreZod
210
+ ? zodToConvexFields(rawInputArgs as unknown as ZodValidator)
211
+ : rawInputArgs
212
+ const customArgsSchema = customArgsAreZod
213
+ ? (z.object(rawInputArgs as any) as unknown as $ZodObject)
214
+ : undefined
196
215
 
197
216
  return function customBuilder(fn: any): any {
198
217
  const { args, handler = fn, returns: maybeObject, ...extra } = fn
@@ -227,7 +246,8 @@ export function customFnBuilder<
227
246
  ctx,
228
247
  allArgs,
229
248
  inputArgs,
230
- extra
249
+ extra,
250
+ customArgsSchema
231
251
  )
232
252
  const argKeys = Object.keys(argsValidator)
233
253
  const rawArgs = pick(allArgs, argKeys)
@@ -251,7 +271,8 @@ export function customFnBuilder<
251
271
  ctx,
252
272
  allArgs,
253
273
  inputArgs,
254
- extra
274
+ extra,
275
+ customArgsSchema
255
276
  )
256
277
  const { finalCtx, finalArgs } = applyCustomizationResult(ctx as any, baseArgs, added)
257
278
 
@@ -293,7 +314,7 @@ export function zCustomQuery<
293
314
  customization: Customization<any, CustomArgsValidator, CustomCtx, CustomMadeArgs, ExtraArgs>
294
315
  ): CustomBuilder<
295
316
  'query',
296
- CustomArgsValidator,
317
+ import('convex/values').ObjectType<CustomArgsValidator>,
297
318
  CustomCtx,
298
319
  CustomMadeArgs,
299
320
  GenericQueryCtx<DataModel>,
@@ -313,7 +334,7 @@ export function zCustomQuery<
313
334
  customization: Customization<any, CustomArgsValidator, CustomCtx, CustomMadeArgs, ExtraArgs>
314
335
  ): CustomBuilder<
315
336
  'query',
316
- CustomArgsValidator,
337
+ import('convex/values').ObjectType<CustomArgsValidator>,
317
338
  CustomCtx,
318
339
  CustomMadeArgs,
319
340
  any,
@@ -358,7 +379,7 @@ export function zCustomMutation<
358
379
  customization: Customization<any, CustomArgsValidator, CustomCtx, CustomMadeArgs, ExtraArgs>
359
380
  ): CustomBuilder<
360
381
  'mutation',
361
- CustomArgsValidator,
382
+ import('convex/values').ObjectType<CustomArgsValidator>,
362
383
  CustomCtx,
363
384
  CustomMadeArgs,
364
385
  ExtractCtx<Builder>,
@@ -396,7 +417,7 @@ export function zCustomAction<
396
417
  customization: Customization<any, CustomArgsValidator, CustomCtx, CustomMadeArgs, ExtraArgs>
397
418
  ): CustomBuilder<
398
419
  'action',
399
- CustomArgsValidator,
420
+ import('convex/values').ObjectType<CustomArgsValidator>,
400
421
  CustomCtx,
401
422
  CustomMadeArgs,
402
423
  ExtractCtx<Builder>,
@@ -174,16 +174,18 @@ export async function runCustomizationInput(
174
174
  ctx: unknown,
175
175
  allArgs: Record<string, unknown>,
176
176
  inputArgs: Record<string, unknown>,
177
- extra: Record<string, unknown>
177
+ extra: Record<string, unknown>,
178
+ argsSchema?: $ZodObject
178
179
  ): Promise<CustomInputResult | undefined> {
179
- return (await customInput(
180
- ctx,
181
- // Cast justification: customInput expects ObjectType<CustomArgsValidator>, but pick()
182
- // returns Partial<T>. The cast is safe because inputArgs keys are derived from
183
- // CustomArgsValidator at the type level.
184
- pick(allArgs, Object.keys(inputArgs)) as any,
185
- extra
186
- )) as CustomInputResult | undefined
180
+ // Cast justification: customInput expects ObjectType<CustomArgsValidator>, but pick()
181
+ // returns Partial<T>. The cast is safe because inputArgs keys are derived from
182
+ // CustomArgsValidator at the type level.
183
+ const picked = pick(allArgs, Object.keys(inputArgs)) as Record<string, unknown>
184
+ // #72: when the customization declared its args as zod, decode them (codec
185
+ // transforms applied) before the customization's `input` runs — symmetric
186
+ // with how consumer args are decoded via parseObjectArgsOrThrow.
187
+ const customArgs = argsSchema ? parseObjectArgsOrThrow(argsSchema, picked) : picked
188
+ return (await customInput(ctx, customArgs as any, extra)) as CustomInputResult | undefined
187
189
  }
188
190
 
189
191
  export function applyCustomizationResult(
@@ -8,8 +8,6 @@ import type {
8
8
  MutationBuilder,
9
9
  QueryBuilder
10
10
  } from 'convex/server'
11
- import type { PropertyValidators } from 'convex/values'
12
- import type { Customization } from 'convex-helpers/server/customFunctions'
13
11
  import { NoOp } from 'convex-helpers/server/customFunctions'
14
12
  import type { z } from 'zod'
15
13
  import { createZodvexActionCtx } from './actionCtx'
@@ -17,8 +15,10 @@ import type { CustomBuilder } from './custom'
17
15
  import { zCustomAction, zCustomMutation, zCustomQuery } from './custom'
18
16
  import { createZodvexCustomization } from './customization'
19
17
  import type { ZodvexDatabaseReader, ZodvexDatabaseWriter } from './db'
18
+ import type { ZodValidator } from './mapping'
20
19
  import type { ZodTableMap } from './schema'
21
20
  import type { AnyRegistry, Overwrite } from './types'
21
+ import type { $ZodObject } from './zod-core'
22
22
 
23
23
  /**
24
24
  * The context type received by query handlers when wrapDb: true.
@@ -71,6 +71,34 @@ type InitServerBuilders = {
71
71
  internalAction: ActionBuilder<any, 'internal'>
72
72
  }
73
73
 
74
+ type MaybePromise<T> = T | Promise<T>
75
+
76
+ /**
77
+ * A `.withContext()` customization for zodvex builders. Unlike convex-helpers'
78
+ * `Customization` (which types `args` as Convex `PropertyValidators`), the
79
+ * declared `args` are **zod** — they run through the same zod→Convex + codec
80
+ * pipeline as consumer args, so `input` receives the **decoded runtime** values
81
+ * (`z.output`), and the resulting function registers the wire validator. See #72.
82
+ */
83
+ type ZodWithContextCustomization<
84
+ InputCtx,
85
+ ZArgs extends ZodValidator,
86
+ CustomCtx extends Record<string, any>,
87
+ CustomMadeArgs extends Record<string, any>,
88
+ ExtraArgs extends Record<string, any>
89
+ > = {
90
+ args?: ZArgs
91
+ input?: (
92
+ ctx: InputCtx,
93
+ args: z.output<$ZodObject<ZArgs>>,
94
+ extra?: ExtraArgs
95
+ ) => MaybePromise<{
96
+ ctx: CustomCtx
97
+ args?: CustomMadeArgs
98
+ onSuccess?: (params: { ctx: unknown; args: unknown; result: unknown }) => unknown
99
+ }>
100
+ }
101
+
74
102
  /**
75
103
  * A zodvex builder: callable CustomBuilder + .withContext() for composing
76
104
  * user customizations on top of the codec layer.
@@ -93,21 +121,21 @@ export type ZodvexBuilder<
93
121
  Record<string, any>
94
122
  > & {
95
123
  withContext: <
96
- CustomArgsValidator extends PropertyValidators,
97
- CustomCtx extends Record<string, any>,
98
- CustomMadeArgs extends Record<string, any>,
124
+ ZArgs extends ZodValidator = Record<string, never>,
125
+ CustomCtx extends Record<string, any> = Record<string, never>,
126
+ CustomMadeArgs extends Record<string, any> = Record<string, never>,
99
127
  ExtraArgs extends Record<string, any> = Record<string, any>
100
128
  >(
101
- customization: Customization<
129
+ customization: ZodWithContextCustomization<
102
130
  Overwrite<InputCtx, CodecCtx>,
103
- CustomArgsValidator,
131
+ ZArgs,
104
132
  CustomCtx,
105
133
  CustomMadeArgs,
106
134
  ExtraArgs
107
135
  >
108
136
  ) => CustomBuilder<
109
137
  FuncType,
110
- CustomArgsValidator,
138
+ z.output<$ZodObject<ZArgs>>,
111
139
  Overwrite<CodecCtx, CustomCtx>,
112
140
  CustomMadeArgs,
113
141
  InputCtx,