@gabrielbryk/json-schema-to-zod 2.12.1 → 2.14.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 (57) hide show
  1. package/.github/RELEASE_SETUP.md +120 -0
  2. package/.github/TOOLING_GUIDE.md +169 -0
  3. package/.github/dependabot.yml +52 -0
  4. package/.github/workflows/ci.yml +33 -0
  5. package/.github/workflows/release.yml +12 -4
  6. package/.github/workflows/security.yml +40 -0
  7. package/.husky/commit-msg +1 -0
  8. package/.husky/pre-commit +1 -0
  9. package/.lintstagedrc.json +3 -0
  10. package/.prettierrc +20 -0
  11. package/AGENTS.md +7 -0
  12. package/CHANGELOG.md +13 -4
  13. package/README.md +24 -9
  14. package/commitlint.config.js +24 -0
  15. package/createIndex.ts +4 -4
  16. package/dist/cli.js +3 -4
  17. package/dist/core/analyzeSchema.js +56 -11
  18. package/dist/core/emitZod.js +43 -12
  19. package/dist/generators/generateBundle.js +67 -92
  20. package/dist/index.js +1 -0
  21. package/dist/parsers/parseAllOf.js +11 -12
  22. package/dist/parsers/parseAnyOf.js +2 -2
  23. package/dist/parsers/parseArray.js +38 -12
  24. package/dist/parsers/parseMultipleType.js +2 -2
  25. package/dist/parsers/parseNumber.js +44 -102
  26. package/dist/parsers/parseObject.js +136 -443
  27. package/dist/parsers/parseOneOf.js +57 -110
  28. package/dist/parsers/parseSchema.js +176 -71
  29. package/dist/parsers/parseSimpleDiscriminatedOneOf.js +2 -2
  30. package/dist/parsers/parseString.js +113 -253
  31. package/dist/types/Types.d.ts +37 -1
  32. package/dist/types/core/analyzeSchema.d.ts +4 -0
  33. package/dist/types/generators/generateBundle.d.ts +1 -1
  34. package/dist/types/index.d.ts +1 -0
  35. package/dist/types/utils/schemaNaming.d.ts +6 -0
  36. package/dist/utils/cliTools.js +1 -2
  37. package/dist/utils/esmEmitter.js +6 -2
  38. package/dist/utils/extractInlineObject.js +1 -3
  39. package/dist/utils/jsdocs.js +1 -4
  40. package/dist/utils/liftInlineObjects.js +76 -15
  41. package/dist/utils/resolveRef.js +35 -10
  42. package/dist/utils/schemaNaming.js +31 -0
  43. package/dist/utils/schemaRepresentation.js +35 -66
  44. package/dist/zodToJsonSchema.js +1 -2
  45. package/docs/IMPROVEMENT-PLAN.md +30 -12
  46. package/docs/ZOD-V4-RECURSIVE-TYPE-LIMITATIONS.md +70 -25
  47. package/docs/proposals/allof-required-merging.md +10 -4
  48. package/docs/proposals/bundle-refactor.md +10 -4
  49. package/docs/proposals/discriminated-union-with-default.md +18 -14
  50. package/docs/proposals/inline-object-lifting.md +15 -5
  51. package/docs/proposals/ref-anchor-support.md +11 -0
  52. package/output.txt +67 -0
  53. package/package.json +18 -5
  54. package/scripts/generateWorkflowSchema.ts +5 -14
  55. package/scripts/regenerate_bundle.ts +25 -0
  56. package/tsc_output.txt +542 -0
  57. package/tsc_output_2.txt +489 -0
