@gabrielbryk/json-schema-to-zod 2.8.0 → 2.9.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 (60) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/core/analyzeSchema.js +62 -0
  3. package/dist/cjs/core/emitZod.js +141 -0
  4. package/dist/cjs/generators/generateBundle.js +103 -59
  5. package/dist/cjs/index.js +4 -0
  6. package/dist/cjs/jsonSchemaToZod.js +5 -167
  7. package/dist/cjs/parsers/parseSchema.js +124 -24
  8. package/dist/cjs/utils/buildRefRegistry.js +56 -0
  9. package/dist/cjs/utils/resolveUri.js +16 -0
  10. package/dist/esm/Types.js +1 -2
  11. package/dist/esm/cli.js +10 -12
  12. package/dist/esm/core/analyzeSchema.js +58 -0
  13. package/dist/esm/core/emitZod.js +137 -0
  14. package/dist/esm/generators/generateBundle.js +104 -64
  15. package/dist/esm/index.js +34 -46
  16. package/dist/esm/jsonSchemaToZod.js +5 -171
  17. package/dist/esm/parsers/parseAllOf.js +5 -8
  18. package/dist/esm/parsers/parseAnyOf.js +6 -10
  19. package/dist/esm/parsers/parseArray.js +11 -15
  20. package/dist/esm/parsers/parseBoolean.js +1 -5
  21. package/dist/esm/parsers/parseConst.js +1 -5
  22. package/dist/esm/parsers/parseDefault.js +3 -7
  23. package/dist/esm/parsers/parseEnum.js +1 -5
  24. package/dist/esm/parsers/parseIfThenElse.js +5 -9
  25. package/dist/esm/parsers/parseMultipleType.js +3 -7
  26. package/dist/esm/parsers/parseNot.js +4 -8
  27. package/dist/esm/parsers/parseNull.js +1 -5
  28. package/dist/esm/parsers/parseNullable.js +4 -8
  29. package/dist/esm/parsers/parseNumber.js +11 -15
  30. package/dist/esm/parsers/parseObject.js +25 -28
  31. package/dist/esm/parsers/parseOneOf.js +6 -10
  32. package/dist/esm/parsers/parseSchema.js +183 -87
  33. package/dist/esm/parsers/parseSimpleDiscriminatedOneOf.js +6 -10
  34. package/dist/esm/parsers/parseString.js +11 -15
  35. package/dist/esm/utils/anyOrUnknown.js +1 -5
  36. package/dist/esm/utils/buildRefRegistry.js +52 -0
  37. package/dist/esm/utils/cliTools.js +7 -13
  38. package/dist/esm/utils/cycles.js +3 -9
  39. package/dist/esm/utils/half.js +1 -5
  40. package/dist/esm/utils/jsdocs.js +3 -8
  41. package/dist/esm/utils/omit.js +1 -5
  42. package/dist/esm/utils/resolveUri.js +12 -0
  43. package/dist/esm/utils/withMessage.js +1 -4
  44. package/dist/esm/zodToJsonSchema.js +1 -4
  45. package/dist/types/Types.d.ts +28 -0
  46. package/dist/types/core/analyzeSchema.d.ts +24 -0
  47. package/dist/types/core/emitZod.d.ts +2 -0
  48. package/dist/types/generators/generateBundle.d.ts +5 -0
  49. package/dist/types/index.d.ts +4 -0
  50. package/dist/types/jsonSchemaToZod.d.ts +1 -1
  51. package/dist/types/parsers/parseSchema.d.ts +2 -1
  52. package/dist/types/utils/buildRefRegistry.d.ts +12 -0
  53. package/dist/types/utils/resolveUri.d.ts +1 -0
  54. package/docs/proposals/bundle-refactor.md +43 -0
  55. package/docs/proposals/ref-anchor-support.md +65 -0
  56. package/eslint.config.js +26 -0
  57. package/package.json +10 -4
  58. /package/{jest.config.js → jest.config.cjs} +0 -0
  59. /package/{postcjs.js → postcjs.cjs} +0 -0
  60. /package/{postesm.js → postesm.cjs} +0 -0
