zod 4.3.3 → 4.3.5
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 +1 -1
- package/src/v4/classic/from-json-schema.ts +1 -1
- package/src/v4/classic/tests/from-json-schema.test.ts +21 -0
- package/src/v4/classic/tests/record.test.ts +52 -0
- package/src/v4/classic/tests/to-json-schema.test.ts +111 -0
- package/src/v4/core/json-schema-processors.ts +34 -13
- package/src/v4/core/versions.ts +1 -1
- package/src/v4/mini/schemas.ts +1 -6
- package/v4/classic/from-json-schema.cjs +1 -1
- package/v4/classic/from-json-schema.js +1 -1
- package/v4/core/json-schema-processors.cjs +33 -13
- package/v4/core/json-schema-processors.js +33 -13
- package/v4/core/versions.cjs +1 -1
- package/v4/core/versions.js +1 -1
- package/v4/mini/schemas.cjs +31 -32
- package/v4/mini/schemas.d.cts +1 -2
- package/v4/mini/schemas.d.ts +1 -2
- package/v4/mini/schemas.js +1 -2
- package/src/v4/mini/tests/refine.test.ts +0 -19
package/package.json
CHANGED
|
@@ -597,7 +597,7 @@ function convertSchema(schema: JSONSchema.JSONSchema | boolean, ctx: ConversionC
|
|
|
597
597
|
}
|
|
598
598
|
}
|
|
599
599
|
|
|
600
|
-
// Content keywords
|
|
600
|
+
// Content keywords - store as metadata
|
|
601
601
|
const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"];
|
|
602
602
|
for (const key of contentMetadataKeys) {
|
|
603
603
|
if (key in schema) {
|
|
@@ -711,3 +711,24 @@ test("$comment and $anchor are captured as metadata", () => {
|
|
|
711
711
|
expect(meta?.$comment).toBe("This is a developer note");
|
|
712
712
|
expect(meta?.$anchor).toBe("my-anchor");
|
|
713
713
|
});
|
|
714
|
+
|
|
715
|
+
test("contentEncoding and contentMediaType are stored as metadata", () => {
|
|
716
|
+
const customRegistry = z.registry<{ contentEncoding?: string; contentMediaType?: string }>();
|
|
717
|
+
|
|
718
|
+
const schema = fromJSONSchema(
|
|
719
|
+
{
|
|
720
|
+
type: "string",
|
|
721
|
+
contentEncoding: "base64",
|
|
722
|
+
contentMediaType: "image/png",
|
|
723
|
+
},
|
|
724
|
+
{ registry: customRegistry }
|
|
725
|
+
);
|
|
726
|
+
|
|
727
|
+
// Should just be a string schema
|
|
728
|
+
expect(schema.parse("aGVsbG8gd29ybGQ=")).toBe("aGVsbG8gd29ybGQ=");
|
|
729
|
+
|
|
730
|
+
// Content keywords should be in metadata
|
|
731
|
+
const meta = customRegistry.get(schema);
|
|
732
|
+
expect(meta?.contentEncoding).toBe("base64");
|
|
733
|
+
expect(meta?.contentMediaType).toBe("image/png");
|
|
734
|
+
});
|
|
@@ -524,6 +524,58 @@ test("intersection of loose records", () => {
|
|
|
524
524
|
expect(() => schema.parse({ name: "John", N_count: "abc" })).toThrow(); // N_count should be number
|
|
525
525
|
});
|
|
526
526
|
|
|
527
|
+
test("object with looseRecord index signature", () => {
|
|
528
|
+
// Simulates TypeScript index signature: { label: string; [key: `label:${string}`]: string }
|
|
529
|
+
const schema = z.object({ label: z.string() }).and(z.looseRecord(z.string().regex(/^label:[a-z]{2}$/), z.string()));
|
|
530
|
+
|
|
531
|
+
type Schema = z.infer<typeof schema>;
|
|
532
|
+
expectTypeOf<Schema>().toEqualTypeOf<{ label: string } & Record<string, string>>();
|
|
533
|
+
|
|
534
|
+
// Valid: has required property and matching pattern keys
|
|
535
|
+
expect(schema.parse({ label: "Purple", "label:en": "Purple", "label:ru": "Пурпурный" })).toEqual({
|
|
536
|
+
label: "Purple",
|
|
537
|
+
"label:en": "Purple",
|
|
538
|
+
"label:ru": "Пурпурный",
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
// Valid: just required property
|
|
542
|
+
expect(schema.parse({ label: "Purple" })).toEqual({ label: "Purple" });
|
|
543
|
+
|
|
544
|
+
// Invalid: missing required property
|
|
545
|
+
expect(schema.safeParse({ "label:en": "Purple" })).toMatchInlineSnapshot(`
|
|
546
|
+
{
|
|
547
|
+
"error": [ZodError: [
|
|
548
|
+
{
|
|
549
|
+
"expected": "string",
|
|
550
|
+
"code": "invalid_type",
|
|
551
|
+
"path": [
|
|
552
|
+
"label"
|
|
553
|
+
],
|
|
554
|
+
"message": "Invalid input: expected string, received undefined"
|
|
555
|
+
}
|
|
556
|
+
]],
|
|
557
|
+
"success": false,
|
|
558
|
+
}
|
|
559
|
+
`);
|
|
560
|
+
|
|
561
|
+
// Invalid: pattern key with wrong value type
|
|
562
|
+
expect(schema.safeParse({ label: "Purple", "label:en": 123 })).toMatchInlineSnapshot(`
|
|
563
|
+
{
|
|
564
|
+
"error": [ZodError: [
|
|
565
|
+
{
|
|
566
|
+
"expected": "string",
|
|
567
|
+
"code": "invalid_type",
|
|
568
|
+
"path": [
|
|
569
|
+
"label:en"
|
|
570
|
+
],
|
|
571
|
+
"message": "Invalid input: expected string, received number"
|
|
572
|
+
}
|
|
573
|
+
]],
|
|
574
|
+
"success": false,
|
|
575
|
+
}
|
|
576
|
+
`);
|
|
577
|
+
});
|
|
578
|
+
|
|
527
579
|
test("numeric string keys", () => {
|
|
528
580
|
const schema = z.record(z.number(), z.number());
|
|
529
581
|
|
|
@@ -929,6 +929,117 @@ describe("toJSONSchema", () => {
|
|
|
929
929
|
`);
|
|
930
930
|
});
|
|
931
931
|
|
|
932
|
+
test("strict record with regex key uses propertyNames", () => {
|
|
933
|
+
const schema = z.record(z.string().regex(/^label:[a-z]{2}$/), z.string());
|
|
934
|
+
|
|
935
|
+
expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
|
|
936
|
+
{
|
|
937
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
938
|
+
"additionalProperties": {
|
|
939
|
+
"type": "string",
|
|
940
|
+
},
|
|
941
|
+
"propertyNames": {
|
|
942
|
+
"pattern": "^label:[a-z]{2}$",
|
|
943
|
+
"type": "string",
|
|
944
|
+
},
|
|
945
|
+
"type": "object",
|
|
946
|
+
}
|
|
947
|
+
`);
|
|
948
|
+
});
|
|
949
|
+
|
|
950
|
+
test("looseRecord with regex key uses patternProperties", () => {
|
|
951
|
+
const schema = z.looseRecord(z.string().regex(/^label:[a-z]{2}$/), z.string());
|
|
952
|
+
|
|
953
|
+
expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
|
|
954
|
+
{
|
|
955
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
956
|
+
"patternProperties": {
|
|
957
|
+
"^label:[a-z]{2}$": {
|
|
958
|
+
"type": "string",
|
|
959
|
+
},
|
|
960
|
+
},
|
|
961
|
+
"type": "object",
|
|
962
|
+
}
|
|
963
|
+
`);
|
|
964
|
+
});
|
|
965
|
+
|
|
966
|
+
test("looseRecord with multiple regex patterns uses patternProperties", () => {
|
|
967
|
+
const schema = z.looseRecord(
|
|
968
|
+
z
|
|
969
|
+
.string()
|
|
970
|
+
.regex(/^prefix_/)
|
|
971
|
+
.regex(/_suffix$/),
|
|
972
|
+
z.number()
|
|
973
|
+
);
|
|
974
|
+
|
|
975
|
+
expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
|
|
976
|
+
{
|
|
977
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
978
|
+
"patternProperties": {
|
|
979
|
+
"^prefix_": {
|
|
980
|
+
"type": "number",
|
|
981
|
+
},
|
|
982
|
+
"_suffix$": {
|
|
983
|
+
"type": "number",
|
|
984
|
+
},
|
|
985
|
+
},
|
|
986
|
+
"type": "object",
|
|
987
|
+
}
|
|
988
|
+
`);
|
|
989
|
+
});
|
|
990
|
+
|
|
991
|
+
test("looseRecord without regex key uses propertyNames", () => {
|
|
992
|
+
// looseRecord with plain string key should still use propertyNames
|
|
993
|
+
const schema = z.looseRecord(z.string(), z.boolean());
|
|
994
|
+
|
|
995
|
+
expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
|
|
996
|
+
{
|
|
997
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
998
|
+
"additionalProperties": {
|
|
999
|
+
"type": "boolean",
|
|
1000
|
+
},
|
|
1001
|
+
"propertyNames": {
|
|
1002
|
+
"type": "string",
|
|
1003
|
+
},
|
|
1004
|
+
"type": "object",
|
|
1005
|
+
}
|
|
1006
|
+
`);
|
|
1007
|
+
});
|
|
1008
|
+
|
|
1009
|
+
test("intersection of object with looseRecord uses patternProperties", () => {
|
|
1010
|
+
const zLabeled = z.object({ label: z.string() });
|
|
1011
|
+
const zLocalizedLabeled = z.looseRecord(z.string().regex(/^label:[a-z]{2}$/), z.string());
|
|
1012
|
+
const schema = zLabeled.and(zLocalizedLabeled);
|
|
1013
|
+
|
|
1014
|
+
expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
|
|
1015
|
+
{
|
|
1016
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
1017
|
+
"allOf": [
|
|
1018
|
+
{
|
|
1019
|
+
"additionalProperties": false,
|
|
1020
|
+
"properties": {
|
|
1021
|
+
"label": {
|
|
1022
|
+
"type": "string",
|
|
1023
|
+
},
|
|
1024
|
+
},
|
|
1025
|
+
"required": [
|
|
1026
|
+
"label",
|
|
1027
|
+
],
|
|
1028
|
+
"type": "object",
|
|
1029
|
+
},
|
|
1030
|
+
{
|
|
1031
|
+
"patternProperties": {
|
|
1032
|
+
"^label:[a-z]{2}$": {
|
|
1033
|
+
"type": "string",
|
|
1034
|
+
},
|
|
1035
|
+
},
|
|
1036
|
+
"type": "object",
|
|
1037
|
+
},
|
|
1038
|
+
],
|
|
1039
|
+
}
|
|
1040
|
+
`);
|
|
1041
|
+
});
|
|
1042
|
+
|
|
932
1043
|
test("tuple", () => {
|
|
933
1044
|
const schema = z.tuple([z.string(), z.number()]);
|
|
934
1045
|
expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
|
|
@@ -431,26 +431,47 @@ export const recordProcessor: Processor<schemas.$ZodRecord> = (schema, ctx, _jso
|
|
|
431
431
|
const json = _json as JSONSchema.ObjectSchema;
|
|
432
432
|
const def = schema._zod.def as schemas.$ZodRecordDef;
|
|
433
433
|
json.type = "object";
|
|
434
|
-
|
|
435
|
-
|
|
434
|
+
|
|
435
|
+
// For looseRecord with regex patterns, use patternProperties
|
|
436
|
+
// This correctly represents "only validate keys matching the pattern" semantics
|
|
437
|
+
// and composes well with allOf (intersections)
|
|
438
|
+
const keyType = def.keyType as schemas.$ZodTypes;
|
|
439
|
+
const keyBag = keyType._zod.bag as schemas.$ZodStringInternals<unknown>["bag"] | undefined;
|
|
440
|
+
const patterns = keyBag?.patterns;
|
|
441
|
+
|
|
442
|
+
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
443
|
+
// Use patternProperties for looseRecord with regex patterns
|
|
444
|
+
const valueSchema = process(def.valueType, ctx as any, {
|
|
436
445
|
...params,
|
|
437
|
-
path: [...params.path, "
|
|
446
|
+
path: [...params.path, "patternProperties", "*"],
|
|
447
|
+
});
|
|
448
|
+
json.patternProperties = {};
|
|
449
|
+
for (const pattern of patterns) {
|
|
450
|
+
json.patternProperties[pattern.source] = valueSchema;
|
|
451
|
+
}
|
|
452
|
+
} else {
|
|
453
|
+
// Default behavior: use propertyNames + additionalProperties
|
|
454
|
+
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
|
|
455
|
+
json.propertyNames = process(def.keyType, ctx as any, {
|
|
456
|
+
...params,
|
|
457
|
+
path: [...params.path, "propertyNames"],
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
json.additionalProperties = process(def.valueType, ctx as any, {
|
|
461
|
+
...params,
|
|
462
|
+
path: [...params.path, "additionalProperties"],
|
|
438
463
|
});
|
|
439
464
|
}
|
|
440
|
-
json.additionalProperties = process(def.valueType, ctx as any, {
|
|
441
|
-
...params,
|
|
442
|
-
path: [...params.path, "additionalProperties"],
|
|
443
|
-
});
|
|
444
465
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
const
|
|
466
|
+
// Add required for keys with discrete values (enum, literal, etc.)
|
|
467
|
+
const keyValues = keyType._zod.values;
|
|
468
|
+
if (keyValues) {
|
|
469
|
+
const validKeyValues = [...keyValues].filter(
|
|
449
470
|
(v): v is string | number => typeof v === "string" || typeof v === "number"
|
|
450
471
|
);
|
|
451
472
|
|
|
452
|
-
if (
|
|
453
|
-
json.required =
|
|
473
|
+
if (validKeyValues.length > 0) {
|
|
474
|
+
json.required = validKeyValues as string[];
|
|
454
475
|
}
|
|
455
476
|
}
|
|
456
477
|
};
|
package/src/v4/core/versions.ts
CHANGED
package/src/v4/mini/schemas.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as core from "../core/index.js";
|
|
2
|
-
import
|
|
2
|
+
import * as util from "../core/util.js";
|
|
3
3
|
import * as parse from "./parse.js";
|
|
4
4
|
|
|
5
5
|
type SomeType = core.SomeType;
|
|
@@ -12,10 +12,6 @@ export interface ZodMiniType<
|
|
|
12
12
|
type: Internals["def"]["type"];
|
|
13
13
|
check(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
|
|
14
14
|
with(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
|
|
15
|
-
refine<Ch extends (arg: core.output<this>) => unknown | Promise<unknown>>(
|
|
16
|
-
check: Ch,
|
|
17
|
-
params?: string | core.$ZodCustomParams
|
|
18
|
-
): Ch extends (arg: any) => arg is infer R ? core.$ZodNarrow<this, R> : this;
|
|
19
15
|
clone(def?: Internals["def"], params?: { parent: boolean }): this;
|
|
20
16
|
register<R extends core.$ZodRegistry>(
|
|
21
17
|
registry: R,
|
|
@@ -72,7 +68,6 @@ export const ZodMiniType: core.$constructor<ZodMiniType> = /*@__PURE__*/ core.$c
|
|
|
72
68
|
);
|
|
73
69
|
};
|
|
74
70
|
inst.with = inst.check;
|
|
75
|
-
inst.refine = (check, params) => inst.check(refine(check, params)) as never;
|
|
76
71
|
inst.clone = (_def, params) => core.clone(inst, _def, params);
|
|
77
72
|
inst.brand = () => inst as any;
|
|
78
73
|
inst.register = ((reg: any, meta: any) => {
|
|
@@ -571,7 +571,7 @@ function convertSchema(schema, ctx) {
|
|
|
571
571
|
extraMeta[key] = schema[key];
|
|
572
572
|
}
|
|
573
573
|
}
|
|
574
|
-
// Content keywords
|
|
574
|
+
// Content keywords - store as metadata
|
|
575
575
|
const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"];
|
|
576
576
|
for (const key of contentMetadataKeys) {
|
|
577
577
|
if (key in schema) {
|
|
@@ -545,7 +545,7 @@ function convertSchema(schema, ctx) {
|
|
|
545
545
|
extraMeta[key] = schema[key];
|
|
546
546
|
}
|
|
547
547
|
}
|
|
548
|
-
// Content keywords
|
|
548
|
+
// Content keywords - store as metadata
|
|
549
549
|
const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"];
|
|
550
550
|
for (const key of contentMetadataKeys) {
|
|
551
551
|
if (key in schema) {
|
|
@@ -436,22 +436,42 @@ const recordProcessor = (schema, ctx, _json, params) => {
|
|
|
436
436
|
const json = _json;
|
|
437
437
|
const def = schema._zod.def;
|
|
438
438
|
json.type = "object";
|
|
439
|
-
|
|
440
|
-
|
|
439
|
+
// For looseRecord with regex patterns, use patternProperties
|
|
440
|
+
// This correctly represents "only validate keys matching the pattern" semantics
|
|
441
|
+
// and composes well with allOf (intersections)
|
|
442
|
+
const keyType = def.keyType;
|
|
443
|
+
const keyBag = keyType._zod.bag;
|
|
444
|
+
const patterns = keyBag?.patterns;
|
|
445
|
+
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
446
|
+
// Use patternProperties for looseRecord with regex patterns
|
|
447
|
+
const valueSchema = (0, to_json_schema_js_1.process)(def.valueType, ctx, {
|
|
441
448
|
...params,
|
|
442
|
-
path: [...params.path, "
|
|
449
|
+
path: [...params.path, "patternProperties", "*"],
|
|
443
450
|
});
|
|
451
|
+
json.patternProperties = {};
|
|
452
|
+
for (const pattern of patterns) {
|
|
453
|
+
json.patternProperties[pattern.source] = valueSchema;
|
|
454
|
+
}
|
|
444
455
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
456
|
+
else {
|
|
457
|
+
// Default behavior: use propertyNames + additionalProperties
|
|
458
|
+
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
|
|
459
|
+
json.propertyNames = (0, to_json_schema_js_1.process)(def.keyType, ctx, {
|
|
460
|
+
...params,
|
|
461
|
+
path: [...params.path, "propertyNames"],
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
json.additionalProperties = (0, to_json_schema_js_1.process)(def.valueType, ctx, {
|
|
465
|
+
...params,
|
|
466
|
+
path: [...params.path, "additionalProperties"],
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
// Add required for keys with discrete values (enum, literal, etc.)
|
|
470
|
+
const keyValues = keyType._zod.values;
|
|
471
|
+
if (keyValues) {
|
|
472
|
+
const validKeyValues = [...keyValues].filter((v) => typeof v === "string" || typeof v === "number");
|
|
473
|
+
if (validKeyValues.length > 0) {
|
|
474
|
+
json.required = validKeyValues;
|
|
455
475
|
}
|
|
456
476
|
}
|
|
457
477
|
};
|
|
@@ -404,22 +404,42 @@ export const recordProcessor = (schema, ctx, _json, params) => {
|
|
|
404
404
|
const json = _json;
|
|
405
405
|
const def = schema._zod.def;
|
|
406
406
|
json.type = "object";
|
|
407
|
-
|
|
408
|
-
|
|
407
|
+
// For looseRecord with regex patterns, use patternProperties
|
|
408
|
+
// This correctly represents "only validate keys matching the pattern" semantics
|
|
409
|
+
// and composes well with allOf (intersections)
|
|
410
|
+
const keyType = def.keyType;
|
|
411
|
+
const keyBag = keyType._zod.bag;
|
|
412
|
+
const patterns = keyBag?.patterns;
|
|
413
|
+
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
414
|
+
// Use patternProperties for looseRecord with regex patterns
|
|
415
|
+
const valueSchema = process(def.valueType, ctx, {
|
|
409
416
|
...params,
|
|
410
|
-
path: [...params.path, "
|
|
417
|
+
path: [...params.path, "patternProperties", "*"],
|
|
411
418
|
});
|
|
419
|
+
json.patternProperties = {};
|
|
420
|
+
for (const pattern of patterns) {
|
|
421
|
+
json.patternProperties[pattern.source] = valueSchema;
|
|
422
|
+
}
|
|
412
423
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
424
|
+
else {
|
|
425
|
+
// Default behavior: use propertyNames + additionalProperties
|
|
426
|
+
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
|
|
427
|
+
json.propertyNames = process(def.keyType, ctx, {
|
|
428
|
+
...params,
|
|
429
|
+
path: [...params.path, "propertyNames"],
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
json.additionalProperties = process(def.valueType, ctx, {
|
|
433
|
+
...params,
|
|
434
|
+
path: [...params.path, "additionalProperties"],
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
// Add required for keys with discrete values (enum, literal, etc.)
|
|
438
|
+
const keyValues = keyType._zod.values;
|
|
439
|
+
if (keyValues) {
|
|
440
|
+
const validKeyValues = [...keyValues].filter((v) => typeof v === "string" || typeof v === "number");
|
|
441
|
+
if (validKeyValues.length > 0) {
|
|
442
|
+
json.required = validKeyValues;
|
|
423
443
|
}
|
|
424
444
|
}
|
|
425
445
|
};
|
package/v4/core/versions.cjs
CHANGED
package/v4/core/versions.js
CHANGED
package/v4/mini/schemas.cjs
CHANGED
|
@@ -127,7 +127,7 @@ exports.function = _function;
|
|
|
127
127
|
exports._function = _function;
|
|
128
128
|
exports.function = _function;
|
|
129
129
|
const core = __importStar(require("../core/index.cjs"));
|
|
130
|
-
const
|
|
130
|
+
const util = __importStar(require("../core/util.cjs"));
|
|
131
131
|
const parse = __importStar(require("./parse.cjs"));
|
|
132
132
|
exports.ZodMiniType = core.$constructor("ZodMiniType", (inst, def) => {
|
|
133
133
|
if (!inst._zod)
|
|
@@ -149,7 +149,6 @@ exports.ZodMiniType = core.$constructor("ZodMiniType", (inst, def) => {
|
|
|
149
149
|
}, { parent: true });
|
|
150
150
|
};
|
|
151
151
|
inst.with = inst.check;
|
|
152
|
-
inst.refine = (check, params) => inst.check(refine(check, params));
|
|
153
152
|
inst.clone = (_def, params) => core.clone(inst, _def, params);
|
|
154
153
|
inst.brand = () => inst;
|
|
155
154
|
inst.register = ((reg, meta) => {
|
|
@@ -221,7 +220,7 @@ function httpUrl(params) {
|
|
|
221
220
|
return core._url(exports.ZodMiniURL, {
|
|
222
221
|
protocol: /^https?$/,
|
|
223
222
|
hostname: core.regexes.domain,
|
|
224
|
-
...
|
|
223
|
+
...util.normalizeParams(params),
|
|
225
224
|
});
|
|
226
225
|
}
|
|
227
226
|
exports.ZodMiniEmoji = core.$constructor("ZodMiniEmoji", (inst, def) => {
|
|
@@ -518,7 +517,7 @@ function array(element, params) {
|
|
|
518
517
|
return new exports.ZodMiniArray({
|
|
519
518
|
type: "array",
|
|
520
519
|
element: element,
|
|
521
|
-
...
|
|
520
|
+
...util.normalizeParams(params),
|
|
522
521
|
});
|
|
523
522
|
}
|
|
524
523
|
// .keyof
|
|
@@ -530,14 +529,14 @@ function keyof(schema) {
|
|
|
530
529
|
exports.ZodMiniObject = core.$constructor("ZodMiniObject", (inst, def) => {
|
|
531
530
|
core.$ZodObject.init(inst, def);
|
|
532
531
|
exports.ZodMiniType.init(inst, def);
|
|
533
|
-
|
|
532
|
+
util.defineLazy(inst, "shape", () => def.shape);
|
|
534
533
|
});
|
|
535
534
|
// @__NO_SIDE_EFFECTS__
|
|
536
535
|
function object(shape, params) {
|
|
537
536
|
const def = {
|
|
538
537
|
type: "object",
|
|
539
538
|
shape: shape ?? {},
|
|
540
|
-
...
|
|
539
|
+
...util.normalizeParams(params),
|
|
541
540
|
};
|
|
542
541
|
return new exports.ZodMiniObject(def);
|
|
543
542
|
}
|
|
@@ -548,7 +547,7 @@ function strictObject(shape, params) {
|
|
|
548
547
|
type: "object",
|
|
549
548
|
shape,
|
|
550
549
|
catchall: never(),
|
|
551
|
-
...
|
|
550
|
+
...util.normalizeParams(params),
|
|
552
551
|
});
|
|
553
552
|
}
|
|
554
553
|
// looseObject
|
|
@@ -558,38 +557,38 @@ function looseObject(shape, params) {
|
|
|
558
557
|
type: "object",
|
|
559
558
|
shape,
|
|
560
559
|
catchall: unknown(),
|
|
561
|
-
...
|
|
560
|
+
...util.normalizeParams(params),
|
|
562
561
|
});
|
|
563
562
|
}
|
|
564
563
|
// object methods
|
|
565
564
|
// @__NO_SIDE_EFFECTS__
|
|
566
565
|
function extend(schema, shape) {
|
|
567
|
-
return
|
|
566
|
+
return util.extend(schema, shape);
|
|
568
567
|
}
|
|
569
568
|
// @__NO_SIDE_EFFECTS__
|
|
570
569
|
function safeExtend(schema, shape) {
|
|
571
|
-
return
|
|
570
|
+
return util.safeExtend(schema, shape);
|
|
572
571
|
}
|
|
573
572
|
// @__NO_SIDE_EFFECTS__
|
|
574
573
|
function merge(schema, shape) {
|
|
575
|
-
return
|
|
574
|
+
return util.extend(schema, shape);
|
|
576
575
|
}
|
|
577
576
|
// @__NO_SIDE_EFFECTS__
|
|
578
577
|
function pick(schema, mask) {
|
|
579
|
-
return
|
|
578
|
+
return util.pick(schema, mask);
|
|
580
579
|
}
|
|
581
580
|
// .omit
|
|
582
581
|
// @__NO_SIDE_EFFECTS__
|
|
583
582
|
function omit(schema, mask) {
|
|
584
|
-
return
|
|
583
|
+
return util.omit(schema, mask);
|
|
585
584
|
}
|
|
586
585
|
// @__NO_SIDE_EFFECTS__
|
|
587
586
|
function partial(schema, mask) {
|
|
588
|
-
return
|
|
587
|
+
return util.partial(exports.ZodMiniOptional, schema, mask);
|
|
589
588
|
}
|
|
590
589
|
// @__NO_SIDE_EFFECTS__
|
|
591
590
|
function required(schema, mask) {
|
|
592
|
-
return
|
|
591
|
+
return util.required(exports.ZodMiniNonOptional, schema, mask);
|
|
593
592
|
}
|
|
594
593
|
// @__NO_SIDE_EFFECTS__
|
|
595
594
|
function catchall(inst, catchall) {
|
|
@@ -604,7 +603,7 @@ function union(options, params) {
|
|
|
604
603
|
return new exports.ZodMiniUnion({
|
|
605
604
|
type: "union",
|
|
606
605
|
options: options,
|
|
607
|
-
...
|
|
606
|
+
...util.normalizeParams(params),
|
|
608
607
|
});
|
|
609
608
|
}
|
|
610
609
|
exports.ZodMiniXor = core.$constructor("ZodMiniXor", (inst, def) => {
|
|
@@ -619,7 +618,7 @@ function xor(options, params) {
|
|
|
619
618
|
type: "union",
|
|
620
619
|
options: options,
|
|
621
620
|
inclusive: false,
|
|
622
|
-
...
|
|
621
|
+
...util.normalizeParams(params),
|
|
623
622
|
});
|
|
624
623
|
}
|
|
625
624
|
exports.ZodMiniDiscriminatedUnion = core.$constructor("ZodMiniDiscriminatedUnion", (inst, def) => {
|
|
@@ -632,7 +631,7 @@ function discriminatedUnion(discriminator, options, params) {
|
|
|
632
631
|
type: "union",
|
|
633
632
|
options,
|
|
634
633
|
discriminator,
|
|
635
|
-
...
|
|
634
|
+
...util.normalizeParams(params),
|
|
636
635
|
});
|
|
637
636
|
}
|
|
638
637
|
exports.ZodMiniIntersection = core.$constructor("ZodMiniIntersection", (inst, def) => {
|
|
@@ -660,7 +659,7 @@ function tuple(items, _paramsOrRest, _params) {
|
|
|
660
659
|
type: "tuple",
|
|
661
660
|
items: items,
|
|
662
661
|
rest,
|
|
663
|
-
...
|
|
662
|
+
...util.normalizeParams(params),
|
|
664
663
|
});
|
|
665
664
|
}
|
|
666
665
|
exports.ZodMiniRecord = core.$constructor("ZodMiniRecord", (inst, def) => {
|
|
@@ -673,7 +672,7 @@ function record(keyType, valueType, params) {
|
|
|
673
672
|
type: "record",
|
|
674
673
|
keyType,
|
|
675
674
|
valueType: valueType,
|
|
676
|
-
...
|
|
675
|
+
...util.normalizeParams(params),
|
|
677
676
|
});
|
|
678
677
|
}
|
|
679
678
|
// @__NO_SIDE_EFFECTS__
|
|
@@ -684,7 +683,7 @@ function partialRecord(keyType, valueType, params) {
|
|
|
684
683
|
type: "record",
|
|
685
684
|
keyType: k,
|
|
686
685
|
valueType: valueType,
|
|
687
|
-
...
|
|
686
|
+
...util.normalizeParams(params),
|
|
688
687
|
});
|
|
689
688
|
}
|
|
690
689
|
function looseRecord(keyType, valueType, params) {
|
|
@@ -693,7 +692,7 @@ function looseRecord(keyType, valueType, params) {
|
|
|
693
692
|
keyType,
|
|
694
693
|
valueType: valueType,
|
|
695
694
|
mode: "loose",
|
|
696
|
-
...
|
|
695
|
+
...util.normalizeParams(params),
|
|
697
696
|
});
|
|
698
697
|
}
|
|
699
698
|
exports.ZodMiniMap = core.$constructor("ZodMiniMap", (inst, def) => {
|
|
@@ -706,7 +705,7 @@ function map(keyType, valueType, params) {
|
|
|
706
705
|
type: "map",
|
|
707
706
|
keyType: keyType,
|
|
708
707
|
valueType: valueType,
|
|
709
|
-
...
|
|
708
|
+
...util.normalizeParams(params),
|
|
710
709
|
});
|
|
711
710
|
}
|
|
712
711
|
exports.ZodMiniSet = core.$constructor("ZodMiniSet", (inst, def) => {
|
|
@@ -718,7 +717,7 @@ function set(valueType, params) {
|
|
|
718
717
|
return new exports.ZodMiniSet({
|
|
719
718
|
type: "set",
|
|
720
719
|
valueType: valueType,
|
|
721
|
-
...
|
|
720
|
+
...util.normalizeParams(params),
|
|
722
721
|
});
|
|
723
722
|
}
|
|
724
723
|
exports.ZodMiniEnum = core.$constructor("ZodMiniEnum", (inst, def) => {
|
|
@@ -732,7 +731,7 @@ function _enum(values, params) {
|
|
|
732
731
|
return new exports.ZodMiniEnum({
|
|
733
732
|
type: "enum",
|
|
734
733
|
entries,
|
|
735
|
-
...
|
|
734
|
+
...util.normalizeParams(params),
|
|
736
735
|
});
|
|
737
736
|
}
|
|
738
737
|
// @__NO_SIDE_EFFECTS__
|
|
@@ -747,7 +746,7 @@ function nativeEnum(entries, params) {
|
|
|
747
746
|
return new exports.ZodMiniEnum({
|
|
748
747
|
type: "enum",
|
|
749
748
|
entries,
|
|
750
|
-
...
|
|
749
|
+
...util.normalizeParams(params),
|
|
751
750
|
});
|
|
752
751
|
}
|
|
753
752
|
exports.ZodMiniLiteral = core.$constructor("ZodMiniLiteral", (inst, def) => {
|
|
@@ -759,7 +758,7 @@ function literal(value, params) {
|
|
|
759
758
|
return new exports.ZodMiniLiteral({
|
|
760
759
|
type: "literal",
|
|
761
760
|
values: Array.isArray(value) ? value : [value],
|
|
762
|
-
...
|
|
761
|
+
...util.normalizeParams(params),
|
|
763
762
|
});
|
|
764
763
|
}
|
|
765
764
|
exports.ZodMiniFile = core.$constructor("ZodMiniFile", (inst, def) => {
|
|
@@ -829,7 +828,7 @@ function _default(innerType, defaultValue) {
|
|
|
829
828
|
type: "default",
|
|
830
829
|
innerType: innerType,
|
|
831
830
|
get defaultValue() {
|
|
832
|
-
return typeof defaultValue === "function" ? defaultValue() :
|
|
831
|
+
return typeof defaultValue === "function" ? defaultValue() : util.shallowClone(defaultValue);
|
|
833
832
|
},
|
|
834
833
|
});
|
|
835
834
|
}
|
|
@@ -843,7 +842,7 @@ function prefault(innerType, defaultValue) {
|
|
|
843
842
|
type: "prefault",
|
|
844
843
|
innerType: innerType,
|
|
845
844
|
get defaultValue() {
|
|
846
|
-
return typeof defaultValue === "function" ? defaultValue() :
|
|
845
|
+
return typeof defaultValue === "function" ? defaultValue() : util.shallowClone(defaultValue);
|
|
847
846
|
},
|
|
848
847
|
});
|
|
849
848
|
}
|
|
@@ -856,7 +855,7 @@ function nonoptional(innerType, params) {
|
|
|
856
855
|
return new exports.ZodMiniNonOptional({
|
|
857
856
|
type: "nonoptional",
|
|
858
857
|
innerType: innerType,
|
|
859
|
-
...
|
|
858
|
+
...util.normalizeParams(params),
|
|
860
859
|
});
|
|
861
860
|
}
|
|
862
861
|
exports.ZodMiniSuccess = core.$constructor("ZodMiniSuccess", (inst, def) => {
|
|
@@ -936,7 +935,7 @@ function templateLiteral(parts, params) {
|
|
|
936
935
|
return new exports.ZodMiniTemplateLiteral({
|
|
937
936
|
type: "template_literal",
|
|
938
937
|
parts,
|
|
939
|
-
...
|
|
938
|
+
...util.normalizeParams(params),
|
|
940
939
|
});
|
|
941
940
|
}
|
|
942
941
|
exports.ZodMiniLazy = core.$constructor("ZodMiniLazy", (inst, def) => {
|
|
@@ -973,7 +972,7 @@ exports.ZodMiniCustom = core.$constructor("ZodMiniCustom", (inst, def) => {
|
|
|
973
972
|
function check(fn, params) {
|
|
974
973
|
const ch = new core.$ZodCheck({
|
|
975
974
|
check: "custom",
|
|
976
|
-
...
|
|
975
|
+
...util.normalizeParams(params),
|
|
977
976
|
});
|
|
978
977
|
ch._zod.check = fn;
|
|
979
978
|
return ch;
|
package/v4/mini/schemas.d.cts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import * as core from "../core/index.cjs";
|
|
2
|
-
import
|
|
2
|
+
import * as util from "../core/util.cjs";
|
|
3
3
|
type SomeType = core.SomeType;
|
|
4
4
|
export interface ZodMiniType<out Output = unknown, out Input = unknown, out Internals extends core.$ZodTypeInternals<Output, Input> = core.$ZodTypeInternals<Output, Input>> extends core.$ZodType<Output, Input, Internals> {
|
|
5
5
|
type: Internals["def"]["type"];
|
|
6
6
|
check(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
|
|
7
7
|
with(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
|
|
8
|
-
refine<Ch extends (arg: core.output<this>) => unknown | Promise<unknown>>(check: Ch, params?: string | core.$ZodCustomParams): Ch extends (arg: any) => arg is infer R ? core.$ZodNarrow<this, R> : this;
|
|
9
8
|
clone(def?: Internals["def"], params?: {
|
|
10
9
|
parent: boolean;
|
|
11
10
|
}): this;
|
package/v4/mini/schemas.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import * as core from "../core/index.js";
|
|
2
|
-
import
|
|
2
|
+
import * as util from "../core/util.js";
|
|
3
3
|
type SomeType = core.SomeType;
|
|
4
4
|
export interface ZodMiniType<out Output = unknown, out Input = unknown, out Internals extends core.$ZodTypeInternals<Output, Input> = core.$ZodTypeInternals<Output, Input>> extends core.$ZodType<Output, Input, Internals> {
|
|
5
5
|
type: Internals["def"]["type"];
|
|
6
6
|
check(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
|
|
7
7
|
with(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
|
|
8
|
-
refine<Ch extends (arg: core.output<this>) => unknown | Promise<unknown>>(check: Ch, params?: string | core.$ZodCustomParams): Ch extends (arg: any) => arg is infer R ? core.$ZodNarrow<this, R> : this;
|
|
9
8
|
clone(def?: Internals["def"], params?: {
|
|
10
9
|
parent: boolean;
|
|
11
10
|
}): this;
|
package/v4/mini/schemas.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as core from "../core/index.js";
|
|
2
|
-
import
|
|
2
|
+
import * as util from "../core/util.js";
|
|
3
3
|
import * as parse from "./parse.js";
|
|
4
4
|
export const ZodMiniType = /*@__PURE__*/ core.$constructor("ZodMiniType", (inst, def) => {
|
|
5
5
|
if (!inst._zod)
|
|
@@ -21,7 +21,6 @@ export const ZodMiniType = /*@__PURE__*/ core.$constructor("ZodMiniType", (inst,
|
|
|
21
21
|
}, { parent: true });
|
|
22
22
|
};
|
|
23
23
|
inst.with = inst.check;
|
|
24
|
-
inst.refine = (check, params) => inst.check(refine(check, params));
|
|
25
24
|
inst.clone = (_def, params) => core.clone(inst, _def, params);
|
|
26
25
|
inst.brand = () => inst;
|
|
27
26
|
inst.register = ((reg, meta) => {
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { describe, expectTypeOf, test } from "vitest";
|
|
2
|
-
import type * as core from "../../core/index.js";
|
|
3
|
-
import * as z from "../index.js";
|
|
4
|
-
|
|
5
|
-
describe("type refinement with type guards", () => {
|
|
6
|
-
test("type guard narrows output type", () => {
|
|
7
|
-
const schema = z.string().refine((s): s is "a" => s === "a");
|
|
8
|
-
|
|
9
|
-
expectTypeOf<core.input<typeof schema>>().toEqualTypeOf<string>();
|
|
10
|
-
expectTypeOf<core.output<typeof schema>>().toEqualTypeOf<"a">();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
test("non-type-guard refine does not narrow", () => {
|
|
14
|
-
const schema = z.string().refine((s) => s.length > 0);
|
|
15
|
-
|
|
16
|
-
expectTypeOf<core.input<typeof schema>>().toEqualTypeOf<string>();
|
|
17
|
-
expectTypeOf<core.output<typeof schema>>().toEqualTypeOf<string>();
|
|
18
|
-
});
|
|
19
|
-
});
|