zodvex 0.3.2 → 0.4.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/dist/__type-tests__/infer-returns.d.ts +2 -0
- package/dist/__type-tests__/infer-returns.d.ts.map +1 -0
- package/dist/__type-tests__/zodTable-inference.d.ts +2 -0
- package/dist/__type-tests__/zodTable-inference.d.ts.map +1 -0
- package/dist/builders.d.ts +173 -0
- package/dist/builders.d.ts.map +1 -0
- package/dist/codec.d.ts +11 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/custom.d.ts +142 -0
- package/dist/custom.d.ts.map +1 -0
- package/dist/ids.d.ts +23 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/index.d.ts +10 -599
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -11
- package/dist/index.js.map +1 -1
- package/dist/mapping/core.d.ts +5 -0
- package/dist/mapping/core.d.ts.map +1 -0
- package/dist/mapping/handlers/enum.d.ts +4 -0
- package/dist/mapping/handlers/enum.d.ts.map +1 -0
- package/dist/mapping/handlers/index.d.ts +5 -0
- package/dist/mapping/handlers/index.d.ts.map +1 -0
- package/dist/mapping/handlers/nullable.d.ts +7 -0
- package/dist/mapping/handlers/nullable.d.ts.map +1 -0
- package/dist/mapping/handlers/record.d.ts +4 -0
- package/dist/mapping/handlers/record.d.ts.map +1 -0
- package/dist/mapping/handlers/union.d.ts +5 -0
- package/dist/mapping/handlers/union.d.ts.map +1 -0
- package/dist/mapping/index.d.ts +4 -0
- package/dist/mapping/index.d.ts.map +1 -0
- package/dist/mapping/types.d.ts +43 -0
- package/dist/mapping/types.d.ts.map +1 -0
- package/dist/mapping/utils.d.ts +6 -0
- package/dist/mapping/utils.d.ts.map +1 -0
- package/dist/registry.d.ts +110 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/tables.d.ts +122 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/transform/index.d.ts +26 -0
- package/dist/transform/index.d.ts.map +1 -0
- package/dist/transform/index.js +442 -0
- package/dist/transform/index.js.map +1 -0
- package/dist/transform/transform.d.ts +47 -0
- package/dist/transform/transform.d.ts.map +1 -0
- package/dist/transform/traverse.d.ts +62 -0
- package/dist/transform/traverse.d.ts.map +1 -0
- package/dist/transform/types.d.ts +115 -0
- package/dist/transform/types.d.ts.map +1 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils.d.ts +39 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/wrappers.d.ts +22 -0
- package/dist/wrappers.d.ts.map +1 -0
- package/package.json +13 -6
- package/src/__type-tests__/infer-returns.ts +24 -0
- package/src/custom.ts +170 -15
- package/src/transform/index.ts +38 -0
- package/src/transform/transform.ts +409 -0
- package/src/transform/traverse.ts +320 -0
- package/src/transform/types.ts +128 -0
- package/src/types.ts +3 -2
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema traversal utilities.
|
|
3
|
+
*
|
|
4
|
+
* General-purpose utilities for walking and inspecting Zod schemas.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { z } from 'zod'
|
|
8
|
+
import type { FieldInfo, SchemaVisitor, WalkSchemaOptions } from './types'
|
|
9
|
+
|
|
10
|
+
const METADATA_CACHE = new WeakMap<z.ZodTypeAny, Record<string, unknown> | undefined>()
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Metadata key for ZodSensitive wrappers.
|
|
14
|
+
*/
|
|
15
|
+
const SENSITIVE_META_KEY = 'zodvex:sensitive'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Duck-type check for ZodSensitive wrapper.
|
|
19
|
+
*/
|
|
20
|
+
function isZodSensitiveDef(schema: any): boolean {
|
|
21
|
+
return schema?._def?.type === 'sensitive' && typeof schema?.unwrap === 'function'
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Get metadata from a Zod schema.
|
|
26
|
+
*
|
|
27
|
+
* Handles both Zod's native .meta() and ZodSensitive wrappers.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const schema = z.string().meta({ encrypted: true })
|
|
32
|
+
* const meta = getMetadata(schema)
|
|
33
|
+
* // => { encrypted: true }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function getMetadata(schema: z.ZodTypeAny): Record<string, unknown> | undefined {
|
|
37
|
+
if (METADATA_CACHE.has(schema)) {
|
|
38
|
+
return METADATA_CACHE.get(schema)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const visited = new Set<z.ZodTypeAny>()
|
|
42
|
+
let current: z.ZodTypeAny | undefined = schema
|
|
43
|
+
|
|
44
|
+
while (current) {
|
|
45
|
+
if (visited.has(current)) return undefined
|
|
46
|
+
visited.add(current)
|
|
47
|
+
|
|
48
|
+
// Fast path: ZodSensitive wrapper stores metadata directly
|
|
49
|
+
if (isZodSensitiveDef(current)) {
|
|
50
|
+
const sensitiveMeta = (current as any)._def.sensitiveMetadata
|
|
51
|
+
const meta = { [SENSITIVE_META_KEY]: sensitiveMeta }
|
|
52
|
+
METADATA_CACHE.set(schema, meta)
|
|
53
|
+
return meta
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const meta = current.meta?.() as Record<string, unknown> | undefined
|
|
57
|
+
if (meta !== undefined) {
|
|
58
|
+
METADATA_CACHE.set(schema, meta)
|
|
59
|
+
return meta
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
current = unwrapOnce(current)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
METADATA_CACHE.set(schema, undefined)
|
|
66
|
+
return undefined
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function unwrapOnce(schema: z.ZodTypeAny): z.ZodTypeAny | undefined {
|
|
70
|
+
const defType = (schema as any)._def?.type as string | undefined
|
|
71
|
+
|
|
72
|
+
switch (defType) {
|
|
73
|
+
case 'sensitive': {
|
|
74
|
+
// ZodSensitive wrapper - unwrap to inner schema
|
|
75
|
+
if (typeof (schema as any).unwrap === 'function') {
|
|
76
|
+
return (schema as any).unwrap()
|
|
77
|
+
}
|
|
78
|
+
return (schema as any)._def?.innerType
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
case 'optional':
|
|
82
|
+
case 'nullable': {
|
|
83
|
+
if (typeof (schema as any).unwrap === 'function') {
|
|
84
|
+
return (schema as any).unwrap()
|
|
85
|
+
}
|
|
86
|
+
return (schema as any)._def?.innerType
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
case 'lazy': {
|
|
90
|
+
const getter = (schema as any)._def?.getter
|
|
91
|
+
if (typeof getter === 'function') {
|
|
92
|
+
return getter()
|
|
93
|
+
}
|
|
94
|
+
return undefined
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
case 'default':
|
|
98
|
+
case 'catch':
|
|
99
|
+
case 'readonly':
|
|
100
|
+
case 'prefault':
|
|
101
|
+
case 'nonoptional': {
|
|
102
|
+
return (schema as any)._def?.innerType
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
case 'pipe': {
|
|
106
|
+
return (schema as any)._def?.in
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
default:
|
|
110
|
+
return undefined
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Check if a schema has metadata matching a predicate.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* const schema = z.string().meta({ sensitive: true })
|
|
120
|
+
* hasMetadata(schema, meta => meta.sensitive === true)
|
|
121
|
+
* // => true
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
export function hasMetadata(
|
|
125
|
+
schema: z.ZodTypeAny,
|
|
126
|
+
predicate: (meta: Record<string, unknown>) => boolean
|
|
127
|
+
): boolean {
|
|
128
|
+
const meta = getMetadata(schema)
|
|
129
|
+
return meta !== undefined && predicate(meta)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Walk a Zod schema, calling visitor functions for each node.
|
|
134
|
+
*
|
|
135
|
+
* Handles: objects, arrays, optionals, nullables, unions, discriminated unions.
|
|
136
|
+
* Prevents infinite recursion on circular schema references.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```ts
|
|
140
|
+
* walkSchema(userSchema, {
|
|
141
|
+
* onField: (info) => {
|
|
142
|
+
* if (info.meta?.encrypted) {
|
|
143
|
+
* console.log(`Encrypted field: ${info.path}`)
|
|
144
|
+
* }
|
|
145
|
+
* }
|
|
146
|
+
* })
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
export function walkSchema(
|
|
150
|
+
schema: z.ZodTypeAny,
|
|
151
|
+
visitor: SchemaVisitor,
|
|
152
|
+
options?: WalkSchemaOptions
|
|
153
|
+
): void {
|
|
154
|
+
const recursionStack = new Set<z.ZodTypeAny>()
|
|
155
|
+
const basePath = options?.path ?? ''
|
|
156
|
+
|
|
157
|
+
function traverse(sch: z.ZodTypeAny, currentPath: string, isOptional: boolean): void {
|
|
158
|
+
// Prevent infinite recursion on circular schema references
|
|
159
|
+
if (recursionStack.has(sch)) return
|
|
160
|
+
recursionStack.add(sch)
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
const defType = (sch as any)._def?.type as string | undefined
|
|
164
|
+
const meta = getMetadata(sch)
|
|
165
|
+
const info: FieldInfo = { path: currentPath, schema: sch, meta, isOptional }
|
|
166
|
+
|
|
167
|
+
// Call onField for every schema node
|
|
168
|
+
if (visitor.onField) {
|
|
169
|
+
const result = visitor.onField(info)
|
|
170
|
+
if (result === 'skip') return
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Dispatch based on schema type
|
|
174
|
+
switch (defType) {
|
|
175
|
+
case 'sensitive': {
|
|
176
|
+
// ZodSensitive wrapper - already reported via onField, now traverse inner
|
|
177
|
+
const inner = (sch as any).unwrap?.() ?? (sch as any)._def?.innerType
|
|
178
|
+
if (inner) {
|
|
179
|
+
traverse(inner, currentPath, isOptional)
|
|
180
|
+
}
|
|
181
|
+
return
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
case 'optional': {
|
|
185
|
+
const inner = (sch as any).unwrap()
|
|
186
|
+
traverse(inner, currentPath, true)
|
|
187
|
+
return
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
case 'nullable': {
|
|
191
|
+
const inner = (sch as any).unwrap()
|
|
192
|
+
traverse(inner, currentPath, isOptional)
|
|
193
|
+
return
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
case 'lazy': {
|
|
197
|
+
const getter = (sch as any)._def?.getter
|
|
198
|
+
if (typeof getter === 'function') {
|
|
199
|
+
const inner = getter()
|
|
200
|
+
traverse(inner, currentPath, isOptional)
|
|
201
|
+
}
|
|
202
|
+
return
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
case 'default':
|
|
206
|
+
case 'catch':
|
|
207
|
+
case 'readonly':
|
|
208
|
+
case 'prefault':
|
|
209
|
+
case 'nonoptional': {
|
|
210
|
+
const inner = (sch as any)._def?.innerType as z.ZodTypeAny | undefined
|
|
211
|
+
if (inner) {
|
|
212
|
+
traverse(inner, currentPath, isOptional)
|
|
213
|
+
}
|
|
214
|
+
return
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
case 'pipe': {
|
|
218
|
+
const inner = (sch as any)._def?.in as z.ZodTypeAny | undefined
|
|
219
|
+
if (inner) {
|
|
220
|
+
traverse(inner, currentPath, isOptional)
|
|
221
|
+
}
|
|
222
|
+
return
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
case 'object': {
|
|
226
|
+
visitor.onObject?.(info)
|
|
227
|
+
const shape = (sch as any).shape
|
|
228
|
+
if (shape) {
|
|
229
|
+
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
230
|
+
const fieldPath = currentPath ? `${currentPath}.${key}` : key
|
|
231
|
+
traverse(fieldSchema as z.ZodTypeAny, fieldPath, false)
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
case 'array': {
|
|
238
|
+
visitor.onArray?.(info)
|
|
239
|
+
const element = (sch as any).element
|
|
240
|
+
if (element) {
|
|
241
|
+
const arrayPath = currentPath ? `${currentPath}[]` : '[]'
|
|
242
|
+
traverse(element, arrayPath, false)
|
|
243
|
+
}
|
|
244
|
+
return
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
case 'union': {
|
|
248
|
+
const unionOptions = (sch as any)._def.options as z.ZodTypeAny[] | undefined
|
|
249
|
+
|
|
250
|
+
// Get options from either _def.options or _def.optionsMap
|
|
251
|
+
const variantOptions =
|
|
252
|
+
unionOptions ||
|
|
253
|
+
((sch as any)._def.optionsMap ? Array.from((sch as any)._def.optionsMap.values()) : [])
|
|
254
|
+
|
|
255
|
+
visitor.onUnion?.(info, variantOptions as z.ZodTypeAny[])
|
|
256
|
+
|
|
257
|
+
for (const variant of variantOptions as z.ZodTypeAny[]) {
|
|
258
|
+
traverse(variant, currentPath, isOptional)
|
|
259
|
+
}
|
|
260
|
+
return
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Primitives and other types are leaf nodes - nothing more to traverse
|
|
265
|
+
} finally {
|
|
266
|
+
recursionStack.delete(sch)
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
traverse(schema, basePath, false)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Find all fields in a schema where metadata matches a predicate.
|
|
275
|
+
*
|
|
276
|
+
* @overload Type guard version - returns narrowed meta type
|
|
277
|
+
*/
|
|
278
|
+
export function findFieldsWithMeta<TMeta extends Record<string, unknown>>(
|
|
279
|
+
schema: z.ZodTypeAny,
|
|
280
|
+
predicate: (meta: Record<string, unknown> | undefined) => meta is TMeta
|
|
281
|
+
): Array<FieldInfo & { meta: TMeta }>
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* @overload Boolean predicate version
|
|
285
|
+
*/
|
|
286
|
+
export function findFieldsWithMeta(
|
|
287
|
+
schema: z.ZodTypeAny,
|
|
288
|
+
predicate: (meta: Record<string, unknown> | undefined) => boolean
|
|
289
|
+
): FieldInfo[]
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Find all fields in a schema where metadata matches a predicate.
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```ts
|
|
296
|
+
* // Find all fields with 'sensitive' metadata
|
|
297
|
+
* const sensitiveFields = findFieldsWithMeta(
|
|
298
|
+
* userSchema,
|
|
299
|
+
* (meta) => meta?.sensitive === true
|
|
300
|
+
* )
|
|
301
|
+
* // => [{ path: 'email', schema: z.string(), meta: { sensitive: true } }, ...]
|
|
302
|
+
* ```
|
|
303
|
+
*/
|
|
304
|
+
export function findFieldsWithMeta(
|
|
305
|
+
schema: z.ZodTypeAny,
|
|
306
|
+
predicate: (meta: Record<string, unknown> | undefined) => boolean
|
|
307
|
+
): FieldInfo[] {
|
|
308
|
+
const results: FieldInfo[] = []
|
|
309
|
+
|
|
310
|
+
walkSchema(schema, {
|
|
311
|
+
onField: info => {
|
|
312
|
+
if (predicate(info.meta)) {
|
|
313
|
+
results.push(info)
|
|
314
|
+
return 'skip' // Don't recurse into matching fields
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
return results
|
|
320
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transform layer type definitions.
|
|
3
|
+
*
|
|
4
|
+
* General-purpose types for schema traversal and value transformation.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { z } from 'zod'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Information about a field during schema traversal.
|
|
11
|
+
*/
|
|
12
|
+
export type FieldInfo = {
|
|
13
|
+
/** Dot-notation path (e.g., 'profile.email', 'contacts[].email') */
|
|
14
|
+
path: string
|
|
15
|
+
/** The Zod schema for this field */
|
|
16
|
+
schema: z.ZodTypeAny
|
|
17
|
+
/** Metadata from schema.meta() if present */
|
|
18
|
+
meta: Record<string, unknown> | undefined
|
|
19
|
+
/** Whether the field is wrapped in optional/nullable */
|
|
20
|
+
isOptional: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Visitor functions for walkSchema().
|
|
25
|
+
*/
|
|
26
|
+
export type SchemaVisitor = {
|
|
27
|
+
/** Called for every field. Return 'skip' to skip children. */
|
|
28
|
+
onField?: (info: FieldInfo) => void | 'skip'
|
|
29
|
+
/** Called when entering an object schema */
|
|
30
|
+
onObject?: (info: FieldInfo) => void
|
|
31
|
+
/** Called when entering an array schema */
|
|
32
|
+
onArray?: (info: FieldInfo) => void
|
|
33
|
+
/** Called when entering a union schema */
|
|
34
|
+
onUnion?: (info: FieldInfo, variants: z.ZodTypeAny[]) => void
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Options for walkSchema().
|
|
39
|
+
*/
|
|
40
|
+
export type WalkSchemaOptions = {
|
|
41
|
+
/** Starting path prefix */
|
|
42
|
+
path?: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Context passed to transform functions.
|
|
47
|
+
*/
|
|
48
|
+
export type TransformContext<TCtx = unknown> = {
|
|
49
|
+
/** Current field path */
|
|
50
|
+
path: string
|
|
51
|
+
/** The Zod schema for this field */
|
|
52
|
+
schema: z.ZodTypeAny
|
|
53
|
+
/** Metadata from schema.meta() if present */
|
|
54
|
+
meta: Record<string, unknown> | undefined
|
|
55
|
+
/** User-provided context */
|
|
56
|
+
ctx: TCtx
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Synchronous transform function signature.
|
|
61
|
+
*/
|
|
62
|
+
export type TransformFn<TCtx = unknown> = (
|
|
63
|
+
value: unknown,
|
|
64
|
+
context: TransformContext<TCtx>
|
|
65
|
+
) => unknown
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Async transform function signature.
|
|
69
|
+
*/
|
|
70
|
+
export type AsyncTransformFn<TCtx = unknown> = (
|
|
71
|
+
value: unknown,
|
|
72
|
+
context: TransformContext<TCtx>
|
|
73
|
+
) => unknown | Promise<unknown>
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Options for transformBySchema().
|
|
77
|
+
*/
|
|
78
|
+
export type TransformOptions = {
|
|
79
|
+
/** Starting path prefix */
|
|
80
|
+
path?: string
|
|
81
|
+
/**
|
|
82
|
+
* How to handle values that don't match any union variant.
|
|
83
|
+
* - 'passthrough': Return value unchanged (default)
|
|
84
|
+
* - 'error': Throw an error
|
|
85
|
+
* - 'null': Replace with null (fail-closed for security)
|
|
86
|
+
*/
|
|
87
|
+
unmatchedUnion?: 'passthrough' | 'error' | 'null'
|
|
88
|
+
/** Callback when a union doesn't match */
|
|
89
|
+
onUnmatchedUnion?: (path: string) => void
|
|
90
|
+
/**
|
|
91
|
+
* Fast predicate to check if a schema needs transformation.
|
|
92
|
+
*
|
|
93
|
+
* When provided, this predicate is called before the transform callback.
|
|
94
|
+
* If it returns false, the transform callback is skipped for this schema
|
|
95
|
+
* (but recursion into children continues).
|
|
96
|
+
*
|
|
97
|
+
* This optimization avoids callback overhead for schemas that don't need
|
|
98
|
+
* transformation, which is useful when only a small subset of fields
|
|
99
|
+
* require processing (e.g., only sensitive fields).
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* // Only call transform for schemas with sensitive metadata
|
|
104
|
+
* transformBySchema(value, schema, ctx, transform, {
|
|
105
|
+
* shouldTransform: (sch) => getSensitiveMetadata(sch) !== undefined
|
|
106
|
+
* })
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
shouldTransform?: (schema: z.ZodTypeAny) => boolean
|
|
110
|
+
/**
|
|
111
|
+
* Process array elements in parallel (async only).
|
|
112
|
+
*
|
|
113
|
+
* When true, array elements are processed with Promise.all() instead of
|
|
114
|
+
* sequentially. This can significantly improve performance for large arrays
|
|
115
|
+
* when transforms involve async operations like entitlement checks.
|
|
116
|
+
*
|
|
117
|
+
* Default: false (sequential processing for backwards compatibility)
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* // Process user entitlements for all items in parallel
|
|
122
|
+
* const result = await transformBySchemaAsync(docs, schema, ctx, transform, {
|
|
123
|
+
* parallel: true
|
|
124
|
+
* })
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
parallel?: boolean
|
|
128
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -26,8 +26,9 @@ export type InferReturns<R> = R extends z.ZodType<any, any, any>
|
|
|
26
26
|
: R
|
|
27
27
|
|
|
28
28
|
// For handler authoring: what the handler returns before wrapper validation/encoding
|
|
29
|
-
// Uses z.
|
|
30
|
-
|
|
29
|
+
// Uses z.output since the handler produces the internal representation (e.g., Date),
|
|
30
|
+
// which is then encoded to wire format (e.g., string) before sending to the client
|
|
31
|
+
export type InferHandlerReturns<R> = R extends z.ZodType<any, any, any> ? z.output<R> : any
|
|
31
32
|
|
|
32
33
|
/**
|
|
33
34
|
* Extract the visibility type from a Convex builder function
|