zodvex 0.7.4 → 0.7.5-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 +1 -1
- package/dist/client/index.js +69 -9
- package/dist/client/index.js.map +1 -1
- package/dist/internal/actionCtx.d.ts +18 -2
- package/dist/internal/actionCtx.d.ts.map +1 -1
- package/dist/internal/init.d.ts.map +1 -1
- package/dist/mini/client/index.js +69 -9
- package/dist/mini/client/index.js.map +1 -1
- package/dist/mini/react/index.js +11 -0
- package/dist/mini/react/index.js.map +1 -1
- package/dist/mini/server/index.js +56 -20
- package/dist/mini/server/index.js.map +1 -1
- package/dist/public/client/zodvexClient.d.ts +38 -2
- package/dist/public/client/zodvexClient.d.ts.map +1 -1
- package/dist/public/react/zodvexReactClient.d.ts +10 -0
- package/dist/public/react/zodvexReactClient.d.ts.map +1 -1
- package/dist/react/index.js +11 -0
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.js +56 -20
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
- package/src/internal/actionCtx.ts +73 -18
- package/src/internal/init.ts +35 -6
- package/src/public/client/zodvexClient.ts +116 -11
- package/src/public/react/zodvexReactClient.ts +17 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/internal/normalizeCodecPaths.ts","../../../src/internal/stripUndefined.ts","../../../src/internal/boundaryHelpers.ts","../../../src/public/react/hooks.ts","../../../src/public/react/zodvexReactClient.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import {\n $ZodArray,\n $ZodCodec,\n $ZodDefault,\n $ZodError,\n $ZodNullable,\n $ZodObject,\n $ZodOptional,\n $ZodType,\n encode\n} from './zod-core'\n\n/**\n * Unwraps ZodOptional/ZodNullable/ZodDefault wrappers to get the structural type.\n */\nfunction unwrapOuter(schema: $ZodType): $ZodType {\n let current: $ZodType = schema\n for (let i = 0; i < 10; i++) {\n if (\n current instanceof $ZodOptional ||\n current instanceof $ZodNullable ||\n current instanceof $ZodDefault\n ) {\n current = current._zod.def.innerType\n continue\n }\n break\n }\n return current\n}\n\n/**\n * Walks a path through a schema tree, truncating at codec boundaries.\n * When a codec is encountered, the path is cut — any deeper segments\n * are wire-internal and should not be exposed to consumers.\n */\nfunction truncateAtCodecBoundary(path: (string | number)[], schema: $ZodType): (string | number)[] {\n const result: (string | number)[] = []\n let current: $ZodType = schema\n\n for (const segment of path) {\n current = unwrapOuter(current)\n\n // If we've landed on a codec, everything from here is wire-internal — stop\n if (current instanceof $ZodCodec) {\n break\n }\n\n // Descend into objects\n if (current instanceof $ZodObject && typeof segment === 'string') {\n const fieldSchema = current._zod.def.shape[segment] as $ZodType | undefined\n if (!fieldSchema) {\n // Unknown field — include segment and stop\n result.push(segment)\n break\n }\n\n result.push(segment)\n\n const unwrapped = unwrapOuter(fieldSchema)\n if (unwrapped instanceof $ZodCodec) {\n // Hit a codec boundary — truncate here\n break\n }\n\n current = fieldSchema\n continue\n }\n\n // Descend into arrays\n if (current instanceof $ZodArray && typeof segment === 'number') {\n result.push(segment)\n current = current._zod.def.element\n continue\n }\n\n // For anything else (unions, records, etc.), include segment and continue\n result.push(segment)\n }\n\n return result\n}\n\n/**\n * Normalizes ZodError paths by truncating at codec boundaries.\n *\n * When z.encode() throws a ZodError, the paths reflect the wire schema\n * structure (e.g., [\"email\", \"value\"] for a custom codec).\n * This function strips the wire-internal segments so consumers see\n * clean field-level paths (e.g., [\"email\"]).\n */\nexport function normalizeCodecPaths(error: $ZodError, schema: $ZodType): $ZodError {\n const normalized = error.issues.map(issue => ({\n ...issue,\n path: truncateAtCodecBoundary(issue.path as (string | number)[], schema)\n }))\n return new $ZodError(normalized)\n}\n\n/**\n * Encodes a value through a Zod schema, normalizing codec-internal\n * path segments in any ZodError before re-throwing.\n *\n * Drop-in replacement for `z.encode(schema, value)` at client boundaries.\n */\nexport function safeEncode(schema: $ZodType, value: unknown): unknown {\n try {\n return encode(schema, value)\n } catch (e) {\n if (e instanceof $ZodError) throw normalizeCodecPaths(e as $ZodError, schema)\n throw e\n }\n}\n","/**\n * Recursively strips `undefined` values from objects and arrays.\n * Used by codec encode/decode to clean wire data.\n *\n * Extracted to its own module so client-safe code (boundaryHelpers)\n * can import it without pulling in zod via utils.ts.\n */\nexport function stripUndefined<T>(value: T): T {\n if (value === null || value === undefined) {\n return value\n }\n\n if (Array.isArray(value)) {\n return value.map(stripUndefined) as T\n }\n\n // Only process plain objects (not class instances, Dates, etc.)\n if (typeof value === 'object' && value.constructor === Object) {\n const result: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(value)) {\n if (val !== undefined) {\n result[key] = stripUndefined(val)\n }\n }\n return result as T\n }\n\n return value\n}\n","import type { FunctionReference } from 'convex/server'\nimport type { $ZodIssue } from 'zod/v4/core'\nimport { safeEncode } from './normalizeCodecPaths'\nimport { stripUndefined } from './stripUndefined'\nimport type { AnyRegistry } from './types'\nimport { $ZodError, safeParse } from './zod-core'\n\n/**\n * Resolves a Convex FunctionReference to its string path.\n *\n * Mirrors `getFunctionName` from `convex/server` but without the server import.\n * Reads the well-known `Symbol.for('functionName')` that Convex attaches to all\n * function references — the same symbol used by Convex's own browser client.\n */\nconst functionNameSymbol = Symbol.for('functionName')\n\nfunction resolveFunctionPath(ref: FunctionReference<any, any, any, any>): string {\n if (typeof ref === 'string') return ref\n const name = (ref as any)[functionNameSymbol]\n if (!name) {\n throw new Error(\n `Expected a Convex function reference (e.g. api.file.func), but received ${JSON.stringify(ref)}`\n )\n }\n return name\n}\n\n/**\n * Options for codec helper behavior.\n */\nexport type BoundaryHelpersOptions = {\n /**\n * How to handle decode failures (schema validation errors on wire data).\n *\n * - `'warn'` (default): log a console.warn and return raw wire data untransformed.\n * - `'throw'`: throw a ZodvexDecodeError (extends z.ZodError). // zod-ok\n */\n onDecodeError?: 'warn' | 'throw'\n}\n\n/**\n * Decode error with function path and wire data context.\n * Extends $ZodError from zod/v4/core for compatibility with both zod and zod/mini.\n * instanceof $ZodError checks work in both variants.\n */\nexport class ZodvexDecodeError extends $ZodError {\n readonly functionPath: string\n readonly wireData: unknown\n\n constructor(functionPath: string, issues: $ZodIssue[], wireData: unknown) {\n super(issues)\n this.functionPath = functionPath\n this.wireData = wireData\n this.name = 'ZodvexDecodeError'\n }\n}\n\n/**\n * Creates shared encode/decode helpers bound to a zodvex registry.\n *\n * These are the core primitives used by all codec boundary implementations:\n * - `encodeArgs`: runtime types -> wire format (e.g., Date -> timestamp number)\n * - `decodeResult`: wire format -> runtime types (e.g., timestamp number -> Date)\n *\n * Both look up the function reference in the registry to find the appropriate\n * Zod schema, then apply the codec transform. Functions not in the registry\n * (or without the relevant schema) pass through unchanged.\n *\n * @param registry - A map of function paths to `{ args?, returns? }` Zod schemas.\n * Typically generated by zodvex codegen into `_zodvex/api.ts`.\n * @param options - Optional configuration for decode error behavior.\n */\nexport function createBoundaryHelpers(registry: AnyRegistry, options?: BoundaryHelpersOptions) {\n const onDecodeError = options?.onDecodeError ?? 'warn'\n const warnedPaths = new Set<string>()\n\n /**\n * Encode args from runtime types to wire format.\n *\n * Uses `safeEncode` (not raw `z.encode`) to normalize codec-internal\n * error paths in ZodErrors, then strips undefined values for Convex\n * serialization compatibility.\n *\n * Passthrough when:\n * - args is null/undefined\n * - function is not in the registry\n * - registry entry has no args schema\n */\n function encodeArgs(ref: FunctionReference<any, any, any, any>, args: any): any {\n if (args == null) return args\n const path = resolveFunctionPath(ref)\n const entry = registry[path]\n if (!entry?.args) {\n if (entry === undefined && !warnedPaths.has(path)) {\n warnedPaths.add(path)\n console.debug(\n `[zodvex] No registry entry for \"${path}\" — args will not be codec-encoded. ` +\n 'If this function uses zodvex wrappers, run `zodvex generate` to update the registry.'\n )\n }\n return args\n }\n return stripUndefined(safeEncode(entry.args, args))\n }\n\n /**\n * Decode a wire result back to runtime types.\n *\n * Uses `.safeParse()` to decode. On failure:\n * - 'warn' (default): logs warning, returns raw wireResult\n * - 'throw': throws ZodvexDecodeError (extends z.ZodError) // zod-ok\n *\n * Passthrough when:\n * - function is not in the registry\n * - registry entry has no returns schema\n */\n function decodeResult(ref: FunctionReference<any, any, any, any>, wireResult: any): any {\n const path = resolveFunctionPath(ref)\n const entry = registry[path]\n if (!entry?.returns) return wireResult\n\n const result = safeParse(entry.returns, wireResult)\n if (result.success) return result.data\n\n if (onDecodeError === 'throw') {\n throw new ZodvexDecodeError(path, result.error.issues, wireResult)\n }\n\n // Default: warn and return raw wire data\n const preview = JSON.stringify(wireResult)\n const truncated = preview.length > 200 ? `${preview.slice(0, 200)}...` : preview\n console.warn(\n `[zodvex] Decode failed for ${path}: ${result.error.issues.map((i: $ZodIssue) => `${i.path.join('.')}: ${i.message}`).join(', ')}. Returning raw wire data. Preview: ${truncated}`\n )\n return wireResult\n }\n\n return { encodeArgs, decodeResult }\n}\n\nexport type BoundaryHelpers = ReturnType<typeof createBoundaryHelpers>\n","import type { OptionalRestArgsOrSkip } from 'convex/react'\nimport { useMutation, useQuery } from 'convex/react'\nimport type { FunctionArgs, FunctionReference, FunctionReturnType } from 'convex/server'\nimport { getFunctionName } from 'convex/server'\nimport type { BoundaryHelpersOptions } from '../../internal/boundaryHelpers'\nimport { createBoundaryHelpers } from '../../internal/boundaryHelpers'\nimport type { AnyRegistry } from '../../internal/types'\n\n/**\n * Creates zodvex-aware React hooks that automatically decode query results\n * and encode mutation arguments using the Zod schemas in the registry.\n *\n * Returned hooks are drop-in replacements for Convex's `useQuery` and\n * `useMutation` — they delegate to the real hooks, then apply codec\n * transforms so that runtime types (e.g. Date) are used instead of wire\n * types (e.g. number timestamps).\n *\n * @param registry - A map of function paths to `{ args?, returns? }` Zod schemas.\n * Typically generated by zodvex codegen into `_zodvex/client.ts`.\n *\n * @example\n * ```typescript\n * import { zodvexRegistry } from '../_zodvex/client'\n * export const { useZodQuery, useZodMutation } = createZodvexHooks(zodvexRegistry)\n *\n * // In a component:\n * const tasks = useZodQuery(api.tasks.list, { status: 'active' })\n * // ^? Task[] — createdAt is Date, not number\n * ```\n */\nexport function createZodvexHooks<R extends AnyRegistry>(\n registry: R,\n options?: BoundaryHelpersOptions\n) {\n const codec = createBoundaryHelpers(registry, options)\n\n /**\n * Drop-in replacement for Convex's `useQuery` with automatic codec decode.\n *\n * Delegates to the real `useQuery` and then decodes the wire result through\n * the `returns` schema in the registry (if one exists for this function).\n *\n * Two overloads:\n * 1. Rest-args (Convex-compatible): `useZodQuery(ref, args)` or `useZodQuery(ref, 'skip')`\n * 2. Union args (composable): `useZodQuery(ref, args | 'skip')` — for wrappers\n * and conditional skip patterns where the decision is made upstream.\n *\n * - Loading state (`undefined`) passes through unchanged.\n * - Functions not in the registry return the raw wire result.\n */\n // Overload 1: drop-in compatible with Convex's useQuery\n function useZodQuery<Query extends FunctionReference<'query', any, any, any>>(\n ref: Query,\n ...args: OptionalRestArgsOrSkip<Query>\n ): FunctionReturnType<Query> | undefined\n // Overload 2: composable — accepts Args | 'skip' union for wrappers\n function useZodQuery<Query extends FunctionReference<'query', any, any, any>>(\n ref: Query,\n args: Query['_args'] | 'skip'\n ): FunctionReturnType<Query> | undefined\n // Implementation\n function useZodQuery(ref: FunctionReference<'query', any, any, any>, ...restArgs: any[]) {\n const args = restArgs[0]\n\n // Encode args: runtime types -> wire format (e.g., Date -> timestamp).\n // Unlike mutations (imperative, user-triggered), hooks fire synchronously\n // during render — an encode error would crash the page. On failure, warn\n // and auto-skip the query (return undefined = loading state).\n let wireArgs: any = 'skip'\n if (args !== 'skip') {\n try {\n wireArgs = codec.encodeArgs(ref, args)\n } catch (err) {\n const path = getFunctionName(ref)\n console.debug(\n `[zodvex] Encode args failed for ${path}, auto-skipping query: ${err instanceof Error ? err.message : String(err)}`\n )\n // wireArgs stays 'skip' — DO NOT early-return, useQuery must run every render\n }\n }\n\n const wireResult = useQuery(\n ref,\n ...((wireArgs === 'skip' ? ['skip'] : [wireArgs]) as OptionalRestArgsOrSkip<typeof ref>)\n )\n\n // Loading state — Convex returns undefined while the subscription is pending\n if (wireResult === undefined) return undefined\n\n // Decode: wire format -> runtime types (e.g., timestamp number -> Date)\n return codec.decodeResult(ref, wireResult)\n }\n\n /**\n * Drop-in replacement for Convex's `useMutation`.\n *\n * Returns an async function that:\n * 1. Encodes the args through the `args` schema (runtime -> wire format)\n * 2. Calls the real mutation with the wire args\n * 3. Decodes the result through the `returns` schema (wire -> runtime format)\n *\n * Functions not in the registry pass args and results through unchanged.\n */\n function useZodMutation<Mutation extends FunctionReference<'mutation', any, any, any>>(\n ref: Mutation\n ) {\n const rawMutate = useMutation(ref)\n\n return async (args: FunctionArgs<Mutation>): Promise<FunctionReturnType<Mutation>> => {\n // Encode args: runtime types -> wire format (e.g., Date -> timestamp)\n const wireArgs = codec.encodeArgs(ref, args)\n\n const wireResult = await (rawMutate as any)(wireArgs)\n\n // Decode result: wire format -> runtime types\n return codec.decodeResult(ref, wireResult)\n }\n }\n\n return { useZodQuery, useZodMutation }\n}\n\n/**\n * The return type of `createZodvexHooks` — useful for typing module-level\n * exports in generated client files.\n */\nexport type ZodvexHooks = ReturnType<typeof createZodvexHooks>\n","import type { AuthTokenFetcher, ConnectionState } from 'convex/browser'\nimport type { Watch, WatchQueryOptions } from 'convex/react'\nimport { ConvexReactClient } from 'convex/react'\nimport type { FunctionArgs, FunctionReference, FunctionReturnType } from 'convex/server'\nimport type { BoundaryHelpersOptions } from '../../internal/boundaryHelpers'\nimport { createBoundaryHelpers } from '../../internal/boundaryHelpers'\nimport type { AnyRegistry } from '../../internal/types'\n\nexport type ZodvexReactClientOptions = ({ url: string } | { client: ConvexReactClient }) &\n BoundaryHelpersOptions\n\nexport class ZodvexReactClient<R extends AnyRegistry = AnyRegistry> {\n private codec: ReturnType<typeof createBoundaryHelpers>\n private innerClient?: ConvexReactClient\n private options: ZodvexReactClientOptions\n private pendingAuth?: {\n fetchToken: AuthTokenFetcher\n onChange?: (isAuthenticated: boolean) => void\n }\n\n constructor(registry: R, options: ZodvexReactClientOptions) {\n this.codec = createBoundaryHelpers(registry, { onDecodeError: options.onDecodeError })\n this.options = options\n if ('client' in options) {\n this.innerClient = options.client\n }\n }\n\n private getUrl(): string {\n if ('url' in this.options) return this.options.url\n if (this.innerClient) return this.innerClient.url\n throw new Error('[zodvex] ZodvexReactClient is missing a Convex URL.')\n }\n\n private getConvex(): ConvexReactClient {\n if (this.innerClient) return this.innerClient\n\n const client = new ConvexReactClient(this.getUrl())\n if (this.pendingAuth) {\n client.setAuth(this.pendingAuth.fetchToken, this.pendingAuth.onChange)\n }\n this.innerClient = client\n return client\n }\n\n get convex(): ConvexReactClient {\n return this.getConvex()\n }\n\n // ---------------------------------------------------------------------------\n // Data methods — codec-wrapped\n // ---------------------------------------------------------------------------\n\n async query<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args']\n ): Promise<Q['_returnType']> {\n const wireResult = await this.getConvex().query(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n async mutation<M extends FunctionReference<'mutation', any, any, any>>(\n ref: M,\n args: M['_args']\n ): Promise<M['_returnType']> {\n const wireResult = await this.getConvex().mutation(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<M>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n async action<A extends FunctionReference<'action', any, any, any>>(\n ref: A,\n args: A['_args']\n ): Promise<A['_returnType']> {\n const wireResult = await this.getConvex().action(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<A>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n watchQuery<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args'],\n options?: WatchQueryOptions\n ): Watch<Q['_returnType']> {\n const wireArgs = this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n const innerWatch = this.getConvex().watchQuery(ref, wireArgs, options as any)\n\n // Memoize by wire reference identity to avoid redundant Zod parse.\n // Convex creates a new object per server transition via jsonToConvex()\n // in remote_query_set.ts, but returns the same reference for repeated\n // reads within a single transition window.\n // See: convex/src/browser/sync/optimistic_updates_impl.ts\n // TODO(CX-733) — Convex internal tracker for client-side result\n // memoization (not yet public).\n let lastWire: unknown\n let lastDecoded: unknown\n\n return {\n onUpdate: (cb: () => void) => innerWatch.onUpdate(cb),\n localQueryResult: () => {\n const wire = innerWatch.localQueryResult()\n if (wire === lastWire) return lastDecoded\n lastWire = wire\n lastDecoded = wire === undefined ? undefined : this.codec.decodeResult(ref, wire)\n return lastDecoded\n },\n journal: () => innerWatch.journal()\n }\n }\n\n // ---------------------------------------------------------------------------\n // Pass-through methods — no codec needed\n // ---------------------------------------------------------------------------\n\n setAuth(fetchToken: AuthTokenFetcher, onChange?: (isAuthenticated: boolean) => void): void {\n this.pendingAuth = { fetchToken, onChange }\n if (this.innerClient) {\n this.innerClient.setAuth(fetchToken, onChange)\n }\n }\n\n clearAuth(): void {\n this.pendingAuth = undefined\n this.innerClient?.clearAuth()\n }\n\n async close(): Promise<void> {\n await this.getConvex().close()\n }\n\n get url(): string {\n return this.getUrl()\n }\n\n connectionState() {\n return this.getConvex().connectionState()\n }\n\n subscribeToConnectionState(cb: (state: ConnectionState) => void): () => void {\n return this.getConvex().subscribeToConnectionState(cb)\n }\n}\n\nexport function createZodvexReactClient<R extends AnyRegistry>(\n registry: R,\n options: ZodvexReactClientOptions\n): ZodvexReactClient<R> {\n return new ZodvexReactClient(registry, options)\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/internal/normalizeCodecPaths.ts","../../../src/internal/stripUndefined.ts","../../../src/internal/boundaryHelpers.ts","../../../src/public/react/hooks.ts","../../../src/public/react/zodvexReactClient.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import {\n $ZodArray,\n $ZodCodec,\n $ZodDefault,\n $ZodError,\n $ZodNullable,\n $ZodObject,\n $ZodOptional,\n $ZodType,\n encode\n} from './zod-core'\n\n/**\n * Unwraps ZodOptional/ZodNullable/ZodDefault wrappers to get the structural type.\n */\nfunction unwrapOuter(schema: $ZodType): $ZodType {\n let current: $ZodType = schema\n for (let i = 0; i < 10; i++) {\n if (\n current instanceof $ZodOptional ||\n current instanceof $ZodNullable ||\n current instanceof $ZodDefault\n ) {\n current = current._zod.def.innerType\n continue\n }\n break\n }\n return current\n}\n\n/**\n * Walks a path through a schema tree, truncating at codec boundaries.\n * When a codec is encountered, the path is cut — any deeper segments\n * are wire-internal and should not be exposed to consumers.\n */\nfunction truncateAtCodecBoundary(path: (string | number)[], schema: $ZodType): (string | number)[] {\n const result: (string | number)[] = []\n let current: $ZodType = schema\n\n for (const segment of path) {\n current = unwrapOuter(current)\n\n // If we've landed on a codec, everything from here is wire-internal — stop\n if (current instanceof $ZodCodec) {\n break\n }\n\n // Descend into objects\n if (current instanceof $ZodObject && typeof segment === 'string') {\n const fieldSchema = current._zod.def.shape[segment] as $ZodType | undefined\n if (!fieldSchema) {\n // Unknown field — include segment and stop\n result.push(segment)\n break\n }\n\n result.push(segment)\n\n const unwrapped = unwrapOuter(fieldSchema)\n if (unwrapped instanceof $ZodCodec) {\n // Hit a codec boundary — truncate here\n break\n }\n\n current = fieldSchema\n continue\n }\n\n // Descend into arrays\n if (current instanceof $ZodArray && typeof segment === 'number') {\n result.push(segment)\n current = current._zod.def.element\n continue\n }\n\n // For anything else (unions, records, etc.), include segment and continue\n result.push(segment)\n }\n\n return result\n}\n\n/**\n * Normalizes ZodError paths by truncating at codec boundaries.\n *\n * When z.encode() throws a ZodError, the paths reflect the wire schema\n * structure (e.g., [\"email\", \"value\"] for a custom codec).\n * This function strips the wire-internal segments so consumers see\n * clean field-level paths (e.g., [\"email\"]).\n */\nexport function normalizeCodecPaths(error: $ZodError, schema: $ZodType): $ZodError {\n const normalized = error.issues.map(issue => ({\n ...issue,\n path: truncateAtCodecBoundary(issue.path as (string | number)[], schema)\n }))\n return new $ZodError(normalized)\n}\n\n/**\n * Encodes a value through a Zod schema, normalizing codec-internal\n * path segments in any ZodError before re-throwing.\n *\n * Drop-in replacement for `z.encode(schema, value)` at client boundaries.\n */\nexport function safeEncode(schema: $ZodType, value: unknown): unknown {\n try {\n return encode(schema, value)\n } catch (e) {\n if (e instanceof $ZodError) throw normalizeCodecPaths(e as $ZodError, schema)\n throw e\n }\n}\n","/**\n * Recursively strips `undefined` values from objects and arrays.\n * Used by codec encode/decode to clean wire data.\n *\n * Extracted to its own module so client-safe code (boundaryHelpers)\n * can import it without pulling in zod via utils.ts.\n */\nexport function stripUndefined<T>(value: T): T {\n if (value === null || value === undefined) {\n return value\n }\n\n if (Array.isArray(value)) {\n return value.map(stripUndefined) as T\n }\n\n // Only process plain objects (not class instances, Dates, etc.)\n if (typeof value === 'object' && value.constructor === Object) {\n const result: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(value)) {\n if (val !== undefined) {\n result[key] = stripUndefined(val)\n }\n }\n return result as T\n }\n\n return value\n}\n","import type { FunctionReference } from 'convex/server'\nimport type { $ZodIssue } from 'zod/v4/core'\nimport { safeEncode } from './normalizeCodecPaths'\nimport { stripUndefined } from './stripUndefined'\nimport type { AnyRegistry } from './types'\nimport { $ZodError, safeParse } from './zod-core'\n\n/**\n * Resolves a Convex FunctionReference to its string path.\n *\n * Mirrors `getFunctionName` from `convex/server` but without the server import.\n * Reads the well-known `Symbol.for('functionName')` that Convex attaches to all\n * function references — the same symbol used by Convex's own browser client.\n */\nconst functionNameSymbol = Symbol.for('functionName')\n\nfunction resolveFunctionPath(ref: FunctionReference<any, any, any, any>): string {\n if (typeof ref === 'string') return ref\n const name = (ref as any)[functionNameSymbol]\n if (!name) {\n throw new Error(\n `Expected a Convex function reference (e.g. api.file.func), but received ${JSON.stringify(ref)}`\n )\n }\n return name\n}\n\n/**\n * Options for codec helper behavior.\n */\nexport type BoundaryHelpersOptions = {\n /**\n * How to handle decode failures (schema validation errors on wire data).\n *\n * - `'warn'` (default): log a console.warn and return raw wire data untransformed.\n * - `'throw'`: throw a ZodvexDecodeError (extends z.ZodError). // zod-ok\n */\n onDecodeError?: 'warn' | 'throw'\n}\n\n/**\n * Decode error with function path and wire data context.\n * Extends $ZodError from zod/v4/core for compatibility with both zod and zod/mini.\n * instanceof $ZodError checks work in both variants.\n */\nexport class ZodvexDecodeError extends $ZodError {\n readonly functionPath: string\n readonly wireData: unknown\n\n constructor(functionPath: string, issues: $ZodIssue[], wireData: unknown) {\n super(issues)\n this.functionPath = functionPath\n this.wireData = wireData\n this.name = 'ZodvexDecodeError'\n }\n}\n\n/**\n * Creates shared encode/decode helpers bound to a zodvex registry.\n *\n * These are the core primitives used by all codec boundary implementations:\n * - `encodeArgs`: runtime types -> wire format (e.g., Date -> timestamp number)\n * - `decodeResult`: wire format -> runtime types (e.g., timestamp number -> Date)\n *\n * Both look up the function reference in the registry to find the appropriate\n * Zod schema, then apply the codec transform. Functions not in the registry\n * (or without the relevant schema) pass through unchanged.\n *\n * @param registry - A map of function paths to `{ args?, returns? }` Zod schemas.\n * Typically generated by zodvex codegen into `_zodvex/api.ts`.\n * @param options - Optional configuration for decode error behavior.\n */\nexport function createBoundaryHelpers(registry: AnyRegistry, options?: BoundaryHelpersOptions) {\n const onDecodeError = options?.onDecodeError ?? 'warn'\n const warnedPaths = new Set<string>()\n\n /**\n * Encode args from runtime types to wire format.\n *\n * Uses `safeEncode` (not raw `z.encode`) to normalize codec-internal\n * error paths in ZodErrors, then strips undefined values for Convex\n * serialization compatibility.\n *\n * Passthrough when:\n * - args is null/undefined\n * - function is not in the registry\n * - registry entry has no args schema\n */\n function encodeArgs(ref: FunctionReference<any, any, any, any>, args: any): any {\n if (args == null) return args\n const path = resolveFunctionPath(ref)\n const entry = registry[path]\n if (!entry?.args) {\n if (entry === undefined && !warnedPaths.has(path)) {\n warnedPaths.add(path)\n console.debug(\n `[zodvex] No registry entry for \"${path}\" — args will not be codec-encoded. ` +\n 'If this function uses zodvex wrappers, run `zodvex generate` to update the registry.'\n )\n }\n return args\n }\n return stripUndefined(safeEncode(entry.args, args))\n }\n\n /**\n * Decode a wire result back to runtime types.\n *\n * Uses `.safeParse()` to decode. On failure:\n * - 'warn' (default): logs warning, returns raw wireResult\n * - 'throw': throws ZodvexDecodeError (extends z.ZodError) // zod-ok\n *\n * Passthrough when:\n * - function is not in the registry\n * - registry entry has no returns schema\n */\n function decodeResult(ref: FunctionReference<any, any, any, any>, wireResult: any): any {\n const path = resolveFunctionPath(ref)\n const entry = registry[path]\n if (!entry?.returns) return wireResult\n\n const result = safeParse(entry.returns, wireResult)\n if (result.success) return result.data\n\n if (onDecodeError === 'throw') {\n throw new ZodvexDecodeError(path, result.error.issues, wireResult)\n }\n\n // Default: warn and return raw wire data\n const preview = JSON.stringify(wireResult)\n const truncated = preview.length > 200 ? `${preview.slice(0, 200)}...` : preview\n console.warn(\n `[zodvex] Decode failed for ${path}: ${result.error.issues.map((i: $ZodIssue) => `${i.path.join('.')}: ${i.message}`).join(', ')}. Returning raw wire data. Preview: ${truncated}`\n )\n return wireResult\n }\n\n return { encodeArgs, decodeResult }\n}\n\nexport type BoundaryHelpers = ReturnType<typeof createBoundaryHelpers>\n","import type { OptionalRestArgsOrSkip } from 'convex/react'\nimport { useMutation, useQuery } from 'convex/react'\nimport type { FunctionArgs, FunctionReference, FunctionReturnType } from 'convex/server'\nimport { getFunctionName } from 'convex/server'\nimport type { BoundaryHelpersOptions } from '../../internal/boundaryHelpers'\nimport { createBoundaryHelpers } from '../../internal/boundaryHelpers'\nimport type { AnyRegistry } from '../../internal/types'\n\n/**\n * Creates zodvex-aware React hooks that automatically decode query results\n * and encode mutation arguments using the Zod schemas in the registry.\n *\n * Returned hooks are drop-in replacements for Convex's `useQuery` and\n * `useMutation` — they delegate to the real hooks, then apply codec\n * transforms so that runtime types (e.g. Date) are used instead of wire\n * types (e.g. number timestamps).\n *\n * @param registry - A map of function paths to `{ args?, returns? }` Zod schemas.\n * Typically generated by zodvex codegen into `_zodvex/client.ts`.\n *\n * @example\n * ```typescript\n * import { zodvexRegistry } from '../_zodvex/client'\n * export const { useZodQuery, useZodMutation } = createZodvexHooks(zodvexRegistry)\n *\n * // In a component:\n * const tasks = useZodQuery(api.tasks.list, { status: 'active' })\n * // ^? Task[] — createdAt is Date, not number\n * ```\n */\nexport function createZodvexHooks<R extends AnyRegistry>(\n registry: R,\n options?: BoundaryHelpersOptions\n) {\n const codec = createBoundaryHelpers(registry, options)\n\n /**\n * Drop-in replacement for Convex's `useQuery` with automatic codec decode.\n *\n * Delegates to the real `useQuery` and then decodes the wire result through\n * the `returns` schema in the registry (if one exists for this function).\n *\n * Two overloads:\n * 1. Rest-args (Convex-compatible): `useZodQuery(ref, args)` or `useZodQuery(ref, 'skip')`\n * 2. Union args (composable): `useZodQuery(ref, args | 'skip')` — for wrappers\n * and conditional skip patterns where the decision is made upstream.\n *\n * - Loading state (`undefined`) passes through unchanged.\n * - Functions not in the registry return the raw wire result.\n */\n // Overload 1: drop-in compatible with Convex's useQuery\n function useZodQuery<Query extends FunctionReference<'query', any, any, any>>(\n ref: Query,\n ...args: OptionalRestArgsOrSkip<Query>\n ): FunctionReturnType<Query> | undefined\n // Overload 2: composable — accepts Args | 'skip' union for wrappers\n function useZodQuery<Query extends FunctionReference<'query', any, any, any>>(\n ref: Query,\n args: Query['_args'] | 'skip'\n ): FunctionReturnType<Query> | undefined\n // Implementation\n function useZodQuery(ref: FunctionReference<'query', any, any, any>, ...restArgs: any[]) {\n const args = restArgs[0]\n\n // Encode args: runtime types -> wire format (e.g., Date -> timestamp).\n // Unlike mutations (imperative, user-triggered), hooks fire synchronously\n // during render — an encode error would crash the page. On failure, warn\n // and auto-skip the query (return undefined = loading state).\n let wireArgs: any = 'skip'\n if (args !== 'skip') {\n try {\n wireArgs = codec.encodeArgs(ref, args)\n } catch (err) {\n const path = getFunctionName(ref)\n console.debug(\n `[zodvex] Encode args failed for ${path}, auto-skipping query: ${err instanceof Error ? err.message : String(err)}`\n )\n // wireArgs stays 'skip' — DO NOT early-return, useQuery must run every render\n }\n }\n\n const wireResult = useQuery(\n ref,\n ...((wireArgs === 'skip' ? ['skip'] : [wireArgs]) as OptionalRestArgsOrSkip<typeof ref>)\n )\n\n // Loading state — Convex returns undefined while the subscription is pending\n if (wireResult === undefined) return undefined\n\n // Decode: wire format -> runtime types (e.g., timestamp number -> Date)\n return codec.decodeResult(ref, wireResult)\n }\n\n /**\n * Drop-in replacement for Convex's `useMutation`.\n *\n * Returns an async function that:\n * 1. Encodes the args through the `args` schema (runtime -> wire format)\n * 2. Calls the real mutation with the wire args\n * 3. Decodes the result through the `returns` schema (wire -> runtime format)\n *\n * Functions not in the registry pass args and results through unchanged.\n */\n function useZodMutation<Mutation extends FunctionReference<'mutation', any, any, any>>(\n ref: Mutation\n ) {\n const rawMutate = useMutation(ref)\n\n return async (args: FunctionArgs<Mutation>): Promise<FunctionReturnType<Mutation>> => {\n // Encode args: runtime types -> wire format (e.g., Date -> timestamp)\n const wireArgs = codec.encodeArgs(ref, args)\n\n const wireResult = await (rawMutate as any)(wireArgs)\n\n // Decode result: wire format -> runtime types\n return codec.decodeResult(ref, wireResult)\n }\n }\n\n return { useZodQuery, useZodMutation }\n}\n\n/**\n * The return type of `createZodvexHooks` — useful for typing module-level\n * exports in generated client files.\n */\nexport type ZodvexHooks = ReturnType<typeof createZodvexHooks>\n","import type { AuthTokenFetcher, ConnectionState } from 'convex/browser'\nimport type { Watch, WatchQueryOptions } from 'convex/react'\nimport { ConvexReactClient } from 'convex/react'\nimport type { FunctionArgs, FunctionReference, FunctionReturnType } from 'convex/server'\nimport type { BoundaryHelpersOptions } from '../../internal/boundaryHelpers'\nimport { createBoundaryHelpers } from '../../internal/boundaryHelpers'\nimport type { AnyRegistry } from '../../internal/types'\n\nexport type ZodvexReactClientOptions = ({ url: string } | { client: ConvexReactClient }) &\n BoundaryHelpersOptions\n\nexport class ZodvexReactClient<R extends AnyRegistry = AnyRegistry> {\n private codec: ReturnType<typeof createBoundaryHelpers>\n private innerClient?: ConvexReactClient\n private options: ZodvexReactClientOptions\n private pendingAuth?: {\n fetchToken: AuthTokenFetcher\n onChange?: (isAuthenticated: boolean) => void\n }\n\n constructor(registry: R, options: ZodvexReactClientOptions) {\n this.codec = createBoundaryHelpers(registry, { onDecodeError: options.onDecodeError })\n this.options = options\n if ('client' in options) {\n this.innerClient = options.client\n }\n }\n\n private getUrl(): string {\n if ('url' in this.options) return this.options.url\n if (this.innerClient) return this.innerClient.url\n throw new Error('[zodvex] ZodvexReactClient is missing a Convex URL.')\n }\n\n private getConvex(): ConvexReactClient {\n if (this.innerClient) return this.innerClient\n\n const client = new ConvexReactClient(this.getUrl())\n if (this.pendingAuth) {\n client.setAuth(this.pendingAuth.fetchToken, this.pendingAuth.onChange)\n }\n this.innerClient = client\n return client\n }\n\n get convex(): ConvexReactClient {\n return this.getConvex()\n }\n\n // ---------------------------------------------------------------------------\n // Data methods — codec-wrapped\n // ---------------------------------------------------------------------------\n\n async query<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args']\n ): Promise<Q['_returnType']> {\n const wireResult = await this.getConvex().query(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n async mutation<M extends FunctionReference<'mutation', any, any, any>>(\n ref: M,\n args: M['_args']\n ): Promise<M['_returnType']> {\n const wireResult = await this.getConvex().mutation(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<M>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n async action<A extends FunctionReference<'action', any, any, any>>(\n ref: A,\n args: A['_args']\n ): Promise<A['_returnType']> {\n const wireResult = await this.getConvex().action(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<A>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n /**\n * Indicates likely future interest in a query subscription. Encodes args to\n * wire before delegating, mirroring {@link watchQuery}.\n */\n prewarmQuery<Q extends FunctionReference<'query', any, any, any>>(queryOptions: {\n query: Q\n args: Q['_args']\n extendSubscriptionFor?: number\n }): void {\n const wireArgs = this.codec.encodeArgs(queryOptions.query, queryOptions.args) as FunctionArgs<Q>\n this.getConvex().prewarmQuery({ ...queryOptions, args: wireArgs })\n }\n\n watchQuery<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args'],\n options?: WatchQueryOptions\n ): Watch<Q['_returnType']> {\n const wireArgs = this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n const innerWatch = this.getConvex().watchQuery(ref, wireArgs, options as any)\n\n // Memoize by wire reference identity to avoid redundant Zod parse.\n // Convex creates a new object per server transition via jsonToConvex()\n // in remote_query_set.ts, but returns the same reference for repeated\n // reads within a single transition window.\n // See: convex/src/browser/sync/optimistic_updates_impl.ts\n // TODO(CX-733) — Convex internal tracker for client-side result\n // memoization (not yet public).\n let lastWire: unknown\n let lastDecoded: unknown\n\n return {\n onUpdate: (cb: () => void) => innerWatch.onUpdate(cb),\n localQueryResult: () => {\n const wire = innerWatch.localQueryResult()\n if (wire === lastWire) return lastDecoded\n lastWire = wire\n lastDecoded = wire === undefined ? undefined : this.codec.decodeResult(ref, wire)\n return lastDecoded\n },\n journal: () => innerWatch.journal()\n }\n }\n\n // ---------------------------------------------------------------------------\n // Pass-through methods — no codec needed\n // ---------------------------------------------------------------------------\n\n setAuth(fetchToken: AuthTokenFetcher, onChange?: (isAuthenticated: boolean) => void): void {\n this.pendingAuth = { fetchToken, onChange }\n if (this.innerClient) {\n this.innerClient.setAuth(fetchToken, onChange)\n }\n }\n\n clearAuth(): void {\n this.pendingAuth = undefined\n this.innerClient?.clearAuth()\n }\n\n async close(): Promise<void> {\n await this.getConvex().close()\n }\n\n get url(): string {\n return this.getUrl()\n }\n\n get logger(): ConvexReactClient['logger'] {\n return this.getConvex().logger\n }\n\n connectionState() {\n return this.getConvex().connectionState()\n }\n\n subscribeToConnectionState(cb: (state: ConnectionState) => void): () => void {\n return this.getConvex().subscribeToConnectionState(cb)\n }\n}\n\nexport function createZodvexReactClient<R extends AnyRegistry>(\n registry: R,\n options: ZodvexReactClientOptions\n): ZodvexReactClient<R> {\n return new ZodvexReactClient(registry, options)\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NoOp } from 'convex-helpers/server/customFunctions';
|
|
2
2
|
export { customCtx } from 'convex-helpers/server/customFunctions';
|
|
3
|
-
import { $ZodObject, clone, $ZodType, parse, encode, $ZodOptional, $ZodUnion, $ZodDiscriminatedUnion, $ZodNullable,
|
|
3
|
+
import { $ZodObject, clone, $ZodType, parse, encode, $ZodOptional, $ZodUnion, $ZodDiscriminatedUnion, $ZodNullable, $ZodDefault, $ZodLazy, $ZodTuple, $ZodCodec, $ZodRecord, $ZodEnum, $ZodLiteral, $ZodArray, safeParse, $ZodError, $ZodCustom, $ZodDate } from 'zod/v4/core';
|
|
4
4
|
import { z } from 'zod/mini';
|
|
5
5
|
import { v, ConvexError } from 'convex/values';
|
|
6
6
|
import { defineSchema, defineTable } from 'convex/server';
|
|
@@ -147,22 +147,42 @@ function createBoundaryHelpers(registry, options) {
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
// src/internal/actionCtx.ts
|
|
150
|
-
function
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const wireArgs = codec2.encodeArgs(ref, restArgs[0]);
|
|
156
|
-
const wireResult = await ctx.runQuery(ref, wireArgs);
|
|
157
|
-
return codec2.decodeResult(ref, wireResult);
|
|
158
|
-
},
|
|
159
|
-
runMutation: async (ref, ...restArgs) => {
|
|
160
|
-
const wireArgs = codec2.encodeArgs(ref, restArgs[0]);
|
|
161
|
-
const wireResult = await ctx.runMutation(ref, wireArgs);
|
|
162
|
-
return codec2.decodeResult(ref, wireResult);
|
|
163
|
-
}
|
|
150
|
+
function wrapRun(fn, codec2) {
|
|
151
|
+
return async (ref, ...restArgs) => {
|
|
152
|
+
const wireArgs = codec2.encodeArgs(ref, restArgs[0]);
|
|
153
|
+
const wireResult = await fn(ref, wireArgs);
|
|
154
|
+
return codec2.decodeResult(ref, wireResult);
|
|
164
155
|
};
|
|
165
156
|
}
|
|
157
|
+
function wrapScheduler(scheduler, codec2) {
|
|
158
|
+
const wrapped = { ...scheduler };
|
|
159
|
+
wrapped.runAfter = (delayMs, ref, ...restArgs) => {
|
|
160
|
+
const wireArgs = codec2.encodeArgs(ref, restArgs[0]);
|
|
161
|
+
return scheduler.runAfter(delayMs, ref, ...restArgs.length ? [wireArgs] : []);
|
|
162
|
+
};
|
|
163
|
+
wrapped.runAt = (timestamp, ref, ...restArgs) => {
|
|
164
|
+
const wireArgs = codec2.encodeArgs(ref, restArgs[0]);
|
|
165
|
+
return scheduler.runAt(timestamp, ref, ...restArgs.length ? [wireArgs] : []);
|
|
166
|
+
};
|
|
167
|
+
return wrapped;
|
|
168
|
+
}
|
|
169
|
+
function createCodecCallOverrides(registry, ctx, options) {
|
|
170
|
+
const codec2 = createBoundaryHelpers(registry, options);
|
|
171
|
+
const overrides = {};
|
|
172
|
+
if (typeof ctx.runQuery === "function") {
|
|
173
|
+
overrides.runQuery = wrapRun(ctx.runQuery, codec2);
|
|
174
|
+
}
|
|
175
|
+
if (typeof ctx.runMutation === "function") {
|
|
176
|
+
overrides.runMutation = wrapRun(ctx.runMutation, codec2);
|
|
177
|
+
}
|
|
178
|
+
if (ctx.scheduler) {
|
|
179
|
+
overrides.scheduler = wrapScheduler(ctx.scheduler, codec2);
|
|
180
|
+
}
|
|
181
|
+
return overrides;
|
|
182
|
+
}
|
|
183
|
+
function createZodvexActionCtx(registry, ctx, options) {
|
|
184
|
+
return { ...ctx, ...createCodecCallOverrides(registry, ctx, options) };
|
|
185
|
+
}
|
|
166
186
|
|
|
167
187
|
// src/internal/schema/objectShape.ts
|
|
168
188
|
function getObjectShape(obj) {
|
|
@@ -1810,10 +1830,11 @@ function initZodvex(schema, server, options) {
|
|
|
1810
1830
|
const codec2 = createZodvexCustomization(schema.__zodTableMap);
|
|
1811
1831
|
const noOp = createNoOpCustomization();
|
|
1812
1832
|
const wrap = options?.wrapDb !== false;
|
|
1813
|
-
const
|
|
1833
|
+
const registryThunk = options?.registry;
|
|
1834
|
+
const actionCust = createActionCustomization(registryThunk, noOp);
|
|
1814
1835
|
const customizations = {
|
|
1815
1836
|
query: wrap ? codec2.query : noOp,
|
|
1816
|
-
mutation: wrap ? codec2.mutation : noOp,
|
|
1837
|
+
mutation: createMutationCustomization(wrap ? codec2.mutation : noOp, registryThunk),
|
|
1817
1838
|
action: actionCust
|
|
1818
1839
|
};
|
|
1819
1840
|
return createInitBuilderBundle(server, customizations);
|
|
@@ -1827,10 +1848,25 @@ function createActionCustomization(registryThunk, noOp) {
|
|
|
1827
1848
|
}
|
|
1828
1849
|
return {
|
|
1829
1850
|
args: {},
|
|
1830
|
-
input: async (ctx) => {
|
|
1831
|
-
|
|
1851
|
+
input: async (ctx) => ({
|
|
1852
|
+
// Auto-encode codec args at outbound call sites: runQuery/runMutation
|
|
1853
|
+
// (encode args, decode result) and scheduler.runAfter/runAt (encode args).
|
|
1854
|
+
ctx: createCodecCallOverrides(registryThunk(), ctx),
|
|
1855
|
+
args: {}
|
|
1856
|
+
})
|
|
1857
|
+
};
|
|
1858
|
+
}
|
|
1859
|
+
function createMutationCustomization(dbCust, registryThunk) {
|
|
1860
|
+
if (!registryThunk) {
|
|
1861
|
+
return dbCust;
|
|
1862
|
+
}
|
|
1863
|
+
return {
|
|
1864
|
+
args: {},
|
|
1865
|
+
input: async (ctx, _args, extra) => {
|
|
1866
|
+
const dbResult = await dbCust.input(ctx, {}, extra);
|
|
1867
|
+
const callOverrides = createCodecCallOverrides(registryThunk(), ctx);
|
|
1832
1868
|
return {
|
|
1833
|
-
ctx: {
|
|
1869
|
+
ctx: { ...dbResult.ctx, ...callOverrides },
|
|
1834
1870
|
args: {}
|
|
1835
1871
|
};
|
|
1836
1872
|
}
|