zodvex 0.7.7-beta.1 → 0.7.7
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/cli/index.js +296 -81
- package/dist/cli/index.js.map +1 -1
- package/dist/client/index.js +2 -2
- package/dist/client/index.js.map +1 -1
- package/dist/codegen/index.js +211 -28
- package/dist/codegen/index.js.map +1 -1
- package/dist/core/index.js +33 -16
- package/dist/core/index.js.map +1 -1
- package/dist/index.js +33 -16
- package/dist/index.js.map +1 -1
- package/dist/internal/boundaryHelpers.d.ts +2 -15
- package/dist/internal/boundaryHelpers.d.ts.map +1 -1
- package/dist/internal/registry.d.ts.map +1 -1
- package/dist/internal/zx.d.ts.map +1 -1
- package/dist/internal/zxDateBrand.d.ts +5 -0
- package/dist/internal/zxDateBrand.d.ts.map +1 -0
- package/dist/legacy/index.js +21 -10
- package/dist/legacy/index.js.map +1 -1
- package/dist/mini/client/index.js +2 -2
- package/dist/mini/client/index.js.map +1 -1
- package/dist/mini/index.js +33 -16
- package/dist/mini/index.js.map +1 -1
- package/dist/mini/react/index.js +2 -2
- package/dist/mini/react/index.js.map +1 -1
- package/dist/mini/server/index.js +23 -12
- package/dist/mini/server/index.js.map +1 -1
- package/dist/public/cli/commands.d.ts.map +1 -1
- package/dist/public/codegen/discover.d.ts.map +1 -1
- package/dist/public/codegen/discovery-hooks.d.ts +2 -1
- package/dist/public/codegen/discovery-hooks.d.ts.map +1 -1
- package/dist/public/codegen/extractCodec.d.ts.map +1 -1
- package/dist/public/codegen/tsconfigPaths.d.ts +41 -0
- package/dist/public/codegen/tsconfigPaths.d.ts.map +1 -0
- package/dist/public/codegen/zodToSource.d.ts.map +1 -1
- package/dist/react/index.js +2 -2
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.js +23 -12
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
- package/src/internal/boundaryHelpers.ts +15 -3
- package/src/internal/registry.ts +12 -9
- package/src/internal/zx.ts +12 -9
- package/src/internal/zxDateBrand.ts +34 -0
- package/src/public/cli/commands.ts +59 -17
- package/src/public/codegen/discover.ts +27 -15
- package/src/public/codegen/discovery-hooks.ts +42 -3
- package/src/public/codegen/extractCodec.ts +5 -11
- package/src/public/codegen/tsconfigPaths.ts +224 -0
- package/src/public/codegen/zodToSource.ts +5 -6
package/dist/client/index.js
CHANGED
|
@@ -100,9 +100,9 @@ var ZodvexDecodeError = class extends $ZodError {
|
|
|
100
100
|
this.name = "ZodvexDecodeError";
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
|
+
var warnedPaths = /* @__PURE__ */ new Set();
|
|
103
104
|
function createBoundaryHelpers(registry, options) {
|
|
104
105
|
const onDecodeError = options?.onDecodeError ?? "warn";
|
|
105
|
-
const warnedPaths = /* @__PURE__ */ new Set();
|
|
106
106
|
function encodeArgs(ref, args) {
|
|
107
107
|
if (args == null) return args;
|
|
108
108
|
const path = resolveFunctionPath(ref);
|
|
@@ -112,7 +112,7 @@ function createBoundaryHelpers(registry, options) {
|
|
|
112
112
|
if (entry === void 0 && !warnedPaths.has(path)) {
|
|
113
113
|
warnedPaths.add(path);
|
|
114
114
|
console.debug(
|
|
115
|
-
`[zodvex] No registry entry for "${path}" \u2014 args
|
|
115
|
+
`[zodvex] No registry entry for "${path}" \u2014 args/returns pass through unencoded. This is expected when the target is a raw (non-zodvex) function; if it should be codec-aware, run \`zodvex generate\` to update the registry.`
|
|
116
116
|
);
|
|
117
117
|
}
|
|
118
118
|
return args;
|
package/dist/client/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/internal/normalizeCodecPaths.ts","../../src/internal/stripUndefined.ts","../../src/internal/boundaryHelpers.ts","../../src/public/client/zodvexClient.ts"],"names":[],"mappings":";;;;;;AAeA,SAAS,YAAY,MAAA,EAA4B;AAC/C,EAAA,IAAI,OAAA,GAAoB,MAAA;AACxB,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,EAAA,EAAI,CAAA,EAAA,EAAK;AAC3B,IAAA,IACE,OAAA,YAAmB,YAAA,IACnB,OAAA,YAAmB,YAAA,IACnB,mBAAmB,WAAA,EACnB;AACA,MAAA,OAAA,GAAU,OAAA,CAAQ,KAAK,GAAA,CAAI,SAAA;AAC3B,MAAA;AAAA,IACF;AACA,IAAA;AAAA,EACF;AACA,EAAA,OAAO,OAAA;AACT;AAOA,SAAS,uBAAA,CAAwB,MAA2B,MAAA,EAAuC;AACjG,EAAA,MAAM,SAA8B,EAAC;AACrC,EAAA,IAAI,OAAA,GAAoB,MAAA;AAExB,EAAA,KAAA,MAAW,WAAW,IAAA,EAAM;AAC1B,IAAA,OAAA,GAAU,YAAY,OAAO,CAAA;AAG7B,IAAA,IAAI,mBAAmB,SAAA,EAAW;AAChC,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,OAAA,YAAmB,UAAA,IAAc,OAAO,OAAA,KAAY,QAAA,EAAU;AAChE,MAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,IAAA,CAAK,GAAA,CAAI,MAAM,OAAO,CAAA;AAClD,MAAA,IAAI,CAAC,WAAA,EAAa;AAEhB,QAAA,MAAA,CAAO,KAAK,OAAO,CAAA;AACnB,QAAA;AAAA,MACF;AAEA,MAAA,MAAA,CAAO,KAAK,OAAO,CAAA;AAEnB,MAAA,MAAM,SAAA,GAAY,YAAY,WAAW,CAAA;AACzC,MAAA,IAAI,qBAAqB,SAAA,EAAW;AAElC,QAAA;AAAA,MACF;AAEA,MAAA,OAAA,GAAU,WAAA;AACV,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,OAAA,YAAmB,SAAA,IAAa,OAAO,OAAA,KAAY,QAAA,EAAU;AAC/D,MAAA,MAAA,CAAO,KAAK,OAAO,CAAA;AACnB,MAAA,OAAA,GAAU,OAAA,CAAQ,KAAK,GAAA,CAAI,OAAA;AAC3B,MAAA;AAAA,IACF;AAGA,IAAA,MAAA,CAAO,KAAK,OAAO,CAAA;AAAA,EACrB;AAEA,EAAA,OAAO,MAAA;AACT;AAUO,SAAS,mBAAA,CAAoB,OAAkB,MAAA,EAA6B;AACjF,EAAA,MAAM,UAAA,GAAa,KAAA,CAAM,MAAA,CAAO,GAAA,CAAI,CAAA,KAAA,MAAU;AAAA,IAC5C,GAAG,KAAA;AAAA,IACH,IAAA,EAAM,uBAAA,CAAwB,KAAA,CAAM,IAAA,EAA6B,MAAM;AAAA,GACzE,CAAE,CAAA;AACF,EAAA,OAAO,IAAI,UAAU,UAAU,CAAA;AACjC;AAQO,SAAS,UAAA,CAAW,QAAkB,KAAA,EAAyB;AACpE,EAAA,IAAI;AACF,IAAA,OAAO,MAAA,CAAO,QAAQ,KAAK,CAAA;AAAA,EAC7B,SAAS,CAAA,EAAG;AACV,IAAA,IAAI,CAAA,YAAa,SAAA,EAAW,MAAM,mBAAA,CAAoB,GAAgB,MAAM,CAAA;AAC5E,IAAA,MAAM,CAAA;AAAA,EACR;AACF;;;ACzGO,SAAS,eAAkB,KAAA,EAAa;AAC7C,EAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,EAAW;AACzC,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,IAAA,OAAO,KAAA,CAAM,IAAI,cAAc,CAAA;AAAA,EACjC;AAGA,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,gBAAgB,MAAA,EAAQ;AAC7D,IAAA,MAAM,SAAkC,EAAC;AACzC,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,GAAG,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC9C,MAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,cAAA,CAAe,GAAG,CAAA;AAAA,MAClC;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,OAAO,KAAA;AACT;;;ACdA,IAAM,kBAAA,mBAAqB,MAAA,CAAO,GAAA,CAAI,cAAc,CAAA;AAEpD,SAAS,oBAAoB,GAAA,EAA2D;AACtF,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,EAAU,OAAO,GAAA;AACpC,EAAA,MAAM,IAAA,GAAQ,IAAY,kBAAkB,CAAA;AAC5C,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAClB,EAAA,OAAO,IAAA;AACT;AAoBO,IAAM,iBAAA,GAAN,cAAgC,SAAA,CAAU;AAAA,EACtC,YAAA;AAAA,EACA,QAAA;AAAA,EAET,WAAA,CAAY,YAAA,EAAsB,MAAA,EAAqB,QAAA,EAAmB;AACxE,IAAA,KAAA,CAAM,MAAM,CAAA;AACZ,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AACpB,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAChB,IAAA,IAAA,CAAK,IAAA,GAAO,mBAAA;AAAA,EACd;AACF,CAAA;AAiBO,SAAS,qBAAA,CAAsB,UAAuB,OAAA,EAAkC;AAC7F,EAAA,MAAM,aAAA,GAAgB,SAAS,aAAA,IAAiB,MAAA;AAChD,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAY;AAcpC,EAAA,SAAS,UAAA,CAAW,KAA4C,IAAA,EAAgB;AAC9E,IAAA,IAAI,IAAA,IAAQ,MAAM,OAAO,IAAA;AACzB,IAAA,MAAM,IAAA,GAAO,oBAAoB,GAAG,CAAA;AACpC,IAAA,IAAI,IAAA,IAAQ,MAAM,OAAO,IAAA;AACzB,IAAA,MAAM,KAAA,GAAQ,SAAS,IAAI,CAAA;AAC3B,IAAA,IAAI,CAAC,OAAO,IAAA,EAAM;AAChB,MAAA,IAAI,UAAU,MAAA,IAAa,CAAC,WAAA,CAAY,GAAA,CAAI,IAAI,CAAA,EAAG;AACjD,QAAA,WAAA,CAAY,IAAI,IAAI,CAAA;AACpB,QAAA,OAAA,CAAQ,KAAA;AAAA,UACN,mCAAmC,IAAI,CAAA,+HAAA;AAAA,SAEzC;AAAA,MACF;AACA,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,cAAA,CAAe,UAAA,CAAW,KAAA,CAAM,IAAA,EAAM,IAAI,CAAC,CAAA;AAAA,EACpD;AAaA,EAAA,SAAS,YAAA,CAAa,KAA4C,UAAA,EAAsB;AACtF,IAAA,MAAM,IAAA,GAAO,oBAAoB,GAAG,CAAA;AACpC,IAAA,IAAI,IAAA,IAAQ,MAAM,OAAO,UAAA;AACzB,IAAA,MAAM,KAAA,GAAQ,SAAS,IAAI,CAAA;AAC3B,IAAA,IAAI,CAAC,KAAA,EAAO,OAAA,EAAS,OAAO,UAAA;AAE5B,IAAA,MAAM,MAAA,GAAS,SAAA,CAAU,KAAA,CAAM,OAAA,EAAS,UAAU,CAAA;AAClD,IAAA,IAAI,MAAA,CAAO,OAAA,EAAS,OAAO,MAAA,CAAO,IAAA;AAElC,IAAA,IAAI,kBAAkB,OAAA,EAAS;AAC7B,MAAA,MAAM,IAAI,iBAAA,CAAkB,IAAA,EAAM,MAAA,CAAO,KAAA,CAAM,QAAQ,UAAU,CAAA;AAAA,IACnE;AAGA,IAAA,MAAM,OAAA,GAAU,IAAA,CAAK,SAAA,CAAU,UAAU,CAAA;AACzC,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,MAAA,GAAS,GAAA,GAAM,CAAA,EAAG,QAAQ,KAAA,CAAM,CAAA,EAAG,GAAG,CAAC,CAAA,GAAA,CAAA,GAAQ,OAAA;AACzE,IAAA,OAAA,CAAQ,IAAA;AAAA,MACN,CAAA,2BAAA,EAA8B,IAAI,CAAA,EAAA,EAAK,MAAA,CAAO,KAAA,CAAM,OAAO,GAAA,CAAI,CAAC,CAAA,KAAiB,CAAA,EAAG,CAAA,CAAE,IAAA,CAAK,KAAK,GAAG,CAAC,CAAA,EAAA,EAAK,CAAA,CAAE,OAAO,CAAA,CAAE,EAAE,IAAA,CAAK,IAAI,CAAC,CAAA,oCAAA,EAAuC,SAAS,CAAA;AAAA,KAClL;AACA,IAAA,OAAO,UAAA;AAAA,EACT;AAEA,EAAA,OAAO,EAAE,YAAY,YAAA,EAAa;AACpC;;;AC1HA,SAAS,eAAe,KAAA,EAAiC;AACvD,EAAA,OAAO,YAAY,KAAA;AACrB;AAEO,IAAM,eAAN,MAAwD;AAAA,EACrD,KAAA;AAAA,EACA,WAAA;AAAA,EACA,GAAA;AAAA,EACA,kBAAA;AAAA,EACA,mBAAA;AAAA,EAER,WAAA,CAAY,UAAa,OAAA,EAA8B;AACrD,IAAA,IAAA,CAAK,QAAQ,qBAAA,CAAsB,QAAA,EAAU,EAAE,aAAA,EAAe,OAAA,CAAQ,eAAe,CAAA;AACrF,IAAA,IAAI,YAAY,OAAA,EAAS;AACvB,MAAA,IAAA,CAAK,cAAc,OAAA,CAAQ,MAAA;AAAA,IAC7B,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,MAAM,OAAA,CAAQ,GAAA;AACnB,MAAA,IAAI,QAAQ,KAAA,EAAO,IAAA,CAAK,kBAAA,GAAqB,cAAA,CAAe,QAAQ,KAAK,CAAA;AAAA,IAC3E;AAAA,EACF;AAAA,EAEQ,MAAA,GAAiB;AACvB,IAAA,IAAI,IAAA,CAAK,GAAA,EAAK,OAAO,IAAA,CAAK,GAAA;AAC1B,IAAA,MAAM,IAAI,MAAM,gDAAgD,CAAA;AAAA,EAClE;AAAA,EAEQ,SAAA,GAA0B;AAChC,IAAA,IAAI,IAAA,CAAK,WAAA,EAAa,OAAO,IAAA,CAAK,WAAA;AAElC,IAAA,MAAM,MAAA,GAAS,IAAI,YAAA,CAAa,IAAA,CAAK,QAAQ,CAAA;AAC7C,IAAA,IAAI,KAAK,kBAAA,EAAoB;AAC3B,MAAA,MAAA,CAAO,OAAA,CAAQ,IAAA,CAAK,kBAAA,EAAoB,IAAA,CAAK,mBAAmB,CAAA;AAAA,IAClE;AACA,IAAA,IAAA,CAAK,WAAA,GAAc,MAAA;AACnB,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,IAAI,MAAA,GAAuB;AACzB,IAAA,OAAO,KAAK,SAAA,EAAU;AAAA,EACxB;AAAA,EAEA,MAAM,KAAA,CACJ,GAAA,EACA,IAAA,EAC2B;AAC3B,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,SAAA,EAAU,CAAE,KAAA;AAAA,MACxC,GAAA;AAAA,MACA,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,GAAA,EAAK,IAAI;AAAA,KACjC;AACA,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,GAAA,EAAK,UAAU,CAAA;AAAA,EAChD;AAAA,EAEA,MAAM,MAAA,CACJ,GAAA,EACA,IAAA,EACA,OAAA,EAC2B;AAC3B,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,SAAA,EAAU,CAAE,QAAA;AAAA,MACxC,GAAA;AAAA,MACA,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,GAAA,EAAK,IAAI,CAAA;AAAA,MAC/B;AAAA,KACF;AACA,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,GAAA,EAAK,UAAU,CAAA;AAAA,EAChD;AAAA;AAAA,EAGA,QAAA,CACE,GAAA,EACA,IAAA,EACA,OAAA,EAC2B;AAC3B,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,GAAA,EAAK,IAAA,EAAM,OAAO,CAAA;AAAA,EACvC;AAAA,EAEA,MAAM,MAAA,CACJ,GAAA,EACA,IAAA,EAC2B;AAC3B,IAAA,MAAM,UAAA,GAAa,MAAM,IAAA,CAAK,SAAA,EAAU,CAAE,MAAA;AAAA,MACxC,GAAA;AAAA,MACA,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,GAAA,EAAK,IAAI;AAAA,KACjC;AACA,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,GAAA,EAAK,UAAU,CAAA;AAAA,EAChD;AAAA,EAEA,SAAA,CACE,GAAA,EACA,IAAA,EACA,QAAA,EACA,OAAA,EACY;AACZ,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,KAAK,IAAI,CAAA;AAChD,IAAA,OAAO,IAAA,CAAK,WAAU,CAAE,QAAA;AAAA,MACtB,GAAA;AAAA,MACA,QAAA;AAAA,MACA,CAAC,UAAA,KAAsC;AACrC,QAAA,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,GAAA,EAAK,UAAU,CAAC,CAAA;AAAA,MACnD,CAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA;AAAA,EAGA,QAAA,CACE,GAAA,EACA,IAAA,EACA,QAAA,EACA,OAAA,EACY;AACZ,IAAA,OAAO,IAAA,CAAK,SAAA,CAAU,GAAA,EAAK,IAAA,EAAM,UAAU,OAAO,CAAA;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,8BAAA,CACE,GAAA,EACA,IAAA,EACA,OAAA,EACA,UAMA,OAAA,EAC4D;AAC5D,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,KAAK,IAAI,CAAA;AAChD,IAAA,OAAO,IAAA,CAAK,WAAU,CAAE,8BAAA;AAAA,MACtB,GAAA;AAAA,MACA,QAAA;AAAA,MACA,OAAA;AAAA,MACA,CAAC,UAAA,KAAoB;AACnB,QAAA,QAAA,CAAS;AAAA,UACP,GAAG,UAAA;AAAA,UACH,IAAA,EAAM,UAAA,CAAW,IAAA,CAAK,GAAA,CAAI,CAAC,IAAA,KAAc,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,GAAA,EAAK,IAAI,CAAC;AAAA,SAC5E,CAAA;AAAA,MACH,CAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA,EASA,OAAA,CACE,gBACA,QAAA,EACM;AACN,IAAA,MAAM,OAAA,GACJ,OAAO,cAAA,KAAmB,UAAA,GAAa,iBAAiB,YAAY,cAAA;AACtE,IAAA,IAAA,CAAK,kBAAA,GAAqB,OAAA;AAC1B,IAAA,IAAA,CAAK,mBAAA,GAAsB,QAAA;AAC3B,IAAA,IAAI,KAAK,WAAA,EAAa;AACpB,MAAA,IAAA,CAAK,WAAA,CAAY,OAAA,CAAQ,OAAA,EAAS,QAAQ,CAAA;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA,EAGA,OAAA,GAAuE;AACrE,IAAA,OAAO,IAAA,CAAK,SAAA,EAAU,CAAE,OAAA,EAAQ;AAAA,EAClC;AAAA;AAAA,EAGA,IAAI,MAAA,GAAkB;AACpB,IAAA,OAAO,IAAA,CAAK,aAAa,MAAA,IAAU,KAAA;AAAA,EACrC;AAAA;AAAA,EAGA,IAAI,QAAA,GAAoB;AACtB,IAAA,OAAO,IAAA,CAAK,aAAa,QAAA,IAAY,KAAA;AAAA,EACvC;AAAA,EAEA,eAAA,GAAmC;AACjC,IAAA,OAAO,IAAA,CAAK,SAAA,EAAU,CAAE,eAAA,EAAgB;AAAA,EAC1C;AAAA,EAEA,2BAA2B,EAAA,EAAkD;AAC3E,IAAA,OAAO,IAAA,CAAK,SAAA,EAAU,CAAE,0BAAA,CAA2B,EAAE,CAAA;AAAA,EACvD;AAAA,EAEA,MAAM,KAAA,GAAQ;AACZ,IAAA,MAAM,IAAA,CAAK,SAAA,EAAU,CAAE,KAAA,EAAM;AAAA,EAC/B;AACF;AAEO,SAAS,kBAAA,CACd,UACA,OAAA,EACiB;AACjB,EAAA,OAAO,IAAI,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAC3C","file":"index.js","sourcesContent":["import {\n $ZodArray,\n $ZodCodec,\n $ZodDefault,\n $ZodError,\n $ZodNullable,\n $ZodObject,\n $ZodOptional,\n $ZodType,\n encode\n} from './zod-core'\n\n/**\n * Unwraps ZodOptional/ZodNullable/ZodDefault wrappers to get the structural type.\n */\nfunction unwrapOuter(schema: $ZodType): $ZodType {\n let current: $ZodType = schema\n for (let i = 0; i < 10; i++) {\n if (\n current instanceof $ZodOptional ||\n current instanceof $ZodNullable ||\n current instanceof $ZodDefault\n ) {\n current = current._zod.def.innerType\n continue\n }\n break\n }\n return current\n}\n\n/**\n * Walks a path through a schema tree, truncating at codec boundaries.\n * When a codec is encountered, the path is cut — any deeper segments\n * are wire-internal and should not be exposed to consumers.\n */\nfunction truncateAtCodecBoundary(path: (string | number)[], schema: $ZodType): (string | number)[] {\n const result: (string | number)[] = []\n let current: $ZodType = schema\n\n for (const segment of path) {\n current = unwrapOuter(current)\n\n // If we've landed on a codec, everything from here is wire-internal — stop\n if (current instanceof $ZodCodec) {\n break\n }\n\n // Descend into objects\n if (current instanceof $ZodObject && typeof segment === 'string') {\n const fieldSchema = current._zod.def.shape[segment] as $ZodType | undefined\n if (!fieldSchema) {\n // Unknown field — include segment and stop\n result.push(segment)\n break\n }\n\n result.push(segment)\n\n const unwrapped = unwrapOuter(fieldSchema)\n if (unwrapped instanceof $ZodCodec) {\n // Hit a codec boundary — truncate here\n break\n }\n\n current = fieldSchema\n continue\n }\n\n // Descend into arrays\n if (current instanceof $ZodArray && typeof segment === 'number') {\n result.push(segment)\n current = current._zod.def.element\n continue\n }\n\n // For anything else (unions, records, etc.), include segment and continue\n result.push(segment)\n }\n\n return result\n}\n\n/**\n * Normalizes ZodError paths by truncating at codec boundaries.\n *\n * When z.encode() throws a ZodError, the paths reflect the wire schema\n * structure (e.g., [\"email\", \"value\"] for a custom codec).\n * This function strips the wire-internal segments so consumers see\n * clean field-level paths (e.g., [\"email\"]).\n */\nexport function normalizeCodecPaths(error: $ZodError, schema: $ZodType): $ZodError {\n const normalized = error.issues.map(issue => ({\n ...issue,\n path: truncateAtCodecBoundary(issue.path as (string | number)[], schema)\n }))\n return new $ZodError(normalized)\n}\n\n/**\n * Encodes a value through a Zod schema, normalizing codec-internal\n * path segments in any ZodError before re-throwing.\n *\n * Drop-in replacement for `z.encode(schema, value)` at client boundaries.\n */\nexport function safeEncode(schema: $ZodType, value: unknown): unknown {\n try {\n return encode(schema, value)\n } catch (e) {\n if (e instanceof $ZodError) throw normalizeCodecPaths(e as $ZodError, schema)\n throw e\n }\n}\n","/**\n * Recursively strips `undefined` values from objects and arrays.\n * Used by codec encode/decode to clean wire data.\n *\n * Extracted to its own module so client-safe code (boundaryHelpers)\n * can import it without pulling in zod via utils.ts.\n */\nexport function stripUndefined<T>(value: T): T {\n if (value === null || value === undefined) {\n return value\n }\n\n if (Array.isArray(value)) {\n return value.map(stripUndefined) as T\n }\n\n // Only process plain objects (not class instances, Dates, etc.)\n if (typeof value === 'object' && value.constructor === Object) {\n const result: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(value)) {\n if (val !== undefined) {\n result[key] = stripUndefined(val)\n }\n }\n return result as T\n }\n\n return value\n}\n","import type { FunctionReference } from 'convex/server'\nimport type { $ZodIssue } from 'zod/v4/core'\nimport { safeEncode } from './normalizeCodecPaths'\nimport { stripUndefined } from './stripUndefined'\nimport type { AnyRegistry } from './types'\nimport { $ZodError, safeParse } from './zod-core'\n\n/**\n * Resolves a Convex FunctionReference to its string path.\n *\n * Mirrors `getFunctionName` from `convex/server` but without the server import.\n * Reads the well-known `Symbol.for('functionName')` that Convex attaches to all\n * function references — the same symbol used by Convex's own browser client.\n */\nconst functionNameSymbol = Symbol.for('functionName')\n\nfunction resolveFunctionPath(ref: FunctionReference<any, any, any, any>): string | null {\n if (typeof ref === 'string') return ref\n const name = (ref as any)[functionNameSymbol]\n if (!name) return null\n return name\n}\n\n/**\n * Options for codec helper behavior.\n */\nexport type BoundaryHelpersOptions = {\n /**\n * How to handle decode failures (schema validation errors on wire data).\n *\n * - `'warn'` (default): log a console.warn and return raw wire data untransformed.\n * - `'throw'`: throw a ZodvexDecodeError (extends z.ZodError). // zod-ok\n */\n onDecodeError?: 'warn' | 'throw'\n}\n\n/**\n * Decode error with function path and wire data context.\n * Extends $ZodError from zod/v4/core for compatibility with both zod and zod/mini.\n * instanceof $ZodError checks work in both variants.\n */\nexport class ZodvexDecodeError extends $ZodError {\n readonly functionPath: string\n readonly wireData: unknown\n\n constructor(functionPath: string, issues: $ZodIssue[], wireData: unknown) {\n super(issues)\n this.functionPath = functionPath\n this.wireData = wireData\n this.name = 'ZodvexDecodeError'\n }\n}\n\n/**\n * Creates shared encode/decode helpers bound to a zodvex registry.\n *\n * These are the core primitives used by all codec boundary implementations:\n * - `encodeArgs`: runtime types -> wire format (e.g., Date -> timestamp number)\n * - `decodeResult`: wire format -> runtime types (e.g., timestamp number -> Date)\n *\n * Both look up the function reference in the registry to find the appropriate\n * Zod schema, then apply the codec transform. Functions not in the registry\n * (or without the relevant schema) pass through unchanged.\n *\n * @param registry - A map of function paths to `{ args?, returns? }` Zod schemas.\n * Typically generated by zodvex codegen into `_zodvex/api.ts`.\n * @param options - Optional configuration for decode error behavior.\n */\nexport function createBoundaryHelpers(registry: AnyRegistry, options?: BoundaryHelpersOptions) {\n const onDecodeError = options?.onDecodeError ?? 'warn'\n const warnedPaths = new Set<string>()\n\n /**\n * Encode args from runtime types to wire format.\n *\n * Uses `safeEncode` (not raw `z.encode`) to normalize codec-internal\n * error paths in ZodErrors, then strips undefined values for Convex\n * serialization compatibility.\n *\n * Passthrough when:\n * - args is null/undefined\n * - function is not in the registry\n * - registry entry has no args schema\n */\n function encodeArgs(ref: FunctionReference<any, any, any, any>, args: any): any {\n if (args == null) return args\n const path = resolveFunctionPath(ref)\n if (path == null) return args\n const entry = registry[path]\n if (!entry?.args) {\n if (entry === undefined && !warnedPaths.has(path)) {\n warnedPaths.add(path)\n console.debug(\n `[zodvex] No registry entry for \"${path}\" — args will not be codec-encoded. ` +\n 'If this function uses zodvex wrappers, run `zodvex generate` to update the registry.'\n )\n }\n return args\n }\n return stripUndefined(safeEncode(entry.args, args))\n }\n\n /**\n * Decode a wire result back to runtime types.\n *\n * Uses `.safeParse()` to decode. On failure:\n * - 'warn' (default): logs warning, returns raw wireResult\n * - 'throw': throws ZodvexDecodeError (extends z.ZodError) // zod-ok\n *\n * Passthrough when:\n * - function is not in the registry\n * - registry entry has no returns schema\n */\n function decodeResult(ref: FunctionReference<any, any, any, any>, wireResult: any): any {\n const path = resolveFunctionPath(ref)\n if (path == null) return wireResult\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, ConnectionState, MutationOptions } from 'convex/browser'\nimport { ConvexClient } from 'convex/browser'\nimport type { FunctionArgs, FunctionReference, FunctionReturnType } from 'convex/server'\nimport type { BoundaryHelpersOptions } from '../../internal/boundaryHelpers'\nimport { createBoundaryHelpers } from '../../internal/boundaryHelpers'\nimport type { AnyRegistry } from '../../internal/types'\n\nexport type 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 private codec: ReturnType<typeof createBoundaryHelpers>\n private innerClient?: ConvexClient\n private url?: string\n private pendingAuthFetcher?: AuthTokenFetcher\n private pendingAuthOnChange?: (isAuthenticated: boolean) => void\n\n constructor(registry: R, options: ZodvexClientOptions) {\n this.codec = createBoundaryHelpers(registry, { onDecodeError: options.onDecodeError })\n if ('client' in options) {\n this.innerClient = options.client\n } else {\n this.url = options.url\n if (options.token) this.pendingAuthFetcher = tokenToFetcher(options.token)\n }\n }\n\n private getUrl(): string {\n if (this.url) return this.url\n throw new Error('[zodvex] ZodvexClient is missing a Convex URL.')\n }\n\n private getConvex(): ConvexClient {\n if (this.innerClient) return this.innerClient\n\n const client = new ConvexClient(this.getUrl())\n if (this.pendingAuthFetcher) {\n client.setAuth(this.pendingAuthFetcher, this.pendingAuthOnChange)\n }\n this.innerClient = client\n return client\n }\n\n get convex(): ConvexClient {\n return this.getConvex()\n }\n\n async query<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args']\n ): Promise<Q['_returnType']> {\n const wireResult = await this.getConvex().query(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n async mutate<M extends FunctionReference<'mutation', any, any, any>>(\n ref: M,\n args: M['_args'],\n options?: MutationOptions\n ): Promise<M['_returnType']> {\n const wireResult = await this.getConvex().mutation(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<M>,\n options\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n /** Alias for {@link mutate} — matches `ConvexClient.mutation` / `ZodvexReactClient.mutation`. */\n mutation<M extends FunctionReference<'mutation', any, any, any>>(\n ref: M,\n args: M['_args'],\n options?: MutationOptions\n ): Promise<M['_returnType']> {\n return this.mutate(ref, args, options)\n }\n\n async action<A extends FunctionReference<'action', any, any, any>>(\n ref: A,\n args: A['_args']\n ): Promise<A['_returnType']> {\n const wireResult = await this.getConvex().action(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<A>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n subscribe<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args'],\n callback: (result: Q['_returnType']) => void,\n onError?: (e: Error) => void\n ): () => void {\n const wireArgs = this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n return this.getConvex().onUpdate(\n ref,\n wireArgs,\n (wireResult: FunctionReturnType<Q>) => {\n callback(this.codec.decodeResult(ref, wireResult))\n },\n onError\n )\n }\n\n /** Alias for {@link subscribe} — matches `ConvexClient.onUpdate`. */\n onUpdate<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args'],\n callback: (result: Q['_returnType']) => void,\n onError?: (e: Error) => void\n ): () => void {\n return this.subscribe(ref, args, callback, onError)\n }\n\n /**\n * Experimental paginated subscription. Encodes args to wire and decodes each\n * page item through the registry, mirroring {@link subscribe}.\n */\n onPaginatedUpdate_experimental<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args'],\n options: { initialNumItems: number },\n callback: (result: {\n page: Q['_returnType'][]\n isDone: boolean\n continueCursor: string\n [key: string]: unknown\n }) => void,\n onError?: (e: Error) => void\n ): ReturnType<ConvexClient['onPaginatedUpdate_experimental']> {\n const wireArgs = this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n return this.getConvex().onPaginatedUpdate_experimental(\n ref,\n wireArgs,\n options,\n (wireResult: any) => {\n callback({\n ...wireResult,\n page: wireResult.page.map((item: any) => this.codec.decodeResult(ref, item))\n })\n },\n onError\n ) as ReturnType<ConvexClient['onPaginatedUpdate_experimental']>\n }\n\n /**\n * Set the auth token. Accepts either a raw token string (convenience) or a\n * Convex `AuthTokenFetcher` plus optional `onChange` callback (parity with\n * `ConvexClient.setAuth`).\n */\n setAuth(token: string | null): void\n setAuth(fetchToken: AuthTokenFetcher, onChange?: (isAuthenticated: boolean) => void): void\n setAuth(\n tokenOrFetcher: string | null | AuthTokenFetcher,\n onChange?: (isAuthenticated: boolean) => void\n ): void {\n const fetcher: AuthTokenFetcher =\n typeof tokenOrFetcher === 'function' ? tokenOrFetcher : async () => tokenOrFetcher\n this.pendingAuthFetcher = fetcher\n this.pendingAuthOnChange = onChange\n if (this.innerClient) {\n this.innerClient.setAuth(fetcher, onChange)\n }\n }\n\n /** Returns the current auth token and its decoded claims, if authenticated. */\n getAuth(): { token: string; decoded: Record<string, any> } | undefined {\n return this.getConvex().getAuth()\n }\n\n /** Whether this client has been closed. False before the inner client is created. */\n get closed(): boolean {\n return this.innerClient?.closed ?? false\n }\n\n /** Whether this client is disabled. False before the inner client is created. */\n get disabled(): boolean {\n return this.innerClient?.disabled ?? false\n }\n\n connectionState(): ConnectionState {\n return this.getConvex().connectionState()\n }\n\n subscribeToConnectionState(cb: (state: ConnectionState) => void): () => void {\n return this.getConvex().subscribeToConnectionState(cb)\n }\n\n async close() {\n await this.getConvex().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/internal/normalizeCodecPaths.ts","../../src/internal/stripUndefined.ts","../../src/internal/boundaryHelpers.ts","../../src/public/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","/**\n * Recursively strips `undefined` values from objects and arrays.\n * Used by codec encode/decode to clean wire data.\n *\n * Extracted to its own module so client-safe code (boundaryHelpers)\n * can import it without pulling in zod via utils.ts.\n */\nexport function stripUndefined<T>(value: T): T {\n if (value === null || value === undefined) {\n return value\n }\n\n if (Array.isArray(value)) {\n return value.map(stripUndefined) as T\n }\n\n // Only process plain objects (not class instances, Dates, etc.)\n if (typeof value === 'object' && value.constructor === Object) {\n const result: Record<string, unknown> = {}\n for (const [key, val] of Object.entries(value)) {\n if (val !== undefined) {\n result[key] = stripUndefined(val)\n }\n }\n return result as T\n }\n\n return value\n}\n","import type { FunctionReference } from 'convex/server'\nimport type { $ZodIssue } from 'zod/v4/core'\nimport { safeEncode } from './normalizeCodecPaths'\nimport { stripUndefined } from './stripUndefined'\nimport type { AnyRegistry } from './types'\nimport { $ZodError, safeParse } from './zod-core'\n\n/**\n * Resolves a Convex FunctionReference to its string path.\n *\n * Mirrors `getFunctionName` from `convex/server` but without the server import.\n * Reads the well-known `Symbol.for('functionName')` that Convex attaches to all\n * function references — the same symbol used by Convex's own browser client.\n */\nconst functionNameSymbol = Symbol.for('functionName')\n\nfunction resolveFunctionPath(ref: FunctionReference<any, any, any, any>): string | null {\n if (typeof ref === 'string') return ref\n const name = (ref as any)[functionNameSymbol]\n if (!name) return null\n return name\n}\n\n/**\n * Options for codec helper behavior.\n */\nexport type BoundaryHelpersOptions = {\n /**\n * How to handle decode failures (schema validation errors on wire data).\n *\n * - `'warn'` (default): log a console.warn and return raw wire data untransformed.\n * - `'throw'`: throw a ZodvexDecodeError (extends z.ZodError). // zod-ok\n */\n onDecodeError?: 'warn' | 'throw'\n}\n\n/**\n * Decode error with function path and wire data context.\n * Extends $ZodError from zod/v4/core for compatibility with both zod and zod/mini.\n * instanceof $ZodError checks work in both variants.\n */\nexport class ZodvexDecodeError extends $ZodError {\n readonly functionPath: string\n readonly wireData: unknown\n\n constructor(functionPath: string, issues: $ZodIssue[], wireData: unknown) {\n super(issues)\n this.functionPath = functionPath\n this.wireData = wireData\n this.name = 'ZodvexDecodeError'\n }\n}\n\n/**\n * Creates shared encode/decode helpers bound to a zodvex registry.\n *\n * These are the core primitives used by all codec boundary implementations:\n * - `encodeArgs`: runtime types -> wire format (e.g., Date -> timestamp number)\n * - `decodeResult`: wire format -> runtime types (e.g., timestamp number -> Date)\n *\n * Both look up the function reference in the registry to find the appropriate\n * Zod schema, then apply the codec transform. Functions not in the registry\n * (or without the relevant schema) pass through unchanged.\n *\n * @param registry - A map of function paths to `{ args?, returns? }` Zod schemas.\n * Typically generated by zodvex codegen into `_zodvex/api.ts`.\n * @param options - Optional configuration for decode error behavior.\n */\n/**\n * Module-scoped so the registry-miss note fires once per path per process.\n * A per-helpers set resets on every Convex invocation (ctx is wrapped per\n * call), which spammed hot paths on every request (#101).\n */\nconst warnedPaths = new Set<string>()\n\n/** @internal Test-only: clears the process-wide registry-miss dedup set. */\nexport function __resetRegistryMissWarnings(): void {\n warnedPaths.clear()\n}\n\nexport function createBoundaryHelpers(registry: AnyRegistry, options?: BoundaryHelpersOptions) {\n const onDecodeError = options?.onDecodeError ?? 'warn'\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 if (path == null) return args\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/returns pass through unencoded. ` +\n 'This is expected when the target is a raw (non-zodvex) function; if it should be ' +\n 'codec-aware, run `zodvex generate` to update the registry.'\n )\n }\n return args\n }\n return stripUndefined(safeEncode(entry.args, args))\n }\n\n /**\n * Decode a wire result back to runtime types.\n *\n * Uses `.safeParse()` to decode. On failure:\n * - 'warn' (default): logs warning, returns raw wireResult\n * - 'throw': throws ZodvexDecodeError (extends z.ZodError) // zod-ok\n *\n * Passthrough when:\n * - function is not in the registry\n * - registry entry has no returns schema\n */\n function decodeResult(ref: FunctionReference<any, any, any, any>, wireResult: any): any {\n const path = resolveFunctionPath(ref)\n if (path == null) return wireResult\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, ConnectionState, MutationOptions } from 'convex/browser'\nimport { ConvexClient } from 'convex/browser'\nimport type { FunctionArgs, FunctionReference, FunctionReturnType } from 'convex/server'\nimport type { BoundaryHelpersOptions } from '../../internal/boundaryHelpers'\nimport { createBoundaryHelpers } from '../../internal/boundaryHelpers'\nimport type { AnyRegistry } from '../../internal/types'\n\nexport type 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 private codec: ReturnType<typeof createBoundaryHelpers>\n private innerClient?: ConvexClient\n private url?: string\n private pendingAuthFetcher?: AuthTokenFetcher\n private pendingAuthOnChange?: (isAuthenticated: boolean) => void\n\n constructor(registry: R, options: ZodvexClientOptions) {\n this.codec = createBoundaryHelpers(registry, { onDecodeError: options.onDecodeError })\n if ('client' in options) {\n this.innerClient = options.client\n } else {\n this.url = options.url\n if (options.token) this.pendingAuthFetcher = tokenToFetcher(options.token)\n }\n }\n\n private getUrl(): string {\n if (this.url) return this.url\n throw new Error('[zodvex] ZodvexClient is missing a Convex URL.')\n }\n\n private getConvex(): ConvexClient {\n if (this.innerClient) return this.innerClient\n\n const client = new ConvexClient(this.getUrl())\n if (this.pendingAuthFetcher) {\n client.setAuth(this.pendingAuthFetcher, this.pendingAuthOnChange)\n }\n this.innerClient = client\n return client\n }\n\n get convex(): ConvexClient {\n return this.getConvex()\n }\n\n async query<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args']\n ): Promise<Q['_returnType']> {\n const wireResult = await this.getConvex().query(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n async mutate<M extends FunctionReference<'mutation', any, any, any>>(\n ref: M,\n args: M['_args'],\n options?: MutationOptions\n ): Promise<M['_returnType']> {\n const wireResult = await this.getConvex().mutation(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<M>,\n options\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n /** Alias for {@link mutate} — matches `ConvexClient.mutation` / `ZodvexReactClient.mutation`. */\n mutation<M extends FunctionReference<'mutation', any, any, any>>(\n ref: M,\n args: M['_args'],\n options?: MutationOptions\n ): Promise<M['_returnType']> {\n return this.mutate(ref, args, options)\n }\n\n async action<A extends FunctionReference<'action', any, any, any>>(\n ref: A,\n args: A['_args']\n ): Promise<A['_returnType']> {\n const wireResult = await this.getConvex().action(\n ref,\n this.codec.encodeArgs(ref, args) as FunctionArgs<A>\n )\n return this.codec.decodeResult(ref, wireResult)\n }\n\n subscribe<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args'],\n callback: (result: Q['_returnType']) => void,\n onError?: (e: Error) => void\n ): () => void {\n const wireArgs = this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n return this.getConvex().onUpdate(\n ref,\n wireArgs,\n (wireResult: FunctionReturnType<Q>) => {\n callback(this.codec.decodeResult(ref, wireResult))\n },\n onError\n )\n }\n\n /** Alias for {@link subscribe} — matches `ConvexClient.onUpdate`. */\n onUpdate<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args'],\n callback: (result: Q['_returnType']) => void,\n onError?: (e: Error) => void\n ): () => void {\n return this.subscribe(ref, args, callback, onError)\n }\n\n /**\n * Experimental paginated subscription. Encodes args to wire and decodes each\n * page item through the registry, mirroring {@link subscribe}.\n */\n onPaginatedUpdate_experimental<Q extends FunctionReference<'query', any, any, any>>(\n ref: Q,\n args: Q['_args'],\n options: { initialNumItems: number },\n callback: (result: {\n page: Q['_returnType'][]\n isDone: boolean\n continueCursor: string\n [key: string]: unknown\n }) => void,\n onError?: (e: Error) => void\n ): ReturnType<ConvexClient['onPaginatedUpdate_experimental']> {\n const wireArgs = this.codec.encodeArgs(ref, args) as FunctionArgs<Q>\n return this.getConvex().onPaginatedUpdate_experimental(\n ref,\n wireArgs,\n options,\n (wireResult: any) => {\n callback({\n ...wireResult,\n page: wireResult.page.map((item: any) => this.codec.decodeResult(ref, item))\n })\n },\n onError\n ) as ReturnType<ConvexClient['onPaginatedUpdate_experimental']>\n }\n\n /**\n * Set the auth token. Accepts either a raw token string (convenience) or a\n * Convex `AuthTokenFetcher` plus optional `onChange` callback (parity with\n * `ConvexClient.setAuth`).\n */\n setAuth(token: string | null): void\n setAuth(fetchToken: AuthTokenFetcher, onChange?: (isAuthenticated: boolean) => void): void\n setAuth(\n tokenOrFetcher: string | null | AuthTokenFetcher,\n onChange?: (isAuthenticated: boolean) => void\n ): void {\n const fetcher: AuthTokenFetcher =\n typeof tokenOrFetcher === 'function' ? tokenOrFetcher : async () => tokenOrFetcher\n this.pendingAuthFetcher = fetcher\n this.pendingAuthOnChange = onChange\n if (this.innerClient) {\n this.innerClient.setAuth(fetcher, onChange)\n }\n }\n\n /** Returns the current auth token and its decoded claims, if authenticated. */\n getAuth(): { token: string; decoded: Record<string, any> } | undefined {\n return this.getConvex().getAuth()\n }\n\n /** Whether this client has been closed. False before the inner client is created. */\n get closed(): boolean {\n return this.innerClient?.closed ?? false\n }\n\n /** Whether this client is disabled. False before the inner client is created. */\n get disabled(): boolean {\n return this.innerClient?.disabled ?? false\n }\n\n connectionState(): ConnectionState {\n return this.getConvex().connectionState()\n }\n\n subscribeToConnectionState(cb: (state: ConnectionState) => void): () => void {\n return this.getConvex().subscribeToConnectionState(cb)\n }\n\n async close() {\n await this.getConvex().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/codegen/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import path2 from 'path';
|
|
2
2
|
import { globSync } from 'tinyglobby';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { $ZodCodec, $
|
|
4
|
+
import { $ZodCodec, $ZodOptional, $ZodNullable, $ZodString, $ZodNumber, $ZodBoolean, $ZodNull, $ZodUndefined, $ZodAny, $ZodObject, $ZodArray, $ZodEnum, $ZodLiteral, $ZodUnion, $ZodTuple, $ZodRecord, $ZodType, clone, $ZodDiscriminatedUnion } from 'zod/v4/core';
|
|
5
5
|
import 'convex/values';
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
|
|
@@ -45,18 +45,34 @@ function zodvexCodec(wire, runtime, transforms) {
|
|
|
45
45
|
return z.codec(wire, runtime, transforms);
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
// src/internal/zxDateBrand.ts
|
|
49
|
+
var ZX_DATE_BRAND = /* @__PURE__ */ Symbol.for("zodvex.zxDate");
|
|
50
|
+
function brandZxDate(codec2) {
|
|
51
|
+
codec2[ZX_DATE_BRAND] = true;
|
|
52
|
+
const def = codec2._zod?.def;
|
|
53
|
+
if (def) def[ZX_DATE_BRAND] = true;
|
|
54
|
+
return codec2;
|
|
55
|
+
}
|
|
56
|
+
function isZxDateCodec(schema) {
|
|
57
|
+
if (!schema || typeof schema !== "object") return false;
|
|
58
|
+
const s = schema;
|
|
59
|
+
return s[ZX_DATE_BRAND] === true || s._zod?.def?.[ZX_DATE_BRAND] === true;
|
|
60
|
+
}
|
|
61
|
+
|
|
48
62
|
// src/internal/zx.ts
|
|
49
63
|
function date() {
|
|
50
|
-
return
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
return brandZxDate(
|
|
65
|
+
zodvexCodec(
|
|
66
|
+
z.number(),
|
|
67
|
+
// Wire: timestamp
|
|
68
|
+
z.custom((val) => val instanceof Date, {
|
|
69
|
+
message: "Expected Date instance"
|
|
70
|
+
}),
|
|
71
|
+
{
|
|
72
|
+
decode: (timestamp) => new Date(timestamp),
|
|
73
|
+
encode: (date2) => date2.getTime()
|
|
74
|
+
}
|
|
75
|
+
)
|
|
60
76
|
);
|
|
61
77
|
}
|
|
62
78
|
function id(tableName) {
|
|
@@ -295,9 +311,35 @@ function createSchemaUpdateSchema(name, inputSchema) {
|
|
|
295
311
|
}
|
|
296
312
|
return inputSchema;
|
|
297
313
|
}
|
|
298
|
-
|
|
314
|
+
function buildHooksSource(aliases) {
|
|
315
|
+
return `
|
|
316
|
+
import { pathToFileURL } from 'node:url';
|
|
317
|
+
|
|
299
318
|
const EXT_CANDIDATES = ['.ts', '.tsx', '.mts', '.js', '.mjs', '.jsx', '/index.ts', '/index.js'];
|
|
300
319
|
|
|
320
|
+
// tsconfig path aliases compiled by loadTsconfigAliases (#99). Bun resolves
|
|
321
|
+
// these natively; Node's ESM loader needs them replayed here.
|
|
322
|
+
const ALIASES = ${JSON.stringify(aliases)};
|
|
323
|
+
|
|
324
|
+
function aliasCandidates(specifier) {
|
|
325
|
+
const out = [];
|
|
326
|
+
for (const a of ALIASES) {
|
|
327
|
+
if (a.star) {
|
|
328
|
+
if (
|
|
329
|
+
specifier.length >= a.prefix.length + a.suffix.length &&
|
|
330
|
+
specifier.startsWith(a.prefix) &&
|
|
331
|
+
specifier.endsWith(a.suffix)
|
|
332
|
+
) {
|
|
333
|
+
const captured = specifier.slice(a.prefix.length, specifier.length - a.suffix.length);
|
|
334
|
+
for (const t of a.targets) out.push(t.prefix + captured + t.suffix);
|
|
335
|
+
}
|
|
336
|
+
} else if (specifier === a.prefix) {
|
|
337
|
+
for (const t of a.targets) out.push(t.prefix);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return out;
|
|
341
|
+
}
|
|
342
|
+
|
|
301
343
|
export async function resolve(specifier, context, nextResolve) {
|
|
302
344
|
if (/_generated\\/api(\\.[mc]?[jt]sx?)?$/.test(specifier)) {
|
|
303
345
|
return { shortCircuit: true, url: 'zodvex-stub://api' };
|
|
@@ -305,6 +347,15 @@ export async function resolve(specifier, context, nextResolve) {
|
|
|
305
347
|
try {
|
|
306
348
|
return await nextResolve(specifier, context);
|
|
307
349
|
} catch (err) {
|
|
350
|
+
// tsconfig path aliases (e.g. '@/convex/...'). Try each mapped absolute
|
|
351
|
+
// path as-is, then with the usual extension/index candidates.
|
|
352
|
+
for (const base of aliasCandidates(specifier)) {
|
|
353
|
+
for (const ext of ['', ...EXT_CANDIDATES]) {
|
|
354
|
+
try {
|
|
355
|
+
return await nextResolve(pathToFileURL(base + ext).href, context);
|
|
356
|
+
} catch {}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
308
359
|
// Convex code uses extensionless relative imports (bundler resolution).
|
|
309
360
|
// Bun resolves those natively; Node's ESM loader does not \u2014 retry with
|
|
310
361
|
// the usual extension candidates before giving up.
|
|
@@ -349,8 +400,9 @@ export function load(url, context, nextLoad) {
|
|
|
349
400
|
return nextLoad(url, context);
|
|
350
401
|
}
|
|
351
402
|
`;
|
|
403
|
+
}
|
|
352
404
|
var hooksRegistered = false;
|
|
353
|
-
function registerDiscoveryHooks() {
|
|
405
|
+
function registerDiscoveryHooks(aliases = []) {
|
|
354
406
|
if (hooksRegistered) return true;
|
|
355
407
|
try {
|
|
356
408
|
const nodeModule = typeof process.getBuiltinModule === "function" ? process.getBuiltinModule("node:module") : (
|
|
@@ -359,7 +411,7 @@ function registerDiscoveryHooks() {
|
|
|
359
411
|
);
|
|
360
412
|
const { register } = nodeModule;
|
|
361
413
|
if (typeof register !== "function") return false;
|
|
362
|
-
register(`data:text/javascript,${encodeURIComponent(
|
|
414
|
+
register(`data:text/javascript,${encodeURIComponent(buildHooksSource(aliases))}`);
|
|
363
415
|
hooksRegistered = true;
|
|
364
416
|
return true;
|
|
365
417
|
} catch {
|
|
@@ -384,8 +436,8 @@ export const components = p;
|
|
|
384
436
|
export const httpRouter = p;
|
|
385
437
|
`;
|
|
386
438
|
function writeGeneratedStubs(convexDir) {
|
|
387
|
-
const generatedDir =
|
|
388
|
-
const apiPath =
|
|
439
|
+
const generatedDir = path2.join(convexDir, "_generated");
|
|
440
|
+
const apiPath = path2.join(generatedDir, "api.ts");
|
|
389
441
|
let original;
|
|
390
442
|
try {
|
|
391
443
|
original = fs.readFileSync(apiPath, "utf8");
|
|
@@ -411,8 +463,7 @@ function findCodec(schema) {
|
|
|
411
463
|
let current = schema;
|
|
412
464
|
for (let i = 0; i < 10; i++) {
|
|
413
465
|
if (current instanceof $ZodCodec) {
|
|
414
|
-
|
|
415
|
-
if (isZxDate) return void 0;
|
|
466
|
+
if (isZxDateCodec(current)) return void 0;
|
|
416
467
|
return current;
|
|
417
468
|
}
|
|
418
469
|
if (current instanceof $ZodOptional || current instanceof $ZodNullable) {
|
|
@@ -444,6 +495,134 @@ function readFnReturns(fn) {
|
|
|
444
495
|
}
|
|
445
496
|
return meta.zodReturns;
|
|
446
497
|
}
|
|
498
|
+
function stripJsonComments(input) {
|
|
499
|
+
let out = "";
|
|
500
|
+
let inString = false;
|
|
501
|
+
let inLine = false;
|
|
502
|
+
let inBlock = false;
|
|
503
|
+
for (let i = 0; i < input.length; i++) {
|
|
504
|
+
const ch = input[i];
|
|
505
|
+
const next = input[i + 1];
|
|
506
|
+
if (inLine) {
|
|
507
|
+
if (ch === "\n") {
|
|
508
|
+
inLine = false;
|
|
509
|
+
out += ch;
|
|
510
|
+
}
|
|
511
|
+
continue;
|
|
512
|
+
}
|
|
513
|
+
if (inBlock) {
|
|
514
|
+
if (ch === "*" && next === "/") {
|
|
515
|
+
inBlock = false;
|
|
516
|
+
i++;
|
|
517
|
+
}
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
if (inString) {
|
|
521
|
+
out += ch;
|
|
522
|
+
if (ch === "\\") {
|
|
523
|
+
out += next ?? "";
|
|
524
|
+
i++;
|
|
525
|
+
} else if (ch === '"') {
|
|
526
|
+
inString = false;
|
|
527
|
+
}
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
if (ch === '"') {
|
|
531
|
+
inString = true;
|
|
532
|
+
out += ch;
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
if (ch === "/" && next === "/") {
|
|
536
|
+
inLine = true;
|
|
537
|
+
i++;
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
if (ch === "/" && next === "*") {
|
|
541
|
+
inBlock = true;
|
|
542
|
+
i++;
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
out += ch;
|
|
546
|
+
}
|
|
547
|
+
return out.replace(/,\s*([}\]])/g, "$1");
|
|
548
|
+
}
|
|
549
|
+
function readTsconfig(configPath) {
|
|
550
|
+
try {
|
|
551
|
+
const raw = fs.readFileSync(configPath, "utf8");
|
|
552
|
+
return JSON.parse(stripJsonComments(raw));
|
|
553
|
+
} catch {
|
|
554
|
+
return null;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
function resolvePathsFromConfig(configPath, seen) {
|
|
558
|
+
const abs = path2.resolve(configPath);
|
|
559
|
+
if (seen.has(abs)) return null;
|
|
560
|
+
seen.add(abs);
|
|
561
|
+
const config = readTsconfig(abs);
|
|
562
|
+
if (!config) return null;
|
|
563
|
+
const dir = path2.dirname(abs);
|
|
564
|
+
const own = config.compilerOptions?.paths;
|
|
565
|
+
if (own) {
|
|
566
|
+
const baseUrl = config.compilerOptions?.baseUrl;
|
|
567
|
+
return { paths: own, baseDir: baseUrl ? path2.resolve(dir, baseUrl) : dir };
|
|
568
|
+
}
|
|
569
|
+
const parents = config.extends == null ? [] : [].concat(config.extends);
|
|
570
|
+
for (const ref of parents) {
|
|
571
|
+
if (!ref.startsWith(".") && !path2.isAbsolute(ref)) continue;
|
|
572
|
+
let target = path2.resolve(dir, ref);
|
|
573
|
+
if (!target.endsWith(".json")) target += ".json";
|
|
574
|
+
const found = resolvePathsFromConfig(target, seen);
|
|
575
|
+
if (found) {
|
|
576
|
+
const childBase = config.compilerOptions?.baseUrl;
|
|
577
|
+
return childBase ? { paths: found.paths, baseDir: path2.resolve(dir, childBase) } : found;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
return null;
|
|
581
|
+
}
|
|
582
|
+
function compileAliases(paths, baseDir) {
|
|
583
|
+
const entries = [];
|
|
584
|
+
for (const [pattern, targets] of Object.entries(paths)) {
|
|
585
|
+
const starIdx = pattern.indexOf("*");
|
|
586
|
+
const star = starIdx !== -1;
|
|
587
|
+
const prefix = star ? pattern.slice(0, starIdx) : pattern;
|
|
588
|
+
const suffix = star ? pattern.slice(starIdx + 1) : "";
|
|
589
|
+
const compiled = targets.map((t) => {
|
|
590
|
+
const tStar = t.indexOf("*");
|
|
591
|
+
const tPrefix = path2.resolve(baseDir, tStar === -1 ? t : t.slice(0, tStar));
|
|
592
|
+
const sep = tStar !== -1 && t.slice(0, tStar).endsWith("/") ? path2.sep : "";
|
|
593
|
+
return {
|
|
594
|
+
prefix: tPrefix + sep,
|
|
595
|
+
suffix: tStar === -1 ? "" : t.slice(tStar + 1)
|
|
596
|
+
};
|
|
597
|
+
});
|
|
598
|
+
entries.push({ prefix, suffix, star, targets: compiled });
|
|
599
|
+
}
|
|
600
|
+
return entries;
|
|
601
|
+
}
|
|
602
|
+
function loadTsconfigAliases(convexDir) {
|
|
603
|
+
const entries = [];
|
|
604
|
+
const seenPatterns = /* @__PURE__ */ new Set();
|
|
605
|
+
let dir = path2.resolve(convexDir);
|
|
606
|
+
for (let depth = 0; depth < 10; depth++) {
|
|
607
|
+
const configPath = path2.join(dir, "tsconfig.json");
|
|
608
|
+
if (fs.existsSync(configPath)) {
|
|
609
|
+
const found = resolvePathsFromConfig(configPath, /* @__PURE__ */ new Set());
|
|
610
|
+
if (found) {
|
|
611
|
+
for (const entry of compileAliases(found.paths, found.baseDir)) {
|
|
612
|
+
const key = `${entry.prefix}*${entry.suffix}`;
|
|
613
|
+
if (!seenPatterns.has(key)) {
|
|
614
|
+
seenPatterns.add(key);
|
|
615
|
+
entries.push(entry);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
const parent = path2.dirname(dir);
|
|
621
|
+
if (parent === dir) break;
|
|
622
|
+
dir = parent;
|
|
623
|
+
}
|
|
624
|
+
return entries;
|
|
625
|
+
}
|
|
447
626
|
|
|
448
627
|
// src/public/codegen/discover.ts
|
|
449
628
|
function walkSchemaRecursive(schema, accessPath, visited, seenCodecs, results) {
|
|
@@ -587,7 +766,7 @@ async function discoverModules(convexDir) {
|
|
|
587
766
|
const models = [];
|
|
588
767
|
const functions = [];
|
|
589
768
|
const codecs = [];
|
|
590
|
-
registerDiscoveryHooks();
|
|
769
|
+
registerDiscoveryHooks(loadTsconfigAliases(convexDir));
|
|
591
770
|
const cleanupStubs = writeGeneratedStubs(convexDir);
|
|
592
771
|
const files = globSync(["**/*.{ts,js}"], {
|
|
593
772
|
cwd: convexDir,
|
|
@@ -607,15 +786,15 @@ async function discoverModules(convexDir) {
|
|
|
607
786
|
"crons.js"
|
|
608
787
|
]
|
|
609
788
|
}).sort();
|
|
610
|
-
|
|
789
|
+
const failedImports = [];
|
|
611
790
|
try {
|
|
612
791
|
for (const file of files) {
|
|
613
|
-
const absPath =
|
|
792
|
+
const absPath = path2.resolve(convexDir, file);
|
|
614
793
|
let moduleExports;
|
|
615
794
|
try {
|
|
616
795
|
moduleExports = await import(absPath);
|
|
617
796
|
} catch (err) {
|
|
618
|
-
|
|
797
|
+
failedImports.push({ file, message: err.message });
|
|
619
798
|
console.warn(`[zodvex] Warning: Failed to import ${file}:`, err.message);
|
|
620
799
|
continue;
|
|
621
800
|
}
|
|
@@ -659,8 +838,7 @@ async function discoverModules(convexDir) {
|
|
|
659
838
|
}
|
|
660
839
|
}
|
|
661
840
|
if (value instanceof $ZodCodec) {
|
|
662
|
-
|
|
663
|
-
if (!isZxDate) {
|
|
841
|
+
if (!isZxDateCodec(value)) {
|
|
664
842
|
if (!codecs.some((c) => c.schema === value)) {
|
|
665
843
|
codecs.push({
|
|
666
844
|
exportName,
|
|
@@ -683,9 +861,14 @@ async function discoverModules(convexDir) {
|
|
|
683
861
|
modelCodecs.push(...found);
|
|
684
862
|
}
|
|
685
863
|
const functionCodecs = walkFunctionCodecs(functions);
|
|
686
|
-
if (
|
|
864
|
+
if (failedImports.length > 0 && !process.env.ZODVEX_ALLOW_IMPORT_FAILURES) {
|
|
865
|
+
const shown = failedImports.slice(0, 10).map((f) => ` - ${f.file}: ${f.message}`).join("\n");
|
|
866
|
+
const more = failedImports.length > 10 ? `
|
|
867
|
+
\u2026 and ${failedImports.length - 10} more` : "";
|
|
687
868
|
throw new Error(
|
|
688
|
-
`[zodvex]
|
|
869
|
+
`[zodvex] ${failedImports.length} module(s) failed to import during discovery \u2014 the generated registry would be incomplete:
|
|
870
|
+
${shown}${more}
|
|
871
|
+
Common causes: Node < 22.18 (no native TypeScript type stripping \u2014 use Bun or upgrade Node), or an import style the discovery resolver does not handle. tsconfig path aliases and extensionless relative imports are supported. Set ZODVEX_ALLOW_IMPORT_FAILURES=1 to generate anyway (skipping the failed modules).`
|
|
689
872
|
);
|
|
690
873
|
}
|
|
691
874
|
return { models, functions, codecs, modelCodecs, functionCodecs };
|
|
@@ -710,7 +893,7 @@ function zodToSource(schema, ctx) {
|
|
|
710
893
|
return `zx.id("${tableName}")`;
|
|
711
894
|
}
|
|
712
895
|
}
|
|
713
|
-
if (schema instanceof $ZodCodec && schema
|
|
896
|
+
if (schema instanceof $ZodCodec && isZxDateCodec(schema)) {
|
|
714
897
|
return "zx.date()";
|
|
715
898
|
}
|
|
716
899
|
if (schema instanceof $ZodCodec) {
|