zodvex 0.5.0 → 0.6.0-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.
Files changed (96) hide show
  1. package/README.md +52 -61
  2. package/dist/actionCtx.d.ts +14 -0
  3. package/dist/actionCtx.d.ts.map +1 -0
  4. package/dist/builders.d.ts.map +1 -1
  5. package/dist/cli/commands.d.ts +9 -0
  6. package/dist/cli/commands.d.ts.map +1 -0
  7. package/dist/cli/index.d.ts +3 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +446 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/cli/init.d.ts +42 -0
  12. package/dist/cli/init.d.ts.map +1 -0
  13. package/dist/client/index.d.ts +3 -0
  14. package/dist/client/index.d.ts.map +1 -0
  15. package/dist/client/index.js +78 -0
  16. package/dist/client/index.js.map +1 -0
  17. package/dist/client/zodvexClient.d.ts +18 -0
  18. package/dist/client/zodvexClient.d.ts.map +1 -0
  19. package/dist/codec.d.ts +15 -0
  20. package/dist/codec.d.ts.map +1 -1
  21. package/dist/codegen/discover.d.ts +32 -0
  22. package/dist/codegen/discover.d.ts.map +1 -0
  23. package/dist/codegen/generate.d.ts +20 -0
  24. package/dist/codegen/generate.d.ts.map +1 -0
  25. package/dist/codegen/index.d.ts +4 -0
  26. package/dist/codegen/index.d.ts.map +1 -0
  27. package/dist/codegen/index.js +271 -0
  28. package/dist/codegen/index.js.map +1 -0
  29. package/dist/codegen/zodToSource.d.ts +22 -0
  30. package/dist/codegen/zodToSource.d.ts.map +1 -0
  31. package/dist/core/index.d.ts +22 -0
  32. package/dist/core/index.d.ts.map +1 -0
  33. package/dist/core/index.js +1383 -0
  34. package/dist/core/index.js.map +1 -0
  35. package/dist/custom.d.ts +3 -86
  36. package/dist/custom.d.ts.map +1 -1
  37. package/dist/customization.d.ts +41 -0
  38. package/dist/customization.d.ts.map +1 -0
  39. package/dist/db.d.ts +118 -0
  40. package/dist/db.d.ts.map +1 -0
  41. package/dist/index.d.ts +18 -12
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +1362 -425
  44. package/dist/index.js.map +1 -1
  45. package/dist/init.d.ts +101 -0
  46. package/dist/init.d.ts.map +1 -0
  47. package/dist/mapping/types.d.ts +35 -10
  48. package/dist/mapping/types.d.ts.map +1 -1
  49. package/dist/meta.d.ts +21 -0
  50. package/dist/meta.d.ts.map +1 -0
  51. package/dist/model.d.ts +116 -0
  52. package/dist/model.d.ts.map +1 -0
  53. package/dist/react/hooks.d.ts +35 -0
  54. package/dist/react/hooks.d.ts.map +1 -0
  55. package/dist/react/index.d.ts +3 -0
  56. package/dist/react/index.d.ts.map +1 -0
  57. package/dist/react/index.js +54 -0
  58. package/dist/react/index.js.map +1 -0
  59. package/dist/schema.d.ts +130 -0
  60. package/dist/schema.d.ts.map +1 -0
  61. package/dist/server/index.d.ts +21 -0
  62. package/dist/server/index.d.ts.map +1 -0
  63. package/dist/server/index.js +1408 -0
  64. package/dist/server/index.js.map +1 -0
  65. package/dist/tables.d.ts +24 -0
  66. package/dist/tables.d.ts.map +1 -1
  67. package/dist/types.d.ts +16 -0
  68. package/dist/types.d.ts.map +1 -1
  69. package/package.json +36 -2
  70. package/src/actionCtx.ts +45 -0
  71. package/src/builders.ts +34 -6
  72. package/src/cli/commands.ts +85 -0
  73. package/src/cli/index.ts +48 -0
  74. package/src/cli/init.ts +99 -0
  75. package/src/client/index.ts +2 -0
  76. package/src/client/zodvexClient.ts +78 -0
  77. package/src/codec.ts +33 -0
  78. package/src/codegen/discover.ts +115 -0
  79. package/src/codegen/generate.ts +185 -0
  80. package/src/codegen/index.ts +13 -0
  81. package/src/codegen/zodToSource.ts +131 -0
  82. package/src/core/index.ts +34 -0
  83. package/src/custom.ts +37 -190
  84. package/src/customization.ts +39 -0
  85. package/src/db.ts +399 -0
  86. package/src/index.ts +19 -14
  87. package/src/init.ts +231 -0
  88. package/src/mapping/types.ts +173 -172
  89. package/src/meta.ts +39 -0
  90. package/src/model.ts +379 -0
  91. package/src/react/hooks.ts +96 -0
  92. package/src/react/index.ts +2 -0
  93. package/src/schema.ts +210 -0
  94. package/src/server/index.ts +30 -0
  95. package/src/tables.ts +55 -25
  96. package/src/types.ts +45 -34
