@gabrielbryk/json-schema-to-zod 2.7.4 → 2.8.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 (51) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/dist/cjs/generators/generateBundle.js +311 -0
  3. package/dist/cjs/index.js +2 -0
  4. package/dist/cjs/jsonSchemaToZod.js +96 -2
  5. package/dist/cjs/parsers/parseArray.js +34 -15
  6. package/dist/cjs/parsers/parseIfThenElse.js +2 -1
  7. package/dist/cjs/parsers/parseNumber.js +81 -39
  8. package/dist/cjs/parsers/parseObject.js +24 -0
  9. package/dist/cjs/parsers/parseSchema.js +23 -1
  10. package/dist/cjs/parsers/parseString.js +294 -54
  11. package/dist/cjs/utils/cycles.js +113 -0
  12. package/dist/cjs/utils/withMessage.js +4 -5
  13. package/dist/esm/Types.js +2 -1
  14. package/dist/esm/cli.js +12 -10
  15. package/dist/esm/generators/generateBundle.js +311 -0
  16. package/dist/esm/index.js +46 -28
  17. package/dist/esm/jsonSchemaToZod.js +105 -7
  18. package/dist/esm/parsers/parseAllOf.js +8 -5
  19. package/dist/esm/parsers/parseAnyOf.js +10 -6
  20. package/dist/esm/parsers/parseArray.js +47 -24
  21. package/dist/esm/parsers/parseBoolean.js +5 -1
  22. package/dist/esm/parsers/parseConst.js +5 -1
  23. package/dist/esm/parsers/parseDefault.js +7 -3
  24. package/dist/esm/parsers/parseEnum.js +5 -1
  25. package/dist/esm/parsers/parseIfThenElse.js +11 -6
  26. package/dist/esm/parsers/parseMultipleType.js +7 -3
  27. package/dist/esm/parsers/parseNot.js +8 -4
  28. package/dist/esm/parsers/parseNull.js +5 -1
  29. package/dist/esm/parsers/parseNullable.js +8 -4
  30. package/dist/esm/parsers/parseNumber.js +88 -42
  31. package/dist/esm/parsers/parseObject.js +52 -25
  32. package/dist/esm/parsers/parseOneOf.js +10 -6
  33. package/dist/esm/parsers/parseSchema.js +85 -59
  34. package/dist/esm/parsers/parseSimpleDiscriminatedOneOf.js +10 -6
  35. package/dist/esm/parsers/parseString.js +303 -59
  36. package/dist/esm/utils/anyOrUnknown.js +5 -1
  37. package/dist/esm/utils/cliTools.js +13 -7
  38. package/dist/esm/utils/cycles.js +113 -0
  39. package/dist/esm/utils/half.js +5 -1
  40. package/dist/esm/utils/jsdocs.js +8 -3
  41. package/dist/esm/utils/omit.js +5 -1
  42. package/dist/esm/utils/withMessage.js +8 -6
  43. package/dist/esm/zodToJsonSchema.js +4 -1
  44. package/dist/types/Types.d.ts +8 -0
  45. package/dist/types/generators/generateBundle.d.ts +57 -0
  46. package/dist/types/index.d.ts +2 -0
  47. package/dist/types/parsers/parseString.d.ts +2 -2
  48. package/dist/types/utils/cycles.d.ts +7 -0
  49. package/dist/types/utils/jsdocs.d.ts +1 -1
  50. package/dist/types/utils/withMessage.d.ts +6 -1
  51. package/package.json +1 -1
