@gabrielbryk/json-schema-to-zod 2.10.0 → 2.11.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 (138) hide show
  1. package/AGENTS.md +44 -0
  2. package/CHANGELOG.md +35 -0
  3. package/README.md +6 -33
  4. package/check-types-lift.sh +23 -0
  5. package/check-types.sh +20 -0
  6. package/dist/{esm/cli.js → cli.js} +0 -6
  7. package/dist/{esm/core → core}/analyzeSchema.js +4 -5
  8. package/dist/core/emitZod.js +263 -0
  9. package/dist/{esm/generators → generators}/generateBundle.js +225 -67
  10. package/dist/{esm/index.js → index.js} +6 -0
  11. package/dist/jsonSchemaToZod.js +17 -0
  12. package/dist/parsers/parseAllOf.js +125 -0
  13. package/dist/parsers/parseAnyOf.js +28 -0
  14. package/dist/{esm/parsers → parsers}/parseArray.js +27 -11
  15. package/dist/parsers/parseBoolean.js +4 -0
  16. package/dist/parsers/parseConst.js +22 -0
  17. package/dist/parsers/parseEnum.js +35 -0
  18. package/dist/{esm/parsers → parsers}/parseIfThenElse.js +11 -7
  19. package/dist/parsers/parseMultipleType.js +10 -0
  20. package/dist/parsers/parseNot.js +14 -0
  21. package/dist/parsers/parseNull.js +4 -0
  22. package/dist/parsers/parseNullable.js +12 -0
  23. package/dist/{esm/parsers → parsers}/parseNumber.js +4 -1
  24. package/dist/{esm/parsers → parsers}/parseObject.js +168 -29
  25. package/dist/parsers/parseOneOf.js +365 -0
  26. package/dist/{esm/parsers → parsers}/parseSchema.js +56 -110
  27. package/dist/parsers/parseSimpleDiscriminatedOneOf.js +24 -0
  28. package/dist/{esm/parsers → parsers}/parseString.js +29 -18
  29. package/dist/types/Types.d.ts +32 -4
  30. package/dist/types/core/analyzeSchema.d.ts +3 -2
  31. package/dist/types/generators/generateBundle.d.ts +0 -2
  32. package/dist/types/index.d.ts +6 -0
  33. package/dist/types/parsers/parseAllOf.d.ts +2 -2
  34. package/dist/types/parsers/parseAnyOf.d.ts +2 -2
  35. package/dist/types/parsers/parseArray.d.ts +2 -2
  36. package/dist/types/parsers/parseBoolean.d.ts +2 -1
  37. package/dist/types/parsers/parseConst.d.ts +2 -2
  38. package/dist/types/parsers/parseDefault.d.ts +2 -2
  39. package/dist/types/parsers/parseEnum.d.ts +2 -2
  40. package/dist/types/parsers/parseIfThenElse.d.ts +2 -2
  41. package/dist/types/parsers/parseMultipleType.d.ts +2 -2
  42. package/dist/types/parsers/parseNot.d.ts +2 -2
  43. package/dist/types/parsers/parseNull.d.ts +2 -1
  44. package/dist/types/parsers/parseNullable.d.ts +2 -2
  45. package/dist/types/parsers/parseNumber.d.ts +2 -2
  46. package/dist/types/parsers/parseObject.d.ts +2 -2
  47. package/dist/types/parsers/parseOneOf.d.ts +2 -2
  48. package/dist/types/parsers/parseSchema.d.ts +2 -2
  49. package/dist/types/parsers/parseSimpleDiscriminatedOneOf.d.ts +2 -2
  50. package/dist/types/parsers/parseString.d.ts +2 -2
  51. package/dist/types/utils/anyOrUnknown.d.ts +5 -4
  52. package/dist/types/utils/esmEmitter.d.ts +29 -0
  53. package/dist/types/utils/extractInlineObject.d.ts +15 -0
  54. package/dist/types/utils/liftInlineObjects.d.ts +21 -0
  55. package/dist/types/utils/namingService.d.ts +21 -0
  56. package/dist/types/utils/resolveRef.d.ts +7 -0
  57. package/dist/types/utils/schemaRepresentation.d.ts +71 -0
  58. package/dist/utils/anyOrUnknown.js +13 -0
  59. package/dist/{esm/utils → utils}/buildRefRegistry.js +4 -0
  60. package/dist/utils/esmEmitter.js +87 -0
  61. package/dist/utils/extractInlineObject.js +119 -0
  62. package/dist/utils/liftInlineObjects.js +476 -0
  63. package/dist/utils/namingService.js +58 -0
  64. package/dist/utils/resolveRef.js +92 -0
  65. package/dist/utils/schemaRepresentation.js +569 -0
  66. package/docs/IMPROVEMENT-PLAN.md +243 -0
  67. package/docs/ZOD-V4-RECURSIVE-TYPE-LIMITATIONS.md +292 -0
  68. package/docs/proposals/bundle-refactor.md +1 -1
  69. package/docs/proposals/discriminated-union-with-default.md +248 -0
  70. package/docs/proposals/inline-object-lifting.md +77 -0
  71. package/eslint.config.js +4 -2
  72. package/jest.config.mjs +19 -0
  73. package/package.json +17 -20
  74. package/scripts/generateWorkflowSchema.ts +0 -1
  75. package/dist/cjs/Types.js +0 -2
  76. package/dist/cjs/cli.js +0 -70
  77. package/dist/cjs/core/analyzeSchema.js +0 -62
  78. package/dist/cjs/core/emitZod.js +0 -141
  79. package/dist/cjs/generators/generateBundle.js +0 -365
  80. package/dist/cjs/index.js +0 -50
  81. package/dist/cjs/jsonSchemaToZod.js +0 -10
  82. package/dist/cjs/package.json +0 -1
  83. package/dist/cjs/parsers/parseAllOf.js +0 -46
  84. package/dist/cjs/parsers/parseAnyOf.js +0 -18
  85. package/dist/cjs/parsers/parseArray.js +0 -90
  86. package/dist/cjs/parsers/parseBoolean.js +0 -5
  87. package/dist/cjs/parsers/parseConst.js +0 -7
  88. package/dist/cjs/parsers/parseDefault.js +0 -8
  89. package/dist/cjs/parsers/parseEnum.js +0 -21
  90. package/dist/cjs/parsers/parseIfThenElse.js +0 -35
  91. package/dist/cjs/parsers/parseMultipleType.js +0 -10
  92. package/dist/cjs/parsers/parseNot.js +0 -12
  93. package/dist/cjs/parsers/parseNull.js +0 -5
  94. package/dist/cjs/parsers/parseNullable.js +0 -12
  95. package/dist/cjs/parsers/parseNumber.js +0 -116
  96. package/dist/cjs/parsers/parseObject.js +0 -315
  97. package/dist/cjs/parsers/parseOneOf.js +0 -53
  98. package/dist/cjs/parsers/parseSchema.js +0 -411
  99. package/dist/cjs/parsers/parseSimpleDiscriminatedOneOf.js +0 -21
  100. package/dist/cjs/parsers/parseString.js +0 -317
  101. package/dist/cjs/utils/anyOrUnknown.js +0 -14
  102. package/dist/cjs/utils/buildRefRegistry.js +0 -56
  103. package/dist/cjs/utils/cliTools.js +0 -108
  104. package/dist/cjs/utils/cycles.js +0 -113
  105. package/dist/cjs/utils/half.js +0 -7
  106. package/dist/cjs/utils/jsdocs.js +0 -20
  107. package/dist/cjs/utils/omit.js +0 -11
  108. package/dist/cjs/utils/resolveUri.js +0 -16
  109. package/dist/cjs/utils/withMessage.js +0 -21
  110. package/dist/cjs/zodToJsonSchema.js +0 -89
  111. package/dist/esm/core/emitZod.js +0 -137
  112. package/dist/esm/jsonSchemaToZod.js +0 -6
  113. package/dist/esm/package.json +0 -1
  114. package/dist/esm/parsers/parseAllOf.js +0 -43
  115. package/dist/esm/parsers/parseAnyOf.js +0 -14
  116. package/dist/esm/parsers/parseBoolean.js +0 -1
  117. package/dist/esm/parsers/parseConst.js +0 -3
  118. package/dist/esm/parsers/parseEnum.js +0 -17
  119. package/dist/esm/parsers/parseMultipleType.js +0 -6
  120. package/dist/esm/parsers/parseNot.js +0 -8
  121. package/dist/esm/parsers/parseNull.js +0 -1
  122. package/dist/esm/parsers/parseNullable.js +0 -8
  123. package/dist/esm/parsers/parseOneOf.js +0 -49
  124. package/dist/esm/parsers/parseSimpleDiscriminatedOneOf.js +0 -17
  125. package/dist/esm/utils/anyOrUnknown.js +0 -10
  126. package/jest.config.cjs +0 -4
  127. package/postcjs.cjs +0 -1
  128. package/postesm.cjs +0 -1
  129. /package/dist/{esm/Types.js → Types.js} +0 -0
  130. /package/dist/{esm/parsers → parsers}/parseDefault.js +0 -0
  131. /package/dist/{esm/utils → utils}/cliTools.js +0 -0
  132. /package/dist/{esm/utils → utils}/cycles.js +0 -0
  133. /package/dist/{esm/utils → utils}/half.js +0 -0
  134. /package/dist/{esm/utils → utils}/jsdocs.js +0 -0
  135. /package/dist/{esm/utils → utils}/omit.js +0 -0
  136. /package/dist/{esm/utils → utils}/resolveUri.js +0 -0
  137. /package/dist/{esm/utils → utils}/withMessage.js +0 -0
  138. /package/dist/{esm/zodToJsonSchema.js → zodToJsonSchema.js} +0 -0
