@gabrielbryk/json-schema-to-zod 2.7.2

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 (99) hide show
  1. package/.prettierrc.json +3 -0
  2. package/CONTRIBUTING.md +9 -0
  3. package/LICENSE +15 -0
  4. package/README.md +157 -0
  5. package/createIndex.ts +32 -0
  6. package/dist/cjs/Types.js +2 -0
  7. package/dist/cjs/cli.js +70 -0
  8. package/dist/cjs/index.js +44 -0
  9. package/dist/cjs/jsonSchemaToZod.js +78 -0
  10. package/dist/cjs/package.json +1 -0
  11. package/dist/cjs/parsers/parseAllOf.js +40 -0
  12. package/dist/cjs/parsers/parseAnyOf.js +18 -0
  13. package/dist/cjs/parsers/parseArray.js +71 -0
  14. package/dist/cjs/parsers/parseBoolean.js +7 -0
  15. package/dist/cjs/parsers/parseConst.js +7 -0
  16. package/dist/cjs/parsers/parseDefault.js +8 -0
  17. package/dist/cjs/parsers/parseEnum.js +21 -0
  18. package/dist/cjs/parsers/parseIfThenElse.js +34 -0
  19. package/dist/cjs/parsers/parseMultipleType.js +10 -0
  20. package/dist/cjs/parsers/parseNot.js +12 -0
  21. package/dist/cjs/parsers/parseNull.js +7 -0
  22. package/dist/cjs/parsers/parseNullable.js +12 -0
  23. package/dist/cjs/parsers/parseNumber.js +74 -0
  24. package/dist/cjs/parsers/parseObject.js +286 -0
  25. package/dist/cjs/parsers/parseOneOf.js +53 -0
  26. package/dist/cjs/parsers/parseSchema.js +285 -0
  27. package/dist/cjs/parsers/parseSimpleDiscriminatedOneOf.js +29 -0
  28. package/dist/cjs/parsers/parseString.js +77 -0
  29. package/dist/cjs/utils/anyOrUnknown.js +14 -0
  30. package/dist/cjs/utils/cliTools.js +108 -0
  31. package/dist/cjs/utils/half.js +7 -0
  32. package/dist/cjs/utils/jsdocs.js +20 -0
  33. package/dist/cjs/utils/omit.js +10 -0
  34. package/dist/cjs/utils/withMessage.js +22 -0
  35. package/dist/cjs/zodToJsonSchema.js +89 -0
  36. package/dist/esm/Types.js +1 -0
  37. package/dist/esm/cli.js +68 -0
  38. package/dist/esm/index.js +28 -0
  39. package/dist/esm/jsonSchemaToZod.js +74 -0
  40. package/dist/esm/package.json +1 -0
  41. package/dist/esm/parsers/parseAllOf.js +37 -0
  42. package/dist/esm/parsers/parseAnyOf.js +14 -0
  43. package/dist/esm/parsers/parseArray.js +67 -0
  44. package/dist/esm/parsers/parseBoolean.js +3 -0
  45. package/dist/esm/parsers/parseConst.js +3 -0
  46. package/dist/esm/parsers/parseDefault.js +4 -0
  47. package/dist/esm/parsers/parseEnum.js +17 -0
  48. package/dist/esm/parsers/parseIfThenElse.js +30 -0
  49. package/dist/esm/parsers/parseMultipleType.js +6 -0
  50. package/dist/esm/parsers/parseNot.js +8 -0
  51. package/dist/esm/parsers/parseNull.js +3 -0
  52. package/dist/esm/parsers/parseNullable.js +8 -0
  53. package/dist/esm/parsers/parseNumber.js +70 -0
  54. package/dist/esm/parsers/parseObject.js +283 -0
  55. package/dist/esm/parsers/parseOneOf.js +49 -0
  56. package/dist/esm/parsers/parseSchema.js +281 -0
  57. package/dist/esm/parsers/parseSimpleDiscriminatedOneOf.js +25 -0
  58. package/dist/esm/parsers/parseString.js +73 -0
  59. package/dist/esm/utils/anyOrUnknown.js +10 -0
  60. package/dist/esm/utils/cliTools.js +102 -0
  61. package/dist/esm/utils/half.js +3 -0
  62. package/dist/esm/utils/jsdocs.js +15 -0
  63. package/dist/esm/utils/omit.js +6 -0
  64. package/dist/esm/utils/withMessage.js +19 -0
  65. package/dist/esm/zodToJsonSchema.js +86 -0
  66. package/dist/types/Types.d.ts +125 -0
  67. package/dist/types/cli.d.ts +2 -0
  68. package/dist/types/index.d.ts +28 -0
  69. package/dist/types/jsonSchemaToZod.d.ts +2 -0
  70. package/dist/types/parsers/parseAllOf.d.ts +4 -0
  71. package/dist/types/parsers/parseAnyOf.d.ts +4 -0
  72. package/dist/types/parsers/parseArray.d.ts +4 -0
  73. package/dist/types/parsers/parseBoolean.d.ts +4 -0
  74. package/dist/types/parsers/parseConst.d.ts +4 -0
  75. package/dist/types/parsers/parseDefault.d.ts +2 -0
  76. package/dist/types/parsers/parseEnum.d.ts +4 -0
  77. package/dist/types/parsers/parseIfThenElse.d.ts +6 -0
  78. package/dist/types/parsers/parseMultipleType.d.ts +4 -0
  79. package/dist/types/parsers/parseNot.d.ts +4 -0
  80. package/dist/types/parsers/parseNull.d.ts +4 -0
  81. package/dist/types/parsers/parseNullable.d.ts +7 -0
  82. package/dist/types/parsers/parseNumber.d.ts +4 -0
  83. package/dist/types/parsers/parseObject.d.ts +4 -0
  84. package/dist/types/parsers/parseOneOf.d.ts +4 -0
  85. package/dist/types/parsers/parseSchema.d.ts +50 -0
  86. package/dist/types/parsers/parseSimpleDiscriminatedOneOf.d.ts +2 -0
  87. package/dist/types/parsers/parseString.d.ts +4 -0
  88. package/dist/types/utils/anyOrUnknown.d.ts +9 -0
  89. package/dist/types/utils/cliTools.d.ts +28 -0
  90. package/dist/types/utils/half.d.ts +1 -0
  91. package/dist/types/utils/jsdocs.d.ts +3 -0
  92. package/dist/types/utils/omit.d.ts +1 -0
  93. package/dist/types/utils/withMessage.d.ts +10 -0
  94. package/dist/types/zodToJsonSchema.d.ts +26 -0
  95. package/jest.config.js +4 -0
  96. package/package.json +83 -0
  97. package/postcjs.js +1 -0
  98. package/postesm.js +1 -0
  99. package/scripts/generateWorkflowSchema.ts +82 -0
