@gabrielbryk/json-schema-to-zod 2.7.2 → 2.7.3

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.
@@ -0,0 +1,8 @@
1
+ # Changesets
2
+
3
+ Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4
+ with multi-package repos, or single-package repos to help you version and publish your code. You can
5
+ find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6
+
7
+ We have a quick list of common questions to get you started engaging with this project in
8
+ [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "https://unpkg.com/@changesets/config@3.1.2/schema.json",
3
+ "changelog": "@changesets/cli/changelog",
4
+ "commit": false,
5
+ "fixed": [],
6
+ "linked": [],
7
+ "access": "public",
8
+ "baseBranch": "main",
9
+ "updateInternalDependencies": "patch",
10
+ "ignore": []
11
+ }
@@ -0,0 +1,50 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: write
11
+ pull-requests: write
12
+ id-token: write
13
+
14
+ jobs:
15
+ release:
16
+ environment: npm-publish
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v5
20
+
21
+ - uses: pnpm/action-setup@v4
22
+ with:
23
+ run_install: false
24
+
25
+ - uses: actions/setup-node@v4
26
+ with:
27
+ node-version: 24
28
+ cache: pnpm
29
+ registry-url: https://registry.npmjs.org
30
+
31
+ - name: Update npm (trusted publishing requires >=11.5.1)
32
+ run: npm install -g npm@latest
33
+
34
+ - name: Install dependencies
35
+ run: pnpm install --frozen-lockfile
36
+
37
+ - name: Build
38
+ run: pnpm build
39
+
40
+ - name: Release with Changesets
41
+ uses: changesets/action@v1
42
+ with:
43
+ commit: "ci: release"
44
+ title: "ci: release"
45
+ version: pnpm changeset version
46
+ publish: pnpm changeset publish --access public
47
+ env:
48
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
49
+ NPM_TOKEN: ""
50
+ NODE_AUTH_TOKEN: ""
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # @gabrielbryk/json-schema-to-zod
2
+
3
+ ## 2.7.3
4
+
5
+ ### Patch Changes
6
+
7
+ - d727121: Fix internal logic; publish patched release.
@@ -17,7 +17,7 @@ const parseIfThenElse = (schema, refs) => {
17
17
  ? ${$then}.safeParse(value)
18
18
  : ${$else}.safeParse(value);
19
19
  if (!result.success) {
20
- result.error.issues.forEach((issue) => ctx.addIssue({...issue}))
20
+ result.error.errors.forEach((error) => ctx.addIssue(error))
21
21
  }
22
22
  })`;
23
23
  // Store original if/then/else for JSON Schema round-trip
@@ -78,16 +78,16 @@ function parseObject(objectSchema, refs) {
78
78
  }
79
79
  else {
80
80
  if (additionalProperties) {
81
- patternProperties += `z.record(z.string(), z.union([${[
81
+ patternProperties += `z.record(z.union([${[
82
82
  ...Object.values(parsedPatternProperties),
83
83
  additionalProperties,
84
84
  ].join(", ")}]))`;
85
85
  }
86
86
  else if (Object.keys(parsedPatternProperties).length > 1) {
87
- patternProperties += `z.record(z.string(), z.union([${Object.values(parsedPatternProperties).join(", ")}]))`;
87
+ patternProperties += `z.record(z.union([${Object.values(parsedPatternProperties).join(", ")}]))`;
88
88
  }
89
89
  else {
90
- patternProperties += `z.record(z.string(), ${Object.values(parsedPatternProperties)})`;
90
+ patternProperties += `z.record(${Object.values(parsedPatternProperties)})`;
91
91
  }
92
92
  }
93
93
  patternProperties += ".superRefine((value, ctx) => {\n";
@@ -103,8 +103,9 @@ function parseObject(objectSchema, refs) {
103
103
  }
104
104
  }
105
105
  for (const key in objectSchema.patternProperties) {
106
+ const escapedPattern = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
106
107
  patternProperties +=
107
- "if (key.match(new RegExp(" + JSON.stringify(key) + "))) {\n";
108
+ "if (key.match(new RegExp(" + JSON.stringify(escapedPattern) + "))) {\n";
108
109
  if (additionalProperties) {
109
110
  patternProperties += "evaluated = true\n";
110
111
  }
@@ -114,7 +115,7 @@ function parseObject(objectSchema, refs) {
114
115
  ".safeParse(value[key])\n";
115
116
  patternProperties += "if (!result.success) {\n";
116
117
  patternProperties += `ctx.addIssue({
117
- path: [key],
118
+ path: [...ctx.path, key],
118
119
  code: 'custom',
119
120
  message: \`Invalid input: Key matching regex /\${key}/ must match schema\`,
120
121
  params: {
@@ -130,7 +131,7 @@ function parseObject(objectSchema, refs) {
130
131
  "const result = " + additionalProperties + ".safeParse(value[key])\n";
131
132
  patternProperties += "if (!result.success) {\n";
132
133
  patternProperties += `ctx.addIssue({
133
- path: [key],
134
+ path: [...ctx.path, key],
134
135
  code: 'custom',
135
136
  message: \`Invalid input: must match catchall schema\`,
136
137
  params: {
@@ -151,10 +152,10 @@ function parseObject(objectSchema, refs) {
151
152
  patternProperties += `.meta({ __jsonSchema: { patternProperties: ${patternPropsJson} } })`;
152
153
  }
153
154
  }
154
- // Check if there will be an .and() call that adds properties from oneOf/anyOf/allOf
155
+ // Check if there will be an .and() call that adds properties from oneOf/anyOf/allOf/if-then-else
155
156
  // In that case, we should NOT use .strict() because it will reject the additional keys
156
157
  // before the union gets a chance to validate them.
157
- const hasCompositionKeywords = parseSchema_js_1.its.an.anyOf(objectSchema) || parseSchema_js_1.its.a.oneOf(objectSchema) || parseSchema_js_1.its.an.allOf(objectSchema);
158
+ const hasCompositionKeywords = parseSchema_js_1.its.an.anyOf(objectSchema) || parseSchema_js_1.its.a.oneOf(objectSchema) || parseSchema_js_1.its.an.allOf(objectSchema) || parseSchema_js_1.its.a.conditional(objectSchema);
158
159
  let output = properties
159
160
  ? patternProperties
160
161
  ? properties + patternProperties
@@ -169,8 +170,8 @@ function parseObject(objectSchema, refs) {
169
170
  : patternProperties
170
171
  ? patternProperties
171
172
  : additionalProperties
172
- ? `z.record(z.string(), ${additionalProperties})`
173
- : `z.record(z.string(), ${(0, anyOrUnknown_js_1.anyOrUnknown)(refs)})`;
173
+ ? `z.record(${additionalProperties})`
174
+ : `z.record(${(0, anyOrUnknown_js_1.anyOrUnknown)(refs)})`;
174
175
  if (unevaluated === false && properties && !hasCompositionKeywords) {
175
176
  output += ".strict()";
176
177
  }
@@ -5,25 +5,17 @@ const parseSchema_js_1 = require("./parseSchema.js");
5
5
  const anyOrUnknown_js_1 = require("../utils/anyOrUnknown.js");
6
6
  const parseSimpleDiscriminatedOneOf = (schema, refs) => {
7
7
  const discriminator = schema.discriminator.propertyName;
8
- const entries = schema.oneOf.map((option, i) => {
9
- const opt = option;
10
- const discriminatorSchema = opt.properties[discriminator];
11
- const value = discriminatorSchema.const ??
12
- (discriminatorSchema.enum && discriminatorSchema.enum[0]);
13
- const parsed = (0, parseSchema_js_1.parseSchema)(option, {
14
- ...refs,
15
- path: [...refs.path, "oneOf", i],
16
- });
17
- const key = typeof value === "string" ? JSON.stringify(value) : JSON.stringify(String(value));
18
- return `${key}: ${parsed}`;
19
- });
8
+ const options = schema.oneOf.map((option, i) => (0, parseSchema_js_1.parseSchema)(option, {
9
+ ...refs,
10
+ path: [...refs.path, "oneOf", i],
11
+ }));
20
12
  return schema.oneOf.length
21
13
  ? schema.oneOf.length === 1
22
14
  ? (0, parseSchema_js_1.parseSchema)(schema.oneOf[0], {
23
15
  ...refs,
24
16
  path: [...refs.path, "oneOf", 0],
25
17
  })
26
- : `z.discriminatedUnion("${discriminator}", { ${entries.join(", ")} })`
18
+ : `z.discriminatedUnion("${discriminator}", [${options.join(", ")}])`
27
19
  : (0, anyOrUnknown_js_1.anyOrUnknown)(refs);
28
20
  };
29
21
  exports.parseSimpleDiscriminatedOneOf = parseSimpleDiscriminatedOneOf;
@@ -14,7 +14,7 @@ export const parseIfThenElse = (schema, refs) => {
14
14
  ? ${$then}.safeParse(value)
15
15
  : ${$else}.safeParse(value);
16
16
  if (!result.success) {
17
- result.error.issues.forEach((issue) => ctx.addIssue({...issue}))
17
+ result.error.errors.forEach((error) => ctx.addIssue(error))
18
18
  }
19
19
  })`;
20
20
  // Store original if/then/else for JSON Schema round-trip
@@ -75,16 +75,16 @@ export function parseObject(objectSchema, refs) {
75
75
  }
76
76
  else {
77
77
  if (additionalProperties) {
78
- patternProperties += `z.record(z.string(), z.union([${[
78
+ patternProperties += `z.record(z.union([${[
79
79
  ...Object.values(parsedPatternProperties),
80
80
  additionalProperties,
81
81
  ].join(", ")}]))`;
82
82
  }
83
83
  else if (Object.keys(parsedPatternProperties).length > 1) {
84
- patternProperties += `z.record(z.string(), z.union([${Object.values(parsedPatternProperties).join(", ")}]))`;
84
+ patternProperties += `z.record(z.union([${Object.values(parsedPatternProperties).join(", ")}]))`;
85
85
  }
86
86
  else {
87
- patternProperties += `z.record(z.string(), ${Object.values(parsedPatternProperties)})`;
87
+ patternProperties += `z.record(${Object.values(parsedPatternProperties)})`;
88
88
  }
89
89
  }
90
90
  patternProperties += ".superRefine((value, ctx) => {\n";
@@ -100,8 +100,9 @@ export function parseObject(objectSchema, refs) {
100
100
  }
101
101
  }
102
102
  for (const key in objectSchema.patternProperties) {
103
+ const escapedPattern = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
103
104
  patternProperties +=
104
- "if (key.match(new RegExp(" + JSON.stringify(key) + "))) {\n";
105
+ "if (key.match(new RegExp(" + JSON.stringify(escapedPattern) + "))) {\n";
105
106
  if (additionalProperties) {
106
107
  patternProperties += "evaluated = true\n";
107
108
  }
@@ -111,7 +112,7 @@ export function parseObject(objectSchema, refs) {
111
112
  ".safeParse(value[key])\n";
112
113
  patternProperties += "if (!result.success) {\n";
113
114
  patternProperties += `ctx.addIssue({
114
- path: [key],
115
+ path: [...ctx.path, key],
115
116
  code: 'custom',
116
117
  message: \`Invalid input: Key matching regex /\${key}/ must match schema\`,
117
118
  params: {
@@ -127,7 +128,7 @@ export function parseObject(objectSchema, refs) {
127
128
  "const result = " + additionalProperties + ".safeParse(value[key])\n";
128
129
  patternProperties += "if (!result.success) {\n";
129
130
  patternProperties += `ctx.addIssue({
130
- path: [key],
131
+ path: [...ctx.path, key],
131
132
  code: 'custom',
132
133
  message: \`Invalid input: must match catchall schema\`,
133
134
  params: {
@@ -148,10 +149,10 @@ export function parseObject(objectSchema, refs) {
148
149
  patternProperties += `.meta({ __jsonSchema: { patternProperties: ${patternPropsJson} } })`;
149
150
  }
150
151
  }
151
- // Check if there will be an .and() call that adds properties from oneOf/anyOf/allOf
152
+ // Check if there will be an .and() call that adds properties from oneOf/anyOf/allOf/if-then-else
152
153
  // In that case, we should NOT use .strict() because it will reject the additional keys
153
154
  // before the union gets a chance to validate them.
154
- const hasCompositionKeywords = its.an.anyOf(objectSchema) || its.a.oneOf(objectSchema) || its.an.allOf(objectSchema);
155
+ const hasCompositionKeywords = its.an.anyOf(objectSchema) || its.a.oneOf(objectSchema) || its.an.allOf(objectSchema) || its.a.conditional(objectSchema);
155
156
  let output = properties
156
157
  ? patternProperties
157
158
  ? properties + patternProperties
@@ -166,8 +167,8 @@ export function parseObject(objectSchema, refs) {
166
167
  : patternProperties
167
168
  ? patternProperties
168
169
  : additionalProperties
169
- ? `z.record(z.string(), ${additionalProperties})`
170
- : `z.record(z.string(), ${anyOrUnknown(refs)})`;
170
+ ? `z.record(${additionalProperties})`
171
+ : `z.record(${anyOrUnknown(refs)})`;
171
172
  if (unevaluated === false && properties && !hasCompositionKeywords) {
172
173
  output += ".strict()";
173
174
  }
@@ -2,24 +2,16 @@ import { parseSchema } from "./parseSchema.js";
2
2
  import { anyOrUnknown } from "../utils/anyOrUnknown.js";
3
3
  export const parseSimpleDiscriminatedOneOf = (schema, refs) => {
4
4
  const discriminator = schema.discriminator.propertyName;
5
- const entries = schema.oneOf.map((option, i) => {
6
- const opt = option;
7
- const discriminatorSchema = opt.properties[discriminator];
8
- const value = discriminatorSchema.const ??
9
- (discriminatorSchema.enum && discriminatorSchema.enum[0]);
10
- const parsed = parseSchema(option, {
11
- ...refs,
12
- path: [...refs.path, "oneOf", i],
13
- });
14
- const key = typeof value === "string" ? JSON.stringify(value) : JSON.stringify(String(value));
15
- return `${key}: ${parsed}`;
16
- });
5
+ const options = schema.oneOf.map((option, i) => parseSchema(option, {
6
+ ...refs,
7
+ path: [...refs.path, "oneOf", i],
8
+ }));
17
9
  return schema.oneOf.length
18
10
  ? schema.oneOf.length === 1
19
11
  ? parseSchema(schema.oneOf[0], {
20
12
  ...refs,
21
13
  path: [...refs.path, "oneOf", 0],
22
14
  })
23
- : `z.discriminatedUnion("${discriminator}", { ${entries.join(", ")} })`
15
+ : `z.discriminatedUnion("${discriminator}", [${options.join(", ")}])`
24
16
  : anyOrUnknown(refs);
25
17
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gabrielbryk/json-schema-to-zod",
3
- "version": "2.7.2",
3
+ "version": "2.7.3",
4
4
  "description": "Converts JSON schema objects or files into Zod schemas",
5
5
  "types": "./dist/types/index.d.ts",
6
6
  "bin": "./dist/cjs/cli.js",
@@ -61,6 +61,7 @@
61
61
  "access": "public"
62
62
  },
63
63
  "devDependencies": {
64
+ "@changesets/cli": "^2.29.8",
64
65
  "@types/json-schema": "^7.0.15",
65
66
  "@types/node": "^20.9.0",
66
67
  "fast-diff": "^1.3.0",