@@ -1,53 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseOneOf = void 0;
4
- const parseSchema_js_1 = require("./parseSchema.js");
5
- const anyOrUnknown_js_1 = require("../utils/anyOrUnknown.js");
6
- const parseOneOf = (schema, refs) => {
7
- if (!schema.oneOf.length) {
8
- return (0, anyOrUnknown_js_1.anyOrUnknown)(refs);
9
- }
10
- if (schema.oneOf.length === 1) {
11
- return (0, parseSchema_js_1.parseSchema)(schema.oneOf[0], {
12
- ...refs,
13
- path: [...refs.path, "oneOf", 0],
14
- });
15
- }
16
- // Generate parsed schemas for each oneOf option
17
- const parsedSchemas = schema.oneOf.map((s, i) => (0, parseSchema_js_1.parseSchema)(s, {
18
- ...refs,
19
- path: [...refs.path, "oneOf", i],
20
- }));
21
- // JSON Schema oneOf = exactly one must match (exclusive OR)
22
- // Zod union = at least one must match (inclusive OR)
23
- //
24
- // By default, use simple z.union() which provides "at least one must match".
25
- // This is more practical for most use cases, as strict oneOf enforcement
26
- // often fails when schemas have overlapping base types.
27
- //
28
- // If strictOneOf is enabled, add superRefine to enforce "exactly one" constraint.
29
- if (refs.strictOneOf) {
30
- return `z.union([${parsedSchemas.join(", ")}]).superRefine((x, ctx) => {
31
- const schemas = [${parsedSchemas.join(", ")}];
32
- const errors = schemas.reduce<z.ZodError[]>(
33
- (errors, schema) =>
34
- ((result) =>
35
- result.error ? [...errors, result.error] : errors)(
36
- schema.safeParse(x),
37
- ),
38
- [],
39
- );
40
- if (schemas.length - errors.length !== 1) {
41
- ctx.addIssue({
42
- path: [],
43
- code: "invalid_union",
44
- errors: errors.map(e => e.issues),
45
- message: "Invalid input: Should pass single schema",
46
- });
47
- }
48
- })`;
49
- }
50
- // Default: use simple z.union() (at least one must match)
51
- return `z.union([${parsedSchemas.join(", ")}])`;
52
- };
53
- exports.parseOneOf = parseOneOf;
@@ -1,411 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.its = exports.parseSchema = void 0;
4
- const parseAnyOf_js_1 = require("./parseAnyOf.js");
5
- const parseBoolean_js_1 = require("./parseBoolean.js");
6
- const parseDefault_js_1 = require("./parseDefault.js");
7
- const parseMultipleType_js_1 = require("./parseMultipleType.js");
8
- const parseNot_js_1 = require("./parseNot.js");
9
- const parseNull_js_1 = require("./parseNull.js");
10
- const parseAllOf_js_1 = require("./parseAllOf.js");
11
- const parseArray_js_1 = require("./parseArray.js");
12
- const parseConst_js_1 = require("./parseConst.js");
13
- const parseEnum_js_1 = require("./parseEnum.js");
14
- const parseIfThenElse_js_1 = require("./parseIfThenElse.js");
15
- const parseNumber_js_1 = require("./parseNumber.js");
16
- const parseObject_js_1 = require("./parseObject.js");
17
- const parseString_js_1 = require("./parseString.js");
18
- const parseOneOf_js_1 = require("./parseOneOf.js");
19
- const parseSimpleDiscriminatedOneOf_js_1 = require("./parseSimpleDiscriminatedOneOf.js");
20
- const parseNullable_js_1 = require("./parseNullable.js");
21
- const anyOrUnknown_js_1 = require("../utils/anyOrUnknown.js");
22
- const resolveUri_js_1 = require("../utils/resolveUri.js");
23
- const buildRefRegistry_js_1 = require("../utils/buildRefRegistry.js");
24
- const parseSchema = (schema, refs = { seen: new Map(), path: [] }, blockMeta) => {
25
- // Ensure ref bookkeeping exists so $ref declarations and getter-based recursion work
26
- refs.root = refs.root ?? schema;
27
- refs.rootBaseUri = refs.rootBaseUri ?? "root:///";
28
- refs.declarations = refs.declarations ?? new Map();
29
- refs.dependencies = refs.dependencies ?? new Map();
30
- refs.inProgress = refs.inProgress ?? new Set();
31
- refs.refNameByPointer = refs.refNameByPointer ?? new Map();
32
- refs.usedNames = refs.usedNames ?? new Set();
33
- if (typeof schema !== "object")
34
- return schema ? (0, anyOrUnknown_js_1.anyOrUnknown)(refs) : "z.never()";
35
- const parentBase = refs.currentBaseUri ?? refs.rootBaseUri ?? "root:///";
36
- const baseUri = typeof schema.$id === "string" ? (0, resolveUri_js_1.resolveUri)(parentBase, schema.$id) : parentBase;
37
- const dynamicAnchors = Array.isArray(refs.dynamicAnchors) ? [...refs.dynamicAnchors] : [];
38
- if (typeof schema.$dynamicAnchor === "string") {
39
- dynamicAnchors.push({
40
- name: schema.$dynamicAnchor,
41
- uri: baseUri,
42
- path: refs.path,
43
- });
44
- }
45
- if (refs.parserOverride) {
46
- const custom = refs.parserOverride(schema, { ...refs, currentBaseUri: baseUri, dynamicAnchors });
47
- if (typeof custom === "string") {
48
- return custom;
49
- }
50
- }
51
- let seen = refs.seen.get(schema);
52
- if (seen) {
53
- if (seen.r !== undefined) {
54
- return seen.r;
55
- }
56
- if (refs.depth === undefined || seen.n >= refs.depth) {
57
- return (0, anyOrUnknown_js_1.anyOrUnknown)(refs);
58
- }
59
- seen.n += 1;
60
- }
61
- else {
62
- seen = { r: undefined, n: 0 };
63
- refs.seen.set(schema, seen);
64
- }
65
- if (exports.its.a.ref(schema)) {
66
- const parsedRef = parseRef(schema, { ...refs, currentBaseUri: baseUri, dynamicAnchors });
67
- seen.r = parsedRef;
68
- return parsedRef;
69
- }
70
- let parsed = selectParser(schema, { ...refs, currentBaseUri: baseUri, dynamicAnchors });
71
- if (!blockMeta) {
72
- if (!refs.withoutDescribes) {
73
- parsed = addDescribes(schema, parsed, { ...refs, currentBaseUri: baseUri, dynamicAnchors });
74
- }
75
- if (!refs.withoutDefaults) {
76
- parsed = addDefaults(schema, parsed);
77
- }
78
- parsed = addAnnotations(schema, parsed);
79
- }
80
- seen.r = parsed;
81
- return parsed;
82
- };
83
- exports.parseSchema = parseSchema;
84
- const parseRef = (schema, refs) => {
85
- const refValue = schema.$dynamicRef ?? schema.$ref;
86
- if (typeof refValue !== "string") {
87
- return (0, anyOrUnknown_js_1.anyOrUnknown)(refs);
88
- }
89
- const resolved = resolveRef(schema, refValue, refs);
90
- if (!resolved) {
91
- refs.onUnresolvedRef?.(refValue, refs.path);
92
- return (0, anyOrUnknown_js_1.anyOrUnknown)(refs);
93
- }
94
- const { schema: target, path, pointerKey } = resolved;
95
- const refName = getOrCreateRefName(pointerKey, path, refs);
96
- if (!refs.declarations.has(refName) && !refs.inProgress.has(refName)) {
97
- refs.inProgress.add(refName);
98
- const declaration = (0, exports.parseSchema)(target, {
99
- ...refs,
100
- path,
101
- currentBaseUri: resolved.baseUri,
102
- currentSchemaName: refName,
103
- root: refs.root,
104
- });
105
- refs.inProgress.delete(refName);
106
- refs.declarations.set(refName, declaration);
107
- }
108
- const current = refs.currentSchemaName;
109
- if (current) {
110
- const deps = refs.dependencies;
111
- const set = deps.get(current) ?? new Set();
112
- set.add(refName);
113
- deps.set(current, set);
114
- }
115
- const currentComponent = refs.currentSchemaName
116
- ? refs.cycleComponentByName?.get(refs.currentSchemaName)
117
- : undefined;
118
- const targetComponent = refs.cycleComponentByName?.get(refName);
119
- const isSameCycle = currentComponent !== undefined &&
120
- targetComponent !== undefined &&
121
- currentComponent === targetComponent &&
122
- refs.cycleRefNames?.has(refName);
123
- // Only lazy if the ref stays inside the current strongly-connected component
124
- // (or is currently being resolved). This avoids TDZ on true cycles while
125
- // letting ordered, acyclic refs stay direct.
126
- if (isSameCycle || refs.inProgress.has(refName)) {
127
- return `z.lazy(() => ${refName})`;
128
- }
129
- return refName;
130
- };
131
- const addDescribes = (schema, parsed, refs) => {
132
- // Use .meta() for richer metadata when withMeta is enabled
133
- if (refs?.withMeta) {
134
- const meta = {};
135
- if (schema.$id)
136
- meta.id = schema.$id;
137
- if (schema.title)
138
- meta.title = schema.title;
139
- if (schema.description)
140
- meta.description = schema.description;
141
- if (schema.examples)
142
- meta.examples = schema.examples;
143
- if (schema.deprecated)
144
- meta.deprecated = schema.deprecated;
145
- if (Object.keys(meta).length > 0) {
146
- parsed += `.meta(${JSON.stringify(meta)})`;
147
- }
148
- }
149
- else if (schema.description) {
150
- parsed += `.describe(${JSON.stringify(schema.description)})`;
151
- }
152
- return parsed;
153
- };
154
- const resolveRef = (schemaNode, ref, refs) => {
155
- const base = refs.currentBaseUri ?? refs.rootBaseUri ?? "root:///";
156
- // Handle dynamicRef lookup via dynamicAnchors stack
157
- const isDynamic = typeof schemaNode.$dynamicRef === "string";
158
- if (isDynamic && refs.dynamicAnchors && ref.startsWith("#")) {
159
- const name = ref.slice(1);
160
- for (let i = refs.dynamicAnchors.length - 1; i >= 0; i -= 1) {
161
- const entry = refs.dynamicAnchors[i];
162
- if (entry.name === name) {
163
- const key = `${entry.uri}#${name}`;
164
- const target = refs.refRegistry?.get(key);
165
- if (target) {
166
- return { schema: target.schema, path: target.path, baseUri: target.baseUri, pointerKey: key };
167
- }
168
- }
169
- }
170
- }
171
- // Resolve URI against base
172
- const resolvedUri = (0, resolveUri_js_1.resolveUri)(base, ref);
173
- const [uriBase, fragment] = resolvedUri.split("#");
174
- const key = fragment ? `${uriBase}#${fragment}` : uriBase;
175
- let regEntry = refs.refRegistry?.get(key);
176
- if (regEntry) {
177
- return { schema: regEntry.schema, path: regEntry.path, baseUri: regEntry.baseUri, pointerKey: key };
178
- }
179
- // Legacy recursive ref: treat as dynamic to __recursive__
180
- if (schemaNode.$recursiveRef) {
181
- const recursiveKey = `${base}#__recursive__`;
182
- regEntry = refs.refRegistry?.get(recursiveKey);
183
- if (regEntry) {
184
- return {
185
- schema: regEntry.schema,
186
- path: regEntry.path,
187
- baseUri: regEntry.baseUri,
188
- pointerKey: recursiveKey,
189
- };
190
- }
191
- }
192
- // External resolver hook
193
- const extBase = uriBaseFromRef(resolvedUri);
194
- if (refs.resolveExternalRef && extBase && !isLocalBase(extBase, refs.rootBaseUri ?? "")) {
195
- const loaded = refs.resolveExternalRef(extBase);
196
- if (loaded) {
197
- // If async resolver is used synchronously here, it will be ignored; keep simple sync for now
198
- const maybePromise = loaded;
199
- const schema = typeof maybePromise.then === "function"
200
- ? undefined
201
- : loaded;
202
- if (schema) {
203
- const { registry } = (0, buildRefRegistry_js_1.buildRefRegistry)(schema, extBase);
204
- registry.forEach((entry, k) => refs.refRegistry?.set(k, entry));
205
- regEntry = refs.refRegistry?.get(key);
206
- if (regEntry) {
207
- return {
208
- schema: regEntry.schema,
209
- path: regEntry.path,
210
- baseUri: regEntry.baseUri,
211
- pointerKey: key,
212
- };
213
- }
214
- }
215
- }
216
- }
217
- // Backward compatibility: JSON Pointer into root
218
- if (refs.root && ref.startsWith("#/")) {
219
- const rawSegments = ref
220
- .slice(2)
221
- .split("/")
222
- .filter((segment) => segment.length > 0)
223
- .map(decodePointerSegment);
224
- let current = refs.root;
225
- for (const segment of rawSegments) {
226
- if (typeof current !== "object" || current === null)
227
- return undefined;
228
- current = current[segment];
229
- }
230
- return { schema: current, path: rawSegments, baseUri: base, pointerKey: ref };
231
- }
232
- return undefined;
233
- };
234
- const decodePointerSegment = (segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~");
235
- const uriBaseFromRef = (resolvedUri) => {
236
- const hashIdx = resolvedUri.indexOf("#");
237
- return hashIdx === -1 ? resolvedUri : resolvedUri.slice(0, hashIdx);
238
- };
239
- const isLocalBase = (base, rootBase) => {
240
- if (!rootBase)
241
- return false;
242
- return base === rootBase;
243
- };
244
- const getOrCreateRefName = (pointer, path, refs) => {
245
- if (refs.refNameByPointer?.has(pointer)) {
246
- return refs.refNameByPointer.get(pointer);
247
- }
248
- const preferred = buildNameFromPath(path, refs.usedNames);
249
- refs.refNameByPointer?.set(pointer, preferred);
250
- refs.usedNames?.add(preferred);
251
- return preferred;
252
- };
253
- const buildNameFromPath = (path, used) => {
254
- const filtered = path
255
- .map((segment, idx) => {
256
- if (idx === 0 && (segment === "$defs" || segment === "definitions")) {
257
- return undefined; // root-level defs prefix is redundant for naming
258
- }
259
- if (segment === "properties")
260
- return undefined; // skip noisy properties segment
261
- if (segment === "$defs" || segment === "definitions")
262
- return "Defs";
263
- return segment;
264
- })
265
- .filter((segment) => segment !== undefined);
266
- const base = filtered.length
267
- ? filtered
268
- .map((segment) => typeof segment === "number"
269
- ? `Ref${segment}`
270
- : segment
271
- .toString()
272
- .replace(/[^a-zA-Z0-9_$]/g, " ")
273
- .split(" ")
274
- .filter(Boolean)
275
- .map(capitalize)
276
- .join(""))
277
- .join("")
278
- : "Ref";
279
- const sanitized = sanitizeIdentifier(base || "Ref");
280
- if (!used || !used.has(sanitized))
281
- return sanitized;
282
- let counter = 2;
283
- let candidate = `${sanitized}${counter}`;
284
- while (used.has(candidate)) {
285
- counter += 1;
286
- candidate = `${sanitized}${counter}`;
287
- }
288
- return candidate;
289
- };
290
- const sanitizeIdentifier = (value) => {
291
- const cleaned = value.replace(/^[^a-zA-Z_$]+/, "").replace(/[^a-zA-Z0-9_$]/g, "");
292
- return cleaned || "Ref";
293
- };
294
- const capitalize = (value) => value.length ? value[0].toUpperCase() + value.slice(1) : value;
295
- const addDefaults = (schema, parsed) => {
296
- if (schema.default !== undefined) {
297
- parsed += `.default(${JSON.stringify(schema.default)})`;
298
- }
299
- return parsed;
300
- };
301
- const addAnnotations = (schema, parsed) => {
302
- if (schema.readOnly) {
303
- parsed += ".readonly()";
304
- }
305
- return parsed;
306
- };
307
- const selectParser = (schema, refs) => {
308
- if (exports.its.a.nullable(schema)) {
309
- return (0, parseNullable_js_1.parseNullable)(schema, refs);
310
- }
311
- else if (exports.its.an.object(schema)) {
312
- return (0, parseObject_js_1.parseObject)(schema, refs);
313
- }
314
- else if (exports.its.an.array(schema)) {
315
- return (0, parseArray_js_1.parseArray)(schema, refs);
316
- }
317
- else if (exports.its.an.anyOf(schema)) {
318
- return (0, parseAnyOf_js_1.parseAnyOf)(schema, refs);
319
- }
320
- else if (exports.its.an.allOf(schema)) {
321
- return (0, parseAllOf_js_1.parseAllOf)(schema, refs);
322
- }
323
- else if (exports.its.a.simpleDiscriminatedOneOf(schema)) {
324
- return (0, parseSimpleDiscriminatedOneOf_js_1.parseSimpleDiscriminatedOneOf)(schema, refs);
325
- }
326
- else if (exports.its.a.oneOf(schema)) {
327
- return (0, parseOneOf_js_1.parseOneOf)(schema, refs);
328
- }
329
- else if (exports.its.a.not(schema)) {
330
- return (0, parseNot_js_1.parseNot)(schema, refs);
331
- }
332
- else if (exports.its.an.enum(schema)) {
333
- return (0, parseEnum_js_1.parseEnum)(schema); //<-- needs to come before primitives
334
- }
335
- else if (exports.its.a.const(schema)) {
336
- return (0, parseConst_js_1.parseConst)(schema);
337
- }
338
- else if (exports.its.a.multipleType(schema)) {
339
- return (0, parseMultipleType_js_1.parseMultipleType)(schema, refs);
340
- }
341
- else if (exports.its.a.primitive(schema, "string")) {
342
- return (0, parseString_js_1.parseString)(schema, refs);
343
- }
344
- else if (exports.its.a.primitive(schema, "number") ||
345
- exports.its.a.primitive(schema, "integer")) {
346
- return (0, parseNumber_js_1.parseNumber)(schema);
347
- }
348
- else if (exports.its.a.primitive(schema, "boolean")) {
349
- return (0, parseBoolean_js_1.parseBoolean)();
350
- }
351
- else if (exports.its.a.primitive(schema, "null")) {
352
- return (0, parseNull_js_1.parseNull)();
353
- }
354
- else if (exports.its.a.conditional(schema)) {
355
- return (0, parseIfThenElse_js_1.parseIfThenElse)(schema, refs);
356
- }
357
- else {
358
- return (0, parseDefault_js_1.parseDefault)(schema, refs);
359
- }
360
- };
361
- exports.its = {
362
- an: {
363
- object: (x) => x.type === "object",
364
- array: (x) => x.type === "array",
365
- anyOf: (x) => x.anyOf !== undefined,
366
- allOf: (x) => x.allOf !== undefined,
367
- enum: (x) => x.enum !== undefined,
368
- },
369
- a: {
370
- nullable: (x) => x.nullable === true,
371
- multipleType: (x) => Array.isArray(x.type),
372
- not: (x) => x.not !== undefined,
373
- ref: (x) => typeof x.$ref === "string" || typeof x.$dynamicRef === "string",
374
- const: (x) => x.const !== undefined,
375
- primitive: (x, p) => x.type === p,
376
- conditional: (x) => Boolean("if" in x && x.if && "then" in x && "else" in x && x.then && x.else),
377
- simpleDiscriminatedOneOf: (x) => {
378
- if (!x.oneOf ||
379
- !Array.isArray(x.oneOf) ||
380
- x.oneOf.length === 0 ||
381
- !x.discriminator ||
382
- typeof x.discriminator !== "object" ||
383
- !("propertyName" in x.discriminator) ||
384
- typeof x.discriminator.propertyName !== "string") {
385
- return false;
386
- }
387
- const discriminatorProp = x.discriminator.propertyName;
388
- return x.oneOf.every((schema) => {
389
- if (!schema ||
390
- typeof schema !== "object" ||
391
- schema.type !== "object" ||
392
- !schema.properties ||
393
- typeof schema.properties !== "object" ||
394
- !(discriminatorProp in schema.properties)) {
395
- return false;
396
- }
397
- const property = schema.properties[discriminatorProp];
398
- return (property &&
399
- typeof property === "object" &&
400
- (property.type === undefined || property.type === "string") &&
401
- // Ensure discriminator has a constant value (const or single-value enum)
402
- (property.const !== undefined ||
403
- (property.enum && Array.isArray(property.enum) && property.enum.length === 1)) &&
404
- // Ensure discriminator property is required
405
- Array.isArray(schema.required) &&
406
- schema.required.includes(discriminatorProp));
407
- });
408
- },
409
- oneOf: (x) => x.oneOf !== undefined,
410
- },
411
- };
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseSimpleDiscriminatedOneOf = void 0;
4
- const parseSchema_js_1 = require("./parseSchema.js");
5
- const anyOrUnknown_js_1 = require("../utils/anyOrUnknown.js");
6
- const parseSimpleDiscriminatedOneOf = (schema, refs) => {
7
- const discriminator = schema.discriminator.propertyName;
8
- const options = schema.oneOf.map((option, i) => (0, parseSchema_js_1.parseSchema)(option, {
9
- ...refs,
10
- path: [...refs.path, "oneOf", i],
11
- }));
12
- return schema.oneOf.length
13
- ? schema.oneOf.length === 1
14
- ? (0, parseSchema_js_1.parseSchema)(schema.oneOf[0], {
15
- ...refs,
16
- path: [...refs.path, "oneOf", 0],
17
- })
18
- : `z.discriminatedUnion("${discriminator}", [${options.join(", ")}])`
19
- : (0, anyOrUnknown_js_1.anyOrUnknown)(refs);
20
- };
21
- exports.parseSimpleDiscriminatedOneOf = parseSimpleDiscriminatedOneOf;