@pajecawav/json2code 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +178 -2
  3. package/dist/cli.d.mts +1 -0
  4. package/dist/cli.mjs +126 -0
  5. package/dist/cli.mjs.map +1 -0
  6. package/dist/core/config.mjs +53 -0
  7. package/dist/core/config.mjs.map +1 -0
  8. package/dist/core/discovery/index.d.mts +10 -0
  9. package/dist/core/discovery/index.d.mts.map +1 -0
  10. package/dist/core/discovery/index.mjs +83 -0
  11. package/dist/core/discovery/index.mjs.map +1 -0
  12. package/dist/core/generate.d.mts +11 -0
  13. package/dist/core/generate.d.mts.map +1 -0
  14. package/dist/core/generate.mjs +89 -0
  15. package/dist/core/generate.mjs.map +1 -0
  16. package/dist/core/ir/types.d.mts +100 -0
  17. package/dist/core/ir/types.d.mts.map +1 -0
  18. package/dist/core/ir/visit.d.mts +8 -0
  19. package/dist/core/ir/visit.d.mts.map +1 -0
  20. package/dist/core/ir/visit.mjs +38 -0
  21. package/dist/core/ir/visit.mjs.map +1 -0
  22. package/dist/core/linker/index.d.mts +32 -0
  23. package/dist/core/linker/index.d.mts.map +1 -0
  24. package/dist/core/linker/index.mjs +103 -0
  25. package/dist/core/linker/index.mjs.map +1 -0
  26. package/dist/core/printer/abstract.d.mts +26 -0
  27. package/dist/core/printer/abstract.d.mts.map +1 -0
  28. package/dist/core/types.d.mts +74 -0
  29. package/dist/core/types.d.mts.map +1 -0
  30. package/dist/core/types.mjs +27 -0
  31. package/dist/core/types.mjs.map +1 -0
  32. package/dist/core/walker/abstract.d.mts +18 -0
  33. package/dist/core/walker/abstract.d.mts.map +1 -0
  34. package/dist/core/walker/json-schema.d.mts +10 -0
  35. package/dist/core/walker/json-schema.d.mts.map +1 -0
  36. package/dist/core/walker/json-schema.mjs +311 -0
  37. package/dist/core/walker/json-schema.mjs.map +1 -0
  38. package/dist/core/walker/ref-resolver.d.mts +22 -0
  39. package/dist/core/walker/ref-resolver.d.mts.map +1 -0
  40. package/dist/core/walker/ref-resolver.mjs +66 -0
  41. package/dist/core/walker/ref-resolver.mjs.map +1 -0
  42. package/dist/core/writer/index.d.mts +19 -0
  43. package/dist/core/writer/index.d.mts.map +1 -0
  44. package/dist/core/writer/index.mjs +84 -0
  45. package/dist/core/writer/index.mjs.map +1 -0
  46. package/dist/diagnostics/errors.d.mts +39 -0
  47. package/dist/diagnostics/errors.d.mts.map +1 -0
  48. package/dist/diagnostics/errors.mjs +50 -0
  49. package/dist/diagnostics/errors.mjs.map +1 -0
  50. package/dist/diagnostics/logger.d.mts +10 -0
  51. package/dist/diagnostics/logger.d.mts.map +1 -0
  52. package/dist/diagnostics/logger.mjs +18 -0
  53. package/dist/diagnostics/logger.mjs.map +1 -0
  54. package/dist/index.d.mts +24 -0
  55. package/dist/index.d.mts.map +1 -0
  56. package/dist/index.mjs +26 -0
  57. package/dist/index.mjs.map +1 -0
  58. package/dist/package.mjs +6 -0
  59. package/dist/package.mjs.map +1 -0
  60. package/dist/targets/index.d.mts +9 -0
  61. package/dist/targets/index.d.mts.map +1 -0
  62. package/dist/targets/index.mjs +30 -0
  63. package/dist/targets/index.mjs.map +1 -0
  64. package/dist/targets/shared.mjs +137 -0
  65. package/dist/targets/shared.mjs.map +1 -0
  66. package/dist/targets/typescript/printer.d.mts +13 -0
  67. package/dist/targets/typescript/printer.d.mts.map +1 -0
  68. package/dist/targets/typescript/printer.mjs +47 -0
  69. package/dist/targets/typescript/printer.mjs.map +1 -0
  70. package/dist/targets/valibot/printer.d.mts +21 -0
  71. package/dist/targets/valibot/printer.d.mts.map +1 -0
  72. package/dist/targets/valibot/printer.mjs +198 -0
  73. package/dist/targets/valibot/printer.mjs.map +1 -0
  74. package/dist/targets/zod/lazy.d.mts +29 -0
  75. package/dist/targets/zod/lazy.d.mts.map +1 -0
  76. package/dist/targets/zod/lazy.mjs +100 -0
  77. package/dist/targets/zod/lazy.mjs.map +1 -0
  78. package/dist/targets/zod/printer.d.mts +21 -0
  79. package/dist/targets/zod/printer.d.mts.map +1 -0
  80. package/dist/targets/zod/printer.mjs +193 -0
  81. package/dist/targets/zod/printer.mjs.map +1 -0
  82. package/package.json +71 -3