@@ -1,36 +1,48 @@
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 parseSchema = (schema, refs = { seen: new Map(), path: [] }, blockMeta) => {
1
+ import { parseAnyOf } from "./parseAnyOf.js";
2
+ import { parseBoolean } from "./parseBoolean.js";
3
+ import { parseDefault } from "./parseDefault.js";
4
+ import { parseMultipleType } from "./parseMultipleType.js";
5
+ import { parseNot } from "./parseNot.js";
6
+ import { parseNull } from "./parseNull.js";
7
+ import { parseAllOf } from "./parseAllOf.js";
8
+ import { parseArray } from "./parseArray.js";
9
+ import { parseConst } from "./parseConst.js";
10
+ import { parseEnum } from "./parseEnum.js";
11
+ import { parseIfThenElse } from "./parseIfThenElse.js";
12
+ import { parseNumber } from "./parseNumber.js";
13
+ import { parseObject } from "./parseObject.js";
14
+ import { parseString } from "./parseString.js";
15
+ import { parseOneOf } from "./parseOneOf.js";
16
+ import { parseSimpleDiscriminatedOneOf } from "./parseSimpleDiscriminatedOneOf.js";
17
+ import { parseNullable } from "./parseNullable.js";
18
+ import { anyOrUnknown } from "../utils/anyOrUnknown.js";
19
+ import { resolveUri } from "../utils/resolveUri.js";
20
+ import { buildRefRegistry } from "../utils/buildRefRegistry.js";
21
+ export const parseSchema = (schema, refs = { seen: new Map(), path: [] }, blockMeta) => {
23
22
  // Ensure ref bookkeeping exists so $ref declarations and getter-based recursion work
24
23
  refs.root = refs.root ?? schema;
24
+ refs.rootBaseUri = refs.rootBaseUri ?? "root:///";
25
25
  refs.declarations = refs.declarations ?? new Map();
26
26
  refs.dependencies = refs.dependencies ?? new Map();
27
27
  refs.inProgress = refs.inProgress ?? new Set();
28
28
  refs.refNameByPointer = refs.refNameByPointer ?? new Map();
29
29
  refs.usedNames = refs.usedNames ?? new Set();
30
30
  if (typeof schema !== "object")
31
- return schema ? (0, anyOrUnknown_js_1.anyOrUnknown)(refs) : "z.never()";
31
+ return schema ? anyOrUnknown(refs) : "z.never()";
32
+ const parentBase = refs.currentBaseUri ?? refs.rootBaseUri ?? "root:///";
33
+ const baseUri = typeof schema.$id === "string"
34
+ ? resolveUri(parentBase, schema.$id)
35
+ : parentBase;
36
+ const dynamicAnchors = Array.isArray(refs.dynamicAnchors) ? [...refs.dynamicAnchors] : [];
37
+ if (typeof schema.$dynamicAnchor === "string") {
38
+ dynamicAnchors.push({
39
+ name: schema.$dynamicAnchor,
40
+ uri: baseUri,
41
+ path: refs.path,
42
+ });
43
+ }
32
44
  if (refs.parserOverride) {
33
- const custom = refs.parserOverride(schema, refs);
45
+ const custom = refs.parserOverride(schema, { ...refs, currentBaseUri: baseUri, dynamicAnchors });
34
46
  if (typeof custom === "string") {
35
47
  return custom;
36
48
  }
@@ -41,7 +53,7 @@ const parseSchema = (schema, refs = { seen: new Map(), path: [] }, blockMeta) =>
41
53
  return seen.r;
42
54
  }
43
55
  if (refs.depth === undefined || seen.n >= refs.depth) {
44
- return (0, anyOrUnknown_js_1.anyOrUnknown)(refs);
56
+ return anyOrUnknown(refs);
45
57
  }
46
58
  seen.n += 1;
47
59
  }
@@ -49,15 +61,15 @@ const parseSchema = (schema, refs = { seen: new Map(), path: [] }, blockMeta) =>
49
61
  seen = { r: undefined, n: 0 };
50
62
  refs.seen.set(schema, seen);
51
63
  }