@@ -1,73 +1,317 @@
1
- import { withMessage } from "../utils/withMessage.js";
2
- import { parseSchema } from "./parseSchema.js";
3
- export const parseString = (schema) => {
4
- let r = "z.string()";
5
- r += withMessage(schema, "format", ({ value }) => {
6
- switch (value) {
7
- case "email":
8
- return [".email(", ")"];
9
- case "ip":
10
- return [".ip(", ")"];
11
- case "ipv4":
12
- return ['.ip({ version: "v4"', ", message: ", " })"];
13
- case "ipv6":
14
- return ['.ip({ version: "v6"', ", message: ", " })"];
15
- case "uri":
16
- return [".url(", ")"];
17
- case "uuid":
18
- return [".uuid(", ")"];
19
- case "date-time":
20
- return [".datetime({ offset: true", ", message: ", " })"];
21
- case "time":
22
- return [".time(", ")"];
23
- case "date":
24
- return [".date(", ")"];
25
- case "binary":
26
- return [".base64(", ")"];
27
- case "duration":
28
- return [".duration(", ")"];
29
- }
30
- });
31
- r += withMessage(schema, "pattern", ({ json }) => [
32
- `.regex(new RegExp(${json})`,
33
- ", ",
34
- ")",
35
- ]);
36
- r += withMessage(schema, "minLength", ({ json }) => [
37
- `.min(${json}`,
38
- ", ",
39
- ")",
40
- ]);
41
- r += withMessage(schema, "maxLength", ({ json }) => [
42
- `.max(${json}`,
43
- ", ",
44
- ")",
45
- ]);
46
- r += withMessage(schema, "contentEncoding", ({ value }) => {
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) => {
7
+ const formatError = schema.errorMessage?.format;
8
+ const refContext = ensureRefs(refs);
9
+ const topLevelFormatMap = {
10
+ email: "z.email",
11
+ ipv4: "z.ipv4",
12
+ ipv6: "z.ipv6",
13
+ uri: "z.url",
14
+ uuid: "z.uuid",
15
+ cuid: "z.cuid",
16
+ cuid2: "z.cuid2",
17
+ nanoid: "z.nanoid",
18
+ ulid: "z.ulid",
19
+ jwt: "z.jwt",
20
+ e164: "z.e164",
21
+ base64url: "z.base64url",
22
+ base64: "z.base64",
23
+ emoji: "z.emoji",
24
+ "idn-email": "z.email",
25
+ };
26
+ const formatFn = schema.format && topLevelFormatMap[schema.format];
27
+ const formatParam = formatError !== undefined ? `{ error: ${JSON.stringify(formatError)} }` : "";
28
+ let r = formatFn ? `${formatFn}(${formatParam})` : "z.string()";
29
+ const formatHandled = Boolean(formatFn);
30
+ let formatWasHandled = formatHandled;
31
+ if (!formatHandled) {
32
+ r += (0, withMessage_js_1.withMessage)(schema, "format", ({ value }) => {
33
+ switch (value) {
34
+ case "email":
35
+ formatWasHandled = true;
36
+ return {
37
+ opener: ".email(",
38
+ closer: ")",
39
+ messagePrefix: "{ error: ",
40
+ messageCloser: " })",
41
+ };
42
+ case "ip":
43
+ formatWasHandled = true;
44
+ return {
45
+ opener: ".ip(",
46
+ closer: ")",
47
+ messagePrefix: "{ error: ",
48
+ messageCloser: " })",
49
+ };
50
+ case "ipv4":
51
+ formatWasHandled = true;
52
+ return {
53
+ opener: '.ip({ version: "v4"',
54
+ closer: " })",
55
+ messagePrefix: ", error: ",
56
+ messageCloser: " })",
57
+ };
58
+ case "ipv6":
59
+ formatWasHandled = true;
60
+ return {
61
+ opener: '.ip({ version: "v6"',
62
+ closer: " })",
63
+ messagePrefix: ", error: ",
64
+ messageCloser: " })",
65
+ };
66
+ case "uri":
67
+ formatWasHandled = true;
68
+ return {
69
+ opener: ".url(",
70
+ closer: ")",
71
+ messagePrefix: "{ error: ",
72
+ messageCloser: " })",
73
+ };
74
+ case "uuid":
75
+ formatWasHandled = true;
76
+ return {
77
+ opener: ".uuid(",
78
+ closer: ")",
79
+ messagePrefix: "{ error: ",
80
+ messageCloser: " })",
81
+ };
82
+ case "cuid":
83
+ formatWasHandled = true;
84
+ return {
85
+ opener: ".cuid(",
86
+ closer: ")",
87
+ messagePrefix: "{ error: ",
88
+ messageCloser: " })",
89
+ };
90
+ case "cuid2":
91
+ formatWasHandled = true;
92
+ return {
93
+ opener: ".cuid2(",
94
+ closer: ")",
95
+ messagePrefix: "{ error: ",
96
+ messageCloser: " })",
97
+ };
98
+ case "nanoid":
99
+ formatWasHandled = true;
100
+ return {
101
+ opener: ".nanoid(",
102
+ closer: ")",
103
+ messagePrefix: "{ error: ",
104
+ messageCloser: " })",
105
+ };
106
+ case "ulid":
107
+ formatWasHandled = true;
108
+ return {
109
+ opener: ".ulid(",
110
+ closer: ")",
111
+ messagePrefix: "{ error: ",
112
+ messageCloser: " })",
113
+ };
114
+ case "jwt":
115
+ formatWasHandled = true;
116
+ return {
117
+ opener: ".jwt(",
118
+ closer: ")",
119
+ messagePrefix: "{ error: ",
120
+ messageCloser: " })",
121
+ };
122
+ case "e164":
123
+ formatWasHandled = true;
124
+ return {
125
+ opener: ".e164(",
126
+ closer: ")",
127
+ messagePrefix: "{ error: ",
128
+ messageCloser: " })",
129
+ };
130
+ case "base64url":
131
+ formatWasHandled = true;
132
+ return {
133
+ opener: ".base64url(",
134
+ closer: ")",
135
+ messagePrefix: "{ error: ",
136
+ messageCloser: " })",
137
+ };
138
+ case "emoji":
139
+ formatWasHandled = true;
140
+ return {
141
+ opener: ".emoji(",
142
+ closer: ")",
143
+ messagePrefix: "{ error: ",
144
+ messageCloser: " })",
145
+ };
146
+ case "date-time":
147
+ formatWasHandled = true;
148
+ return {
149
+ opener: ".datetime({ offset: true",
150
+ closer: " })",
151
+ messagePrefix: ", error: ",
152
+ messageCloser: " })",
153
+ };
154
+ case "time":
155
+ formatWasHandled = true;
156
+ return {
157
+ opener: ".time(",
158
+ closer: ")",
159
+ messagePrefix: "{ error: ",
160
+ messageCloser: " })",
161
+ };
162
+ case "date":
163
+ formatWasHandled = true;
164
+ return {
165
+ opener: ".date(",
166
+ closer: ")",
167
+ messagePrefix: "{ error: ",
168
+ messageCloser: " })",
169
+ };
170
+ case "binary":
171
+ formatWasHandled = true;
172
+ return {
173
+ opener: ".base64(",
174
+ closer: ")",
175
+ messagePrefix: "{ error: ",
176
+ messageCloser: " })",
177
+ };
178
+ case "duration":
179
+ formatWasHandled = true;
180
+ return {
181
+ opener: ".duration(",
182
+ closer: ")",
183
+ messagePrefix: "{ error: ",
184
+ messageCloser: " })",
185
+ };
186
+ case "hostname":
187
+ case "idn-hostname":
188
+ formatWasHandled = true;
189
+ return {
190
+ opener: ".refine((val) => { if (typeof val !== \"string\" || val.length === 0 || val.length > 253) return false; return val.split(\".\").every((label) => label.length > 0 && label.length <= 63 && /^[A-Za-z0-9-]+$/.test(label) && label[0] !== \"-\" && label[label.length - 1] !== \"-\"); }",
191
+ closer: ")",
192
+ messagePrefix: ", { error: ",
193
+ messageCloser: " })",
194
+ };
195
+ case "idn-email":
196
+ formatWasHandled = true;
197
+ return {
198
+ opener: ".email(",
199
+ closer: ")",
200
+ messagePrefix: "{ error: ",
201
+ messageCloser: " })",
202
+ };
203
+ case "uri-reference":
204
+ case "iri":
205
+ case "iri-reference":
206
+ formatWasHandled = true;
207
+ return {
208
+ opener: '.refine((val) => { try { new URL(val, "http://example.com"); return true; } catch { return false; } }',
209
+ closer: ")",
210
+ messagePrefix: ", { error: ",
211
+ messageCloser: " })",
212
+ };
213
+ case "json-pointer":
214
+ formatWasHandled = true;
215
+ return {
216
+ opener: ".refine((val) => typeof val === \"string\" && /^(?:\\/(?:[^/~]|~[01])*)*$/.test(val)",
217
+ closer: ")",
218
+ messagePrefix: ", { error: ",
219
+ messageCloser: " })",
220
+ };
221
+ case "relative-json-pointer":
222
+ formatWasHandled = true;
223
+ return {
224
+ opener: ".refine((val) => typeof val === \"string\" && /^(?:0|[1-9][0-9]*)(?:#|(?:\\/(?:[^/~]|~[01])*))*$/.test(val)",
225
+ closer: ")",
226
+ messagePrefix: ", { error: ",
227
+ messageCloser: " })",
228
+ };
229
+ case "uri-template":
230
+ formatWasHandled = true;
231
+ return {
232
+ opener: ".refine((val) => { if (typeof val !== \"string\") return false; const opens = (val.match(/\\{/g) || []).length; const closes = (val.match(/\\}/g) || []).length; return opens === closes; }",
233
+ closer: ")",
234
+ messagePrefix: ", { error: ",
235
+ messageCloser: " })",
236
+ };
237
+ case "regex":
238
+ formatWasHandled = true;
239
+ return {
240
+ opener: ".refine((val) => { try { new RegExp(val); return true; } catch { return false; } }",
241
+ closer: ")",
242
+ messagePrefix: ", { error: ",
243
+ messageCloser: " })",
244
+ };
245
+ }
246
+ });
247
+ }
248
+ if (schema.format && !formatWasHandled) {
249
+ refContext.onUnknownFormat?.(schema.format, refContext.path);
250
+ }
251
+ r += (0, withMessage_js_1.withMessage)(schema, "pattern", ({ json }) => ({
252
+ opener: `.regex(new RegExp(${json})`,
253
+ closer: ")",
254
+ messagePrefix: ", { error: ",
255
+ messageCloser: " })",
256
+ }));
257
+ r += (0, withMessage_js_1.withMessage)(schema, "minLength", ({ json }) => ({
258
+ opener: `.min(${json}`,
259
+ closer: ")",
260
+ messagePrefix: ", { error: ",
261
+ messageCloser: " })",
262
+ }));
263
+ r += (0, withMessage_js_1.withMessage)(schema, "maxLength", ({ json }) => ({
264
+ opener: `.max(${json}`,
265
+ closer: ")",
266
+ messagePrefix: ", { error: ",
267
+ messageCloser: " })",
268
+ }));
269
+ r += (0, withMessage_js_1.withMessage)(schema, "contentEncoding", ({ value }) => {
47
270
  if (value === "base64") {
48
- return [".base64(", ")"];
271
+ return {
272
+ opener: ".base64(",
273
+ closer: ")",
274
+ messagePrefix: "{ error: ",
275
+ messageCloser: " })",
276
+ };
49
277
  }
50
278
  });
51
- const contentMediaType = withMessage(schema, "contentMediaType", ({ value }) => {
279
+ const contentMediaType = (0, withMessage_js_1.withMessage)(schema, "contentMediaType", ({ value }) => {
52
280
  if (value === "application/json") {
53
- return [
54
- ".transform((str, ctx) => { try { return JSON.parse(str); } catch (err) { ctx.addIssue({ code: \"custom\", message: \"Invalid JSON\" }); }}",
55
- ", ",
56
- ")"
57
- ];
281
+ return {
282
+ opener: '.transform((str, ctx) => { try { return JSON.parse(str); } catch (err) { ctx.addIssue({ code: "custom", message: "Invalid JSON" }); }}',
283
+ closer: ")",
284
+ messagePrefix: ", { error: ",
285
+ messageCloser: " })",
286
+ };
58
287
  }
59
288
  });
60
289
  if (contentMediaType != "") {
61
290
  r += contentMediaType;
62
- r += withMessage(schema, "contentSchema", ({ value }) => {
291
+ r += (0, withMessage_js_1.withMessage)(schema, "contentSchema", ({ value }) => {
63
292
  if (value && value instanceof Object) {
64
- return [
65
- `.pipe(${parseSchema(value)}`,
66
- ", ",
67
- ")"
68
- ];
293
+ return {
294
+ opener: `.pipe(${(0, parseSchema_js_1.parseSchema)(value, refContext)}`,
295
+ closer: ")",
296
+ messagePrefix: ", { error: ",
297
+ messageCloser: " })",
298
+ };
69
299
  }
70
300
  });
71
301
  }
72
302
  return r;
73
303
  };
304
+ exports.parseString = parseString;
305
+ function ensureRefs(refs) {
306
+ if (refs)
307
+ return refs;
308
+ return {
309
+ path: [],
310
+ seen: new Map(),
311
+ declarations: new Map(),
312
+ dependencies: new Map(),
313
+ inProgress: new Set(),
314
+ refNameByPointer: new Map(),
315
+ usedNames: new Set(),
316
+ };
317
+ }
@@ -1,3 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.anyOrUnknown = void 0;
1
4
  /**
2
5
  * Returns "z.unknown()" if the useUnknown option is enabled, otherwise "z.any()".
3
6
  * This helper is used throughout the library for fallback cases.
@@ -5,6 +8,7 @@
5
8
  * @param refs - The refs object containing options
6
9
  * @returns The appropriate Zod schema string
7
10
  */
8
- export const anyOrUnknown = (refs) => {
11
+ const anyOrUnknown = (refs) => {
9
12
  return refs?.useUnknown ? "z.unknown()" : "z.any()";
10
13
  };
14
+ exports.anyOrUnknown = anyOrUnknown;
@@ -1,5 +1,11 @@
1
- import { statSync, readFileSync } from "fs";
2
- export function parseArgs(params, args, help) {
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) {
3
9
  const result = {};
4
10
  if (help) {
5
11
  let index = args.indexOf("--help");
@@ -56,15 +62,15 @@ export function parseArgs(params, args, help) {
56
62
  }
57
63
  return result;
58
64
  }
59
- export function parseOrReadJSON(jsonOrPath) {
65
+ function parseOrReadJSON(jsonOrPath) {
60
66
  jsonOrPath = jsonOrPath.trim();
61
67
  if (jsonOrPath.length < 255 &&
62
- statSync(jsonOrPath, { throwIfNoEntry: false })?.isFile()) {
63
- jsonOrPath = readFileSync(jsonOrPath, "utf-8");
68
+ (0, fs_1.statSync)(jsonOrPath, { throwIfNoEntry: false })?.isFile()) {
69
+ jsonOrPath = (0, fs_1.readFileSync)(jsonOrPath, "utf-8");
64
70
  }
65
71
  return JSON.parse(jsonOrPath);
66
72
  }
67
- export function readPipe() {
73
+ function readPipe() {
68
74
  return new Promise((resolve, reject) => {
69
75
  let buf = "";
70
76
  process.stdin
@@ -79,7 +85,7 @@ export function readPipe() {
79
85
  });
80
86
  });
81
87
  }
82
- export function printParams(params) {
88
+ function printParams(params) {
83
89
  const longest = Object.keys(params).reduce((l, c) => (c.length > l ? c.length : l), 5);
84
90
  const header = "Name " + " ".repeat(longest - 2) + "Short Description";
85
91
  console.log(header);
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.computeScc = exports.detectCycles = exports.findRefDependencies = void 0;
4
+ const findRefDependencies = (schema, validDefNames) => {
5
+ const deps = new Set();
6
+ function traverse(obj) {
7
+ if (obj === null || typeof obj !== "object")
8
+ return;
9
+ if (Array.isArray(obj)) {
10
+ obj.forEach(traverse);
11
+ return;
12
+ }
13
+ const record = obj;
14
+ if (typeof record["$ref"] === "string") {
15
+ const ref = record["$ref"];
16
+ const match = ref.match(/^#\/(?:\$defs|definitions)\/(.+)$/);
17
+ if (match && validDefNames.includes(match[1])) {
18
+ deps.add(match[1]);
19
+ }
20
+ }
21
+ for (const value of Object.values(record)) {
22
+ traverse(value);
23
+ }
24
+ }
25
+ traverse(schema);
26
+ return deps;
27
+ };
28
+ exports.findRefDependencies = findRefDependencies;
29
+ const detectCycles = (defNames, deps) => {
30
+ const cycleNodes = new Set();
31
+ const visited = new Set();
32
+ const recursionStack = new Set();
33
+ function dfs(node, path) {
34
+ if (recursionStack.has(node)) {
35
+ const cycleStart = path.indexOf(node);
36
+ for (let i = cycleStart; i < path.length; i++) {
37
+ cycleNodes.add(path[i]);
38
+ }
39
+ cycleNodes.add(node);
40
+ return;
41
+ }
42
+ if (visited.has(node))
43
+ return;
44
+ visited.add(node);
45
+ recursionStack.add(node);
46
+ const targets = deps.get(node);
47
+ if (targets) {
48
+ for (const dep of targets) {
49
+ dfs(dep, [...path, node]);
50
+ }
51
+ }
52
+ recursionStack.delete(node);
53
+ }
54
+ for (const defName of defNames) {
55
+ if (!visited.has(defName))
56
+ dfs(defName, []);
57
+ }
58
+ return cycleNodes;
59
+ };
60
+ exports.detectCycles = detectCycles;
61
+ const computeScc = (defNames, deps) => {
62
+ // Tarjan's algorithm, keeps mapping for quick "is this ref in my cycle?"
63
+ const index = new Map();
64
+ const lowlink = new Map();
65
+ const stack = [];
66
+ const onStack = new Set();
67
+ const componentByName = new Map();
68
+ const cycleMembers = new Set();
69
+ let currentIndex = 0;
70
+ let componentId = 0;
71
+ const strongConnect = (v) => {
72
+ index.set(v, currentIndex);
73
+ lowlink.set(v, currentIndex);
74
+ currentIndex += 1;
75
+ stack.push(v);
76
+ onStack.add(v);
77
+ const neighbors = deps.get(v);
78
+ if (neighbors) {
79
+ for (const w of neighbors) {
80
+ if (!index.has(w)) {
81
+ strongConnect(w);
82
+ lowlink.set(v, Math.min(lowlink.get(v), lowlink.get(w)));
83
+ }
84
+ else if (onStack.has(w)) {
85
+ lowlink.set(v, Math.min(lowlink.get(v), index.get(w)));
86
+ }
87
+ }
88
+ }
89
+ if (lowlink.get(v) === index.get(v)) {
90
+ const component = [];
91
+ let w;
92
+ do {
93
+ w = stack.pop();
94
+ if (w === undefined)
95
+ break;
96
+ onStack.delete(w);
97
+ component.push(w);
98
+ componentByName.set(w, componentId);
99
+ } while (w !== v);
100
+ if (component.length > 1) {
101
+ component.forEach((name) => cycleMembers.add(name));
102
+ }
103
+ componentId += 1;
104
+ }
105
+ };
106
+ for (const name of defNames) {
107
+ if (!index.has(name)) {
108
+ strongConnect(name);
109
+ }
110
+ }
111
+ return { cycleMembers, componentByName };
112
+ };
113
+ exports.computeScc = computeScc;
@@ -1,3 +1,7 @@
1
- export const half = (arr) => {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.half = void 0;
4
+ const half = (arr) => {
2
5
  return [arr.slice(0, arr.length / 2), arr.slice(arr.length / 2)];
3
6
  };
7
+ exports.half = half;
@@ -1,4 +1,7 @@
1
- export const expandJsdocs = (jsdocs) => {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addJsdocs = exports.expandJsdocs = void 0;
4
+ const expandJsdocs = (jsdocs) => {
2
5
  const lines = jsdocs.split("\n");
3
6
  const result = lines.length === 1
4
7
  ? lines[0]
@@ -6,10 +9,12 @@ export const expandJsdocs = (jsdocs) => {
6
9
  .join("\n")}\n`;
7
10
  return `/**${result}*/\n`;
8
11
  };
9
- export const addJsdocs = (schema, parsed) => {
12
+ exports.expandJsdocs = expandJsdocs;
13
+ const addJsdocs = (schema, parsed) => {
10
14
  const description = schema.description;
11
15
  if (!description) {
12
16
  return parsed;
13
17
  }
14
- return `\n${expandJsdocs(description)}${parsed}`;
18
+ return `\n${(0, exports.expandJsdocs)(description)}${parsed}`;
15
19
  };
20
+ exports.addJsdocs = addJsdocs;
@@ -1,6 +1,10 @@
1
- export const omit = (obj, ...keys) => Object.keys(obj).reduce((acc, key) => {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.omit = void 0;
4
+ const omit = (obj, ...keys) => Object.keys(obj).reduce((acc, key) => {
2
5
  if (!keys.includes(key)) {
3
6
  acc[key] = obj[key];
4
7
  }
5
8
  return acc;
6
9
  }, {});
10
+ exports.omit = omit;
@@ -1,17 +1,19 @@
1
- export function withMessage(schema, key, get) {
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withMessage = withMessage;
4
+ function withMessage(schema, key, get) {
2
5
  const value = schema[key];
3
6
  let r = "";
4
7
  if (value !== undefined) {
5
8
  const got = get({ value, json: JSON.stringify(value) });
6
9
  if (got) {
7
- const opener = got[0];
8
- const prefix = got.length === 3 ? got[1] : "";
9
- const closer = got.length === 3 ? got[2] : got[1];
10
+ const { opener, closer, messagePrefix = "", messageCloser } = got;
10
11
  r += opener;
11
12
  if (schema.errorMessage?.[key] !== undefined) {
12
- r += prefix + JSON.stringify(schema.errorMessage[key]);
13
+ r += messagePrefix + JSON.stringify(schema.errorMessage[key]);
14
+ r += messageCloser ?? closer;
15
+ return r;
13
16
  }
14
- r;
15
17
  r += closer;
16
18
  }
17
19
  }
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  /**
2
3
  * Post-processor for Zod's z.toJSONSchema() output.
3
4
  *
@@ -14,6 +15,8 @@
14
15
  * - patternProperties (stored in __jsonSchema.patternProperties)
15
16
  * - if/then/else conditionals (stored in __jsonSchema.conditional)
16
17
  */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.reconstructJsonSchema = reconstructJsonSchema;
17
20
  /**
18
21
  * Recursively process a JSON Schema to reconstruct original features from __jsonSchema meta.
19
22
  *
@@ -21,7 +24,7 @@
21
24
  * - allOf[object, {__jsonSchema: {conditional: ...}}] -> object with if/then/else at top level
22
25
  * - patternProperties meta -> patternProperties at current level
23
26
  */
24
- export function reconstructJsonSchema(schema) {
27
+ function reconstructJsonSchema(schema) {
25
28
  if (typeof schema !== "object" || schema === null) {
26
29
  return schema;
27
30
  }
@@ -94,6 +94,11 @@ export type Options = {
94
94
  * @default false
95
95
  */
96
96
  strictOneOf?: boolean;
97
+ /**
98
+ * Called when a string format is encountered that has no built-in mapping.
99
+ * Can be used to log or throw on unknown formats.
100
+ */
101
+ onUnknownFormat?: (format: string, path: (string | number)[]) => void;
97
102
  };
98
103
  export type Refs = Options & {
99
104
  path: (string | number)[];
@@ -103,10 +108,13 @@ export type Refs = Options & {
103
108
  }>;
104
109
  root?: JsonSchema;
105
110
  declarations?: Map<string, string>;
111
+ dependencies?: Map<string, Set<string>>;
106
112
  inProgress?: Set<string>;
107
113
  refNameByPointer?: Map<string, string>;
108
114
  usedNames?: Set<string>;
109
115
  currentSchemaName?: string;
116
+ cycleRefNames?: Set<string>;
117
+ cycleComponentByName?: Map<string, number>;
110
118
  };
111
119
  export type SimpleDiscriminatedOneOfSchema<D extends string = string> = JsonSchemaObject & {
112
120
  oneOf: (JsonSchemaObject & {