@@ -0,0 +1,198 @@
1
+ import { DiagnosticCode, createDiagnostic } from "../../diagnostics/errors.mjs";
2
+ import { collectImports, defaultMatches, literal, quoteKey, regexLiteral, renderTsType } from "../shared.mjs";
3
+ import { buildLazyGraph, nodeId } from "../zod/lazy.mjs";
4
+ //#region src/targets/valibot/printer.ts
5
+ /** Generates valibot v1 schemas from IR documents. */
6
+ var ValibotPrinter = class {
7
+ name = "valibot";
8
+ async print(docs, ctx) {
9
+ const byId = new Map(docs.map((d) => [d.docId, d]));
10
+ const graph = buildLazyGraph(docs);
11
+ const files = [];
12
+ for (const doc of docs) files.push({
13
+ path: ctx.outputPath(doc.docId),
14
+ content: this.printDoc(doc, ctx, byId, graph)
15
+ });
16
+ return files;
17
+ }
18
+ printDoc(doc, ctx, byId, graph) {
19
+ const imports = collectImports(doc, ctx, byId);
20
+ const warnings = [];
21
+ const r = {
22
+ ctx,
23
+ byId,
24
+ graph,
25
+ warnings
26
+ };
27
+ const lines = [];
28
+ lines.push(`import * as v from ${JSON.stringify(ctx.options.importPaths.valibot ?? "valibot")};`);
29
+ const sorted = [...imports.entries()].toSorted(([a], [b]) => a.localeCompare(b));
30
+ for (const [, info] of sorted) lines.push(`import { ${[...info.names].toSorted().join(", ")} } from ${JSON.stringify(info.path)};`);
31
+ lines.push("");
32
+ for (const name of doc.exportOrder) {
33
+ const ir = doc.exports.get(name);
34
+ if (!ir) continue;
35
+ const exportName = ctx.resolveExportName(doc, name);
36
+ const cyclic = graph.isCyclic(nodeId(doc.docId, name));
37
+ if (cyclic) {
38
+ const aliasRef = (ref) => this.aliasRefExpr(ref, doc, r);
39
+ lines.push(`export type ${exportName} = ${renderTsType(ir, aliasRef, { readonlyArrays: false })};`);
40
+ lines.push("");
41
+ }
42
+ if (ir.meta?.deprecated) lines.push("/** @deprecated */");
43
+ const annotation = cyclic ? `: v.GenericSchema<unknown, ${exportName}>` : "";
44
+ lines.push(`export const ${exportName}${annotation} = ${this.exprOf(ir, doc, name, r)};`);
45
+ if (!cyclic) lines.push(`export type ${exportName} = v.InferOutput<typeof ${exportName}>;`);
46
+ lines.push("");
47
+ }
48
+ for (const warning of warnings) ctx.diagnostics.push(createDiagnostic(DiagnosticCode.UnknownKeyword, "warning", warning, { docId: doc.docId }));
49
+ return `${lines.join("\n").trimEnd()}\n`;
50
+ }
51
+ exprOf(ir, doc, name, r) {
52
+ let base;
53
+ switch (ir.kind) {
54
+ case "ref":
55
+ base = this.refExpr(ir.ref, doc, name, r);
56
+ break;
57
+ case "string":
58
+ base = this.stringExpr(ir);
59
+ break;
60
+ case "integer":
61
+ case "number":
62
+ base = this.numberExpr(ir);
63
+ break;
64
+ case "boolean":
65
+ base = ir.const !== void 0 ? `v.literal(${ir.const})` : "v.boolean()";
66
+ break;
67
+ case "null":
68
+ base = "v.null()";
69
+ break;
70
+ case "literal":
71
+ base = `v.literal(${literal(ir.value)})`;
72
+ break;
73
+ case "array":
74
+ base = this.arrayExpr(ir, doc, name, r);
75
+ break;
76
+ case "tuple":
77
+ base = this.tupleExpr(ir, doc, name, r);
78
+ break;
79
+ case "object":
80
+ base = this.objectExpr(ir, doc, name, r);
81
+ break;
82
+ case "record":
83
+ base = `v.record(v.string(), ${this.exprOf(ir.values, doc, name, r)})`;
84
+ break;
85
+ case "union":
86
+ if (ir.variants.length === 0) base = "v.never()";
87
+ else if (ir.variants.length === 1) {
88
+ const single = ir.variants[0];
89
+ base = single ? this.exprOf(single, doc, name, r) : "v.never()";
90
+ } else base = `v.union([${ir.variants.map((x) => this.exprOf(x, doc, name, r)).join(", ")}])`;
91
+ break;
92
+ case "intersection":
93
+ if (ir.variants.length === 0) base = "v.unknown()";
94
+ else if (ir.variants.length === 1) {
95
+ const single = ir.variants[0];
96
+ base = single ? this.exprOf(single, doc, name, r) : "v.unknown()";
97
+ } else base = `v.intersect([${ir.variants.map((x) => this.exprOf(x, doc, name, r)).join(", ")}])`;
98
+ break;
99
+ case "unknown": base = "v.unknown()";
100
+ }
101
+ if (ir.meta?.description) base = `v.pipe(${base}, v.description(${JSON.stringify(ir.meta.description)}))`;
102
+ return base;
103
+ }
104
+ refExpr(ref, doc, name, r) {
105
+ const target = r.byId.get(ref.docId);
106
+ const exportName = target ? r.ctx.resolveExportName(target, ref.exportName) : ref.exportName;
107
+ if (r.graph.needsLazy(nodeId(doc.docId, name), nodeId(ref.docId, ref.exportName))) return `v.lazy(() => ${exportName})`;
108
+ return exportName;
109
+ }
110
+ /** Ref renderer for structural aliases of cyclic exports. */
111
+ aliasRefExpr(ref, doc, r) {
112
+ if (ref.docId === doc.docId) {
113
+ if (!doc.exports.has(ref.exportName)) return "unknown";
114
+ const resolved = r.ctx.resolveExportName(doc, ref.exportName);
115
+ if (r.graph.isCyclic(nodeId(doc.docId, ref.exportName))) return resolved;
116
+ return `v.InferOutput<typeof ${resolved}>`;
117
+ }
118
+ const target = r.byId.get(ref.docId);
119
+ if (!target) return "unknown";
120
+ const exportName = r.ctx.resolveExportName(target, ref.exportName);
121
+ if (r.graph.isCyclic(nodeId(ref.docId, ref.exportName))) return exportName;
122
+ return `v.InferOutput<typeof ${exportName}>`;
123
+ }
124
+ stringExpr(ir) {
125
+ if (ir.const !== void 0) return `v.literal(${JSON.stringify(ir.const)})`;
126
+ if (ir.enum) {
127
+ if (ir.enum.length === 0) return "v.string()";
128
+ return `v.picklist([${ir.enum.map((x) => JSON.stringify(x)).join(", ")}])`;
129
+ }
130
+ const actions = [];
131
+ const format = stringFormatAction(ir.format);
132
+ if (format) actions.push(format);
133
+ if (ir.minLength !== void 0) actions.push(`v.minLength(${ir.minLength})`);
134
+ if (ir.maxLength !== void 0) actions.push(`v.maxLength(${ir.maxLength})`);
135
+ if (ir.pattern !== void 0) actions.push(`v.regex(${regexLiteral(ir.pattern)})`);
136
+ if (actions.length === 0) return "v.string()";
137
+ return `v.pipe(v.string(), ${actions.join(", ")})`;
138
+ }
139
+ numberExpr(ir) {
140
+ if (ir.const !== void 0) return `v.literal(${ir.const})`;
141
+ if (ir.enum) {
142
+ if (ir.enum.length === 0) return "v.number()";
143
+ return `v.union([${ir.enum.map((x) => `v.literal(${x})`).join(", ")}])`;
144
+ }
145
+ const actions = [];
146
+ if (ir.kind === "integer") actions.push("v.integer()");
147
+ if (ir.minimum !== void 0) actions.push(`v.minValue(${ir.minimum})`);
148
+ if (ir.maximum !== void 0) actions.push(`v.maxValue(${ir.maximum})`);
149
+ if (ir.exclusiveMinimum !== void 0) actions.push(`v.gtValue(${ir.exclusiveMinimum})`);
150
+ if (ir.exclusiveMaximum !== void 0) actions.push(`v.ltValue(${ir.exclusiveMaximum})`);
151
+ if (ir.multipleOf !== void 0) actions.push(`v.multipleOf(${ir.multipleOf})`);
152
+ if (actions.length === 0) return "v.number()";
153
+ return `v.pipe(v.number(), ${actions.join(", ")})`;
154
+ }
155
+ arrayExpr(ir, doc, name, r) {
156
+ const items = ir.items ? this.exprOf(ir.items, doc, name, r) : "v.unknown()";
157
+ const actions = [];
158
+ if (ir.minItems !== void 0) actions.push(`v.minLength(${ir.minItems})`);
159
+ if (ir.maxItems !== void 0) actions.push(`v.maxLength(${ir.maxItems})`);
160
+ if (ir.uniqueItems === true) r.warnings.push("uniqueItems is not supported by the valibot target and was ignored");
161
+ if (actions.length === 0) return `v.array(${items})`;
162
+ return `v.pipe(v.array(${items}), ${actions.join(", ")})`;
163
+ }
164
+ tupleExpr(ir, doc, name, r) {
165
+ return `v.tupleWithRest([${ir.items.map((i) => this.exprOf(i, doc, name, r)).join(", ")}], ${ir.additionalItems ? this.exprOf(ir.additionalItems, doc, name, r) : "v.never()"})`;
166
+ }
167
+ objectExpr(ir, doc, name, r) {
168
+ const required = new Set(ir.required);
169
+ const parts = [];
170
+ for (const [key, val] of ir.properties) {
171
+ let expr = this.exprOf(val, doc, name, r);
172
+ if (r.ctx.options.defaults && val.meta?.default !== void 0 && defaultMatches(val, val.meta.default)) expr = `v.optional(${expr}, ${JSON.stringify(val.meta?.default)})`;
173
+ else if (!required.has(key)) expr = `v.optional(${expr})`;
174
+ else if (r.ctx.options.defaults && val.meta?.default !== void 0 && !defaultMatches(val, val.meta.default)) r.warnings.push(`default ${JSON.stringify(val.meta.default)} does not match schema type and was ignored`);
175
+ parts.push(`${quoteKey(key)}: ${expr}`);
176
+ }
177
+ const entries = parts.length === 0 ? "{}" : `{ ${parts.join(", ")} }`;
178
+ if (ir.additionalProperties === false) return `v.strictObject(${entries})`;
179
+ if (ir.additionalProperties) return `v.objectWithRest(${entries}, ${this.exprOf(ir.additionalProperties, doc, name, r)})`;
180
+ return `v.object(${entries})`;
181
+ }
182
+ };
183
+ function stringFormatAction(format) {
184
+ switch (format) {
185
+ case "uuid": return "v.uuid()";
186
+ case "email": return "v.email()";
187
+ case "uri":
188
+ case "url": return "v.url()";
189
+ case "date": return "v.isoDate()";
190
+ case "date-time": return "v.isoDateTime()";
191
+ case "time": return "v.isoTime()";
192
+ default: return;
193
+ }
194
+ }
195
+ //#endregion
196
+ export { ValibotPrinter };
197
+
198
+ //# sourceMappingURL=printer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"printer.mjs","names":[],"sources":["../../../src/targets/valibot/printer.ts"],"sourcesContent":["import type { Ref, IRType, SourceDoc } from \"../../core/ir/types.js\";\nimport type { AbstractPrinter, PrintContext } from \"../../core/printer/abstract.js\";\nimport type { PrintedFile } from \"../../core/types.js\";\nimport { createDiagnostic, DiagnosticCode } from \"../../diagnostics/errors.js\";\nimport {\n\tcollectImports,\n\tdefaultMatches,\n\tliteral,\n\tquoteKey,\n\tregexLiteral,\n\trenderTsType,\n} from \"../shared.js\";\nimport { buildLazyGraph, nodeId, type LazyGraph } from \"../zod/lazy.js\";\n\ninterface RenderCtx {\n\treadonly ctx: PrintContext;\n\treadonly byId: Map<string, SourceDoc>;\n\treadonly graph: LazyGraph;\n\treadonly warnings: string[];\n}\n\n/** Generates valibot v1 schemas from IR documents. */\nexport class ValibotPrinter implements AbstractPrinter {\n\tpublic readonly name = \"valibot\";\n\n\tpublic async print(docs: readonly SourceDoc[], ctx: PrintContext): Promise<PrintedFile[]> {\n\t\tconst byId = new Map<string, SourceDoc>(docs.map(d => [d.docId, d] as const));\n\t\tconst graph = buildLazyGraph(docs);\n\t\tconst files: PrintedFile[] = [];\n\t\tfor (const doc of docs) {\n\t\t\tfiles.push({\n\t\t\t\tpath: ctx.outputPath(doc.docId),\n\t\t\t\tcontent: this.printDoc(doc, ctx, byId, graph),\n\t\t\t});\n\t\t}\n\t\treturn files;\n\t}\n\n\tprivate printDoc(\n\t\tdoc: SourceDoc,\n\t\tctx: PrintContext,\n\t\tbyId: Map<string, SourceDoc>,\n\t\tgraph: LazyGraph,\n\t): string {\n\t\tconst imports = collectImports(doc, ctx, byId);\n\t\tconst warnings: string[] = [];\n\t\tconst r: RenderCtx = { ctx, byId, graph, warnings };\n\n\t\tconst lines: string[] = [];\n\t\tlines.push(\n\t\t\t`import * as v from ${JSON.stringify(ctx.options.importPaths.valibot ?? \"valibot\")};`,\n\t\t);\n\t\tconst sorted = [...imports.entries()].toSorted(([a], [b]) => a.localeCompare(b));\n\t\tfor (const [, info] of sorted) {\n\t\t\tlines.push(\n\t\t\t\t`import { ${[...info.names].toSorted().join(\", \")} } from ${JSON.stringify(info.path)};`,\n\t\t\t);\n\t\t}\n\t\tlines.push(\"\");\n\n\t\tfor (const name of doc.exportOrder) {\n\t\t\tconst ir = doc.exports.get(name);\n\t\t\tif (!ir) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst exportName = ctx.resolveExportName(doc, name);\n\t\t\tconst cyclic = graph.isCyclic(nodeId(doc.docId, name));\n\t\t\tif (cyclic) {\n\t\t\t\t// structural alias doubles as the annotation type; it breaks the\n\t\t\t\t// const's self-inference cycle and is mutually recursive with others\n\t\t\t\tconst aliasRef = (ref: Ref): string => this.aliasRefExpr(ref, doc, r);\n\t\t\t\tlines.push(\n\t\t\t\t\t`export type ${exportName} = ${renderTsType(ir, aliasRef, { readonlyArrays: false })};`,\n\t\t\t\t);\n\t\t\t\tlines.push(\"\");\n\t\t\t}\n\t\t\tif (ir.meta?.deprecated) {\n\t\t\t\tlines.push(\"/** @deprecated */\");\n\t\t\t}\n\t\t\t// GenericSchema<Input, Output>: input stays `unknown` — optional fields\n\t\t\t// with defaults accept undefined at the input but not the output\n\t\t\tconst annotation = cyclic ? `: v.GenericSchema<unknown, ${exportName}>` : \"\";\n\t\t\tlines.push(\n\t\t\t\t`export const ${exportName}${annotation} = ${this.exprOf(ir, doc, name, r)};`,\n\t\t\t);\n\t\t\tif (!cyclic) {\n\t\t\t\tlines.push(`export type ${exportName} = v.InferOutput<typeof ${exportName}>;`);\n\t\t\t}\n\t\t\tlines.push(\"\");\n\t\t}\n\n\t\tfor (const warning of warnings) {\n\t\t\tctx.diagnostics.push(\n\t\t\t\tcreateDiagnostic(DiagnosticCode.UnknownKeyword, \"warning\", warning, {\n\t\t\t\t\tdocId: doc.docId,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn `${lines.join(\"\\n\").trimEnd()}\\n`;\n\t}\n\n\tprivate exprOf(ir: IRType, doc: SourceDoc, name: string, r: RenderCtx): string {\n\t\tlet base: string;\n\t\tswitch (ir.kind) {\n\t\t\tcase \"ref\":\n\t\t\t\tbase = this.refExpr(ir.ref, doc, name, r);\n\t\t\t\tbreak;\n\t\t\tcase \"string\":\n\t\t\t\tbase = this.stringExpr(ir);\n\t\t\t\tbreak;\n\t\t\tcase \"integer\":\n\t\t\tcase \"number\":\n\t\t\t\tbase = this.numberExpr(ir);\n\t\t\t\tbreak;\n\t\t\tcase \"boolean\":\n\t\t\t\tbase = ir.const !== undefined ? `v.literal(${ir.const})` : \"v.boolean()\";\n\t\t\t\tbreak;\n\t\t\tcase \"null\":\n\t\t\t\tbase = \"v.null()\";\n\t\t\t\tbreak;\n\t\t\tcase \"literal\":\n\t\t\t\tbase = `v.literal(${literal(ir.value)})`;\n\t\t\t\tbreak;\n\t\t\tcase \"array\":\n\t\t\t\tbase = this.arrayExpr(ir, doc, name, r);\n\t\t\t\tbreak;\n\t\t\tcase \"tuple\":\n\t\t\t\tbase = this.tupleExpr(ir, doc, name, r);\n\t\t\t\tbreak;\n\t\t\tcase \"object\":\n\t\t\t\tbase = this.objectExpr(ir, doc, name, r);\n\t\t\t\tbreak;\n\t\t\tcase \"record\":\n\t\t\t\tbase = `v.record(v.string(), ${this.exprOf(ir.values, doc, name, r)})`;\n\t\t\t\tbreak;\n\t\t\tcase \"union\": {\n\t\t\t\tif (ir.variants.length === 0) {\n\t\t\t\t\tbase = \"v.never()\";\n\t\t\t\t} else if (ir.variants.length === 1) {\n\t\t\t\t\tconst single = ir.variants[0];\n\t\t\t\t\tbase = single ? this.exprOf(single, doc, name, r) : \"v.never()\";\n\t\t\t\t} else {\n\t\t\t\t\tbase = `v.union([${ir.variants.map(x => this.exprOf(x, doc, name, r)).join(\", \")}])`;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"intersection\": {\n\t\t\t\tif (ir.variants.length === 0) {\n\t\t\t\t\tbase = \"v.unknown()\";\n\t\t\t\t} else if (ir.variants.length === 1) {\n\t\t\t\t\tconst single = ir.variants[0];\n\t\t\t\t\tbase = single ? this.exprOf(single, doc, name, r) : \"v.unknown()\";\n\t\t\t\t} else {\n\t\t\t\t\tbase = `v.intersect([${ir.variants.map(x => this.exprOf(x, doc, name, r)).join(\", \")}])`;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"unknown\":\n\t\t\t\tbase = \"v.unknown()\";\n\t\t\t\tbreak;\n\t\t}\n\t\tif (ir.meta?.description) {\n\t\t\tbase = `v.pipe(${base}, v.description(${JSON.stringify(ir.meta.description)}))`;\n\t\t}\n\t\treturn base;\n\t}\n\n\tprivate refExpr(ref: Ref, doc: SourceDoc, name: string, r: RenderCtx): string {\n\t\tconst target = r.byId.get(ref.docId);\n\t\tconst exportName = target\n\t\t\t? r.ctx.resolveExportName(target, ref.exportName)\n\t\t\t: ref.exportName;\n\t\tif (r.graph.needsLazy(nodeId(doc.docId, name), nodeId(ref.docId, ref.exportName))) {\n\t\t\treturn `v.lazy(() => ${exportName})`;\n\t\t}\n\t\treturn exportName;\n\t}\n\n\t/** Ref renderer for structural aliases of cyclic exports. */\n\tprivate aliasRefExpr(ref: Ref, doc: SourceDoc, r: RenderCtx): string {\n\t\tif (ref.docId === doc.docId) {\n\t\t\tif (!doc.exports.has(ref.exportName)) {\n\t\t\t\treturn \"unknown\";\n\t\t\t}\n\t\t\tconst resolved = r.ctx.resolveExportName(doc, ref.exportName);\n\t\t\tif (r.graph.isCyclic(nodeId(doc.docId, ref.exportName))) {\n\t\t\t\treturn resolved;\n\t\t\t}\n\t\t\treturn `v.InferOutput<typeof ${resolved}>`;\n\t\t}\n\t\tconst target = r.byId.get(ref.docId);\n\t\tif (!target) {\n\t\t\treturn \"unknown\";\n\t\t}\n\t\tconst exportName = r.ctx.resolveExportName(target, ref.exportName);\n\t\tif (r.graph.isCyclic(nodeId(ref.docId, ref.exportName))) {\n\t\t\treturn exportName;\n\t\t}\n\t\treturn `v.InferOutput<typeof ${exportName}>`;\n\t}\n\n\tprivate stringExpr(ir: Extract<IRType, { kind: \"string\" }>): string {\n\t\tif (ir.const !== undefined) {\n\t\t\treturn `v.literal(${JSON.stringify(ir.const)})`;\n\t\t}\n\t\tif (ir.enum) {\n\t\t\tif (ir.enum.length === 0) {\n\t\t\t\treturn \"v.string()\";\n\t\t\t}\n\t\t\treturn `v.picklist([${ir.enum.map(x => JSON.stringify(x)).join(\", \")}])`;\n\t\t}\n\t\tconst actions: string[] = [];\n\t\tconst format = stringFormatAction(ir.format);\n\t\tif (format) {\n\t\t\tactions.push(format);\n\t\t}\n\t\tif (ir.minLength !== undefined) {\n\t\t\tactions.push(`v.minLength(${ir.minLength})`);\n\t\t}\n\t\tif (ir.maxLength !== undefined) {\n\t\t\tactions.push(`v.maxLength(${ir.maxLength})`);\n\t\t}\n\t\tif (ir.pattern !== undefined) {\n\t\t\tactions.push(`v.regex(${regexLiteral(ir.pattern)})`);\n\t\t}\n\t\tif (actions.length === 0) {\n\t\t\treturn \"v.string()\";\n\t\t}\n\t\treturn `v.pipe(v.string(), ${actions.join(\", \")})`;\n\t}\n\n\tprivate numberExpr(ir: Extract<IRType, { kind: \"number\" | \"integer\" }>): string {\n\t\tif (ir.const !== undefined) {\n\t\t\treturn `v.literal(${ir.const})`;\n\t\t}\n\t\tif (ir.enum) {\n\t\t\tif (ir.enum.length === 0) {\n\t\t\t\treturn \"v.number()\";\n\t\t\t}\n\t\t\treturn `v.union([${ir.enum.map(x => `v.literal(${x})`).join(\", \")}])`;\n\t\t}\n\t\tconst actions: string[] = [];\n\t\tif (ir.kind === \"integer\") {\n\t\t\tactions.push(\"v.integer()\");\n\t\t}\n\t\tif (ir.minimum !== undefined) {\n\t\t\tactions.push(`v.minValue(${ir.minimum})`);\n\t\t}\n\t\tif (ir.maximum !== undefined) {\n\t\t\tactions.push(`v.maxValue(${ir.maximum})`);\n\t\t}\n\t\tif (ir.exclusiveMinimum !== undefined) {\n\t\t\tactions.push(`v.gtValue(${ir.exclusiveMinimum})`);\n\t\t}\n\t\tif (ir.exclusiveMaximum !== undefined) {\n\t\t\tactions.push(`v.ltValue(${ir.exclusiveMaximum})`);\n\t\t}\n\t\tif (ir.multipleOf !== undefined) {\n\t\t\tactions.push(`v.multipleOf(${ir.multipleOf})`);\n\t\t}\n\t\tif (actions.length === 0) {\n\t\t\treturn \"v.number()\";\n\t\t}\n\t\treturn `v.pipe(v.number(), ${actions.join(\", \")})`;\n\t}\n\n\tprivate arrayExpr(\n\t\tir: Extract<IRType, { kind: \"array\" }>,\n\t\tdoc: SourceDoc,\n\t\tname: string,\n\t\tr: RenderCtx,\n\t): string {\n\t\tconst items = ir.items ? this.exprOf(ir.items, doc, name, r) : \"v.unknown()\";\n\t\tconst actions: string[] = [];\n\t\tif (ir.minItems !== undefined) {\n\t\t\tactions.push(`v.minLength(${ir.minItems})`);\n\t\t}\n\t\tif (ir.maxItems !== undefined) {\n\t\t\tactions.push(`v.maxLength(${ir.maxItems})`);\n\t\t}\n\t\tif (ir.uniqueItems === true) {\n\t\t\tr.warnings.push(\"uniqueItems is not supported by the valibot target and was ignored\");\n\t\t}\n\t\tif (actions.length === 0) {\n\t\t\treturn `v.array(${items})`;\n\t\t}\n\t\treturn `v.pipe(v.array(${items}), ${actions.join(\", \")})`;\n\t}\n\n\tprivate tupleExpr(\n\t\tir: Extract<IRType, { kind: \"tuple\" }>,\n\t\tdoc: SourceDoc,\n\t\tname: string,\n\t\tr: RenderCtx,\n\t): string {\n\t\tconst items = ir.items.map(i => this.exprOf(i, doc, name, r)).join(\", \");\n\t\t// valibot tuples truncate extra items; a `never` rest enforces the exact\n\t\t// length (parity with the zod target), a schema rest validates the tail\n\t\tconst rest = ir.additionalItems\n\t\t\t? this.exprOf(ir.additionalItems, doc, name, r)\n\t\t\t: \"v.never()\";\n\t\treturn `v.tupleWithRest([${items}], ${rest})`;\n\t}\n\n\tprivate objectExpr(\n\t\tir: Extract<IRType, { kind: \"object\" }>,\n\t\tdoc: SourceDoc,\n\t\tname: string,\n\t\tr: RenderCtx,\n\t): string {\n\t\tconst required = new Set(ir.required);\n\t\tconst parts: string[] = [];\n\t\tfor (const [key, val] of ir.properties) {\n\t\t\tlet expr = this.exprOf(val, doc, name, r);\n\t\t\tconst hasDefault =\n\t\t\t\tr.ctx.options.defaults &&\n\t\t\t\tval.meta?.default !== undefined &&\n\t\t\t\tdefaultMatches(val, val.meta.default);\n\t\t\tif (hasDefault) {\n\t\t\t\texpr = `v.optional(${expr}, ${JSON.stringify(val.meta?.default)})`;\n\t\t\t} else if (!required.has(key)) {\n\t\t\t\texpr = `v.optional(${expr})`;\n\t\t\t} else if (\n\t\t\t\tr.ctx.options.defaults &&\n\t\t\t\tval.meta?.default !== undefined &&\n\t\t\t\t!defaultMatches(val, val.meta.default)\n\t\t\t) {\n\t\t\t\tr.warnings.push(\n\t\t\t\t\t`default ${JSON.stringify(val.meta.default)} does not match schema type and was ignored`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tparts.push(`${quoteKey(key)}: ${expr}`);\n\t\t}\n\t\tconst entries = parts.length === 0 ? \"{}\" : `{ ${parts.join(\", \")} }`;\n\t\tif (ir.additionalProperties === false) {\n\t\t\treturn `v.strictObject(${entries})`;\n\t\t}\n\t\tif (ir.additionalProperties) {\n\t\t\treturn `v.objectWithRest(${entries}, ${this.exprOf(ir.additionalProperties, doc, name, r)})`;\n\t\t}\n\t\treturn `v.object(${entries})`;\n\t}\n}\n\nfunction stringFormatAction(format: string | undefined): string | undefined {\n\tswitch (format) {\n\t\tcase \"uuid\":\n\t\t\treturn \"v.uuid()\";\n\t\tcase \"email\":\n\t\t\treturn \"v.email()\";\n\t\tcase \"uri\":\n\t\tcase \"url\":\n\t\t\treturn \"v.url()\";\n\t\tcase \"date\":\n\t\t\treturn \"v.isoDate()\";\n\t\tcase \"date-time\":\n\t\t\treturn \"v.isoDateTime()\";\n\t\tcase \"time\":\n\t\t\treturn \"v.isoTime()\";\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { SourceDoc } from "../../core/ir/types.mjs";
2
+ //#region src/targets/zod/lazy.d.ts
3
+ /** Global node id: `${docId}#${exportName}`. */
4
+ export type NodeId = string;
5
+ export declare function nodeId(docId: string, exportName: string): NodeId;
6
+ export interface LazyGraph {
7
+ /** Whether the ref edge `from → to` must be rendered as `z.lazy(() => …)` / `v.lazy(() => …)`. */
8
+ readonly needsLazy: (from: NodeId, to: NodeId) => boolean;
9
+ /** Whether the node participates in a reference cycle (self-loop or larger). */
10
+ readonly isCyclic: (node: NodeId) => boolean;
11
+ }
12
+ /**
13
+ * Builds a lazy-rendering graph over the global export set.
14
+ *
15
+ * A ref must be wrapped in `z.lazy(() => X)` / `v.lazy(() => X)` when:
16
+ * - it is a self-reference, or
17
+ * - it points to an export declared later in the same file (TDZ at module evaluation), or
18
+ * - it participates in a cycle in the global import graph (circular ESM would read
19
+ * an uninitialized binding at evaluation time). The cycle may run through OTHER
20
+ * exports of the involved documents, so document-level reachability is checked
21
+ * in addition to node-level: a ref into a document that (transitively) imports
22
+ * the current one must be lazy even when the two exports themselves are acyclic.
23
+ *
24
+ * A node "participates in a cycle" when it can reach itself; such exports need a
25
+ * structural type alias + generic annotation to break TS inference circularity.
26
+ */
27
+ export declare function buildLazyGraph(docs: readonly SourceDoc[]): LazyGraph;
28
+ //#endregion
29
+ //# sourceMappingURL=lazy.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy.d.mts","names":[],"sources":["../../../src/targets/zod/lazy.ts"],"mappings":";;;YAIY;wBAEI,OAAO,eAAe,qBAAqB;iBAI1C;;WAEP,YAAY,MAAM,QAAQ,IAAI;;WAE9B,WAAW,MAAM;;;;;;;;;;;;;;;;;wBAkBX,eAAe,eAAe,cAAc"}
@@ -0,0 +1,100 @@
1
+ import { visitRefs } from "../../core/ir/visit.mjs";
2
+ //#region src/targets/zod/lazy.ts
3
+ function nodeId(docId, exportName) {
4
+ return `${docId}#${exportName}`;
5
+ }
6
+ /**
7
+ * Builds a lazy-rendering graph over the global export set.
8
+ *
9
+ * A ref must be wrapped in `z.lazy(() => X)` / `v.lazy(() => X)` when:
10
+ * - it is a self-reference, or
11
+ * - it points to an export declared later in the same file (TDZ at module evaluation), or
12
+ * - it participates in a cycle in the global import graph (circular ESM would read
13
+ * an uninitialized binding at evaluation time). The cycle may run through OTHER
14
+ * exports of the involved documents, so document-level reachability is checked
15
+ * in addition to node-level: a ref into a document that (transitively) imports
16
+ * the current one must be lazy even when the two exports themselves are acyclic.
17
+ *
18
+ * A node "participates in a cycle" when it can reach itself; such exports need a
19
+ * structural type alias + generic annotation to break TS inference circularity.
20
+ */
21
+ function buildLazyGraph(docs) {
22
+ const nodeIds = /* @__PURE__ */ new Set();
23
+ const edges = /* @__PURE__ */ new Map();
24
+ const indexInDoc = /* @__PURE__ */ new Map();
25
+ const docOf = /* @__PURE__ */ new Map();
26
+ const docEdges = /* @__PURE__ */ new Map();
27
+ for (const doc of docs) doc.exportOrder.forEach((name, index) => {
28
+ const id = nodeId(doc.docId, name);
29
+ nodeIds.add(id);
30
+ indexInDoc.set(id, index);
31
+ docOf.set(id, doc.docId);
32
+ });
33
+ for (const doc of docs) for (const name of doc.exportOrder) {
34
+ const ir = doc.exports.get(name);
35
+ if (!ir) continue;
36
+ const from = nodeId(doc.docId, name);
37
+ const targets = [];
38
+ visitRefs(ir, (ref) => {
39
+ const to = nodeId(ref.docId, ref.exportName);
40
+ if (nodeIds.has(to) && !targets.includes(to)) {
41
+ targets.push(to);
42
+ const fromDocs = docEdges.get(doc.docId);
43
+ if (fromDocs) fromDocs.add(ref.docId);
44
+ else docEdges.set(doc.docId, /* @__PURE__ */ new Set([ref.docId]));
45
+ }
46
+ });
47
+ edges.set(from, targets);
48
+ }
49
+ const reachCache = /* @__PURE__ */ new Map();
50
+ const reachableFrom = (start) => {
51
+ const cached = reachCache.get(start);
52
+ if (cached) return cached;
53
+ const visited = /* @__PURE__ */ new Set();
54
+ reachCache.set(start, visited);
55
+ const stack = [...edges.get(start) ?? []];
56
+ while (stack.length > 0) {
57
+ const current = stack.pop();
58
+ if (current === void 0 || visited.has(current)) continue;
59
+ visited.add(current);
60
+ for (const next of edges.get(current) ?? []) stack.push(next);
61
+ }
62
+ return visited;
63
+ };
64
+ const docReachCache = /* @__PURE__ */ new Map();
65
+ const docsReachableFrom = (start) => {
66
+ const cached = docReachCache.get(start);
67
+ if (cached) return cached;
68
+ const visited = /* @__PURE__ */ new Set();
69
+ docReachCache.set(start, visited);
70
+ const stack = [...docEdges.get(start) ?? []];
71
+ while (stack.length > 0) {
72
+ const current = stack.pop();
73
+ if (current === void 0 || visited.has(current)) continue;
74
+ visited.add(current);
75
+ for (const next of docEdges.get(current) ?? []) stack.push(next);
76
+ }
77
+ return visited;
78
+ };
79
+ const isCyclic = (node) => reachableFrom(node).has(node);
80
+ const needsLazy = (from, to) => {
81
+ if (from === to) return true;
82
+ const fromDoc = docOf.get(from);
83
+ const toDoc = docOf.get(to);
84
+ if (fromDoc !== void 0 && fromDoc === toDoc) {
85
+ const fromIndex = indexInDoc.get(from);
86
+ const toIndex = indexInDoc.get(to);
87
+ if (fromIndex !== void 0 && toIndex !== void 0 && toIndex > fromIndex) return true;
88
+ }
89
+ if (fromDoc !== void 0 && toDoc !== void 0 && fromDoc !== toDoc) return docsReachableFrom(toDoc).has(fromDoc);
90
+ return reachableFrom(to).has(from);
91
+ };
92
+ return {
93
+ needsLazy,
94
+ isCyclic
95
+ };
96
+ }
97
+ //#endregion
98
+ export { buildLazyGraph, nodeId };
99
+
100
+ //# sourceMappingURL=lazy.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy.mjs","names":[],"sources":["../../../src/targets/zod/lazy.ts"],"sourcesContent":["import type { SourceDoc } from \"../../core/ir/types.js\";\nimport { visitRefs } from \"../../core/ir/visit.js\";\n\n/** Global node id: `${docId}#${exportName}`. */\nexport type NodeId = string;\n\nexport function nodeId(docId: string, exportName: string): NodeId {\n\treturn `${docId}#${exportName}`;\n}\n\nexport interface LazyGraph {\n\t/** Whether the ref edge `from → to` must be rendered as `z.lazy(() => …)` / `v.lazy(() => …)`. */\n\treadonly needsLazy: (from: NodeId, to: NodeId) => boolean;\n\t/** Whether the node participates in a reference cycle (self-loop or larger). */\n\treadonly isCyclic: (node: NodeId) => boolean;\n}\n\n/**\n * Builds a lazy-rendering graph over the global export set.\n *\n * A ref must be wrapped in `z.lazy(() => X)` / `v.lazy(() => X)` when:\n * - it is a self-reference, or\n * - it points to an export declared later in the same file (TDZ at module evaluation), or\n * - it participates in a cycle in the global import graph (circular ESM would read\n * an uninitialized binding at evaluation time). The cycle may run through OTHER\n * exports of the involved documents, so document-level reachability is checked\n * in addition to node-level: a ref into a document that (transitively) imports\n * the current one must be lazy even when the two exports themselves are acyclic.\n *\n * A node \"participates in a cycle\" when it can reach itself; such exports need a\n * structural type alias + generic annotation to break TS inference circularity.\n */\nexport function buildLazyGraph(docs: readonly SourceDoc[]): LazyGraph {\n\tconst nodeIds = new Set<NodeId>();\n\tconst edges = new Map<NodeId, NodeId[]>();\n\tconst indexInDoc = new Map<NodeId, number>();\n\tconst docOf = new Map<NodeId, string>();\n\tconst docEdges = new Map<string, Set<string>>();\n\n\tfor (const doc of docs) {\n\t\tdoc.exportOrder.forEach((name, index) => {\n\t\t\tconst id = nodeId(doc.docId, name);\n\t\t\tnodeIds.add(id);\n\t\t\tindexInDoc.set(id, index);\n\t\t\tdocOf.set(id, doc.docId);\n\t\t});\n\t}\n\tfor (const doc of docs) {\n\t\tfor (const name of doc.exportOrder) {\n\t\t\tconst ir = doc.exports.get(name);\n\t\t\tif (!ir) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst from = nodeId(doc.docId, name);\n\t\t\tconst targets: NodeId[] = [];\n\t\t\tvisitRefs(ir, ref => {\n\t\t\t\tconst to = nodeId(ref.docId, ref.exportName);\n\t\t\t\tif (nodeIds.has(to) && !targets.includes(to)) {\n\t\t\t\t\ttargets.push(to);\n\t\t\t\t\tconst fromDocs = docEdges.get(doc.docId);\n\t\t\t\t\tif (fromDocs) {\n\t\t\t\t\t\tfromDocs.add(ref.docId);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdocEdges.set(doc.docId, new Set([ref.docId]));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tedges.set(from, targets);\n\t\t}\n\t}\n\n\tconst reachCache = new Map<NodeId, Set<NodeId>>();\n\tconst reachableFrom = (start: NodeId): Set<NodeId> => {\n\t\tconst cached = reachCache.get(start);\n\t\tif (cached) {\n\t\t\treturn cached;\n\t\t}\n\t\tconst visited = new Set<NodeId>();\n\t\treachCache.set(start, visited);\n\t\tconst stack: NodeId[] = [...(edges.get(start) ?? [])];\n\t\twhile (stack.length > 0) {\n\t\t\tconst current = stack.pop();\n\t\t\tif (current === undefined || visited.has(current)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvisited.add(current);\n\t\t\tfor (const next of edges.get(current) ?? []) {\n\t\t\t\tstack.push(next);\n\t\t\t}\n\t\t}\n\t\treturn visited;\n\t};\n\n\tconst docReachCache = new Map<string, Set<string>>();\n\tconst docsReachableFrom = (start: string): Set<string> => {\n\t\tconst cached = docReachCache.get(start);\n\t\tif (cached) {\n\t\t\treturn cached;\n\t\t}\n\t\tconst visited = new Set<string>();\n\t\tdocReachCache.set(start, visited);\n\t\tconst stack: string[] = [...(docEdges.get(start) ?? [])];\n\t\twhile (stack.length > 0) {\n\t\t\tconst current = stack.pop();\n\t\t\tif (current === undefined || visited.has(current)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvisited.add(current);\n\t\t\tfor (const next of docEdges.get(current) ?? []) {\n\t\t\t\tstack.push(next);\n\t\t\t}\n\t\t}\n\t\treturn visited;\n\t};\n\n\tconst isCyclic = (node: NodeId): boolean => reachableFrom(node).has(node);\n\n\tconst needsLazy = (from: NodeId, to: NodeId): boolean => {\n\t\tif (from === to) {\n\t\t\treturn true;\n\t\t}\n\t\tconst fromDoc = docOf.get(from);\n\t\tconst toDoc = docOf.get(to);\n\t\tif (fromDoc !== undefined && fromDoc === toDoc) {\n\t\t\tconst fromIndex = indexInDoc.get(from);\n\t\t\tconst toIndex = indexInDoc.get(to);\n\t\t\tif (fromIndex !== undefined && toIndex !== undefined && toIndex > fromIndex) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\tif (fromDoc !== undefined && toDoc !== undefined && fromDoc !== toDoc) {\n\t\t\t// the target document (transitively) imports ours: circular ESM\n\t\t\treturn docsReachableFrom(toDoc).has(fromDoc);\n\t\t}\n\t\treturn reachableFrom(to).has(from);\n\t};\n\n\treturn { needsLazy, isCyclic };\n}\n"],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { SourceDoc } from "../../core/ir/types.mjs";
2
+ import { AbstractPrinter, PrintContext } from "../../core/printer/abstract.mjs";
3
+ import { PrintedFile } from "../../core/types.mjs";
4
+ //#region src/targets/zod/printer.d.ts
5
+ /** Generates zod v4 schemas from IR documents. */
6
+ export declare class ZodPrinter implements AbstractPrinter {
7
+ readonly name = "zod";
8
+ print(docs: readonly SourceDoc[], ctx: PrintContext): Promise<PrintedFile[]>;
9
+ private printDoc;
10
+ private exprOf;
11
+ private refExpr;
12
+ /** Ref renderer for structural aliases of cyclic exports. */
13
+ private aliasRefExpr;
14
+ private stringExpr;
15
+ private numberExpr;
16
+ private arrayExpr;
17
+ private tupleExpr;
18
+ private objectExpr;
19
+ }
20
+ //#endregion
21
+ //# sourceMappingURL=printer.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"printer.d.mts","names":[],"sources":["../../../src/targets/zod/printer.ts"],"mappings":";;;;;qBAsBa,sBAAsB;WAClB;EAEhB,MAAmB,eAAe,aAAa,KAAK,eAAe,QAAQ;UAanE;UA0DA;UAiEA;;UAYA;UAsBA;UAuBA;UA6BA;UAoBA;UAcA"}
@@ -0,0 +1,193 @@
1
+ import { DiagnosticCode, createDiagnostic } from "../../diagnostics/errors.mjs";
2
+ import { collectImports, defaultMatches, literal, quoteKey, regexLiteral, renderTsType } from "../shared.mjs";
3
+ import { buildLazyGraph, nodeId } from "./lazy.mjs";
4
+ //#region src/targets/zod/printer.ts
5
+ /** Generates zod v4 schemas from IR documents. */
6
+ var ZodPrinter = class {
7
+ name = "zod";
8
+ async print(docs, ctx) {
9
+ const byId = new Map(docs.map((d) => [d.docId, d]));
10
+ const graph = buildLazyGraph(docs);
11
+ const files = [];
12
+ for (const doc of docs) files.push({
13
+ path: ctx.outputPath(doc.docId),
14
+ content: this.printDoc(doc, ctx, byId, graph)
15
+ });
16
+ return files;
17
+ }
18
+ printDoc(doc, ctx, byId, graph) {
19
+ const imports = collectImports(doc, ctx, byId);
20
+ const warnings = [];
21
+ const r = {
22
+ ctx,
23
+ byId,
24
+ graph,
25
+ warnings
26
+ };
27
+ const lines = [];
28
+ lines.push(`import { z } from ${JSON.stringify(ctx.options.importPaths.zod ?? "zod")};`);
29
+ const sorted = [...imports.entries()].toSorted(([a], [b]) => a.localeCompare(b));
30
+ for (const [, info] of sorted) {
31
+ const names = [...info.names].toSorted();
32
+ lines.push(`import { ${names.join(", ")} } from ${JSON.stringify(info.path)};`);
33
+ }
34
+ lines.push("");
35
+ for (const name of doc.exportOrder) {
36
+ const ir = doc.exports.get(name);
37
+ if (!ir) continue;
38
+ const exportName = ctx.resolveExportName(doc, name);
39
+ const cyclic = graph.isCyclic(nodeId(doc.docId, name));
40
+ if (cyclic) {
41
+ const aliasRef = (ref) => this.aliasRefExpr(ref, doc, r);
42
+ lines.push(`export type ${exportName} = ${renderTsType(ir, aliasRef, { readonlyArrays: false })};`);
43
+ lines.push("");
44
+ }
45
+ if (ir.meta?.deprecated) lines.push("/** @deprecated */");
46
+ const annotation = cyclic ? `: z.ZodType<${exportName}>` : "";
47
+ lines.push(`export const ${exportName}${annotation} = ${this.exprOf(ir, doc, name, r)};`);
48
+ if (!cyclic) lines.push(`export type ${exportName} = z.infer<typeof ${exportName}>;`);
49
+ lines.push("");
50
+ }
51
+ for (const warning of warnings) ctx.diagnostics.push(createDiagnostic(DiagnosticCode.UnknownKeyword, "warning", warning, { docId: doc.docId }));
52
+ return `${lines.join("\n").trimEnd()}\n`;
53
+ }
54
+ exprOf(ir, doc, name, r) {
55
+ let base;
56
+ switch (ir.kind) {
57
+ case "ref":
58
+ base = this.refExpr(ir.ref, doc, name, r);
59
+ break;
60
+ case "string":
61
+ base = this.stringExpr(ir);
62
+ break;
63
+ case "integer":
64
+ case "number":
65
+ base = this.numberExpr(ir);
66
+ break;
67
+ case "boolean":
68
+ base = ir.const !== void 0 ? `z.literal(${ir.const})` : "z.boolean()";
69
+ break;
70
+ case "null":
71
+ base = "z.null()";
72
+ break;
73
+ case "literal":
74
+ base = `z.literal(${literal(ir.value)})`;
75
+ break;
76
+ case "array":
77
+ base = this.arrayExpr(ir, doc, name, r);
78
+ break;
79
+ case "tuple":
80
+ base = this.tupleExpr(ir, doc, name, r);
81
+ break;
82
+ case "object":
83
+ base = this.objectExpr(ir, doc, name, r);
84
+ break;
85
+ case "record":
86
+ base = `z.record(z.string(), ${this.exprOf(ir.values, doc, name, r)})`;
87
+ break;
88
+ case "union":
89
+ if (ir.variants.length === 0) base = "z.never()";
90
+ else if (ir.variants.length === 1) {
91
+ const single = ir.variants[0];
92
+ base = single ? this.exprOf(single, doc, name, r) : "z.never()";
93
+ } else base = `z.union([${ir.variants.map((v) => this.exprOf(v, doc, name, r)).join(", ")}])`;
94
+ break;
95
+ case "intersection":
96
+ if (ir.variants.length === 0) base = "z.unknown()";
97
+ else base = ir.variants.map((v) => this.exprOf(v, doc, name, r)).reduce((acc, v) => `z.intersection(${acc}, ${v})`);
98
+ break;
99
+ case "unknown": base = "z.unknown()";
100
+ }
101
+ if (ir.meta?.description) base = `${base}.describe(${JSON.stringify(ir.meta.description)})`;
102
+ return base;
103
+ }
104
+ refExpr(ref, doc, name, r) {
105
+ const target = r.byId.get(ref.docId);
106
+ const exportName = target ? r.ctx.resolveExportName(target, ref.exportName) : ref.exportName;
107
+ if (r.graph.needsLazy(nodeId(doc.docId, name), nodeId(ref.docId, ref.exportName))) return `z.lazy(() => ${exportName})`;
108
+ return exportName;
109
+ }
110
+ /** Ref renderer for structural aliases of cyclic exports. */
111
+ aliasRefExpr(ref, doc, r) {
112
+ if (ref.docId === doc.docId) {
113
+ if (!doc.exports.has(ref.exportName)) return "unknown";
114
+ const resolved = r.ctx.resolveExportName(doc, ref.exportName);
115
+ if (r.graph.isCyclic(nodeId(doc.docId, ref.exportName))) return resolved;
116
+ return `z.infer<typeof ${resolved}>`;
117
+ }
118
+ const target = r.byId.get(ref.docId);
119
+ if (!target) return "unknown";
120
+ const exportName = r.ctx.resolveExportName(target, ref.exportName);
121
+ if (r.graph.isCyclic(nodeId(ref.docId, ref.exportName))) return exportName;
122
+ return `z.infer<typeof ${exportName}>`;
123
+ }
124
+ stringExpr(ir) {
125
+ if (ir.const !== void 0) return `z.literal(${JSON.stringify(ir.const)})`;
126
+ if (ir.enum) {
127
+ if (ir.enum.length === 0) return "z.string()";
128
+ return `z.enum([${ir.enum.map((v) => JSON.stringify(v)).join(", ")}])`;
129
+ }
130
+ let expr = stringFormatBase(ir.format);
131
+ if (ir.minLength !== void 0) expr += `.min(${ir.minLength})`;
132
+ if (ir.maxLength !== void 0) expr += `.max(${ir.maxLength})`;
133
+ if (ir.pattern !== void 0) expr += `.regex(${regexLiteral(ir.pattern)})`;
134
+ return expr;
135
+ }
136
+ numberExpr(ir) {
137
+ if (ir.const !== void 0) return `z.literal(${ir.const})`;
138
+ if (ir.enum) {
139
+ if (ir.enum.length === 0) return ir.kind === "integer" ? "z.int()" : "z.number()";
140
+ return `z.union([${ir.enum.map((v) => `z.literal(${v})`).join(", ")}])`;
141
+ }
142
+ let expr = ir.kind === "integer" ? "z.int()" : "z.number()";
143
+ if (ir.minimum !== void 0) expr += `.min(${ir.minimum})`;
144
+ if (ir.maximum !== void 0) expr += `.max(${ir.maximum})`;
145
+ if (ir.exclusiveMinimum !== void 0) expr += `.gt(${ir.exclusiveMinimum})`;
146
+ if (ir.exclusiveMaximum !== void 0) expr += `.lt(${ir.exclusiveMaximum})`;
147
+ if (ir.multipleOf !== void 0) expr += `.multipleOf(${ir.multipleOf})`;
148
+ return expr;
149
+ }
150
+ arrayExpr(ir, doc, name, r) {
151
+ let expr = `z.array(${ir.items ? this.exprOf(ir.items, doc, name, r) : "z.unknown()"})`;
152
+ if (ir.minItems !== void 0) expr += `.min(${ir.minItems})`;
153
+ if (ir.maxItems !== void 0) expr += `.max(${ir.maxItems})`;
154
+ if (ir.uniqueItems === true) r.warnings.push("uniqueItems is not supported by the zod target and was ignored");
155
+ return expr;
156
+ }
157
+ tupleExpr(ir, doc, name, r) {
158
+ let expr = `z.tuple([${ir.items.map((i) => this.exprOf(i, doc, name, r)).join(", ")}])`;
159
+ if (ir.additionalItems) expr += `.rest(${this.exprOf(ir.additionalItems, doc, name, r)})`;
160
+ return expr;
161
+ }
162
+ objectExpr(ir, doc, name, r) {
163
+ const required = new Set(ir.required);
164
+ const parts = [];
165
+ for (const [key, val] of ir.properties) {
166
+ let expr = this.exprOf(val, doc, name, r);
167
+ if (r.ctx.options.defaults && val.meta?.default !== void 0 && defaultMatches(val, val.meta.default)) expr = `${expr}.default(${JSON.stringify(val.meta?.default)})`;
168
+ else if (!required.has(key)) expr = `${expr}.optional()`;
169
+ else if (r.ctx.options.defaults && val.meta?.default !== void 0 && !defaultMatches(val, val.meta.default)) r.warnings.push(`default ${JSON.stringify(val.meta.default)} does not match schema type and was ignored`);
170
+ parts.push(`${quoteKey(key)}: ${expr}`);
171
+ }
172
+ let expr = parts.length === 0 ? "z.object({})" : `z.object({ ${parts.join(", ")} })`;
173
+ if (ir.additionalProperties === false) expr = `${expr}.strict()`;
174
+ else if (ir.additionalProperties) expr = `${expr}.catchall(${this.exprOf(ir.additionalProperties, doc, name, r)})`;
175
+ return expr;
176
+ }
177
+ };
178
+ function stringFormatBase(format) {
179
+ switch (format) {
180
+ case "uuid": return "z.uuid()";
181
+ case "email": return "z.email()";
182
+ case "uri":
183
+ case "url": return "z.url()";
184
+ case "date": return "z.iso.date()";
185
+ case "date-time": return "z.iso.datetime()";
186
+ case "time": return "z.iso.time()";
187
+ default: return "z.string()";
188
+ }
189
+ }
190
+ //#endregion
191
+ export { ZodPrinter };
192
+
193
+ //# sourceMappingURL=printer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"printer.mjs","names":[],"sources":["../../../src/targets/zod/printer.ts"],"sourcesContent":["import type { IRType, Ref, SourceDoc } from \"../../core/ir/types.js\";\nimport type { AbstractPrinter, PrintContext } from \"../../core/printer/abstract.js\";\nimport type { PrintedFile } from \"../../core/types.js\";\nimport { createDiagnostic, DiagnosticCode } from \"../../diagnostics/errors.js\";\nimport {\n\tcollectImports,\n\tdefaultMatches,\n\tliteral,\n\tquoteKey,\n\tregexLiteral,\n\trenderTsType,\n} from \"../shared.js\";\nimport { buildLazyGraph, nodeId, type LazyGraph } from \"./lazy.js\";\n\ninterface RenderCtx {\n\treadonly ctx: PrintContext;\n\treadonly byId: Map<string, SourceDoc>;\n\treadonly graph: LazyGraph;\n\treadonly warnings: string[];\n}\n\n/** Generates zod v4 schemas from IR documents. */\nexport class ZodPrinter implements AbstractPrinter {\n\tpublic readonly name = \"zod\";\n\n\tpublic async print(docs: readonly SourceDoc[], ctx: PrintContext): Promise<PrintedFile[]> {\n\t\tconst byId = new Map<string, SourceDoc>(docs.map(d => [d.docId, d] as const));\n\t\tconst graph = buildLazyGraph(docs);\n\t\tconst files: PrintedFile[] = [];\n\t\tfor (const doc of docs) {\n\t\t\tfiles.push({\n\t\t\t\tpath: ctx.outputPath(doc.docId),\n\t\t\t\tcontent: this.printDoc(doc, ctx, byId, graph),\n\t\t\t});\n\t\t}\n\t\treturn files;\n\t}\n\n\tprivate printDoc(\n\t\tdoc: SourceDoc,\n\t\tctx: PrintContext,\n\t\tbyId: Map<string, SourceDoc>,\n\t\tgraph: LazyGraph,\n\t): string {\n\t\tconst imports = collectImports(doc, ctx, byId);\n\t\tconst warnings: string[] = [];\n\t\tconst r: RenderCtx = { ctx, byId, graph, warnings };\n\n\t\tconst lines: string[] = [];\n\t\tlines.push(`import { z } from ${JSON.stringify(ctx.options.importPaths.zod ?? \"zod\")};`);\n\t\tconst sorted = [...imports.entries()].toSorted(([a], [b]) => a.localeCompare(b));\n\t\tfor (const [, info] of sorted) {\n\t\t\tconst names = [...info.names].toSorted();\n\t\t\tlines.push(`import { ${names.join(\", \")} } from ${JSON.stringify(info.path)};`);\n\t\t}\n\t\tlines.push(\"\");\n\n\t\tfor (const name of doc.exportOrder) {\n\t\t\tconst ir = doc.exports.get(name);\n\t\t\tif (!ir) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst exportName = ctx.resolveExportName(doc, name);\n\t\t\tconst cyclic = graph.isCyclic(nodeId(doc.docId, name));\n\t\t\tif (cyclic) {\n\t\t\t\t// structural alias doubles as the annotation type; it breaks the\n\t\t\t\t// const's self-inference cycle and is mutually recursive with others\n\t\t\t\tconst aliasRef = (ref: Ref): string => this.aliasRefExpr(ref, doc, r);\n\t\t\t\tlines.push(\n\t\t\t\t\t`export type ${exportName} = ${renderTsType(ir, aliasRef, { readonlyArrays: false })};`,\n\t\t\t\t);\n\t\t\t\tlines.push(\"\");\n\t\t\t}\n\t\t\tif (ir.meta?.deprecated) {\n\t\t\t\tlines.push(\"/** @deprecated */\");\n\t\t\t}\n\t\t\tconst annotation = cyclic ? `: z.ZodType<${exportName}>` : \"\";\n\t\t\tlines.push(\n\t\t\t\t`export const ${exportName}${annotation} = ${this.exprOf(ir, doc, name, r)};`,\n\t\t\t);\n\t\t\tif (!cyclic) {\n\t\t\t\tlines.push(`export type ${exportName} = z.infer<typeof ${exportName}>;`);\n\t\t\t}\n\t\t\tlines.push(\"\");\n\t\t}\n\n\t\tfor (const warning of warnings) {\n\t\t\tctx.diagnostics.push(\n\t\t\t\tcreateDiagnostic(DiagnosticCode.UnknownKeyword, \"warning\", warning, {\n\t\t\t\t\tdocId: doc.docId,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\treturn `${lines.join(\"\\n\").trimEnd()}\\n`;\n\t}\n\n\tprivate exprOf(ir: IRType, doc: SourceDoc, name: string, r: RenderCtx): string {\n\t\tlet base: string;\n\t\tswitch (ir.kind) {\n\t\t\tcase \"ref\":\n\t\t\t\tbase = this.refExpr(ir.ref, doc, name, r);\n\t\t\t\tbreak;\n\t\t\tcase \"string\":\n\t\t\t\tbase = this.stringExpr(ir);\n\t\t\t\tbreak;\n\t\t\tcase \"integer\":\n\t\t\tcase \"number\":\n\t\t\t\tbase = this.numberExpr(ir);\n\t\t\t\tbreak;\n\t\t\tcase \"boolean\":\n\t\t\t\tbase = ir.const !== undefined ? `z.literal(${ir.const})` : \"z.boolean()\";\n\t\t\t\tbreak;\n\t\t\tcase \"null\":\n\t\t\t\tbase = \"z.null()\";\n\t\t\t\tbreak;\n\t\t\tcase \"literal\":\n\t\t\t\tbase = `z.literal(${literal(ir.value)})`;\n\t\t\t\tbreak;\n\t\t\tcase \"array\":\n\t\t\t\tbase = this.arrayExpr(ir, doc, name, r);\n\t\t\t\tbreak;\n\t\t\tcase \"tuple\":\n\t\t\t\tbase = this.tupleExpr(ir, doc, name, r);\n\t\t\t\tbreak;\n\t\t\tcase \"object\":\n\t\t\t\tbase = this.objectExpr(ir, doc, name, r);\n\t\t\t\tbreak;\n\t\t\tcase \"record\":\n\t\t\t\tbase = `z.record(z.string(), ${this.exprOf(ir.values, doc, name, r)})`;\n\t\t\t\tbreak;\n\t\t\tcase \"union\": {\n\t\t\t\tif (ir.variants.length === 0) {\n\t\t\t\t\tbase = \"z.never()\";\n\t\t\t\t} else if (ir.variants.length === 1) {\n\t\t\t\t\tconst single = ir.variants[0];\n\t\t\t\t\tbase = single ? this.exprOf(single, doc, name, r) : \"z.never()\";\n\t\t\t\t} else {\n\t\t\t\t\tbase = `z.union([${ir.variants.map(v => this.exprOf(v, doc, name, r)).join(\", \")}])`;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"intersection\": {\n\t\t\t\tif (ir.variants.length === 0) {\n\t\t\t\t\tbase = \"z.unknown()\";\n\t\t\t\t} else {\n\t\t\t\t\tbase = ir.variants\n\t\t\t\t\t\t.map(v => this.exprOf(v, doc, name, r))\n\t\t\t\t\t\t.reduce((acc, v) => `z.intersection(${acc}, ${v})`);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"unknown\":\n\t\t\t\tbase = \"z.unknown()\";\n\t\t\t\tbreak;\n\t\t}\n\t\tif (ir.meta?.description) {\n\t\t\tbase = `${base}.describe(${JSON.stringify(ir.meta.description)})`;\n\t\t}\n\t\treturn base;\n\t}\n\n\tprivate refExpr(ref: Ref, doc: SourceDoc, name: string, r: RenderCtx): string {\n\t\tconst target = r.byId.get(ref.docId);\n\t\tconst exportName = target\n\t\t\t? r.ctx.resolveExportName(target, ref.exportName)\n\t\t\t: ref.exportName;\n\t\tif (r.graph.needsLazy(nodeId(doc.docId, name), nodeId(ref.docId, ref.exportName))) {\n\t\t\treturn `z.lazy(() => ${exportName})`;\n\t\t}\n\t\treturn exportName;\n\t}\n\n\t/** Ref renderer for structural aliases of cyclic exports. */\n\tprivate aliasRefExpr(ref: Ref, doc: SourceDoc, r: RenderCtx): string {\n\t\tif (ref.docId === doc.docId) {\n\t\t\tif (!doc.exports.has(ref.exportName)) {\n\t\t\t\treturn \"unknown\";\n\t\t\t}\n\t\t\tconst resolved = r.ctx.resolveExportName(doc, ref.exportName);\n\t\t\tif (r.graph.isCyclic(nodeId(doc.docId, ref.exportName))) {\n\t\t\t\treturn resolved;\n\t\t\t}\n\t\t\treturn `z.infer<typeof ${resolved}>`;\n\t\t}\n\t\tconst target = r.byId.get(ref.docId);\n\t\tif (!target) {\n\t\t\treturn \"unknown\";\n\t\t}\n\t\tconst exportName = r.ctx.resolveExportName(target, ref.exportName);\n\t\tif (r.graph.isCyclic(nodeId(ref.docId, ref.exportName))) {\n\t\t\treturn exportName;\n\t\t}\n\t\treturn `z.infer<typeof ${exportName}>`;\n\t}\n\n\tprivate stringExpr(ir: Extract<IRType, { kind: \"string\" }>): string {\n\t\tif (ir.const !== undefined) {\n\t\t\treturn `z.literal(${JSON.stringify(ir.const)})`;\n\t\t}\n\t\tif (ir.enum) {\n\t\t\tif (ir.enum.length === 0) {\n\t\t\t\treturn \"z.string()\";\n\t\t\t}\n\t\t\treturn `z.enum([${ir.enum.map(v => JSON.stringify(v)).join(\", \")}])`;\n\t\t}\n\t\tlet expr = stringFormatBase(ir.format);\n\t\tif (ir.minLength !== undefined) {\n\t\t\texpr += `.min(${ir.minLength})`;\n\t\t}\n\t\tif (ir.maxLength !== undefined) {\n\t\t\texpr += `.max(${ir.maxLength})`;\n\t\t}\n\t\tif (ir.pattern !== undefined) {\n\t\t\texpr += `.regex(${regexLiteral(ir.pattern)})`;\n\t\t}\n\t\treturn expr;\n\t}\n\n\tprivate numberExpr(ir: Extract<IRType, { kind: \"number\" | \"integer\" }>): string {\n\t\tif (ir.const !== undefined) {\n\t\t\treturn `z.literal(${ir.const})`;\n\t\t}\n\t\tif (ir.enum) {\n\t\t\tif (ir.enum.length === 0) {\n\t\t\t\treturn ir.kind === \"integer\" ? \"z.int()\" : \"z.number()\";\n\t\t\t}\n\t\t\treturn `z.union([${ir.enum.map(v => `z.literal(${v})`).join(\", \")}])`;\n\t\t}\n\t\tlet expr = ir.kind === \"integer\" ? \"z.int()\" : \"z.number()\";\n\t\tif (ir.minimum !== undefined) {\n\t\t\texpr += `.min(${ir.minimum})`;\n\t\t}\n\t\tif (ir.maximum !== undefined) {\n\t\t\texpr += `.max(${ir.maximum})`;\n\t\t}\n\t\tif (ir.exclusiveMinimum !== undefined) {\n\t\t\texpr += `.gt(${ir.exclusiveMinimum})`;\n\t\t}\n\t\tif (ir.exclusiveMaximum !== undefined) {\n\t\t\texpr += `.lt(${ir.exclusiveMaximum})`;\n\t\t}\n\t\tif (ir.multipleOf !== undefined) {\n\t\t\texpr += `.multipleOf(${ir.multipleOf})`;\n\t\t}\n\t\treturn expr;\n\t}\n\n\tprivate arrayExpr(\n\t\tir: Extract<IRType, { kind: \"array\" }>,\n\t\tdoc: SourceDoc,\n\t\tname: string,\n\t\tr: RenderCtx,\n\t): string {\n\t\tconst items = ir.items ? this.exprOf(ir.items, doc, name, r) : \"z.unknown()\";\n\t\tlet expr = `z.array(${items})`;\n\t\tif (ir.minItems !== undefined) {\n\t\t\texpr += `.min(${ir.minItems})`;\n\t\t}\n\t\tif (ir.maxItems !== undefined) {\n\t\t\texpr += `.max(${ir.maxItems})`;\n\t\t}\n\t\tif (ir.uniqueItems === true) {\n\t\t\tr.warnings.push(\"uniqueItems is not supported by the zod target and was ignored\");\n\t\t}\n\t\treturn expr;\n\t}\n\n\tprivate tupleExpr(\n\t\tir: Extract<IRType, { kind: \"tuple\" }>,\n\t\tdoc: SourceDoc,\n\t\tname: string,\n\t\tr: RenderCtx,\n\t): string {\n\t\tconst items = ir.items.map(i => this.exprOf(i, doc, name, r)).join(\", \");\n\t\tlet expr = `z.tuple([${items}])`;\n\t\tif (ir.additionalItems) {\n\t\t\texpr += `.rest(${this.exprOf(ir.additionalItems, doc, name, r)})`;\n\t\t}\n\t\treturn expr;\n\t}\n\n\tprivate objectExpr(\n\t\tir: Extract<IRType, { kind: \"object\" }>,\n\t\tdoc: SourceDoc,\n\t\tname: string,\n\t\tr: RenderCtx,\n\t): string {\n\t\tconst required = new Set(ir.required);\n\t\tconst parts: string[] = [];\n\t\tfor (const [key, val] of ir.properties) {\n\t\t\tlet expr = this.exprOf(val, doc, name, r);\n\t\t\tconst hasDefault =\n\t\t\t\tr.ctx.options.defaults &&\n\t\t\t\tval.meta?.default !== undefined &&\n\t\t\t\tdefaultMatches(val, val.meta.default);\n\t\t\tif (hasDefault) {\n\t\t\t\texpr = `${expr}.default(${JSON.stringify(val.meta?.default)})`;\n\t\t\t} else if (!required.has(key)) {\n\t\t\t\texpr = `${expr}.optional()`;\n\t\t\t} else if (\n\t\t\t\tr.ctx.options.defaults &&\n\t\t\t\tval.meta?.default !== undefined &&\n\t\t\t\t!defaultMatches(val, val.meta.default)\n\t\t\t) {\n\t\t\t\tr.warnings.push(\n\t\t\t\t\t`default ${JSON.stringify(val.meta.default)} does not match schema type and was ignored`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tparts.push(`${quoteKey(key)}: ${expr}`);\n\t\t}\n\t\tlet expr = parts.length === 0 ? \"z.object({})\" : `z.object({ ${parts.join(\", \")} })`;\n\t\tif (ir.additionalProperties === false) {\n\t\t\texpr = `${expr}.strict()`;\n\t\t} else if (ir.additionalProperties) {\n\t\t\texpr = `${expr}.catchall(${this.exprOf(ir.additionalProperties, doc, name, r)})`;\n\t\t}\n\t\treturn expr;\n\t}\n}\n\nfunction stringFormatBase(format: string | undefined): string {\n\tswitch (format) {\n\t\tcase \"uuid\":\n\t\t\treturn \"z.uuid()\";\n\t\tcase \"email\":\n\t\t\treturn \"z.email()\";\n\t\tcase \"uri\":\n\t\tcase \"url\":\n\t\t\treturn \"z.url()\";\n\t\tcase \"date\":\n\t\t\treturn \"z.iso.date()\";\n\t\tcase \"date-time\":\n\t\t\treturn \"z.iso.datetime()\";\n\t\tcase \"time\":\n\t\t\treturn \"z.iso.time()\";\n\t\tdefault:\n\t\t\treturn \"z.string()\";\n\t}\n}\n"],"mappings":"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"}