package/README.md CHANGED
@@ -9,6 +9,7 @@ Type-safe Convex functions with Zod schemas. Preserve Convex's optional/nullable
9
9
  ## Table of Contents
10
10
 
11
11
  - [Installation](#installation)
12
+ - [Import Paths](#import-paths)
12
13
  - [Quick Start](#quick-start)
13
14
  - [Defining Schemas](#defining-schemas)
14
15
  - [Table Definitions](#table-definitions)
@@ -41,6 +42,45 @@ npm install zodvex zod@^4.1.0 convex convex-helpers
41
42
  - `convex` (>= 1.27.0)
42
43
  - `convex-helpers` (>= 0.1.104)
43
44
 
45
+ ## Import Paths
46
+
47
+ zodvex provides multiple entry points for optimal bundle sizes:
48
+
49
+ ### `zodvex/core` - Client-Safe (Recommended for client code)
50
+
51
+ Use this in React components, hooks, and any client-side code:
52
+
53
+ ```typescript
54
+ import { zx, zodToConvex } from 'zodvex/core'
55
+
56
+ // Define schemas that can be used anywhere
57
+ const userSchema = z.object({
58
+ id: zx.id('users'),
59
+ createdAt: zx.date(),
60
+ })
61
+ ```
62
+
63
+ ### `zodvex/server` - Server-Only
64
+
65
+ Use this in Convex functions and schema definitions:
66
+
67
+ ```typescript
68
+ import { zodTable, zCustomQuery } from 'zodvex/server'
69
+
70
+ // In convex/schema.ts
71
+ const Users = zodTable('users', userShape)
72
+ ```
73
+
74
+ ### `zodvex` - Full Library (Backwards Compatible)
75
+
76
+ For convenience or when you don't care about bundle size:
77
+
78
+ ```typescript
79
+ import { zx, zodTable } from 'zodvex'
80
+ ```
81
+
82
+ > **Note:** This pulls in server code. Use `zodvex/core` for client bundles.
83
+
44
84
  ## Quick Start
45
85
 
46
86
  ### 1. Set up your builders
@@ -488,80 +528,31 @@ export const updateProfile = authMutation({
488
528
  })
489
529
  ```
490
530
 
491
- #### Hooks and Transforms
531
+ #### onSuccess Hook
492
532
 
493
- For advanced use cases like logging, analytics, or data transformations, use `customCtxWithHooks`:
533
+ The `onSuccess` callback follows convex-helpers' `Customization` convention return it from your customization's `input` function:
494
534
 
495
535
  ```ts
496
- import { zCustomMutationBuilder, customCtxWithHooks } from 'zodvex'
536
+ import { zCustomMutationBuilder } from 'zodvex'
497
537
  import { type MutationCtx, mutation } from './_generated/server'
498
538
 
499
- export const secureMutation = zCustomMutationBuilder(
500
- mutation,
501
- customCtxWithHooks(async (ctx: MutationCtx) => {
539
+ export const secureMutation = zCustomMutationBuilder(mutation, {
540
+ args: {},
541
+ input: async (ctx: MutationCtx) => {
502
542
  const securityCtx = await getSecurityContext(ctx)
503
-
504
543
  return {
505
- // Custom context (same as customCtx)
506
544
  ctx: { securityCtx },
507
-
508
- // Hooks: observe execution (side effects, no return value)
509
- hooks: {
510
- onSuccess: ({ ctx, args, result }) => {
511
- // Called after successful execution
512
- console.log('Mutation succeeded:', { args, result })
513
- analytics.track('mutation_success', { userId: ctx.securityCtx.userId })
514
- }
515
- },
516
-
517
- // Transforms: modify data in the flow
518
- transforms: {
519
- // Transform args after validation, before handler
520
- input: (args, schema) => {
521
- // e.g., Convert wire format to runtime objects
522
- return transformIncomingArgs(args, securityCtx)
523
- },
524
- // Transform result after handler, before response
525
- output: (result, schema) => {
526
- // e.g., Mask sensitive fields based on permissions
527
- return transformOutgoingResult(result, securityCtx)
528
- }
545
+ args: {},
546
+ onSuccess: ({ ctx, args, result }) => {
547
+ console.log('Mutation succeeded:', { args, result })
529
548
  }
530
549
  }
531
- })
532
- )
533
- ```
534
-
535
- **Execution order:**
536
-
537
- 1. Args received from client
538
- 2. Zod validation on args
539
- 3. `transforms.input` runs (if provided)
540
- 4. Handler executes
541
- 5. Zod validation on returns (if provided)
542
- 6. `hooks.onSuccess` runs (if provided)
543
- 7. `transforms.output` runs (if provided)
544
- 8. Response sent to client
545
-
546
- **Use cases:**
547
-
548
- | Feature | Use Case |
549
- |---------|----------|
550
- | `hooks.onSuccess` | Logging, analytics, audit trails, cache invalidation |
551
- | `transforms.input` | Wire format → runtime objects, field decryption, data hydration |
552
- | `transforms.output` | Sensitive field masking, data redaction, format conversion |
553
-
554
- **Note:** Both `transforms.input` and `transforms.output` can be async:
555
-
556
- ```ts
557
- transforms: {
558
- input: async (args, schema) => {
559
- const decrypted = await decrypt(args.sensitiveField)
560
- return { ...args, sensitiveField: decrypted }
561
550
  }
562
- }
551
+ })
563
552
  ```
564
553
 
554
+ `onSuccess` runs after the handler and Zod return validation, seeing runtime types (e.g., `Date`, not timestamps).
555
+
565
556
  ### Custom Codecs
566
557
 
567
558
  For complex type transformations beyond the built-in `zx.date()` and `zx.id()`, use `zx.codec()` to create custom codecs that automatically work with validator generation and runtime encoding/decoding.
@@ -0,0 +1,14 @@
1
+ import type { GenericActionCtx, GenericDataModel } from 'convex/server';
2
+ import type { AnyRegistry } from './types';
3
+ /**
4
+ * Wraps an action context's runQuery/runMutation with automatic
5
+ * codec transforms via the zodvex registry.
6
+ *
7
+ * - Args are encoded (runtime -> wire) before calling the inner function
8
+ * - Results are decoded (wire -> runtime) before returning to the handler
9
+ * - Functions not in the registry pass through unchanged
10
+ *
11
+ * @internal Used by initZodvex when registry option is provided.
12
+ */
13
+ export declare function createZodvexActionCtx<DM extends GenericDataModel>(registry: AnyRegistry, ctx: GenericActionCtx<DM>): GenericActionCtx<DM>;
14
+ //# sourceMappingURL=actionCtx.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actionCtx.d.ts","sourceRoot":"","sources":["../src/actionCtx.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAGvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAG1C;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,SAAS,gBAAgB,EAC/D,QAAQ,EAAE,WAAW,EACrB,GAAG,EAAE,gBAAgB,CAAC,EAAE,CAAC,GACxB,gBAAgB,CAAC,EAAE,CAAC,CAyBtB"}
@@ -1 +1 @@
1
- {"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../src/builders.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../src/builders.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * One-shot codegen. Discovers modules, generates files.
3
+ */
4
+ export declare function generate(convexDir?: string): Promise<void>;
5
+ /**
6
+ * Watch mode. Runs generate() once, then watches for changes.
7
+ */
8
+ export declare function dev(convexDir?: string): Promise<void>;
9
+ //# sourceMappingURL=commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAsB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBhE;AAED;;GAEG;AACH,wBAAsB,GAAG,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoC3D"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bun
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,446 @@
1
+ #!/usr/bin/env bun
2
+ import fs from 'fs';
3
+ import path2 from 'path';
4
+ import { Glob } from 'bun';
5
+ import { z } from 'zod';
6
+
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropNames = Object.getOwnPropertyNames;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
16
+
17
+ // src/cli/init.ts
18
+ var init_exports = {};
19
+ __export(init_exports, {
20
+ ensureConcurrently: () => ensureConcurrently,
21
+ generateStubs: () => generateStubs,
22
+ gitignoreEntry: () => gitignoreEntry,
23
+ init: () => init,
24
+ rewriteDeployScript: () => rewriteDeployScript,
25
+ rewriteDevScript: () => rewriteDevScript
26
+ });
27
+ function rewriteDevScript(script) {
28
+ if (script.includes("zodvex dev")) return null;
29
+ const match = script.match(/\b((?:bunx|npx)\s+convex\s+dev)\b/);
30
+ if (!match) return null;
31
+ return `concurrently "zodvex dev" "${script}"`;
32
+ }
33
+ function rewriteDeployScript(script) {
34
+ if (script.includes("zodvex generate")) return null;
35
+ const match = script.match(/\b((?:bunx|npx)\s+convex\s+deploy)\b/);
36
+ if (!match) return null;
37
+ const idx = script.indexOf(match[1]);
38
+ const before = script.slice(0, idx);
39
+ const after = script.slice(idx);
40
+ return `${before}zodvex generate && ${after}`;
41
+ }
42
+ function ensureConcurrently(pkg) {
43
+ if (pkg.dependencies?.concurrently) return "exists";
44
+ if (pkg.devDependencies?.concurrently) return "exists";
45
+ return "add";
46
+ }
47
+ function gitignoreEntry(content) {
48
+ if (content.includes("convex/_zodvex/")) return null;
49
+ const lines = content ? content.split("\n") : [];
50
+ lines.push("# zodvex generated files", "convex/_zodvex/");
51
+ return lines.join("\n");
52
+ }
53
+ function generateStubs(convexDir2) {
54
+ const zodvexDir = path2.join(convexDir2, "_zodvex");
55
+ fs.mkdirSync(zodvexDir, { recursive: true });
56
+ const apiStub = `// Auto-generated stub. Run \`zodvex generate\` to populate.
57
+ export const zodvexRegistry = {} as const
58
+ `;
59
+ fs.writeFileSync(path2.join(zodvexDir, "api.ts"), apiStub);
60
+ const clientStub = `// Auto-generated stub. Run \`zodvex generate\` to populate.
61
+ import { zodvexRegistry } from './api'
62
+
63
+ export const useZodQuery = undefined as any
64
+ export const useZodMutation = undefined as any
65
+ export const createClient = undefined as any
66
+ `;
67
+ fs.writeFileSync(path2.join(zodvexDir, "client.ts"), clientStub);
68
+ }
69
+ async function init() {
70
+ const convexDir2 = path2.resolve("convex");
71
+ if (!fs.existsSync(convexDir2)) {
72
+ console.error("[zodvex] No convex/ directory found. Run this from your project root.");
73
+ return;
74
+ }
75
+ generateStubs(convexDir2);
76
+ console.log("[zodvex] Generated stub files in convex/_zodvex/");
77
+ console.log("[zodvex] Run `zodvex generate` to populate with your models and functions.");
78
+ }
79
+ var init_init = __esm({
80
+ "src/cli/init.ts"() {
81
+ }
82
+ });
83
+
84
+ // src/meta.ts
85
+ var META_KEY = "__zodvexMeta";
86
+ function readMeta(target) {
87
+ if (target == null || typeof target !== "object" && typeof target !== "function") {
88
+ return void 0;
89
+ }
90
+ return target[META_KEY];
91
+ }
92
+
93
+ // src/codegen/discover.ts
94
+ async function discoverModules(convexDir2) {
95
+ const models = [];
96
+ const functions = [];
97
+ const codecs = [];
98
+ const glob = new Glob("**/*.{ts,js}");
99
+ const files = [];
100
+ for await (const file of glob.scan({ cwd: convexDir2 })) {
101
+ if (file.startsWith("_generated/") || file.startsWith("_zodvex/") || file.startsWith("node_modules/") || file.endsWith(".d.ts")) {
102
+ continue;
103
+ }
104
+ files.push(file);
105
+ }
106
+ for (const file of files) {
107
+ const absPath = path2.resolve(convexDir2, file);
108
+ let moduleExports;
109
+ try {
110
+ moduleExports = await import(absPath);
111
+ } catch (err) {
112
+ console.warn(`[zodvex] Warning: Failed to import ${file}:`, err.message);
113
+ continue;
114
+ }
115
+ const moduleName = file.replace(/\.(ts|js)$/, "").replace(/\\/g, "/");
116
+ for (const [exportName, value] of Object.entries(moduleExports)) {
117
+ const meta = readMeta(value);
118
+ if (meta) {
119
+ if (meta.type === "model") {
120
+ models.push({
121
+ exportName,
122
+ tableName: meta.tableName,
123
+ sourceFile: file,
124
+ schemas: meta.schemas
125
+ });
126
+ } else if (meta.type === "function") {
127
+ functions.push({
128
+ functionPath: `${moduleName}:${exportName}`,
129
+ exportName,
130
+ sourceFile: file,
131
+ zodArgs: meta.zodArgs,
132
+ zodReturns: meta.zodReturns
133
+ });
134
+ }
135
+ }
136
+ if (value instanceof z.ZodCodec) {
137
+ const def = value._zod?.def;
138
+ const isZxDate = def?.in instanceof z.ZodNumber && def?.out instanceof z.ZodCustom;
139
+ if (!isZxDate) {
140
+ if (!codecs.some((c) => c.schema === value)) {
141
+ codecs.push({
142
+ exportName,
143
+ sourceFile: file,
144
+ schema: value
145
+ });
146
+ }
147
+ }
148
+ }
149
+ }
150
+ }
151
+ return { models, functions, codecs };
152
+ }
153
+ function zodToSource(schema, ctx) {
154
+ const def = schema._zod?.def;
155
+ if (schema instanceof z.ZodOptional) {
156
+ return `${zodToSource(def.innerType, ctx)}.optional()`;
157
+ }
158
+ if (schema instanceof z.ZodNullable) {
159
+ return `${zodToSource(def.innerType, ctx)}.nullable()`;
160
+ }
161
+ if (schema instanceof z.ZodString && schema.description?.startsWith("convexId:")) {
162
+ const tableName = schema.description.slice("convexId:".length);
163
+ return `zx.id("${tableName}")`;
164
+ }
165
+ if (schema instanceof z.ZodCodec && def.in instanceof z.ZodNumber && def.out instanceof z.ZodCustom) {
166
+ return "zx.date()";
167
+ }
168
+ if (schema instanceof z.ZodCodec) {
169
+ if (ctx?.codecMap) {
170
+ const ref = ctx.codecMap.get(schema);
171
+ if (ref) {
172
+ if (!ctx.neededCodecImports.has(ref.sourceFile)) {
173
+ ctx.neededCodecImports.set(ref.sourceFile, /* @__PURE__ */ new Set());
174
+ }
175
+ ctx.neededCodecImports.get(ref.sourceFile).add(ref.exportName);
176
+ return ref.exportName;
177
+ }
178
+ }
179
+ const wireSource = zodToSource(def.in, ctx);
180
+ return `${wireSource} /* codec: transforms lost */`;
181
+ }
182
+ if (schema instanceof z.ZodString) return "z.string()";
183
+ if (schema instanceof z.ZodNumber) return "z.number()";
184
+ if (schema instanceof z.ZodBoolean) return "z.boolean()";
185
+ if (schema instanceof z.ZodNull) return "z.null()";
186
+ if (schema instanceof z.ZodUndefined) return "z.undefined()";
187
+ if (schema instanceof z.ZodAny) return "z.any()";
188
+ if (schema instanceof z.ZodObject) {
189
+ const shape = def.shape;
190
+ const fields = Object.entries(shape).map(([key, value]) => `${key}: ${zodToSource(value, ctx)}`).join(", ");
191
+ return `z.object({ ${fields} })`;
192
+ }
193
+ if (schema instanceof z.ZodArray) {
194
+ return `z.array(${zodToSource(def.element, ctx)})`;
195
+ }
196
+ if (schema instanceof z.ZodEnum) {
197
+ const values = schema.options.map((v) => `"${v}"`).join(", ");
198
+ return `z.enum([${values}])`;
199
+ }
200
+ if (schema instanceof z.ZodLiteral) {
201
+ const values = def.values;
202
+ const value = values.values().next().value;
203
+ if (typeof value === "string") return `z.literal("${value}")`;
204
+ return `z.literal(${value})`;
205
+ }
206
+ if (schema instanceof z.ZodUnion) {
207
+ const members = def.options.map((s) => zodToSource(s, ctx)).join(", ");
208
+ return `z.union([${members}])`;
209
+ }
210
+ if (schema instanceof z.ZodTuple) {
211
+ const items = def.items.map((s) => zodToSource(s, ctx)).join(", ");
212
+ return `z.tuple([${items}])`;
213
+ }
214
+ if (schema instanceof z.ZodRecord) {
215
+ return `z.record(${zodToSource(def.keyType, ctx)}, ${zodToSource(def.valueType, ctx)})`;
216
+ }
217
+ const typeName = def?.type ?? "unknown";
218
+ return `z.any() /* unsupported: ${typeName} */`;
219
+ }
220
+
221
+ // src/codegen/generate.ts
222
+ var HEADER = `// AUTO-GENERATED by zodvex \u2014 do not edit
223
+ // Run \`zodvex generate\` to regenerate
224
+ `;
225
+ function generateSchemaFile(models) {
226
+ const exports$1 = models.map((m) => {
227
+ const importPath = `../${m.sourceFile.replace(/\.ts$/, "")}`;
228
+ return `export { ${m.exportName} } from '${importPath}'`;
229
+ }).join("\n");
230
+ return `${HEADER}
231
+ ${exports$1}
232
+ `;
233
+ }
234
+ function tryUnwrapToIdentity(schema, identityMap) {
235
+ let current = schema;
236
+ const suffixes = [];
237
+ const maxDepth = 5;
238
+ for (let i = 0; i < maxDepth; i++) {
239
+ const def = current._zod?.def;
240
+ if (current instanceof z.ZodOptional) {
241
+ suffixes.push(".optional()");
242
+ current = def.innerType;
243
+ } else if (current instanceof z.ZodNullable) {
244
+ suffixes.push(".nullable()");
245
+ current = def.innerType;
246
+ } else {
247
+ break;
248
+ }
249
+ const ref = identityMap.get(current);
250
+ if (ref) {
251
+ return { ref, suffix: suffixes.reverse().join("") };
252
+ }
253
+ }
254
+ return null;
255
+ }
256
+ function generateApiFile(functions, models, codecs) {
257
+ const identityMap = /* @__PURE__ */ new Map();
258
+ const neededModelImports = /* @__PURE__ */ new Set();
259
+ for (const model of models) {
260
+ const importPath = `../${model.sourceFile.replace(/\.ts$/, "")}`;
261
+ for (const key of ["doc", "insert", "update", "docArray", "paginatedDoc"]) {
262
+ identityMap.set(model.schemas[key], {
263
+ importPath,
264
+ exportName: model.exportName,
265
+ schemaKey: key
266
+ });
267
+ }
268
+ }
269
+ const codecMap = /* @__PURE__ */ new Map();
270
+ if (codecs) {
271
+ for (const codec of codecs) {
272
+ const importPath = `../${codec.sourceFile.replace(/\.ts$/, "")}`;
273
+ codecMap.set(codec.schema, {
274
+ exportName: codec.exportName,
275
+ sourceFile: importPath
276
+ });
277
+ }
278
+ }
279
+ const zodToSourceCtx = {
280
+ codecMap,
281
+ neededCodecImports: /* @__PURE__ */ new Map()
282
+ };
283
+ let needsZod = false;
284
+ let needsZx = false;
285
+ function resolveSchema(schema) {
286
+ if (!schema) return "undefined";
287
+ const ref = identityMap.get(schema);
288
+ if (ref) {
289
+ neededModelImports.add(ref.exportName);
290
+ return `${ref.exportName}.schema.${ref.schemaKey}`;
291
+ }
292
+ const unwrapped = tryUnwrapToIdentity(schema, identityMap);
293
+ if (unwrapped) {
294
+ neededModelImports.add(unwrapped.ref.exportName);
295
+ return `${unwrapped.ref.exportName}.schema.${unwrapped.ref.schemaKey}${unwrapped.suffix}`;
296
+ }
297
+ const source = zodToSource(schema, zodToSourceCtx);
298
+ if (source.includes("z.")) needsZod = true;
299
+ if (source.includes("zx.")) needsZx = true;
300
+ return source;
301
+ }
302
+ const entries = functions.map((fn) => {
303
+ const args = resolveSchema(fn.zodArgs);
304
+ const returns = resolveSchema(fn.zodReturns);
305
+ return ` '${fn.functionPath}': {
306
+ args: ${args},
307
+ returns: ${returns},
308
+ }`;
309
+ }).join(",\n");
310
+ const imports = [];
311
+ if (needsZod) imports.push("import { z } from 'zod'");
312
+ if (needsZx) imports.push("import { zx } from 'zodvex/core'");
313
+ for (const exportName of neededModelImports) {
314
+ const model = models.find((m) => m.exportName === exportName);
315
+ if (model) {
316
+ const importPath = `../${model.sourceFile.replace(/\.ts$/, "")}`;
317
+ imports.push(`import { ${exportName} } from '${importPath}'`);
318
+ }
319
+ }
320
+ for (const [importPath, exportNames] of zodToSourceCtx.neededCodecImports) {
321
+ const names = Array.from(exportNames).sort().join(", ");
322
+ imports.push(`import { ${names} } from '${importPath}'`);
323
+ }
324
+ const importSection = imports.length > 0 ? `${imports.join("\n")}
325
+
326
+ ` : "";
327
+ return `${HEADER}
328
+ ${importSection}export const zodvexRegistry = {
329
+ ${entries},
330
+ } as const
331
+ `;
332
+ }
333
+ function generateClientFile() {
334
+ return `${HEADER}
335
+ import { createZodvexHooks } from 'zodvex/react'
336
+ import { createZodvexClient, type ZodvexClientOptions } from 'zodvex/client'
337
+ import { zodvexRegistry } from './api'
338
+
339
+ export const { useZodQuery, useZodMutation } = createZodvexHooks(zodvexRegistry)
340
+
341
+ export const createClient = (options: ZodvexClientOptions) =>
342
+ createZodvexClient(zodvexRegistry, options)
343
+ `;
344
+ }
345
+
346
+ // src/cli/commands.ts
347
+ async function generate(convexDir2) {
348
+ const resolved = resolveConvexDir(convexDir2);
349
+ const zodvexDir = path2.join(resolved, "_zodvex");
350
+ const result = await discoverModules(resolved);
351
+ const schemaContent = generateSchemaFile(result.models);
352
+ const apiContent = generateApiFile(result.functions, result.models, result.codecs);
353
+ const clientContent = generateClientFile();
354
+ fs.mkdirSync(zodvexDir, { recursive: true });
355
+ fs.writeFileSync(path2.join(zodvexDir, "schema.ts"), schemaContent);
356
+ fs.writeFileSync(path2.join(zodvexDir, "api.ts"), apiContent);
357
+ fs.writeFileSync(path2.join(zodvexDir, "client.ts"), clientContent);
358
+ console.log(
359
+ `[zodvex] Generated ${result.models.length} model(s), ${result.functions.length} function(s), ${result.codecs.length} codec(s)`
360
+ );
361
+ }
362
+ async function dev(convexDir2) {
363
+ const resolved = resolveConvexDir(convexDir2);
364
+ console.log("[zodvex] Starting watch mode...");
365
+ await generate(resolved);
366
+ let debounceTimer = null;
367
+ const watcher = fs.watch(resolved, { recursive: true }, (_event, filename) => {
368
+ if (!filename) return;
369
+ if (filename.startsWith("_zodvex") || filename.startsWith("_generated") || !filename.endsWith(".ts") && !filename.endsWith(".js")) {
370
+ return;
371
+ }
372
+ if (debounceTimer) clearTimeout(debounceTimer);
373
+ debounceTimer = setTimeout(async () => {
374
+ console.log("[zodvex] Regenerating...");
375
+ try {
376
+ await generate(resolved);
377
+ } catch (err) {
378
+ console.error("[zodvex] Generation failed:", err.message);
379
+ }
380
+ }, 300);
381
+ });
382
+ process.on("SIGINT", () => {
383
+ if (debounceTimer) clearTimeout(debounceTimer);
384
+ watcher.close();
385
+ process.exit(0);
386
+ });
387
+ }
388
+ function resolveConvexDir(dir) {
389
+ if (dir) {
390
+ const resolved = path2.resolve(dir);
391
+ if (!fs.existsSync(resolved)) {
392
+ throw new Error(`Convex directory not found: ${resolved}`);
393
+ }
394
+ return resolved;
395
+ }
396
+ const defaultDir = path2.resolve("convex");
397
+ if (!fs.existsSync(defaultDir)) {
398
+ throw new Error("No convex/ directory found. Specify the path: zodvex generate <path>");
399
+ }
400
+ return defaultDir;
401
+ }
402
+
403
+ // src/cli/index.ts
404
+ var command = process.argv[2];
405
+ var convexDir = process.argv[3];
406
+ async function main() {
407
+ switch (command) {
408
+ case "generate":
409
+ await generate(convexDir);
410
+ break;
411
+ case "dev":
412
+ await dev(convexDir);
413
+ break;
414
+ case "init":
415
+ const { init: init2 } = await Promise.resolve().then(() => (init_init(), init_exports));
416
+ await init2();
417
+ break;
418
+ case "help":
419
+ case "--help":
420
+ case "-h":
421
+ case void 0:
422
+ printHelp();
423
+ break;
424
+ default:
425
+ console.error(`Unknown command: ${command}`);
426
+ printHelp();
427
+ process.exit(1);
428
+ }
429
+ }
430
+ function printHelp() {
431
+ console.log(`
432
+ zodvex - Convex codegen for Zod schemas
433
+
434
+ Usage:
435
+ zodvex generate [convex-dir] Generate schema and validator files
436
+ zodvex dev [convex-dir] Watch mode \u2014 regenerate on changes
437
+ zodvex init Set up zodvex in an existing Convex project
438
+ zodvex help Show this help message
439
+ `);
440
+ }
441
+ main().catch((err) => {
442
+ console.error(err.message);
443
+ process.exit(1);
444
+ });
445
+ //# sourceMappingURL=index.js.map
446
+ //# sourceMappingURL=index.js.map