package/output.txt ADDED
@@ -0,0 +1,67 @@
1
+
2
+ > @gabrielbryk/json-schema-to-zod@2.12.0 test
3
+ > NODE_OPTIONS=--experimental-vm-modules jest test/jsonSchemaToZod.test.ts
4
+
5
+ console.log
6
+ import { z } from "zod";
7
+ const _Node = z.object({ "value": z.string(), get "next"(): z.ZodOptional<typeof Node> { return Node.optional(); } });
8
+ export const Node = _Node.passthrough();
9
+ export default Node;
10
+
11
+ at test/jsonSchemaToZod.test.ts:341:13
12
+
13
+ (node:175) ExperimentalWarning: VM Modules is an experimental feature and might change at any time
14
+ (Use `node --trace-warnings ...` to show where the warning was created)
15
+ FAIL test/jsonSchemaToZod.test.ts
16
+ jsonSchemaToZod
17
+ ✓ should accept json schema 7 and 4 (6 ms)
18
+ ✓ should produce a string of JS code creating a Zod schema from a simple JSON schema (1 ms)
19
+ ✓ should be possible to skip the import line
20
+ ✓ should be possible to add types (1 ms)
21
+ ✓ should be possible to add types with a custom name template
22
+ ✓ should throw when given type but no name
23
+ ✓ should include defaults
24
+ ✓ should include falsy defaults
25
+ ✓ should include falsy defaults (1 ms)
26
+ ✓ can exclude defaults
27
+ ✓ should include describes (1 ms)
28
+ ✓ can exclude describes
29
+ ✓ can include jsdocs (2 ms)
30
+ ✓ will remove optionality if default is present (1 ms)
31
+ ✓ will handle falsy defaults
32
+ ✓ will ignore undefined as default
33
+ ✓ should be possible to define a custom parser (1 ms)
34
+ ✓ can output with name
35
+ ✓ can output without name
36
+ ✕ declares $refs as named schemas and uses getters for recursion (10 ms)
37
+ ✓ uses upgraded discriminatedUnion map syntax (1 ms)
38
+ ✓ supports propertyNames validation (1 ms)
39
+ ✓ supports dependentSchemas (1 ms)
40
+ ✓ supports contains with min/max contains (1 ms)
41
+ ✓ supports contains on tuples (1 ms)
42
+ ✓ can export reference declarations when requested
43
+
44
+ ● jsonSchemaToZod › declares $refs as named schemas and uses getters for recursion
45
+
46
+ expect(received).toStrictEqual(expected) // deep equality
47
+
48
+ Expected: true
49
+ Received: false
50
+
51
+ 71 | }
52
+ 72 |
53
+ > 73 | expect(result).toStrictEqual(expected);
54
+ | ^
55
+ 74 | });
56
+ 75 | });
57
+ 76 | });
58
+
59
+ at test/suite.ts:73:26
60
+ at test/jsonSchemaToZod.test.ts:344:5
61
+ at Object.<anonymous> (test/suite.ts:19:9)
62
+
63
+ Test Suites: 1 failed, 1 total
64
+ Tests: 1 failed, 25 passed, 26 total
65
+ Snapshots: 0 total
66
+ Time: 0.363 s, estimated 1 s
67
+ Ran all test suites matching /test\/jsonSchemaToZod.test.ts/i.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gabrielbryk/json-schema-to-zod",
3
- "version": "2.12.1",
3
+ "version": "2.14.0",
4
4
  "description": "Converts JSON schema objects or files into Zod schemas",
5
5
  "type": "module",
6
6
  "types": "./dist/types/index.d.ts",
@@ -60,19 +60,24 @@
60
60
  },
61
61
  "devDependencies": {
62
62
  "@changesets/cli": "^2.29.8",
63
- "@typescript-eslint/eslint-plugin": "^8.49.0",
64
- "@typescript-eslint/parser": "^8.49.0",
65
- "@types/json-schema": "^7.0.15",
63
+ "@commitlint/cli": "^20.2.0",
64
+ "@commitlint/config-conventional": "^20.2.0",
66
65
  "@types/jest": "^29.5.14",
66
+ "@types/json-schema": "^7.0.15",
67
67
  "@types/node": "^20.9.0",
68
+ "@typescript-eslint/eslint-plugin": "^8.49.0",
69
+ "@typescript-eslint/parser": "^8.49.0",
68
70
  "eslint": "^9.39.1",
71
+ "husky": "^9.1.7",
69
72
  "jest": "^29.7.0",
70
73
  "js-yaml": "^4.1.0",
74
+ "lint-staged": "^16.2.7",
75
+ "prettier": "^3.7.4",
71
76
  "rimraf": "^5.0.5",
72
77
  "ts-jest": "^29.3.4",
73
78
  "tsx": "^4.1.1",
74
79
  "typescript": "^5.2.2",
75
- "zod": "^4.1.13"
80
+ "zod": "^4.3.5"
76
81
  },
