zod 4.1.0-canary.20250729T053738 → 4.1.0-canary.20250730T051934

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.
package/package.json CHANGED
@@ -1,9 +1,16 @@
1
1
  {
2
2
  "name": "zod",
3
- "version": "4.1.0-canary.20250729T053738",
3
+ "version": "4.1.0-canary.20250730T051934",
4
4
  "type": "module",
5
+ "license": "MIT",
5
6
  "author": "Colin McDonnell <zod@colinhacks.com>",
6
7
  "description": "TypeScript-first schema declaration and validation library with static type inference",
8
+ "homepage": "https://zod.dev",
9
+ "llms": "https://zod.dev/llms.txt",
10
+ "llmsFull": "https://zod.dev/llms-full.txt",
11
+ "mcpServer": "https://mcp.inkeep.com/zod/mcp",
12
+ "funding": "https://github.com/sponsors/colinhacks",
13
+ "sideEffects": false,
7
14
  "files": [
8
15
  "src",
9
16
  "**/*.js",
@@ -13,10 +20,6 @@
13
20
  "**/*.d.mts",
14
21
  "**/*.d.cts"
15
22
  ],
16
- "funding": "https://github.com/sponsors/colinhacks",
17
- "homepage": "https://zod.dev",
18
- "llms": "https://zod.dev/llms.txt",
19
- "mcp": "https://mcp.inkeep.com/zod/mcp",
20
23
  "keywords": [
21
24
  "typescript",
22
25
  "schema",
@@ -24,8 +27,6 @@
24
27
  "type",
25
28
  "inference"
26
29
  ],
27
- "license": "MIT",
28
- "sideEffects": false,
29
30
  "main": "./index.cjs",
30
31
  "types": "./index.d.cts",
31
32
  "module": "./index.js",
@@ -121,3 +121,16 @@ test("pipe optionality inside objects", () => {
121
121
  e: string;
122
122
  }>();
123
123
  });
