zodvex 0.7.0 → 0.7.1-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/dist/boundaryHelpers.d.ts +6 -5
- package/dist/boundaryHelpers.d.ts.map +1 -1
- package/dist/client/index.js +4 -4
- package/dist/client/index.js.map +1 -1
- package/dist/core/index.js +28 -20
- package/dist/core/index.js.map +1 -1
- package/dist/index.js +31 -23
- package/dist/index.js.map +1 -1
- package/dist/mini/index.js +28 -20
- package/dist/mini/index.js.map +1 -1
- package/dist/normalizeCodecPaths.d.ts +2 -3
- package/dist/normalizeCodecPaths.d.ts.map +1 -1
- package/dist/react/index.js +4 -4
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.js +14 -11
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
- package/src/boundaryHelpers.ts +8 -7
- package/src/ids.ts +5 -5
- package/src/model.ts +5 -5
- package/src/normalizeCodecPaths.ts +3 -4
- package/src/tables.ts +5 -5
- package/src/utils.ts +4 -4
- package/src/zx.ts +5 -5
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { FunctionReference } from 'convex/server';
|
|
2
|
-
import {
|
|
2
|
+
import type { $ZodIssue } from 'zod/v4/core';
|
|
3
3
|
import type { AnyRegistry } from './types';
|
|
4
|
+
import { $ZodError } from './zod-core';
|
|
4
5
|
/**
|
|
5
6
|
* Options for codec helper behavior.
|
|
6
7
|
*/
|
|
@@ -15,13 +16,13 @@ export type BoundaryHelpersOptions = {
|
|
|
15
16
|
};
|
|
16
17
|
/**
|
|
17
18
|
* Decode error with function path and wire data context.
|
|
18
|
-
* Extends
|
|
19
|
-
*
|
|
19
|
+
* Extends $ZodError from zod/v4/core for compatibility with both zod and zod/mini.
|
|
20
|
+
* instanceof $ZodError checks work in both variants.
|
|
20
21
|
*/
|
|
21
|
-
export declare class ZodvexDecodeError extends
|
|
22
|
+
export declare class ZodvexDecodeError extends $ZodError {
|
|
22
23
|
readonly functionPath: string;
|
|
23
24
|
readonly wireData: unknown;
|
|
24
|
-
constructor(functionPath: string, issues:
|
|
25
|
+
constructor(functionPath: string, issues: $ZodIssue[], wireData: unknown);
|
|
25
26
|
}
|
|
26
27
|
/**
|
|
27
28
|
* Creates shared encode/decode helpers bound to a zodvex registry.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"boundaryHelpers.d.ts","sourceRoot":"","sources":["../src/boundaryHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"boundaryHelpers.d.ts","sourceRoot":"","sources":["../src/boundaryHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAEtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAE5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAE1C,OAAO,EAAE,SAAS,EAAa,MAAM,YAAY,CAAA;AAsBjD;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACjC,CAAA;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;IAC9C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;gBAEd,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,OAAO;CAMzE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,sBAAsB;sBAgBlE,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,QAAQ,GAAG,KAAG,GAAG;wBA4BpD,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,cAAc,GAAG,KAAG,GAAG;EAsBxF;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA"}
|
package/dist/client/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ConvexClient } from 'convex/browser';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
2
|
+
import { safeParse, $ZodError, encode, $ZodCodec, $ZodObject, $ZodArray, $ZodOptional, $ZodNullable, $ZodDefault } from 'zod/v4/core';
|
|
3
|
+
import 'zod';
|
|
4
4
|
|
|
5
5
|
// src/client/zodvexClient.ts
|
|
6
6
|
|
|
@@ -52,7 +52,7 @@ function normalizeCodecPaths(error, schema) {
|
|
|
52
52
|
...issue,
|
|
53
53
|
path: truncateAtCodecBoundary(issue.path, schema)
|
|
54
54
|
}));
|
|
55
|
-
return new ZodError(normalized);
|
|
55
|
+
return new $ZodError(normalized);
|
|
56
56
|
}
|
|
57
57
|
function safeEncode(schema, value) {
|
|
58
58
|
try {
|
|
@@ -93,7 +93,7 @@ function resolveFunctionPath(ref) {
|
|
|
93
93
|
}
|
|
94
94
|
return name;
|
|
95
95
|
}
|
|
96
|
-
var ZodvexDecodeError = class extends
|
|
96
|
+
var ZodvexDecodeError = class extends $ZodError {
|
|
97
97
|
functionPath;
|
|
98
98
|
wireData;
|
|
99
99
|
constructor(functionPath, issues, wireData) {
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/normalizeCodecPaths.ts","../../src/utils.ts","../../src/boundaryHelpers.ts","../../src/client/zodvexClient.ts"],"names":["z"],"mappings":"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","file":"index.js","sourcesContent":["import { ZodError } from 'zod'\nimport {\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","import { z } from 'zod'\nimport {\n $ZodArray,\n $ZodCodec,\n $ZodDate,\n $ZodDefault,\n $ZodNullable,\n $ZodObject,\n $ZodOptional,\n $ZodRecord,\n $ZodTuple,\n $ZodType,\n $ZodUnion,\n type input as zinput\n} from './zod-core'\n\n// Private copy — importing from ./mapping pulls convex/values into client bundles\n// (mapping/utils.ts imports `v` from convex/values which is server-only).\nfunction getObjectShape(obj: any): Record<string, any> {\n if (obj instanceof $ZodObject) return obj._zod.def.shape as Record<string, any>\n if (obj && typeof obj === 'object' && typeof obj.shape === 'object')\n return obj.shape as Record<string, any>\n return {}\n}\n\nexport function pick<T extends Record<string, any>, K extends keyof T>(\n obj: T,\n keys: K[]\n): Pick<T, K> {\n const result = {} as Pick<T, K>\n for (const key of keys) {\n if (key in obj) result[key] = obj[key]\n }\n return result\n}\n\n// Typed identity helper for returns schemas\nexport function returnsAs<R extends $ZodType>() {\n return <T extends zinput<R>>(v: T) => v\n}\n\n/**\n * Recursively strips undefined values from objects for Convex serialization.\n * Convex rejects objects with explicit undefined properties, so we need to\n * remove them before returning from handlers.\n *\n * Only processes plain objects (Object.prototype). Class instances, Dates,\n * and other non-plain objects are passed through unchanged.\n *\n * @param value - The value to strip undefined from\n * @returns The value with undefined properties removed from plain objects\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\n// Helper: standard Convex paginate() result schema\nexport function zPaginated<T extends $ZodType>(item: T) {\n return z.object({\n page: z.array(item),\n isDone: z.boolean(),\n continueCursor: z.string().nullable().optional()\n })\n}\n\n/**\n * Maps Date fields to number fields for docSchema generation.\n * Handles Date, Date.optional(), Date.nullable(), and Date.default() cases.\n * Returns the original field for non-Date types.\n *\n * @deprecated Use `zx.date()` instead for automatic Date ↔ timestamp conversion.\n */\nexport function mapDateFieldToNumber(field: $ZodType): $ZodType {\n // Direct Date field\n if (field instanceof $ZodDate) {\n return z.number()\n }\n\n // Optional Date field\n if (field instanceof $ZodOptional && field._zod.def.innerType instanceof $ZodDate) {\n return z.number().optional()\n }\n\n // Nullable Date field\n if (field instanceof $ZodNullable && field._zod.def.innerType instanceof $ZodDate) {\n return z.number().nullable()\n }\n\n // Date with default value\n if (field instanceof $ZodDefault) {\n const inner = field._zod.def.innerType\n if (inner instanceof $ZodDate) {\n return z.number().optional()\n }\n }\n\n // Non-Date field - return as-is\n return field\n}\n\n// Schema picking utilities (moved from pick.ts for consolidation)\ntype Mask = readonly string[] | Record<string, boolean | 1 | true>\n\nfunction toKeys(mask: Mask): string[] {\n if (Array.isArray(mask)) return mask.map(String)\n return Object.keys(mask).filter(k => !!(mask as any)[k])\n}\n\n/**\n * Returns a plain shape object containing only the selected fields.\n * Accepts either a ZodObject or a raw shape object.\n */\nexport function pickShape(\n schemaOrShape: z.ZodObject<any> | Record<string, any>,\n mask: Mask\n): Record<string, any> {\n const keys = toKeys(mask)\n const shape =\n schemaOrShape instanceof $ZodObject ? getObjectShape(schemaOrShape) : schemaOrShape || {}\n\n const out: Record<string, any> = {}\n for (const k of keys) {\n if (k in shape) out[k] = (shape as any)[k]\n }\n return out\n}\n\n// Builds a fresh Zod object from the selected fields (avoids Zod's .pick())\nexport function safePick(schema: z.ZodObject<any>, mask: Mask): z.ZodObject<any> {\n return z.object(pickShape(schema, mask))\n}\n\n/**\n * Convenience: omit a set of keys by building the complement.\n * Avoids using Zod's .omit() which can cause type depth issues.\n */\nexport function safeOmit(schema: z.ZodObject<any>, mask: Mask): z.ZodObject<any> {\n const shape = getObjectShape(schema)\n const omit = new Set(toKeys(mask))\n const keep = Object.keys(shape).filter(k => !omit.has(k))\n const picked = pickShape(schema, keep)\n return z.object(picked)\n}\n\n/**\n * Recursively checks if a schema contains native z.date().\n * Stops recursion at ZodCodec boundaries since codecs handle their own transforms.\n */\nfunction containsNativeZodDate(schema: $ZodType): boolean {\n // Check if this is a native ZodDate (not our codec)\n if (schema instanceof $ZodDate) {\n return true\n }\n\n // Codecs handle their own transforms - don't recurse into them\n if (schema instanceof $ZodCodec) {\n return false\n }\n\n // Recurse into wrappers - cast unwrap result to ZodTypeAny for Zod v4 compatibility\n if (\n schema instanceof $ZodOptional ||\n schema instanceof $ZodNullable ||\n schema instanceof $ZodDefault\n ) {\n return containsNativeZodDate(schema._zod.def.innerType)\n }\n\n // Recurse into objects\n if (schema instanceof $ZodObject) {\n return Object.values(schema._zod.def.shape).some(field => containsNativeZodDate(field))\n }\n\n // Recurse into arrays\n if (schema instanceof $ZodArray) {\n return containsNativeZodDate(schema._zod.def.element)\n }\n\n // Recurse into unions\n if (schema instanceof $ZodUnion) {\n return schema._zod.def.options.some(opt => containsNativeZodDate(opt))\n }\n\n // Recurse into records\n if (schema instanceof $ZodRecord) {\n return containsNativeZodDate(schema._zod.def.valueType)\n }\n\n // Recurse into tuples\n if (schema instanceof $ZodTuple) {\n const items = schema._zod.def.items\n return items ? items.some(item => containsNativeZodDate(item)) : false\n }\n\n return false\n}\n\n/**\n * Throws if schema contains native z.date() which isn't compatible with Convex.\n * Guides users to use zx.date() instead.\n *\n * @param schema - The Zod schema to check\n * @param context - Context for the error message (args, returns, schema)\n * @throws Error with migration guidance if z.date() is found\n */\nexport function assertNoNativeZodDate(\n schema: $ZodType,\n context: 'args' | 'returns' | 'schema'\n): void {\n if (containsNativeZodDate(schema)) {\n throw new Error(\n `[zodvex] Native z.date() found in ${context}. ` +\n `Convex stores dates as timestamps (numbers), which z.date() cannot parse.\\n\\n` +\n `Fix: Replace z.date() with zx.date()\\n\\n` +\n `Before: { createdAt: z.date() }\\n` +\n `After: { createdAt: zx.date() }\\n\\n` +\n `zx.date() is a codec that handles timestamp ↔ Date conversion automatically.`\n )\n }\n}\n","import type { FunctionReference } from 'convex/server'\nimport { z } from 'zod'\nimport { safeEncode } from './normalizeCodecPaths'\nimport type { AnyRegistry } from './types'\nimport { stripUndefined } from './utils'\nimport { 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).\n */\n onDecodeError?: 'warn' | 'throw'\n}\n\n/**\n * Decode error with function path and wire data context.\n * Extends z.ZodError for compatibility with existing Zod tooling\n * (instanceof ZodError checks, Sentry, error boundaries, etc.).\n */\nexport class ZodvexDecodeError extends z.ZodError {\n readonly functionPath: string\n readonly wireData: unknown\n\n constructor(functionPath: string, issues: z.core.$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)\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: z.core.$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 { AuthTokenFetcher } from 'convex/browser'\nimport { ConvexClient } from 'convex/browser'\nimport type { FunctionArgs, FunctionReference, FunctionReturnType } from 'convex/server'\nimport type { BoundaryHelpersOptions } from '../boundaryHelpers'\nimport { createBoundaryHelpers } from '../boundaryHelpers'\nimport type { AnyRegistry } from '../types'\n\nexport type ZodvexClientOptions = (\n | { url: string; token?: string | null }\n | { client: ConvexClient }\n) &\n BoundaryHelpersOptions\n\n/** Wrap a static token string as an AuthTokenFetcher for ConvexClient */\nfunction tokenToFetcher(token: string): AuthTokenFetcher {\n return async () => token\n}\n\nexport class ZodvexClient<R extends AnyRegistry = AnyRegistry> {\n readonly convex: ConvexClient\n private codec: ReturnType<typeof createBoundaryHelpers>\n\n constructor(registry: R, options: ZodvexClientOptions) {\n this.codec = createBoundaryHelpers(registry, { onDecodeError: options.onDecodeError })\n if ('client' in options) {\n this.convex = options.client\n } else {\n this.convex = new ConvexClient(options.url)\n if (options.token) this.convex.setAuth(tokenToFetcher(options.token))\n }\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.convex.query(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n async mutate<M extends FunctionReference<'mutation', any, any, any>>(\n ref: M,\n args: M['_args']\n ): Promise<M['_returnType']> {\n const wireResult = await this.convex.mutation(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<M>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n subscribe<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args'],\n callback: (result: Q['_returnType']) => void\n ): () => void {\n const wireArgs = this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n return this.convex.onUpdate(ref, wireArgs, (wireResult: FunctionReturnType<Q>) => {\n callback(this.codec.decodeResult(ref, wireResult))\n })\n }\n\n setAuth(token: string | null) {\n this.convex.setAuth(async () => token)\n }\n\n async close() {\n await this.convex.close()\n }\n}\n\nexport function createZodvexClient<R extends AnyRegistry>(\n registry: R,\n options: ZodvexClientOptions\n): ZodvexClient<R> {\n return new ZodvexClient(registry, options)\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/normalizeCodecPaths.ts","../../src/utils.ts","../../src/boundaryHelpers.ts","../../src/client/zodvexClient.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","import { z } from 'zod'\nimport {\n $ZodArray,\n $ZodCodec,\n $ZodDate,\n $ZodDefault,\n $ZodNullable,\n $ZodObject,\n $ZodOptional,\n $ZodRecord,\n $ZodTuple,\n $ZodType,\n $ZodUnion,\n type input as zinput\n} from './zod-core'\n\n// Private copy — importing from ./mapping pulls convex/values into client bundles\n// (mapping/utils.ts imports `v` from convex/values which is server-only).\nfunction getObjectShape(obj: any): Record<string, any> {\n if (obj instanceof $ZodObject) return obj._zod.def.shape as Record<string, any>\n if (obj && typeof obj === 'object' && typeof obj.shape === 'object')\n return obj.shape as Record<string, any>\n return {}\n}\n\nexport function pick<T extends Record<string, any>, K extends keyof T>(\n obj: T,\n keys: K[]\n): Pick<T, K> {\n const result = {} as Pick<T, K>\n for (const key of keys) {\n if (key in obj) result[key] = obj[key]\n }\n return result\n}\n\n// Typed identity helper for returns schemas\nexport function returnsAs<R extends $ZodType>() {\n return <T extends zinput<R>>(v: T) => v\n}\n\n/**\n * Recursively strips undefined values from objects for Convex serialization.\n * Convex rejects objects with explicit undefined properties, so we need to\n * remove them before returning from handlers.\n *\n * Only processes plain objects (Object.prototype). Class instances, Dates,\n * and other non-plain objects are passed through unchanged.\n *\n * @param value - The value to strip undefined from\n * @returns The value with undefined properties removed from plain objects\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\n// Helper: standard Convex paginate() result schema\nexport function zPaginated<T extends $ZodType>(item: T) {\n return z.object({\n page: z.array(item),\n isDone: z.boolean(),\n continueCursor: z.optional(z.nullable(z.string()))\n })\n}\n\n/**\n * Maps Date fields to number fields for docSchema generation.\n * Handles Date, Date.optional(), Date.nullable(), and Date.default() cases.\n * Returns the original field for non-Date types.\n *\n * @deprecated Use `zx.date()` instead for automatic Date ↔ timestamp conversion.\n */\nexport function mapDateFieldToNumber(field: $ZodType): $ZodType {\n // Direct Date field\n if (field instanceof $ZodDate) {\n return z.number()\n }\n\n // Optional Date field\n if (field instanceof $ZodOptional && field._zod.def.innerType instanceof $ZodDate) {\n return z.optional(z.number())\n }\n\n // Nullable Date field\n if (field instanceof $ZodNullable && field._zod.def.innerType instanceof $ZodDate) {\n return z.nullable(z.number())\n }\n\n // Date with default value\n if (field instanceof $ZodDefault) {\n const inner = field._zod.def.innerType\n if (inner instanceof $ZodDate) {\n return z.optional(z.number())\n }\n }\n\n // Non-Date field - return as-is\n return field\n}\n\n// Schema picking utilities (moved from pick.ts for consolidation)\ntype Mask = readonly string[] | Record<string, boolean | 1 | true>\n\nfunction toKeys(mask: Mask): string[] {\n if (Array.isArray(mask)) return mask.map(String)\n return Object.keys(mask).filter(k => !!(mask as any)[k])\n}\n\n/**\n * Returns a plain shape object containing only the selected fields.\n * Accepts either a ZodObject or a raw shape object.\n */\nexport function pickShape(\n schemaOrShape: z.ZodObject<any> | Record<string, any>,\n mask: Mask\n): Record<string, any> {\n const keys = toKeys(mask)\n const shape =\n schemaOrShape instanceof $ZodObject ? getObjectShape(schemaOrShape) : schemaOrShape || {}\n\n const out: Record<string, any> = {}\n for (const k of keys) {\n if (k in shape) out[k] = (shape as any)[k]\n }\n return out\n}\n\n// Builds a fresh Zod object from the selected fields (avoids Zod's .pick())\nexport function safePick(schema: z.ZodObject<any>, mask: Mask): z.ZodObject<any> {\n return z.object(pickShape(schema, mask))\n}\n\n/**\n * Convenience: omit a set of keys by building the complement.\n * Avoids using Zod's .omit() which can cause type depth issues.\n */\nexport function safeOmit(schema: z.ZodObject<any>, mask: Mask): z.ZodObject<any> {\n const shape = getObjectShape(schema)\n const omit = new Set(toKeys(mask))\n const keep = Object.keys(shape).filter(k => !omit.has(k))\n const picked = pickShape(schema, keep)\n return z.object(picked)\n}\n\n/**\n * Recursively checks if a schema contains native z.date().\n * Stops recursion at ZodCodec boundaries since codecs handle their own transforms.\n */\nfunction containsNativeZodDate(schema: $ZodType): boolean {\n // Check if this is a native ZodDate (not our codec)\n if (schema instanceof $ZodDate) {\n return true\n }\n\n // Codecs handle their own transforms - don't recurse into them\n if (schema instanceof $ZodCodec) {\n return false\n }\n\n // Recurse into wrappers - cast unwrap result to ZodTypeAny for Zod v4 compatibility\n if (\n schema instanceof $ZodOptional ||\n schema instanceof $ZodNullable ||\n schema instanceof $ZodDefault\n ) {\n return containsNativeZodDate(schema._zod.def.innerType)\n }\n\n // Recurse into objects\n if (schema instanceof $ZodObject) {\n return Object.values(schema._zod.def.shape).some(field => containsNativeZodDate(field))\n }\n\n // Recurse into arrays\n if (schema instanceof $ZodArray) {\n return containsNativeZodDate(schema._zod.def.element)\n }\n\n // Recurse into unions\n if (schema instanceof $ZodUnion) {\n return schema._zod.def.options.some(opt => containsNativeZodDate(opt))\n }\n\n // Recurse into records\n if (schema instanceof $ZodRecord) {\n return containsNativeZodDate(schema._zod.def.valueType)\n }\n\n // Recurse into tuples\n if (schema instanceof $ZodTuple) {\n const items = schema._zod.def.items\n return items ? items.some(item => containsNativeZodDate(item)) : false\n }\n\n return false\n}\n\n/**\n * Throws if schema contains native z.date() which isn't compatible with Convex.\n * Guides users to use zx.date() instead.\n *\n * @param schema - The Zod schema to check\n * @param context - Context for the error message (args, returns, schema)\n * @throws Error with migration guidance if z.date() is found\n */\nexport function assertNoNativeZodDate(\n schema: $ZodType,\n context: 'args' | 'returns' | 'schema'\n): void {\n if (containsNativeZodDate(schema)) {\n throw new Error(\n `[zodvex] Native z.date() found in ${context}. ` +\n `Convex stores dates as timestamps (numbers), which z.date() cannot parse.\\n\\n` +\n `Fix: Replace z.date() with zx.date()\\n\\n` +\n `Before: { createdAt: z.date() }\\n` +\n `After: { createdAt: zx.date() }\\n\\n` +\n `zx.date() is a codec that handles timestamp ↔ Date conversion automatically.`\n )\n }\n}\n","import type { FunctionReference } from 'convex/server'\nimport type { z } from 'zod'\nimport type { $ZodIssue } from 'zod/v4/core'\nimport { safeEncode } from './normalizeCodecPaths'\nimport type { AnyRegistry } from './types'\nimport { stripUndefined } from './utils'\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).\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)\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 { AuthTokenFetcher } from 'convex/browser'\nimport { ConvexClient } from 'convex/browser'\nimport type { FunctionArgs, FunctionReference, FunctionReturnType } from 'convex/server'\nimport type { BoundaryHelpersOptions } from '../boundaryHelpers'\nimport { createBoundaryHelpers } from '../boundaryHelpers'\nimport type { AnyRegistry } from '../types'\n\nexport type ZodvexClientOptions = (\n | { url: string; token?: string | null }\n | { client: ConvexClient }\n) &\n BoundaryHelpersOptions\n\n/** Wrap a static token string as an AuthTokenFetcher for ConvexClient */\nfunction tokenToFetcher(token: string): AuthTokenFetcher {\n return async () => token\n}\n\nexport class ZodvexClient<R extends AnyRegistry = AnyRegistry> {\n readonly convex: ConvexClient\n private codec: ReturnType<typeof createBoundaryHelpers>\n\n constructor(registry: R, options: ZodvexClientOptions) {\n this.codec = createBoundaryHelpers(registry, { onDecodeError: options.onDecodeError })\n if ('client' in options) {\n this.convex = options.client\n } else {\n this.convex = new ConvexClient(options.url)\n if (options.token) this.convex.setAuth(tokenToFetcher(options.token))\n }\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.convex.query(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n async mutate<M extends FunctionReference<'mutation', any, any, any>>(\n ref: M,\n args: M['_args']\n ): Promise<M['_returnType']> {\n const wireResult = await this.convex.mutation(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<M>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n subscribe<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args'],\n callback: (result: Q['_returnType']) => void\n ): () => void {\n const wireArgs = this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n return this.convex.onUpdate(ref, wireArgs, (wireResult: FunctionReturnType<Q>) => {\n callback(this.codec.decodeResult(ref, wireResult))\n })\n }\n\n setAuth(token: string | null) {\n this.convex.setAuth(async () => token)\n }\n\n async close() {\n await this.convex.close()\n }\n}\n\nexport function createZodvexClient<R extends AnyRegistry>(\n registry: R,\n options: ZodvexClientOptions\n): ZodvexClient<R> {\n return new ZodvexClient(registry, options)\n}\n"]}
|
package/dist/core/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { $ZodError, encode, $ZodDate, $ZodOptional, $ZodNullable, $ZodDefault, $ZodObject, $ZodType, parse, safeParse, $ZodCodec, $ZodArray, $ZodLazy, $ZodTuple, $ZodRecord, $ZodEnum, $ZodLiteral, $ZodUnion, $ZodNumber, $ZodCustom, clone, $ZodDiscriminatedUnion } from 'zod/v4/core';
|
|
2
|
+
import { z } from 'zod';
|
|
3
3
|
import { v } from 'convex/values';
|
|
4
4
|
|
|
5
|
-
// src/
|
|
5
|
+
// src/zod-core.ts
|
|
6
6
|
|
|
7
7
|
// src/normalizeCodecPaths.ts
|
|
8
8
|
function unwrapOuter(schema) {
|
|
@@ -52,7 +52,7 @@ function normalizeCodecPaths(error, schema) {
|
|
|
52
52
|
...issue,
|
|
53
53
|
path: truncateAtCodecBoundary(issue.path, schema)
|
|
54
54
|
}));
|
|
55
|
-
return new ZodError(normalized);
|
|
55
|
+
return new $ZodError(normalized);
|
|
56
56
|
}
|
|
57
57
|
function safeEncode(schema, value) {
|
|
58
58
|
try {
|
|
@@ -93,7 +93,7 @@ function zPaginated(item) {
|
|
|
93
93
|
return z.object({
|
|
94
94
|
page: z.array(item),
|
|
95
95
|
isDone: z.boolean(),
|
|
96
|
-
continueCursor: z.
|
|
96
|
+
continueCursor: z.optional(z.nullable(z.string()))
|
|
97
97
|
});
|
|
98
98
|
}
|
|
99
99
|
function mapDateFieldToNumber(field) {
|
|
@@ -101,15 +101,15 @@ function mapDateFieldToNumber(field) {
|
|
|
101
101
|
return z.number();
|
|
102
102
|
}
|
|
103
103
|
if (field instanceof $ZodOptional && field._zod.def.innerType instanceof $ZodDate) {
|
|
104
|
-
return z.
|
|
104
|
+
return z.optional(z.number());
|
|
105
105
|
}
|
|
106
106
|
if (field instanceof $ZodNullable && field._zod.def.innerType instanceof $ZodDate) {
|
|
107
|
-
return z.
|
|
107
|
+
return z.nullable(z.number());
|
|
108
108
|
}
|
|
109
109
|
if (field instanceof $ZodDefault) {
|
|
110
110
|
const inner = field._zod.def.innerType;
|
|
111
111
|
if (inner instanceof $ZodDate) {
|
|
112
|
-
return z.
|
|
112
|
+
return z.optional(z.number());
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
115
|
return field;
|
|
@@ -192,7 +192,7 @@ function resolveFunctionPath(ref) {
|
|
|
192
192
|
}
|
|
193
193
|
return name;
|
|
194
194
|
}
|
|
195
|
-
var ZodvexDecodeError = class extends
|
|
195
|
+
var ZodvexDecodeError = class extends $ZodError {
|
|
196
196
|
functionPath;
|
|
197
197
|
wireData;
|
|
198
198
|
constructor(functionPath, issues, wireData) {
|
|
@@ -244,9 +244,14 @@ var registryHelpers = {
|
|
|
244
244
|
setMetadata: (type, meta) => metadata.set(type, meta)
|
|
245
245
|
};
|
|
246
246
|
function zid(tableName) {
|
|
247
|
-
const baseSchema = z.string().
|
|
248
|
-
|
|
249
|
-
|
|
247
|
+
const baseSchema = z.string().check(
|
|
248
|
+
z.refine((val) => typeof val === "string" && val.length > 0, {
|
|
249
|
+
message: `Invalid ID for table "${tableName}"`
|
|
250
|
+
}),
|
|
251
|
+
// Add a human-readable marker for client-side introspection utilities
|
|
252
|
+
// used in apps/native (e.g., to detect relationship fields in dynamic forms).
|
|
253
|
+
z.describe(`convexId:${tableName}`)
|
|
254
|
+
);
|
|
250
255
|
registryHelpers.setMetadata(baseSchema, {
|
|
251
256
|
isConvexId: true,
|
|
252
257
|
tableName
|
|
@@ -773,9 +778,12 @@ function date() {
|
|
|
773
778
|
);
|
|
774
779
|
}
|
|
775
780
|
function id(tableName) {
|
|
776
|
-
const baseSchema = z.string().
|
|
777
|
-
|
|
778
|
-
|
|
781
|
+
const baseSchema = z.string().check(
|
|
782
|
+
z.refine((val) => typeof val === "string" && val.length > 0, {
|
|
783
|
+
message: `Invalid ID for table "${tableName}"`
|
|
784
|
+
}),
|
|
785
|
+
z.describe(`convexId:${tableName}`)
|
|
786
|
+
);
|
|
779
787
|
registryHelpers.setMetadata(baseSchema, {
|
|
780
788
|
isConvexId: true,
|
|
781
789
|
tableName
|
|
@@ -867,14 +875,14 @@ function defineZodModel(name, fieldsOrSchema) {
|
|
|
867
875
|
}
|
|
868
876
|
const updateSchema = z.object({
|
|
869
877
|
_id: zx.id(name),
|
|
870
|
-
_creationTime: z.
|
|
878
|
+
_creationTime: z.optional(z.number()),
|
|
871
879
|
...partialShape
|
|
872
880
|
});
|
|
873
881
|
const docArraySchema = z.array(docSchema);
|
|
874
882
|
const paginatedDocSchema = z.object({
|
|
875
883
|
page: z.array(docSchema),
|
|
876
884
|
isDone: z.boolean(),
|
|
877
|
-
continueCursor: z.
|
|
885
|
+
continueCursor: z.optional(z.nullable(z.string()))
|
|
878
886
|
});
|
|
879
887
|
const schema = {
|
|
880
888
|
doc: docSchema,
|
|
@@ -918,7 +926,7 @@ function createUnionModel(name, inputSchema) {
|
|
|
918
926
|
const paginatedDocSchema = z.object({
|
|
919
927
|
page: z.array(docSchema),
|
|
920
928
|
isDone: z.boolean(),
|
|
921
|
-
continueCursor: z.
|
|
929
|
+
continueCursor: z.optional(z.nullable(z.string()))
|
|
922
930
|
});
|
|
923
931
|
let updateSchema;
|
|
924
932
|
if (isZodUnion(inputSchema)) {
|
|
@@ -931,7 +939,7 @@ function createUnionModel(name, inputSchema) {
|
|
|
931
939
|
}
|
|
932
940
|
return z.object({
|
|
933
941
|
_id: zx.id(name),
|
|
934
|
-
_creationTime: z.
|
|
942
|
+
_creationTime: z.optional(z.number()),
|
|
935
943
|
...partialShape
|
|
936
944
|
});
|
|
937
945
|
}
|
|
@@ -945,7 +953,7 @@ function createUnionModel(name, inputSchema) {
|
|
|
945
953
|
}
|
|
946
954
|
updateSchema = z.object({
|
|
947
955
|
_id: zx.id(name),
|
|
948
|
-
_creationTime: z.
|
|
956
|
+
_creationTime: z.optional(z.number()),
|
|
949
957
|
...partialShape
|
|
950
958
|
});
|
|
951
959
|
} else {
|