77
82
  "scripts": {
78
83
  "build:esm": "tsc -p tsconfig.build.json",
@@ -82,6 +87,14 @@
82
87
  "gen": "tsx ./createIndex.ts",
83
88
  "test": "NODE_OPTIONS=--experimental-vm-modules jest",
84
89
  "lint": "eslint \"src/**/*.{ts,tsx}\" \"test/**/*.ts\"",
90
+ "lint:fix": "eslint \"src/**/*.{ts,tsx}\" \"test/**/*.ts\" --fix",
91
+ "format:write": "prettier --write .",
92
+ "format:check": "prettier --check .",
93
+ "audit": "pnpm audit --audit-level=moderate",
94
+ "ci": "pnpm run build && pnpm run format:check && pnpm run lint",
95
+ "lint-staged": "lint-staged",
96
+ "local-release": "changeset version && changeset publish",
97
+ "release": "changeset publish",
85
98
  "smoke:esm": "pnpm build:esm && node --input-type=module -e \"import { jsonSchemaToZod } from './dist/index.js'; console.log(jsonSchemaToZod({type:'string'}));\""
86
99
  }
87
100
  }
@@ -1,5 +1,5 @@
1
1
  import { readFileSync, mkdirSync, writeFileSync } from "fs";
2
- import { dirname, join } from "path";
2
+ import { join } from "path";
3
3
  import yaml from "js-yaml";
4
4
  import jsonSchemaToZod from "../src/index.js";
5
5
 
@@ -45,32 +45,23 @@ function main() {
45
45
 
46
46
  for (const block of blocks) {
47
47
  const normalizedLines = block.lines.map((l, idx) =>
48
- idx === 0 ? l.replace(/^\s*(export\s+)?const\s+/, "export const ") : l,
48
+ idx === 0 ? l.replace(/^\s*(export\s+)?const\s+/, "export const ") : l
49
49
  );
50
50
  const content = normalizedLines.join("\n");
51
51
  const deps = Array.from(names)
52
52
  .filter((n) => n !== block.name)
53
53
  .filter((n) => new RegExp(`\\b${n}\\b`).test(content));
54
54
 
55
- const importDepLines = deps.map(
56
- (dep) => `import { ${dep} } from "./${dep}.js"`,
57
- );
55
+ const importDepLines = deps.map((dep) => `import { ${dep} } from "./${dep}.js"`);
58
56
 
59
- const fileContent = [
60
- ...importLines,
61
- ...importDepLines,
62
- content,
63
- "",
64
- ].join("\n");
57
+ const fileContent = [...importLines, ...importDepLines, content, ""].join("\n");
65
58
 
66
59
  writeFileSync(join(SCHEMA_DIR, `${block.name}.ts`), fileContent);
67
60
  }
68
61
 
69
62
  // index exports all and the root schema
70
63
  const exportLines = Array.from(
71
- new Set(
72
- blocks.map((b) => `export { ${b.name} } from "./schemas/${b.name}.js"`),
73
- ),
64
+ new Set(blocks.map((b) => `export { ${b.name} } from "./schemas/${b.name}.js"`))
74
65
  );
75
66
 
76
67
  writeFileSync(OUTPUT_INDEX, exportLines.join("\n") + "\n");
@@ -0,0 +1,25 @@
1
+ import { readFileSync, writeFileSync, mkdirSync } from "fs";
2
+ import { join } from "path";
3
+ import yaml from "js-yaml";
4
+ import { generateSchemaBundle } from "../src/index.ts";
5
+
6
+ const schema = yaml.load(readFileSync("test/fixtures/workflow.yaml", "utf8")) as any;
7
+
8
+ const toPascalCase = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
9
+
10
+ const result = generateSchemaBundle(schema, {
11
+ name: "workflowSchema",
12
+ splitDefs: {
13
+ fileName: (defName) => `${toPascalCase(defName)}.schema.ts`,
14
+ },
15
+ });
16
+
17
+ // Ensure directory exists
18
+ const outputDir = "test/output/workflow/schemas";
19
+ mkdirSync(outputDir, { recursive: true });
20
+
21
+ result.files.forEach((file) => {
22
+ writeFileSync(join(outputDir, file.fileName), file.contents);
23
+ });
24
+
25
+ console.log(`Generated ${result.files.length} files in ${outputDir}`);