124
+
125
+ test("optional prop with pipe", () => {
126
+ const schema = z.object({
127
+ id: z
128
+ .union([z.number(), z.string().nullish()])
129
+ .transform((val) => (val === null || val === undefined ? val : Number(val)))
130
+ .pipe(z.number())
131
+ .optional(),
132
+ });
133
+
134
+ schema.parse({});
135
+ schema.parse({}, { jitless: true });
136
+ });
@@ -539,6 +539,19 @@ describe("toJSONSchema", () => {
539
539
  `);
540
540
  });
541
541
 
542
+ test("number constraints draft-4", () => {
543
+ expect(z.toJSONSchema(z.number().gt(5).lt(10), { target: "draft-4" })).toMatchInlineSnapshot(`
544
+ {
545
+ "$schema": "http://json-schema.org/draft-04/schema#",
546
+ "exclusiveMaximum": true,
547
+ "exclusiveMinimum": true,
548
+ "maximum": 10,
549
+ "minimum": 5,
550
+ "type": "number",
551
+ }
552
+ `);
553
+ });
554
+
542
555
  test("arrays", () => {
543
556
  expect(z.toJSONSchema(z.array(z.string()))).toMatchInlineSnapshot(`
544
557
  {
@@ -745,6 +758,19 @@ describe("toJSONSchema", () => {
745
758
  `);
746
759
  });
747
760
 
761
+ test("literal draft-4", () => {
762
+ const a = z.literal("hello");
763
+ expect(z.toJSONSchema(a, { target: "draft-4" })).toMatchInlineSnapshot(`
764
+ {
765
+ "$schema": "http://json-schema.org/draft-04/schema#",
766
+ "enum": [
767
+ "hello",
768
+ ],
769
+ "type": "string",
770
+ }
771
+ `);
772
+ });
773
+
748
774
  // pipe
749
775
  test("pipe", () => {
750
776
  const schema = z
@@ -45,7 +45,10 @@ export type Schema =
45
45
  export type _JSONSchema = boolean | JSONSchema;
46
46
  export type JSONSchema = {
47
47
  [k: string]: unknown;
48
- $schema?: "https://json-schema.org/draft/2020-12/schema" | "http://json-schema.org/draft-07/schema#";
48
+ $schema?:
49
+ | "https://json-schema.org/draft/2020-12/schema"
50
+ | "http://json-schema.org/draft-07/schema#"
51
+ | "http://json-schema.org/draft-04/schema#";
49
52
  $id?: string;
50
53
  $anchor?: string;
51
54
  $ref?: string;
@@ -75,9 +78,9 @@ export type JSONSchema = {
75
78
  not?: _JSONSchema;
76
79
  multipleOf?: number;
77
80
  maximum?: number;
78
- exclusiveMaximum?: number;
81
+ exclusiveMaximum?: number | boolean;
79
82
  minimum?: number;
80
- exclusiveMinimum?: number;
83
+ exclusiveMinimum?: number | boolean;
81
84
  maxLength?: number;
82
85
  minLength?: number;
83
86
  pattern?: string;
@@ -3007,6 +3007,13 @@ export interface $ZodOptional<T extends SomeType = $ZodType> extends $ZodType {
3007
3007
  _zod: $ZodOptionalInternals<T>;
3008
3008
  }
3009
3009
 
3010
+ function handleOptionalResult(result: ParsePayload, input: unknown) {
3011
+ if (result.issues.length && input === undefined) {
3012
+ return { issues: [], value: undefined };
3013
+ }
3014
+ return result;
3015
+ }
3016
+
3010
3017
  export const $ZodOptional: core.$constructor<$ZodOptional> = /*@__PURE__*/ core.$constructor(
3011
3018
  "$ZodOptional",
3012
3019
  (inst, def) => {
@@ -3024,7 +3031,9 @@ export const $ZodOptional: core.$constructor<$ZodOptional> = /*@__PURE__*/ core.
3024
3031
 
3025
3032
  inst._zod.parse = (payload, ctx) => {
3026
3033
  if (def.innerType._zod.optin === "optional") {
3027
- return def.innerType._zod.run(payload, ctx);
3034
+ const result = def.innerType._zod.run(payload, ctx);
3035
+ if (result instanceof Promise) return result.then((r) => handleOptionalResult(r, payload.value));
3036
+ return handleOptionalResult(result, payload.value);
3028
3037
  }
3029
3038
  if (payload.value === undefined) {
3030
3039
  return payload;
@@ -10,8 +10,9 @@ interface JSONSchemaGeneratorParams {
10
10
  metadata?: $ZodRegistry<Record<string, any>>;
11
11
  /** The JSON Schema version to target.
12
12
  * - `"draft-2020-12"` — Default. JSON Schema Draft 2020-12
13
- * - `"draft-7"` — JSON Schema Draft 7 */
14
- target?: "draft-7" | "draft-2020-12";
13
+ * - `"draft-7"` — JSON Schema Draft 7
14
+ * - `"draft-4"` JSON Schema Draft 4 */
15
+ target?: "draft-4" | "draft-7" | "draft-2020-12";
15
16
  /** How to handle unrepresentable types.
16
17
  * - `"throw"` — Default. Unrepresentable types throw an error
17
18
  * - `"any"` — Unrepresentable types become `{}` */
@@ -71,7 +72,7 @@ interface Seen {
71
72
 
72
73
  export class JSONSchemaGenerator {
73
74
  metadataRegistry: $ZodRegistry<Record<string, any>>;
74
- target: "draft-7" | "draft-2020-12";
75
+ target: "draft-4" | "draft-7" | "draft-2020-12";
75
76
  unrepresentable: "throw" | "any";
76
77
  override: (ctx: {
77
78
  zodSchema: schemas.$ZodTypes;
@@ -163,7 +164,7 @@ export class JSONSchemaGenerator {
163
164
  else if (regexes.length > 1) {
164
165
  result.schema.allOf = [
165
166
  ...regexes.map((regex) => ({
166
- ...(this.target === "draft-7" ? ({ type: "string" } as const) : {}),
167
+ ...(this.target === "draft-7" || this.target === "draft-4" ? ({ type: "string" } as const) : {}),
167
168
  pattern: regex.source,
168
169
  })),
169
170
  ];
@@ -178,19 +179,33 @@ export class JSONSchemaGenerator {
178
179
  if (typeof format === "string" && format.includes("int")) json.type = "integer";
179
180
  else json.type = "number";
180
181
 
181
- if (typeof exclusiveMinimum === "number") json.exclusiveMinimum = exclusiveMinimum;
182
+ if (typeof exclusiveMinimum === "number") {
183
+ if (this.target === "draft-4") {
184
+ json.minimum = exclusiveMinimum;
185
+ json.exclusiveMinimum = true;
186
+ } else {
187
+ json.exclusiveMinimum = exclusiveMinimum;
188
+ }
189
+ }
182
190
  if (typeof minimum === "number") {
183
191
  json.minimum = minimum;
184
- if (typeof exclusiveMinimum === "number") {
192
+ if (typeof exclusiveMinimum === "number" && this.target !== "draft-4") {
185
193
  if (exclusiveMinimum >= minimum) delete json.minimum;
186
194
  else delete json.exclusiveMinimum;
187
195
  }
188
196
  }
189
197
 
190
- if (typeof exclusiveMaximum === "number") json.exclusiveMaximum = exclusiveMaximum;
198
+ if (typeof exclusiveMaximum === "number") {
199
+ if (this.target === "draft-4") {
200
+ json.maximum = exclusiveMaximum;
201
+ json.exclusiveMaximum = true;
202
+ } else {
203
+ json.exclusiveMaximum = exclusiveMaximum;
204
+ }
205
+ }
191
206
  if (typeof maximum === "number") {
192
207
  json.maximum = maximum;
193
- if (typeof exclusiveMaximum === "number") {
208
+ if (typeof exclusiveMaximum === "number" && this.target !== "draft-4") {
194
209
  if (exclusiveMaximum <= maximum) delete json.maximum;
195
210
  else delete json.exclusiveMaximum;
196
211
  }
@@ -379,7 +394,12 @@ export class JSONSchemaGenerator {
379
394
  case "record": {
380
395
  const json: JSONSchema.ObjectSchema = _json as any;
381
396
  json.type = "object";
382
- json.propertyNames = this.process(def.keyType, { ...params, path: [...params.path, "propertyNames"] });
397
+ if (this.target !== "draft-4") {
398
+ json.propertyNames = this.process(def.keyType, {
399
+ ...params,
400
+ path: [...params.path, "propertyNames"],
401
+ });
402
+ }
383
403
  json.additionalProperties = this.process(def.valueType, {
384
404
  ...params,
385
405
  path: [...params.path, "additionalProperties"],
@@ -432,7 +452,11 @@ export class JSONSchemaGenerator {
432
452
  } else if (vals.length === 1) {
433
453
  const val = vals[0]!;
434
454
  json.type = val === null ? ("null" as const) : (typeof val as any);
435
- json.const = val;
455
+ if (this.target === "draft-4") {
456
+ json.enum = [val];
457
+ } else {
458
+ json.const = val;
459
+ }
436
460
  } else {
437
461
  if (vals.every((v) => typeof v === "number")) json.type = "number";
438
462
  if (vals.every((v) => typeof v === "string")) json.type = "string";
@@ -749,7 +773,7 @@ export class JSONSchemaGenerator {
749
773
 
750
774
  // merge referenced schema into current
751
775
  const refSchema = this.seen.get(ref)!.schema;
752
- if (refSchema.$ref && params.target === "draft-7") {
776
+ if (refSchema.$ref && (params.target === "draft-7" || params.target === "draft-4")) {
753
777
  schema.allOf = schema.allOf ?? [];
754
778
  schema.allOf.push(refSchema);
755
779
  } else {
@@ -776,6 +800,8 @@ export class JSONSchemaGenerator {
776
800
  result.$schema = "https://json-schema.org/draft/2020-12/schema";
777
801
  } else if (this.target === "draft-7") {
778
802
  result.$schema = "http://json-schema.org/draft-07/schema#";
803
+ } else if (this.target === "draft-4") {
804
+ result.$schema = "http://json-schema.org/draft-04/schema#";
779
805
  } else {
780
806
  // @ts-ignore
781
807
  console.warn(`Invalid target: ${this.target}`);
@@ -1,5 +1,5 @@
1
1
  export const version = {
2
2
  major: 4,
3
3
  minor: 0,
4
- patch: 11 as number,
4
+ patch: 13 as number,
5
5
  } as const;
@@ -2,7 +2,7 @@ export type Schema = ObjectSchema | ArraySchema | StringSchema | NumberSchema |
2
2
  export type _JSONSchema = boolean | JSONSchema;
3
3
  export type JSONSchema = {
4
4
  [k: string]: unknown;
5
- $schema?: "https://json-schema.org/draft/2020-12/schema" | "http://json-schema.org/draft-07/schema#";
5
+ $schema?: "https://json-schema.org/draft/2020-12/schema" | "http://json-schema.org/draft-07/schema#" | "http://json-schema.org/draft-04/schema#";
6
6
  $id?: string;
7
7
  $anchor?: string;
8
8
  $ref?: string;
@@ -32,9 +32,9 @@ export type JSONSchema = {
32
32
  not?: _JSONSchema;
33
33
  multipleOf?: number;
34
34
  maximum?: number;
35
- exclusiveMaximum?: number;
35
+ exclusiveMaximum?: number | boolean;
36
36
  minimum?: number;
37
- exclusiveMinimum?: number;
37
+ exclusiveMinimum?: number | boolean;
38
38
  maxLength?: number;
39
39
  minLength?: number;
40
40
  pattern?: string;
@@ -2,7 +2,7 @@ export type Schema = ObjectSchema | ArraySchema | StringSchema | NumberSchema |
2
2
  export type _JSONSchema = boolean | JSONSchema;
3
3
  export type JSONSchema = {
4
4
  [k: string]: unknown;
5
- $schema?: "https://json-schema.org/draft/2020-12/schema" | "http://json-schema.org/draft-07/schema#";
5
+ $schema?: "https://json-schema.org/draft/2020-12/schema" | "http://json-schema.org/draft-07/schema#" | "http://json-schema.org/draft-04/schema#";
6
6
  $id?: string;
7
7
  $anchor?: string;
8
8
  $ref?: string;
@@ -32,9 +32,9 @@ export type JSONSchema = {
32
32
  not?: _JSONSchema;
33
33
  multipleOf?: number;
34
34
  maximum?: number;
35
- exclusiveMaximum?: number;
35
+ exclusiveMaximum?: number | boolean;
36
36
  minimum?: number;
37
- exclusiveMinimum?: number;
37
+ exclusiveMinimum?: number | boolean;
38
38
  maxLength?: number;
39
39
  minLength?: number;
40
40
  pattern?: string;
@@ -1415,6 +1415,12 @@ exports.$ZodTransform = core.$constructor("$ZodTransform", (inst, def) => {
1415
1415
  return payload;
1416
1416
  };
1417
1417
  });
1418
+ function handleOptionalResult(result, input) {
1419
+ if (result.issues.length && input === undefined) {
1420
+ return { issues: [], value: undefined };
1421
+ }
1422
+ return result;
1423
+ }
1418
1424
  exports.$ZodOptional = core.$constructor("$ZodOptional", (inst, def) => {
1419
1425
  exports.$ZodType.init(inst, def);
1420
1426
  inst._zod.optin = "optional";
@@ -1428,7 +1434,10 @@ exports.$ZodOptional = core.$constructor("$ZodOptional", (inst, def) => {
1428
1434
  });
1429
1435
  inst._zod.parse = (payload, ctx) => {
1430
1436
  if (def.innerType._zod.optin === "optional") {
1431
- return def.innerType._zod.run(payload, ctx);
1437
+ const result = def.innerType._zod.run(payload, ctx);
1438
+ if (result instanceof Promise)
1439
+ return result.then((r) => handleOptionalResult(r, payload.value));
1440
+ return handleOptionalResult(result, payload.value);
1432
1441
  }
1433
1442
  if (payload.value === undefined) {
1434
1443
  return payload;
@@ -1384,6 +1384,12 @@ export const $ZodTransform = /*@__PURE__*/ core.$constructor("$ZodTransform", (i
1384
1384
  return payload;
1385
1385
  };
1386
1386
  });
1387
+ function handleOptionalResult(result, input) {
1388
+ if (result.issues.length && input === undefined) {
1389
+ return { issues: [], value: undefined };
1390
+ }
1391
+ return result;
1392
+ }
1387
1393
  export const $ZodOptional = /*@__PURE__*/ core.$constructor("$ZodOptional", (inst, def) => {
1388
1394
  $ZodType.init(inst, def);
1389
1395
  inst._zod.optin = "optional";
@@ -1397,7 +1403,10 @@ export const $ZodOptional = /*@__PURE__*/ core.$constructor("$ZodOptional", (ins
1397
1403
  });
1398
1404
  inst._zod.parse = (payload, ctx) => {
1399
1405
  if (def.innerType._zod.optin === "optional") {
1400
- return def.innerType._zod.run(payload, ctx);
1406
+ const result = def.innerType._zod.run(payload, ctx);
1407
+ if (result instanceof Promise)
1408
+ return result.then((r) => handleOptionalResult(r, payload.value));
1409
+ return handleOptionalResult(result, payload.value);
1401
1410
  }
1402
1411
  if (payload.value === undefined) {
1403
1412
  return payload;
@@ -83,7 +83,7 @@ class JSONSchemaGenerator {
83
83
  else if (regexes.length > 1) {
84
84
  result.schema.allOf = [
85
85
  ...regexes.map((regex) => ({
86
- ...(this.target === "draft-7" ? { type: "string" } : {}),
86
+ ...(this.target === "draft-7" || this.target === "draft-4" ? { type: "string" } : {}),
87
87
  pattern: regex.source,
88
88
  })),
89
89
  ];
@@ -98,22 +98,36 @@ class JSONSchemaGenerator {
98
98
  json.type = "integer";
99
99
  else
100
100
  json.type = "number";
101
- if (typeof exclusiveMinimum === "number")
102
- json.exclusiveMinimum = exclusiveMinimum;
101
+ if (typeof exclusiveMinimum === "number") {
102
+ if (this.target === "draft-4") {
103
+ json.minimum = exclusiveMinimum;
104
+ json.exclusiveMinimum = true;
105
+ }
106
+ else {
107
+ json.exclusiveMinimum = exclusiveMinimum;
108
+ }
109
+ }
103
110
  if (typeof minimum === "number") {
104
111
  json.minimum = minimum;
105
- if (typeof exclusiveMinimum === "number") {
112
+ if (typeof exclusiveMinimum === "number" && this.target !== "draft-4") {
106
113
  if (exclusiveMinimum >= minimum)
107
114
  delete json.minimum;
108
115
  else
109
116
  delete json.exclusiveMinimum;
110
117
  }
111
118
  }
112
- if (typeof exclusiveMaximum === "number")
113
- json.exclusiveMaximum = exclusiveMaximum;
119
+ if (typeof exclusiveMaximum === "number") {
120
+ if (this.target === "draft-4") {
121
+ json.maximum = exclusiveMaximum;
122
+ json.exclusiveMaximum = true;
123
+ }
124
+ else {
125
+ json.exclusiveMaximum = exclusiveMaximum;
126
+ }
127
+ }
114
128
  if (typeof maximum === "number") {
115
129
  json.maximum = maximum;
116
- if (typeof exclusiveMaximum === "number") {
130
+ if (typeof exclusiveMaximum === "number" && this.target !== "draft-4") {
117
131
  if (exclusiveMaximum <= maximum)
118
132
  delete json.maximum;
119
133
  else
@@ -294,7 +308,12 @@ class JSONSchemaGenerator {
294
308
  case "record": {
295
309
  const json = _json;
296
310
  json.type = "object";
297
- json.propertyNames = this.process(def.keyType, { ...params, path: [...params.path, "propertyNames"] });
311
+ if (this.target !== "draft-4") {
312
+ json.propertyNames = this.process(def.keyType, {
313
+ ...params,
314
+ path: [...params.path, "propertyNames"],
315
+ });
316
+ }
298
317
  json.additionalProperties = this.process(def.valueType, {
299
318
  ...params,
300
319
  path: [...params.path, "additionalProperties"],
@@ -354,7 +373,12 @@ class JSONSchemaGenerator {
354
373
  else if (vals.length === 1) {
355
374
  const val = vals[0];
356
375
  json.type = val === null ? "null" : typeof val;
357
- json.const = val;
376
+ if (this.target === "draft-4") {
377
+ json.enum = [val];
378
+ }
379
+ else {
380
+ json.const = val;
381
+ }
358
382
  }
359
383
  else {
360
384
  if (vals.every((v) => typeof v === "number"))
@@ -650,7 +674,7 @@ class JSONSchemaGenerator {
650
674
  flattenRef(ref, params);
651
675
  // merge referenced schema into current
652
676
  const refSchema = this.seen.get(ref).schema;
653
- if (refSchema.$ref && params.target === "draft-7") {
677
+ if (refSchema.$ref && (params.target === "draft-7" || params.target === "draft-4")) {
654
678
  schema.allOf = schema.allOf ?? [];
655
679
  schema.allOf.push(refSchema);
656
680
  }
@@ -677,6 +701,9 @@ class JSONSchemaGenerator {
677
701
  else if (this.target === "draft-7") {
678
702
  result.$schema = "http://json-schema.org/draft-07/schema#";
679
703
  }
704
+ else if (this.target === "draft-4") {
705
+ result.$schema = "http://json-schema.org/draft-04/schema#";
706
+ }
680
707
  else {
681
708
  // @ts-ignore
682
709
  console.warn(`Invalid target: ${this.target}`);
@@ -7,8 +7,9 @@ interface JSONSchemaGeneratorParams {
7
7
  metadata?: $ZodRegistry<Record<string, any>>;
8
8
  /** The JSON Schema version to target.
9
9
  * - `"draft-2020-12"` — Default. JSON Schema Draft 2020-12
10
- * - `"draft-7"` — JSON Schema Draft 7 */
11
- target?: "draft-7" | "draft-2020-12";
10
+ * - `"draft-7"` — JSON Schema Draft 7
11
+ * - `"draft-4"` JSON Schema Draft 4 */
12
+ target?: "draft-4" | "draft-7" | "draft-2020-12";
12
13
  /** How to handle unrepresentable types.
13
14
  * - `"throw"` — Default. Unrepresentable types throw an error
14
15
  * - `"any"` — Unrepresentable types become `{}` */
@@ -60,7 +61,7 @@ interface Seen {
60
61
  }
61
62
  export declare class JSONSchemaGenerator {
62
63
  metadataRegistry: $ZodRegistry<Record<string, any>>;
63
- target: "draft-7" | "draft-2020-12";
64
+ target: "draft-4" | "draft-7" | "draft-2020-12";
64
65
  unrepresentable: "throw" | "any";
65
66
  override: (ctx: {
66
67
  zodSchema: schemas.$ZodTypes;
@@ -7,8 +7,9 @@ interface JSONSchemaGeneratorParams {
7
7
  metadata?: $ZodRegistry<Record<string, any>>;
8
8
  /** The JSON Schema version to target.
9
9
  * - `"draft-2020-12"` — Default. JSON Schema Draft 2020-12
10
- * - `"draft-7"` — JSON Schema Draft 7 */
11
- target?: "draft-7" | "draft-2020-12";
10
+ * - `"draft-7"` — JSON Schema Draft 7
11
+ * - `"draft-4"` JSON Schema Draft 4 */
12
+ target?: "draft-4" | "draft-7" | "draft-2020-12";
12
13
  /** How to handle unrepresentable types.
13
14
  * - `"throw"` — Default. Unrepresentable types throw an error
14
15
  * - `"any"` — Unrepresentable types become `{}` */
@@ -60,7 +61,7 @@ interface Seen {
60
61
  }
61
62
  export declare class JSONSchemaGenerator {
62
63
  metadataRegistry: $ZodRegistry<Record<string, any>>;
63
- target: "draft-7" | "draft-2020-12";
64
+ target: "draft-4" | "draft-7" | "draft-2020-12";
64
65
  unrepresentable: "throw" | "any";
65
66
  override: (ctx: {
66
67
  zodSchema: schemas.$ZodTypes;
@@ -79,7 +79,7 @@ export class JSONSchemaGenerator {
79
79
  else if (regexes.length > 1) {
80
80
  result.schema.allOf = [
81
81
  ...regexes.map((regex) => ({
82
- ...(this.target === "draft-7" ? { type: "string" } : {}),
82
+ ...(this.target === "draft-7" || this.target === "draft-4" ? { type: "string" } : {}),
83
83
  pattern: regex.source,
84
84
  })),
85
85
  ];
@@ -94,22 +94,36 @@ export class JSONSchemaGenerator {
94
94
  json.type = "integer";
95
95
  else
96
96
  json.type = "number";
97
- if (typeof exclusiveMinimum === "number")
98
- json.exclusiveMinimum = exclusiveMinimum;
97
+ if (typeof exclusiveMinimum === "number") {
98
+ if (this.target === "draft-4") {
99
+ json.minimum = exclusiveMinimum;
100
+ json.exclusiveMinimum = true;
101
+ }
102
+ else {
103
+ json.exclusiveMinimum = exclusiveMinimum;
104
+ }
105
+ }
99
106
  if (typeof minimum === "number") {
100
107
  json.minimum = minimum;
101
- if (typeof exclusiveMinimum === "number") {
108
+ if (typeof exclusiveMinimum === "number" && this.target !== "draft-4") {
102
109
  if (exclusiveMinimum >= minimum)
103
110
  delete json.minimum;
104
111
  else
105
112
  delete json.exclusiveMinimum;
106
113
  }
107
114
  }
108
- if (typeof exclusiveMaximum === "number")
109
- json.exclusiveMaximum = exclusiveMaximum;
115
+ if (typeof exclusiveMaximum === "number") {
116
+ if (this.target === "draft-4") {
117
+ json.maximum = exclusiveMaximum;
118
+ json.exclusiveMaximum = true;
119
+ }
120
+ else {
121
+ json.exclusiveMaximum = exclusiveMaximum;
122
+ }
123
+ }
110
124
  if (typeof maximum === "number") {
111
125
  json.maximum = maximum;
112
- if (typeof exclusiveMaximum === "number") {
126
+ if (typeof exclusiveMaximum === "number" && this.target !== "draft-4") {
113
127
  if (exclusiveMaximum <= maximum)
114
128
  delete json.maximum;
115
129
  else
@@ -290,7 +304,12 @@ export class JSONSchemaGenerator {
290
304
  case "record": {
291
305
  const json = _json;
292
306
  json.type = "object";
293
- json.propertyNames = this.process(def.keyType, { ...params, path: [...params.path, "propertyNames"] });
307
+ if (this.target !== "draft-4") {
308
+ json.propertyNames = this.process(def.keyType, {
309
+ ...params,
310
+ path: [...params.path, "propertyNames"],
311
+ });
312
+ }
294
313
  json.additionalProperties = this.process(def.valueType, {
295
314
  ...params,
296
315
  path: [...params.path, "additionalProperties"],
@@ -350,7 +369,12 @@ export class JSONSchemaGenerator {
350
369
  else if (vals.length === 1) {
351
370
  const val = vals[0];
352
371
  json.type = val === null ? "null" : typeof val;
353
- json.const = val;
372
+ if (this.target === "draft-4") {
373
+ json.enum = [val];
374
+ }
375
+ else {
376
+ json.const = val;
377
+ }
354
378
  }
355
379
  else {
356
380
  if (vals.every((v) => typeof v === "number"))
@@ -646,7 +670,7 @@ export class JSONSchemaGenerator {
646
670
  flattenRef(ref, params);
647
671
  // merge referenced schema into current
648
672
  const refSchema = this.seen.get(ref).schema;
649
- if (refSchema.$ref && params.target === "draft-7") {
673
+ if (refSchema.$ref && (params.target === "draft-7" || params.target === "draft-4")) {
650
674
  schema.allOf = schema.allOf ?? [];
651
675
  schema.allOf.push(refSchema);
652
676
  }
@@ -673,6 +697,9 @@ export class JSONSchemaGenerator {
673
697
  else if (this.target === "draft-7") {
674
698
  result.$schema = "http://json-schema.org/draft-07/schema#";
675
699
  }
700
+ else if (this.target === "draft-4") {
701
+ result.$schema = "http://json-schema.org/draft-04/schema#";
702
+ }
676
703
  else {
677
704
  // @ts-ignore
678
705
  console.warn(`Invalid target: ${this.target}`);
@@ -4,5 +4,5 @@ exports.version = void 0;
4
4
  exports.version = {
5
5
  major: 4,
6
6
  minor: 0,
7
- patch: 11,
7
+ patch: 13,
8
8
  };
@@ -1,5 +1,5 @@
1
1
  export const version = {
2
2
  major: 4,
3
3
  minor: 0,
4
- patch: 11,
4
+ patch: 13,
5
5
  };