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.
- package/README.md +52 -61
- package/dist/actionCtx.d.ts +14 -0
- package/dist/actionCtx.d.ts.map +1 -0
- package/dist/builders.d.ts.map +1 -1
- package/dist/cli/commands.d.ts +9 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +446 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +42 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +78 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/zodvexClient.d.ts +18 -0
- package/dist/client/zodvexClient.d.ts.map +1 -0
- package/dist/codec.d.ts +15 -0
- package/dist/codec.d.ts.map +1 -1
- package/dist/codegen/discover.d.ts +32 -0
- package/dist/codegen/discover.d.ts.map +1 -0
- package/dist/codegen/generate.d.ts +20 -0
- package/dist/codegen/generate.d.ts.map +1 -0
- package/dist/codegen/index.d.ts +4 -0
- package/dist/codegen/index.d.ts.map +1 -0
- package/dist/codegen/index.js +271 -0
- package/dist/codegen/index.js.map +1 -0
- package/dist/codegen/zodToSource.d.ts +22 -0
- package/dist/codegen/zodToSource.d.ts.map +1 -0
- package/dist/core/index.d.ts +22 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +1383 -0
- package/dist/core/index.js.map +1 -0
- package/dist/custom.d.ts +3 -86
- package/dist/custom.d.ts.map +1 -1
- package/dist/customization.d.ts +41 -0
- package/dist/customization.d.ts.map +1 -0
- package/dist/db.d.ts +118 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/index.d.ts +18 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1362 -425
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts +101 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/mapping/types.d.ts +35 -10
- package/dist/mapping/types.d.ts.map +1 -1
- package/dist/meta.d.ts +21 -0
- package/dist/meta.d.ts.map +1 -0
- package/dist/model.d.ts +116 -0
- package/dist/model.d.ts.map +1 -0
- package/dist/react/hooks.d.ts +35 -0
- package/dist/react/hooks.d.ts.map +1 -0
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +54 -0
- package/dist/react/index.js.map +1 -0
- package/dist/schema.d.ts +130 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/server/index.d.ts +21 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +1408 -0
- package/dist/server/index.js.map +1 -0
- package/dist/tables.d.ts +24 -0
- package/dist/tables.d.ts.map +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +36 -2
- package/src/actionCtx.ts +45 -0
- package/src/builders.ts +34 -6
- package/src/cli/commands.ts +85 -0
- package/src/cli/index.ts +48 -0
- package/src/cli/init.ts +99 -0
- package/src/client/index.ts +2 -0
- package/src/client/zodvexClient.ts +78 -0
- package/src/codec.ts +33 -0
- package/src/codegen/discover.ts +115 -0
- package/src/codegen/generate.ts +185 -0
- package/src/codegen/index.ts +13 -0
- package/src/codegen/zodToSource.ts +131 -0
- package/src/core/index.ts +34 -0
- package/src/custom.ts +37 -190
- package/src/customization.ts +39 -0
- package/src/db.ts +399 -0
- package/src/index.ts +19 -14
- package/src/init.ts +231 -0
- package/src/mapping/types.ts +173 -172
- package/src/meta.ts +39 -0
- package/src/model.ts +379 -0
- package/src/react/hooks.ts +96 -0
- package/src/react/index.ts +2 -0
- package/src/schema.ts +210 -0
- package/src/server/index.ts +30 -0
- package/src/tables.ts +55 -25
- 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
|
-
####
|
|
531
|
+
#### onSuccess Hook
|
|
492
532
|
|
|
493
|
-
|
|
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
|
|
536
|
+
import { zCustomMutationBuilder } from 'zodvex'
|
|
497
537
|
import { type MutationCtx, mutation } from './_generated/server'
|
|
498
538
|
|
|
499
|
-
export const secureMutation = zCustomMutationBuilder(
|
|
500
|
-
|
|
501
|
-
|
|
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
|
-
|
|
509
|
-
|
|
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"}
|
package/dist/builders.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../src/builders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EAChB,MAAM,eAAe,CAAA;AACtB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uCAAuC,CAAA;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,KAAK,aAAa,EAAmB,MAAM,UAAU,CAAA;AAC9D,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,eAAe,EAChB,MAAM,SAAS,CAAA;
|
|
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 @@
|
|
|
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
|