zodvex 0.7.7-beta.0 → 0.7.7-beta.1
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 +55 -107
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +34 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/client/index.js +3 -5
- package/dist/client/index.js.map +1 -1
- package/dist/codegen/index.js +33 -3
- package/dist/codegen/index.js.map +1 -1
- package/dist/core/index.js +27 -6
- package/dist/core/index.js.map +1 -1
- package/dist/index.js +27 -6
- package/dist/index.js.map +1 -1
- package/dist/internal/boundaryHelpers.d.ts.map +1 -1
- package/dist/internal/custom.d.ts.map +1 -1
- package/dist/internal/registry.d.ts +7 -2
- package/dist/internal/registry.d.ts.map +1 -1
- package/dist/legacy/index.js +6 -2
- package/dist/legacy/index.js.map +1 -1
- package/dist/mini/client/index.js +3 -5
- package/dist/mini/client/index.js.map +1 -1
- package/dist/mini/index.js +27 -6
- package/dist/mini/index.js.map +1 -1
- package/dist/mini/react/index.js +3 -5
- package/dist/mini/react/index.js.map +1 -1
- package/dist/mini/server/index.js +9 -7
- package/dist/mini/server/index.js.map +1 -1
- package/dist/public/cli/index.d.ts +1 -1
- package/dist/public/codegen/discover.d.ts.map +1 -1
- package/dist/public/codegen/discovery-hooks.d.ts.map +1 -1
- package/dist/react/index.js +3 -5
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.js +9 -7
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/index.ts +1 -1
- package/src/internal/boundaryHelpers.ts +4 -6
- package/src/internal/custom.ts +11 -2
- package/src/internal/db.ts +1 -1
- package/src/internal/mapping/types.ts +2 -2
- package/src/internal/registry.ts +47 -3
- package/src/internal/types.ts +2 -2
- package/src/public/cli/index.ts +1 -1
- package/src/public/codegen/discover.ts +14 -0
- package/src/public/codegen/discovery-hooks.ts +31 -5
package/README.md
CHANGED
|
@@ -2,43 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
#### [Zod](https://zod.dev/) + [Convex](https://www.convex.dev/)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- [Why zodvex?](#why-zodvex)
|
|
12
|
-
- [Installation](#installation)
|
|
13
|
-
- [Quick Start](#quick-start)
|
|
14
|
-
- [Import Paths](#import-paths)
|
|
15
|
-
- [Features](#features)
|
|
16
|
-
- [Codec-Aware Database](#codec-aware-database)
|
|
17
|
-
- [Codegen & Client-Side Schema Sharing](#codegen--client-side-schema-sharing)
|
|
18
|
-
- [Using zodvex Without Codecs](#using-zodvex-without-codecs)
|
|
19
|
-
- [Supported Types](#supported-types)
|
|
20
|
-
- [Upgrading?](#upgrading)
|
|
21
|
-
- [API Reference](#api-reference)
|
|
22
|
-
- [Roadmap](#roadmap)
|
|
23
|
-
- [License](#license)
|
|
5
|
+
Use Zod v4 as your schema language for Convex — define your data once and use it end to end, with automatic validation and codecs at every boundary.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/zodvex)
|
|
8
|
+
[](https://github.com/panzacoder/zodvex/actions/workflows/ci.yml)
|
|
9
|
+
[](./LICENSE)
|
|
24
10
|
|
|
25
11
|
## Why zodvex?
|
|
26
12
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
- **
|
|
30
|
-
|
|
13
|
+
**Your Zod schemas are the source of truth** — tables, function arguments, and return types defined once, used database to frontend. Two things make that real:
|
|
14
|
+
|
|
15
|
+
- **Functions run full Zod pipelines.** Your argument and return schemas execute as real Zod at runtime — refinements like `.min()` and `.email()`, transformations, codecs — not erased down to structural checks.
|
|
16
|
+
|
|
17
|
+
- **The database is Zod-validated, automatically.** `ctx.db` parses every read and encodes every write through your schemas: `.email()` holds at the row level where Convex's structural checks stop, and codecs live in the schema itself — handlers see `Date` objects and branded IDs while Convex stores plain values.
|
|
31
18
|
|
|
32
|
-
|
|
33
|
-
|---------|--------|---------------------|
|
|
34
|
-
| Codec-aware DB | `initZodvex` wraps `ctx.db` automatically | Manual |
|
|
35
|
-
| Date handling | `zx.date()` — automatic Date ↔ timestamp | Manual `z.codec()` |
|
|
36
|
-
| Typed IDs | `zx.id('table')` with type branding | Manual |
|
|
37
|
-
| Custom codecs | `zx.codec()` with auto-detection | Not provided |
|
|
38
|
-
| Client-safe models | `defineZodModel` (importable in React) | Not provided |
|
|
39
|
-
| Codegen | Optional typed hooks, boundary helpers | Not provided |
|
|
19
|
+
What you gain over Convex out of the box:
|
|
40
20
|
|
|
41
|
-
|
|
21
|
+
| | Convex | with zodvex |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| Type safety | end-to-end inference | same — driven by your Zod schemas |
|
|
24
|
+
| Runtime validation | structural checks | full Zod — refinements, transforms, codecs |
|
|
25
|
+
| End-to-end validation | per-function validators | one Zod schema — client, functions, and db access |
|
|
26
|
+
| Client calls | `useQuery(api.fn)` infers types | `useZodQuery(api.fn)` infers the runtime schema too — args encoded, results decoded (via codegen) |
|
|
27
|
+
| Dates & custom types | `number` timestamps | `Date` objects and custom codecs (`zx.date()`, `zx.codec()`) |
|
|
28
|
+
| Rows on read | as stored | parsed & decoded through your schema |
|
|
29
|
+
| Row-level rules & audit | build your own | `.withRules()` / `.audit()` on `ctx.db` |
|
|
30
|
+
|
|
31
|
+
All of it wired once with `initZodvex` — see [Features](#features).
|
|
42
32
|
|
|
43
33
|
## Installation
|
|
44
34
|
|
|
@@ -72,7 +62,9 @@ export const EventModel = defineZodModel('events', {
|
|
|
72
62
|
|
|
73
63
|
> `defineZodModel` is client-safe — you can import it in React.
|
|
74
64
|
|
|
75
|
-
### Step 2.
|
|
65
|
+
### Step 2. Wire it up
|
|
66
|
+
|
|
67
|
+
Two one-time files: build your Convex schema from your models, and create your function builders.
|
|
76
68
|
|
|
77
69
|
```ts
|
|
78
70
|
// convex/schema.ts
|
|
@@ -84,8 +76,6 @@ export default defineZodSchema({
|
|
|
84
76
|
})
|
|
85
77
|
```
|
|
86
78
|
|
|
87
|
-
### Step 3. Set up builders
|
|
88
|
-
|
|
89
79
|
```ts
|
|
90
80
|
// convex/functions.ts
|
|
91
81
|
import { initZodvex } from 'zodvex/server'
|
|
@@ -101,9 +91,9 @@ export const { zq, zm, za, ziq, zim, zia } = initZodvex(schema, {
|
|
|
101
91
|
})
|
|
102
92
|
```
|
|
103
93
|
|
|
104
|
-
`initZodvex` returns builders for all six Convex function types
|
|
94
|
+
`initZodvex` returns builders for all six Convex function types, with `ctx.db` wrapped for automatic codec encode/decode. You write these two files once and rarely touch them again.
|
|
105
95
|
|
|
106
|
-
### Step
|
|
96
|
+
### Step 3. Write functions
|
|
107
97
|
|
|
108
98
|
```ts
|
|
109
99
|
// convex/events.ts
|
|
@@ -114,7 +104,7 @@ import { EventModel } from './models'
|
|
|
114
104
|
|
|
115
105
|
export const list = zq({
|
|
116
106
|
args: {},
|
|
117
|
-
returns:
|
|
107
|
+
returns: zx.docArray(EventModel),
|
|
118
108
|
handler: async (ctx) => {
|
|
119
109
|
// Dates come back as Date objects, not numbers
|
|
120
110
|
return await ctx.db.query('events').collect()
|
|
@@ -136,39 +126,52 @@ export const create = zm({
|
|
|
136
126
|
})
|
|
137
127
|
```
|
|
138
128
|
|
|
139
|
-
> `zx.id('events')` is a typed
|
|
129
|
+
> `zx.id('events')` is a typed ID validator — branding only, no wire transform. `zx.date()` and `zx.codec()` are codecs. Details in [Features](#features).
|
|
140
130
|
|
|
141
131
|
See the full [quickstart example](./examples/quickstart/) for a runnable project.
|
|
142
132
|
|
|
143
133
|
## Import Paths
|
|
144
134
|
|
|
145
|
-
Four entry points:
|
|
135
|
+
Four primary entry points:
|
|
146
136
|
|
|
147
137
|
- **`zodvex`** — Client-safe full-Zod surface. Use in React components and shared code.
|
|
148
138
|
- **`zodvex/server`** — Server-only. Use in Convex functions and schema definitions.
|
|
149
139
|
- **`zodvex/mini`** — Client-safe zod/mini surface.
|
|
150
140
|
- **`zodvex/mini/server`** — Server-only zod/mini surface.
|
|
151
|
-
- **`zodvex/legacy`** — Deprecated runtime APIs kept only for migration.
|
|
152
141
|
|
|
153
|
-
|
|
142
|
+
Focused entrypoints — `zodvex/react`, `zodvex/client`, `zodvex/codegen` (and their `zodvex/mini` variants) — back the codegen workflow and are mostly consumed by generated code; see [Codegen](#codegen--client-side-schema-sharing).
|
|
143
|
+
|
|
144
|
+
Two deprecated paths remain for migration only:
|
|
145
|
+
|
|
146
|
+
- **`zodvex/legacy`** — Deprecated runtime APIs kept only for migration.
|
|
147
|
+
- **`zodvex/core`** — Deprecated compatibility alias for `zodvex`.
|
|
154
148
|
|
|
155
149
|
## Features
|
|
156
150
|
|
|
157
151
|
### Codec-Aware Database
|
|
158
152
|
|
|
159
|
-
`initZodvex` wraps `ctx.db` so reads decode automatically and writes encode automatically.
|
|
153
|
+
`initZodvex` wraps `ctx.db` so reads decode automatically and writes encode automatically. Codecs are opt-in per field — schemas without them get the same validation, typed IDs, and correct optional/nullable mapping through the exact same setup.
|
|
160
154
|
|
|
161
155
|
- **`zx.date()`** — Date ↔ timestamp codec. Stored as `v.float64()`, used as `Date` in handlers.
|
|
162
156
|
- **`zx.codec(wire, runtime, transforms)`** — Custom codecs for complex transformations (encryption, serialization, etc.).
|
|
163
|
-
- **`zx.id('table')`** — Typed Convex ID validator with `GenericId<T>` branding
|
|
157
|
+
- **`zx.id('table')`** — Typed Convex ID validator with `GenericId<T>` branding — no wire transform (not a codec).
|
|
164
158
|
|
|
165
159
|
Guides: [Custom Codecs](./docs/guide/custom-codecs.md), [Date Handling](./docs/guide/date-handling.md)
|
|
166
160
|
|
|
161
|
+
### Row-Level Rules & Audit
|
|
162
|
+
|
|
163
|
+
The same wrapped `ctx.db` carries per-row security and observability — both operating on decoded documents (`Date` objects, typed IDs), never wire values:
|
|
164
|
+
|
|
165
|
+
- **`.withRules(ruleCtx, rules)`** — gate and transform reads and writes per table (`read`, `insert`, `patch`, `replace`, `delete`), with an optional deny-by-default policy.
|
|
166
|
+
- **`.audit({ afterRead, afterWrite })`** — observe successful reads and writes; composes with `.withRules()`, so audit sees only what the rules allowed.
|
|
167
|
+
|
|
168
|
+
Guide: [Rules & Audit](./docs/guide/rules-and-audit.md)
|
|
169
|
+
|
|
167
170
|
### Codegen & Client-Side Schema Sharing
|
|
168
171
|
|
|
169
172
|
zodvex includes an optional CLI that generates typed client code:
|
|
170
173
|
|
|
171
|
-
- **Typed hooks** — `useZodQuery`, `useZodMutation`
|
|
174
|
+
- **Typed hooks** — `useZodQuery`, `useZodMutation`, generated into `convex/_zodvex/client` — import them from there; args are encoded and results decoded automatically
|
|
172
175
|
- **Boundary helpers** — `encodeArgs`, `decodeResult` for custom client integrations
|
|
173
176
|
- **Cross-function auto-codec** — `ctx.runQuery` / `ctx.runMutation` encode args + decode results, and `ctx.scheduler.runAfter` / `ctx.scheduler.runAt` encode args, via the registry. Pass natural decoded values; zodvex encodes them to wire at the call site.
|
|
174
177
|
|
|
@@ -183,20 +186,6 @@ zodvex dev # watch mode
|
|
|
183
186
|
|
|
184
187
|
Guides: [Codegen](./docs/guide/codegen.md) | Example: [examples/task-manager/](./examples/task-manager/)
|
|
185
188
|
|
|
186
|
-
### Using zodvex Without Codecs
|
|
187
|
-
|
|
188
|
-
`zodTable` and `zQueryBuilder` still work without `initZodvex`:
|
|
189
|
-
|
|
190
|
-
```ts
|
|
191
|
-
import { zodTable, zQueryBuilder } from 'zodvex/legacy'
|
|
192
|
-
import { query } from './_generated/server'
|
|
193
|
-
|
|
194
|
-
const Users = zodTable('users', { name: z.string() })
|
|
195
|
-
const zq = zQueryBuilder(query)
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
At this level, zodvex is roughly equivalent to convex-helpers. This is a valid stepping-stone, but the API is deprecated. When you're ready for codecs, see the [Quick Start](#quick-start) above.
|
|
199
|
-
|
|
200
189
|
## Supported Types
|
|
201
190
|
|
|
202
191
|
| Zod Type | Convex Validator |
|
|
@@ -217,52 +206,13 @@ At this level, zodvex is roughly equivalent to convex-helpers. This is a valid s
|
|
|
217
206
|
|
|
218
207
|
> **Note:** Native `z.date()` is **not supported** — use `zx.date()` instead. See [Date Handling](./docs/guide/date-handling.md) for details.
|
|
219
208
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
¹ Enum types in Zod v4 produce a slightly different TypeScript signature than manually created unions:
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
// Manual union (precise tuple type)
|
|
226
|
-
const manual = v.union(v.literal('a'), v.literal('b'))
|
|
227
|
-
// Type: VUnion<"a" | "b", [VLiteral<"a", "required">, VLiteral<"b", "required">], "required", never>
|
|
228
|
-
|
|
229
|
-
// From Zod enum (array type)
|
|
230
|
-
const fromZod = zodToConvex(z.enum(['a', 'b']))
|
|
231
|
-
// Type: VUnion<"a" | "b", Array<VLiteral<"a" | "b", "required">>, "required", never>
|
|
232
|
-
```
|
|
233
|
-
|
|
234
|
-
**This difference is purely cosmetic with no functional impact:**
|
|
235
|
-
|
|
236
|
-
- Value types are identical (`"a" | "b"`)
|
|
237
|
-
- Runtime validation is identical
|
|
238
|
-
- Type safety for function arguments/returns is preserved
|
|
239
|
-
- Convex uses `T[number]` which works identically for both array and tuple types
|
|
209
|
+
¹ Enum unions carry a cosmetically different TypeScript signature than hand-written `v.union(v.literal(...))` calls — identical values, runtime validation, and type safety. Details: [Mapping Helpers](./docs/guide/mapping-helpers.md#zod-v4-enum-type-note).
|
|
240
210
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
**zx namespace types:**
|
|
244
|
-
|
|
245
|
-
```ts
|
|
246
|
-
import { zx } from 'zodvex'
|
|
247
|
-
|
|
248
|
-
// Convex IDs — typed validator, NOT a codec
|
|
249
|
-
zx.id('tableName') // → v.id('tableName')
|
|
250
|
-
zx.id('tableName').optional() // → v.optional(v.id('tableName'))
|
|
251
|
-
|
|
252
|
-
// Dates — codec (Date ↔ timestamp)
|
|
253
|
-
zx.date() // → v.float64() (timestamp)
|
|
254
|
-
zx.date().optional() // → v.optional(v.float64())
|
|
255
|
-
zx.date().nullable() // → v.union(v.float64(), v.null())
|
|
256
|
-
|
|
257
|
-
// Custom codecs
|
|
258
|
-
zx.codec(wireSchema, runtimeSchema, { encode, decode })
|
|
259
|
-
```
|
|
211
|
+
For zodvex's own types — `zx.id()`, `zx.date()`, `zx.codec()` — and exactly how they map to Convex validators, see [The zx Namespace](./docs/guide/zx-namespace.md).
|
|
260
212
|
|
|
261
213
|
## Upgrading?
|
|
262
214
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
Automated renames are available:
|
|
215
|
+
Read the [migration guide](./MIGRATION.md) for what changed in each release and why. Automated renames are available:
|
|
266
216
|
|
|
267
217
|
```bash
|
|
268
218
|
npx zodvex migrate ./convex # apply renames
|
|
@@ -273,7 +223,8 @@ npx zodvex migrate ./convex --dry-run # preview changes
|
|
|
273
223
|
|
|
274
224
|
- [The zx Namespace](./docs/guide/zx-namespace.md) — `zx.id()`, `zx.date()`, `zx.codec()`
|
|
275
225
|
- [Builders](./docs/guide/builders.md) — `initZodvex` and legacy builders
|
|
276
|
-
- [Custom Context](./docs/guide/custom-context.md) — `.withContext()`, `onSuccess`
|
|
226
|
+
- [Custom Context](./docs/guide/custom-context.md) — `.withContext()`, `defineContext`, `onSuccess`
|
|
227
|
+
- [Rules & Audit](./docs/guide/rules-and-audit.md) — `.withRules()`, `.audit()` on `ctx.db`
|
|
277
228
|
- [Custom Codecs](./docs/guide/custom-codecs.md) — `zx.codec()`, `decodeDoc`/`encodeDoc`
|
|
278
229
|
- [Date Handling](./docs/guide/date-handling.md) — `zx.date()` deep dive
|
|
279
230
|
- [Form Validation](./docs/guide/form-validation.md) — react-hook-form integration
|
|
@@ -288,10 +239,7 @@ npx zodvex migrate ./convex --dry-run # preview changes
|
|
|
288
239
|
|
|
289
240
|
## Roadmap
|
|
290
241
|
|
|
291
|
-
|
|
292
|
-
- Migration tooling: pre-0.5 → current zodvex
|
|
293
|
-
- Additional example projects (e.g., full-stack with React, codegen showcase)
|
|
294
|
-
- Per-feature READMEs in examples/task-manager/
|
|
242
|
+
See the [roadmap](./docs/roadmap.md) for where zodvex is heading — deploy-scale performance, ecosystem interop, and the model/namespace evolution.
|
|
295
243
|
|
|
296
244
|
## License
|
|
297
245
|
|
|
@@ -299,4 +247,4 @@ MIT
|
|
|
299
247
|
|
|
300
248
|
---
|
|
301
249
|
|
|
302
|
-
Built with ❤️
|
|
250
|
+
Built with ❤️ for the [Convex](https://www.convex.dev/) ecosystem. Thanks to [convex-helpers](https://github.com/get-convex/convex-helpers) for the early foundations.
|
package/dist/cli/index.d.ts
CHANGED
package/dist/cli/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
import fs2, { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
3
3
|
import path3, { resolve, relative, join } from 'path';
|
|
4
4
|
import { Project, SyntaxKind } from 'ts-morph';
|
|
@@ -1305,11 +1305,30 @@ function createSchemaUpdateSchema(name, inputSchema) {
|
|
|
1305
1305
|
return inputSchema;
|
|
1306
1306
|
}
|
|
1307
1307
|
var HOOKS_SOURCE = `
|
|
1308
|
-
|
|
1308
|
+
const EXT_CANDIDATES = ['.ts', '.tsx', '.mts', '.js', '.mjs', '.jsx', '/index.ts', '/index.js'];
|
|
1309
|
+
|
|
1310
|
+
export async function resolve(specifier, context, nextResolve) {
|
|
1309
1311
|
if (/_generated\\/api(\\.[mc]?[jt]sx?)?$/.test(specifier)) {
|
|
1310
1312
|
return { shortCircuit: true, url: 'zodvex-stub://api' };
|
|
1311
1313
|
}
|
|
1312
|
-
|
|
1314
|
+
try {
|
|
1315
|
+
return await nextResolve(specifier, context);
|
|
1316
|
+
} catch (err) {
|
|
1317
|
+
// Convex code uses extensionless relative imports (bundler resolution).
|
|
1318
|
+
// Bun resolves those natively; Node's ESM loader does not \u2014 retry with
|
|
1319
|
+
// the usual extension candidates before giving up.
|
|
1320
|
+
if (
|
|
1321
|
+
(specifier.startsWith('./') || specifier.startsWith('../')) &&
|
|
1322
|
+
!/\\.[cm]?[jt]sx?$/.test(specifier)
|
|
1323
|
+
) {
|
|
1324
|
+
for (const ext of EXT_CANDIDATES) {
|
|
1325
|
+
try {
|
|
1326
|
+
return await nextResolve(specifier + ext, context);
|
|
1327
|
+
} catch {}
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
throw err;
|
|
1331
|
+
}
|
|
1313
1332
|
}
|
|
1314
1333
|
|
|
1315
1334
|
export function load(url, context, nextLoad) {
|
|
@@ -1343,7 +1362,11 @@ var hooksRegistered = false;
|
|
|
1343
1362
|
function registerDiscoveryHooks() {
|
|
1344
1363
|
if (hooksRegistered) return true;
|
|
1345
1364
|
try {
|
|
1346
|
-
const
|
|
1365
|
+
const nodeModule = typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("node:module") : (
|
|
1366
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
1367
|
+
__require("module")
|
|
1368
|
+
);
|
|
1369
|
+
const { register } = nodeModule;
|
|
1347
1370
|
if (typeof register !== "function") return false;
|
|
1348
1371
|
register(`data:text/javascript,${encodeURIComponent(HOOKS_SOURCE)}`);
|
|
1349
1372
|
hooksRegistered = true;
|
|
@@ -1572,6 +1595,7 @@ async function discoverModules(convexDir2) {
|
|
|
1572
1595
|
"crons.js"
|
|
1573
1596
|
]
|
|
1574
1597
|
}).sort();
|
|
1598
|
+
let importFailures = 0;
|
|
1575
1599
|
try {
|
|
1576
1600
|
for (const file of files) {
|
|
1577
1601
|
const absPath = path3.resolve(convexDir2, file);
|
|
@@ -1579,6 +1603,7 @@ async function discoverModules(convexDir2) {
|
|
|
1579
1603
|
try {
|
|
1580
1604
|
moduleExports = await import(absPath);
|
|
1581
1605
|
} catch (err) {
|
|
1606
|
+
importFailures++;
|
|
1582
1607
|
console.warn(`[zodvex] Warning: Failed to import ${file}:`, err.message);
|
|
1583
1608
|
continue;
|
|
1584
1609
|
}
|
|
@@ -1646,6 +1671,11 @@ async function discoverModules(convexDir2) {
|
|
|
1646
1671
|
modelCodecs.push(...found);
|
|
1647
1672
|
}
|
|
1648
1673
|
const functionCodecs = walkFunctionCodecs(functions);
|
|
1674
|
+
if (importFailures > 0 && models.length === 0 && functions.length === 0) {
|
|
1675
|
+
throw new Error(
|
|
1676
|
+
`[zodvex] Discovery imported 0 modules (${importFailures} file(s) failed to load). Importing TypeScript at runtime requires Bun or Node >= 22.18 (native type stripping). Re-run with Bun (\`bunx zodvex generate\`) or upgrade Node.`
|
|
1677
|
+
);
|
|
1678
|
+
}
|
|
1649
1679
|
return { models, functions, codecs, modelCodecs, functionCodecs };
|
|
1650
1680
|
} finally {
|
|
1651
1681
|
cleanupStubs();
|