52
- if (exports.its.a.ref(schema)) {
53
- const parsedRef = parseRef(schema, refs);
64
+ if (its.a.ref(schema)) {
65
+ const parsedRef = parseRef(schema, { ...refs, currentBaseUri: baseUri, dynamicAnchors });
54
66
  seen.r = parsedRef;
55
67
  return parsedRef;
56
68
  }
57
- let parsed = selectParser(schema, refs);
69
+ let parsed = selectParser(schema, { ...refs, currentBaseUri: baseUri, dynamicAnchors });
58
70
  if (!blockMeta) {
59
71
  if (!refs.withoutDescribes) {
60
- parsed = addDescribes(schema, parsed, refs);
72
+ parsed = addDescribes(schema, parsed, { ...refs, currentBaseUri: baseUri, dynamicAnchors });
61
73
  }
62
74
  if (!refs.withoutDefaults) {
63
75
  parsed = addDefaults(schema, parsed);
@@ -67,19 +79,21 @@ const parseSchema = (schema, refs = { seen: new Map(), path: [] }, blockMeta) =>
67
79
  seen.r = parsed;
68
80
  return parsed;
69
81
  };
70
- exports.parseSchema = parseSchema;
71
82
  const parseRef = (schema, refs) => {
72
- const resolved = resolveRef(refs.root, schema.$ref);
83
+ const refValue = schema.$dynamicRef ?? schema.$ref;
84
+ const resolved = resolveRef(schema, refValue, refs);
73
85
  if (!resolved) {
74
- return (0, anyOrUnknown_js_1.anyOrUnknown)(refs);
86
+ refs.onUnresolvedRef?.(refValue, refs.path);
87
+ return anyOrUnknown(refs);
75
88
  }
76
- const { schema: target, path } = resolved;
77
- const refName = getOrCreateRefName(schema.$ref, path, refs);
89
+ const { schema: target, path, pointerKey } = resolved;
90
+ const refName = getOrCreateRefName(pointerKey, path, refs);
78
91
  if (!refs.declarations.has(refName) && !refs.inProgress.has(refName)) {
79
92
  refs.inProgress.add(refName);
80
- const declaration = (0, exports.parseSchema)(target, {
93
+ const declaration = parseSchema(target, {
81
94
  ...refs,
82
95
  path,
96
+ currentBaseUri: resolved.baseUri,
83
97
  currentSchemaName: refName,
84
98
  root: refs.root,
85
99
  });
@@ -132,23 +146,93 @@ const addDescribes = (schema, parsed, refs) => {
132
146
  }
133
147
  return parsed;
134
148
  };
135
- const resolveRef = (root, ref) => {
136
- if (!root || !ref.startsWith("#/"))
137
- return undefined;
138
- const rawSegments = ref
139
- .slice(2)
140
- .split("/")
141
- .filter((segment) => segment.length > 0)
142
- .map(decodePointerSegment);
143
- let current = root;
144
- for (const segment of rawSegments) {
145
- if (typeof current !== "object" || current === null)
146
- return undefined;
147
- current = current[segment];
148
- }
149
- return { schema: current, path: rawSegments };
149
+ const resolveRef = (schemaNode, ref, refs) => {
150
+ const base = refs.currentBaseUri ?? refs.rootBaseUri ?? "root:///";
151
+ // Handle dynamicRef lookup via dynamicAnchors stack
152
+ const isDynamic = typeof schemaNode.$dynamicRef === "string";
153
+ if (isDynamic && refs.dynamicAnchors && ref.startsWith("#")) {
154
+ const name = ref.slice(1);
155
+ for (let i = refs.dynamicAnchors.length - 1; i >= 0; i -= 1) {
156
+ const entry = refs.dynamicAnchors[i];
157
+ if (entry.name === name) {
158
+ const key = `${entry.uri}#${name}`;
159
+ const target = refs.refRegistry?.get(key);
160
+ if (target) {
161
+ return { schema: target.schema, path: target.path, baseUri: target.baseUri, pointerKey: key };
162
+ }
163
+ }
164
+ }
165
+ }
166
+ // Resolve URI against base
167
+ const resolvedUri = resolveUri(base, ref);
168
+ const [uriBase, fragment] = resolvedUri.split("#");
169
+ const key = fragment ? `${uriBase}#${fragment}` : uriBase;
170
+ let regEntry = refs.refRegistry?.get(key);
171
+ if (regEntry) {
172
+ return { schema: regEntry.schema, path: regEntry.path, baseUri: regEntry.baseUri, pointerKey: key };
173
+ }
174
+ // Legacy recursive ref: treat as dynamic to __recursive__
175
+ if (schemaNode.$recursiveRef) {
176
+ const recursiveKey = `${base}#__recursive__`;
177
+ regEntry = refs.refRegistry?.get(recursiveKey);
178
+ if (regEntry) {
179
+ return {
180
+ schema: regEntry.schema,
181
+ path: regEntry.path,
182
+ baseUri: regEntry.baseUri,
183
+ pointerKey: recursiveKey,
184
+ };
185
+ }
186
+ }
187
+ // External resolver hook
188
+ const extBase = uriBaseFromRef(resolvedUri);
189
+ if (refs.resolveExternalRef && extBase && !isLocalBase(extBase, refs.rootBaseUri ?? "")) {
190
+ const loaded = refs.resolveExternalRef(extBase);
191
+ if (loaded) {
192
+ // If async resolver is used synchronously here, it will be ignored; keep simple sync for now
193
+ const schema = loaded.then ? undefined : loaded;
194
+ if (schema) {
195
+ const { registry } = buildRefRegistry(schema, extBase);
196
+ registry.forEach((entry, k) => refs.refRegistry?.set(k, entry));
197
+ regEntry = refs.refRegistry?.get(key);
198
+ if (regEntry) {
199
+ return {
200
+ schema: regEntry.schema,
201
+ path: regEntry.path,
202
+ baseUri: regEntry.baseUri,
203
+ pointerKey: key,
204
+ };
205
+ }
206
+ }
207
+ }
208
+ }
209
+ // Backward compatibility: JSON Pointer into root
210
+ if (refs.root && ref.startsWith("#/")) {
211
+ const rawSegments = ref
212
+ .slice(2)
213
+ .split("/")
214
+ .filter((segment) => segment.length > 0)
215
+ .map(decodePointerSegment);
216
+ let current = refs.root;
217
+ for (const segment of rawSegments) {
218
+ if (typeof current !== "object" || current === null)
219
+ return undefined;
220
+ current = current[segment];
221
+ }
222
+ return { schema: current, path: rawSegments, baseUri: base, pointerKey: ref };
223
+ }
224
+ return undefined;
150
225
  };
151
226
  const decodePointerSegment = (segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~");
227
+ const uriBaseFromRef = (resolvedUri) => {
228
+ const hashIdx = resolvedUri.indexOf("#");
229
+ return hashIdx === -1 ? resolvedUri : resolvedUri.slice(0, hashIdx);
230
+ };
231
+ const isLocalBase = (base, rootBase) => {
232
+ if (!rootBase)
233
+ return false;
234
+ return base === rootBase;
235
+ };
152
236
  const getOrCreateRefName = (pointer, path, refs) => {
153
237
  if (refs.refNameByPointer?.has(pointer)) {
154
238
  return refs.refNameByPointer.get(pointer);
@@ -159,12 +243,24 @@ const getOrCreateRefName = (pointer, path, refs) => {
159
243
  return preferred;
160
244
  };
161
245
  const buildNameFromPath = (path, used) => {
162
- const filtered = path.filter((segment) => segment !== "$defs" && segment !== "definitions" && segment !== "properties");
246
+ const filtered = path
247
+ .map((segment, idx) => {
248
+ if (idx === 0 && (segment === "$defs" || segment === "definitions")) {
249
+ return undefined; // root-level defs prefix is redundant for naming
250
+ }
251
+ if (segment === "properties")
252
+ return undefined; // skip noisy properties segment
253
+ if (segment === "$defs" || segment === "definitions")
254
+ return "Defs";
255
+ return segment;
256
+ })
257
+ .filter((segment) => segment !== undefined);
163
258
  const base = filtered.length
164
259
  ? filtered
165
260
  .map((segment) => typeof segment === "number"
166
261
  ? `Ref${segment}`
167
262
  : segment
263
+ .toString()
168
264
  .replace(/[^a-zA-Z0-9_$]/g, " ")
169
265
  .split(" ")
170
266
  .filter(Boolean)
@@ -201,60 +297,60 @@ const addAnnotations = (schema, parsed) => {
201
297
  return parsed;
202
298
  };
203
299
  const selectParser = (schema, refs) => {
204
- if (exports.its.a.nullable(schema)) {
205
- return (0, parseNullable_js_1.parseNullable)(schema, refs);
300
+ if (its.a.nullable(schema)) {
301
+ return parseNullable(schema, refs);
206
302
  }
207
- else if (exports.its.an.object(schema)) {
208
- return (0, parseObject_js_1.parseObject)(schema, refs);
303
+ else if (its.an.object(schema)) {
304
+ return parseObject(schema, refs);
209
305
  }
210
- else if (exports.its.an.array(schema)) {
211
- return (0, parseArray_js_1.parseArray)(schema, refs);
306
+ else if (its.an.array(schema)) {
307
+ return parseArray(schema, refs);
212
308
  }
213
- else if (exports.its.an.anyOf(schema)) {
214
- return (0, parseAnyOf_js_1.parseAnyOf)(schema, refs);
309
+ else if (its.an.anyOf(schema)) {
310
+ return parseAnyOf(schema, refs);
215
311
  }
216
- else if (exports.its.an.allOf(schema)) {
217
- return (0, parseAllOf_js_1.parseAllOf)(schema, refs);
312
+ else if (its.an.allOf(schema)) {
313
+ return parseAllOf(schema, refs);
218
314
  }
219
- else if (exports.its.a.simpleDiscriminatedOneOf(schema)) {
220
- return (0, parseSimpleDiscriminatedOneOf_js_1.parseSimpleDiscriminatedOneOf)(schema, refs);
315
+ else if (its.a.simpleDiscriminatedOneOf(schema)) {
316
+ return parseSimpleDiscriminatedOneOf(schema, refs);
221
317
  }
222
- else if (exports.its.a.oneOf(schema)) {
223
- return (0, parseOneOf_js_1.parseOneOf)(schema, refs);
318
+ else if (its.a.oneOf(schema)) {
319
+ return parseOneOf(schema, refs);
224
320
  }
225
- else if (exports.its.a.not(schema)) {
226
- return (0, parseNot_js_1.parseNot)(schema, refs);
321
+ else if (its.a.not(schema)) {
322
+ return parseNot(schema, refs);
227
323
  }
228
- else if (exports.its.an.enum(schema)) {
229
- return (0, parseEnum_js_1.parseEnum)(schema); //<-- needs to come before primitives
324
+ else if (its.an.enum(schema)) {
325
+ return parseEnum(schema); //<-- needs to come before primitives
230
326
  }
231
- else if (exports.its.a.const(schema)) {
232
- return (0, parseConst_js_1.parseConst)(schema);
327
+ else if (its.a.const(schema)) {
328
+ return parseConst(schema);
233
329
  }
234
- else if (exports.its.a.multipleType(schema)) {
235
- return (0, parseMultipleType_js_1.parseMultipleType)(schema, refs);
330
+ else if (its.a.multipleType(schema)) {
331
+ return parseMultipleType(schema, refs);
236
332
  }
237
- else if (exports.its.a.primitive(schema, "string")) {
238
- return (0, parseString_js_1.parseString)(schema, refs);
333
+ else if (its.a.primitive(schema, "string")) {
334
+ return parseString(schema, refs);
239
335
  }
240
- else if (exports.its.a.primitive(schema, "number") ||
241
- exports.its.a.primitive(schema, "integer")) {
242
- return (0, parseNumber_js_1.parseNumber)(schema);
336
+ else if (its.a.primitive(schema, "number") ||
337
+ its.a.primitive(schema, "integer")) {
338
+ return parseNumber(schema);
243
339
  }
244
- else if (exports.its.a.primitive(schema, "boolean")) {
245
- return (0, parseBoolean_js_1.parseBoolean)(schema);
340
+ else if (its.a.primitive(schema, "boolean")) {
341
+ return parseBoolean(schema);
246
342
  }
247
- else if (exports.its.a.primitive(schema, "null")) {
248
- return (0, parseNull_js_1.parseNull)(schema);
343
+ else if (its.a.primitive(schema, "null")) {
344
+ return parseNull(schema);
249
345
  }
250
- else if (exports.its.a.conditional(schema)) {
251
- return (0, parseIfThenElse_js_1.parseIfThenElse)(schema, refs);
346
+ else if (its.a.conditional(schema)) {
347
+ return parseIfThenElse(schema, refs);
252
348
  }
253
349
  else {
254
- return (0, parseDefault_js_1.parseDefault)(schema, refs);
350
+ return parseDefault(schema, refs);
255
351
  }
256
352
  };
257
- exports.its = {
353
+ export const its = {
258
354
  an: {
259
355
  object: (x) => x.type === "object",
260
356
  array: (x) => x.type === "array",
@@ -266,7 +362,7 @@ exports.its = {
266
362
  nullable: (x) => x.nullable === true,
267
363
  multipleType: (x) => Array.isArray(x.type),
268
364
  not: (x) => x.not !== undefined,
269
- ref: (x) => typeof x.$ref === "string",
365
+ ref: (x) => typeof x.$ref === "string" || typeof x.$dynamicRef === "string",
270
366
  const: (x) => x.const !== undefined,
271
367
  primitive: (x, p) => x.type === p,
272
368
  conditional: (x) => Boolean("if" in x && x.if && "then" in x && "else" in x && x.then && x.else),
@@ -1,21 +1,17 @@
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) => {
1
+ import { parseSchema } from "./parseSchema.js";
2
+ import { anyOrUnknown } from "../utils/anyOrUnknown.js";
3
+ export const parseSimpleDiscriminatedOneOf = (schema, refs) => {
7
4
  const discriminator = schema.discriminator.propertyName;
8
- const options = schema.oneOf.map((option, i) => (0, parseSchema_js_1.parseSchema)(option, {
5
+ const options = schema.oneOf.map((option, i) => parseSchema(option, {
9
6
  ...refs,
10
7
  path: [...refs.path, "oneOf", i],
11
8
  }));
12
9
  return schema.oneOf.length
13
10
  ? schema.oneOf.length === 1
14
- ? (0, parseSchema_js_1.parseSchema)(schema.oneOf[0], {
11
+ ? parseSchema(schema.oneOf[0], {
15
12
  ...refs,
16
13
  path: [...refs.path, "oneOf", 0],
17
14
  })
18
15
  : `z.discriminatedUnion("${discriminator}", [${options.join(", ")}])`
19
- : (0, anyOrUnknown_js_1.anyOrUnknown)(refs);
16
+ : anyOrUnknown(refs);
20
17
  };
21
- exports.parseSimpleDiscriminatedOneOf = parseSimpleDiscriminatedOneOf;
@@ -1,9 +1,6 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseString = void 0;
4
- const withMessage_js_1 = require("../utils/withMessage.js");
5
- const parseSchema_js_1 = require("./parseSchema.js");
6
- const parseString = (schema, refs) => {
1
+ import { withMessage } from "../utils/withMessage.js";
2
+ import { parseSchema } from "./parseSchema.js";
3
+ export const parseString = (schema, refs) => {
7
4
  const formatError = schema.errorMessage?.format;
8
5
  const refContext = ensureRefs(refs);
9
6
  const topLevelFormatMap = {
@@ -29,7 +26,7 @@ const parseString = (schema, refs) => {
29
26
  const formatHandled = Boolean(formatFn);
30
27
  let formatWasHandled = formatHandled;
31
28
  if (!formatHandled) {
32
- r += (0, withMessage_js_1.withMessage)(schema, "format", ({ value }) => {
29
+ r += withMessage(schema, "format", ({ value }) => {
33
30
  switch (value) {
34
31
  case "email":
35
32
  formatWasHandled = true;
@@ -248,25 +245,25 @@ const parseString = (schema, refs) => {
248
245
  if (schema.format && !formatWasHandled) {
249
246
  refContext.onUnknownFormat?.(schema.format, refContext.path);
250
247
  }
251
- r += (0, withMessage_js_1.withMessage)(schema, "pattern", ({ json }) => ({
248
+ r += withMessage(schema, "pattern", ({ json }) => ({
252
249
  opener: `.regex(new RegExp(${json})`,
253
250
  closer: ")",
254
251
  messagePrefix: ", { error: ",
255
252
  messageCloser: " })",
256
253
  }));
257
- r += (0, withMessage_js_1.withMessage)(schema, "minLength", ({ json }) => ({
254
+ r += withMessage(schema, "minLength", ({ json }) => ({
258
255
  opener: `.min(${json}`,
259
256
  closer: ")",
260
257
  messagePrefix: ", { error: ",
261
258
  messageCloser: " })",
262
259
  }));
263
- r += (0, withMessage_js_1.withMessage)(schema, "maxLength", ({ json }) => ({
260
+ r += withMessage(schema, "maxLength", ({ json }) => ({
264
261
  opener: `.max(${json}`,
265
262
  closer: ")",
266
263
  messagePrefix: ", { error: ",
267
264
  messageCloser: " })",
268
265
  }));
269
- r += (0, withMessage_js_1.withMessage)(schema, "contentEncoding", ({ value }) => {
266
+ r += withMessage(schema, "contentEncoding", ({ value }) => {
270
267
  if (value === "base64") {
271
268
  return {
272
269
  opener: ".base64(",
@@ -276,7 +273,7 @@ const parseString = (schema, refs) => {
276
273
  };
277
274
  }
278
275
  });
279
- const contentMediaType = (0, withMessage_js_1.withMessage)(schema, "contentMediaType", ({ value }) => {
276
+ const contentMediaType = withMessage(schema, "contentMediaType", ({ value }) => {
280
277
  if (value === "application/json") {
281
278
  return {
282
279
  opener: '.transform((str, ctx) => { try { return JSON.parse(str); } catch (err) { ctx.addIssue({ code: "custom", message: "Invalid JSON" }); }}',
@@ -288,10 +285,10 @@ const parseString = (schema, refs) => {
288
285
  });
289
286
  if (contentMediaType != "") {
290
287
  r += contentMediaType;
291
- r += (0, withMessage_js_1.withMessage)(schema, "contentSchema", ({ value }) => {
288
+ r += withMessage(schema, "contentSchema", ({ value }) => {
292
289
  if (value && value instanceof Object) {
293
290
  return {
294
- opener: `.pipe(${(0, parseSchema_js_1.parseSchema)(value, refContext)}`,
291
+ opener: `.pipe(${parseSchema(value, refContext)}`,
295
292
  closer: ")",
296
293
  messagePrefix: ", { error: ",
297
294
  messageCloser: " })",
@@ -301,7 +298,6 @@ const parseString = (schema, refs) => {
301
298
  }
302
299
  return r;
303
300
  };
304
- exports.parseString = parseString;
305
301
  function ensureRefs(refs) {
306
302
  if (refs)
307
303
  return refs;
@@ -1,6 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.anyOrUnknown = void 0;
4
1
  /**
5
2
  * Returns "z.unknown()" if the useUnknown option is enabled, otherwise "z.any()".
6
3
  * This helper is used throughout the library for fallback cases.
@@ -8,7 +5,6 @@ exports.anyOrUnknown = void 0;
8
5
  * @param refs - The refs object containing options
9
6
  * @returns The appropriate Zod schema string
10
7
  */
11
- const anyOrUnknown = (refs) => {
8
+ export const anyOrUnknown = (refs) => {
12
9
  return refs?.useUnknown ? "z.unknown()" : "z.any()";
13
10
  };
14
- exports.anyOrUnknown = anyOrUnknown;
@@ -0,0 +1,52 @@
1
+ import { resolveUri } from "./resolveUri.js";
2
+ export const buildRefRegistry = (schema, rootBaseUri = "root:///", opts = {}) => {
3
+ const registry = new Map();
4
+ const walk = (node, baseUri, path) => {
5
+ if (typeof node !== "object" || node === null)
6
+ return;
7
+ const obj = node;
8
+ const nextBase = obj.$id ? resolveUri(baseUri, obj.$id) : baseUri;
9
+ // Legacy recursive anchor
10
+ if (obj.$recursiveAnchor === true) {
11
+ const name = "__recursive__";
12
+ registry.set(`${nextBase}#${name}`, {
13
+ schema: node,
14
+ path,
15
+ baseUri: nextBase,
16
+ dynamic: true,
17
+ anchor: name,
18
+ });
19
+ }
20
+ // Register base entry
21
+ registry.set(nextBase, { schema: node, path, baseUri: nextBase });
22
+ if (typeof obj.$anchor === "string") {
23
+ registry.set(`${nextBase}#${obj.$anchor}`, {
24
+ schema: node,
25
+ path,
26
+ baseUri: nextBase,
27
+ anchor: obj.$anchor,
28
+ });
29
+ }
30
+ if (typeof obj.$dynamicAnchor === "string") {
31
+ const name = obj.$dynamicAnchor;
32
+ registry.set(`${nextBase}#${name}`, {
33
+ schema: node,
34
+ path,
35
+ baseUri: nextBase,
36
+ dynamic: true,
37
+ anchor: name,
38
+ });
39
+ }
40
+ for (const key in obj) {
41
+ const value = obj[key];
42
+ if (Array.isArray(value)) {
43
+ value.forEach((v, i) => walk(v, nextBase, [...path, key, i]));
44
+ }
45
+ else if (typeof value === "object" && value !== null) {
46
+ walk(value, nextBase, [...path, key]);
47
+ }
48
+ }
49
+ };
50
+ walk(schema, rootBaseUri, []);
51
+ return { registry, rootBaseUri };
52
+ };
@@ -1,11 +1,5 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseArgs = parseArgs;
4
- exports.parseOrReadJSON = parseOrReadJSON;
5
- exports.readPipe = readPipe;
6
- exports.printParams = printParams;
7
- const fs_1 = require("fs");
8
- function parseArgs(params, args, help) {
1
+ import { statSync, readFileSync } from "fs";
2
+ export function parseArgs(params, args, help) {
9
3
  const result = {};
10
4
  if (help) {
11
5
  let index = args.indexOf("--help");
@@ -62,15 +56,15 @@ function parseArgs(params, args, help) {
62
56
  }
63
57
  return result;
64
58
  }
65
- function parseOrReadJSON(jsonOrPath) {
59
+ export function parseOrReadJSON(jsonOrPath) {
66
60
  jsonOrPath = jsonOrPath.trim();
67
61
  if (jsonOrPath.length < 255 &&
68
- (0, fs_1.statSync)(jsonOrPath, { throwIfNoEntry: false })?.isFile()) {
69
- jsonOrPath = (0, fs_1.readFileSync)(jsonOrPath, "utf-8");
62
+ statSync(jsonOrPath, { throwIfNoEntry: false })?.isFile()) {
63
+ jsonOrPath = readFileSync(jsonOrPath, "utf-8");
70
64
  }
71
65
  return JSON.parse(jsonOrPath);
72
66
  }
73
- function readPipe() {
67
+ export function readPipe() {
74
68
  return new Promise((resolve, reject) => {
75
69
  let buf = "";
76
70
  process.stdin
@@ -85,7 +79,7 @@ function readPipe() {
85
79
  });
86
80
  });
87
81
  }
88
- function printParams(params) {
82
+ export function printParams(params) {
89
83
  const longest = Object.keys(params).reduce((l, c) => (c.length > l ? c.length : l), 5);
90
84
  const header = "Name " + " ".repeat(longest - 2) + "Short Description";
91
85
  console.log(header);
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.computeScc = exports.detectCycles = exports.findRefDependencies = void 0;
4
- const findRefDependencies = (schema, validDefNames) => {
1
+ export const findRefDependencies = (schema, validDefNames) => {
5
2
  const deps = new Set();
6
3
  function traverse(obj) {
7
4
  if (obj === null || typeof obj !== "object")
@@ -25,8 +22,7 @@ const findRefDependencies = (schema, validDefNames) => {
25
22
  traverse(schema);
26
23
  return deps;
27
24
  };
28
- exports.findRefDependencies = findRefDependencies;
29
- const detectCycles = (defNames, deps) => {
25
+ export const detectCycles = (defNames, deps) => {
30
26
  const cycleNodes = new Set();
31
27
  const visited = new Set();
32
28
  const recursionStack = new Set();
@@ -57,8 +53,7 @@ const detectCycles = (defNames, deps) => {
57
53
  }
58
54
  return cycleNodes;
59
55
  };
60
- exports.detectCycles = detectCycles;
61
- const computeScc = (defNames, deps) => {
56
+ export const computeScc = (defNames, deps) => {
62
57
  // Tarjan's algorithm, keeps mapping for quick "is this ref in my cycle?"
63
58
  const index = new Map();
64
59
  const lowlink = new Map();
@@ -110,4 +105,3 @@ const computeScc = (defNames, deps) => {
110
105
  }
111
106
  return { cycleMembers, componentByName };
112
107
  };
113
- exports.computeScc = computeScc;
@@ -1,7 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.half = void 0;
4
- const half = (arr) => {
1
+ export const half = (arr) => {
5
2
  return [arr.slice(0, arr.length / 2), arr.slice(arr.length / 2)];
6
3
  };
7
- exports.half = half;
@@ -1,7 +1,4 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.addJsdocs = exports.expandJsdocs = void 0;
4
- const expandJsdocs = (jsdocs) => {
1
+ export const expandJsdocs = (jsdocs) => {
5
2
  const lines = jsdocs.split("\n");
6
3
  const result = lines.length === 1
7
4
  ? lines[0]
@@ -9,12 +6,10 @@ const expandJsdocs = (jsdocs) => {
9
6
  .join("\n")}\n`;
10
7
  return `/**${result}*/\n`;
11
8
  };
12
- exports.expandJsdocs = expandJsdocs;
13
- const addJsdocs = (schema, parsed) => {
9
+ export const addJsdocs = (schema, parsed) => {
14
10
  const description = schema.description;
15
11
  if (!description) {
16
12
  return parsed;
17
13
  }
18
- return `\n${(0, exports.expandJsdocs)(description)}${parsed}`;
14
+ return `\n${expandJsdocs(description)}${parsed}`;
19
15
  };
20
- exports.addJsdocs = addJsdocs;