@@ -0,0 +1,28 @@
1
+ export type Param = {
2
+ shorthand?: string;
3
+ description?: string;
4
+ required?: boolean | string | undefined;
5
+ } & ({
6
+ value?: "boolean";
7
+ } | {
8
+ value: "number";
9
+ } | {
10
+ value: "string";
11
+ } | {
12
+ value: {
13
+ [key: number]: string;
14
+ };
15
+ });
16
+ export type Params = {
17
+ [name: string]: Param;
18
+ };
19
+ type InferReturnType<T extends Params> = {
20
+ [name in keyof T]: (T[name]["value"] extends "number" ? number : T[name]["value"] extends "string" ? string : T[name]["value"] extends {
21
+ [key: number]: string;
22
+ } ? T[name]["value"][number] : T[name]["value"] extends never ? boolean : boolean) | (T[name]["required"] extends string | true ? never : undefined);
23
+ };
24
+ export declare function parseArgs<T extends Params>(params: T, args: string[], help?: boolean | string): InferReturnType<T>;
25
+ export declare function parseOrReadJSON(jsonOrPath: string): unknown;
26
+ export declare function readPipe(): Promise<string>;
27
+ export declare function printParams(params: Record<string, Param>): void;
28
+ export {};
@@ -0,0 +1 @@
1
+ export declare const half: <T>(arr: T[]) => [T[], T[]];
@@ -0,0 +1,3 @@
1
+ import { JsonSchemaObject } from "../Types";
2
+ export declare const expandJsdocs: (jsdocs: string) => string;
3
+ export declare const addJsdocs: (schema: JsonSchemaObject, parsed: string) => string;
@@ -0,0 +1 @@
1
+ export declare const omit: <T extends object, K extends keyof T>(obj: T, ...keys: K[]) => Omit<T, K>;
@@ -0,0 +1,10 @@
1
+ import { JsonSchemaObject } from "../Types.js";
2
+ type Opener = string;
3
+ type MessagePrefix = string;
4
+ type Closer = string;
5
+ type Builder = [Opener, Closer] | [Opener, MessagePrefix, Closer];
6
+ export declare function withMessage(schema: JsonSchemaObject, key: string, get: (props: {
7
+ value: unknown;
8
+ json: string;
9
+ }) => Builder | void): string;
10
+ export {};
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Post-processor for Zod's z.toJSONSchema() output.
3
+ *
4
+ * When `preserveJsonSchemaForRoundTrip` was used during JSON Schema → Zod conversion,
5
+ * this function reconstructs the original JSON Schema features from the stored __jsonSchema meta.
6
+ *
7
+ * Usage:
8
+ * 1. Convert JSON Schema to Zod code with `preserveJsonSchemaForRoundTrip: true`
9
+ * 2. Evaluate the Zod code to get a schema instance
10
+ * 3. Call Zod's `z.toJSONSchema(schema)` to get JSON Schema output
11
+ * 4. Pass that output to `reconstructJsonSchema()` to restore preserved features
12
+ *
13
+ * Handles:
14
+ * - patternProperties (stored in __jsonSchema.patternProperties)
15
+ * - if/then/else conditionals (stored in __jsonSchema.conditional)
16
+ */
17
+ type JsonSchemaObject = Record<string, unknown>;
18
+ /**
19
+ * Recursively process a JSON Schema to reconstruct original features from __jsonSchema meta.
20
+ *
21
+ * Handles special cases:
22
+ * - allOf[object, {__jsonSchema: {conditional: ...}}] -> object with if/then/else at top level
23
+ * - patternProperties meta -> patternProperties at current level
24
+ */
25
+ export declare function reconstructJsonSchema(schema: JsonSchemaObject): JsonSchemaObject;
26
+ export {};
package/jest.config.js ADDED
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ preset: "ts-jest",
3
+ testEnvironment: "node",
4
+ };
package/package.json ADDED
@@ -0,0 +1,83 @@
1
+ {
2
+ "name": "@gabrielbryk/json-schema-to-zod",
3
+ "version": "2.7.2",
4
+ "description": "Converts JSON schema objects or files into Zod schemas",
5
+ "types": "./dist/types/index.d.ts",
6
+ "bin": "./dist/cjs/cli.js",
7
+ "main": "./dist/cjs/index.js",
8
+ "module": "./dist/esm/index.js",
9
+ "exports": {
10
+ "import": {
11
+ "types": "./dist/types/index.d.ts",
12
+ "default": "./dist/esm/index.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/types/index.d.ts",
16
+ "default": "./dist/cjs/index.js"
17
+ }
18
+ },
19
+ "c8": {
20
+ "exclude": [
21
+ "dist",
22
+ "createIndex.ts",
23
+ "jest.config.js",
24
+ "postcjs.js",
25
+ "postesm.js",
26
+ "test"
27
+ ]
28
+ },
29
+ "keywords": [
30
+ "zod",
31
+ "json",
32
+ "schema",
33
+ "converter",
34
+ "cli"
35
+ ],
36
+ "author": "Stefan Terdell",
37
+ "contributors": [
38
+ "Chen (https://github.com/werifu)",
39
+ "Nuno Carduso (https://github.com/ncardoso-barracuda)",
40
+ "Lars Strojny (https://github.com/lstrojny)",
41
+ "Navtoj Chahal (https://github.com/navtoj)",
42
+ "Ben McCann (https://github.com/benmccann)",
43
+ "Dmitry Zakharov (https://github.com/DZakh)",
44
+ "Michel Turpin (https://github.com/grimly)",
45
+ "David Barratt (https://github.com/davidbarratt)",
46
+ "pevisscher (https://github.com/pevisscher)",
47
+ "Aidin Abedi (https://github.com/aidinabedi)",
48
+ "Brett Zamir (https://github.com/brettz9)",
49
+ "vForgeOne (https://github.com/vforgeone)",
50
+ "Adrian Ordonez (https://github.com/adrianord)",
51
+ "Jonas Reucher (https://github.com/Mantls)",
52
+ "Nicolas Forstner (https://github.com/nlsfnr)",
53
+ "Jordyn https://github.com/ColourfulMelon"
54
+ ],
55
+ "license": "ISC",
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "https://github.com/gabrielbryk/json-schema-to-zod"
59
+ },
60
+ "publishConfig": {
61
+ "access": "public"
62
+ },
63
+ "devDependencies": {
64
+ "@types/json-schema": "^7.0.15",
65
+ "@types/node": "^20.9.0",
66
+ "fast-diff": "^1.3.0",
67
+ "js-yaml": "^4.1.0",
68
+ "rimraf": "^5.0.5",
69
+ "tsx": "^4.1.1",
70
+ "typescript": "^5.2.2",
71
+ "zod": "^4.1.13"
72
+ },
73
+ "scripts": {
74
+ "build:types": "tsc -p tsconfig.types.json",
75
+ "build:cjs": "tsc -p tsconfig.cjs.json && node postcjs.js",
76
+ "build:esm": "tsc -p tsconfig.esm.json && node postesm.js",
77
+ "build": "pnpm gen && pnpm test && rimraf ./dist && pnpm build:types && pnpm build:cjs && pnpm build:esm",
78
+ "dry": "pnpm build && pnpm publish --dry-run",
79
+ "dev": "tsx watch test/index.ts",
80
+ "gen": "tsx ./createIndex.ts",
81
+ "test": "tsx test/index.ts"
82
+ }
83
+ }
package/postcjs.js ADDED
@@ -0,0 +1 @@
1
+ require("fs").writeFileSync("./dist/cjs/package.json", '{"type":"commonjs"}', "utf-8")
package/postesm.js ADDED
@@ -0,0 +1 @@
1
+ require("fs").writeFileSync("./dist/esm/package.json", '{"type":"module"}', "utf-8")
@@ -0,0 +1,82 @@
1
+ import { readFileSync, mkdirSync, writeFileSync } from "fs";
2
+ import { dirname, join } from "path";
3
+ import yaml from "js-yaml";
4
+ import jsonSchemaToZod from "../src/index.js";
5
+
6
+ const WORKFLOW_SOURCE = "test/fixtures/workflow.yaml";
7
+ const OUTPUT_DIR = "test/output/workflow";
8
+ const SCHEMA_DIR = join(OUTPUT_DIR, "schemas");
9
+ const OUTPUT_INDEX = join(OUTPUT_DIR, "index.ts");
10
+
11
+ function main() {
12
+ const schema = yaml.load(readFileSync(WORKFLOW_SOURCE, "utf8")) as any;
13
+
14
+ const generated = jsonSchemaToZod(schema, {
15
+ module: "esm",
16
+ name: "workflowSchema",
17
+ exportRefs: true,
18
+ });
19
+
20
+ const lines = generated
21
+ .split("\n")
22
+ .map((line) => line.trimEnd())
23
+ .filter((line, idx, arr) => !(line === "" && arr[idx - 1] === ""));
24
+
25
+ const importLines = lines.filter((line) => line.startsWith("import "));
26
+
27
+ // Extract blocks: export const Name = ... (until next export const or end)
28
+ const blocks: { name: string; lines: string[]; exported: boolean }[] = [];
29
+ let current: { name: string; lines: string[]; exported: boolean } | null = null;
30
+
31
+ for (const line of lines) {
32
+ const match = line.match(/^(export\s+)?const ([A-Za-z_$][A-Za-z0-9_$]*)\s*=\s*(.*)/);
33
+ if (match) {
34
+ if (current) blocks.push(current);
35
+ const [, expKeyword, name] = match;
36
+ current = { name, exported: Boolean(expKeyword), lines: [line] };
37
+ } else if (current) {
38
+ current.lines.push(line);
39
+ }
40
+ }
41
+ if (current) blocks.push(current);
42
+
43
+ const names = new Set(blocks.map((b) => b.name));
44
+
45
+ mkdirSync(SCHEMA_DIR, { recursive: true });
46
+
47
+ for (const block of blocks) {
48
+ const normalizedLines = block.lines.map((l, idx) =>
49
+ idx === 0 ? l.replace(/^\s*(export\s+)?const\s+/, "export const ") : l,
50
+ );
51
+ const content = normalizedLines.join("\n");
52
+ const deps = Array.from(names)
53
+ .filter((n) => n !== block.name)
54
+ .filter((n) => new RegExp(`\\b${n}\\b`).test(content));
55
+
56
+ const importDepLines = deps.map(
57
+ (dep) => `import { ${dep} } from "./${dep}.js"`,
58
+ );
59
+
60
+ const fileContent = [
61
+ ...importLines,
62
+ ...importDepLines,
63
+ content,
64
+ "",
65
+ ].join("\n");
66
+
67
+ writeFileSync(join(SCHEMA_DIR, `${block.name}.ts`), fileContent);
68
+ }
69
+
70
+ // index exports all and the root schema
71
+ const exportLines = Array.from(
72
+ new Set(
73
+ blocks.map((b) => `export { ${b.name} } from "./schemas/${b.name}.js"`),
74
+ ),
75
+ );
76
+
77
+ writeFileSync(OUTPUT_INDEX, exportLines.join("\n") + "\n");
78
+
79
+ console.log(`Generated per-schema files in ${SCHEMA_DIR} and index at ${OUTPUT_INDEX}`);
80
+ }
81
+
82
+ main();