Update dashboard, kb, memory +4 more (+28 ~18 -1)
This commit is contained in:
30
node_modules/zod/src/v4/classic/checks.ts
generated
vendored
Normal file
30
node_modules/zod/src/v4/classic/checks.ts
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
export {
|
||||
_lt as lt,
|
||||
_lte as lte,
|
||||
_gt as gt,
|
||||
_gte as gte,
|
||||
_positive as positive,
|
||||
_negative as negative,
|
||||
_nonpositive as nonpositive,
|
||||
_nonnegative as nonnegative,
|
||||
_multipleOf as multipleOf,
|
||||
_maxSize as maxSize,
|
||||
_minSize as minSize,
|
||||
_size as size,
|
||||
_maxLength as maxLength,
|
||||
_minLength as minLength,
|
||||
_length as length,
|
||||
_regex as regex,
|
||||
_lowercase as lowercase,
|
||||
_uppercase as uppercase,
|
||||
_includes as includes,
|
||||
_startsWith as startsWith,
|
||||
_endsWith as endsWith,
|
||||
_property as property,
|
||||
_mime as mime,
|
||||
_overwrite as overwrite,
|
||||
_normalize as normalize,
|
||||
_trim as trim,
|
||||
_toLowerCase as toLowerCase,
|
||||
_toUpperCase as toUpperCase,
|
||||
} from "../core/index.js";
|
||||
27
node_modules/zod/src/v4/classic/coerce.ts
generated
vendored
Normal file
27
node_modules/zod/src/v4/classic/coerce.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import * as core from "../core/index.js";
|
||||
import * as schemas from "./schemas.js";
|
||||
|
||||
export interface ZodCoercedString<T = unknown> extends schemas._ZodString<core.$ZodStringInternals<T>> {}
|
||||
export function string<T = unknown>(params?: string | core.$ZodStringParams): ZodCoercedString<T> {
|
||||
return core._coercedString(schemas.ZodString, params) as any;
|
||||
}
|
||||
|
||||
export interface ZodCoercedNumber<T = unknown> extends schemas._ZodNumber<core.$ZodNumberInternals<T>> {}
|
||||
export function number<T = unknown>(params?: string | core.$ZodNumberParams): ZodCoercedNumber<T> {
|
||||
return core._coercedNumber(schemas.ZodNumber, params) as ZodCoercedNumber<T>;
|
||||
}
|
||||
|
||||
export interface ZodCoercedBoolean<T = unknown> extends schemas._ZodBoolean<core.$ZodBooleanInternals<T>> {}
|
||||
export function boolean<T = unknown>(params?: string | core.$ZodBooleanParams): ZodCoercedBoolean<T> {
|
||||
return core._coercedBoolean(schemas.ZodBoolean, params) as ZodCoercedBoolean<T>;
|
||||
}
|
||||
|
||||
export interface ZodCoercedBigInt<T = unknown> extends schemas._ZodBigInt<core.$ZodBigIntInternals<T>> {}
|
||||
export function bigint<T = unknown>(params?: string | core.$ZodBigIntParams): ZodCoercedBigInt<T> {
|
||||
return core._coercedBigint(schemas.ZodBigInt, params) as ZodCoercedBigInt<T>;
|
||||
}
|
||||
|
||||
export interface ZodCoercedDate<T = unknown> extends schemas._ZodDate<core.$ZodDateInternals<T>> {}
|
||||
export function date<T = unknown>(params?: string | core.$ZodDateParams): ZodCoercedDate<T> {
|
||||
return core._coercedDate(schemas.ZodDate, params) as ZodCoercedDate<T>;
|
||||
}
|
||||
66
node_modules/zod/src/v4/classic/compat.ts
generated
vendored
Normal file
66
node_modules/zod/src/v4/classic/compat.ts
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
// Zod 3 compat layer
|
||||
|
||||
import * as core from "../core/index.js";
|
||||
import type { ZodType } from "./schemas.js";
|
||||
|
||||
export type {
|
||||
/** @deprecated Use `z.output<T>` instead. */
|
||||
output as TypeOf,
|
||||
/** @deprecated Use `z.output<T>` instead. */
|
||||
output as Infer,
|
||||
/** @deprecated Use `z.core.$$ZodFirstPartyTypes` instead */
|
||||
$ZodTypes as ZodFirstPartySchemaTypes,
|
||||
} from "../core/index.js";
|
||||
|
||||
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
||||
export const ZodIssueCode = {
|
||||
invalid_type: "invalid_type",
|
||||
too_big: "too_big",
|
||||
too_small: "too_small",
|
||||
invalid_format: "invalid_format",
|
||||
not_multiple_of: "not_multiple_of",
|
||||
unrecognized_keys: "unrecognized_keys",
|
||||
invalid_union: "invalid_union",
|
||||
invalid_key: "invalid_key",
|
||||
invalid_element: "invalid_element",
|
||||
invalid_value: "invalid_value",
|
||||
custom: "custom",
|
||||
} as const;
|
||||
|
||||
/** @deprecated Use `z.$ZodFlattenedError` */
|
||||
export type inferFlattenedErrors<T extends core.$ZodType, U = string> = core.$ZodFlattenedError<core.output<T>, U>;
|
||||
|
||||
/** @deprecated Use `z.$ZodFormattedError` */
|
||||
export type inferFormattedError<T extends core.$ZodType<any, any>, U = string> = core.$ZodFormattedError<
|
||||
core.output<T>,
|
||||
U
|
||||
>;
|
||||
|
||||
/** Use `z.$brand` instead */
|
||||
export type BRAND<T extends string | number | symbol = string | number | symbol> = {
|
||||
[core.$brand]: { [k in T]: true };
|
||||
};
|
||||
export { $brand, config } from "../core/index.js";
|
||||
|
||||
/** @deprecated Use `z.config(params)` instead. */
|
||||
export function setErrorMap(map: core.$ZodErrorMap): void {
|
||||
core.config({
|
||||
customError: map,
|
||||
});
|
||||
}
|
||||
|
||||
/** @deprecated Use `z.config()` instead. */
|
||||
export function getErrorMap(): core.$ZodErrorMap<core.$ZodIssue> | undefined {
|
||||
return core.config().customError;
|
||||
}
|
||||
|
||||
export type {
|
||||
/** @deprecated Use z.ZodType (without generics) instead. */
|
||||
ZodType as ZodTypeAny,
|
||||
/** @deprecated Use `z.ZodType` */
|
||||
ZodType as ZodSchema,
|
||||
/** @deprecated Use `z.ZodType` */
|
||||
ZodType as Schema,
|
||||
};
|
||||
|
||||
export type ZodRawShape = core.$ZodShape;
|
||||
75
node_modules/zod/src/v4/classic/errors.ts
generated
vendored
Normal file
75
node_modules/zod/src/v4/classic/errors.ts
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
import * as core from "../core/index.js";
|
||||
import { $ZodError } from "../core/index.js";
|
||||
|
||||
/** @deprecated Use `z.core.$ZodIssue` from `@zod/core` instead, especially if you are building a library on top of Zod. */
|
||||
export type ZodIssue = core.$ZodIssue;
|
||||
|
||||
/** An Error-like class used to store Zod validation issues. */
|
||||
export interface ZodError<T = unknown> extends $ZodError<T> {
|
||||
/** @deprecated Use the `z.treeifyError(err)` function instead. */
|
||||
format(): core.$ZodFormattedError<T>;
|
||||
format<U>(mapper: (issue: core.$ZodIssue) => U): core.$ZodFormattedError<T, U>;
|
||||
/** @deprecated Use the `z.treeifyError(err)` function instead. */
|
||||
flatten(): core.$ZodFlattenedError<T>;
|
||||
flatten<U>(mapper: (issue: core.$ZodIssue) => U): core.$ZodFlattenedError<T, U>;
|
||||
/** @deprecated Push directly to `.issues` instead. */
|
||||
addIssue(issue: core.$ZodIssue): void;
|
||||
/** @deprecated Push directly to `.issues` instead. */
|
||||
addIssues(issues: core.$ZodIssue[]): void;
|
||||
|
||||
/** @deprecated Check `err.issues.length === 0` instead. */
|
||||
isEmpty: boolean;
|
||||
}
|
||||
|
||||
const initializer = (inst: ZodError, issues: core.$ZodIssue[]) => {
|
||||
$ZodError.init(inst, issues);
|
||||
inst.name = "ZodError";
|
||||
Object.defineProperties(inst, {
|
||||
format: {
|
||||
value: (mapper: any) => core.formatError(inst, mapper),
|
||||
// enumerable: false,
|
||||
},
|
||||
flatten: {
|
||||
value: (mapper: any) => core.flattenError(inst, mapper),
|
||||
// enumerable: false,
|
||||
},
|
||||
addIssue: {
|
||||
value: (issue: any) => inst.issues.push(issue),
|
||||
// enumerable: false,
|
||||
},
|
||||
addIssues: {
|
||||
value: (issues: any) => inst.issues.push(...issues),
|
||||
// enumerable: false,
|
||||
},
|
||||
isEmpty: {
|
||||
get() {
|
||||
return inst.issues.length === 0;
|
||||
},
|
||||
// enumerable: false,
|
||||
},
|
||||
});
|
||||
// Object.defineProperty(inst, "isEmpty", {
|
||||
// get() {
|
||||
// return inst.issues.length === 0;
|
||||
// },
|
||||
// });
|
||||
};
|
||||
export const ZodError: core.$constructor<ZodError> = core.$constructor("ZodError", initializer);
|
||||
export const ZodRealError: core.$constructor<ZodError> = core.$constructor("ZodError", initializer, {
|
||||
Parent: Error,
|
||||
});
|
||||
|
||||
export type {
|
||||
/** @deprecated Use `z.core.$ZodFlattenedError` instead. */
|
||||
$ZodFlattenedError as ZodFlattenedError,
|
||||
/** @deprecated Use `z.core.$ZodFormattedError` instead. */
|
||||
$ZodFormattedError as ZodFormattedError,
|
||||
/** @deprecated Use `z.core.$ZodErrorMap` instead. */
|
||||
$ZodErrorMap as ZodErrorMap,
|
||||
} from "../core/index.js";
|
||||
|
||||
/** @deprecated Use `z.core.$ZodRawIssue` instead. */
|
||||
export type IssueData = core.$ZodRawIssue;
|
||||
|
||||
// /** @deprecated Use `z.core.$ZodErrorMapCtx` instead. */
|
||||
// export type ErrorMapCtx = core.$ZodErrorMapCtx;
|
||||
50
node_modules/zod/src/v4/classic/external.ts
generated
vendored
Normal file
50
node_modules/zod/src/v4/classic/external.ts
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
export * as core from "../core/index.js";
|
||||
export * from "./schemas.js";
|
||||
export * from "./checks.js";
|
||||
export * from "./errors.js";
|
||||
export * from "./parse.js";
|
||||
export * from "./compat.js";
|
||||
|
||||
// zod-specified
|
||||
import { config } from "../core/index.js";
|
||||
import en from "../locales/en.js";
|
||||
config(en());
|
||||
|
||||
export type { infer, output, input } from "../core/index.js";
|
||||
export {
|
||||
globalRegistry,
|
||||
type GlobalMeta,
|
||||
registry,
|
||||
config,
|
||||
function,
|
||||
$output,
|
||||
$input,
|
||||
$brand,
|
||||
clone,
|
||||
regexes,
|
||||
treeifyError,
|
||||
prettifyError,
|
||||
formatError,
|
||||
flattenError,
|
||||
toJSONSchema,
|
||||
TimePrecision,
|
||||
NEVER,
|
||||
} from "../core/index.js";
|
||||
|
||||
export * as locales from "../locales/index.js";
|
||||
|
||||
// iso
|
||||
// must be exported from top-level
|
||||
// https://github.com/colinhacks/zod/issues/4491
|
||||
export { ZodISODateTime, ZodISODate, ZodISOTime, ZodISODuration } from "./iso.js";
|
||||
export * as iso from "./iso.js";
|
||||
|
||||
// coerce
|
||||
export type {
|
||||
ZodCoercedString,
|
||||
ZodCoercedNumber,
|
||||
ZodCoercedBigInt,
|
||||
ZodCoercedBoolean,
|
||||
ZodCoercedDate,
|
||||
} from "./coerce.js";
|
||||
export * as coerce from "./coerce.js";
|
||||
5
node_modules/zod/src/v4/classic/index.ts
generated
vendored
Normal file
5
node_modules/zod/src/v4/classic/index.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import * as z from "./external.js";
|
||||
|
||||
export { z };
|
||||
export * from "./external.js";
|
||||
export default z;
|
||||
90
node_modules/zod/src/v4/classic/iso.ts
generated
vendored
Normal file
90
node_modules/zod/src/v4/classic/iso.ts
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
import * as core from "../core/index.js";
|
||||
import * as schemas from "./schemas.js";
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//////////////////////////////////////////////
|
||||
////////// //////////
|
||||
////////// ZodISODateTime //////////
|
||||
////////// //////////
|
||||
//////////////////////////////////////////////
|
||||
//////////////////////////////////////////////
|
||||
|
||||
export interface ZodISODateTime extends schemas.ZodStringFormat {
|
||||
_zod: core.$ZodISODateTimeInternals;
|
||||
}
|
||||
export const ZodISODateTime: core.$constructor<ZodISODateTime> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodISODateTime",
|
||||
(inst, def) => {
|
||||
core.$ZodISODateTime.init(inst, def);
|
||||
schemas.ZodStringFormat.init(inst, def);
|
||||
}
|
||||
);
|
||||
|
||||
export function datetime(params?: string | core.$ZodISODateTimeParams): ZodISODateTime {
|
||||
return core._isoDateTime(ZodISODateTime, params);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
//////////////////////////////////////////
|
||||
////////// //////////
|
||||
////////// ZodISODate //////////
|
||||
////////// //////////
|
||||
//////////////////////////////////////////
|
||||
//////////////////////////////////////////
|
||||
|
||||
export interface ZodISODate extends schemas.ZodStringFormat {
|
||||
_zod: core.$ZodISODateInternals;
|
||||
}
|
||||
export const ZodISODate: core.$constructor<ZodISODate> = /*@__PURE__*/ core.$constructor("ZodISODate", (inst, def) => {
|
||||
core.$ZodISODate.init(inst, def);
|
||||
schemas.ZodStringFormat.init(inst, def);
|
||||
});
|
||||
|
||||
export function date(params?: string | core.$ZodISODateParams): ZodISODate {
|
||||
return core._isoDate(ZodISODate, params);
|
||||
}
|
||||
|
||||
// ZodISOTime
|
||||
|
||||
//////////////////////////////////////////
|
||||
//////////////////////////////////////////
|
||||
////////// //////////
|
||||
////////// ZodISOTime //////////
|
||||
////////// //////////
|
||||
//////////////////////////////////////////
|
||||
//////////////////////////////////////////
|
||||
|
||||
export interface ZodISOTime extends schemas.ZodStringFormat {
|
||||
_zod: core.$ZodISOTimeInternals;
|
||||
}
|
||||
export const ZodISOTime: core.$constructor<ZodISOTime> = /*@__PURE__*/ core.$constructor("ZodISOTime", (inst, def) => {
|
||||
core.$ZodISOTime.init(inst, def);
|
||||
schemas.ZodStringFormat.init(inst, def);
|
||||
});
|
||||
|
||||
export function time(params?: string | core.$ZodISOTimeParams): ZodISOTime {
|
||||
return core._isoTime(ZodISOTime, params);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//////////////////////////////////////////////
|
||||
////////// //////////
|
||||
////////// ZodISODuration //////////
|
||||
////////// //////////
|
||||
//////////////////////////////////////////////
|
||||
//////////////////////////////////////////////
|
||||
|
||||
export interface ZodISODuration extends schemas.ZodStringFormat {
|
||||
_zod: core.$ZodISODurationInternals;
|
||||
}
|
||||
export const ZodISODuration: core.$constructor<ZodISODuration> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodISODuration",
|
||||
(inst, def) => {
|
||||
core.$ZodISODuration.init(inst, def);
|
||||
schemas.ZodStringFormat.init(inst, def);
|
||||
}
|
||||
);
|
||||
|
||||
export function duration(params?: string | core.$ZodISODurationParams): ZodISODuration {
|
||||
return core._isoDuration(ZodISODuration, params);
|
||||
}
|
||||
33
node_modules/zod/src/v4/classic/parse.ts
generated
vendored
Normal file
33
node_modules/zod/src/v4/classic/parse.ts
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import * as core from "../core/index.js";
|
||||
import { type ZodError, ZodRealError } from "./errors.js";
|
||||
|
||||
export type ZodSafeParseResult<T> = ZodSafeParseSuccess<T> | ZodSafeParseError<T>;
|
||||
export type ZodSafeParseSuccess<T> = { success: true; data: T; error?: never };
|
||||
export type ZodSafeParseError<T> = { success: false; data?: never; error: ZodError<T> };
|
||||
|
||||
export const parse: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>,
|
||||
_params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass }
|
||||
) => core.output<T> = /* @__PURE__ */ core._parse(ZodRealError) as any;
|
||||
|
||||
export const parseAsync: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>,
|
||||
_params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass }
|
||||
) => Promise<core.output<T>> = /* @__PURE__ */ core._parseAsync(ZodRealError) as any;
|
||||
|
||||
export const safeParse: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
// _params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass }
|
||||
) => ZodSafeParseResult<core.output<T>> = /* @__PURE__ */ core._safeParse(ZodRealError) as any;
|
||||
|
||||
export const safeParseAsync: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => Promise<ZodSafeParseResult<core.output<T>>> = /* @__PURE__ */ core._safeParseAsync(ZodRealError) as any;
|
||||
2054
node_modules/zod/src/v4/classic/schemas.ts
generated
vendored
Normal file
2054
node_modules/zod/src/v4/classic/schemas.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
26
node_modules/zod/src/v4/classic/tests/anyunknown.test.ts
generated
vendored
Normal file
26
node_modules/zod/src/v4/classic/tests/anyunknown.test.ts
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("check any inference", () => {
|
||||
const t1 = z.any();
|
||||
t1.optional();
|
||||
t1.nullable();
|
||||
type t1 = z.infer<typeof t1>;
|
||||
expectTypeOf<t1>().toEqualTypeOf<any>();
|
||||
});
|
||||
|
||||
test("check unknown inference", () => {
|
||||
const t1 = z.unknown();
|
||||
t1.optional();
|
||||
t1.nullable();
|
||||
type t1 = z.infer<typeof t1>;
|
||||
expectTypeOf<t1>().toEqualTypeOf<unknown>();
|
||||
});
|
||||
|
||||
test("check never inference", () => {
|
||||
const t1 = z.never();
|
||||
expect(() => t1.parse(undefined)).toThrow();
|
||||
expect(() => t1.parse("asdf")).toThrow();
|
||||
expect(() => t1.parse(null)).toThrow();
|
||||
});
|
||||
264
node_modules/zod/src/v4/classic/tests/array.test.ts
generated
vendored
Normal file
264
node_modules/zod/src/v4/classic/tests/array.test.ts
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("type inference", () => {
|
||||
const schema = z.string().array();
|
||||
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<string[]>();
|
||||
});
|
||||
|
||||
test("array min/max", async () => {
|
||||
const schema = z.array(z.string()).min(2).max(2);
|
||||
const r1 = await schema.safeParse(["asdf"]);
|
||||
expect(r1.success).toEqual(false);
|
||||
expect(r1.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected array to have >=2 items",
|
||||
"minimum": 2,
|
||||
"origin": "array",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
||||
const r2 = await schema.safeParse(["asdf", "asdf", "asdf"]);
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 2,
|
||||
"message": "Too big: expected array to have <=2 items",
|
||||
"origin": "array",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test("array length", async () => {
|
||||
const schema = z.array(z.string()).length(2);
|
||||
schema.parse(["asdf", "asdf"]);
|
||||
|
||||
const r1 = await schema.safeParse(["asdf"]);
|
||||
expect(r1.success).toEqual(false);
|
||||
expect(r1.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"exact": true,
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected array to have >=2 items",
|
||||
"minimum": 2,
|
||||
"origin": "array",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
||||
const r2 = await schema.safeParse(["asdf", "asdf", "asdf"]);
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"exact": true,
|
||||
"inclusive": true,
|
||||
"maximum": 2,
|
||||
"message": "Too big: expected array to have <=2 items",
|
||||
"origin": "array",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test("array.nonempty()", () => {
|
||||
const schema = z.string().array().nonempty();
|
||||
schema.parse(["a"]);
|
||||
expect(() => schema.parse([])).toThrow();
|
||||
});
|
||||
|
||||
test("array.nonempty().max()", () => {
|
||||
const schema = z.string().array().nonempty().max(2);
|
||||
schema.parse(["a"]);
|
||||
expect(() => schema.parse([])).toThrow();
|
||||
expect(() => schema.parse(["a", "a", "a"])).toThrow();
|
||||
});
|
||||
|
||||
test("parse empty array in nonempty", () => {
|
||||
expect(() =>
|
||||
z
|
||||
.array(z.string())
|
||||
.nonempty()
|
||||
.parse([] as any)
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
test("get element", () => {
|
||||
const schema = z.string().array();
|
||||
schema.element.parse("asdf");
|
||||
expect(() => schema.element.parse(12)).toThrow();
|
||||
});
|
||||
|
||||
test("continue parsing despite array size error", () => {
|
||||
const schema = z.object({
|
||||
people: z.string().array().min(2),
|
||||
});
|
||||
|
||||
const result = schema.safeParse({
|
||||
people: [123],
|
||||
});
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"people",
|
||||
0
|
||||
],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
},
|
||||
{
|
||||
"origin": "array",
|
||||
"code": "too_small",
|
||||
"minimum": 2,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"people"
|
||||
],
|
||||
"message": "Too small: expected array to have >=2 items"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("parse should fail given sparse array", () => {
|
||||
const schema = z.array(z.string()).nonempty().min(1).max(3);
|
||||
const result = schema.safeParse(new Array(3));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
0
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
1
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
2
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
// const unique = z.string().array().unique();
|
||||
// const uniqueArrayOfObjects = z.array(z.object({ name: z.string() })).unique({ identifier: (item) => item.name });
|
||||
|
||||
// test("passing unique validation", () => {
|
||||
// unique.parse(["a", "b", "c"]);
|
||||
// uniqueArrayOfObjects.parse([{ name: "Leo" }, { name: "Joe" }]);
|
||||
// });
|
||||
|
||||
// test("failing unique validation", () => {
|
||||
// expect(() => unique.parse(["a", "a", "b"])).toThrow();
|
||||
// expect(() => uniqueArrayOfObjects.parse([{ name: "Leo" }, { name: "Leo" }])).toThrow();
|
||||
// });
|
||||
|
||||
// test("continue parsing despite array of primitives uniqueness error", () => {
|
||||
// const schema = z.number().array().unique();
|
||||
|
||||
// const result = schema.safeParse([1, 1, 2, 2, 3]);
|
||||
|
||||
// expect(result.success).toEqual(false);
|
||||
// if (!result.success) {
|
||||
// const issue = result.error.issues.find(({ code }) => code === "not_unique");
|
||||
// expect(issue?.message).toEqual("Values must be unique");
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("continue parsing despite array of objects not_unique error", () => {
|
||||
// const schema = z.array(z.object({ name: z.string() })).unique({
|
||||
// identifier: (item) => item.name,
|
||||
// showDuplicates: true,
|
||||
// });
|
||||
|
||||
// const result = schema.safeParse([
|
||||
// { name: "Leo" },
|
||||
// { name: "Joe" },
|
||||
// { name: "Leo" },
|
||||
// ]);
|
||||
|
||||
// expect(result.success).toEqual(false);
|
||||
// if (!result.success) {
|
||||
// const issue = result.error.issues.find(({ code }) => code === "not_unique");
|
||||
// expect(issue?.message).toEqual("Element(s): 'Leo' not unique");
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("returns custom error message without duplicate elements", () => {
|
||||
// const schema = z.number().array().unique({ message: "Custom message" });
|
||||
|
||||
// const result = schema.safeParse([1, 1, 2, 2, 3]);
|
||||
|
||||
// expect(result.success).toEqual(false);
|
||||
// if (!result.success) {
|
||||
// const issue = result.error.issues.find(({ code }) => code === "not_unique");
|
||||
// expect(issue?.message).toEqual("Custom message");
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("returns error message with duplicate elements", () => {
|
||||
// const schema = z.number().array().unique({ showDuplicates: true });
|
||||
|
||||
// const result = schema.safeParse([1, 1, 2, 2, 3]);
|
||||
|
||||
// expect(result.success).toEqual(false);
|
||||
// if (!result.success) {
|
||||
// const issue = result.error.issues.find(({ code }) => code === "not_unique");
|
||||
// expect(issue?.message).toEqual("Element(s): '1,2' not unique");
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("returns custom error message with duplicate elements", () => {
|
||||
// const schema = z
|
||||
// .number()
|
||||
// .array()
|
||||
// .unique({
|
||||
// message: (item) => `Custom message: '${item}' are not unique`,
|
||||
// showDuplicates: true,
|
||||
// });
|
||||
|
||||
// const result = schema.safeParse([1, 1, 2, 2, 3]);
|
||||
|
||||
// expect(result.success).toEqual(false);
|
||||
// if (!result.success) {
|
||||
// const issue = result.error.issues.find(({ code }) => code === "not_unique");
|
||||
// expect(issue?.message).toEqual("Custom message: '1,2' are not unique");
|
||||
// }
|
||||
// });
|
||||
210
node_modules/zod/src/v4/classic/tests/assignability.test.ts
generated
vendored
Normal file
210
node_modules/zod/src/v4/classic/tests/assignability.test.ts
generated
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
import { expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("assignability", () => {
|
||||
// $ZodString
|
||||
z.string() satisfies z.core.$ZodString;
|
||||
z.string() satisfies z.ZodString;
|
||||
|
||||
// $ZodNumber
|
||||
z.number() satisfies z.core.$ZodNumber;
|
||||
z.number() satisfies z.ZodNumber;
|
||||
|
||||
// $ZodBigInt
|
||||
z.bigint() satisfies z.core.$ZodBigInt;
|
||||
z.bigint() satisfies z.ZodBigInt;
|
||||
|
||||
// $ZodBoolean
|
||||
z.boolean() satisfies z.core.$ZodBoolean;
|
||||
z.boolean() satisfies z.ZodBoolean;
|
||||
|
||||
// $ZodDate
|
||||
z.date() satisfies z.core.$ZodDate;
|
||||
z.date() satisfies z.ZodDate;
|
||||
|
||||
// $ZodSymbol
|
||||
z.symbol() satisfies z.core.$ZodSymbol;
|
||||
z.symbol() satisfies z.ZodSymbol;
|
||||
|
||||
// $ZodUndefined
|
||||
z.undefined() satisfies z.core.$ZodUndefined;
|
||||
z.undefined() satisfies z.ZodUndefined;
|
||||
|
||||
// $ZodNullable
|
||||
z.string().nullable() satisfies z.core.$ZodNullable;
|
||||
z.string().nullable() satisfies z.ZodNullable;
|
||||
|
||||
// $ZodNull
|
||||
z.null() satisfies z.core.$ZodNull;
|
||||
z.null() satisfies z.ZodNull;
|
||||
|
||||
// $ZodAny
|
||||
z.any() satisfies z.core.$ZodAny;
|
||||
z.any() satisfies z.ZodAny;
|
||||
|
||||
// $ZodUnknown
|
||||
z.unknown() satisfies z.core.$ZodUnknown;
|
||||
z.unknown() satisfies z.ZodUnknown;
|
||||
|
||||
// $ZodNever
|
||||
z.never() satisfies z.core.$ZodNever;
|
||||
z.never() satisfies z.ZodNever;
|
||||
|
||||
// $ZodVoid
|
||||
z.void() satisfies z.core.$ZodVoid;
|
||||
z.void() satisfies z.ZodVoid;
|
||||
|
||||
// $ZodArray
|
||||
z.array(z.string()) satisfies z.core.$ZodArray;
|
||||
z.array(z.string()) satisfies z.ZodArray;
|
||||
z.array(z.string()) satisfies z.ZodType<Array<unknown>>;
|
||||
|
||||
// $ZodObject
|
||||
z.object({ key: z.string() }) satisfies z.core.$ZodObject;
|
||||
z.object({ key: z.string() }) satisfies z.ZodObject<{ key: z.ZodType }>;
|
||||
z.object({ key: z.string() }) satisfies z.ZodType<{ key: string }>;
|
||||
|
||||
// $ZodUnion
|
||||
z.union([z.string(), z.number()]) satisfies z.core.$ZodUnion;
|
||||
z.union([z.string(), z.number()]) satisfies z.ZodUnion;
|
||||
z.union([z.string(), z.number()]) satisfies z.ZodType<string | number>;
|
||||
|
||||
// $ZodIntersection
|
||||
z.intersection(z.string(), z.number()) satisfies z.core.$ZodIntersection;
|
||||
z.intersection(z.string(), z.number()) satisfies z.ZodIntersection;
|
||||
|
||||
// $ZodTuple
|
||||
z.tuple([z.string(), z.number()]) satisfies z.core.$ZodTuple;
|
||||
z.tuple([z.string(), z.number()]) satisfies z.ZodTuple;
|
||||
|
||||
// $ZodRecord
|
||||
z.record(z.string(), z.number()) satisfies z.core.$ZodRecord;
|
||||
z.record(z.string(), z.number()) satisfies z.ZodRecord;
|
||||
|
||||
// $ZodMap
|
||||
z.map(z.string(), z.number()) satisfies z.core.$ZodMap;
|
||||
z.map(z.string(), z.number()) satisfies z.ZodMap;
|
||||
|
||||
// $ZodSet
|
||||
z.set(z.string()) satisfies z.core.$ZodSet;
|
||||
z.set(z.string()) satisfies z.ZodSet;
|
||||
|
||||
// $ZodLiteral
|
||||
z.literal("example") satisfies z.core.$ZodLiteral;
|
||||
z.literal("example") satisfies z.ZodLiteral;
|
||||
|
||||
// $ZodEnum
|
||||
z.enum(["a", "b", "c"]) satisfies z.core.$ZodEnum;
|
||||
z.enum(["a", "b", "c"]) satisfies z.ZodEnum;
|
||||
|
||||
// $ZodPromise
|
||||
z.promise(z.string()) satisfies z.core.$ZodPromise;
|
||||
z.promise(z.string()) satisfies z.ZodPromise;
|
||||
|
||||
// $ZodLazy
|
||||
const lazySchema = z.lazy(() => z.string());
|
||||
lazySchema satisfies z.core.$ZodLazy;
|
||||
lazySchema satisfies z.ZodLazy;
|
||||
|
||||
// $ZodOptional
|
||||
z.string().optional() satisfies z.core.$ZodOptional;
|
||||
z.string().optional() satisfies z.ZodOptional;
|
||||
|
||||
// $ZodDefault
|
||||
z.string().default("default") satisfies z.core.$ZodDefault;
|
||||
z.string().default("default") satisfies z.ZodDefault;
|
||||
|
||||
// $ZodTemplateLiteral
|
||||
z.templateLiteral([z.literal("a"), z.literal("b")]) satisfies z.core.$ZodTemplateLiteral;
|
||||
z.templateLiteral([z.literal("a"), z.literal("b")]) satisfies z.ZodTemplateLiteral;
|
||||
|
||||
// $ZodCustom
|
||||
z.custom<string>((val) => typeof val === "string") satisfies z.core.$ZodCustom;
|
||||
z.custom<string>((val) => typeof val === "string") satisfies z.ZodCustom;
|
||||
|
||||
// $ZodTransform
|
||||
z.transform((val) => val as string) satisfies z.core.$ZodTransform;
|
||||
z.transform((val) => val as string) satisfies z.ZodTransform;
|
||||
|
||||
// $ZodNonOptional
|
||||
z.string().optional().nonoptional() satisfies z.core.$ZodNonOptional;
|
||||
z.string().optional().nonoptional() satisfies z.ZodNonOptional;
|
||||
|
||||
// $ZodReadonly
|
||||
z.object({ key: z.string() }).readonly() satisfies z.core.$ZodReadonly;
|
||||
z.object({ key: z.string() }).readonly() satisfies z.ZodReadonly;
|
||||
|
||||
// $ZodNaN
|
||||
z.nan() satisfies z.core.$ZodNaN;
|
||||
z.nan() satisfies z.ZodNaN;
|
||||
|
||||
// $ZodPipe
|
||||
z.unknown().pipe(z.number()) satisfies z.core.$ZodPipe;
|
||||
z.unknown().pipe(z.number()) satisfies z.ZodPipe;
|
||||
|
||||
// $ZodSuccess
|
||||
z.success(z.string()) satisfies z.core.$ZodSuccess;
|
||||
z.success(z.string()) satisfies z.ZodSuccess;
|
||||
|
||||
// $ZodCatch
|
||||
z.string().catch("fallback") satisfies z.core.$ZodCatch;
|
||||
z.string().catch("fallback") satisfies z.ZodCatch;
|
||||
|
||||
// $ZodFile
|
||||
z.file() satisfies z.core.$ZodFile;
|
||||
z.file() satisfies z.ZodFile;
|
||||
});
|
||||
|
||||
test("checks", () => {
|
||||
const _a: z.core.$ZodCheck = {} as any as z.core.$ZodChecks;
|
||||
const _b: z.core.$ZodCheck = {} as any as z.core.$ZodStringFormatChecks;
|
||||
const _c: z.core.$ZodType = {} as any as z.core.$ZodTypes;
|
||||
const _d: z.core.$ZodType = {} as any as z.core.$ZodStringFormatTypes;
|
||||
});
|
||||
|
||||
test("assignability to $ZodType", () => {
|
||||
z.string() satisfies z.ZodType;
|
||||
z.number() satisfies z.ZodType;
|
||||
z.boolean() satisfies z.ZodType;
|
||||
z.object({ key: z.string() }) satisfies z.ZodType;
|
||||
z.object({ key: z.string() }) satisfies z.ZodType<{ key: string }>;
|
||||
z.array(z.string()) satisfies z.ZodType;
|
||||
z.union([z.string(), z.number()]) satisfies z.ZodType;
|
||||
z.intersection(z.string(), z.number()) satisfies z.ZodType;
|
||||
z.tuple([z.string(), z.number()]) satisfies z.ZodType;
|
||||
z.record(z.string(), z.number()) satisfies z.ZodType;
|
||||
z.map(z.string(), z.number()) satisfies z.ZodType;
|
||||
z.set(z.string()) satisfies z.ZodType;
|
||||
z.literal("example") satisfies z.ZodType;
|
||||
|
||||
expectTypeOf<z.ZodType extends z.core.$ZodType ? true : false>().toEqualTypeOf<true>();
|
||||
});
|
||||
|
||||
test("assignability with narrowing", () => {
|
||||
type _RefinedSchema<T extends z.ZodType<object> | z.ZodUnion> = T extends z.ZodUnion
|
||||
? RefinedUnionSchema<T> // <-- Type instantiation is excessively deep and possibly infinite.
|
||||
: T extends z.ZodType<object>
|
||||
? RefinedTypeSchema<z.output<T>> // <-- Type instantiation is excessively deep and possibly infinite.
|
||||
: never;
|
||||
|
||||
type RefinedTypeSchema<T extends object> = T;
|
||||
|
||||
type RefinedUnionSchema<T extends z.ZodUnion> = T;
|
||||
});
|
||||
|
||||
test("generic assignability in objects", () => {
|
||||
interface SortItem<T extends string> {
|
||||
key: T;
|
||||
order: string;
|
||||
}
|
||||
|
||||
const createSortItemSchema = <T extends z.ZodType<string>>(sortKeySchema: T) =>
|
||||
z.object({
|
||||
key: sortKeySchema,
|
||||
order: z.string(),
|
||||
});
|
||||
|
||||
<T extends z.ZodType<string>>(sortKeySchema: T, defaultSortBy: SortItem<z.output<T>>[] = []) =>
|
||||
createSortItemSchema(sortKeySchema).array().default(defaultSortBy);
|
||||
});
|
||||
381
node_modules/zod/src/v4/classic/tests/async-parsing.test.ts
generated
vendored
Normal file
381
node_modules/zod/src/v4/classic/tests/async-parsing.test.ts
generated
vendored
Normal file
@@ -0,0 +1,381 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
/// string
|
||||
const stringSchema = z.string();
|
||||
|
||||
test("string async parse", async () => {
|
||||
const goodData = "XXX";
|
||||
const badData = 12;
|
||||
|
||||
const goodResult = await stringSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await stringSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// number
|
||||
const numberSchema = z.number();
|
||||
test("number async parse", async () => {
|
||||
const goodData = 1234.2353;
|
||||
const badData = "1234";
|
||||
|
||||
const goodResult = await numberSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await numberSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// bigInt
|
||||
const bigIntSchema = z.bigint();
|
||||
test("bigInt async parse", async () => {
|
||||
const goodData = BigInt(145);
|
||||
const badData = 134;
|
||||
|
||||
const goodResult = await bigIntSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await bigIntSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// boolean
|
||||
const booleanSchema = z.boolean();
|
||||
test("boolean async parse", async () => {
|
||||
const goodData = true;
|
||||
const badData = 1;
|
||||
|
||||
const goodResult = await booleanSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await booleanSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// date
|
||||
const dateSchema = z.date();
|
||||
test("date async parse", async () => {
|
||||
const goodData = new Date();
|
||||
const badData = new Date().toISOString();
|
||||
|
||||
const goodResult = await dateSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await dateSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// undefined
|
||||
const undefinedSchema = z.undefined();
|
||||
test("undefined async parse", async () => {
|
||||
const goodData = undefined;
|
||||
const badData = "XXX";
|
||||
|
||||
const goodResult = await undefinedSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(undefined);
|
||||
|
||||
const badResult = await undefinedSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// null
|
||||
const nullSchema = z.null();
|
||||
test("null async parse", async () => {
|
||||
const goodData = null;
|
||||
const badData = undefined;
|
||||
|
||||
const goodResult = await nullSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await nullSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// any
|
||||
const anySchema = z.any();
|
||||
test("any async parse", async () => {
|
||||
const goodData = [{}];
|
||||
// const badData = 'XXX';
|
||||
|
||||
const goodResult = await anySchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
// const badResult = await anySchema.safeParseAsync(badData);
|
||||
// expect(badResult.success).toBe(false);
|
||||
// if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// unknown
|
||||
const unknownSchema = z.unknown();
|
||||
test("unknown async parse", async () => {
|
||||
const goodData = ["asdf", 124, () => {}];
|
||||
// const badData = 'XXX';
|
||||
|
||||
const goodResult = await unknownSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
// const badResult = await unknownSchema.safeParseAsync(badData);
|
||||
// expect(badResult.success).toBe(false);
|
||||
// if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// void
|
||||
const voidSchema = z.void();
|
||||
test("void async parse", async () => {
|
||||
const goodData = undefined;
|
||||
const badData = 0;
|
||||
|
||||
const goodResult = await voidSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await voidSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// array
|
||||
const arraySchema = z.array(z.string());
|
||||
test("array async parse", async () => {
|
||||
const goodData = ["XXX"];
|
||||
const badData = "XXX";
|
||||
|
||||
const goodResult = await arraySchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await arraySchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// object
|
||||
const objectSchema = z.object({ string: z.string() });
|
||||
test("object async parse", async () => {
|
||||
const goodData = { string: "XXX" };
|
||||
const badData = { string: 12 };
|
||||
|
||||
const goodResult = await objectSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await objectSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// union
|
||||
const unionSchema = z.union([z.string(), z.undefined()]);
|
||||
test("union async parse", async () => {
|
||||
const goodData = undefined;
|
||||
const badData = null;
|
||||
|
||||
const goodResult = await unionSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await unionSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// record
|
||||
const recordSchema = z.record(z.string(), z.object({}));
|
||||
test("record async parse", async () => {
|
||||
const goodData = { adsf: {}, asdf: {} };
|
||||
const badData = [{}];
|
||||
|
||||
const goodResult = await recordSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await recordSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// function
|
||||
// const functionSchema = z.function();
|
||||
// test("function async parse", async () => {
|
||||
// const goodData = () => {};
|
||||
// const badData = "XXX";
|
||||
|
||||
// const goodResult = await functionSchema.safeParseAsync(goodData);
|
||||
// expect(goodResult.success).toBe(true);
|
||||
// if (goodResult.success) expect(typeof goodResult.data).toEqual("function");
|
||||
|
||||
// const badResult = await functionSchema.safeParseAsync(badData);
|
||||
// expect(badResult.success).toBe(false);
|
||||
// if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
// });
|
||||
|
||||
/// literal
|
||||
const literalSchema = z.literal("asdf");
|
||||
test("literal async parse", async () => {
|
||||
const goodData = "asdf";
|
||||
const badData = "asdff";
|
||||
|
||||
const goodResult = await literalSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await literalSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// enum
|
||||
const enumSchema = z.enum(["fish", "whale"]);
|
||||
test("enum async parse", async () => {
|
||||
const goodData = "whale";
|
||||
const badData = "leopard";
|
||||
|
||||
const goodResult = await enumSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await enumSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// nativeEnum
|
||||
enum nativeEnumTest {
|
||||
asdf = "qwer",
|
||||
}
|
||||
// @ts-ignore
|
||||
const nativeEnumSchema = z.nativeEnum(nativeEnumTest);
|
||||
test("nativeEnum async parse", async () => {
|
||||
const goodData = nativeEnumTest.asdf;
|
||||
const badData = "asdf";
|
||||
|
||||
const goodResult = await nativeEnumSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await nativeEnumSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// promise
|
||||
const promiseSchema = z.promise(z.number());
|
||||
test("promise async parse good", async () => {
|
||||
const goodData = Promise.resolve(123);
|
||||
|
||||
const goodResult = await promiseSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
expect(typeof goodResult.data).toEqual("number");
|
||||
expect(goodResult.data).toEqual(123);
|
||||
});
|
||||
|
||||
test("promise async parse bad", async () => {
|
||||
const badData = Promise.resolve("XXX");
|
||||
const badResult = await promiseSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
test("async validation non-empty strings", async () => {
|
||||
const base = z.object({
|
||||
hello: z.string().refine((x) => x && x.length > 0),
|
||||
foo: z.string().refine((x) => x && x.length > 0),
|
||||
});
|
||||
|
||||
const testval = { hello: "", foo: "" };
|
||||
const result1 = base.safeParse(testval);
|
||||
const result2 = base.safeParseAsync(testval);
|
||||
|
||||
const r1 = result1;
|
||||
await result2.then((r2) => {
|
||||
expect(r1.error!.issues.length).toBe(r2.error!.issues.length);
|
||||
});
|
||||
});
|
||||
|
||||
test("async validation multiple errors 1", async () => {
|
||||
const base = z.object({
|
||||
hello: z.string(),
|
||||
foo: z.number(),
|
||||
});
|
||||
|
||||
const testval = { hello: 3, foo: "hello" };
|
||||
const result1 = base.safeParse(testval);
|
||||
const result2 = base.safeParseAsync(testval);
|
||||
|
||||
await result2.then((result2) => {
|
||||
expect(result2.error!.issues.length).toBe(result1.error!.issues.length);
|
||||
});
|
||||
});
|
||||
|
||||
test("async validation multiple errors 2", async () => {
|
||||
const base = (is_async?: boolean) =>
|
||||
z.object({
|
||||
hello: z.string(),
|
||||
foo: z.object({
|
||||
bar: z.number().refine(
|
||||
is_async
|
||||
? async () =>
|
||||
new Promise((resolve) => {
|
||||
setTimeout(() => resolve(false), 500);
|
||||
})
|
||||
: () => false
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
const testval = { hello: 3, foo: { bar: 4 } };
|
||||
const result1 = base().safeParse(testval);
|
||||
const result2 = base(true).safeParseAsync(testval);
|
||||
|
||||
await result2.then((result2) => {
|
||||
expect(result1.error!.issues.length).toBe(result2.error!.issues.length);
|
||||
});
|
||||
});
|
||||
|
||||
test("ensure early async failure prevents follow-up refinement checks", async () => {
|
||||
let count = 0;
|
||||
const base = z.object({
|
||||
hello: z.string(),
|
||||
foo: z
|
||||
.number()
|
||||
.refine(async () => {
|
||||
count++;
|
||||
return true;
|
||||
})
|
||||
.refine(async () => {
|
||||
count++;
|
||||
return true;
|
||||
}, "Good"),
|
||||
});
|
||||
|
||||
const testval = { hello: "bye", foo: 3 };
|
||||
const result = await base.safeParseAsync(testval);
|
||||
if (result.success === false) {
|
||||
expect(result.error.issues.length).toBe(1);
|
||||
expect(count).toBe(1);
|
||||
}
|
||||
|
||||
// await result.then((r) => {
|
||||
// if (r.success === false) expect(r.error.issues.length).toBe(1);
|
||||
// expect(count).toBe(2);
|
||||
// });
|
||||
});
|
||||
68
node_modules/zod/src/v4/classic/tests/async-refinements.test.ts
generated
vendored
Normal file
68
node_modules/zod/src/v4/classic/tests/async-refinements.test.ts
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("async refine .parse()", async () => {
|
||||
// throws ZodAsyncError
|
||||
const s1 = z.string().refine(async (_val) => true);
|
||||
expect(() => s1.safeParse("asdf")).toThrow();
|
||||
});
|
||||
|
||||
test("async refine", async () => {
|
||||
const s1 = z.string().refine(async (_val) => true);
|
||||
const r1 = await s1.parseAsync("asdf");
|
||||
expect(r1).toEqual("asdf");
|
||||
|
||||
const s2 = z.string().refine(async (_val) => false);
|
||||
const r2 = await s2.safeParseAsync("asdf");
|
||||
expect(r2.success).toBe(false);
|
||||
expect(r2).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("async refine with Promises", async () => {
|
||||
// expect.assertions(2);
|
||||
|
||||
const schema1 = z.string().refine((_val) => Promise.resolve(true));
|
||||
const v1 = await schema1.parseAsync("asdf");
|
||||
expect(v1).toEqual("asdf");
|
||||
|
||||
const schema2 = z.string().refine((_val) => Promise.resolve(false));
|
||||
await expect(schema2.parseAsync("asdf")).rejects.toBeDefined();
|
||||
|
||||
const schema3 = z.string().refine((_val) => Promise.resolve(true));
|
||||
await expect(schema3.parseAsync("asdf")).resolves.toEqual("asdf");
|
||||
return await expect(schema3.parseAsync("qwer")).resolves.toEqual("qwer");
|
||||
});
|
||||
|
||||
test("async refine that uses value", async () => {
|
||||
const schema1 = z.string().refine(async (val) => {
|
||||
return val.length > 5;
|
||||
});
|
||||
|
||||
const r1 = await schema1.safeParseAsync("asdf");
|
||||
expect(r1.success).toBe(false);
|
||||
expect(r1.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const r2 = await schema1.safeParseAsync("asdf123");
|
||||
expect(r2.success).toBe(true);
|
||||
expect(r2.data).toEqual("asdf123");
|
||||
});
|
||||
7
node_modules/zod/src/v4/classic/tests/base.test.ts
generated
vendored
Normal file
7
node_modules/zod/src/v4/classic/tests/base.test.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("test this binding", () => {
|
||||
const parse = z.string().parse;
|
||||
expect(parse("asdf")).toBe("asdf");
|
||||
});
|
||||
54
node_modules/zod/src/v4/classic/tests/bigint.test.ts
generated
vendored
Normal file
54
node_modules/zod/src/v4/classic/tests/bigint.test.ts
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const gtFive = z.bigint().gt(BigInt(5));
|
||||
const gteFive = z.bigint().gte(BigInt(5));
|
||||
const ltFive = z.bigint().lt(BigInt(5));
|
||||
const lteFive = z.bigint().lte(BigInt(5));
|
||||
const positive = z.bigint().positive();
|
||||
const negative = z.bigint().negative();
|
||||
const nonnegative = z.bigint().nonnegative();
|
||||
const nonpositive = z.bigint().nonpositive();
|
||||
const multipleOfFive = z.bigint().multipleOf(BigInt(5));
|
||||
|
||||
test("passing validations", () => {
|
||||
z.bigint().parse(BigInt(1));
|
||||
z.bigint().parse(BigInt(0));
|
||||
z.bigint().parse(BigInt(-1));
|
||||
gtFive.parse(BigInt(6));
|
||||
gteFive.parse(BigInt(5));
|
||||
gteFive.parse(BigInt(6));
|
||||
ltFive.parse(BigInt(4));
|
||||
lteFive.parse(BigInt(5));
|
||||
lteFive.parse(BigInt(4));
|
||||
positive.parse(BigInt(3));
|
||||
negative.parse(BigInt(-2));
|
||||
nonnegative.parse(BigInt(0));
|
||||
nonnegative.parse(BigInt(7));
|
||||
nonpositive.parse(BigInt(0));
|
||||
nonpositive.parse(BigInt(-12));
|
||||
multipleOfFive.parse(BigInt(15));
|
||||
});
|
||||
|
||||
test("failing validations", () => {
|
||||
expect(() => gtFive.parse(BigInt(5))).toThrow();
|
||||
expect(() => gteFive.parse(BigInt(4))).toThrow();
|
||||
expect(() => ltFive.parse(BigInt(5))).toThrow();
|
||||
expect(() => lteFive.parse(BigInt(6))).toThrow();
|
||||
expect(() => positive.parse(BigInt(0))).toThrow();
|
||||
expect(() => positive.parse(BigInt(-2))).toThrow();
|
||||
expect(() => negative.parse(BigInt(0))).toThrow();
|
||||
expect(() => negative.parse(BigInt(3))).toThrow();
|
||||
expect(() => nonnegative.parse(BigInt(-1))).toThrow();
|
||||
expect(() => nonpositive.parse(BigInt(1))).toThrow();
|
||||
expect(() => multipleOfFive.parse(BigInt(13))).toThrow();
|
||||
});
|
||||
|
||||
test("min max getters", () => {
|
||||
expect(z.bigint().min(BigInt(5)).minValue).toEqual(BigInt(5));
|
||||
expect(z.bigint().min(BigInt(5)).min(BigInt(10)).minValue).toEqual(BigInt(10));
|
||||
|
||||
expect(z.bigint().max(BigInt(5)).maxValue).toEqual(BigInt(5));
|
||||
expect(z.bigint().max(BigInt(5)).max(BigInt(1)).maxValue).toEqual(BigInt(1));
|
||||
});
|
||||
63
node_modules/zod/src/v4/classic/tests/brand.test.ts
generated
vendored
Normal file
63
node_modules/zod/src/v4/classic/tests/brand.test.ts
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
import { expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("branded types", () => {
|
||||
const mySchema = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
})
|
||||
.brand<"superschema">();
|
||||
|
||||
// simple branding
|
||||
type MySchema = z.infer<typeof mySchema>;
|
||||
|
||||
expectTypeOf<MySchema>().toEqualTypeOf<{ name: string } & z.$brand<"superschema">>();
|
||||
|
||||
const doStuff = (arg: MySchema) => arg;
|
||||
doStuff(mySchema.parse({ name: "hello there" }));
|
||||
|
||||
// inheritance
|
||||
const extendedSchema = mySchema.brand<"subschema">();
|
||||
type ExtendedSchema = z.infer<typeof extendedSchema>;
|
||||
expectTypeOf<ExtendedSchema>().toEqualTypeOf<{ name: string } & z.BRAND<"superschema"> & z.BRAND<"subschema">>();
|
||||
|
||||
doStuff(extendedSchema.parse({ name: "hello again" }));
|
||||
|
||||
// number branding
|
||||
const numberSchema = z.number().brand<42>();
|
||||
type NumberSchema = z.infer<typeof numberSchema>;
|
||||
expectTypeOf<NumberSchema>().toEqualTypeOf<number & { [z.$brand]: { 42: true } }>();
|
||||
|
||||
// symbol branding
|
||||
const MyBrand: unique symbol = Symbol("hello");
|
||||
type MyBrand = typeof MyBrand;
|
||||
const symbolBrand = z.number().brand<"sup">().brand<typeof MyBrand>();
|
||||
type SymbolBrand = z.infer<typeof symbolBrand>;
|
||||
// number & { [z.BRAND]: { sup: true, [MyBrand]: true } }
|
||||
expectTypeOf<SymbolBrand>().toEqualTypeOf<number & z.BRAND<"sup"> & z.BRAND<MyBrand>>();
|
||||
|
||||
// keeping brands out of input types
|
||||
const age = z.number().brand<"age">();
|
||||
|
||||
type Age = z.infer<typeof age>;
|
||||
type AgeInput = z.input<typeof age>;
|
||||
|
||||
expectTypeOf<AgeInput>().not.toEqualTypeOf<Age>();
|
||||
expectTypeOf<number>().toEqualTypeOf<AgeInput>();
|
||||
expectTypeOf<number & z.BRAND<"age">>().toEqualTypeOf<Age>();
|
||||
|
||||
// @ts-expect-error
|
||||
doStuff({ name: "hello there!" });
|
||||
});
|
||||
|
||||
test("$branded", () => {
|
||||
const a = z.string().brand<"a">();
|
||||
|
||||
expectTypeOf<typeof a>().toEqualTypeOf<z.core.$ZodBranded<z.ZodString, "a">>();
|
||||
});
|
||||
|
||||
test("branded record", () => {
|
||||
const recordWithBrandedNumberKeys = z.record(z.string().brand("SomeBrand"), z.number());
|
||||
type recordWithBrandedNumberKeys = z.infer<typeof recordWithBrandedNumberKeys>;
|
||||
expectTypeOf<recordWithBrandedNumberKeys>().toEqualTypeOf<Record<string & z.core.$brand<"SomeBrand">, number>>();
|
||||
});
|
||||
252
node_modules/zod/src/v4/classic/tests/catch.test.ts
generated
vendored
Normal file
252
node_modules/zod/src/v4/classic/tests/catch.test.ts
generated
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/v4";
|
||||
import type { util } from "zod/v4/core";
|
||||
|
||||
test("basic catch", () => {
|
||||
expect(z.string().catch("default").parse(undefined)).toBe("default");
|
||||
});
|
||||
|
||||
test("catch fn does not run when parsing succeeds", () => {
|
||||
let isCalled = false;
|
||||
const cb = () => {
|
||||
isCalled = true;
|
||||
return "asdf";
|
||||
};
|
||||
expect(z.string().catch(cb).parse("test")).toBe("test");
|
||||
expect(isCalled).toEqual(false);
|
||||
});
|
||||
|
||||
test("basic catch async", async () => {
|
||||
const result = await z.string().catch("default").parseAsync(1243);
|
||||
expect(result).toBe("default");
|
||||
});
|
||||
|
||||
test("catch replace wrong types", () => {
|
||||
expect(z.string().catch("default").parse(true)).toBe("default");
|
||||
expect(z.string().catch("default").parse(true)).toBe("default");
|
||||
expect(z.string().catch("default").parse(15)).toBe("default");
|
||||
expect(z.string().catch("default").parse([])).toBe("default");
|
||||
expect(z.string().catch("default").parse(new Map())).toBe("default");
|
||||
expect(z.string().catch("default").parse(new Set())).toBe("default");
|
||||
expect(z.string().catch("default").parse({})).toBe("default");
|
||||
});
|
||||
|
||||
test("catch with transform", () => {
|
||||
const stringWithDefault = z
|
||||
.string()
|
||||
.transform((val) => val.toUpperCase())
|
||||
.catch("default");
|
||||
|
||||
expect(stringWithDefault.parse(undefined)).toBe("default");
|
||||
expect(stringWithDefault.parse(15)).toBe("default");
|
||||
expect(stringWithDefault).toBeInstanceOf(z.ZodCatch);
|
||||
expect(stringWithDefault.unwrap()).toBeInstanceOf(z.ZodPipe);
|
||||
expect(stringWithDefault.unwrap().in).toBeInstanceOf(z.ZodString);
|
||||
expect(stringWithDefault.unwrap().out).toBeInstanceOf(z.ZodTransform);
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | util.Whatever>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("catch on existing optional", () => {
|
||||
const stringWithDefault = z.string().optional().catch("asdf");
|
||||
expect(stringWithDefault.parse(undefined)).toBe(undefined);
|
||||
expect(stringWithDefault.parse(15)).toBe("asdf");
|
||||
expect(stringWithDefault).toBeInstanceOf(z.ZodCatch);
|
||||
expect(stringWithDefault.unwrap()).toBeInstanceOf(z.ZodOptional);
|
||||
expect(stringWithDefault.unwrap().unwrap()).toBeInstanceOf(z.ZodString);
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined | util.Whatever>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string | undefined>();
|
||||
});
|
||||
|
||||
test("optional on catch", () => {
|
||||
const stringWithDefault = z.string().catch("asdf").optional();
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | util.Whatever>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string | undefined>();
|
||||
});
|
||||
|
||||
test("complex chain example", () => {
|
||||
const complex = z
|
||||
.string()
|
||||
.catch("asdf")
|
||||
.transform((val) => `${val}!`)
|
||||
.transform((val) => val.toUpperCase())
|
||||
.catch("qwer")
|
||||
.unwrap()
|
||||
.optional()
|
||||
.catch("asdfasdf");
|
||||
|
||||
expect(complex.parse("qwer")).toBe("QWER!");
|
||||
expect(complex.parse(15)).toBe("ASDF!");
|
||||
expect(complex.parse(true)).toBe("ASDF!");
|
||||
});
|
||||
|
||||
test("removeCatch", () => {
|
||||
const stringWithRemovedDefault = z.string().catch("asdf").unwrap();
|
||||
|
||||
type out = z.output<typeof stringWithRemovedDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("nested", () => {
|
||||
const inner = z.string().catch("asdf");
|
||||
const outer = z.object({ inner }).catch({
|
||||
inner: "asdf",
|
||||
});
|
||||
type input = z.input<typeof outer>;
|
||||
expectTypeOf<input>().toEqualTypeOf<{ inner: string | util.Whatever } | util.Whatever>();
|
||||
type out = z.output<typeof outer>;
|
||||
|
||||
expectTypeOf<out>().toEqualTypeOf<{ inner: string }>();
|
||||
expect(outer.parse(undefined)).toEqual({ inner: "asdf" });
|
||||
expect(outer.parse({})).toEqual({ inner: "asdf" });
|
||||
expect(outer.parse({ inner: undefined })).toEqual({ inner: "asdf" });
|
||||
});
|
||||
|
||||
test("chained catch", () => {
|
||||
const stringWithDefault = z.string().catch("inner").catch("outer");
|
||||
const result = stringWithDefault.parse(undefined);
|
||||
expect(result).toEqual("inner");
|
||||
const resultDiff = stringWithDefault.parse(5);
|
||||
expect(resultDiff).toEqual("inner");
|
||||
});
|
||||
|
||||
test("native enum", () => {
|
||||
enum Fruits {
|
||||
apple = "apple",
|
||||
orange = "orange",
|
||||
}
|
||||
|
||||
const schema = z.object({
|
||||
fruit: z.nativeEnum(Fruits).catch(Fruits.apple),
|
||||
});
|
||||
|
||||
expect(schema.parse({})).toEqual({ fruit: Fruits.apple });
|
||||
expect(schema.parse({ fruit: 15 })).toEqual({ fruit: Fruits.apple });
|
||||
});
|
||||
|
||||
test("enum", () => {
|
||||
const schema = z.object({
|
||||
fruit: z.enum(["apple", "orange"]).catch("apple"),
|
||||
});
|
||||
|
||||
expect(schema.parse({})).toEqual({ fruit: "apple" });
|
||||
expect(schema.parse({ fruit: true })).toEqual({ fruit: "apple" });
|
||||
expect(schema.parse({ fruit: 15 })).toEqual({ fruit: "apple" });
|
||||
});
|
||||
|
||||
test("reported issues with nested usage", () => {
|
||||
const schema = z.object({
|
||||
string: z.string(),
|
||||
obj: z.object({
|
||||
sub: z.object({
|
||||
lit: z.literal("a"),
|
||||
subCatch: z.number().catch(23),
|
||||
}),
|
||||
midCatch: z.number().catch(42),
|
||||
}),
|
||||
number: z.number().catch(0),
|
||||
bool: z.boolean(),
|
||||
});
|
||||
|
||||
try {
|
||||
schema.parse({
|
||||
string: {},
|
||||
obj: {
|
||||
sub: {
|
||||
lit: "b",
|
||||
subCatch: "24",
|
||||
},
|
||||
midCatch: 444,
|
||||
},
|
||||
number: "",
|
||||
bool: "yes",
|
||||
});
|
||||
} catch (error) {
|
||||
const issues = (error as z.ZodError).issues;
|
||||
|
||||
expect(issues.length).toEqual(3);
|
||||
expect(issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received object",
|
||||
"path": [
|
||||
"string",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"message": "Invalid input: expected "a"",
|
||||
"path": [
|
||||
"obj",
|
||||
"sub",
|
||||
"lit",
|
||||
],
|
||||
"values": [
|
||||
"a",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "boolean",
|
||||
"message": "Invalid input: expected boolean, received string",
|
||||
"path": [
|
||||
"bool",
|
||||
],
|
||||
},
|
||||
]
|
||||
`);
|
||||
// expect(issues[0].message).toMatch("string");
|
||||
// expect(issues[1].message).toMatch("literal");
|
||||
// expect(issues[2].message).toMatch("boolean");
|
||||
}
|
||||
});
|
||||
|
||||
test("catch error", () => {
|
||||
const schema = z.object({
|
||||
age: z.number(),
|
||||
name: z.string().catch((ctx) => {
|
||||
ctx.issues;
|
||||
// issues = ctx.issues;
|
||||
|
||||
return "John Doe";
|
||||
}),
|
||||
});
|
||||
|
||||
const result = schema.safeParse({
|
||||
age: null,
|
||||
name: null,
|
||||
});
|
||||
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"age"
|
||||
],
|
||||
"message": "Invalid input: expected number, received null"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("ctx.input", () => {
|
||||
const schema = z.string().catch((ctx) => {
|
||||
return String(ctx.input);
|
||||
});
|
||||
|
||||
expect(schema.parse(123)).toEqual("123");
|
||||
});
|
||||
20
node_modules/zod/src/v4/classic/tests/coalesce.test.ts
generated
vendored
Normal file
20
node_modules/zod/src/v4/classic/tests/coalesce.test.ts
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
test("coalesce", () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
// test("nonoptional with default", () => {
|
||||
// const schema = z.string().optional().coalesce("hi");
|
||||
// expectTypeOf<typeof schema._input>().toEqualTypeOf<string | undefined>();
|
||||
// expectTypeOf<typeof schema._output>().toEqualTypeOf<string>();
|
||||
// expect(schema.parse(undefined)).toBe("hi");
|
||||
// });
|
||||
|
||||
// test("nonoptional in object", () => {
|
||||
// const schema = z.object({ hi: z.string().optional().nonoptional("hi") });
|
||||
|
||||
// expectTypeOf<typeof schema._input>().toEqualTypeOf<{ hi: string | undefined }>();
|
||||
// expectTypeOf<typeof schema._output>().toEqualTypeOf<{ hi: string }>();
|
||||
// expect(schema.parse(undefined)).toBe("hi");
|
||||
// });
|
||||
160
node_modules/zod/src/v4/classic/tests/coerce.test.ts
generated
vendored
Normal file
160
node_modules/zod/src/v4/classic/tests/coerce.test.ts
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("string coercion", () => {
|
||||
const schema = z.coerce.string();
|
||||
expect(schema.parse("sup")).toEqual("sup");
|
||||
expect(schema.parse("")).toEqual("");
|
||||
expect(schema.parse(12)).toEqual("12");
|
||||
expect(schema.parse(0)).toEqual("0");
|
||||
expect(schema.parse(-12)).toEqual("-12");
|
||||
expect(schema.parse(3.14)).toEqual("3.14");
|
||||
expect(schema.parse(BigInt(15))).toEqual("15");
|
||||
expect(schema.parse(Number.NaN)).toEqual("NaN");
|
||||
expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual("Infinity");
|
||||
expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual("-Infinity");
|
||||
expect(schema.parse(true)).toEqual("true");
|
||||
expect(schema.parse(false)).toEqual("false");
|
||||
expect(schema.parse(null)).toEqual("null");
|
||||
expect(schema.parse(undefined)).toEqual("undefined");
|
||||
expect(schema.parse({ hello: "world!" })).toEqual("[object Object]");
|
||||
expect(schema.parse(["item", "another_item"])).toEqual("item,another_item");
|
||||
expect(schema.parse([])).toEqual("");
|
||||
expect(schema.parse(new Date("2022-01-01T00:00:00.000Z"))).toEqual(new Date("2022-01-01T00:00:00.000Z").toString());
|
||||
});
|
||||
|
||||
test("number coercion", () => {
|
||||
const schema = z.coerce.number();
|
||||
expect(schema.parse("12")).toEqual(12);
|
||||
expect(schema.parse("0")).toEqual(0);
|
||||
expect(schema.parse("-12")).toEqual(-12);
|
||||
expect(schema.parse("3.14")).toEqual(3.14);
|
||||
expect(schema.parse("")).toEqual(0);
|
||||
expect(() => schema.parse("NOT_A_NUMBER")).toThrow(); // z.ZodError
|
||||
expect(schema.parse(12)).toEqual(12);
|
||||
expect(schema.parse(0)).toEqual(0);
|
||||
expect(schema.parse(-12)).toEqual(-12);
|
||||
expect(schema.parse(3.14)).toEqual(3.14);
|
||||
expect(schema.parse(BigInt(15))).toEqual(15);
|
||||
expect(() => schema.parse(Number.NaN)).toThrow(); // z.ZodError
|
||||
// expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual(Number.POSITIVE_INFINITY);
|
||||
// expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual(Number.NEGATIVE_INFINITY);
|
||||
expect(schema.parse(true)).toEqual(1);
|
||||
expect(schema.parse(false)).toEqual(0);
|
||||
expect(schema.parse(null)).toEqual(0);
|
||||
expect(() => schema.parse(undefined)).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse({ hello: "world!" })).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse(["item", "another_item"])).toThrow(); // z.ZodError
|
||||
expect(schema.parse([])).toEqual(0);
|
||||
expect(schema.parse(new Date(1670139203496))).toEqual(1670139203496);
|
||||
});
|
||||
|
||||
test("boolean coercion", () => {
|
||||
const schema = z.coerce.boolean();
|
||||
expect(schema.parse("true")).toEqual(true);
|
||||
expect(schema.parse("false")).toEqual(true);
|
||||
expect(schema.parse("0")).toEqual(true);
|
||||
expect(schema.parse("1")).toEqual(true);
|
||||
expect(schema.parse("")).toEqual(false);
|
||||
expect(schema.parse(1)).toEqual(true);
|
||||
expect(schema.parse(0)).toEqual(false);
|
||||
expect(schema.parse(-1)).toEqual(true);
|
||||
expect(schema.parse(3.14)).toEqual(true);
|
||||
expect(schema.parse(BigInt(15))).toEqual(true);
|
||||
expect(schema.parse(Number.NaN)).toEqual(false);
|
||||
expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual(true);
|
||||
expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual(true);
|
||||
expect(schema.parse(true)).toEqual(true);
|
||||
expect(schema.parse(false)).toEqual(false);
|
||||
expect(schema.parse(null)).toEqual(false);
|
||||
expect(schema.parse(undefined)).toEqual(false);
|
||||
expect(schema.parse({ hello: "world!" })).toEqual(true);
|
||||
expect(schema.parse(["item", "another_item"])).toEqual(true);
|
||||
expect(schema.parse([])).toEqual(true);
|
||||
expect(schema.parse(new Date(1670139203496))).toEqual(true);
|
||||
});
|
||||
|
||||
test("bigint coercion", () => {
|
||||
const schema = z.coerce.bigint();
|
||||
expect(schema.parse("5")).toEqual(BigInt(5));
|
||||
expect(schema.parse("0")).toEqual(BigInt(0));
|
||||
expect(schema.parse("-5")).toEqual(BigInt(-5));
|
||||
expect(() => schema.parse("3.14")).toThrow(); // not a z.ZodError!
|
||||
expect(schema.parse("")).toEqual(BigInt(0));
|
||||
expect(() => schema.parse("NOT_A_NUMBER")).toThrow(); // not a z.ZodError!
|
||||
expect(schema.parse(5)).toEqual(BigInt(5));
|
||||
expect(schema.parse(0)).toEqual(BigInt(0));
|
||||
expect(schema.parse(-5)).toEqual(BigInt(-5));
|
||||
expect(() => schema.parse(3.14)).toThrow(); // not a z.ZodError!
|
||||
expect(schema.parse(BigInt(5))).toEqual(BigInt(5));
|
||||
expect(() => schema.parse(Number.NaN)).toThrow(); // not a z.ZodError!
|
||||
expect(() => schema.parse(Number.POSITIVE_INFINITY)).toThrow(); // not a z.ZodError!
|
||||
expect(() => schema.parse(Number.NEGATIVE_INFINITY)).toThrow(); // not a z.ZodError!
|
||||
expect(schema.parse(true)).toEqual(BigInt(1));
|
||||
expect(schema.parse(false)).toEqual(BigInt(0));
|
||||
expect(() => schema.parse(null)).toThrow(); // not a z.ZodError!
|
||||
expect(() => schema.parse(undefined)).toThrow(); // not a z.ZodError!
|
||||
expect(() => schema.parse({ hello: "world!" })).toThrow(); // not a z.ZodError!
|
||||
expect(() => schema.parse(["item", "another_item"])).toThrow(); // not a z.ZodError!
|
||||
expect(schema.parse([])).toEqual(BigInt(0));
|
||||
expect(schema.parse(new Date(1670139203496))).toEqual(BigInt(1670139203496));
|
||||
});
|
||||
|
||||
test("date coercion", () => {
|
||||
const schema = z.coerce.date();
|
||||
expect(schema.parse(new Date().toDateString())).toBeInstanceOf(Date);
|
||||
expect(schema.parse(new Date().toISOString())).toBeInstanceOf(Date);
|
||||
expect(schema.parse(new Date().toUTCString())).toBeInstanceOf(Date);
|
||||
expect(schema.parse("5")).toBeInstanceOf(Date);
|
||||
expect(schema.parse("2000-01-01")).toBeInstanceOf(Date);
|
||||
// expect(schema.parse("0")).toBeInstanceOf(Date);
|
||||
// expect(schema.parse("-5")).toBeInstanceOf(Date);
|
||||
// expect(schema.parse("3.14")).toBeInstanceOf(Date);
|
||||
expect(() => schema.parse("")).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse("NOT_A_DATE")).toThrow(); // z.ZodError
|
||||
expect(schema.parse(5)).toBeInstanceOf(Date);
|
||||
expect(schema.parse(0)).toBeInstanceOf(Date);
|
||||
expect(schema.parse(-5)).toBeInstanceOf(Date);
|
||||
expect(schema.parse(3.14)).toBeInstanceOf(Date);
|
||||
expect(() => schema.parse(BigInt(5))).toThrow(); // not a z.ZodError!
|
||||
expect(() => schema.parse(Number.NaN)).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse(Number.POSITIVE_INFINITY)).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse(Number.NEGATIVE_INFINITY)).toThrow(); // z.ZodError
|
||||
expect(schema.parse(true)).toBeInstanceOf(Date);
|
||||
expect(schema.parse(false)).toBeInstanceOf(Date);
|
||||
expect(schema.parse(null)).toBeInstanceOf(Date);
|
||||
expect(() => schema.parse(undefined)).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse({ hello: "world!" })).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse(["item", "another_item"])).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse([])).toThrow(); // z.ZodError
|
||||
expect(schema.parse(new Date())).toBeInstanceOf(Date);
|
||||
});
|
||||
|
||||
// test("template literal coercion", () => {
|
||||
// const schema = z.coerce
|
||||
// .templateLiteral()
|
||||
// .interpolated(z.number().finite())
|
||||
// .interpolated(
|
||||
// z.enum(["px", "em", "rem", "vh", "vw", "vmin", "vmax"]).optional()
|
||||
// );
|
||||
// expect(schema.parse(300)).toEqual("300");
|
||||
// expect(schema.parse(BigInt(300))).toEqual("300");
|
||||
// expect(schema.parse("300")).toEqual("300");
|
||||
// expect(schema.parse("300px")).toEqual("300px");
|
||||
// expect(schema.parse("300em")).toEqual("300em");
|
||||
// expect(schema.parse("300rem")).toEqual("300rem");
|
||||
// expect(schema.parse("300vh")).toEqual("300vh");
|
||||
// expect(schema.parse("300vw")).toEqual("300vw");
|
||||
// expect(schema.parse("300vmin")).toEqual("300vmin");
|
||||
// expect(schema.parse("300vmax")).toEqual("300vmax");
|
||||
// expect(schema.parse(["300px"])).toEqual("300px");
|
||||
// });
|
||||
|
||||
test("override input type", () => {
|
||||
const a = z.coerce.string<any>();
|
||||
type input = z.input<typeof a>;
|
||||
expectTypeOf<input>().toEqualTypeOf<any>();
|
||||
type output = z.infer<typeof a>;
|
||||
expectTypeOf<output>().toEqualTypeOf<string>();
|
||||
});
|
||||
352
node_modules/zod/src/v4/classic/tests/continuability.test.ts
generated
vendored
Normal file
352
node_modules/zod/src/v4/classic/tests/continuability.test.ts
generated
vendored
Normal file
@@ -0,0 +1,352 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("continuability", () => {
|
||||
/**
|
||||
* | $ZodGUID
|
||||
| $ZodUUID
|
||||
| $ZodEmail
|
||||
| $ZodURL
|
||||
| $ZodEmoji
|
||||
| $ZodNanoID
|
||||
| $ZodCUID
|
||||
| $ZodCUID2
|
||||
| $ZodULID
|
||||
| $ZodXID
|
||||
| $ZodKSUID
|
||||
| $ZodISODateTime
|
||||
| $ZodISODate
|
||||
| $ZodISOTime
|
||||
| $ZodISODuration
|
||||
| $ZodIPv4
|
||||
| $ZodIPv6
|
||||
| $ZodCIDRv4
|
||||
| $ZodCIDRv6
|
||||
| $ZodBase64
|
||||
| $ZodBase64URL
|
||||
| $ZodE164
|
||||
| $ZodJWT;
|
||||
*/
|
||||
expect(
|
||||
z
|
||||
.email()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "email",
|
||||
"message": "Invalid email address",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.uuid()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "uuid",
|
||||
"message": "Invalid UUID",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.url()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "url",
|
||||
"message": "Invalid URL",
|
||||
"path": [],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.jwt()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "jwt",
|
||||
"message": "Invalid JWT",
|
||||
"path": [],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.cidrv4()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "cidrv4",
|
||||
"message": "Invalid IPv4 range",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\/([0-9]|[1-2][0-9]|3[0-2])$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.cidrv6()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "cidrv6",
|
||||
"message": "Invalid IPv6 range",
|
||||
"path": [],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.ipv4()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "ipv4",
|
||||
"message": "Invalid IPv4 address",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.ipv6()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "ipv6",
|
||||
"message": "Invalid IPv6 address",
|
||||
"path": [],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.emoji()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "emoji",
|
||||
"message": "Invalid emoji",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$/u",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.nanoid()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "nanoid",
|
||||
"message": "Invalid nanoid",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^[a-zA-Z0-9_-]{21}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.cuid()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "cuid",
|
||||
"message": "Invalid cuid",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^[cC][^\\s-]{8,}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.cuid2()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "cuid2",
|
||||
"message": "Invalid cuid2",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^[0-9a-z]+$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.ulid()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "ulid",
|
||||
"message": "Invalid ULID",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.xid()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "xid",
|
||||
"message": "Invalid XID",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^[0-9a-vA-V]{20}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.ksuid()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "ksuid",
|
||||
"message": "Invalid KSUID",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^[A-Za-z0-9]{27}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
40
node_modules/zod/src/v4/classic/tests/custom.test.ts
generated
vendored
Normal file
40
node_modules/zod/src/v4/classic/tests/custom.test.ts
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("passing validations", () => {
|
||||
const example1 = z.custom<number>((x) => typeof x === "number");
|
||||
example1.parse(1234);
|
||||
expect(() => example1.parse({})).toThrow();
|
||||
});
|
||||
|
||||
test("string params", () => {
|
||||
const example1 = z.custom<number>((x) => typeof x !== "number", "customerr");
|
||||
const result = example1.safeParse(1234);
|
||||
expect(result.success).toEqual(false);
|
||||
expect(JSON.stringify(result.error).includes("customerr")).toEqual(true);
|
||||
});
|
||||
|
||||
test("instanceof", () => {
|
||||
const fn = (value: string) => Uint8Array.from(Buffer.from(value, "base64"));
|
||||
|
||||
// Argument of type 'ZodCustom<Uint8Array<ArrayBuffer>, unknown>' is not assignable to parameter of type '$ZodType<any, Uint8Array<ArrayBuffer>>'.
|
||||
z.string().transform(fn).pipe(z.instanceof(Uint8Array));
|
||||
});
|
||||
|
||||
test("non-continuable by default", () => {
|
||||
const A = z
|
||||
.custom<string>((val) => typeof val === "string")
|
||||
.transform((_) => {
|
||||
throw new Error("Invalid input");
|
||||
});
|
||||
expect(A.safeParse(123).error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
31
node_modules/zod/src/v4/classic/tests/date.test.ts
generated
vendored
Normal file
31
node_modules/zod/src/v4/classic/tests/date.test.ts
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const beforeBenchmarkDate = new Date(2022, 10, 4);
|
||||
const benchmarkDate = new Date(2022, 10, 5);
|
||||
const afterBenchmarkDate = new Date(2022, 10, 6);
|
||||
|
||||
const minCheck = z.date().min(benchmarkDate);
|
||||
const maxCheck = z.date().max(benchmarkDate);
|
||||
|
||||
test("passing validations", () => {
|
||||
minCheck.parse(benchmarkDate);
|
||||
minCheck.parse(afterBenchmarkDate);
|
||||
|
||||
maxCheck.parse(benchmarkDate);
|
||||
maxCheck.parse(beforeBenchmarkDate);
|
||||
});
|
||||
|
||||
test("failing validations", () => {
|
||||
expect(() => minCheck.parse(beforeBenchmarkDate)).toThrow();
|
||||
expect(() => maxCheck.parse(afterBenchmarkDate)).toThrow();
|
||||
});
|
||||
|
||||
test("min max getters", () => {
|
||||
expect(minCheck.minDate).toEqual(benchmarkDate);
|
||||
expect(minCheck.min(afterBenchmarkDate).minDate).toEqual(afterBenchmarkDate);
|
||||
|
||||
expect(maxCheck.maxDate).toEqual(benchmarkDate);
|
||||
expect(maxCheck.max(beforeBenchmarkDate).maxDate).toEqual(beforeBenchmarkDate);
|
||||
});
|
||||
296
node_modules/zod/src/v4/classic/tests/datetime.test.ts
generated
vendored
Normal file
296
node_modules/zod/src/v4/classic/tests/datetime.test.ts
generated
vendored
Normal file
@@ -0,0 +1,296 @@
|
||||
import { checkSync } from "recheck";
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("basic datetime parsing", () => {
|
||||
const datetime = z.string().datetime();
|
||||
datetime.parse("1970-01-01T00:00:00.000Z");
|
||||
datetime.parse("2022-10-13T09:52:31.816Z");
|
||||
datetime.parse("2022-10-13T09:52:31.8162314Z");
|
||||
datetime.parse("1970-01-01T00:00:00Z");
|
||||
datetime.parse("2022-10-13T09:52:31Z");
|
||||
expect(() => datetime.parse("")).toThrow();
|
||||
expect(() => datetime.parse("foo")).toThrow();
|
||||
expect(() => datetime.parse("2020-10-14")).toThrow();
|
||||
expect(() => datetime.parse("T18:45:12.123")).toThrow();
|
||||
expect(() => datetime.parse("2020-10-14T17:42:29+00:00")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime parsing with precision -1", () => {
|
||||
const datetimeNoMs = z.string().datetime({ precision: -1, offset: true, local: true });
|
||||
datetimeNoMs.parse("1970-01-01T00:00Z");
|
||||
datetimeNoMs.parse("2022-10-13T09:52Z");
|
||||
datetimeNoMs.parse("2022-10-13T09:52+02:00");
|
||||
|
||||
datetimeNoMs.parse("2022-10-13T09:52");
|
||||
expect(() => datetimeNoMs.parse("tuna")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("2022-10-13T09:52+02")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.000Z")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.Z")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("2022-10-13T09:52:31.816Z")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime parsing with precision 0", () => {
|
||||
const datetimeNoMs = z.string().datetime({ precision: 0 });
|
||||
datetimeNoMs.parse("1970-01-01T00:00:00Z");
|
||||
datetimeNoMs.parse("2022-10-13T09:52:31Z");
|
||||
expect(() => datetimeNoMs.parse("tuna")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.000Z")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.Z")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("2022-10-13T09:52:31.816Z")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime parsing with precision 3", () => {
|
||||
const datetime3Ms = z.string().datetime({ precision: 3 });
|
||||
datetime3Ms.parse("1970-01-01T00:00:00.000Z");
|
||||
datetime3Ms.parse("2022-10-13T09:52:31.123Z");
|
||||
expect(() => datetime3Ms.parse("tuna")).toThrow();
|
||||
expect(() => datetime3Ms.parse("1970-01-01T00:00:00.1Z")).toThrow();
|
||||
expect(() => datetime3Ms.parse("1970-01-01T00:00:00.12Z")).toThrow();
|
||||
expect(() => datetime3Ms.parse("2022-10-13T09:52:31Z")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime parsing with offset", () => {
|
||||
const datetimeOffset = z.string().datetime({ offset: true });
|
||||
datetimeOffset.parse("1970-01-01T00:00:00.000Z");
|
||||
datetimeOffset.parse("2022-10-13T09:52:31.816234134Z");
|
||||
datetimeOffset.parse("1970-01-01T00:00:00Z");
|
||||
datetimeOffset.parse("2022-10-13T09:52:31.4Z");
|
||||
datetimeOffset.parse("2020-10-14T17:42:29+00:00");
|
||||
datetimeOffset.parse("2020-10-14T17:42:29+03:15");
|
||||
expect(() => datetimeOffset.parse("2020-10-14T17:42:29+0315")).toThrow();
|
||||
expect(() => datetimeOffset.parse("2020-10-14T17:42:29+03")).toThrow();
|
||||
expect(() => datetimeOffset.parse("tuna")).toThrow();
|
||||
expect(() => datetimeOffset.parse("2022-10-13T09:52:31.Z")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime parsing with offset and precision 0", () => {
|
||||
const datetimeOffsetNoMs = z.string().datetime({ offset: true, precision: 0 });
|
||||
datetimeOffsetNoMs.parse("1970-01-01T00:00:00Z");
|
||||
datetimeOffsetNoMs.parse("2022-10-13T09:52:31Z");
|
||||
datetimeOffsetNoMs.parse("2020-10-14T17:42:29+00:00");
|
||||
expect(() => datetimeOffsetNoMs.parse("2020-10-14T17:42:29+0000")).toThrow();
|
||||
expect(() => datetimeOffsetNoMs.parse("2020-10-14T17:42:29+00")).toThrow();
|
||||
expect(() => datetimeOffsetNoMs.parse("tuna")).toThrow();
|
||||
expect(() => datetimeOffsetNoMs.parse("1970-01-01T00:00:00.000Z")).toThrow();
|
||||
expect(() => datetimeOffsetNoMs.parse("1970-01-01T00:00:00.Z")).toThrow();
|
||||
expect(() => datetimeOffsetNoMs.parse("2022-10-13T09:52:31.816Z")).toThrow();
|
||||
expect(() => datetimeOffsetNoMs.parse("2020-10-14T17:42:29.124+00:00")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime parsing with offset and precision 4", () => {
|
||||
const datetimeOffset4Ms = z.string().datetime({ offset: true, precision: 4 });
|
||||
datetimeOffset4Ms.parse("1970-01-01T00:00:00.1234Z");
|
||||
datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+00:00");
|
||||
expect(() => datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+0000")).toThrow();
|
||||
expect(() => datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+00")).toThrow();
|
||||
expect(() => datetimeOffset4Ms.parse("tuna")).toThrow();
|
||||
expect(() => datetimeOffset4Ms.parse("1970-01-01T00:00:00.123Z")).toThrow();
|
||||
expect(() => datetimeOffset4Ms.parse("2020-10-14T17:42:29.124+00:00")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime offset normalization", () => {
|
||||
const a = z.iso.datetime({ offset: true });
|
||||
|
||||
expect(a.safeParse("2020-10-14T17:42:29+02")).toMatchObject({ success: false });
|
||||
expect(a.safeParse("2020-10-14T17:42:29+0200")).toMatchObject({ success: false });
|
||||
a.safeParse("2020-10-14T17:42:29+02:00");
|
||||
});
|
||||
|
||||
test("datetime parsing with local option", () => {
|
||||
const a = z.string().datetime({ local: true });
|
||||
|
||||
expect(a.safeParse("1970-01-01T00:00")).toMatchObject({ success: true });
|
||||
expect(a.safeParse("1970-01-01T00:00:00")).toMatchObject({ success: true });
|
||||
expect(a.safeParse("2022-10-13T09:52:31.816")).toMatchObject({ success: true });
|
||||
expect(a.safeParse("1970-01-01T00:00:00.000")).toMatchObject({ success: true });
|
||||
expect(a.safeParse("1970-01-01T00")).toMatchObject({ success: false });
|
||||
|
||||
// Should reject timezone indicators and invalid formats
|
||||
|
||||
expect(() => a.parse("2022-10-13T09:52:31+00:00")).toThrow();
|
||||
expect(() => a.parse("2022-10-13 09:52:31")).toThrow();
|
||||
expect(() => a.parse("2022-10-13T24:52:31")).toThrow();
|
||||
expect(() => a.parse("2022-10-13T24:52")).toThrow();
|
||||
expect(() => a.parse("2022-10-13T24:52Z")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime parsing with local and offset", () => {
|
||||
const a = z.string().datetime({ local: true, offset: true });
|
||||
|
||||
// expect(a.parse("2022-10-13T12:52")).toEqual("2022-10-13T12:52:00");
|
||||
a.parse("2022-10-13T12:52:00");
|
||||
a.parse("2022-10-13T12:52:00Z");
|
||||
a.parse("2022-10-13T12:52Z");
|
||||
a.parse("2022-10-13T12:52");
|
||||
a.parse("2022-10-13T12:52+02:00");
|
||||
expect(() => a.parse("2022-10-13T12:52:00+02")).toThrow();
|
||||
// expect(() => a.parse("2022-10-13T12:52Z")).toThrow();
|
||||
// expect(() => a.parse("2022-10-13T12:52+02:00")).toThrow();
|
||||
});
|
||||
|
||||
test("date parsing", () => {
|
||||
const date = z.string().date();
|
||||
date.parse("1970-01-01");
|
||||
date.parse("2022-01-31");
|
||||
date.parse("2022-03-31");
|
||||
date.parse("2022-04-30");
|
||||
date.parse("2022-05-31");
|
||||
date.parse("2022-06-30");
|
||||
date.parse("2022-07-31");
|
||||
date.parse("2022-08-31");
|
||||
date.parse("2022-09-30");
|
||||
date.parse("2022-10-31");
|
||||
date.parse("2022-11-30");
|
||||
date.parse("2022-12-31");
|
||||
|
||||
date.parse("2000-02-29");
|
||||
date.parse("2400-02-29");
|
||||
expect(() => date.parse("2022-02-29")).toThrow();
|
||||
expect(() => date.parse("2100-02-29")).toThrow();
|
||||
expect(() => date.parse("2200-02-29")).toThrow();
|
||||
expect(() => date.parse("2300-02-29")).toThrow();
|
||||
expect(() => date.parse("2500-02-29")).toThrow();
|
||||
|
||||
expect(() => date.parse("")).toThrow();
|
||||
expect(() => date.parse("foo")).toThrow();
|
||||
expect(() => date.parse("200-01-01")).toThrow();
|
||||
expect(() => date.parse("20000-01-01")).toThrow();
|
||||
expect(() => date.parse("2000-0-01")).toThrow();
|
||||
expect(() => date.parse("2000-011-01")).toThrow();
|
||||
expect(() => date.parse("2000-01-0")).toThrow();
|
||||
expect(() => date.parse("2000-01-011")).toThrow();
|
||||
expect(() => date.parse("2000/01/01")).toThrow();
|
||||
expect(() => date.parse("01-01-2022")).toThrow();
|
||||
expect(() => date.parse("01/01/2022")).toThrow();
|
||||
expect(() => date.parse("2000-01-01 00:00:00Z")).toThrow();
|
||||
expect(() => date.parse("2020-10-14T17:42:29+00:00")).toThrow();
|
||||
expect(() => date.parse("2020-10-14T17:42:29Z")).toThrow();
|
||||
expect(() => date.parse("2020-10-14T17:42:29")).toThrow();
|
||||
expect(() => date.parse("2020-10-14T17:42:29.123Z")).toThrow();
|
||||
|
||||
expect(() => date.parse("2000-00-12")).toThrow();
|
||||
expect(() => date.parse("2000-12-00")).toThrow();
|
||||
expect(() => date.parse("2000-01-32")).toThrow();
|
||||
expect(() => date.parse("2000-13-01")).toThrow();
|
||||
expect(() => date.parse("2000-21-01")).toThrow();
|
||||
|
||||
expect(() => date.parse("2000-02-30")).toThrow();
|
||||
expect(() => date.parse("2000-02-31")).toThrow();
|
||||
expect(() => date.parse("2000-04-31")).toThrow();
|
||||
expect(() => date.parse("2000-06-31")).toThrow();
|
||||
expect(() => date.parse("2000-09-31")).toThrow();
|
||||
expect(() => date.parse("2000-11-31")).toThrow();
|
||||
});
|
||||
|
||||
test("time parsing", () => {
|
||||
const time = z.string().time();
|
||||
time.parse("00:00:00");
|
||||
time.parse("23:00:00");
|
||||
time.parse("00:59:00");
|
||||
time.parse("00:00:59");
|
||||
time.parse("23:59:59");
|
||||
time.parse("09:52:31");
|
||||
time.parse("23:59:59.9999999");
|
||||
time.parse("00:00");
|
||||
expect(() => time.parse("")).toThrow();
|
||||
expect(() => time.parse("foo")).toThrow();
|
||||
expect(() => time.parse("00:00:00Z")).toThrow();
|
||||
expect(() => time.parse("0:00:00")).toThrow();
|
||||
expect(() => time.parse("00:0:00")).toThrow();
|
||||
expect(() => time.parse("00:00:0")).toThrow();
|
||||
expect(() => time.parse("00:00:00.000+00:00")).toThrow();
|
||||
expect(() => time.parse("24:00:00")).toThrow();
|
||||
expect(() => time.parse("00:60:00")).toThrow();
|
||||
expect(() => time.parse("00:00:60")).toThrow();
|
||||
expect(() => time.parse("24:60:60")).toThrow();
|
||||
|
||||
const time2 = z.string().time({ precision: 2 });
|
||||
time2.parse("00:00:00.00");
|
||||
time2.parse("09:52:31.12");
|
||||
time2.parse("23:59:59.99");
|
||||
expect(() => time2.parse("")).toThrow();
|
||||
expect(() => time2.parse("foo")).toThrow();
|
||||
expect(() => time2.parse("00:00:00")).toThrow();
|
||||
expect(() => time2.parse("00:00:00.00Z")).toThrow();
|
||||
expect(() => time2.parse("00:00:00.0")).toThrow();
|
||||
expect(() => time2.parse("00:00:00.000")).toThrow();
|
||||
expect(() => time2.parse("00:00:00.00+00:00")).toThrow();
|
||||
|
||||
const time3 = z.string().time({ precision: z.TimePrecision.Minute });
|
||||
time3.parse("00:00");
|
||||
expect(() => time3.parse("00:00:00")).toThrow();
|
||||
});
|
||||
|
||||
test("duration", () => {
|
||||
const duration = z.string().duration();
|
||||
|
||||
const validDurations = [
|
||||
"P3Y6M4DT12H30M5S",
|
||||
"P2Y9M3DT12H31M8.001S",
|
||||
// "+P3Y6M4DT12H30M5S",
|
||||
// "-PT0.001S",
|
||||
// "+PT0.001S",
|
||||
"PT0,001S",
|
||||
"PT12H30M5S",
|
||||
// "-P2M1D",
|
||||
// "P-2M-1D",
|
||||
// "-P5DT10H",
|
||||
// "P-5DT-10H",
|
||||
"P1Y",
|
||||
"P2MT30M",
|
||||
"PT6H",
|
||||
"P5W",
|
||||
// "P0.5Y",
|
||||
// "P0,5Y",
|
||||
// "P42YT7.004M",
|
||||
];
|
||||
|
||||
const invalidDurations = [
|
||||
"foo bar",
|
||||
"",
|
||||
" ",
|
||||
"P",
|
||||
"PT",
|
||||
"P1Y2MT",
|
||||
"T1H",
|
||||
"P0.5Y1D",
|
||||
"P0,5Y6M",
|
||||
"P1YT",
|
||||
"P-2M-1D",
|
||||
"P-5DT-10H",
|
||||
"P1W2D",
|
||||
"-P1D",
|
||||
];
|
||||
|
||||
for (const val of validDurations) {
|
||||
const result = duration.safeParse(val);
|
||||
if (!result.success) {
|
||||
throw Error(`Valid duration could not be parsed: ${val}`);
|
||||
}
|
||||
}
|
||||
|
||||
for (const val of invalidDurations) {
|
||||
const result = duration.safeParse(val);
|
||||
|
||||
if (result.success) {
|
||||
throw Error(`Invalid duration was successful parsed: ${val}`);
|
||||
}
|
||||
|
||||
expect(result.error.issues[0].message).toEqual("Invalid ISO duration");
|
||||
}
|
||||
});
|
||||
|
||||
test("redos checker", () => {
|
||||
const a = z.iso.datetime();
|
||||
const b = z.string().datetime({ offset: true });
|
||||
const c = z.string().datetime({ local: true });
|
||||
const d = z.string().datetime({ local: true, offset: true, precision: 3 });
|
||||
const e = z.string().date();
|
||||
const f = z.string().time();
|
||||
const g = z.string().duration();
|
||||
for (const schema of [a, b, c, d, e, f, g]) {
|
||||
const result = checkSync(schema._zod.pattern.source, "");
|
||||
if (result.status !== "safe") throw Error("ReDoS issue");
|
||||
}
|
||||
});
|
||||
313
node_modules/zod/src/v4/classic/tests/default.test.ts
generated
vendored
Normal file
313
node_modules/zod/src/v4/classic/tests/default.test.ts
generated
vendored
Normal file
@@ -0,0 +1,313 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
test("basic defaults", () => {
|
||||
expect(z.string().default("default").parse(undefined)).toBe("default");
|
||||
});
|
||||
|
||||
test("default with optional", () => {
|
||||
const schema = z.string().optional().default("default");
|
||||
expect(schema.parse(undefined)).toBe("default");
|
||||
expect(schema.unwrap().parse(undefined)).toBe(undefined);
|
||||
});
|
||||
|
||||
test("default with transform", () => {
|
||||
const stringWithDefault = z
|
||||
.string()
|
||||
.transform((val) => val.toUpperCase())
|
||||
.default("default");
|
||||
expect(stringWithDefault.parse(undefined)).toBe("default");
|
||||
expect(stringWithDefault).toBeInstanceOf(z.ZodDefault);
|
||||
expect(stringWithDefault.unwrap()).toBeInstanceOf(z.ZodPipe);
|
||||
expect(stringWithDefault.unwrap().in).toBeInstanceOf(z.ZodString);
|
||||
expect(stringWithDefault.unwrap().out).toBeInstanceOf(z.ZodTransform);
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("default on existing optional", () => {
|
||||
const stringWithDefault = z.string().optional().default("asdf");
|
||||
expect(stringWithDefault.parse(undefined)).toBe("asdf");
|
||||
expect(stringWithDefault).toBeInstanceOf(z.ZodDefault);
|
||||
expect(stringWithDefault.unwrap()).toBeInstanceOf(z.ZodOptional);
|
||||
expect(stringWithDefault.unwrap().unwrap()).toBeInstanceOf(z.ZodString);
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("optional on default", () => {
|
||||
const stringWithDefault = z.string().default("asdf").optional();
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string | undefined>();
|
||||
|
||||
expect(stringWithDefault.parse(undefined)).toBe("asdf");
|
||||
});
|
||||
|
||||
// test("complex chain example", () => {
|
||||
// const complex = z
|
||||
// .string()
|
||||
// .default("asdf")
|
||||
// .transform((val) => val.toUpperCase())
|
||||
// .default("qwer")
|
||||
// .unwrap()
|
||||
// .optional()
|
||||
// .default("asdfasdf");
|
||||
|
||||
// expect(complex.parse(undefined)).toBe("asdfasdf");
|
||||
// });
|
||||
|
||||
test("removeDefault", () => {
|
||||
const stringWithRemovedDefault = z.string().default("asdf").removeDefault();
|
||||
|
||||
type out = z.output<typeof stringWithRemovedDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("apply default at output", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.transform((_) => (Math.random() > 0 ? undefined : _))
|
||||
.default("asdf");
|
||||
expect(schema.parse("")).toEqual("asdf");
|
||||
});
|
||||
|
||||
test("nested", () => {
|
||||
const inner = z.string().default("asdf");
|
||||
const outer = z.object({ inner }).default({
|
||||
inner: "qwer",
|
||||
});
|
||||
type input = z.input<typeof outer>;
|
||||
expectTypeOf<input>().toEqualTypeOf<{ inner?: string | undefined } | undefined>();
|
||||
type out = z.output<typeof outer>;
|
||||
expectTypeOf<out>().toEqualTypeOf<{ inner: string }>();
|
||||
expect(outer.parse(undefined)).toEqual({ inner: "qwer" });
|
||||
expect(outer.parse({})).toEqual({ inner: "asdf" });
|
||||
expect(outer.parse({ inner: undefined })).toEqual({ inner: "asdf" });
|
||||
});
|
||||
|
||||
test("chained defaults", () => {
|
||||
const stringWithDefault = z.string().default("inner").default("outer");
|
||||
const result = stringWithDefault.parse(undefined);
|
||||
expect(result).toEqual("outer");
|
||||
});
|
||||
|
||||
test("object optionality", () => {
|
||||
const schema = z.object({
|
||||
hi: z.string().default("hi"),
|
||||
});
|
||||
type schemaInput = z.input<typeof schema>;
|
||||
type schemaOutput = z.output<typeof schema>;
|
||||
expectTypeOf<schemaInput>().toEqualTypeOf<{ hi?: string | undefined }>();
|
||||
expectTypeOf<schemaOutput>().toEqualTypeOf<{ hi: string }>();
|
||||
expect(schema.parse({})).toEqual({
|
||||
hi: "hi",
|
||||
});
|
||||
});
|
||||
|
||||
test("nested prefault/default", () => {
|
||||
const a = z
|
||||
.string()
|
||||
.default("a")
|
||||
.refine((val) => val.startsWith("a"));
|
||||
const b = z
|
||||
.string()
|
||||
.refine((val) => val.startsWith("b"))
|
||||
.default("b");
|
||||
const c = z
|
||||
.string()
|
||||
.prefault("c")
|
||||
.refine((val) => val.startsWith("c"));
|
||||
const d = z
|
||||
.string()
|
||||
.refine((val) => val.startsWith("d"))
|
||||
.prefault("d");
|
||||
|
||||
const obj = z.object({
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
});
|
||||
|
||||
expect(obj.safeParse({ a: "a1", b: "b1", c: "c1", d: "d1" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": {
|
||||
"a": "a1",
|
||||
"b": "b1",
|
||||
"c": "c1",
|
||||
"d": "d1",
|
||||
},
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(obj.safeParse({ a: "f", b: "f", c: "f", d: "f" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"a"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"b"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"c"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"d"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(obj.safeParse({})).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": {
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
"c": "c",
|
||||
"d": "d",
|
||||
},
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(obj.safeParse({ a: undefined, b: undefined, c: undefined, d: undefined })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": {
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
"c": "c",
|
||||
"d": "d",
|
||||
},
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
|
||||
const obj2 = z.object({
|
||||
a: a.optional(),
|
||||
b: b.optional(),
|
||||
c: c.optional(),
|
||||
d: d.optional(),
|
||||
});
|
||||
expect(obj2.safeParse({ a: undefined, b: undefined, c: undefined, d: undefined })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": {
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
"c": "c",
|
||||
"d": "d",
|
||||
},
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(a.parse(undefined)).toBe("a");
|
||||
expect(b.parse(undefined)).toBe("b");
|
||||
expect(c.parse(undefined)).toBe("c");
|
||||
expect(d.parse(undefined)).toBe("d");
|
||||
});
|
||||
|
||||
test("failing default", () => {
|
||||
const a = z
|
||||
.string()
|
||||
.default("z")
|
||||
.refine((val) => val.startsWith("a"));
|
||||
const b = z
|
||||
.string()
|
||||
.refine((val) => val.startsWith("b"))
|
||||
.default("z");
|
||||
const c = z
|
||||
.string()
|
||||
.prefault("z")
|
||||
.refine((val) => val.startsWith("c"));
|
||||
const d = z
|
||||
.string()
|
||||
.refine((val) => val.startsWith("d"))
|
||||
.prefault("z");
|
||||
|
||||
const obj = z.object({
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
});
|
||||
|
||||
expect(
|
||||
obj.safeParse({
|
||||
a: undefined,
|
||||
b: undefined,
|
||||
c: undefined,
|
||||
d: undefined,
|
||||
}).error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [
|
||||
"a",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [
|
||||
"c",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [
|
||||
"d",
|
||||
],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test("partial should not clobber defaults", () => {
|
||||
const objWithDefaults = z.object({
|
||||
a: z.string().default("defaultA"),
|
||||
b: z.string().default("defaultB"),
|
||||
c: z.string().default("defaultC"),
|
||||
});
|
||||
|
||||
const objPartialWithOneRequired = objWithDefaults.partial(); //.required({ a: true });
|
||||
|
||||
const test = objPartialWithOneRequired.parse({});
|
||||
expect(test).toMatchInlineSnapshot(`
|
||||
{
|
||||
"a": "defaultA",
|
||||
"b": "defaultB",
|
||||
"c": "defaultC",
|
||||
}
|
||||
`);
|
||||
});
|
||||
32
node_modules/zod/src/v4/classic/tests/description.test.ts
generated
vendored
Normal file
32
node_modules/zod/src/v4/classic/tests/description.test.ts
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const description = "a description";
|
||||
|
||||
// test("passing `description` to schema should add a description", () => {
|
||||
// expect(z.string({ description }).description).toEqual(description);
|
||||
// expect(z.number({ description }).description).toEqual(description);
|
||||
// expect(z.boolean({ description }).description).toEqual(description);
|
||||
// });
|
||||
|
||||
test(".describe", () => {
|
||||
expect(z.string().describe(description).description).toEqual(description);
|
||||
expect(z.number().describe(description).description).toEqual(description);
|
||||
expect(z.boolean().describe(description).description).toEqual(description);
|
||||
});
|
||||
|
||||
test("adding description with z.globalRegistry", () => {
|
||||
const schema = z.string();
|
||||
z.core.globalRegistry.add(schema, { description });
|
||||
z.core.globalRegistry.get(schema);
|
||||
expect(schema.description).toEqual(description);
|
||||
});
|
||||
|
||||
// in Zod 4 descriptions are not inherited
|
||||
// test("description should carry over to chained schemas", () => {
|
||||
// const schema = z.string().describe(description);
|
||||
// expect(schema.description).toEqual(description);
|
||||
// expect(schema.optional().description).toEqual(description);
|
||||
// expect(schema.optional().nullable().default("default").description).toEqual(description);
|
||||
// });
|
||||
619
node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts
generated
vendored
Normal file
619
node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts
generated
vendored
Normal file
@@ -0,0 +1,619 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("_values", () => {
|
||||
expect(z.string()._zod.values).toEqual(undefined);
|
||||
expect(z.enum(["a", "b"])._zod.values).toEqual(new Set(["a", "b"]));
|
||||
expect(z.nativeEnum({ a: "A", b: "B" })._zod.values).toEqual(new Set(["A", "B"]));
|
||||
expect(z.literal("test")._zod.values).toEqual(new Set(["test"]));
|
||||
expect(z.literal(123)._zod.values).toEqual(new Set([123]));
|
||||
expect(z.literal(true)._zod.values).toEqual(new Set([true]));
|
||||
expect(z.literal(BigInt(123))._zod.values).toEqual(new Set([BigInt(123)]));
|
||||
expect(z.undefined()._zod.values).toEqual(new Set([undefined]));
|
||||
expect(z.null()._zod.values).toEqual(new Set([null]));
|
||||
|
||||
const t = z.literal("test");
|
||||
expect(t.optional()._zod.values).toEqual(new Set(["test", undefined]));
|
||||
expect(t.nullable()._zod.values).toEqual(new Set(["test", null]));
|
||||
expect(t.default("test")._zod.values).toEqual(new Set(["test"]));
|
||||
expect(t.catch("test")._zod.values).toEqual(new Set(["test"]));
|
||||
|
||||
const pre = z.preprocess((val) => String(val), z.string()).pipe(z.literal("test"));
|
||||
expect(pre._zod.values).toEqual(undefined);
|
||||
|
||||
const post = z.literal("test").transform((_) => Math.random());
|
||||
expect(post._zod.values).toEqual(new Set(["test"]));
|
||||
|
||||
// Test that readonly literals pass through their values property
|
||||
expect(z.literal("test").readonly()._zod.values).toEqual(new Set(["test"]));
|
||||
});
|
||||
|
||||
test("valid parse - object", () => {
|
||||
expect(
|
||||
z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
])
|
||||
.parse({ type: "a", a: "abc" })
|
||||
).toEqual({ type: "a", a: "abc" });
|
||||
});
|
||||
|
||||
test("valid - include discriminator key (deprecated)", () => {
|
||||
expect(
|
||||
z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
])
|
||||
.parse({ type: "a", a: "abc" })
|
||||
).toEqual({ type: "a", a: "abc" });
|
||||
});
|
||||
|
||||
test("valid - optional discriminator (object)", () => {
|
||||
const schema = z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a").optional(), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
]);
|
||||
expect(schema.parse({ type: "a", a: "abc" })).toEqual({ type: "a", a: "abc" });
|
||||
expect(schema.parse({ a: "abc" })).toEqual({ a: "abc" });
|
||||
});
|
||||
|
||||
test("valid - discriminator value of various primitive types", () => {
|
||||
const schema = z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("1"), val: z.string() }),
|
||||
z.object({ type: z.literal(1), val: z.string() }),
|
||||
z.object({ type: z.literal(BigInt(1)), val: z.string() }),
|
||||
z.object({ type: z.literal("true"), val: z.string() }),
|
||||
z.object({ type: z.literal(true), val: z.string() }),
|
||||
z.object({ type: z.literal("null"), val: z.string() }),
|
||||
z.object({ type: z.null(), val: z.string() }),
|
||||
z.object({ type: z.literal("undefined"), val: z.string() }),
|
||||
z.object({ type: z.undefined(), val: z.string() }),
|
||||
]);
|
||||
|
||||
expect(schema.parse({ type: "1", val: "val" })).toEqual({ type: "1", val: "val" });
|
||||
expect(schema.parse({ type: 1, val: "val" })).toEqual({ type: 1, val: "val" });
|
||||
expect(schema.parse({ type: BigInt(1), val: "val" })).toEqual({
|
||||
type: BigInt(1),
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: "true", val: "val" })).toEqual({
|
||||
type: "true",
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: true, val: "val" })).toEqual({
|
||||
type: true,
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: "null", val: "val" })).toEqual({
|
||||
type: "null",
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: null, val: "val" })).toEqual({
|
||||
type: null,
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: "undefined", val: "val" })).toEqual({
|
||||
type: "undefined",
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: undefined, val: "val" })).toEqual({
|
||||
type: undefined,
|
||||
val: "val",
|
||||
});
|
||||
|
||||
const fail = schema.safeParse({
|
||||
type: "not_a_key",
|
||||
val: "val",
|
||||
});
|
||||
expect(fail.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
test("invalid - null", () => {
|
||||
try {
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
]).parse(null);
|
||||
throw new Error();
|
||||
} catch (e: any) {
|
||||
// [
|
||||
// {
|
||||
// code: z.ZodIssueCode.invalid_type,
|
||||
// expected: z.ZodParsedType.object,
|
||||
// input: null,
|
||||
// message: "Expected object, received null",
|
||||
// received: z.ZodParsedType.null,
|
||||
// path: [],
|
||||
// },
|
||||
// ];
|
||||
expect(e.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "object",
|
||||
"message": "Invalid input: expected object, received null",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("invalid discriminator value", () => {
|
||||
const result = z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
])
|
||||
.safeParse({ type: "x", a: "abc" });
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_union",
|
||||
"errors": [],
|
||||
"note": "No matching discriminator",
|
||||
"path": [
|
||||
"type"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("invalid discriminator value - unionFallback", () => {
|
||||
const result = z
|
||||
.discriminatedUnion(
|
||||
"type",
|
||||
[z.object({ type: z.literal("a"), a: z.string() }), z.object({ type: z.literal("b"), b: z.string() })],
|
||||
{ unionFallback: true }
|
||||
)
|
||||
.safeParse({ type: "x", a: "abc" });
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_union",
|
||||
"errors": [
|
||||
[
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"a"
|
||||
],
|
||||
"path": [
|
||||
"type"
|
||||
],
|
||||
"message": "Invalid input: expected \\"a\\""
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"b"
|
||||
],
|
||||
"path": [
|
||||
"type"
|
||||
],
|
||||
"message": "Invalid input: expected \\"b\\""
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"b"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("valid discriminator value, invalid data", () => {
|
||||
const result = z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
])
|
||||
.safeParse({ type: "a", b: "abc" });
|
||||
|
||||
// [
|
||||
// {
|
||||
// code: z.ZodIssueCode.invalid_type,
|
||||
// expected: z.ZodParsedType.string,
|
||||
// message: "Required",
|
||||
// path: ["a"],
|
||||
// received: z.ZodParsedType.undefined,
|
||||
// },
|
||||
// ];
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"a"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("wrong schema - missing discriminator", () => {
|
||||
try {
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ b: z.string() }) as any,
|
||||
])._zod.propValues;
|
||||
throw new Error();
|
||||
} catch (e: any) {
|
||||
expect(e.message.includes("Invalid discriminated union option")).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
// removed to account for unions of unions
|
||||
// test("wrong schema - duplicate discriminator values", () => {
|
||||
// try {
|
||||
// z.discriminatedUnion("type",[
|
||||
// z.object({ type: z.literal("a"), a: z.string() }),
|
||||
// z.object({ type: z.literal("a"), b: z.string() }),
|
||||
// ]);
|
||||
// throw new Error();
|
||||
// } catch (e: any) {
|
||||
// expect(e.message.includes("Duplicate discriminator value")).toEqual(true);
|
||||
// }
|
||||
// });
|
||||
|
||||
test("async - valid", async () => {
|
||||
const schema = await z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal("a"),
|
||||
a: z
|
||||
.string()
|
||||
.refine(async () => true)
|
||||
.transform(async (val) => Number(val)),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("b"),
|
||||
b: z.string(),
|
||||
}),
|
||||
]);
|
||||
const data = { type: "a", a: "1" };
|
||||
const result = await schema.safeParseAsync(data);
|
||||
expect(result.data).toEqual({ type: "a", a: 1 });
|
||||
});
|
||||
|
||||
test("async - invalid", async () => {
|
||||
// try {
|
||||
const a = z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal("a"),
|
||||
a: z
|
||||
.string()
|
||||
.refine(async () => true)
|
||||
.transform(async (val) => val),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("b"),
|
||||
b: z.string(),
|
||||
}),
|
||||
]);
|
||||
const result = await a.safeParseAsync({ type: "a", a: 1 });
|
||||
|
||||
// expect(JSON.parse(e.message)).toEqual([
|
||||
// {
|
||||
// code: "invalid_type",
|
||||
// expected: "string",
|
||||
// input: 1,
|
||||
// received: "number",
|
||||
// path: ["a"],
|
||||
// message: "Expected string, received number",
|
||||
// },
|
||||
// ]);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"a"
|
||||
],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("valid - literals with .default or .pipe", () => {
|
||||
const schema = z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal("foo").default("foo"),
|
||||
a: z.string(),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("custom"),
|
||||
method: z.string(),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("bar").transform((val) => val),
|
||||
c: z.string(),
|
||||
}),
|
||||
]);
|
||||
expect(schema.parse({ type: "foo", a: "foo" })).toEqual({
|
||||
type: "foo",
|
||||
a: "foo",
|
||||
});
|
||||
});
|
||||
|
||||
test("enum and nativeEnum", () => {
|
||||
enum MyEnum {
|
||||
d = 0,
|
||||
e = "e",
|
||||
}
|
||||
|
||||
const schema = z.discriminatedUnion("key", [
|
||||
z.object({
|
||||
key: z.literal("a"),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
z.object({
|
||||
key: z.enum(["b", "c"]),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
z.object({
|
||||
key: z.nativeEnum(MyEnum),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
]);
|
||||
|
||||
type schema = z.infer<typeof schema>;
|
||||
expectTypeOf<schema>().toEqualTypeOf<{ key: "a" } | { key: "b" | "c" } | { key: MyEnum.d | MyEnum.e }>();
|
||||
|
||||
schema.parse({ key: "a" });
|
||||
schema.parse({ key: "b" });
|
||||
schema.parse({ key: "c" });
|
||||
schema.parse({ key: MyEnum.d });
|
||||
schema.parse({ key: MyEnum.e });
|
||||
schema.parse({ key: "e" });
|
||||
});
|
||||
|
||||
test("branded", () => {
|
||||
const schema = z.discriminatedUnion("key", [
|
||||
z.object({
|
||||
key: z.literal("a"),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
z.object({
|
||||
key: z.literal("b").brand<"asdfasdf">(),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
]);
|
||||
|
||||
type schema = z.infer<typeof schema>;
|
||||
expectTypeOf<schema>().toEqualTypeOf<{ key: "a" } | { key: "b" & z.core.$brand<"asdfasdf"> }>();
|
||||
|
||||
schema.parse({ key: "a" });
|
||||
schema.parse({ key: "b" });
|
||||
expect(() => {
|
||||
schema.parse({ key: "c" });
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test("optional and nullable", () => {
|
||||
const schema = z.discriminatedUnion("key", [
|
||||
z.object({
|
||||
key: z.literal("a").optional(),
|
||||
a: z.literal(true),
|
||||
}),
|
||||
z.object({
|
||||
key: z.literal("b").nullable(),
|
||||
b: z.literal(true),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
]);
|
||||
|
||||
type schema = z.infer<typeof schema>;
|
||||
expectTypeOf<schema>().toEqualTypeOf<{ key?: "a" | undefined; a: true } | { key: "b" | null; b: true }>();
|
||||
|
||||
schema.parse({ key: "a", a: true });
|
||||
schema.parse({ key: undefined, a: true });
|
||||
schema.parse({ key: "b", b: true });
|
||||
schema.parse({ key: null, b: true });
|
||||
expect(() => {
|
||||
schema.parse({ key: null, a: true });
|
||||
}).toThrow();
|
||||
expect(() => {
|
||||
schema.parse({ key: "b", a: true });
|
||||
}).toThrow();
|
||||
|
||||
const value = schema.parse({ key: null, b: true });
|
||||
|
||||
if (!("key" in value)) value.a;
|
||||
if (value.key === undefined) value.a;
|
||||
if (value.key === "a") value.a;
|
||||
if (value.key === "b") value.b;
|
||||
if (value.key === null) value.b;
|
||||
});
|
||||
|
||||
test("multiple discriminators", () => {
|
||||
const FreeConfig = z.object({
|
||||
type: z.literal("free"),
|
||||
min_cents: z.null(),
|
||||
});
|
||||
|
||||
// console.log(FreeConfig.shape.type);
|
||||
const PricedConfig = z.object({
|
||||
type: z.literal("fiat-price"),
|
||||
// min_cents: z.int().nullable(),
|
||||
min_cents: z.null(),
|
||||
});
|
||||
|
||||
const Config = z.discriminatedUnion("type", [FreeConfig, PricedConfig]);
|
||||
|
||||
Config.parse({
|
||||
min_cents: null,
|
||||
type: "fiat-price",
|
||||
name: "Standard",
|
||||
});
|
||||
|
||||
expect(() => {
|
||||
Config.parse({
|
||||
min_cents: null,
|
||||
type: "not real",
|
||||
name: "Standard",
|
||||
});
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test("single element union", () => {
|
||||
const schema = z.object({
|
||||
a: z.literal("discKey"),
|
||||
b: z.enum(["apple", "banana"]),
|
||||
c: z.object({ id: z.string() }),
|
||||
});
|
||||
|
||||
const input = {
|
||||
a: "discKey",
|
||||
b: "apple",
|
||||
c: {}, // Invalid, as schema requires `id` property
|
||||
};
|
||||
|
||||
// Validation must fail here, but it doesn't
|
||||
|
||||
const u = z.discriminatedUnion("a", [schema]);
|
||||
const result = u.safeParse(input);
|
||||
expect(result).toMatchObject({ success: false });
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"c",
|
||||
"id"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(u.options.length).toEqual(1);
|
||||
});
|
||||
|
||||
test("nested discriminated unions", () => {
|
||||
const BaseError = z.object({ status: z.literal("failed"), message: z.string() });
|
||||
const MyErrors = z.discriminatedUnion("code", [
|
||||
BaseError.extend({ code: z.literal(400) }),
|
||||
BaseError.extend({ code: z.literal(401) }),
|
||||
BaseError.extend({ code: z.literal(500) }),
|
||||
]);
|
||||
|
||||
const MyResult = z.discriminatedUnion("status", [
|
||||
z.object({ status: z.literal("success"), data: z.string() }),
|
||||
MyErrors,
|
||||
]);
|
||||
|
||||
expect(MyErrors._zod.propValues).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": Set {
|
||||
400,
|
||||
401,
|
||||
500,
|
||||
},
|
||||
"status": Set {
|
||||
"failed",
|
||||
},
|
||||
}
|
||||
`);
|
||||
expect(MyResult._zod.propValues).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": Set {
|
||||
400,
|
||||
401,
|
||||
500,
|
||||
},
|
||||
"status": Set {
|
||||
"success",
|
||||
"failed",
|
||||
},
|
||||
}
|
||||
`);
|
||||
|
||||
const result = MyResult.parse({ status: "success", data: "hello" });
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": "hello",
|
||||
"status": "success",
|
||||
}
|
||||
`);
|
||||
const result2 = MyResult.parse({ status: "failed", code: 400, message: "bad request" });
|
||||
expect(result2).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": 400,
|
||||
"message": "bad request",
|
||||
"status": "failed",
|
||||
}
|
||||
`);
|
||||
const result3 = MyResult.parse({ status: "failed", code: 401, message: "unauthorized" });
|
||||
expect(result3).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": 401,
|
||||
"message": "unauthorized",
|
||||
"status": "failed",
|
||||
}
|
||||
`);
|
||||
const result4 = MyResult.parse({ status: "failed", code: 500, message: "internal server error" });
|
||||
expect(result4).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": 500,
|
||||
"message": "internal server error",
|
||||
"status": "failed",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("readonly literal discriminator", () => {
|
||||
const discUnion = z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a").readonly(), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.number() }),
|
||||
]);
|
||||
|
||||
// Test that both discriminator values are correctly included in propValues
|
||||
const propValues = discUnion._zod.propValues;
|
||||
expect(propValues?.type?.has("a")).toBe(true);
|
||||
expect(propValues?.type?.has("b")).toBe(true);
|
||||
|
||||
// Test that the discriminated union works correctly
|
||||
const result1 = discUnion.parse({ type: "a", a: "hello" });
|
||||
expect(result1).toEqual({ type: "a", a: "hello" });
|
||||
|
||||
const result2 = discUnion.parse({ type: "b", b: 42 });
|
||||
expect(result2).toEqual({ type: "b", b: 42 });
|
||||
|
||||
// Test that invalid discriminator values are rejected
|
||||
expect(() => {
|
||||
discUnion.parse({ type: "c", a: "hello" });
|
||||
}).toThrow();
|
||||
});
|
||||
285
node_modules/zod/src/v4/classic/tests/enum.test.ts
generated
vendored
Normal file
285
node_modules/zod/src/v4/classic/tests/enum.test.ts
generated
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("enum from string array", () => {
|
||||
const MyEnum = z.enum(["Red", "Green", "Blue"]);
|
||||
expect(MyEnum.enum.Red).toEqual("Red");
|
||||
|
||||
type MyEnum = z.infer<typeof MyEnum>;
|
||||
expectTypeOf<MyEnum>().toEqualTypeOf<"Red" | "Green" | "Blue">();
|
||||
});
|
||||
|
||||
test("enum from const object", () => {
|
||||
const Fruits: { Apple: "apple"; Banana: "banana" } = {
|
||||
Apple: "apple",
|
||||
Banana: "banana",
|
||||
};
|
||||
const fruitEnum = z.nativeEnum(Fruits);
|
||||
type fruitEnum = z.infer<typeof fruitEnum>;
|
||||
fruitEnum.parse("apple");
|
||||
fruitEnum.parse("banana");
|
||||
fruitEnum.parse(Fruits.Apple);
|
||||
fruitEnum.parse(Fruits.Banana);
|
||||
expectTypeOf<fruitEnum>().toEqualTypeOf<"apple" | "banana">();
|
||||
});
|
||||
|
||||
test("enum from native enum", () => {
|
||||
enum Fruits {
|
||||
Apple = "apple",
|
||||
Banana = "banana",
|
||||
Orange = 3,
|
||||
}
|
||||
// @ts-ignore
|
||||
const fruitEnum = z.nativeEnum(Fruits);
|
||||
type fruitEnum = z.infer<typeof fruitEnum>;
|
||||
fruitEnum.parse("apple");
|
||||
fruitEnum.parse("banana");
|
||||
fruitEnum.parse(Fruits.Apple);
|
||||
fruitEnum.parse(Fruits.Banana);
|
||||
|
||||
expect(fruitEnum.safeParse("Apple").success).toEqual(false);
|
||||
expect(fruitEnum.safeParse("Cantaloupe").success).toEqual(false);
|
||||
|
||||
expectTypeOf<fruitEnum>().toMatchTypeOf<Fruits>();
|
||||
expectTypeOf<Fruits>().toMatchTypeOf<fruitEnum>();
|
||||
});
|
||||
|
||||
test("enum from native enum with numeric keys", () => {
|
||||
const FruitValues = {
|
||||
Apple: 10,
|
||||
Banana: 20,
|
||||
// @ts-ignore
|
||||
} as const;
|
||||
const fruitEnum = z.nativeEnum(FruitValues);
|
||||
type fruitEnum = z.infer<typeof fruitEnum>;
|
||||
fruitEnum.parse(10);
|
||||
fruitEnum.parse(20);
|
||||
fruitEnum.parse(FruitValues.Apple);
|
||||
fruitEnum.parse(FruitValues.Banana);
|
||||
expectTypeOf<fruitEnum>().toEqualTypeOf<10 | 20>();
|
||||
});
|
||||
|
||||
test("issue metadata", () => {
|
||||
const schema = z.enum(["Red", "Green", "Blue"]);
|
||||
const result = schema.safeParse("Yellow");
|
||||
expect(result.error!.issues[0]).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"message": "Invalid option: expected one of "Red"|"Green"|"Blue"",
|
||||
"path": [],
|
||||
"values": [
|
||||
"Red",
|
||||
"Green",
|
||||
"Blue",
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("enum from non-const inputs", () => {
|
||||
const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"];
|
||||
const FoodEnum = z.enum(foods);
|
||||
|
||||
expectTypeOf<z.infer<typeof FoodEnum>>().toEqualTypeOf<string>();
|
||||
expect(FoodEnum.safeParse("Pasta").success).toEqual(true);
|
||||
expect(FoodEnum.safeParse("Cucumbers").success).toEqual(false);
|
||||
});
|
||||
|
||||
test("get options", () => {
|
||||
expect(z.enum(["tuna", "trout"]).options).toEqual(["tuna", "trout"]);
|
||||
});
|
||||
|
||||
test("readonly enum", () => {
|
||||
const HTTP_SUCCESS = ["200", "201"] as const;
|
||||
const arg = z.enum(HTTP_SUCCESS);
|
||||
type arg = z.infer<typeof arg>;
|
||||
expectTypeOf<arg>().toEqualTypeOf<"200" | "201">();
|
||||
|
||||
arg.parse("201");
|
||||
expect(() => arg.parse("202")).toThrow();
|
||||
});
|
||||
|
||||
test("error map", () => {
|
||||
const result = z
|
||||
.enum(["test"], { error: (iss) => (iss.input === undefined ? "REQUIRED" : undefined) })
|
||||
.safeParse(undefined);
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues[0].message).toEqual("REQUIRED");
|
||||
}
|
||||
});
|
||||
|
||||
test("type signatures", () => {
|
||||
const a = z.enum(["a", "b", "c"]);
|
||||
const b = z.enum(a.options);
|
||||
expectTypeOf(a).toEqualTypeOf(b);
|
||||
|
||||
const c = z.enum({ a: 1, b: 2 } as const);
|
||||
expectTypeOf(c.enum).toEqualTypeOf<{
|
||||
readonly a: 1;
|
||||
readonly b: 2;
|
||||
}>();
|
||||
|
||||
enum Fruit {
|
||||
Apple = "apple",
|
||||
Banana = "banana",
|
||||
Orange = "orange",
|
||||
}
|
||||
const d = z.enum(Fruit);
|
||||
expectTypeOf(d.enum).toEqualTypeOf(Fruit);
|
||||
|
||||
const e = z.enum({ a: 1, b: 2 });
|
||||
expectTypeOf(e.enum).toEqualTypeOf<{
|
||||
readonly a: 1;
|
||||
readonly b: 2;
|
||||
}>();
|
||||
});
|
||||
|
||||
test("extract", () => {
|
||||
const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"] as const;
|
||||
const FoodEnum = z.enum(foods);
|
||||
const ItalianEnum = FoodEnum.extract(["Pasta", "Pizza"]);
|
||||
|
||||
expect(ItalianEnum.safeParse("Pasta").success).toEqual(true);
|
||||
expect(ItalianEnum.safeParse("Tacos").success).toEqual(false);
|
||||
|
||||
expectTypeOf<z.infer<typeof ItalianEnum>>().toEqualTypeOf<"Pasta" | "Pizza">();
|
||||
});
|
||||
|
||||
test("exclude", () => {
|
||||
const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"] as const;
|
||||
const FoodEnum = z.enum(foods);
|
||||
const UnhealthyEnum = FoodEnum.exclude(["Salad"]);
|
||||
|
||||
expect(UnhealthyEnum.safeParse("Pasta").success).toEqual(true);
|
||||
expect(UnhealthyEnum.safeParse("Salad").success).toEqual(false);
|
||||
expectTypeOf<z.infer<typeof UnhealthyEnum>>().toEqualTypeOf<"Pasta" | "Pizza" | "Tacos" | "Burgers">();
|
||||
|
||||
const EmptyFoodEnum = FoodEnum.exclude(foods);
|
||||
expectTypeOf<typeof EmptyFoodEnum>().toEqualTypeOf<z.ZodEnum<{}>>();
|
||||
expectTypeOf<z.infer<typeof EmptyFoodEnum>>().toEqualTypeOf<never>();
|
||||
});
|
||||
|
||||
test("error map inheritance", () => {
|
||||
const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"] as const;
|
||||
const FoodEnum = z.enum(foods, { error: () => "This is not food!" });
|
||||
const ItalianEnum = FoodEnum.extract(["Pasta", "Pizza"]);
|
||||
|
||||
const foodsError = FoodEnum.safeParse("Cucumbers");
|
||||
const italianError = ItalianEnum.safeParse("Tacos");
|
||||
|
||||
expect(foodsError.error!.issues[0].message).toEqual(italianError.error!.issues[0].message);
|
||||
|
||||
const UnhealthyEnum = FoodEnum.exclude(["Salad"], {
|
||||
error: () => ({ message: "This is not healthy food!" }),
|
||||
});
|
||||
const unhealthyError = UnhealthyEnum.safeParse("Salad");
|
||||
if (!unhealthyError.success) {
|
||||
expect(unhealthyError.error.issues[0].message).toEqual("This is not healthy food!");
|
||||
}
|
||||
});
|
||||
|
||||
test("readonly in ZodEnumDef", () => {
|
||||
type _a = z.ZodEnum<{ readonly a: "a"; readonly b: "b" }>;
|
||||
type _b = z.ZodEnum<{ a: "a"; b: "b" }>;
|
||||
});
|
||||
|
||||
test("enum error message, invalid enum elementstring", () => {
|
||||
const result = z.enum(["Tuna", "Trout"]).safeParse("Salmon");
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"Tuna",
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid option: expected one of \\"Tuna\\"|\\"Trout\\""
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("enum error message, invalid type", () => {
|
||||
const result = z.enum(["Tuna", "Trout"]).safeParse(12);
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
// expect(result.error!.issues[0].message).toEqual('Invalid input: expected one of "Tuna"|"Trout"');
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"Tuna",
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid option: expected one of \\"Tuna\\"|\\"Trout\\""
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("nativeEnum default error message", () => {
|
||||
enum Fish {
|
||||
Tuna = "Tuna",
|
||||
Trout = "Trout",
|
||||
}
|
||||
const result = z.nativeEnum(Fish).safeParse("Salmon");
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
// expect(result.error!.issues[0].message).toEqual('Invalid input: expected one of "Tuna"|"Trout"');
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"Tuna",
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid option: expected one of \\"Tuna\\"|\\"Trout\\""
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("enum with message returns the custom error message", () => {
|
||||
const schema = z.enum(["apple", "banana"], {
|
||||
message: "the value provided is invalid",
|
||||
});
|
||||
|
||||
const result1 = schema.safeParse("berries");
|
||||
expect(result1.success).toEqual(false);
|
||||
if (!result1.success) {
|
||||
expect(result1.error.issues[0].message).toEqual("the value provided is invalid");
|
||||
}
|
||||
|
||||
const result2 = schema.safeParse(undefined);
|
||||
expect(result2.success).toEqual(false);
|
||||
if (!result2.success) {
|
||||
expect(result2.error.issues[0].message).toEqual("the value provided is invalid");
|
||||
}
|
||||
|
||||
const result3 = schema.safeParse("banana");
|
||||
expect(result3.success).toEqual(true);
|
||||
|
||||
const result4 = schema.safeParse(null);
|
||||
expect(result4.success).toEqual(false);
|
||||
if (!result4.success) {
|
||||
expect(result4.error.issues[0].message).toEqual("the value provided is invalid");
|
||||
}
|
||||
});
|
||||
|
||||
test("enum with diagonal keys", () => {
|
||||
const schema_02 = z.enum({
|
||||
A: 1,
|
||||
B: "A",
|
||||
});
|
||||
|
||||
expect(schema_02.safeParse("A")).toMatchObject({ success: true });
|
||||
});
|
||||
527
node_modules/zod/src/v4/classic/tests/error-utils.test.ts
generated
vendored
Normal file
527
node_modules/zod/src/v4/classic/tests/error-utils.test.ts
generated
vendored
Normal file
@@ -0,0 +1,527 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
declare const iss: z.core.$ZodIssueCode;
|
||||
|
||||
const Test = z.object({
|
||||
f1: z.number(),
|
||||
f2: z.string().optional(),
|
||||
f3: z.string().nullable(),
|
||||
f4: z.array(z.object({ t: z.union([z.string(), z.boolean()]) })),
|
||||
});
|
||||
// type TestFlattenedErrors = core.inferFlattenedErrors<typeof Test, { message: string; code: number }>;
|
||||
// type TestFormErrors = core.inferFlattenedErrors<typeof Test>;
|
||||
const parsed = Test.safeParse({});
|
||||
|
||||
test("regular error", () => {
|
||||
expect(parsed).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"f1"
|
||||
],
|
||||
"message": "Invalid input: expected number, received undefined"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"f3"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
},
|
||||
{
|
||||
"expected": "array",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"f4"
|
||||
],
|
||||
"message": "Invalid input: expected array, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test(".flatten()", () => {
|
||||
const flattened = parsed.error!.flatten();
|
||||
// flattened.
|
||||
expectTypeOf(flattened).toMatchTypeOf<{
|
||||
formErrors: string[];
|
||||
fieldErrors: {
|
||||
f2?: string[];
|
||||
f1?: string[];
|
||||
f3?: string[];
|
||||
f4?: string[];
|
||||
};
|
||||
}>();
|
||||
|
||||
expect(flattened).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"f1": [
|
||||
"Invalid input: expected number, received undefined",
|
||||
],
|
||||
"f3": [
|
||||
"Invalid input: expected string, received undefined",
|
||||
],
|
||||
"f4": [
|
||||
"Invalid input: expected array, received undefined",
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("custom .flatten()", () => {
|
||||
type ErrorType = { message: string; code: number };
|
||||
const flattened = parsed.error!.flatten((iss) => ({ message: iss.message, code: 1234 }));
|
||||
expectTypeOf(flattened).toMatchTypeOf<{
|
||||
formErrors: ErrorType[];
|
||||
fieldErrors: {
|
||||
f2?: ErrorType[];
|
||||
f1?: ErrorType[];
|
||||
f3?: ErrorType[];
|
||||
f4?: ErrorType[];
|
||||
};
|
||||
}>();
|
||||
|
||||
expect(flattened).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"f1": [
|
||||
{
|
||||
"code": 1234,
|
||||
"message": "Invalid input: expected number, received undefined",
|
||||
},
|
||||
],
|
||||
"f3": [
|
||||
{
|
||||
"code": 1234,
|
||||
"message": "Invalid input: expected string, received undefined",
|
||||
},
|
||||
],
|
||||
"f4": [
|
||||
{
|
||||
"code": 1234,
|
||||
"message": "Invalid input: expected array, received undefined",
|
||||
},
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test(".format()", () => {
|
||||
const formatted = parsed.error!.format();
|
||||
expectTypeOf(formatted).toMatchTypeOf<{
|
||||
_errors: string[];
|
||||
f2?: { _errors: string[] };
|
||||
f1?: { _errors: string[] };
|
||||
f3?: { _errors: string[] };
|
||||
f4?: {
|
||||
[x: number]: {
|
||||
_errors: string[];
|
||||
t?: {
|
||||
_errors: string[];
|
||||
};
|
||||
};
|
||||
_errors: string[];
|
||||
};
|
||||
}>();
|
||||
|
||||
expect(formatted).toMatchInlineSnapshot(`
|
||||
{
|
||||
"_errors": [],
|
||||
"f1": {
|
||||
"_errors": [
|
||||
"Invalid input: expected number, received undefined",
|
||||
],
|
||||
},
|
||||
"f3": {
|
||||
"_errors": [
|
||||
"Invalid input: expected string, received undefined",
|
||||
],
|
||||
},
|
||||
"f4": {
|
||||
"_errors": [
|
||||
"Invalid input: expected array, received undefined",
|
||||
],
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("custom .format()", () => {
|
||||
type ErrorType = { message: string; code: number };
|
||||
const formatted = parsed.error!.format((iss) => ({ message: iss.message, code: 1234 }));
|
||||
expectTypeOf(formatted).toMatchTypeOf<{
|
||||
_errors: ErrorType[];
|
||||
f2?: { _errors: ErrorType[] };
|
||||
f1?: { _errors: ErrorType[] };
|
||||
f3?: { _errors: ErrorType[] };
|
||||
f4?: {
|
||||
[x: number]: {
|
||||
_errors: ErrorType[];
|
||||
t?: {
|
||||
_errors: ErrorType[];
|
||||
};
|
||||
};
|
||||
_errors: ErrorType[];
|
||||
};
|
||||
}>();
|
||||
|
||||
expect(formatted).toMatchInlineSnapshot(`
|
||||
{
|
||||
"_errors": [],
|
||||
"f1": {
|
||||
"_errors": [
|
||||
{
|
||||
"code": 1234,
|
||||
"message": "Invalid input: expected number, received undefined",
|
||||
},
|
||||
],
|
||||
},
|
||||
"f3": {
|
||||
"_errors": [
|
||||
{
|
||||
"code": 1234,
|
||||
"message": "Invalid input: expected string, received undefined",
|
||||
},
|
||||
],
|
||||
},
|
||||
"f4": {
|
||||
"_errors": [
|
||||
{
|
||||
"code": 1234,
|
||||
"message": "Invalid input: expected array, received undefined",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("all errors", () => {
|
||||
const propertySchema = z.string();
|
||||
const schema = z
|
||||
.object({
|
||||
a: propertySchema,
|
||||
b: propertySchema,
|
||||
})
|
||||
.refine(
|
||||
(val) => {
|
||||
return val.a === val.b;
|
||||
},
|
||||
{ message: "Must be equal" }
|
||||
);
|
||||
|
||||
const r1 = schema.safeParse({
|
||||
a: "asdf",
|
||||
b: "qwer",
|
||||
});
|
||||
|
||||
expect(z.core.flattenError(r1.error!)).toEqual({
|
||||
formErrors: ["Must be equal"],
|
||||
fieldErrors: {},
|
||||
});
|
||||
|
||||
const r2 = schema.safeParse({
|
||||
a: null,
|
||||
b: null,
|
||||
});
|
||||
|
||||
// const error = _error as z.ZodError;
|
||||
expect(z.core.flattenError(r2.error!)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"a": [
|
||||
"Invalid input: expected string, received null",
|
||||
],
|
||||
"b": [
|
||||
"Invalid input: expected string, received null",
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
|
||||
expect(z.core.flattenError(r2.error!, (iss) => iss.message.toUpperCase())).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"a": [
|
||||
"INVALID INPUT: EXPECTED STRING, RECEIVED NULL",
|
||||
],
|
||||
"b": [
|
||||
"INVALID INPUT: EXPECTED STRING, RECEIVED NULL",
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
// Test identity
|
||||
|
||||
expect(z.core.flattenError(r2.error!, (i: z.ZodIssue) => i)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"a": [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received null",
|
||||
"path": [
|
||||
"a",
|
||||
],
|
||||
},
|
||||
],
|
||||
"b": [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received null",
|
||||
"path": [
|
||||
"b",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
|
||||
// Test mapping
|
||||
const f1 = z.core.flattenError(r2.error!, (i: z.ZodIssue) => i.message.length);
|
||||
expect(f1).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"a": [
|
||||
45,
|
||||
],
|
||||
"b": [
|
||||
45,
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
// expect(f1.fieldErrors.a![0]).toEqual("Invalid input: expected string".length);
|
||||
// expect(f1).toMatchObject({
|
||||
// formErrors: [],
|
||||
// fieldErrors: {
|
||||
// a: ["Invalid input: expected string".length],
|
||||
// b: ["Invalid input: expected string".length],
|
||||
// },
|
||||
// });
|
||||
});
|
||||
|
||||
const schema = z.strictObject({
|
||||
username: z.string(),
|
||||
favoriteNumbers: z.array(z.number()),
|
||||
nesting: z.object({
|
||||
a: z.string(),
|
||||
}),
|
||||
});
|
||||
const result = schema.safeParse({
|
||||
username: 1234,
|
||||
favoriteNumbers: [1234, "4567"],
|
||||
nesting: {
|
||||
a: 123,
|
||||
},
|
||||
extra: 1234,
|
||||
});
|
||||
|
||||
test("z.treeifyError", () => {
|
||||
expect(z.treeifyError(result.error!)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"errors": [
|
||||
"Unrecognized key: "extra"",
|
||||
],
|
||||
"properties": {
|
||||
"favoriteNumbers": {
|
||||
"errors": [],
|
||||
"items": [
|
||||
,
|
||||
{
|
||||
"errors": [
|
||||
"Invalid input: expected number, received string",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
"nesting": {
|
||||
"errors": [],
|
||||
"properties": {
|
||||
"a": {
|
||||
"errors": [
|
||||
"Invalid input: expected string, received number",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
"username": {
|
||||
"errors": [
|
||||
"Invalid input: expected string, received number",
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("z.treeifyError 2", () => {
|
||||
const schema = z.strictObject({
|
||||
name: z.string(),
|
||||
logLevel: z.union([z.string(), z.number()]),
|
||||
env: z.literal(["production", "development"]),
|
||||
});
|
||||
|
||||
const data = {
|
||||
name: 1000,
|
||||
logLevel: false,
|
||||
extra: 1000,
|
||||
};
|
||||
|
||||
const result = schema.safeParse(data);
|
||||
const err = z.treeifyError(result.error!);
|
||||
expect(err).toMatchInlineSnapshot(`
|
||||
{
|
||||
"errors": [
|
||||
"Unrecognized key: "extra"",
|
||||
],
|
||||
"properties": {
|
||||
"env": {
|
||||
"errors": [
|
||||
"Invalid option: expected one of "production"|"development"",
|
||||
],
|
||||
},
|
||||
"logLevel": {
|
||||
"errors": [
|
||||
"Invalid input: expected string, received boolean",
|
||||
"Invalid input: expected number, received boolean",
|
||||
],
|
||||
},
|
||||
"name": {
|
||||
"errors": [
|
||||
"Invalid input: expected string, received number",
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("z.prettifyError", () => {
|
||||
expect(z.prettifyError(result.error!)).toMatchInlineSnapshot(`
|
||||
"✖ Unrecognized key: "extra"
|
||||
✖ Invalid input: expected string, received number
|
||||
→ at username
|
||||
✖ Invalid input: expected number, received string
|
||||
→ at favoriteNumbers[1]
|
||||
✖ Invalid input: expected string, received number
|
||||
→ at nesting.a"
|
||||
`);
|
||||
});
|
||||
|
||||
test("z.toDotPath", () => {
|
||||
expect(z.core.toDotPath(["a", "b", 0, "c"])).toMatchInlineSnapshot(`"a.b[0].c"`);
|
||||
|
||||
expect(z.core.toDotPath(["a", Symbol("b"), 0, "c"])).toMatchInlineSnapshot(`"a["Symbol(b)"][0].c"`);
|
||||
|
||||
// Test with periods in keys
|
||||
expect(z.core.toDotPath(["user.name", "first.last"])).toMatchInlineSnapshot(`"["user.name"]["first.last"]"`);
|
||||
|
||||
// Test with special characters
|
||||
expect(z.core.toDotPath(["user", "$special", Symbol("#symbol")])).toMatchInlineSnapshot(
|
||||
`"user.$special["Symbol(#symbol)"]"`
|
||||
);
|
||||
|
||||
// Test with dots and quotes
|
||||
expect(z.core.toDotPath(["search", `query("foo.bar"="abc")`])).toMatchInlineSnapshot(
|
||||
`"search["query(\\"foo.bar\\"=\\"abc\\")"]"`
|
||||
);
|
||||
|
||||
// Test with newlines
|
||||
expect(z.core.toDotPath(["search", `foo\nbar`])).toMatchInlineSnapshot(`"search["foo\\nbar"]"`);
|
||||
|
||||
// Test with empty strings
|
||||
expect(z.core.toDotPath(["", "empty"])).toMatchInlineSnapshot(`".empty"`);
|
||||
|
||||
// Test with array indices
|
||||
expect(z.core.toDotPath(["items", 0, 1, 2])).toMatchInlineSnapshot(`"items[0][1][2]"`);
|
||||
|
||||
// Test with mixed path elements
|
||||
expect(z.core.toDotPath(["users", "user.config", 0, "settings.theme"])).toMatchInlineSnapshot(
|
||||
`"users["user.config"][0]["settings.theme"]"`
|
||||
);
|
||||
|
||||
// Test with square brackets in keys
|
||||
expect(z.core.toDotPath(["data[0]", "value"])).toMatchInlineSnapshot(`"["data[0]"].value"`);
|
||||
|
||||
// Test with empty path
|
||||
expect(z.core.toDotPath([])).toMatchInlineSnapshot(`""`);
|
||||
});
|
||||
|
||||
test("inheritance", () => {
|
||||
const e1 = new z.ZodError([]);
|
||||
expect(e1).toBeInstanceOf(z.core.$ZodError);
|
||||
expect(e1).toBeInstanceOf(z.ZodError);
|
||||
// expect(e1).not.toBeInstanceOf(Error);
|
||||
|
||||
const e2 = new z.ZodRealError([]);
|
||||
expect(e2).toBeInstanceOf(z.ZodError);
|
||||
expect(e2).toBeInstanceOf(z.ZodRealError);
|
||||
expect(e2).toBeInstanceOf(Error);
|
||||
});
|
||||
|
||||
test("disc union treeify/format", () => {
|
||||
const schema = z.discriminatedUnion(
|
||||
"foo",
|
||||
[
|
||||
z.object({
|
||||
foo: z.literal("x"),
|
||||
x: z.string(),
|
||||
}),
|
||||
z.object({
|
||||
foo: z.literal("y"),
|
||||
y: z.string(),
|
||||
}),
|
||||
],
|
||||
{
|
||||
error: "Invalid discriminator",
|
||||
}
|
||||
);
|
||||
|
||||
const error = schema.safeParse({ foo: "invalid" }).error;
|
||||
expect(z.treeifyError(error!)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"errors": [],
|
||||
"properties": {
|
||||
"foo": {
|
||||
"errors": [
|
||||
"Invalid discriminator",
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
`);
|
||||
expect(z.prettifyError(error!)).toMatchInlineSnapshot(`
|
||||
"✖ Invalid discriminator
|
||||
→ at foo"
|
||||
`);
|
||||
expect(z.formatError(error!)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"_errors": [],
|
||||
"foo": {
|
||||
"_errors": [
|
||||
"Invalid discriminator",
|
||||
],
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
711
node_modules/zod/src/v4/classic/tests/error.test.ts
generated
vendored
Normal file
711
node_modules/zod/src/v4/classic/tests/error.test.ts
generated
vendored
Normal file
@@ -0,0 +1,711 @@
|
||||
import { inspect } from "node:util";
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("error creation", () => {
|
||||
const err1 = new z.ZodError([]);
|
||||
|
||||
err1.issues.push({
|
||||
code: "invalid_type",
|
||||
expected: "object",
|
||||
path: [],
|
||||
message: "",
|
||||
input: "adf",
|
||||
});
|
||||
err1.isEmpty;
|
||||
|
||||
const err2 = new z.ZodError(err1.issues);
|
||||
const err3 = new z.ZodError([]);
|
||||
err3.addIssues(err1.issues);
|
||||
err3.addIssue(err1.issues[0]);
|
||||
err1.message;
|
||||
err2.message;
|
||||
err3.message;
|
||||
});
|
||||
|
||||
test("do not allow error and message together", () => {
|
||||
expect(() =>
|
||||
z.string().refine((_) => true, {
|
||||
message: "override",
|
||||
error: (iss) => (iss.input === undefined ? "asdf" : null),
|
||||
})
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
const errorMap: z.ZodErrorMap = (issue) => {
|
||||
if (issue.code === "invalid_type") {
|
||||
if (issue.expected === "string") {
|
||||
return { message: "bad type!" };
|
||||
}
|
||||
}
|
||||
if (issue.code === "custom") {
|
||||
return { message: `less-than-${issue.params?.minimum}` };
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
test("type error with custom error map", () => {
|
||||
const result = z.string().safeParse(234, { error: errorMap });
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "bad type!"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("refinement fail with params", () => {
|
||||
const result = z
|
||||
.number()
|
||||
.refine((val) => val >= 3, {
|
||||
params: { minimum: 3 },
|
||||
})
|
||||
.safeParse(2, { error: errorMap });
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"params": {
|
||||
"minimum": 3
|
||||
},
|
||||
"message": "less-than-3"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("hard coded error with custom errormap", () => {
|
||||
const result = z
|
||||
.string()
|
||||
.refine((val) => val.length > 12, {
|
||||
params: { minimum: 13 },
|
||||
message: "override",
|
||||
})
|
||||
.safeParse("asdf", { error: () => "contextual" });
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"params": {
|
||||
"minimum": 13
|
||||
},
|
||||
"message": "override"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("default error message", () => {
|
||||
const result = z
|
||||
.number()
|
||||
.refine((x) => x > 3)
|
||||
.safeParse(2);
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("override error in refine", () => {
|
||||
const result = z
|
||||
.number()
|
||||
.refine((x) => x > 3, "override")
|
||||
.safeParse(2);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "override"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("override error in refinement", () => {
|
||||
const result = z
|
||||
.number()
|
||||
.refine((x) => x > 3, {
|
||||
message: "override",
|
||||
})
|
||||
.safeParse(2);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "override"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("array minimum", () => {
|
||||
let result = z.array(z.string()).min(3, "tooshort").safeParse(["asdf", "qwer"]);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues[0].code).toEqual("too_small");
|
||||
expect(result.error!.issues[0].message).toEqual("tooshort");
|
||||
|
||||
result = z.array(z.string()).min(3).safeParse(["asdf", "qwer"]);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues[0].code).toEqual("too_small");
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"origin": "array",
|
||||
"code": "too_small",
|
||||
"minimum": 3,
|
||||
"inclusive": true,
|
||||
"path": [],
|
||||
"message": "Too small: expected array to have >=3 items"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("literal bigint default error message", () => {
|
||||
const result = z.literal(BigInt(12)).safeParse(BigInt(13));
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"12"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid input: expected 12n"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("custom path in custom error map", () => {
|
||||
const schema = z.object({
|
||||
items: z.array(z.string()).refine((data) => data.length > 3, {
|
||||
path: ["items-too-few"],
|
||||
}),
|
||||
});
|
||||
|
||||
const errorMap: z.ZodErrorMap = (issue) => {
|
||||
expect((issue.path ?? []).length).toBe(2);
|
||||
return { message: "doesnt matter" };
|
||||
};
|
||||
const result = schema.safeParse({ items: ["first"] }, { error: errorMap });
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"items",
|
||||
"items-too-few"
|
||||
],
|
||||
"message": "doesnt matter"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
// test("error metadata from value", () => {
|
||||
// const dynamicRefine = z.string().refine(
|
||||
// (val) => val === val.toUpperCase(),
|
||||
// (val) => ({ params: { val } })
|
||||
// );
|
||||
|
||||
// const result = dynamicRefine.safeParse("asdf");
|
||||
// expect(result.success).toEqual(false);
|
||||
// if (!result.success) {
|
||||
// const sub = result.error.issues[0];
|
||||
// expect(result.error.issues[0].code).toEqual("custom");
|
||||
// if (sub.code === "custom") {
|
||||
// expect(sub.params?.val).toEqual("asdf");
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("don't call refine after validation failed", () => {
|
||||
// const asdf = z
|
||||
// .union([
|
||||
// z.number(),
|
||||
// z.string().transform(z.number(), (val) => {
|
||||
// return parseFloat(val);
|
||||
// }),
|
||||
// ])
|
||||
// .refine((v) => v >= 1);
|
||||
|
||||
// expect(() => asdf.safeParse("foo")).not.toThrow();
|
||||
// });
|
||||
|
||||
test("root level formatting", () => {
|
||||
const schema = z.string().email();
|
||||
const result = schema.safeParse("asdfsdf");
|
||||
expect(result.success).toBe(false);
|
||||
|
||||
expect(result.error!.format()).toMatchInlineSnapshot(`
|
||||
{
|
||||
"_errors": [
|
||||
"Invalid email address",
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("custom path", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
password: z.string(),
|
||||
confirm: z.string(),
|
||||
})
|
||||
.refine((val) => val.confirm === val.password, { path: ["confirm"] });
|
||||
|
||||
const result = schema.safeParse({
|
||||
password: "peanuts",
|
||||
confirm: "qeanuts",
|
||||
});
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
const error = result.error!.format();
|
||||
expect(error._errors).toEqual([]);
|
||||
expect(error.password?._errors).toEqual(undefined);
|
||||
expect(error.confirm?._errors).toEqual(["Invalid input"]);
|
||||
});
|
||||
|
||||
test("custom path", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
password: z.string().min(6),
|
||||
confirm: z.string().min(6),
|
||||
})
|
||||
.refine((val) => val.confirm === val.password);
|
||||
|
||||
const result = schema.safeParse({
|
||||
password: "qwer",
|
||||
confirm: "asdf",
|
||||
});
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues.length).toEqual(3);
|
||||
});
|
||||
|
||||
const schema = z.object({
|
||||
inner: z.object({
|
||||
name: z
|
||||
.string()
|
||||
.refine((val) => val.length > 5)
|
||||
.array()
|
||||
.refine((val) => val.length <= 1),
|
||||
}),
|
||||
});
|
||||
|
||||
test("no abort early on refinements", () => {
|
||||
const invalidItem = {
|
||||
inner: { name: ["aasd", "asdfasdfasfd"] },
|
||||
};
|
||||
|
||||
const result1 = schema.safeParse(invalidItem);
|
||||
expect(result1.success).toBe(false);
|
||||
expect(result1.error!.issues.length).toEqual(2);
|
||||
});
|
||||
|
||||
test("detect issue with input fallback", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.transform((val) => val.length)
|
||||
.refine(() => false, { message: "always fails" })
|
||||
.refine(
|
||||
(val) => {
|
||||
if (typeof val !== "number") throw new Error();
|
||||
return (val ^ 2) > 10;
|
||||
} // should be number but it's a string
|
||||
);
|
||||
expect(() => schema.parse("hello")).toThrow(z.ZodError);
|
||||
});
|
||||
|
||||
test("formatting", () => {
|
||||
const invalidItem = {
|
||||
inner: { name: ["aasd", "asdfasdfasfd"] },
|
||||
};
|
||||
const invalidArray = {
|
||||
inner: { name: ["asdfasdf", "asdfasdfasfd"] },
|
||||
};
|
||||
const result1 = schema.safeParse(invalidItem);
|
||||
const result2 = schema.safeParse(invalidArray);
|
||||
|
||||
expect(result1.success).toBe(false);
|
||||
expect(result2.success).toBe(false);
|
||||
const error1 = result1.error!.format();
|
||||
expect(error1._errors).toEqual([]);
|
||||
expect(error1.inner?._errors).toEqual([]);
|
||||
expect(error1.inner?.name?.[1]).toEqual(undefined);
|
||||
|
||||
type FormattedError = z.inferFormattedError<typeof schema>;
|
||||
const error2: FormattedError = result2.error!.format();
|
||||
expect(error2._errors).toEqual([]);
|
||||
expect(error2.inner?._errors).toEqual([]);
|
||||
expect(error2.inner?.name?._errors).toEqual(["Invalid input"]);
|
||||
expect(error2.inner?.name?.[0]).toEqual(undefined);
|
||||
expect(error2.inner?.name?.[1]).toEqual(undefined);
|
||||
expect(error2.inner?.name?.[2]).toEqual(undefined);
|
||||
|
||||
// test custom mapper
|
||||
type FormattedErrorWithNumber = z.inferFormattedError<typeof schema, number>;
|
||||
const errorWithNumber: FormattedErrorWithNumber = result2.error!.format(() => 5);
|
||||
expect(errorWithNumber._errors).toEqual([]);
|
||||
expect(errorWithNumber.inner?._errors).toEqual([]);
|
||||
expect(errorWithNumber.inner?.name?._errors).toEqual([5]);
|
||||
});
|
||||
|
||||
test("formatting with nullable and optional fields", () => {
|
||||
const nameSchema = z.string().refine((val) => val.length > 5);
|
||||
const schema = z.object({
|
||||
nullableObject: z.object({ name: nameSchema }).nullable(),
|
||||
nullableArray: z.array(nameSchema).nullable(),
|
||||
nullableTuple: z.tuple([nameSchema, nameSchema, z.number()]).nullable(),
|
||||
optionalObject: z.object({ name: nameSchema }).optional(),
|
||||
optionalArray: z.array(nameSchema).optional(),
|
||||
optionalTuple: z.tuple([nameSchema, nameSchema, z.number()]).optional(),
|
||||
});
|
||||
const invalidItem = {
|
||||
nullableObject: { name: "abcd" },
|
||||
nullableArray: ["abcd"],
|
||||
nullableTuple: ["abcd", "abcd", 1],
|
||||
optionalObject: { name: "abcd" },
|
||||
optionalArray: ["abcd"],
|
||||
optionalTuple: ["abcd", "abcd", 1],
|
||||
};
|
||||
const result = schema.safeParse(invalidItem);
|
||||
expect(result.success).toBe(false);
|
||||
const error: z.inferFormattedError<typeof schema> = result.error!.format();
|
||||
expect(error._errors).toEqual([]);
|
||||
expect(error.nullableObject?._errors).toEqual([]);
|
||||
expect(error.nullableObject?.name?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.nullableArray?._errors).toEqual([]);
|
||||
expect(error.nullableArray?.[0]?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.nullableTuple?._errors).toEqual([]);
|
||||
expect(error.nullableTuple?.[0]?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.nullableTuple?.[1]?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.optionalObject?._errors).toEqual([]);
|
||||
expect(error.optionalObject?.name?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.optionalArray?._errors).toEqual([]);
|
||||
expect(error.optionalArray?.[0]?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.optionalTuple?._errors).toEqual([]);
|
||||
expect(error.optionalTuple?.[0]?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.optionalTuple?.[1]?._errors).toEqual(["Invalid input"]);
|
||||
|
||||
expect(error).toMatchInlineSnapshot(`
|
||||
{
|
||||
"_errors": [],
|
||||
"nullableArray": {
|
||||
"0": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
"_errors": [],
|
||||
},
|
||||
"nullableObject": {
|
||||
"_errors": [],
|
||||
"name": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
},
|
||||
"nullableTuple": {
|
||||
"0": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
"1": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
"_errors": [],
|
||||
},
|
||||
"optionalArray": {
|
||||
"0": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
"_errors": [],
|
||||
},
|
||||
"optionalObject": {
|
||||
"_errors": [],
|
||||
"name": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
},
|
||||
"optionalTuple": {
|
||||
"0": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
"1": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
"_errors": [],
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("inferFlattenedErrors", () => {
|
||||
const schemaWithTransform = z.object({ foo: z.string() }).transform((o) => ({ bar: o.foo }));
|
||||
|
||||
const result = schemaWithTransform.safeParse({});
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
type ValidationErrors = z.inferFlattenedErrors<typeof schemaWithTransform>;
|
||||
const error: ValidationErrors = result.error!.flatten();
|
||||
expect(error).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"foo": [
|
||||
"Invalid input: expected string, received undefined",
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
const stringWithCustomError = z.string({
|
||||
error: () => "bound",
|
||||
});
|
||||
|
||||
test("schema-bound error map", () => {
|
||||
const result = stringWithCustomError.safeParse(1234);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues[0].message).toEqual("bound");
|
||||
});
|
||||
|
||||
test("bound error map overrides contextual", () => {
|
||||
// support contextual override
|
||||
const result = stringWithCustomError.safeParse(undefined, {
|
||||
error: () => ({ message: "override" }),
|
||||
});
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues[0].message).toEqual("bound");
|
||||
});
|
||||
|
||||
test("z.config customError ", () => {
|
||||
// support overrideErrorMap
|
||||
|
||||
z.config({ customError: () => ({ message: "override" }) });
|
||||
const result = stringWithCustomError.min(10).safeParse("tooshort");
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 10,
|
||||
"inclusive": true,
|
||||
"path": [],
|
||||
"message": "override"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
expect(result.error!.issues[0].message).toEqual("override");
|
||||
z.config({ customError: undefined });
|
||||
});
|
||||
|
||||
// test("invalid and required", () => {
|
||||
// const str = z.string({
|
||||
// invalid_type_error: "Invalid name",
|
||||
// required_error: "Name is required",
|
||||
// });
|
||||
// const result1 = str.safeParse(1234);
|
||||
// expect(result1.success).toBe(false);
|
||||
// if (!result1.success) {
|
||||
// expect(result1.error.issues[0].message).toEqual("Invalid name");
|
||||
// }
|
||||
// const result2 = str.safeParse(undefined);
|
||||
// expect(result2.success).toBe(false);
|
||||
// if (!result2.success) {
|
||||
// expect(result2.error.issues[0].message).toEqual("Name is required");
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("Fallback to default required error", () => {
|
||||
// const str = z.string({
|
||||
// invalid_type_error: "Invalid name",
|
||||
// // required_error: "Name is required",
|
||||
// });
|
||||
|
||||
// const result2 = str.safeParse(undefined);
|
||||
// expect(result2.success).toBe(false);
|
||||
// if (!result2.success) {
|
||||
// expect(result2.error.issues[0].message).toEqual("Required");
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("invalid and required and errorMap", () => {
|
||||
// expect(() => {
|
||||
// return z.string({
|
||||
// invalid_type_error: "Invalid name",
|
||||
// required_error: "Name is required",
|
||||
// errorMap: () => ({ message: "override" }),
|
||||
// });
|
||||
// }).toThrow();
|
||||
// });
|
||||
|
||||
// test("strict error message", () => {
|
||||
// const errorMsg = "Invalid object";
|
||||
// const obj = z.object({ x: z.string() }).strict(errorMsg);
|
||||
// const result = obj.safeParse({ x: "a", y: "b" });
|
||||
// expect(result.success).toBe(false);
|
||||
// if (!result.success) {
|
||||
// expect(result.error.issues[0].message).toEqual(errorMsg);
|
||||
// }
|
||||
// });
|
||||
|
||||
test("empty string error message", () => {
|
||||
const schema = z.string().max(1, { message: "" });
|
||||
const result = schema.safeParse("asdf");
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues[0].message).toEqual("");
|
||||
});
|
||||
|
||||
test("dont short circuit on continuable errors", () => {
|
||||
const user = z
|
||||
.object({
|
||||
password: z.string().min(6),
|
||||
confirm: z.string(),
|
||||
})
|
||||
.refine((data) => data.password === data.confirm, {
|
||||
message: "Passwords don't match",
|
||||
path: ["confirm"],
|
||||
});
|
||||
const result = user.safeParse({ password: "asdf", confirm: "qwer" });
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 6,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"password"
|
||||
],
|
||||
"message": "Too small: expected string to have >=6 characters"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"confirm"
|
||||
],
|
||||
"message": "Passwords don't match"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
// expect(result.error!.issues.length).toEqual(2);
|
||||
});
|
||||
|
||||
test("string error params", () => {
|
||||
const a = z.string("Bad!");
|
||||
expect(a.safeParse(123).error!.issues[0].message).toBe("Bad!");
|
||||
|
||||
const b = z.string().min(5, "Too short!");
|
||||
expect(b.safeParse("abc").error!.issues[0].message).toBe("Too short!");
|
||||
|
||||
const c = z.uuid("Bad UUID!");
|
||||
expect(c.safeParse("not-a-uuid").error!.issues[0].message).toBe("Bad UUID!");
|
||||
|
||||
const d = z.string().datetime({ message: "Bad date!" });
|
||||
expect(d.safeParse("not-a-date").error!.issues[0].message).toBe("Bad date!");
|
||||
|
||||
const e = z.array(z.string(), "Bad array!");
|
||||
expect(e.safeParse("not-an-array").error!.issues[0].message).toBe("Bad array!");
|
||||
|
||||
const f = z.array(z.string()).min(5, "Too few items!");
|
||||
expect(f.safeParse(["a", "b"]).error!.issues[0].message).toBe("Too few items!");
|
||||
|
||||
const g = z.set(z.string(), "Bad set!");
|
||||
expect(g.safeParse("not-a-set").error!.issues[0].message).toBe("Bad set!");
|
||||
|
||||
const h = z.array(z.string(), "Bad array!");
|
||||
expect(h.safeParse(123).error!.issues[0].message).toBe("Bad array!");
|
||||
|
||||
const i = z.set(z.string(), "Bad set!");
|
||||
expect(i.safeParse(123).error!.issues[0].message).toBe("Bad set!");
|
||||
|
||||
const j = z.array(z.string(), "Bad array!");
|
||||
expect(j.safeParse(null).error!.issues[0].message).toBe("Bad array!");
|
||||
});
|
||||
|
||||
test("error inheritance", () => {
|
||||
const e1 = z.string().safeParse(123).error!;
|
||||
expect(e1).toBeInstanceOf(z.core.$ZodError);
|
||||
expect(e1).toBeInstanceOf(z.ZodError);
|
||||
expect(e1).toBeInstanceOf(z.ZodRealError);
|
||||
// expect(e1).not.toBeInstanceOf(Error);
|
||||
|
||||
try {
|
||||
z.string().parse(123);
|
||||
} catch (e2) {
|
||||
expect(e1).toBeInstanceOf(z.core.$ZodError);
|
||||
expect(e2).toBeInstanceOf(z.ZodError);
|
||||
expect(e2).toBeInstanceOf(z.ZodRealError);
|
||||
// expect(e2).toBeInstanceOf(Error);
|
||||
}
|
||||
});
|
||||
|
||||
test("error serialization", () => {
|
||||
try {
|
||||
z.string().parse(123);
|
||||
} catch (e) {
|
||||
expect(e).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
expect(inspect(e).split("\n").slice(0, 8).join("\n")).toMatchInlineSnapshot(`
|
||||
"ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]"
|
||||
`);
|
||||
}
|
||||
});
|
||||
91
node_modules/zod/src/v4/classic/tests/file.test.ts
generated
vendored
Normal file
91
node_modules/zod/src/v4/classic/tests/file.test.ts
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
// @ts-ignore
|
||||
import { File as WebFile } from "@web-std/file";
|
||||
|
||||
import { afterEach, beforeEach, expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const minCheck = z.file().min(5);
|
||||
const maxCheck = z.file().max(8);
|
||||
const mimeCheck = z.file().mime(["text/plain", "application/json"]);
|
||||
|
||||
const originalFile = global.File;
|
||||
beforeEach(async () => {
|
||||
if (!globalThis.File) globalThis.File = WebFile;
|
||||
});
|
||||
afterEach(() => {
|
||||
if (globalThis.File !== originalFile) {
|
||||
globalThis.File = originalFile;
|
||||
}
|
||||
});
|
||||
|
||||
test("passing validations", () => {
|
||||
minCheck.safeParse(new File(["12345"], "test.txt"));
|
||||
maxCheck.safeParse(new File(["12345678"], "test.txt"));
|
||||
mimeCheck.safeParse(new File([""], "test.csv", { type: "text/plain" }));
|
||||
expect(() => mimeCheck.parse(new File([""], "test.txt"))).toThrow();
|
||||
expect(() => mimeCheck.parse(new File([""], "test.txt", { type: "text/csv" }))).toThrow();
|
||||
});
|
||||
|
||||
test("failing validations", () => {
|
||||
expect(minCheck.safeParse(new File(["1234"], "test.txt"))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "file",
|
||||
"code": "too_small",
|
||||
"minimum": 5,
|
||||
"path": [],
|
||||
"message": "Too small: expected file to have >5 bytes"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(maxCheck.safeParse(new File(["123456789"], "test.txt"))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "file",
|
||||
"code": "too_big",
|
||||
"maximum": 8,
|
||||
"path": [],
|
||||
"message": "Too big: expected file to have <8 bytes"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(mimeCheck.safeParse(new File([""], "test.csv"))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"text/plain",
|
||||
"application/json"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid option: expected one of \\"text/plain\\"|\\"application/json\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(mimeCheck.safeParse(new File([""], "test.csv", { type: "text/csv" }))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"text/plain",
|
||||
"application/json"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid option: expected one of \\"text/plain\\"|\\"application/json\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
175
node_modules/zod/src/v4/classic/tests/firstparty.test.ts
generated
vendored
Normal file
175
node_modules/zod/src/v4/classic/tests/firstparty.test.ts
generated
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
import { expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
import type * as core from "zod/v4/core";
|
||||
|
||||
test("first party switch", () => {
|
||||
const myType = z.string() as core.$ZodTypes;
|
||||
const def = myType._zod.def;
|
||||
switch (def.type) {
|
||||
case "string":
|
||||
break;
|
||||
case "number":
|
||||
break;
|
||||
case "bigint":
|
||||
break;
|
||||
case "boolean":
|
||||
break;
|
||||
case "date":
|
||||
break;
|
||||
case "symbol":
|
||||
break;
|
||||
case "undefined":
|
||||
break;
|
||||
case "null":
|
||||
break;
|
||||
case "any":
|
||||
break;
|
||||
case "unknown":
|
||||
break;
|
||||
case "never":
|
||||
break;
|
||||
case "void":
|
||||
break;
|
||||
case "array":
|
||||
break;
|
||||
case "object":
|
||||
break;
|
||||
case "union":
|
||||
break;
|
||||
case "intersection":
|
||||
break;
|
||||
case "tuple":
|
||||
break;
|
||||
case "record":
|
||||
break;
|
||||
case "map":
|
||||
break;
|
||||
case "set":
|
||||
break;
|
||||
case "literal":
|
||||
break;
|
||||
case "enum":
|
||||
break;
|
||||
case "promise":
|
||||
break;
|
||||
case "optional":
|
||||
break;
|
||||
case "nonoptional":
|
||||
break;
|
||||
case "nullable":
|
||||
break;
|
||||
case "default":
|
||||
break;
|
||||
case "prefault":
|
||||
break;
|
||||
case "template_literal":
|
||||
break;
|
||||
case "custom":
|
||||
break;
|
||||
case "transform":
|
||||
break;
|
||||
case "readonly":
|
||||
break;
|
||||
case "nan":
|
||||
break;
|
||||
case "pipe":
|
||||
break;
|
||||
case "success":
|
||||
break;
|
||||
case "catch":
|
||||
break;
|
||||
case "file":
|
||||
break;
|
||||
case "lazy":
|
||||
break;
|
||||
default:
|
||||
expectTypeOf(def).toEqualTypeOf<never>();
|
||||
}
|
||||
});
|
||||
|
||||
test("$ZodSchemaTypes", () => {
|
||||
const type = "string" as core.$ZodTypeDef["type"];
|
||||
switch (type) {
|
||||
case "string":
|
||||
break;
|
||||
case "number":
|
||||
break;
|
||||
case "int":
|
||||
break;
|
||||
case "bigint":
|
||||
break;
|
||||
case "boolean":
|
||||
break;
|
||||
case "date":
|
||||
break;
|
||||
case "symbol":
|
||||
break;
|
||||
case "undefined":
|
||||
break;
|
||||
case "null":
|
||||
break;
|
||||
case "any":
|
||||
break;
|
||||
case "unknown":
|
||||
break;
|
||||
case "never":
|
||||
break;
|
||||
case "void":
|
||||
break;
|
||||
case "array":
|
||||
break;
|
||||
case "object":
|
||||
break;
|
||||
case "union":
|
||||
break;
|
||||
case "intersection":
|
||||
break;
|
||||
case "tuple":
|
||||
break;
|
||||
case "record":
|
||||
break;
|
||||
case "map":
|
||||
break;
|
||||
case "set":
|
||||
break;
|
||||
case "literal":
|
||||
break;
|
||||
case "enum":
|
||||
break;
|
||||
case "promise":
|
||||
break;
|
||||
case "optional":
|
||||
break;
|
||||
case "nonoptional":
|
||||
break;
|
||||
case "nullable":
|
||||
break;
|
||||
case "default":
|
||||
break;
|
||||
case "prefault":
|
||||
break;
|
||||
case "template_literal":
|
||||
break;
|
||||
case "custom":
|
||||
break;
|
||||
case "transform":
|
||||
break;
|
||||
case "readonly":
|
||||
break;
|
||||
case "nan":
|
||||
break;
|
||||
case "pipe":
|
||||
break;
|
||||
case "success":
|
||||
break;
|
||||
case "catch":
|
||||
break;
|
||||
case "file":
|
||||
break;
|
||||
case "lazy":
|
||||
break;
|
||||
|
||||
default:
|
||||
expectTypeOf(type).toEqualTypeOf<never>();
|
||||
}
|
||||
});
|
||||
268
node_modules/zod/src/v4/classic/tests/function.test.ts
generated
vendored
Normal file
268
node_modules/zod/src/v4/classic/tests/function.test.ts
generated
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const args1 = z.tuple([z.string()]);
|
||||
const returns1 = z.number();
|
||||
const func1 = z.function({
|
||||
input: args1,
|
||||
|
||||
output: returns1,
|
||||
});
|
||||
|
||||
test("function parsing", () => {
|
||||
const parsed = func1.implement((arg: any) => arg.length);
|
||||
const result = parsed("asdf");
|
||||
expect(result).toBe(4);
|
||||
});
|
||||
|
||||
test("parsed function fail 1", () => {
|
||||
// @ts-expect-error
|
||||
const parsed = func1.implement((x: string) => x);
|
||||
expect(() => parsed("asdf")).toThrow();
|
||||
});
|
||||
|
||||
test("parsed function fail 2", () => {
|
||||
// @ts-expect-error
|
||||
const parsed = func1.implement((x: string) => x);
|
||||
expect(() => parsed(13 as any)).toThrow();
|
||||
});
|
||||
|
||||
test("function inference 1", () => {
|
||||
type func1 = (typeof func1)["_input"];
|
||||
expectTypeOf<func1>().toEqualTypeOf<(k: string) => number>();
|
||||
});
|
||||
|
||||
// test("method parsing", () => {
|
||||
// const methodObject = z.object({
|
||||
// property: z.number(),
|
||||
// method: z
|
||||
// .function()
|
||||
// .input(z.tuple([z.string()]))
|
||||
// .output(z.number()),
|
||||
// });
|
||||
// const methodInstance = {
|
||||
// property: 3,
|
||||
// method: function (s: string) {
|
||||
// return s.length + this.property;
|
||||
// },
|
||||
// };
|
||||
// const parsed = methodObject.parse(methodInstance);
|
||||
// expect(parsed.method("length=8")).toBe(11); // 8 length + 3 property
|
||||
// });
|
||||
|
||||
// test("async method parsing", async () => {
|
||||
// const methodObject = z.object({
|
||||
// property: z.number(),
|
||||
// method: z.function().input(z.string()).output(z.promise(z.number())),
|
||||
// });
|
||||
// const methodInstance = {
|
||||
// property: 3,
|
||||
// method: async function (s: string) {
|
||||
// return s.length + this.property;
|
||||
// },
|
||||
// };
|
||||
// const parsed = methodObject.parse(methodInstance);
|
||||
// expect(await parsed.method("length=8")).toBe(11); // 8 length + 3 property
|
||||
// });
|
||||
|
||||
test("args method", () => {
|
||||
const t1 = z.function();
|
||||
type t1 = (typeof t1)["_input"];
|
||||
expectTypeOf<t1>().toEqualTypeOf<(...args_1: never[]) => unknown>();
|
||||
t1._input;
|
||||
|
||||
const t2args = z.tuple([z.string()], z.unknown());
|
||||
|
||||
const t2 = t1.input(t2args);
|
||||
type t2 = (typeof t2)["_input"];
|
||||
expectTypeOf<t2>().toEqualTypeOf<(arg: string, ...args_1: unknown[]) => unknown>();
|
||||
|
||||
const t3 = t2.output(z.boolean());
|
||||
type t3 = (typeof t3)["_input"];
|
||||
expectTypeOf<t3>().toEqualTypeOf<(arg: string, ...args_1: unknown[]) => boolean>();
|
||||
});
|
||||
|
||||
// test("custom args", () => {
|
||||
// const fn = z.function().implement((_a: string, _b: number) => {
|
||||
// return new Date();
|
||||
// });
|
||||
|
||||
// expectTypeOf(fn).toEqualTypeOf<(a: string, b: number) => Date>();
|
||||
// });
|
||||
|
||||
const args2 = z.tuple([
|
||||
z.object({
|
||||
f1: z.number(),
|
||||
f2: z.string().nullable(),
|
||||
f3: z.array(z.boolean().optional()).optional(),
|
||||
}),
|
||||
]);
|
||||
const returns2 = z.union([z.string(), z.number()]);
|
||||
|
||||
const func2 = z.function({
|
||||
input: args2,
|
||||
output: returns2,
|
||||
});
|
||||
|
||||
test("function inference 2", () => {
|
||||
type func2 = (typeof func2)["_input"];
|
||||
|
||||
expectTypeOf<func2>().toEqualTypeOf<
|
||||
(arg: {
|
||||
f3?: (boolean | undefined)[] | undefined;
|
||||
f1: number;
|
||||
f2: string | null;
|
||||
}) => string | number
|
||||
>();
|
||||
});
|
||||
|
||||
test("valid function run", () => {
|
||||
const validFunc2Instance = func2.implement((_x) => {
|
||||
_x.f2;
|
||||
_x.f3![0];
|
||||
return "adf" as any;
|
||||
});
|
||||
|
||||
validFunc2Instance({
|
||||
f1: 21,
|
||||
f2: "asdf",
|
||||
f3: [true, false],
|
||||
});
|
||||
});
|
||||
|
||||
test("input validation error", () => {
|
||||
const schema = z.function({
|
||||
input: z.tuple([z.string()]),
|
||||
output: z.void(),
|
||||
});
|
||||
const fn = schema.implement(() => 1234 as any);
|
||||
|
||||
// @ts-expect-error
|
||||
const checker = () => fn();
|
||||
|
||||
try {
|
||||
checker();
|
||||
} catch (e: any) {
|
||||
expect(e.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received undefined",
|
||||
"path": [
|
||||
0,
|
||||
],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("array inputs", () => {
|
||||
const a = z.function({
|
||||
input: [
|
||||
z.object({
|
||||
name: z.string(),
|
||||
age: z.number().int(),
|
||||
}),
|
||||
],
|
||||
output: z.string(),
|
||||
});
|
||||
|
||||
a.implement((args) => {
|
||||
return `${args.age}`;
|
||||
});
|
||||
|
||||
const b = z.function({
|
||||
input: [
|
||||
z.object({
|
||||
name: z.string(),
|
||||
age: z.number().int(),
|
||||
}),
|
||||
],
|
||||
});
|
||||
b.implement((args) => {
|
||||
return `${args.age}`;
|
||||
});
|
||||
});
|
||||
|
||||
test("output validation error", () => {
|
||||
const schema = z.function({
|
||||
input: z.tuple([]),
|
||||
output: z.string(),
|
||||
});
|
||||
const fn = schema.implement(() => 1234 as any);
|
||||
try {
|
||||
fn();
|
||||
} catch (e: any) {
|
||||
expect(e.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("function with async refinements", async () => {
|
||||
const schema = z
|
||||
.function()
|
||||
.input([z.string().refine(async (val) => val.length > 10)])
|
||||
.output(z.promise(z.number().refine(async (val) => val > 10)));
|
||||
|
||||
const func = schema.implementAsync(async (val) => {
|
||||
return val.length;
|
||||
});
|
||||
const results = [];
|
||||
try {
|
||||
await func("asdfasdf");
|
||||
results.push("success");
|
||||
} catch (_) {
|
||||
results.push("fail");
|
||||
}
|
||||
try {
|
||||
await func("asdflkjasdflkjsf");
|
||||
results.push("success");
|
||||
} catch (_) {
|
||||
results.push("fail");
|
||||
}
|
||||
|
||||
expect(results).toEqual(["fail", "success"]);
|
||||
});
|
||||
|
||||
test("non async function with async refinements should fail", async () => {
|
||||
const func = z
|
||||
.function()
|
||||
.input([z.string().refine(async (val) => val.length > 10)])
|
||||
.output(z.number().refine(async (val) => val > 10))
|
||||
.implement((val) => {
|
||||
return val.length;
|
||||
});
|
||||
|
||||
const results = [];
|
||||
try {
|
||||
await func("asdasdfasdffasdf");
|
||||
results.push("success");
|
||||
} catch (_) {
|
||||
results.push("fail");
|
||||
}
|
||||
|
||||
expect(results).toEqual(["fail"]);
|
||||
});
|
||||
|
||||
test("extra parameters with rest", () => {
|
||||
const maxLength5 = z
|
||||
.function()
|
||||
.input([z.string()], z.unknown())
|
||||
.output(z.boolean())
|
||||
.implement((str, _arg, _qewr) => {
|
||||
return str.length <= 5;
|
||||
});
|
||||
|
||||
const filteredList = ["apple", "orange", "pear", "banana", "strawberry"].filter(maxLength5);
|
||||
expect(filteredList.length).toEqual(2);
|
||||
});
|
||||
72
node_modules/zod/src/v4/classic/tests/generics.test.ts
generated
vendored
Normal file
72
node_modules/zod/src/v4/classic/tests/generics.test.ts
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
function nest<TData extends z.ZodType>(schema: TData) {
|
||||
return z.object({
|
||||
nested: schema,
|
||||
});
|
||||
}
|
||||
|
||||
test("generics", () => {
|
||||
const a = nest(z.object({ a: z.string() }));
|
||||
type a = z.infer<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<{ nested: { a: string } }>();
|
||||
|
||||
const b = nest(z.object({ a: z.string().optional() }));
|
||||
type b = z.infer<typeof b>;
|
||||
expectTypeOf<b>().toEqualTypeOf<{ nested: { a?: string | undefined } }>();
|
||||
});
|
||||
|
||||
test("generics with optional", () => {
|
||||
async function stripOuter<TData extends z.ZodType>(schema: TData, data: unknown) {
|
||||
return z
|
||||
.object({
|
||||
nested: schema.optional(),
|
||||
})
|
||||
.transform((data) => {
|
||||
return data.nested;
|
||||
})
|
||||
.parse({ nested: data });
|
||||
}
|
||||
|
||||
const result = stripOuter(z.object({ a: z.string() }), { a: "asdf" });
|
||||
expectTypeOf<typeof result>().toEqualTypeOf<Promise<{ a: string } | undefined>>();
|
||||
});
|
||||
|
||||
// test("assignability", () => {
|
||||
// const createSchemaAndParse = <K extends string, VS extends z.ZodString>(key: K, valueSchema: VS, data: unknown) => {
|
||||
// const schema = z.object({
|
||||
// [key]: valueSchema,
|
||||
// });
|
||||
// // return { [key]: valueSchema };
|
||||
// const parsed = schema.parse(data);
|
||||
// return parsed;
|
||||
// // const inferred: z.infer<z.ZodObject<{ [k in K]: VS }>> = parsed;
|
||||
// // return inferred;
|
||||
// };
|
||||
// const parsed = createSchemaAndParse("foo", z.string(), { foo: "" });
|
||||
// expectTypeOf<typeof parsed>().toEqualTypeOf<{ foo: string }>();
|
||||
// });
|
||||
|
||||
test("nested no undefined", () => {
|
||||
const inner = z.string().or(z.array(z.string()));
|
||||
const outer = z.object({ inner });
|
||||
type outerSchema = z.infer<typeof outer>;
|
||||
expectTypeOf<outerSchema>().toEqualTypeOf<{ inner: string | string[] }>();
|
||||
|
||||
expect(outer.safeParse({ inner: undefined }).success).toEqual(false);
|
||||
});
|
||||
|
||||
test("generic on output type", () => {
|
||||
const createV4Schema = <Output>(opts: {
|
||||
schema: z.ZodType<Output>;
|
||||
}) => {
|
||||
return opts.schema;
|
||||
};
|
||||
|
||||
createV4Schema({
|
||||
schema: z.object({
|
||||
name: z.string(),
|
||||
}),
|
||||
})?._zod?.output?.name;
|
||||
});
|
||||
829
node_modules/zod/src/v4/classic/tests/index.test.ts
generated
vendored
Normal file
829
node_modules/zod/src/v4/classic/tests/index.test.ts
generated
vendored
Normal file
@@ -0,0 +1,829 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
import type { util } from "zod/v4/core";
|
||||
|
||||
test("z.boolean", () => {
|
||||
const a = z.boolean();
|
||||
expect(z.parse(a, true)).toEqual(true);
|
||||
expect(z.parse(a, false)).toEqual(false);
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
expect(() => z.parse(a, "true")).toThrow();
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<boolean>();
|
||||
});
|
||||
|
||||
test("z.bigint", () => {
|
||||
const a = z.bigint();
|
||||
expect(z.parse(a, BigInt(123))).toEqual(BigInt(123));
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
expect(() => z.parse(a, "123")).toThrow();
|
||||
});
|
||||
|
||||
test("z.symbol", () => {
|
||||
const a = z.symbol();
|
||||
const sym = Symbol();
|
||||
expect(z.parse(a, sym)).toEqual(sym);
|
||||
expect(() => z.parse(a, "symbol")).toThrow();
|
||||
});
|
||||
|
||||
test("z.date", () => {
|
||||
const a = z.date();
|
||||
const date = new Date();
|
||||
expect(z.parse(a, date)).toEqual(date);
|
||||
expect(() => z.parse(a, "date")).toThrow();
|
||||
});
|
||||
|
||||
test("z.coerce.string", () => {
|
||||
const a = z.coerce.string();
|
||||
expect(z.parse(a, 123)).toEqual("123");
|
||||
expect(z.parse(a, true)).toEqual("true");
|
||||
expect(z.parse(a, null)).toEqual("null");
|
||||
expect(z.parse(a, undefined)).toEqual("undefined");
|
||||
});
|
||||
|
||||
test("z.coerce.number", () => {
|
||||
const a = z.coerce.number();
|
||||
expect(z.parse(a, "123")).toEqual(123);
|
||||
expect(z.parse(a, "123.45")).toEqual(123.45);
|
||||
expect(z.parse(a, true)).toEqual(1);
|
||||
expect(z.parse(a, false)).toEqual(0);
|
||||
expect(() => z.parse(a, "abc")).toThrow();
|
||||
});
|
||||
|
||||
test("z.coerce.boolean", () => {
|
||||
const a = z.coerce.boolean();
|
||||
// test booleans
|
||||
expect(z.parse(a, true)).toEqual(true);
|
||||
expect(z.parse(a, false)).toEqual(false);
|
||||
expect(z.parse(a, "true")).toEqual(true);
|
||||
expect(z.parse(a, "false")).toEqual(true);
|
||||
expect(z.parse(a, 1)).toEqual(true);
|
||||
expect(z.parse(a, 0)).toEqual(false);
|
||||
expect(z.parse(a, {})).toEqual(true);
|
||||
expect(z.parse(a, [])).toEqual(true);
|
||||
expect(z.parse(a, undefined)).toEqual(false);
|
||||
expect(z.parse(a, null)).toEqual(false);
|
||||
expect(z.parse(a, "")).toEqual(false);
|
||||
});
|
||||
|
||||
test("z.coerce.bigint", () => {
|
||||
const a = z.coerce.bigint();
|
||||
expect(z.parse(a, "123")).toEqual(BigInt(123));
|
||||
expect(z.parse(a, 123)).toEqual(BigInt(123));
|
||||
expect(() => z.parse(a, "abc")).toThrow();
|
||||
});
|
||||
|
||||
test("z.coerce.date", () => {
|
||||
const a = z.coerce.date();
|
||||
const date = new Date();
|
||||
expect(z.parse(a, date.toISOString())).toEqual(date);
|
||||
expect(z.parse(a, date.getTime())).toEqual(date);
|
||||
expect(() => z.parse(a, "invalid date")).toThrow();
|
||||
});
|
||||
|
||||
test("z.iso.datetime", () => {
|
||||
const d1 = "2021-01-01T00:00:00Z";
|
||||
const d2 = "2021-01-01T00:00:00.123Z";
|
||||
const d3 = "2021-01-01T00:00:00";
|
||||
const d4 = "2021-01-01T00:00:00+07:00";
|
||||
const d5 = "bad data";
|
||||
|
||||
// local: false, offset: false, precision: null
|
||||
const a = z.iso.datetime();
|
||||
expect(z.safeParse(a, d1).success).toEqual(true);
|
||||
expect(z.safeParse(a, d2).success).toEqual(true);
|
||||
expect(z.safeParse(a, d3).success).toEqual(false);
|
||||
expect(z.safeParse(a, d4).success).toEqual(false);
|
||||
expect(z.safeParse(a, d5).success).toEqual(false);
|
||||
|
||||
const b = z.iso.datetime({ local: true });
|
||||
expect(z.safeParse(b, d1).success).toEqual(true);
|
||||
expect(z.safeParse(b, d2).success).toEqual(true);
|
||||
expect(z.safeParse(b, d3).success).toEqual(true);
|
||||
expect(z.safeParse(b, d4).success).toEqual(false);
|
||||
expect(z.safeParse(b, d5).success).toEqual(false);
|
||||
|
||||
const c = z.iso.datetime({ offset: true });
|
||||
expect(z.safeParse(c, d1).success).toEqual(true);
|
||||
expect(z.safeParse(c, d2).success).toEqual(true);
|
||||
expect(z.safeParse(c, d3).success).toEqual(false);
|
||||
expect(z.safeParse(c, d4).success).toEqual(true);
|
||||
expect(z.safeParse(c, d5).success).toEqual(false);
|
||||
|
||||
const d = z.iso.datetime({ precision: 3 });
|
||||
expect(z.safeParse(d, d1).success).toEqual(false);
|
||||
expect(z.safeParse(d, d2).success).toEqual(true);
|
||||
expect(z.safeParse(d, d3).success).toEqual(false);
|
||||
expect(z.safeParse(d, d4).success).toEqual(false);
|
||||
expect(z.safeParse(d, d5).success).toEqual(false);
|
||||
});
|
||||
|
||||
test("z.iso.date", () => {
|
||||
const d1 = "2021-01-01";
|
||||
const d2 = "bad data";
|
||||
|
||||
const a = z.iso.date();
|
||||
expect(z.safeParse(a, d1).success).toEqual(true);
|
||||
expect(z.safeParse(a, d2).success).toEqual(false);
|
||||
|
||||
const b = z.string().check(z.iso.date());
|
||||
expect(z.safeParse(b, d1).success).toEqual(true);
|
||||
expect(z.safeParse(b, d2).success).toEqual(false);
|
||||
});
|
||||
|
||||
test("z.iso.time", () => {
|
||||
const d1 = "00:00:00";
|
||||
const d2 = "00:00:00.123";
|
||||
const d3 = "bad data";
|
||||
|
||||
const a = z.iso.time();
|
||||
expect(z.safeParse(a, d1).success).toEqual(true);
|
||||
expect(z.safeParse(a, d2).success).toEqual(true);
|
||||
expect(z.safeParse(a, d3).success).toEqual(false);
|
||||
|
||||
const b = z.iso.time({ precision: 3 });
|
||||
expect(z.safeParse(b, d1).success).toEqual(false);
|
||||
expect(z.safeParse(b, d2).success).toEqual(true);
|
||||
expect(z.safeParse(b, d3).success).toEqual(false);
|
||||
|
||||
const c = z.string().check(z.iso.time());
|
||||
expect(z.safeParse(c, d1).success).toEqual(true);
|
||||
expect(z.safeParse(c, d2).success).toEqual(true);
|
||||
expect(z.safeParse(c, d3).success).toEqual(false);
|
||||
});
|
||||
|
||||
test("z.iso.duration", () => {
|
||||
const d1 = "P3Y6M4DT12H30M5S";
|
||||
const d2 = "bad data";
|
||||
|
||||
const a = z.iso.duration();
|
||||
expect(z.safeParse(a, d1).success).toEqual(true);
|
||||
expect(z.safeParse(a, d2).success).toEqual(false);
|
||||
|
||||
const b = z.string().check(z.iso.duration());
|
||||
expect(z.safeParse(b, d1).success).toEqual(true);
|
||||
expect(z.safeParse(b, d2).success).toEqual(false);
|
||||
});
|
||||
|
||||
test("z.undefined", () => {
|
||||
const a = z.undefined();
|
||||
expect(z.parse(a, undefined)).toEqual(undefined);
|
||||
expect(() => z.parse(a, "undefined")).toThrow();
|
||||
});
|
||||
|
||||
test("z.null", () => {
|
||||
const a = z.null();
|
||||
expect(z.parse(a, null)).toEqual(null);
|
||||
expect(() => z.parse(a, "null")).toThrow();
|
||||
});
|
||||
|
||||
test("z.any", () => {
|
||||
const a = z.any();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, 123)).toEqual(123);
|
||||
expect(z.parse(a, true)).toEqual(true);
|
||||
expect(z.parse(a, null)).toEqual(null);
|
||||
expect(z.parse(a, undefined)).toEqual(undefined);
|
||||
z.parse(a, {});
|
||||
z.parse(a, []);
|
||||
z.parse(a, Symbol());
|
||||
z.parse(a, new Date());
|
||||
});
|
||||
|
||||
test("z.unknown", () => {
|
||||
const a = z.unknown();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, 123)).toEqual(123);
|
||||
expect(z.parse(a, true)).toEqual(true);
|
||||
expect(z.parse(a, null)).toEqual(null);
|
||||
expect(z.parse(a, undefined)).toEqual(undefined);
|
||||
z.parse(a, {});
|
||||
z.parse(a, []);
|
||||
z.parse(a, Symbol());
|
||||
z.parse(a, new Date());
|
||||
});
|
||||
|
||||
test("z.never", () => {
|
||||
const a = z.never();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
});
|
||||
|
||||
test("z.void", () => {
|
||||
const a = z.void();
|
||||
expect(z.parse(a, undefined)).toEqual(undefined);
|
||||
expect(() => z.parse(a, null)).toThrow();
|
||||
});
|
||||
|
||||
test("z.array", () => {
|
||||
const a = z.array(z.string());
|
||||
expect(z.parse(a, ["hello", "world"])).toEqual(["hello", "world"]);
|
||||
expect(() => z.parse(a, [123])).toThrow();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
});
|
||||
|
||||
test("z.union", () => {
|
||||
const a = z.union([z.string(), z.number()]);
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, 123)).toEqual(123);
|
||||
expect(() => z.parse(a, true)).toThrow();
|
||||
});
|
||||
|
||||
test("z.intersection", () => {
|
||||
const a = z.intersection(z.object({ a: z.string() }), z.object({ b: z.number() }));
|
||||
expect(z.parse(a, { a: "hello", b: 123 })).toEqual({ a: "hello", b: 123 });
|
||||
expect(() => z.parse(a, { a: "hello" })).toThrow();
|
||||
expect(() => z.parse(a, { b: 123 })).toThrow();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
});
|
||||
|
||||
test("z.tuple", () => {
|
||||
const a = z.tuple([z.string(), z.number()]);
|
||||
expect(z.parse(a, ["hello", 123])).toEqual(["hello", 123]);
|
||||
expect(() => z.parse(a, ["hello", "world"])).toThrow();
|
||||
expect(() => z.parse(a, [123, 456])).toThrow();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
|
||||
// tuple with rest
|
||||
const b = z.tuple([z.string(), z.number(), z.optional(z.string())], z.boolean());
|
||||
type b = z.output<typeof b>;
|
||||
|
||||
expectTypeOf<b>().toEqualTypeOf<[string, number, string?, ...boolean[]]>();
|
||||
const datas = [
|
||||
["hello", 123],
|
||||
["hello", 123, "world"],
|
||||
["hello", 123, "world", true],
|
||||
["hello", 123, "world", true, false, true],
|
||||
];
|
||||
for (const data of datas) {
|
||||
expect(z.parse(b, data)).toEqual(data);
|
||||
}
|
||||
|
||||
expect(() => z.parse(b, ["hello", 123, 123])).toThrow();
|
||||
expect(() => z.parse(b, ["hello", 123, "world", 123])).toThrow();
|
||||
|
||||
// tuple with readonly args
|
||||
const cArgs = [z.string(), z.number(), z.optional(z.string())] as const;
|
||||
const c = z.tuple(cArgs, z.boolean());
|
||||
type c = z.output<typeof c>;
|
||||
expectTypeOf<c>().toEqualTypeOf<[string, number, string?, ...boolean[]]>();
|
||||
// type c = z.output<typeof c>;
|
||||
});
|
||||
|
||||
test("z.record", () => {
|
||||
// record schema with enum keys
|
||||
const a = z.record(z.string(), z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<Record<string, string>>();
|
||||
|
||||
const b = z.record(z.union([z.string(), z.number(), z.symbol()]), z.string());
|
||||
type b = z.output<typeof b>;
|
||||
expectTypeOf<b>().toEqualTypeOf<Record<string | number | symbol, string>>();
|
||||
expect(z.parse(b, { a: "hello", 1: "world", [Symbol.for("asdf")]: "symbol" })).toEqual({
|
||||
a: "hello",
|
||||
1: "world",
|
||||
[Symbol.for("asdf")]: "symbol",
|
||||
});
|
||||
|
||||
// enum keys
|
||||
const c = z.record(z.enum(["a", "b", "c"]), z.string());
|
||||
type c = z.output<typeof c>;
|
||||
expectTypeOf<c>().toEqualTypeOf<Record<"a" | "b" | "c", string>>();
|
||||
expect(z.parse(c, { a: "hello", b: "world", c: "world" })).toEqual({
|
||||
a: "hello",
|
||||
b: "world",
|
||||
c: "world",
|
||||
});
|
||||
// missing keys
|
||||
expect(() => z.parse(c, { a: "hello", b: "world" })).toThrow();
|
||||
// extra keys
|
||||
expect(() => z.parse(c, { a: "hello", b: "world", c: "world", d: "world" })).toThrow();
|
||||
|
||||
// partial enum
|
||||
const d = z.record(z.enum(["a", "b"]).or(z.never()), z.string());
|
||||
type d = z.output<typeof d>;
|
||||
expectTypeOf<d>().toEqualTypeOf<Record<"a" | "b", string>>();
|
||||
});
|
||||
|
||||
test("z.map", () => {
|
||||
const a = z.map(z.string(), z.number());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<Map<string, number>>();
|
||||
expect(z.parse(a, new Map([["hello", 123]]))).toEqual(new Map([["hello", 123]]));
|
||||
expect(() => z.parse(a, new Map([["hello", "world"]]))).toThrow();
|
||||
expect(() => z.parse(a, new Map([[1243, "world"]]))).toThrow();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
|
||||
const r1 = z.safeParse(a, new Map([[123, 123]]));
|
||||
expect(r1.error?.issues[0].code).toEqual("invalid_type");
|
||||
expect(r1.error?.issues[0].path).toEqual([123]);
|
||||
|
||||
const r2: any = z.safeParse(a, new Map([[BigInt(123), 123]]));
|
||||
expect(r2.error!.issues[0].code).toEqual("invalid_key");
|
||||
expect(r2.error!.issues[0].path).toEqual([]);
|
||||
|
||||
const r3: any = z.safeParse(a, new Map([["hello", "world"]]));
|
||||
expect(r3.error!.issues[0].code).toEqual("invalid_type");
|
||||
expect(r3.error!.issues[0].path).toEqual(["hello"]);
|
||||
});
|
||||
|
||||
test("z.map invalid_element", () => {
|
||||
const a = z.map(z.bigint(), z.number());
|
||||
const r1 = z.safeParse(a, new Map([[BigInt(123), BigInt(123)]]));
|
||||
|
||||
expect(r1.error!.issues[0].code).toEqual("invalid_element");
|
||||
expect(r1.error!.issues[0].path).toEqual([]);
|
||||
});
|
||||
|
||||
test("z.map async", async () => {
|
||||
const a = z.map(z.string().check(z.refine(async () => true)), z.number().check(z.refine(async () => true)));
|
||||
const d1 = new Map([["hello", 123]]);
|
||||
expect(await z.parseAsync(a, d1)).toEqual(d1);
|
||||
|
||||
await expect(z.parseAsync(a, new Map([[123, 123]]))).rejects.toThrow();
|
||||
await expect(z.parseAsync(a, new Map([["hi", "world"]]))).rejects.toThrow();
|
||||
await expect(z.parseAsync(a, new Map([[1243, "world"]]))).rejects.toThrow();
|
||||
await expect(z.parseAsync(a, "hello")).rejects.toThrow();
|
||||
|
||||
const r = await z.safeParseAsync(a, new Map([[123, 123]]));
|
||||
expect(r.success).toEqual(false);
|
||||
expect(r.error!.issues[0].code).toEqual("invalid_type");
|
||||
expect(r.error!.issues[0].path).toEqual([123]);
|
||||
});
|
||||
|
||||
test("z.set", () => {
|
||||
const a = z.set(z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<Set<string>>();
|
||||
expect(z.parse(a, new Set(["hello", "world"]))).toEqual(new Set(["hello", "world"]));
|
||||
expect(() => z.parse(a, new Set([123]))).toThrow();
|
||||
expect(() => z.parse(a, ["hello", "world"])).toThrow();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
|
||||
const b = z.set(z.number());
|
||||
expect(z.parse(b, new Set([1, 2, 3]))).toEqual(new Set([1, 2, 3]));
|
||||
expect(() => z.parse(b, new Set(["hello"]))).toThrow();
|
||||
expect(() => z.parse(b, [1, 2, 3])).toThrow();
|
||||
expect(() => z.parse(b, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.enum", () => {
|
||||
const a = z.enum(["A", "B", "C"]);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<"A" | "B" | "C">();
|
||||
expect(z.parse(a, "A")).toEqual("A");
|
||||
expect(z.parse(a, "B")).toEqual("B");
|
||||
expect(z.parse(a, "C")).toEqual("C");
|
||||
expect(() => z.parse(a, "D")).toThrow();
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
|
||||
expect(a.enum.A).toEqual("A");
|
||||
expect(a.enum.B).toEqual("B");
|
||||
expect(a.enum.C).toEqual("C");
|
||||
expect((a.enum as any).D).toEqual(undefined);
|
||||
});
|
||||
|
||||
test("z.enum - native", () => {
|
||||
enum NativeEnum {
|
||||
A = "A",
|
||||
B = "B",
|
||||
C = "C",
|
||||
}
|
||||
const a = z.enum(NativeEnum);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<NativeEnum>();
|
||||
expect(z.parse(a, NativeEnum.A)).toEqual(NativeEnum.A);
|
||||
expect(z.parse(a, NativeEnum.B)).toEqual(NativeEnum.B);
|
||||
expect(z.parse(a, NativeEnum.C)).toEqual(NativeEnum.C);
|
||||
expect(() => z.parse(a, "D")).toThrow();
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
|
||||
// test a.enum
|
||||
a;
|
||||
expect(a.enum.A).toEqual(NativeEnum.A);
|
||||
expect(a.enum.B).toEqual(NativeEnum.B);
|
||||
expect(a.enum.C).toEqual(NativeEnum.C);
|
||||
});
|
||||
|
||||
test("z.nativeEnum", () => {
|
||||
enum NativeEnum {
|
||||
A = "A",
|
||||
B = "B",
|
||||
C = "C",
|
||||
}
|
||||
const a = z.nativeEnum(NativeEnum);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<NativeEnum>();
|
||||
expect(z.parse(a, NativeEnum.A)).toEqual(NativeEnum.A);
|
||||
expect(z.parse(a, NativeEnum.B)).toEqual(NativeEnum.B);
|
||||
expect(z.parse(a, NativeEnum.C)).toEqual(NativeEnum.C);
|
||||
expect(() => z.parse(a, "D")).toThrow();
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
|
||||
// test a.enum
|
||||
a;
|
||||
expect(a.enum.A).toEqual(NativeEnum.A);
|
||||
expect(a.enum.B).toEqual(NativeEnum.B);
|
||||
expect(a.enum.C).toEqual(NativeEnum.C);
|
||||
});
|
||||
|
||||
test("z.literal", () => {
|
||||
const a = z.literal("hello");
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<"hello">();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(() => z.parse(a, "world")).toThrow();
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.file", () => {
|
||||
const a = z.file();
|
||||
const file = new File(["content"], "filename.txt", { type: "text/plain" });
|
||||
expect(z.parse(a, file)).toEqual(file);
|
||||
expect(() => z.parse(a, "file")).toThrow();
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.transform", () => {
|
||||
const a = z.pipe(
|
||||
z.string(),
|
||||
z.transform((val) => val.toUpperCase())
|
||||
);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
expect(z.parse(a, "hello")).toEqual("HELLO");
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.transform async", async () => {
|
||||
const a = z.pipe(
|
||||
z.string(),
|
||||
z.transform(async (val) => val.toUpperCase())
|
||||
);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
expect(await z.parseAsync(a, "hello")).toEqual("HELLO");
|
||||
await expect(() => z.parseAsync(a, 123)).rejects.toThrow();
|
||||
});
|
||||
|
||||
test("z.preprocess", () => {
|
||||
const a = z.pipe(
|
||||
z.transform((val) => String(val).toUpperCase()),
|
||||
z.string()
|
||||
);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
expect(z.parse(a, 123)).toEqual("123");
|
||||
expect(z.parse(a, true)).toEqual("TRUE");
|
||||
expect(z.parse(a, BigInt(1234))).toEqual("1234");
|
||||
// expect(() => z.parse(a, Symbol("asdf"))).toThrow();
|
||||
});
|
||||
|
||||
// test("z.preprocess async", () => {
|
||||
// const a = z.preprocess(async (val) => String(val), z.string());
|
||||
// type a = z.output<typeof a>;
|
||||
// expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
// expect(z.parse(a, 123)).toEqual("123");
|
||||
// expect(z.parse(a, true)).toEqual("true");
|
||||
// expect(() => z.parse(a, {})).toThrow();
|
||||
// });
|
||||
|
||||
test("z.optional", () => {
|
||||
const a = z.optional(z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string | undefined>();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, undefined)).toEqual(undefined);
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.nullable", () => {
|
||||
const a = z.nullable(z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string | null>();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, null)).toEqual(null);
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.default", () => {
|
||||
const a = z._default(z.string(), "default");
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
expect(z.parse(a, undefined)).toEqual("default");
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
|
||||
const b = z._default(z.string(), () => "default");
|
||||
expect(z.parse(b, undefined)).toEqual("default");
|
||||
expect(z.parse(b, "hello")).toEqual("hello");
|
||||
expect(() => z.parse(b, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.catch", () => {
|
||||
const a = z.catch(z.string(), "default");
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, 123)).toEqual("default");
|
||||
|
||||
const b = z.catch(z.string(), () => "default");
|
||||
expect(z.parse(b, "hello")).toEqual("hello");
|
||||
expect(z.parse(b, 123)).toEqual("default");
|
||||
|
||||
const c = z.catch(z.string(), (ctx) => {
|
||||
return `${ctx.error.issues.length}issues`;
|
||||
});
|
||||
expect(z.parse(c, 1234)).toEqual("1issues");
|
||||
});
|
||||
|
||||
test("z.nan", () => {
|
||||
const a = z.nan();
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<number>();
|
||||
expect(z.parse(a, Number.NaN)).toEqual(Number.NaN);
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
expect(() => z.parse(a, "NaN")).toThrow();
|
||||
});
|
||||
|
||||
test("z.pipe", () => {
|
||||
const a = z.pipe(
|
||||
z.pipe(
|
||||
z.string(),
|
||||
z.transform((val) => val.length)
|
||||
),
|
||||
z.number()
|
||||
);
|
||||
type a_in = z.input<typeof a>;
|
||||
expectTypeOf<a_in>().toEqualTypeOf<string>();
|
||||
type a_out = z.output<typeof a>;
|
||||
expectTypeOf<a_out>().toEqualTypeOf<number>();
|
||||
|
||||
expect(z.parse(a, "123")).toEqual(3);
|
||||
expect(z.parse(a, "hello")).toEqual(5);
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.readonly", () => {
|
||||
const a = z.readonly(z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<Readonly<string>>();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.templateLiteral", () => {
|
||||
const a = z.templateLiteral([z.string(), z.number()]);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<`${string}${number}`>();
|
||||
expect(z.parse(a, "hello123")).toEqual("hello123");
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
|
||||
// multipart
|
||||
const b = z.templateLiteral([z.string(), z.number(), z.string()]);
|
||||
type b = z.output<typeof b>;
|
||||
expectTypeOf<b>().toEqualTypeOf<`${string}${number}${string}`>();
|
||||
expect(z.parse(b, "hello123world")).toEqual("hello123world");
|
||||
expect(z.parse(b, "123")).toEqual("123");
|
||||
expect(() => z.parse(b, "hello")).toThrow();
|
||||
expect(() => z.parse(b, 123)).toThrow();
|
||||
|
||||
// include boolean
|
||||
const c = z.templateLiteral([z.string(), z.boolean()]);
|
||||
type c = z.output<typeof c>;
|
||||
expectTypeOf<c>().toEqualTypeOf<`${string}${boolean}`>();
|
||||
expect(z.parse(c, "hellotrue")).toEqual("hellotrue");
|
||||
expect(z.parse(c, "hellofalse")).toEqual("hellofalse");
|
||||
expect(() => z.parse(c, "hello")).toThrow();
|
||||
expect(() => z.parse(c, 123)).toThrow();
|
||||
|
||||
// include literal prefix
|
||||
const d = z.templateLiteral([z.literal("hello"), z.number()]);
|
||||
type d = z.output<typeof d>;
|
||||
expectTypeOf<d>().toEqualTypeOf<`hello${number}`>();
|
||||
expect(z.parse(d, "hello123")).toEqual("hello123");
|
||||
expect(() => z.parse(d, 123)).toThrow();
|
||||
expect(() => z.parse(d, "world123")).toThrow();
|
||||
|
||||
// include literal union
|
||||
const e = z.templateLiteral([z.literal(["aa", "bb"]), z.number()]);
|
||||
type e = z.output<typeof e>;
|
||||
expectTypeOf<e>().toEqualTypeOf<`aa${number}` | `bb${number}`>();
|
||||
expect(z.parse(e, "aa123")).toEqual("aa123");
|
||||
expect(z.parse(e, "bb123")).toEqual("bb123");
|
||||
expect(() => z.parse(e, "cc123")).toThrow();
|
||||
expect(() => z.parse(e, 123)).toThrow();
|
||||
});
|
||||
|
||||
// this returns both a schema and a check
|
||||
test("z.custom schema", () => {
|
||||
const a = z.custom((val) => {
|
||||
return typeof val === "string";
|
||||
});
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.custom check", () => {
|
||||
// @ts-expect-error Inference not possible, use z.refine()
|
||||
z.date().check(z.custom((val) => val.getTime() > 0));
|
||||
});
|
||||
|
||||
test("z.check", () => {
|
||||
// this is a more flexible version of z.custom that accepts an arbitrary _parse logic
|
||||
// the function should return base.$ZodResult
|
||||
const a = z.any().check(
|
||||
z.check<string>((ctx) => {
|
||||
if (typeof ctx.value === "string") return;
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
origin: "custom",
|
||||
message: "Expected a string",
|
||||
input: ctx.value,
|
||||
});
|
||||
})
|
||||
);
|
||||
expect(z.safeParse(a, "hello")).toMatchObject({
|
||||
success: true,
|
||||
data: "hello",
|
||||
});
|
||||
expect(z.safeParse(a, 123)).toMatchObject({
|
||||
success: false,
|
||||
error: { issues: [{ code: "custom", message: "Expected a string" }] },
|
||||
});
|
||||
});
|
||||
|
||||
test("z.instanceof", () => {
|
||||
class A {}
|
||||
|
||||
const a = z.instanceof(A);
|
||||
expect(z.parse(a, new A())).toBeInstanceOf(A);
|
||||
expect(() => z.parse(a, {})).toThrow();
|
||||
});
|
||||
|
||||
test("z.refine", () => {
|
||||
const a = z.number().check(
|
||||
z.refine((val) => val > 3),
|
||||
z.refine((val) => val < 10)
|
||||
);
|
||||
expect(z.parse(a, 5)).toEqual(5);
|
||||
expect(() => z.parse(a, 2)).toThrow();
|
||||
expect(() => z.parse(a, 11)).toThrow();
|
||||
expect(() => z.parse(a, "hi")).toThrow();
|
||||
});
|
||||
|
||||
// test("z.superRefine", () => {
|
||||
// const a = z.number([
|
||||
// z.superRefine((val, ctx) => {
|
||||
// if (val < 3) {
|
||||
// return ctx.addIssue({
|
||||
// code: "custom",
|
||||
// origin: "custom",
|
||||
// message: "Too small",
|
||||
// input: val,
|
||||
// });
|
||||
// }
|
||||
// if (val > 10) {
|
||||
// return ctx.addIssue("Too big");
|
||||
// }
|
||||
// }),
|
||||
// ]);
|
||||
|
||||
// expect(z.parse(a, 5)).toEqual(5);
|
||||
// expect(() => z.parse(a, 2)).toThrow();
|
||||
// expect(() => z.parse(a, 11)).toThrow();
|
||||
// expect(() => z.parse(a, "hi")).toThrow();
|
||||
// });
|
||||
|
||||
test("z.transform", () => {
|
||||
const a = z.transform((val: number) => {
|
||||
return `${val}`;
|
||||
});
|
||||
type a_in = z.input<typeof a>;
|
||||
expectTypeOf<a_in>().toEqualTypeOf<number>();
|
||||
type a_out = z.output<typeof a>;
|
||||
expectTypeOf<a_out>().toEqualTypeOf<string>();
|
||||
expect(z.parse(a, 123)).toEqual("123");
|
||||
});
|
||||
|
||||
test("z.$brand()", () => {
|
||||
const a = z.string().brand<"my-brand">();
|
||||
type a = z.output<typeof a>;
|
||||
const branded = (_: a) => {};
|
||||
// @ts-expect-error
|
||||
branded("asdf");
|
||||
});
|
||||
|
||||
test("z.lazy", () => {
|
||||
const a = z.lazy(() => z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
// schema that validates JSON-like data
|
||||
test("z.json", () => {
|
||||
const a = z.json();
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<util.JSONType>();
|
||||
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, 123)).toEqual(123);
|
||||
expect(z.parse(a, true)).toEqual(true);
|
||||
expect(z.parse(a, null)).toEqual(null);
|
||||
expect(z.parse(a, {})).toEqual({});
|
||||
expect(z.parse(a, { a: "hello" })).toEqual({ a: "hello" });
|
||||
expect(z.parse(a, [1, 2, 3])).toEqual([1, 2, 3]);
|
||||
expect(z.parse(a, [{ a: "hello" }])).toEqual([{ a: "hello" }]);
|
||||
|
||||
// fail cases
|
||||
expect(() => z.parse(a, new Date())).toThrow();
|
||||
expect(() => z.parse(a, Symbol())).toThrow();
|
||||
expect(() => z.parse(a, { a: new Date() })).toThrow();
|
||||
expect(() => z.parse(a, undefined)).toThrow();
|
||||
expect(() => z.parse(a, { a: undefined })).toThrow();
|
||||
});
|
||||
|
||||
// promise
|
||||
test("z.promise", async () => {
|
||||
const a = z.promise(z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
|
||||
expect(await z.safeParseAsync(a, Promise.resolve("hello"))).toMatchObject({
|
||||
success: true,
|
||||
data: "hello",
|
||||
});
|
||||
expect(await z.safeParseAsync(a, Promise.resolve(123))).toMatchObject({
|
||||
success: false,
|
||||
});
|
||||
|
||||
const b = z.string();
|
||||
expect(() => z.parse(b, Promise.resolve("hello"))).toThrow();
|
||||
});
|
||||
// test("type assertions", () => {
|
||||
// const schema = z.pipe(
|
||||
// z.string(),
|
||||
// z.transform((val) => val.length)
|
||||
// );
|
||||
// schema.assertInput<string>();
|
||||
// // @ts-expect-error
|
||||
// schema.assertInput<number>();
|
||||
|
||||
// schema.assertOutput<number>();
|
||||
// // @ts-expect-error
|
||||
// schema.assertOutput<string>();
|
||||
// });
|
||||
|
||||
test("isPlainObject", () => {
|
||||
expect(z.core.util.isPlainObject({})).toEqual(true);
|
||||
expect(z.core.util.isPlainObject(Object.create(null))).toEqual(true);
|
||||
expect(z.core.util.isPlainObject([])).toEqual(false);
|
||||
expect(z.core.util.isPlainObject(new Date())).toEqual(false);
|
||||
expect(z.core.util.isPlainObject(null)).toEqual(false);
|
||||
expect(z.core.util.isPlainObject(undefined)).toEqual(false);
|
||||
expect(z.core.util.isPlainObject("string")).toEqual(false);
|
||||
expect(z.core.util.isPlainObject(123)).toEqual(false);
|
||||
expect(z.core.util.isPlainObject(Symbol())).toEqual(false);
|
||||
});
|
||||
|
||||
test("def typing", () => {
|
||||
z.string().def.type satisfies "string";
|
||||
z.number().def.type satisfies "number";
|
||||
z.bigint().def.type satisfies "bigint";
|
||||
z.boolean().def.type satisfies "boolean";
|
||||
z.date().def.type satisfies "date";
|
||||
z.symbol().def.type satisfies "symbol";
|
||||
z.undefined().def.type satisfies "undefined";
|
||||
z.string().nullable().def.type satisfies "nullable";
|
||||
z.null().def.type satisfies "null";
|
||||
z.any().def.type satisfies "any";
|
||||
z.unknown().def.type satisfies "unknown";
|
||||
z.never().def.type satisfies "never";
|
||||
z.void().def.type satisfies "void";
|
||||
z.array(z.string()).def.type satisfies "array";
|
||||
z.object({ key: z.string() }).def.type satisfies "object";
|
||||
z.union([z.string(), z.number()]).def.type satisfies "union";
|
||||
z.intersection(z.string(), z.number()).def.type satisfies "intersection";
|
||||
z.tuple([z.string(), z.number()]).def.type satisfies "tuple";
|
||||
z.record(z.string(), z.number()).def.type satisfies "record";
|
||||
z.map(z.string(), z.number()).def.type satisfies "map";
|
||||
z.set(z.string()).def.type satisfies "set";
|
||||
z.literal("example").def.type satisfies "literal";
|
||||
z.enum(["a", "b", "c"]).def.type satisfies "enum";
|
||||
z.promise(z.string()).def.type satisfies "promise";
|
||||
z.lazy(() => z.string()).def.type satisfies "lazy";
|
||||
z.string().optional().def.type satisfies "optional";
|
||||
z.string().default("default").def.type satisfies "default";
|
||||
z.templateLiteral([z.literal("a"), z.literal("b")]).def.type satisfies "template_literal";
|
||||
z.custom<string>((val) => typeof val === "string").def.type satisfies "custom";
|
||||
z.transform((val) => val as string).def.type satisfies "transform";
|
||||
z.string().optional().nonoptional().def.type satisfies "nonoptional";
|
||||
z.object({ key: z.string() }).readonly().def.type satisfies "readonly";
|
||||
z.nan().def.type satisfies "nan";
|
||||
z.unknown().pipe(z.number()).def.type satisfies "pipe";
|
||||
z.success(z.string()).def.type satisfies "success";
|
||||
z.string().catch("fallback").def.type satisfies "catch";
|
||||
z.file().def.type satisfies "file";
|
||||
});
|
||||
34
node_modules/zod/src/v4/classic/tests/instanceof.test.ts
generated
vendored
Normal file
34
node_modules/zod/src/v4/classic/tests/instanceof.test.ts
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("instanceof", async () => {
|
||||
class Test {}
|
||||
class Subtest extends Test {}
|
||||
abstract class AbstractBar {
|
||||
constructor(public val: string) {}
|
||||
}
|
||||
class Bar extends AbstractBar {}
|
||||
|
||||
const TestSchema = z.instanceof(Test);
|
||||
const SubtestSchema = z.instanceof(Subtest);
|
||||
const AbstractSchema = z.instanceof(AbstractBar);
|
||||
const BarSchema = z.instanceof(Bar);
|
||||
|
||||
TestSchema.parse(new Test());
|
||||
TestSchema.parse(new Subtest());
|
||||
SubtestSchema.parse(new Subtest());
|
||||
AbstractSchema.parse(new Bar("asdf"));
|
||||
const bar = BarSchema.parse(new Bar("asdf"));
|
||||
expect(bar.val).toEqual("asdf");
|
||||
|
||||
await expect(() => SubtestSchema.parse(new Test())).toThrow();
|
||||
await expect(() => TestSchema.parse(12)).toThrow();
|
||||
|
||||
expectTypeOf<Test>().toEqualTypeOf<z.infer<typeof TestSchema>>();
|
||||
});
|
||||
|
||||
test("instanceof fatal", () => {
|
||||
const schema = z.instanceof(Date).refine((d) => d.toString());
|
||||
const res = schema.safeParse(null);
|
||||
expect(res.success).toBe(false);
|
||||
});
|
||||
171
node_modules/zod/src/v4/classic/tests/intersection.test.ts
generated
vendored
Normal file
171
node_modules/zod/src/v4/classic/tests/intersection.test.ts
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import type { util } from "zod/v4/core";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("object intersection", () => {
|
||||
const A = z.object({ a: z.string() });
|
||||
const B = z.object({ b: z.string() });
|
||||
|
||||
const C = z.intersection(A, B); // BaseC.merge(HasID);
|
||||
type C = z.infer<typeof C>;
|
||||
expectTypeOf<C>().toEqualTypeOf<{ a: string } & { b: string }>();
|
||||
const data = { a: "foo", b: "foo" };
|
||||
expect(C.parse(data)).toEqual(data);
|
||||
expect(() => C.parse({ a: "foo" })).toThrow();
|
||||
});
|
||||
|
||||
test("object intersection: loose", () => {
|
||||
const A = z.looseObject({ a: z.string() });
|
||||
const B = z.object({ b: z.string() });
|
||||
|
||||
const C = z.intersection(A, B); // BaseC.merge(HasID);
|
||||
type C = z.infer<typeof C>;
|
||||
expectTypeOf<C>().toEqualTypeOf<{ a: string; [x: string]: unknown } & { b: string }>();
|
||||
const data = { a: "foo", b: "foo", c: "extra" };
|
||||
expect(C.parse(data)).toEqual(data);
|
||||
expect(() => C.parse({ a: "foo" })).toThrow();
|
||||
});
|
||||
|
||||
test("object intersection: strict", () => {
|
||||
const A = z.strictObject({ a: z.string() });
|
||||
const B = z.object({ b: z.string() });
|
||||
|
||||
const C = z.intersection(A, B); // BaseC.merge(HasID);
|
||||
type C = z.infer<typeof C>;
|
||||
expectTypeOf<C>().toEqualTypeOf<{ a: string } & { b: string }>();
|
||||
const data = { a: "foo", b: "foo", c: "extra" };
|
||||
|
||||
const result = C.safeParse(data);
|
||||
expect(result.success).toEqual(false);
|
||||
});
|
||||
|
||||
test("deep intersection", () => {
|
||||
const Animal = z.object({
|
||||
properties: z.object({
|
||||
is_animal: z.boolean(),
|
||||
}),
|
||||
});
|
||||
const Cat = z.intersection(
|
||||
z.object({
|
||||
properties: z.object({
|
||||
jumped: z.boolean(),
|
||||
}),
|
||||
}),
|
||||
Animal
|
||||
);
|
||||
|
||||
type Cat = util.Flatten<z.infer<typeof Cat>>;
|
||||
expectTypeOf<Cat>().toEqualTypeOf<{ properties: { is_animal: boolean } & { jumped: boolean } }>();
|
||||
const a = Cat.safeParse({ properties: { is_animal: true, jumped: true } });
|
||||
expect(a.data!.properties).toEqual({ is_animal: true, jumped: true });
|
||||
});
|
||||
|
||||
test("deep intersection of arrays", async () => {
|
||||
const Author = z.object({
|
||||
posts: z.array(
|
||||
z.object({
|
||||
post_id: z.number(),
|
||||
})
|
||||
),
|
||||
});
|
||||
const Registry = z.intersection(
|
||||
Author,
|
||||
z.object({
|
||||
posts: z.array(
|
||||
z.object({
|
||||
title: z.string(),
|
||||
})
|
||||
),
|
||||
})
|
||||
);
|
||||
|
||||
const posts = [
|
||||
{ post_id: 1, title: "Novels" },
|
||||
{ post_id: 2, title: "Fairy tales" },
|
||||
];
|
||||
const cat = Registry.parse({ posts });
|
||||
expect(cat.posts).toEqual(posts);
|
||||
const asyncCat = await Registry.parseAsync({ posts });
|
||||
expect(asyncCat.posts).toEqual(posts);
|
||||
});
|
||||
|
||||
test("invalid intersection types", async () => {
|
||||
const numberIntersection = z.intersection(
|
||||
z.number(),
|
||||
z.number().transform((x) => x + 1)
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
numberIntersection.parse(1234);
|
||||
}).toThrowErrorMatchingInlineSnapshot(`[Error: Unmergable intersection. Error path: []]`);
|
||||
});
|
||||
|
||||
test("invalid array merge (incompatible lengths)", async () => {
|
||||
const stringArrInt = z.intersection(
|
||||
z.string().array(),
|
||||
z
|
||||
.string()
|
||||
.array()
|
||||
.transform((val) => [...val, "asdf"])
|
||||
);
|
||||
|
||||
expect(() => stringArrInt.safeParse(["asdf", "qwer"])).toThrowErrorMatchingInlineSnapshot(
|
||||
`[Error: Unmergable intersection. Error path: []]`
|
||||
);
|
||||
});
|
||||
|
||||
test("invalid array merge (incompatible elements)", async () => {
|
||||
const stringArrInt = z.intersection(
|
||||
z.string().array(),
|
||||
z
|
||||
.string()
|
||||
.array()
|
||||
.transform((val) => [...val.slice(0, -1), "asdf"])
|
||||
);
|
||||
|
||||
expect(() => stringArrInt.safeParse(["asdf", "qwer"])).toThrowErrorMatchingInlineSnapshot(
|
||||
`[Error: Unmergable intersection. Error path: [1]]`
|
||||
);
|
||||
});
|
||||
|
||||
test("invalid object merge", async () => {
|
||||
const Cat = z.object({
|
||||
phrase: z.string().transform((val) => `${val} Meow`),
|
||||
});
|
||||
const Dog = z.object({
|
||||
phrase: z.string().transform((val) => `${val} Woof`),
|
||||
});
|
||||
const CatDog = z.intersection(Cat, Dog);
|
||||
|
||||
expect(() => CatDog.parse({ phrase: "Hello, my name is CatDog." })).toThrowErrorMatchingInlineSnapshot(
|
||||
`[Error: Unmergable intersection. Error path: ["phrase"]]`
|
||||
);
|
||||
});
|
||||
|
||||
test("invalid deep merge of object and array combination", async () => {
|
||||
const University = z.object({
|
||||
students: z.array(
|
||||
z.object({
|
||||
name: z.string().transform((val) => `Student name: ${val}`),
|
||||
})
|
||||
),
|
||||
});
|
||||
const Registry = z.intersection(
|
||||
University,
|
||||
z.object({
|
||||
students: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
surname: z.string(),
|
||||
})
|
||||
),
|
||||
})
|
||||
);
|
||||
|
||||
const students = [{ name: "John", surname: "Doe" }];
|
||||
|
||||
expect(() => Registry.parse({ students })).toThrowErrorMatchingInlineSnapshot(
|
||||
`[Error: Unmergable intersection. Error path: ["students",0,"name"]]`
|
||||
);
|
||||
});
|
||||
108
node_modules/zod/src/v4/classic/tests/json.test.ts
generated
vendored
Normal file
108
node_modules/zod/src/v4/classic/tests/json.test.ts
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
import { test } from "vitest";
|
||||
// import * as z from "zod/v4";
|
||||
|
||||
test(() => {});
|
||||
// test("overload types", () => {
|
||||
// const schema = z.string().json();
|
||||
// util.assertEqual<typeof schema, z.ZodString>(true);
|
||||
// const schema2 = z.string().json(z.number());
|
||||
// util.assertEqual<typeof schema2, z.ZodPipe<z.ZodTransform<any, string>, z.ZodNumber>>(true);
|
||||
// const r2 = schema2.parse("12");
|
||||
// util.assertEqual<number, typeof r2>(true);
|
||||
// });
|
||||
// test("parse string to json", async () => {
|
||||
// const Env = z.object({
|
||||
// myJsonConfig: z.string().jsonString(z.object({ foo: z.number() })),
|
||||
// someOtherValue: z.string(),
|
||||
// });
|
||||
|
||||
// expect(
|
||||
// Env.parse({
|
||||
// myJsonConfig: '{ "foo": 123 }',
|
||||
// someOtherValue: "abc",
|
||||
// })
|
||||
// ).toEqual({
|
||||
// myJsonConfig: { foo: 123 },
|
||||
// someOtherValue: "abc",
|
||||
// });
|
||||
|
||||
// const invalidValues = Env.safeParse({
|
||||
// myJsonConfig: '{"foo": "not a number!"}',
|
||||
// someOtherValue: null,
|
||||
// });
|
||||
// expect(JSON.parse(JSON.stringify(invalidValues))).toEqual({
|
||||
// success: false,
|
||||
// error: {
|
||||
// name: "ZodError",
|
||||
// issues: [
|
||||
// {
|
||||
// code: "invalid_type",
|
||||
// expected: "number",
|
||||
// input: "not a number!",
|
||||
// received: "string",
|
||||
// path: ["myJsonConfig", "foo"],
|
||||
// message: "Expected number, received string",
|
||||
// },
|
||||
// {
|
||||
// code: "invalid_type",
|
||||
// expected: "string",
|
||||
// input: null,
|
||||
// received: "null",
|
||||
// path: ["someOtherValue"],
|
||||
// message: "Expected string, received null",
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// });
|
||||
|
||||
// const invalidJsonSyntax = Env.safeParse({
|
||||
// myJsonConfig: "This is not valid json",
|
||||
// someOtherValue: null,
|
||||
// });
|
||||
// expect(JSON.parse(JSON.stringify(invalidJsonSyntax))).toMatchObject({
|
||||
// success: false,
|
||||
// error: {
|
||||
// name: "ZodError",
|
||||
// issues: [
|
||||
// {
|
||||
// code: "invalid_string",
|
||||
// input: {
|
||||
// _def: {
|
||||
// catchall: {
|
||||
// _def: {
|
||||
// typeName: "ZodNever",
|
||||
// },
|
||||
// },
|
||||
// typeName: "ZodObject",
|
||||
// unknownKeys: "strip",
|
||||
// },
|
||||
// },
|
||||
// validation: "json",
|
||||
// message: "Invalid json",
|
||||
// path: ["myJsonConfig"],
|
||||
// },
|
||||
// {
|
||||
// code: "invalid_type",
|
||||
// expected: "string",
|
||||
// input: null,
|
||||
// received: "null",
|
||||
// path: ["someOtherValue"],
|
||||
// message: "Expected string, received null",
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// });
|
||||
// });
|
||||
|
||||
// test("no argument", () => {
|
||||
// const schema = z.string().json();
|
||||
// util.assertEqual<typeof schema, z.ZodString>(true);
|
||||
// z.string().json().parse(`{}`);
|
||||
// z.string().json().parse(`null`);
|
||||
// z.string().json().parse(`12`);
|
||||
// z.string().json().parse(`{ "test": "test"}`);
|
||||
// expect(() => z.string().json().parse(`asdf`)).toThrow();
|
||||
// expect(() => z.string().json().parse(`{ "test": undefined }`)).toThrow();
|
||||
// expect(() => z.string().json().parse(`{ "test": 12n }`)).toThrow();
|
||||
// expect(() => z.string().json().parse(`{ test: "test" }`)).toThrow();
|
||||
// });
|
||||
227
node_modules/zod/src/v4/classic/tests/lazy.test.ts
generated
vendored
Normal file
227
node_modules/zod/src/v4/classic/tests/lazy.test.ts
generated
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("opt passthrough", () => {
|
||||
const object = z.object({
|
||||
a: z.lazy(() => z.string()),
|
||||
b: z.lazy(() => z.string().optional()),
|
||||
c: z.lazy(() => z.string().default("default")),
|
||||
});
|
||||
|
||||
type ObjectTypeIn = z.input<typeof object>;
|
||||
expectTypeOf<ObjectTypeIn>().toEqualTypeOf<{
|
||||
a: string;
|
||||
b?: string | undefined;
|
||||
c?: string | undefined;
|
||||
}>();
|
||||
|
||||
type ObjectTypeOut = z.output<typeof object>;
|
||||
expectTypeOf<ObjectTypeOut>().toEqualTypeOf<{
|
||||
a: string;
|
||||
b?: string | undefined;
|
||||
c: string;
|
||||
}>();
|
||||
|
||||
const result = object.parse(
|
||||
{
|
||||
a: "hello",
|
||||
b: undefined,
|
||||
},
|
||||
{ jitless: true }
|
||||
);
|
||||
expect(result).toEqual({
|
||||
a: "hello",
|
||||
// b: undefined,
|
||||
c: "default",
|
||||
});
|
||||
|
||||
expect(z.lazy(() => z.string())._zod.optin).toEqual(undefined);
|
||||
expect(z.lazy(() => z.string())._zod.optout).toEqual(undefined);
|
||||
|
||||
expect(z.lazy(() => z.string().optional())._zod.optin).toEqual("optional");
|
||||
expect(z.lazy(() => z.string().optional())._zod.optout).toEqual("optional");
|
||||
|
||||
expect(z.lazy(() => z.string().default("asdf"))._zod.optin).toEqual("optional");
|
||||
expect(z.lazy(() => z.string().default("asdf"))._zod.optout).toEqual(undefined);
|
||||
});
|
||||
|
||||
////////////// LAZY //////////////
|
||||
|
||||
test("schema getter", () => {
|
||||
z.lazy(() => z.string()).parse("asdf");
|
||||
});
|
||||
|
||||
test("lazy proxy", () => {
|
||||
const schema = z.lazy(() => z.string())._zod.innerType.min(6);
|
||||
schema.parse("123456");
|
||||
expect(schema.safeParse("12345").success).toBe(false);
|
||||
});
|
||||
|
||||
interface Category {
|
||||
name: string;
|
||||
subcategories: Category[];
|
||||
}
|
||||
|
||||
const testCategory: Category = {
|
||||
name: "I",
|
||||
subcategories: [
|
||||
{
|
||||
name: "A",
|
||||
subcategories: [
|
||||
{
|
||||
name: "1",
|
||||
subcategories: [
|
||||
{
|
||||
name: "a",
|
||||
subcategories: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
test("recursion with z.lazy", () => {
|
||||
const Category: z.ZodType<Category> = z.lazy(() =>
|
||||
z.object({
|
||||
name: z.string(),
|
||||
subcategories: z.array(Category),
|
||||
})
|
||||
);
|
||||
Category.parse(testCategory);
|
||||
});
|
||||
|
||||
type LinkedList = null | { value: number; next: LinkedList };
|
||||
|
||||
const linkedListExample = {
|
||||
value: 1,
|
||||
next: {
|
||||
value: 2,
|
||||
next: {
|
||||
value: 3,
|
||||
next: {
|
||||
value: 4,
|
||||
next: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
test("recursive union wit z.lazy", () => {
|
||||
const LinkedListSchema: z.ZodType<LinkedList> = z.lazy(() =>
|
||||
z.union([
|
||||
z.null(),
|
||||
z.object({
|
||||
value: z.number(),
|
||||
next: LinkedListSchema,
|
||||
}),
|
||||
])
|
||||
);
|
||||
LinkedListSchema.parse(linkedListExample);
|
||||
});
|
||||
|
||||
interface A {
|
||||
val: number;
|
||||
b: B;
|
||||
}
|
||||
|
||||
interface B {
|
||||
val: number;
|
||||
a?: A | undefined;
|
||||
}
|
||||
|
||||
test("mutual recursion with lazy", () => {
|
||||
const Alazy: z.ZodType<A> = z.lazy(() =>
|
||||
z.object({
|
||||
val: z.number(),
|
||||
b: Blazy,
|
||||
})
|
||||
);
|
||||
|
||||
const Blazy: z.ZodType<B> = z.lazy(() =>
|
||||
z.object({
|
||||
val: z.number(),
|
||||
a: Alazy.optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const testData = {
|
||||
val: 1,
|
||||
b: {
|
||||
val: 5,
|
||||
a: {
|
||||
val: 3,
|
||||
b: {
|
||||
val: 4,
|
||||
a: {
|
||||
val: 2,
|
||||
b: {
|
||||
val: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Alazy.parse(testData);
|
||||
Blazy.parse(testData.b);
|
||||
|
||||
expect(() => Alazy.parse({ val: "asdf" })).toThrow();
|
||||
});
|
||||
|
||||
// TODO
|
||||
test("mutual recursion with cyclical data", () => {
|
||||
const a: any = { val: 1 };
|
||||
const b: any = { val: 2 };
|
||||
a.b = b;
|
||||
b.a = a;
|
||||
});
|
||||
|
||||
test("complicated self-recursion", () => {
|
||||
const Category = z.object({
|
||||
name: z.string(),
|
||||
age: z.optional(z.number()),
|
||||
get nullself() {
|
||||
return Category.nullable();
|
||||
},
|
||||
get optself() {
|
||||
return Category.optional();
|
||||
},
|
||||
get self() {
|
||||
return Category;
|
||||
},
|
||||
get subcategories() {
|
||||
return z.array(Category);
|
||||
},
|
||||
nested: z.object({
|
||||
get sub() {
|
||||
return Category;
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
type _Category = z.output<typeof Category>;
|
||||
});
|
||||
|
||||
test("lazy initialization", () => {
|
||||
const a: any = z.lazy(() => a).optional();
|
||||
const b: any = z.lazy(() => b).nullable();
|
||||
const c: any = z.lazy(() => c).default({} as any);
|
||||
const d: any = z.lazy(() => d).prefault({} as any);
|
||||
const e: any = z.lazy(() => e).nonoptional();
|
||||
const f: any = z.lazy(() => f).catch({} as any);
|
||||
const g: any = z.lazy(() => z.object({ g })).readonly();
|
||||
|
||||
const baseCategorySchema = z.object({
|
||||
name: z.string(),
|
||||
});
|
||||
type Category = z.infer<typeof baseCategorySchema> & {
|
||||
subcategories: Category[];
|
||||
};
|
||||
const categorySchema: z.ZodType<Category> = baseCategorySchema.extend({
|
||||
subcategories: z.lazy(() => categorySchema.array()),
|
||||
});
|
||||
});
|
||||
92
node_modules/zod/src/v4/classic/tests/literal.test.ts
generated
vendored
Normal file
92
node_modules/zod/src/v4/classic/tests/literal.test.ts
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const literalTuna = z.literal("tuna");
|
||||
const literalTunaCustomMessage = z.literal("tuna", {
|
||||
message: "That's not a tuna",
|
||||
});
|
||||
const literalFortyTwo = z.literal(42);
|
||||
const literalTrue = z.literal(true);
|
||||
|
||||
test("passing validations", () => {
|
||||
literalTuna.parse("tuna");
|
||||
literalFortyTwo.parse(42);
|
||||
literalTrue.parse(true);
|
||||
});
|
||||
|
||||
test("failing validations", () => {
|
||||
expect(() => literalTuna.parse("shark")).toThrow();
|
||||
expect(() => literalFortyTwo.parse(43)).toThrow();
|
||||
expect(() => literalTrue.parse(false)).toThrow();
|
||||
});
|
||||
|
||||
test("invalid_literal should have `input` field with data", () => {
|
||||
const data = "shark";
|
||||
const result = literalTuna.safeParse(data);
|
||||
|
||||
const issue = result.error!.issues[0];
|
||||
expect(issue.code).toBe("invalid_value");
|
||||
expect(issue).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"message": "Invalid input: expected "tuna"",
|
||||
"path": [],
|
||||
"values": [
|
||||
"tuna",
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("invalid_literal should return default message", () => {
|
||||
const data = "shark";
|
||||
const result = literalTuna.safeParse(data);
|
||||
|
||||
const issue = result.error!.issues[0];
|
||||
expect(issue.message).toEqual(`Invalid input: expected \"tuna\"`);
|
||||
});
|
||||
|
||||
test("invalid_literal should return custom message", () => {
|
||||
const data = "shark";
|
||||
const result = literalTunaCustomMessage.safeParse(data);
|
||||
|
||||
const issue = result.error!.issues[0];
|
||||
expect(issue.message).toEqual(`That's not a tuna`);
|
||||
});
|
||||
|
||||
test("literal default error message", () => {
|
||||
const result = z.literal("Tuna").safeParse("Trout");
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"Tuna"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid input: expected \\"Tuna\\""
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("literal bigint default error message", () => {
|
||||
const result = z.literal(BigInt(12)).safeParse(BigInt(13));
|
||||
expect(result.success).toBe(false);
|
||||
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error!.issues[0].message).toEqual(`Invalid input: expected 12n`);
|
||||
});
|
||||
|
||||
test(".value getter", () => {
|
||||
expect(z.literal("tuna").value).toEqual("tuna");
|
||||
expect(() => z.literal([1, 2, 3]).value).toThrow();
|
||||
});
|
||||
|
||||
test("readonly", () => {
|
||||
const a = ["asdf"] as const;
|
||||
z.literal(a);
|
||||
});
|
||||
196
node_modules/zod/src/v4/classic/tests/map.test.ts
generated
vendored
Normal file
196
node_modules/zod/src/v4/classic/tests/map.test.ts
generated
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const stringMap = z.map(z.string(), z.string());
|
||||
type stringMap = z.infer<typeof stringMap>;
|
||||
|
||||
test("type inference", () => {
|
||||
expectTypeOf<stringMap>().toEqualTypeOf<Map<string, string>>();
|
||||
});
|
||||
|
||||
test("valid parse", () => {
|
||||
const result = stringMap.safeParse(
|
||||
new Map([
|
||||
["first", "foo"],
|
||||
["second", "bar"],
|
||||
])
|
||||
);
|
||||
expect(result.success).toEqual(true);
|
||||
expect(result.data).toMatchInlineSnapshot(`
|
||||
Map {
|
||||
"first" => "foo",
|
||||
"second" => "bar",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("valid parse async", async () => {
|
||||
const asyncMap = z.map(
|
||||
z.string().refine(async () => false, "bad key"),
|
||||
z.string().refine(async () => false, "bad value")
|
||||
);
|
||||
const result = await asyncMap.safeParseAsync(new Map([["first", "foo"]]));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"first"
|
||||
],
|
||||
"message": "bad key"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"first"
|
||||
],
|
||||
"message": "bad value"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("throws when a Set is given", () => {
|
||||
const result = stringMap.safeParse(new Set([]));
|
||||
expect(result.success).toEqual(false);
|
||||
if (result.success === false) {
|
||||
expect(result.error.issues.length).toEqual(1);
|
||||
expect(result.error.issues[0].code).toEqual("invalid_type");
|
||||
}
|
||||
});
|
||||
|
||||
test("throws when the given map has invalid key and invalid input", () => {
|
||||
const result = stringMap.safeParse(new Map([[42, Symbol()]]));
|
||||
expect(result.success).toEqual(false);
|
||||
if (result.success === false) {
|
||||
expect(result.error.issues.length).toEqual(2);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
42
|
||||
],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
42
|
||||
],
|
||||
"message": "Invalid input: expected string, received symbol"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("throws when the given map has multiple invalid entries", () => {
|
||||
// const result = stringMap.safeParse(new Map([[42, Symbol()]]));
|
||||
|
||||
const result = stringMap.safeParse(
|
||||
new Map([
|
||||
[1, "foo"],
|
||||
["bar", 2],
|
||||
] as [any, any][]) as Map<any, any>
|
||||
);
|
||||
|
||||
// const result = stringMap.safeParse(new Map([[42, Symbol()]]));
|
||||
expect(result.success).toEqual(false);
|
||||
if (result.success === false) {
|
||||
expect(result.error.issues.length).toEqual(2);
|
||||
expect(result.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received number",
|
||||
"path": [
|
||||
1,
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received number",
|
||||
"path": [
|
||||
"bar",
|
||||
],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("dirty", async () => {
|
||||
const map = z.map(
|
||||
z.string().refine((val) => val === val.toUpperCase(), {
|
||||
message: "Keys must be uppercase",
|
||||
}),
|
||||
z.string()
|
||||
);
|
||||
const result = await map.spa(
|
||||
new Map([
|
||||
["first", "foo"],
|
||||
["second", "bar"],
|
||||
])
|
||||
);
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(2);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"first"
|
||||
],
|
||||
"message": "Keys must be uppercase"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"second"
|
||||
],
|
||||
"message": "Keys must be uppercase"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("map with object keys", () => {
|
||||
const map = z.map(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
}),
|
||||
z.string()
|
||||
);
|
||||
const data = new Map([
|
||||
[{ name: "John", age: 30 }, "foo"],
|
||||
[{ name: "Jane", age: 25 }, "bar"],
|
||||
]);
|
||||
const result = map.safeParse(data);
|
||||
expect(result.success).toEqual(true);
|
||||
expect(result.data!).toEqual(data);
|
||||
|
||||
const badData = new Map([["bad", "foo"]]);
|
||||
const badResult = map.safeParse(badData);
|
||||
expect(badResult.success).toEqual(false);
|
||||
expect(badResult.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "object",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"bad"
|
||||
],
|
||||
"message": "Invalid input: expected object, received string"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
21
node_modules/zod/src/v4/classic/tests/nan.test.ts
generated
vendored
Normal file
21
node_modules/zod/src/v4/classic/tests/nan.test.ts
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const schema = z.nan();
|
||||
|
||||
test("passing validations", () => {
|
||||
schema.parse(Number.NaN);
|
||||
schema.parse(Number("Not a number"));
|
||||
expectTypeOf<typeof schema._output>().toEqualTypeOf<number>();
|
||||
});
|
||||
|
||||
test("failing validations", () => {
|
||||
expect(() => schema.parse(5)).toThrow();
|
||||
expect(() => schema.parse("John")).toThrow();
|
||||
expect(() => schema.parse(true)).toThrow();
|
||||
expect(() => schema.parse(null)).toThrow();
|
||||
expect(() => schema.parse(undefined)).toThrow();
|
||||
expect(() => schema.parse({})).toThrow();
|
||||
expect(() => schema.parse([])).toThrow();
|
||||
});
|
||||
168
node_modules/zod/src/v4/classic/tests/nested-refine.test.ts
generated
vendored
Normal file
168
node_modules/zod/src/v4/classic/tests/nested-refine.test.ts
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("nested refinements", () => {
|
||||
const zodSchema = z
|
||||
.object({
|
||||
password: z.string().min(1),
|
||||
nested: z
|
||||
.object({
|
||||
confirm: z
|
||||
.string()
|
||||
.min(1)
|
||||
.refine((value) => value.length > 2, {
|
||||
message: "Confirm length should be > 2",
|
||||
}),
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
return data.confirm === "bar";
|
||||
},
|
||||
{
|
||||
path: ["confirm"],
|
||||
error: 'Value must be "bar"',
|
||||
}
|
||||
),
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
return data.nested.confirm === data.password;
|
||||
},
|
||||
{
|
||||
path: ["nested", "confirm"],
|
||||
error: "Password and confirm must match",
|
||||
}
|
||||
);
|
||||
|
||||
const DATA = {
|
||||
password: "bar",
|
||||
nested: { confirm: "" },
|
||||
};
|
||||
expect(zodSchema.safeParse(DATA)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 1,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Too small: expected string to have >=1 characters"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Confirm length should be > 2"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Value must be \\"bar\\""
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Password and confirm must match"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(zodSchema.safeParse(DATA, { jitless: true })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 1,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Too small: expected string to have >=1 characters"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Confirm length should be > 2"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Value must be \\"bar\\""
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Password and confirm must match"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(zodSchema["~standard"].validate(DATA)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"issues": [
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected string to have >=1 characters",
|
||||
"minimum": 1,
|
||||
"origin": "string",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Confirm length should be > 2",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Value must be "bar"",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Password and confirm must match",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
86
node_modules/zod/src/v4/classic/tests/nonoptional.test.ts
generated
vendored
Normal file
86
node_modules/zod/src/v4/classic/tests/nonoptional.test.ts
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
test("nonoptional", () => {
|
||||
const schema = z.string().nonoptional();
|
||||
expectTypeOf<typeof schema._input>().toEqualTypeOf<string>();
|
||||
expectTypeOf<typeof schema._output>().toEqualTypeOf<string>();
|
||||
|
||||
const result = schema.safeParse(undefined);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("nonoptional with default", () => {
|
||||
const schema = z.string().optional().nonoptional();
|
||||
expectTypeOf<typeof schema._input>().toEqualTypeOf<string>();
|
||||
expectTypeOf<typeof schema._output>().toEqualTypeOf<string>();
|
||||
|
||||
const result = schema.safeParse(undefined);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "nonoptional",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected nonoptional, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("nonoptional in object", () => {
|
||||
const schema = z.object({ hi: z.string().optional().nonoptional() });
|
||||
|
||||
expectTypeOf<typeof schema._input>().toEqualTypeOf<{ hi: string }>();
|
||||
expectTypeOf<typeof schema._output>().toEqualTypeOf<{ hi: string }>();
|
||||
const r1 = schema.safeParse({ hi: "asdf" });
|
||||
expect(r1.success).toEqual(true);
|
||||
|
||||
const r2 = schema.safeParse({ hi: undefined });
|
||||
// expect(schema.safeParse({ hi: undefined }).success).toEqual(false);
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "nonoptional",
|
||||
"path": [
|
||||
"hi"
|
||||
],
|
||||
"message": "Invalid input: expected nonoptional, received undefined"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const r3 = schema.safeParse({});
|
||||
expect(r3.success).toEqual(false);
|
||||
expect(r3.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "nonoptional",
|
||||
"path": [
|
||||
"hi"
|
||||
],
|
||||
"message": "Invalid input: expected nonoptional, received undefined"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
22
node_modules/zod/src/v4/classic/tests/nullable.test.ts
generated
vendored
Normal file
22
node_modules/zod/src/v4/classic/tests/nullable.test.ts
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test(".nullable()", () => {
|
||||
const nullable = z.string().nullable();
|
||||
expect(nullable.parse(null)).toBe(null);
|
||||
expect(nullable.parse("asdf")).toBe("asdf");
|
||||
expect(() => nullable.parse(123)).toThrow();
|
||||
});
|
||||
|
||||
test(".nullable unwrap", () => {
|
||||
const schema = z.string().nullable();
|
||||
expect(schema).toBeInstanceOf(z.ZodNullable);
|
||||
expect(schema.unwrap()).toBeInstanceOf(z.ZodString);
|
||||
});
|
||||
|
||||
test("z.null", () => {
|
||||
const n = z.null();
|
||||
expect(n.parse(null)).toBe(null);
|
||||
expect(() => n.parse("asdf")).toThrow();
|
||||
});
|
||||
247
node_modules/zod/src/v4/classic/tests/number.test.ts
generated
vendored
Normal file
247
node_modules/zod/src/v4/classic/tests/number.test.ts
generated
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("z.number() basic validation", () => {
|
||||
const schema = z.number();
|
||||
expect(schema.parse(1234)).toEqual(1234);
|
||||
});
|
||||
|
||||
test("NaN validation", () => {
|
||||
const schema = z.number();
|
||||
expect(() => schema.parse(Number.NaN)).toThrow();
|
||||
});
|
||||
|
||||
test("Infinity validation", () => {
|
||||
const schema = z.number();
|
||||
expect(schema.safeParse(Number.POSITIVE_INFINITY)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"received": "Infinity",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected number, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse(Number.NEGATIVE_INFINITY)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"received": "Infinity",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected number, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test(".gt() validation", () => {
|
||||
const schema = z.number().gt(0).gt(5);
|
||||
expect(schema.parse(6)).toEqual(6);
|
||||
expect(() => schema.parse(5)).toThrow();
|
||||
});
|
||||
|
||||
test(".gte() validation", () => {
|
||||
const schema = z.number().gt(0).gte(1).gte(5);
|
||||
expect(schema.parse(5)).toEqual(5);
|
||||
expect(() => schema.parse(4)).toThrow();
|
||||
});
|
||||
|
||||
test(".min() validation", () => {
|
||||
const schema = z.number().min(0).min(5);
|
||||
expect(schema.parse(5)).toEqual(5);
|
||||
expect(() => schema.parse(4)).toThrow();
|
||||
});
|
||||
|
||||
test(".lt() validation", () => {
|
||||
const schema = z.number().lte(10).lt(5);
|
||||
expect(schema.parse(4)).toEqual(4);
|
||||
expect(() => schema.parse(5)).toThrow();
|
||||
});
|
||||
|
||||
test(".lte() validation", () => {
|
||||
const schema = z.number().lte(10).lte(5);
|
||||
expect(schema.parse(5)).toEqual(5);
|
||||
expect(() => schema.parse(6)).toThrow();
|
||||
});
|
||||
|
||||
test(".max() validation", () => {
|
||||
const schema = z.number().max(10).max(5);
|
||||
expect(schema.parse(5)).toEqual(5);
|
||||
expect(() => schema.parse(6)).toThrow();
|
||||
});
|
||||
|
||||
test(".int() validation", () => {
|
||||
const schema = z.number().int();
|
||||
expect(schema.parse(4)).toEqual(4);
|
||||
expect(() => schema.parse(3.14)).toThrow();
|
||||
});
|
||||
|
||||
test(".positive() validation", () => {
|
||||
const schema = z.number().positive();
|
||||
expect(schema.parse(1)).toEqual(1);
|
||||
expect(() => schema.parse(0)).toThrow();
|
||||
expect(() => schema.parse(-1)).toThrow();
|
||||
});
|
||||
|
||||
test(".negative() validation", () => {
|
||||
const schema = z.number().negative();
|
||||
expect(schema.parse(-1)).toEqual(-1);
|
||||
expect(() => schema.parse(0)).toThrow();
|
||||
expect(() => schema.parse(1)).toThrow();
|
||||
});
|
||||
|
||||
test(".nonpositive() validation", () => {
|
||||
const schema = z.number().nonpositive();
|
||||
expect(schema.parse(0)).toEqual(0);
|
||||
expect(schema.parse(-1)).toEqual(-1);
|
||||
expect(() => schema.parse(1)).toThrow();
|
||||
});
|
||||
|
||||
test(".nonnegative() validation", () => {
|
||||
const schema = z.number().nonnegative();
|
||||
expect(schema.parse(0)).toEqual(0);
|
||||
expect(schema.parse(1)).toEqual(1);
|
||||
expect(() => schema.parse(-1)).toThrow();
|
||||
});
|
||||
|
||||
test(".multipleOf() with positive divisor", () => {
|
||||
const schema = z.number().multipleOf(5);
|
||||
expect(schema.parse(15)).toEqual(15);
|
||||
expect(schema.parse(-15)).toEqual(-15);
|
||||
expect(() => schema.parse(7.5)).toThrow();
|
||||
expect(() => schema.parse(-7.5)).toThrow();
|
||||
});
|
||||
|
||||
test(".multipleOf() with negative divisor", () => {
|
||||
const schema = z.number().multipleOf(-5);
|
||||
expect(schema.parse(-15)).toEqual(-15);
|
||||
expect(schema.parse(15)).toEqual(15);
|
||||
expect(() => schema.parse(-7.5)).toThrow();
|
||||
expect(() => schema.parse(7.5)).toThrow();
|
||||
});
|
||||
|
||||
test(".step() validation", () => {
|
||||
const schemaPointOne = z.number().step(0.1);
|
||||
const schemaPointZeroZeroZeroOne = z.number().step(0.0001);
|
||||
const schemaSixPointFour = z.number().step(6.4);
|
||||
|
||||
expect(schemaPointOne.parse(6)).toEqual(6);
|
||||
expect(schemaPointOne.parse(6.1)).toEqual(6.1);
|
||||
expect(schemaSixPointFour.parse(12.8)).toEqual(12.8);
|
||||
expect(schemaPointZeroZeroZeroOne.parse(3.01)).toEqual(3.01);
|
||||
expect(() => schemaPointOne.parse(6.11)).toThrow();
|
||||
expect(() => schemaPointOne.parse(6.1000000001)).toThrow();
|
||||
expect(() => schemaSixPointFour.parse(6.41)).toThrow();
|
||||
});
|
||||
|
||||
test(".finite() validation", () => {
|
||||
const schema = z.number().finite();
|
||||
expect(schema.parse(123)).toEqual(123);
|
||||
expect(schema.safeParse(Number.POSITIVE_INFINITY)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"received": "Infinity",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected number, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse(Number.NEGATIVE_INFINITY)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"received": "Infinity",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected number, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test(".safe() validation", () => {
|
||||
const schema = z.number().safe();
|
||||
expect(schema.parse(Number.MIN_SAFE_INTEGER)).toEqual(Number.MIN_SAFE_INTEGER);
|
||||
expect(schema.parse(Number.MAX_SAFE_INTEGER)).toEqual(Number.MAX_SAFE_INTEGER);
|
||||
expect(() => schema.parse(Number.MIN_SAFE_INTEGER - 1)).toThrow();
|
||||
expect(() => schema.parse(Number.MAX_SAFE_INTEGER + 1)).toThrow();
|
||||
});
|
||||
|
||||
test("min value getters", () => {
|
||||
expect(z.number().minValue).toBeNull;
|
||||
expect(z.number().lt(5).minValue).toBeNull;
|
||||
expect(z.number().lte(5).minValue).toBeNull;
|
||||
expect(z.number().max(5).minValue).toBeNull;
|
||||
expect(z.number().negative().minValue).toBeNull;
|
||||
expect(z.number().nonpositive().minValue).toBeNull;
|
||||
expect(z.number().int().minValue).toBeNull;
|
||||
expect(z.number().multipleOf(5).minValue).toBeNull;
|
||||
expect(z.number().finite().minValue).toBeNull;
|
||||
expect(z.number().gt(5).minValue).toEqual(5);
|
||||
expect(z.number().gte(5).minValue).toEqual(5);
|
||||
expect(z.number().min(5).minValue).toEqual(5);
|
||||
expect(z.number().min(5).min(10).minValue).toEqual(10);
|
||||
expect(z.number().positive().minValue).toEqual(0);
|
||||
expect(z.number().nonnegative().minValue).toEqual(0);
|
||||
expect(z.number().safe().minValue).toEqual(Number.MIN_SAFE_INTEGER);
|
||||
});
|
||||
|
||||
test("max value getters", () => {
|
||||
expect(z.number().maxValue).toBeNull;
|
||||
expect(z.number().gt(5).maxValue).toBeNull;
|
||||
expect(z.number().gte(5).maxValue).toBeNull;
|
||||
expect(z.number().min(5).maxValue).toBeNull;
|
||||
expect(z.number().positive().maxValue).toBeNull;
|
||||
expect(z.number().nonnegative().maxValue).toBeNull;
|
||||
expect(z.number().int().minValue).toBeNull;
|
||||
expect(z.number().multipleOf(5).minValue).toBeNull;
|
||||
expect(z.number().finite().minValue).toBeNull;
|
||||
expect(z.number().lt(5).maxValue).toEqual(5);
|
||||
expect(z.number().lte(5).maxValue).toEqual(5);
|
||||
expect(z.number().max(5).maxValue).toEqual(5);
|
||||
expect(z.number().max(5).max(1).maxValue).toEqual(1);
|
||||
expect(z.number().negative().maxValue).toEqual(0);
|
||||
expect(z.number().nonpositive().maxValue).toEqual(0);
|
||||
expect(z.number().safe().maxValue).toEqual(Number.MAX_SAFE_INTEGER);
|
||||
});
|
||||
|
||||
test("int getter", () => {
|
||||
expect(z.number().isInt).toEqual(false);
|
||||
expect(z.number().int().isInt).toEqual(true);
|
||||
expect(z.number().safe().isInt).toEqual(true);
|
||||
expect(z.number().multipleOf(5).isInt).toEqual(true);
|
||||
});
|
||||
|
||||
/** In Zod 4, number schemas don't accept infinite values. */
|
||||
test("finite getter", () => {
|
||||
expect(z.number().isFinite).toEqual(true);
|
||||
});
|
||||
|
||||
test("string format methods", () => {
|
||||
const a = z.int32().min(5);
|
||||
expect(a.parse(6)).toEqual(6);
|
||||
expect(() => a.parse(1)).toThrow();
|
||||
});
|
||||
|
||||
test("error customization", () => {
|
||||
z.number().gte(5, { error: (iss) => "Min: " + iss.minimum.valueOf() });
|
||||
z.number().lte(5, { error: (iss) => "Max: " + iss.maximum.valueOf() });
|
||||
});
|
||||
563
node_modules/zod/src/v4/classic/tests/object.test.ts
generated
vendored
Normal file
563
node_modules/zod/src/v4/classic/tests/object.test.ts
generated
vendored
Normal file
@@ -0,0 +1,563 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
import * as core from "zod/v4/core";
|
||||
|
||||
const Test = z.object({
|
||||
f1: z.number(),
|
||||
f2: z.string().optional(),
|
||||
f3: z.string().nullable(),
|
||||
f4: z.array(z.object({ t: z.union([z.string(), z.boolean()]) })),
|
||||
});
|
||||
|
||||
test("object type inference", () => {
|
||||
type TestType = {
|
||||
f1: number;
|
||||
f2?: string | undefined;
|
||||
f3: string | null;
|
||||
f4: { t: string | boolean }[];
|
||||
};
|
||||
|
||||
expectTypeOf<z.TypeOf<typeof Test>>().toEqualTypeOf<TestType>();
|
||||
});
|
||||
|
||||
test("unknown throw", () => {
|
||||
const asdf: unknown = 35;
|
||||
expect(() => Test.parse(asdf)).toThrow();
|
||||
});
|
||||
|
||||
test("shape() should return schema of particular key", () => {
|
||||
const f1Schema = Test.shape.f1;
|
||||
const f2Schema = Test.shape.f2;
|
||||
const f3Schema = Test.shape.f3;
|
||||
const f4Schema = Test.shape.f4;
|
||||
|
||||
expect(f1Schema).toBeInstanceOf(z.ZodNumber);
|
||||
expect(f2Schema).toBeInstanceOf(z.ZodOptional);
|
||||
expect(f3Schema).toBeInstanceOf(z.ZodNullable);
|
||||
expect(f4Schema).toBeInstanceOf(z.ZodArray);
|
||||
});
|
||||
|
||||
test("correct parsing", () => {
|
||||
Test.parse({
|
||||
f1: 12,
|
||||
f2: "string",
|
||||
f3: "string",
|
||||
f4: [
|
||||
{
|
||||
t: "string",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Test.parse({
|
||||
f1: 12,
|
||||
f3: null,
|
||||
f4: [
|
||||
{
|
||||
t: false,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test("nonstrict by default", () => {
|
||||
z.object({ points: z.number() }).parse({
|
||||
points: 2314,
|
||||
unknown: "asdf",
|
||||
});
|
||||
});
|
||||
|
||||
test("parse optional keys ", () => {
|
||||
const schema = z.object({
|
||||
a: z.string().optional(),
|
||||
});
|
||||
expect(schema.parse({ a: "asdf" })).toEqual({ a: "asdf" });
|
||||
});
|
||||
|
||||
test("empty object", () => {
|
||||
const schema = z.object({});
|
||||
expect(schema.parse({})).toEqual({});
|
||||
expect(schema.parse({ name: "asdf" })).toEqual({});
|
||||
expect(schema.safeParse(null).success).toEqual(false);
|
||||
expect(schema.safeParse("asdf").success).toEqual(false);
|
||||
expectTypeOf<z.output<typeof schema>>().toEqualTypeOf<Record<string, never>>();
|
||||
});
|
||||
|
||||
const data = {
|
||||
points: 2314,
|
||||
unknown: "asdf",
|
||||
};
|
||||
|
||||
test("strip by default", () => {
|
||||
const val = z.object({ points: z.number() }).parse(data);
|
||||
expect(val).toEqual({ points: 2314 });
|
||||
});
|
||||
|
||||
test("unknownkeys override", () => {
|
||||
const val = z.object({ points: z.number() }).strict().passthrough().strip().passthrough().parse(data);
|
||||
|
||||
expect(val).toEqual(data);
|
||||
});
|
||||
|
||||
test("passthrough unknown", () => {
|
||||
const val = z.object({ points: z.number() }).passthrough().parse(data);
|
||||
|
||||
expect(val).toEqual(data);
|
||||
});
|
||||
|
||||
test("strip unknown", () => {
|
||||
const val = z.object({ points: z.number() }).strip().parse(data);
|
||||
|
||||
expect(val).toEqual({ points: 2314 });
|
||||
});
|
||||
|
||||
test("strict", () => {
|
||||
const val = z.object({ points: z.number() }).strict().safeParse(data);
|
||||
|
||||
expect(val.success).toEqual(false);
|
||||
});
|
||||
|
||||
test("catchall inference", () => {
|
||||
const o1 = z
|
||||
.object({
|
||||
first: z.string(),
|
||||
})
|
||||
.catchall(z.number());
|
||||
|
||||
const d1 = o1.parse({ first: "asdf", num: 1243 });
|
||||
// expectTypeOf<(typeof d1)["asdf"]>().toEqualTypeOf<number>();
|
||||
expectTypeOf<(typeof d1)["first"]>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("catchall overrides strict", () => {
|
||||
const o1 = z.object({ first: z.string().optional() }).strict().catchall(z.number());
|
||||
|
||||
// should run fine
|
||||
// setting a catchall overrides the unknownKeys behavior
|
||||
o1.parse({
|
||||
asdf: 1234,
|
||||
});
|
||||
|
||||
// should only run catchall validation
|
||||
// against unknown keys
|
||||
o1.parse({
|
||||
first: "asdf",
|
||||
asdf: 1234,
|
||||
});
|
||||
});
|
||||
|
||||
test("catchall overrides strict", () => {
|
||||
const o1 = z
|
||||
.object({
|
||||
first: z.string(),
|
||||
})
|
||||
.strict()
|
||||
.catchall(z.number());
|
||||
|
||||
// should run fine
|
||||
// setting a catchall overrides the unknownKeys behavior
|
||||
o1.parse({
|
||||
first: "asdf",
|
||||
asdf: 1234,
|
||||
});
|
||||
});
|
||||
|
||||
test("optional keys are unset", async () => {
|
||||
const SNamedEntity = z.object({
|
||||
id: z.string(),
|
||||
set: z.string().optional(),
|
||||
unset: z.string().optional(),
|
||||
});
|
||||
const result = await SNamedEntity.parse({
|
||||
id: "asdf",
|
||||
set: undefined,
|
||||
});
|
||||
expect(Object.keys(result)).toEqual(["id", "set"]);
|
||||
});
|
||||
|
||||
test("catchall parsing", async () => {
|
||||
const result = z.object({ name: z.string() }).catchall(z.number()).parse({ name: "Foo", validExtraKey: 61 });
|
||||
|
||||
expect(result).toEqual({ name: "Foo", validExtraKey: 61 });
|
||||
|
||||
const result2 = z
|
||||
.object({ name: z.string() })
|
||||
.catchall(z.number())
|
||||
.safeParse({ name: "Foo", validExtraKey: 61, invalid: "asdf" });
|
||||
|
||||
expect(result2.success).toEqual(false);
|
||||
});
|
||||
|
||||
test("nonexistent keys", async () => {
|
||||
const Schema = z.union([z.object({ a: z.string() }), z.object({ b: z.number() })]);
|
||||
const obj = { a: "A" };
|
||||
const result = await Schema.spa(obj); // Works with 1.11.10, breaks with 2.0.0-beta.21
|
||||
expect(result.success).toBe(true);
|
||||
});
|
||||
|
||||
test("test async union", async () => {
|
||||
const Schema2 = z.union([
|
||||
z.object({
|
||||
ty: z.string(),
|
||||
}),
|
||||
z.object({
|
||||
ty: z.number(),
|
||||
}),
|
||||
]);
|
||||
|
||||
const obj = { ty: "A" };
|
||||
const result = await Schema2.spa(obj); // Works with 1.11.10, breaks with 2.0.0-beta.21
|
||||
expect(result.success).toEqual(true);
|
||||
});
|
||||
|
||||
test("test inferred merged type", async () => {
|
||||
const asdf = z.object({ a: z.string() }).merge(z.object({ a: z.number() }));
|
||||
type asdf = z.infer<typeof asdf>;
|
||||
|
||||
expectTypeOf<asdf>().toEqualTypeOf<{ a: number }>();
|
||||
});
|
||||
|
||||
test("inferred type with Record shape", () => {
|
||||
type A = z.ZodObject<Record<string, z.ZodType<string, number>>>;
|
||||
expectTypeOf<z.infer<A>>().toEqualTypeOf<Record<string, string>>();
|
||||
expectTypeOf<z.input<A>>().toEqualTypeOf<Record<string, number>>();
|
||||
|
||||
type B = z.ZodObject;
|
||||
expectTypeOf<z.infer<B>>().toEqualTypeOf<Record<string, unknown>>();
|
||||
expectTypeOf<z.input<B>>().toEqualTypeOf<Record<string, unknown>>();
|
||||
});
|
||||
|
||||
test("inferred merged object type with optional properties", async () => {
|
||||
const Merged = z
|
||||
.object({ a: z.string(), b: z.string().optional() })
|
||||
.merge(z.object({ a: z.string().optional(), b: z.string() }));
|
||||
type Merged = z.infer<typeof Merged>;
|
||||
expectTypeOf<Merged>().toEqualTypeOf<{ a?: string; b: string }>();
|
||||
expectTypeOf<Merged>().toEqualTypeOf<{ a?: string; b: string }>();
|
||||
});
|
||||
|
||||
test("inferred unioned object type with optional properties", async () => {
|
||||
const Unioned = z.union([
|
||||
z.object({ a: z.string(), b: z.string().optional() }),
|
||||
z.object({ a: z.string().optional(), b: z.string() }),
|
||||
]);
|
||||
type Unioned = z.infer<typeof Unioned>;
|
||||
expectTypeOf<Unioned>().toEqualTypeOf<{ a: string; b?: string } | { a?: string; b: string }>();
|
||||
});
|
||||
|
||||
test("inferred enum type", async () => {
|
||||
const Enum = z.object({ a: z.string(), b: z.string().optional() }).keyof();
|
||||
|
||||
expect(Enum.enum).toEqual({
|
||||
a: "a",
|
||||
b: "b",
|
||||
});
|
||||
|
||||
expect(Enum._zod.def.entries).toEqual({
|
||||
a: "a",
|
||||
b: "b",
|
||||
});
|
||||
type Enum = z.infer<typeof Enum>;
|
||||
expectTypeOf<Enum>().toEqualTypeOf<"a" | "b">();
|
||||
});
|
||||
|
||||
test("inferred partial object type with optional properties", async () => {
|
||||
const Partial = z.object({ a: z.string(), b: z.string().optional() }).partial();
|
||||
type Partial = z.infer<typeof Partial>;
|
||||
expectTypeOf<Partial>().toEqualTypeOf<{ a?: string; b?: string }>();
|
||||
});
|
||||
|
||||
test("inferred picked object type with optional properties", async () => {
|
||||
const Picked = z.object({ a: z.string(), b: z.string().optional() }).pick({ b: true });
|
||||
type Picked = z.infer<typeof Picked>;
|
||||
expectTypeOf<Picked>().toEqualTypeOf<{ b?: string }>();
|
||||
});
|
||||
|
||||
test("inferred type for unknown/any keys", () => {
|
||||
const myType = z.object({
|
||||
anyOptional: z.any().optional(),
|
||||
anyRequired: z.any(),
|
||||
unknownOptional: z.unknown().optional(),
|
||||
unknownRequired: z.unknown(),
|
||||
});
|
||||
type myType = z.infer<typeof myType>;
|
||||
expectTypeOf<myType>().toEqualTypeOf<{
|
||||
anyOptional?: any;
|
||||
anyRequired: any;
|
||||
unknownOptional?: unknown;
|
||||
unknownRequired: unknown;
|
||||
}>();
|
||||
});
|
||||
|
||||
test("strictObject", async () => {
|
||||
const strictObj = z.strictObject({
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const syncResult = strictObj.safeParse({ name: "asdf", unexpected: 13 });
|
||||
expect(syncResult.success).toEqual(false);
|
||||
|
||||
const asyncResult = await strictObj.spa({ name: "asdf", unexpected: 13 });
|
||||
expect(asyncResult.success).toEqual(false);
|
||||
});
|
||||
|
||||
test("object with refine", async () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.string().default("foo"),
|
||||
b: z.number(),
|
||||
})
|
||||
.refine(() => true);
|
||||
expect(schema.parse({ b: 5 })).toEqual({ b: 5, a: "foo" });
|
||||
const result = await schema.parseAsync({ b: 5 });
|
||||
expect(result).toEqual({ b: 5, a: "foo" });
|
||||
});
|
||||
|
||||
test("intersection of object with date", async () => {
|
||||
const schema = z.object({
|
||||
a: z.date(),
|
||||
});
|
||||
expect(z.intersection(schema, schema).parse({ a: new Date(1637353595983) })).toEqual({
|
||||
a: new Date(1637353595983),
|
||||
});
|
||||
const result = await schema.parseAsync({ a: new Date(1637353595983) });
|
||||
expect(result).toEqual({ a: new Date(1637353595983) });
|
||||
});
|
||||
|
||||
test("intersection of object with refine with date", async () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.date(),
|
||||
})
|
||||
.refine(() => true);
|
||||
expect(z.intersection(schema, schema).parse({ a: new Date(1637353595983) })).toEqual({
|
||||
a: new Date(1637353595983),
|
||||
});
|
||||
const result = await schema.parseAsync({ a: new Date(1637353595983) });
|
||||
expect(result).toEqual({ a: new Date(1637353595983) });
|
||||
});
|
||||
|
||||
test("constructor key", () => {
|
||||
const person = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
expect(() =>
|
||||
person.parse({
|
||||
name: "bob dylan",
|
||||
constructor: 61,
|
||||
})
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
test("constructor key", () => {
|
||||
const Example = z.object({
|
||||
prop: z.string(),
|
||||
opt: z.number().optional(),
|
||||
arr: z.string().array(),
|
||||
});
|
||||
|
||||
type Example = z.infer<typeof Example>;
|
||||
expectTypeOf<keyof Example>().toEqualTypeOf<"prop" | "opt" | "arr">();
|
||||
});
|
||||
|
||||
test("catchall", () => {
|
||||
const a = z.object({});
|
||||
expect(a._zod.def.catchall).toBeUndefined();
|
||||
|
||||
const b = z.strictObject({});
|
||||
expect(b._zod.def.catchall).toBeInstanceOf(core.$ZodNever);
|
||||
|
||||
const c = z.looseObject({});
|
||||
expect(c._zod.def.catchall).toBeInstanceOf(core.$ZodUnknown);
|
||||
|
||||
const d = z.object({}).catchall(z.number());
|
||||
expect(d._zod.def.catchall).toBeInstanceOf(core.$ZodNumber);
|
||||
});
|
||||
|
||||
test("unknownkeys merging", () => {
|
||||
// This one is "strict"
|
||||
const a = z.looseObject({
|
||||
a: z.string(),
|
||||
});
|
||||
|
||||
const b = z.strictObject({ b: z.string() });
|
||||
|
||||
// incoming object overrides
|
||||
const c = a.merge(b);
|
||||
expect(c._zod.def.catchall).toBeInstanceOf(core.$ZodNever);
|
||||
});
|
||||
|
||||
const personToExtend = z.object({
|
||||
firstName: z.string(),
|
||||
lastName: z.string(),
|
||||
});
|
||||
|
||||
test("extend() should return schema with new key", () => {
|
||||
const PersonWithNickname = personToExtend.extend({ nickName: z.string() });
|
||||
type PersonWithNickname = z.infer<typeof PersonWithNickname>;
|
||||
|
||||
const expected = { firstName: "f", nickName: "n", lastName: "l" };
|
||||
const actual = PersonWithNickname.parse(expected);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
expectTypeOf<keyof PersonWithNickname>().toEqualTypeOf<"firstName" | "lastName" | "nickName">();
|
||||
expectTypeOf<PersonWithNickname>().toEqualTypeOf<{ firstName: string; lastName: string; nickName: string }>();
|
||||
});
|
||||
|
||||
test("extend() should have power to override existing key", () => {
|
||||
const PersonWithNumberAsLastName = personToExtend.extend({
|
||||
lastName: z.number(),
|
||||
});
|
||||
type PersonWithNumberAsLastName = z.infer<typeof PersonWithNumberAsLastName>;
|
||||
|
||||
const expected = { firstName: "f", lastName: 42 };
|
||||
const actual = PersonWithNumberAsLastName.parse(expected);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
expectTypeOf<PersonWithNumberAsLastName>().toEqualTypeOf<{ firstName: string; lastName: number }>();
|
||||
});
|
||||
|
||||
test("passthrough index signature", () => {
|
||||
const a = z.object({ a: z.string() });
|
||||
type a = z.infer<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<{ a: string }>();
|
||||
const b = a.passthrough();
|
||||
type b = z.infer<typeof b>;
|
||||
expectTypeOf<b>().toEqualTypeOf<{ a: string; [k: string]: unknown }>();
|
||||
});
|
||||
|
||||
// test("xor", () => {
|
||||
// type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
|
||||
// type XOR<T, U> = T extends object ? (U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : U) : T;
|
||||
|
||||
// type A = { name: string; a: number };
|
||||
// type B = { name: string; b: number };
|
||||
// type C = XOR<A, B>;
|
||||
// type Outer = { data: C };
|
||||
// const Outer = z.object({
|
||||
// data: z.union([z.object({ name: z.string(), a: z.number() }), z.object({ name: z.string(), b: z.number() })]),
|
||||
// }) satisfies z.ZodType<Outer, any>;
|
||||
// });
|
||||
|
||||
test("assignability", () => {
|
||||
z.object({ a: z.string() }) satisfies z.ZodObject<{ a: z.ZodString }>;
|
||||
z.object({ a: z.string() }).catchall(z.number()) satisfies z.ZodObject<{ a: z.ZodString }>;
|
||||
z.object({ a: z.string() }).strict() satisfies z.ZodObject;
|
||||
z.object({}) satisfies z.ZodObject;
|
||||
|
||||
z.looseObject({ name: z.string() }) satisfies z.ZodObject<
|
||||
{
|
||||
name: z.ZodString;
|
||||
},
|
||||
z.core.$loose
|
||||
>;
|
||||
z.looseObject({ name: z.string() }) satisfies z.ZodObject<{
|
||||
name: z.ZodString;
|
||||
}>;
|
||||
z.strictObject({ name: z.string() }) satisfies z.ZodObject<
|
||||
{
|
||||
name: z.ZodString;
|
||||
},
|
||||
z.core.$loose
|
||||
>;
|
||||
z.strictObject({ name: z.string() }) satisfies z.ZodObject<
|
||||
{
|
||||
name: z.ZodString;
|
||||
},
|
||||
z.core.$strict
|
||||
>;
|
||||
z.object({ name: z.string() }) satisfies z.ZodObject<{
|
||||
name: z.ZodString;
|
||||
}>;
|
||||
z.object({
|
||||
a: z.string(),
|
||||
b: z.number(),
|
||||
c: z.boolean(),
|
||||
}) satisfies z.core.$ZodObject;
|
||||
});
|
||||
|
||||
test("null prototype", () => {
|
||||
const schema = z.object({ a: z.string() });
|
||||
const obj = Object.create(null);
|
||||
obj.a = "foo";
|
||||
expect(schema.parse(obj)).toEqual({ a: "foo" });
|
||||
});
|
||||
|
||||
test("empty objects", () => {
|
||||
const A = z.looseObject({});
|
||||
type Ain = z.input<typeof A>;
|
||||
expectTypeOf<Ain>().toEqualTypeOf<Record<string, unknown>>();
|
||||
type Aout = z.output<typeof A>;
|
||||
expectTypeOf<Aout>().toEqualTypeOf<Record<string, unknown>>();
|
||||
|
||||
const B = z.object({});
|
||||
type Bout = z.output<typeof B>;
|
||||
expectTypeOf<Bout>().toEqualTypeOf<Record<string, never>>();
|
||||
type Bin = z.input<typeof B>;
|
||||
expectTypeOf<Bin>().toEqualTypeOf<Record<string, never>>();
|
||||
|
||||
const C = z.strictObject({});
|
||||
type Cout = z.output<typeof C>;
|
||||
expectTypeOf<Cout>().toEqualTypeOf<Record<string, never>>();
|
||||
type Cin = z.input<typeof C>;
|
||||
expectTypeOf<Cin>().toEqualTypeOf<Record<string, never>>();
|
||||
});
|
||||
|
||||
test("preserve key order", () => {
|
||||
const schema = z.object({
|
||||
a: z.string().optional(),
|
||||
b: z.string(),
|
||||
});
|
||||
const r1 = schema.safeParse({ a: "asdf", b: "qwer" });
|
||||
const r2 = schema.safeParse({ a: "asdf", b: "qwer" }, { jitless: true });
|
||||
|
||||
expect(Object.keys(r1.data!)).toMatchInlineSnapshot(`
|
||||
[
|
||||
"a",
|
||||
"b",
|
||||
]
|
||||
`);
|
||||
expect(Object.keys(r1.data!)).toEqual(Object.keys(r2.data!));
|
||||
});
|
||||
|
||||
test("empty shape", () => {
|
||||
const a = z.object({});
|
||||
|
||||
a.parse({});
|
||||
a.parse({}, { jitless: true });
|
||||
a.parse(Object.create(null));
|
||||
a.parse(Object.create(null), { jitless: true });
|
||||
|
||||
expect(() => a.parse([])).toThrow();
|
||||
expect(() => a.parse([], { jitless: true })).toThrow();
|
||||
});
|
||||
|
||||
test("zodtype assignability", () => {
|
||||
// Does not error
|
||||
z.object({ hello: z.string().optional() }) satisfies z.ZodType<{ hello?: string | undefined }>;
|
||||
z.object({ hello: z.string() }) satisfies z.ZodType<{ hello?: string | undefined }>;
|
||||
// @ts-expect-error
|
||||
z.object({}) satisfies z.ZodType<{ hello: string | undefined }>;
|
||||
// @ts-expect-error
|
||||
z.object({ hello: z.string().optional() }) satisfies z.ZodType<{ hello: string | undefined }>;
|
||||
// @ts-expect-error
|
||||
z.object({ hello: z.string().optional() }) satisfies z.ZodType<{ hello: string }>;
|
||||
// @ts-expect-error
|
||||
z.object({ hello: z.number() }) satisfies z.ZodType<{ hello?: string | undefined }>;
|
||||
});
|
||||
|
||||
test("index signature in shape", () => {
|
||||
function makeZodObj<const T extends string>(key: T) {
|
||||
return z.looseObject({
|
||||
[key]: z.string(),
|
||||
});
|
||||
}
|
||||
|
||||
const schema = makeZodObj("foo");
|
||||
type schema = z.infer<typeof schema>;
|
||||
|
||||
expectTypeOf<schema>().toEqualTypeOf<Record<string, string>>();
|
||||
});
|
||||
123
node_modules/zod/src/v4/classic/tests/optional.test.ts
generated
vendored
Normal file
123
node_modules/zod/src/v4/classic/tests/optional.test.ts
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
// @ts-ignore TS6133
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test(".optional()", () => {
|
||||
const schema = z.string().optional();
|
||||
expect(schema.parse("adsf")).toEqual("adsf");
|
||||
expect(schema.parse(undefined)).toEqual(undefined);
|
||||
expect(schema.safeParse(null).success).toEqual(false);
|
||||
|
||||
expectTypeOf<typeof schema._output>().toEqualTypeOf<string | undefined>();
|
||||
});
|
||||
|
||||
test("unwrap", () => {
|
||||
const unwrapped = z.string().optional().unwrap();
|
||||
expect(unwrapped).toBeInstanceOf(z.ZodString);
|
||||
});
|
||||
|
||||
test("optionality", () => {
|
||||
const a = z.string();
|
||||
expect(a._zod.optin).toEqual(undefined);
|
||||
expect(a._zod.optout).toEqual(undefined);
|
||||
|
||||
const b = z.string().optional();
|
||||
expect(b._zod.optin).toEqual("optional");
|
||||
expect(b._zod.optout).toEqual("optional");
|
||||
|
||||
const c = z.string().default("asdf");
|
||||
expect(c._zod.optin).toEqual("optional");
|
||||
expect(c._zod.optout).toEqual(undefined);
|
||||
|
||||
const d = z.string().optional().nullable();
|
||||
expect(d._zod.optin).toEqual("optional");
|
||||
expect(d._zod.optout).toEqual("optional");
|
||||
|
||||
const e = z.string().default("asdf").nullable();
|
||||
expect(e._zod.optin).toEqual("optional");
|
||||
expect(e._zod.optout).toEqual(undefined);
|
||||
|
||||
// z.undefined should NOT be optional
|
||||
const f = z.undefined();
|
||||
expect(f._zod.optin).toEqual("optional");
|
||||
expect(f._zod.optout).toEqual("optional");
|
||||
expectTypeOf<typeof f._zod.optin>().toEqualTypeOf<"optional" | undefined>();
|
||||
expectTypeOf<typeof f._zod.optout>().toEqualTypeOf<"optional" | undefined>();
|
||||
|
||||
// z.union should be optional if any of the types are optional
|
||||
const g = z.union([z.string(), z.undefined()]);
|
||||
expect(g._zod.optin).toEqual("optional");
|
||||
expect(g._zod.optout).toEqual("optional");
|
||||
expectTypeOf<typeof g._zod.optin>().toEqualTypeOf<"optional" | undefined>();
|
||||
expectTypeOf<typeof g._zod.optout>().toEqualTypeOf<"optional" | undefined>();
|
||||
|
||||
const h = z.union([z.string(), z.optional(z.string())]);
|
||||
expect(h._zod.optin).toEqual("optional");
|
||||
expect(h._zod.optout).toEqual("optional");
|
||||
expectTypeOf<typeof h._zod.optin>().toEqualTypeOf<"optional">();
|
||||
expectTypeOf<typeof h._zod.optout>().toEqualTypeOf<"optional">();
|
||||
});
|
||||
|
||||
test("pipe optionality", () => {
|
||||
z.string().optional()._zod.optin;
|
||||
const a = z.string().optional().pipe(z.string());
|
||||
expect(a._zod.optin).toEqual("optional");
|
||||
expect(a._zod.optout).toEqual(undefined);
|
||||
expectTypeOf<typeof a._zod.optin>().toEqualTypeOf<"optional">();
|
||||
expectTypeOf<typeof a._zod.optout>().toEqualTypeOf<"optional" | undefined>();
|
||||
|
||||
const b = z
|
||||
.string()
|
||||
.transform((val) => (Math.random() ? val : undefined))
|
||||
.pipe(z.string().optional());
|
||||
expect(b._zod.optin).toEqual(undefined);
|
||||
expect(b._zod.optout).toEqual("optional");
|
||||
expectTypeOf<typeof b._zod.optin>().toEqualTypeOf<"optional" | undefined>();
|
||||
expectTypeOf<typeof b._zod.optout>().toEqualTypeOf<"optional">();
|
||||
|
||||
const c = z.string().default("asdf").pipe(z.string());
|
||||
expect(c._zod.optin).toEqual("optional");
|
||||
expect(c._zod.optout).toEqual(undefined);
|
||||
|
||||
const d = z
|
||||
.string()
|
||||
.transform((val) => (Math.random() ? val : undefined))
|
||||
.pipe(z.string().default("asdf"));
|
||||
expect(d._zod.optin).toEqual(undefined);
|
||||
expect(d._zod.optout).toEqual(undefined);
|
||||
});
|
||||
|
||||
test("pipe optionality inside objects", () => {
|
||||
const schema = z.object({
|
||||
a: z.string().optional(),
|
||||
b: z.string().optional().pipe(z.string()),
|
||||
c: z.string().default("asdf").pipe(z.string()),
|
||||
d: z
|
||||
.string()
|
||||
.transform((val) => (Math.random() ? val : undefined))
|
||||
.pipe(z.string().optional()),
|
||||
e: z
|
||||
.string()
|
||||
.transform((val) => (Math.random() ? val : undefined))
|
||||
.pipe(z.string().default("asdf")),
|
||||
});
|
||||
|
||||
type SchemaIn = z.input<typeof schema>;
|
||||
expectTypeOf<SchemaIn>().toEqualTypeOf<{
|
||||
a?: string | undefined;
|
||||
b?: string | undefined;
|
||||
c?: string | undefined;
|
||||
d: string;
|
||||
e: string;
|
||||
}>();
|
||||
|
||||
type SchemaOut = z.output<typeof schema>;
|
||||
expectTypeOf<SchemaOut>().toEqualTypeOf<{
|
||||
a?: string | undefined;
|
||||
b: string;
|
||||
c: string;
|
||||
d?: string | undefined;
|
||||
e: string;
|
||||
}>();
|
||||
});
|
||||
147
node_modules/zod/src/v4/classic/tests/partial.test.ts
generated
vendored
Normal file
147
node_modules/zod/src/v4/classic/tests/partial.test.ts
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const nested = z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
outer: z.object({
|
||||
inner: z.string(),
|
||||
}),
|
||||
array: z.array(z.object({ asdf: z.string() })),
|
||||
});
|
||||
|
||||
test("shallow inference", () => {
|
||||
const shallow = nested.partial();
|
||||
type shallow = z.infer<typeof shallow>;
|
||||
|
||||
expectTypeOf<shallow>().toEqualTypeOf<{
|
||||
name?: string | undefined;
|
||||
age?: number | undefined;
|
||||
outer?: { inner: string } | undefined;
|
||||
array?: { asdf: string }[] | undefined;
|
||||
}>();
|
||||
});
|
||||
|
||||
test("shallow partial parse", () => {
|
||||
const shallow = nested.partial();
|
||||
shallow.parse({});
|
||||
shallow.parse({
|
||||
name: "asdf",
|
||||
age: 23143,
|
||||
});
|
||||
});
|
||||
|
||||
test("required", () => {
|
||||
const object = z.object({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
field: z.string().optional().default("asdf"),
|
||||
nullableField: z.number().nullable(),
|
||||
nullishField: z.string().nullish(),
|
||||
});
|
||||
|
||||
const requiredObject = object.required();
|
||||
expect(requiredObject.shape.name).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.name.unwrap()).toBeInstanceOf(z.ZodString);
|
||||
expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.age.unwrap()).toBeInstanceOf(z.ZodOptional);
|
||||
expect(requiredObject.shape.field).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.field.unwrap()).toBeInstanceOf(z.ZodDefault);
|
||||
expect(requiredObject.shape.nullableField).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.nullableField.unwrap()).toBeInstanceOf(z.ZodNullable);
|
||||
expect(requiredObject.shape.nullishField).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.nullishField.unwrap()).toBeInstanceOf(z.ZodOptional);
|
||||
expect(requiredObject.shape.nullishField.unwrap().unwrap()).toBeInstanceOf(z.ZodNullable);
|
||||
});
|
||||
|
||||
test("required inference", () => {
|
||||
const object = z.object({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
field: z.string().optional().default("asdf"),
|
||||
nullableField: z.number().nullable(),
|
||||
nullishField: z.string().nullish(),
|
||||
});
|
||||
|
||||
const requiredObject = object.required();
|
||||
|
||||
type required = z.infer<typeof requiredObject>;
|
||||
type expected = {
|
||||
name: string;
|
||||
age: number;
|
||||
field: string;
|
||||
nullableField: number | null;
|
||||
nullishField: string | null;
|
||||
};
|
||||
expectTypeOf<expected>().toEqualTypeOf<required>();
|
||||
});
|
||||
|
||||
test("required with mask", () => {
|
||||
const object = z.object({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
field: z.string().optional().default("asdf"),
|
||||
country: z.string().optional(),
|
||||
});
|
||||
|
||||
const requiredObject = object.required({ age: true });
|
||||
expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString);
|
||||
expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault);
|
||||
expect(requiredObject.shape.country).toBeInstanceOf(z.ZodOptional);
|
||||
});
|
||||
|
||||
test("required with mask -- ignore falsy values", () => {
|
||||
const object = z.object({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
field: z.string().optional().default("asdf"),
|
||||
country: z.string().optional(),
|
||||
});
|
||||
|
||||
// @ts-expect-error
|
||||
const requiredObject = object.required({ age: true, country: false });
|
||||
expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString);
|
||||
expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault);
|
||||
expect(requiredObject.shape.country).toBeInstanceOf(z.ZodOptional);
|
||||
});
|
||||
|
||||
test("partial with mask", async () => {
|
||||
const object = z.object({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
field: z.string().optional().default("asdf"),
|
||||
country: z.string(),
|
||||
});
|
||||
|
||||
const masked = object.partial({ age: true, field: true, name: true }).strict();
|
||||
|
||||
expect(masked.shape.name).toBeInstanceOf(z.ZodOptional);
|
||||
expect(masked.shape.age).toBeInstanceOf(z.ZodOptional);
|
||||
expect(masked.shape.field).toBeInstanceOf(z.ZodOptional);
|
||||
expect(masked.shape.country).toBeInstanceOf(z.ZodString);
|
||||
|
||||
masked.parse({ country: "US" });
|
||||
await masked.parseAsync({ country: "US" });
|
||||
});
|
||||
|
||||
test("partial with mask -- ignore falsy values", async () => {
|
||||
const object = z.object({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
field: z.string().optional().default("asdf"),
|
||||
country: z.string(),
|
||||
});
|
||||
|
||||
// @ts-expect-error
|
||||
const masked = object.partial({ name: true, country: false }).strict();
|
||||
|
||||
expect(masked.shape.name).toBeInstanceOf(z.ZodOptional);
|
||||
expect(masked.shape.age).toBeInstanceOf(z.ZodOptional);
|
||||
expect(masked.shape.field).toBeInstanceOf(z.ZodDefault);
|
||||
expect(masked.shape.country).toBeInstanceOf(z.ZodString);
|
||||
|
||||
masked.parse({ country: "US" });
|
||||
await masked.parseAsync({ country: "US" });
|
||||
});
|
||||
127
node_modules/zod/src/v4/classic/tests/pickomit.test.ts
generated
vendored
Normal file
127
node_modules/zod/src/v4/classic/tests/pickomit.test.ts
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const fish = z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
nested: z.object({}),
|
||||
});
|
||||
|
||||
test("pick type inference", () => {
|
||||
const nameonlyFish = fish.pick({ name: true });
|
||||
type nameonlyFish = z.infer<typeof nameonlyFish>;
|
||||
expectTypeOf<nameonlyFish>().toEqualTypeOf<{ name: string }>();
|
||||
});
|
||||
|
||||
test("pick parse - success", () => {
|
||||
const nameonlyFish = fish.pick({ name: true });
|
||||
nameonlyFish.parse({ name: "bob" });
|
||||
|
||||
// @ts-expect-error checking runtime picks `name` only.
|
||||
const anotherNameonlyFish = fish.pick({ name: true, age: false });
|
||||
anotherNameonlyFish.parse({ name: "bob" });
|
||||
});
|
||||
|
||||
test("pick parse - fail", () => {
|
||||
fish.pick({ name: true }).parse({ name: "12" } as any);
|
||||
fish.pick({ name: true }).parse({ name: "bob", age: 12 } as any);
|
||||
fish.pick({ age: true }).parse({ age: 12 } as any);
|
||||
|
||||
const nameonlyFish = fish.pick({ name: true }).strict();
|
||||
const bad1 = () => nameonlyFish.parse({ name: 12 } as any);
|
||||
const bad2 = () => nameonlyFish.parse({ name: "bob", age: 12 } as any);
|
||||
const bad3 = () => nameonlyFish.parse({ age: 12 } as any);
|
||||
|
||||
// @ts-expect-error checking runtime picks `name` only.
|
||||
const anotherNameonlyFish = fish.pick({ name: true, age: false }).strict();
|
||||
const bad4 = () => anotherNameonlyFish.parse({ name: "bob", age: 12 } as any);
|
||||
|
||||
expect(bad1).toThrow();
|
||||
expect(bad2).toThrow();
|
||||
expect(bad3).toThrow();
|
||||
expect(bad4).toThrow();
|
||||
});
|
||||
|
||||
test("pick - remove optional", () => {
|
||||
const schema = z.object({ a: z.string(), b: z.string().optional() });
|
||||
expect("a" in schema._zod.def.shape).toEqual(true);
|
||||
expect("b" in schema._zod.def.shape!).toEqual(true);
|
||||
const picked = schema.pick({ a: true });
|
||||
expect("a" in picked._zod.def.shape).toEqual(true);
|
||||
expect("b" in picked._zod.def.shape!).toEqual(false);
|
||||
});
|
||||
|
||||
test("omit type inference", () => {
|
||||
const nonameFish = fish.omit({ name: true });
|
||||
type nonameFish = z.infer<typeof nonameFish>;
|
||||
|
||||
expectTypeOf<nonameFish>().toEqualTypeOf<{ age: number; nested: Record<string, never> }>();
|
||||
});
|
||||
|
||||
test("omit parse - success", () => {
|
||||
const nonameFish = fish.omit({ name: true });
|
||||
nonameFish.parse({ age: 12, nested: {} });
|
||||
|
||||
// @ts-expect-error checking runtime omits `name` only.
|
||||
const anotherNonameFish = fish.omit({ name: true, age: false });
|
||||
anotherNonameFish.parse({ age: 12, nested: {} });
|
||||
});
|
||||
|
||||
test("omit parse - fail", () => {
|
||||
const nonameFish = fish.omit({ name: true });
|
||||
const bad1 = () => nonameFish.parse({ name: 12 } as any);
|
||||
const bad2 = () => nonameFish.parse({ age: 12 } as any);
|
||||
const bad3 = () => nonameFish.parse({} as any);
|
||||
|
||||
// @ts-expect-error checking runtime omits `name` only.
|
||||
const anotherNonameFish = fish.omit({ name: true, age: false });
|
||||
const bad4 = () => anotherNonameFish.parse({ nested: {} } as any);
|
||||
|
||||
expect(bad1).toThrow();
|
||||
expect(bad2).toThrow();
|
||||
expect(bad3).toThrow();
|
||||
expect(bad4).toThrow();
|
||||
});
|
||||
|
||||
test("omit - remove optional", () => {
|
||||
const schema = z.object({ a: z.string(), b: z.string().optional() });
|
||||
expect("a" in schema._zod.def.shape).toEqual(true);
|
||||
const omitted = schema.omit({ a: true });
|
||||
expect("a" in omitted._zod.def.shape).toEqual(false);
|
||||
});
|
||||
|
||||
test("nonstrict inference", () => {
|
||||
const laxfish = fish.pick({ name: true }).catchall(z.any());
|
||||
type laxfish = z.infer<typeof laxfish>;
|
||||
expectTypeOf<laxfish>().toEqualTypeOf<{ name: string; [k: string]: any }>();
|
||||
});
|
||||
|
||||
test("nonstrict parsing - pass", () => {
|
||||
const laxfish = fish.passthrough().pick({ name: true });
|
||||
laxfish.parse({ name: "asdf", whatever: "asdf" });
|
||||
laxfish.parse({ name: "asdf", age: 12, nested: {} });
|
||||
});
|
||||
|
||||
test("nonstrict parsing - fail", () => {
|
||||
const laxfish = fish.passthrough().pick({ name: true });
|
||||
const bad = () => laxfish.parse({ whatever: "asdf" } as any);
|
||||
expect(bad).toThrow();
|
||||
});
|
||||
|
||||
test("pick/omit/required/partial - do not allow unknown keys", () => {
|
||||
const schema = z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
});
|
||||
|
||||
expect(() => schema.pick({ name: true, asdf: true })).toThrow();
|
||||
|
||||
// @ts-expect-error
|
||||
expect(() => schema.pick({ $unknown: true })).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => schema.omit({ $unknown: true })).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => schema.required({ $unknown: true })).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => schema.partial({ $unknown: true })).toThrow();
|
||||
});
|
||||
81
node_modules/zod/src/v4/classic/tests/pipe.test.ts
generated
vendored
Normal file
81
node_modules/zod/src/v4/classic/tests/pipe.test.ts
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("string to number pipe", () => {
|
||||
const schema = z.string().transform(Number).pipe(z.number());
|
||||
expect(schema.parse("1234")).toEqual(1234);
|
||||
});
|
||||
|
||||
test("string to number pipe async", async () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.transform(async (val) => Number(val))
|
||||
.pipe(z.number());
|
||||
expect(await schema.parseAsync("1234")).toEqual(1234);
|
||||
});
|
||||
|
||||
test("string with default fallback", () => {
|
||||
const stringWithDefault = z
|
||||
.pipe(
|
||||
z.transform((v) => (v === "none" ? undefined : v)),
|
||||
z.string()
|
||||
)
|
||||
.catch("default");
|
||||
|
||||
expect(stringWithDefault.parse("ok")).toBe("ok");
|
||||
expect(stringWithDefault.parse(undefined)).toBe("default");
|
||||
expect(stringWithDefault.parse("none")).toBe("default");
|
||||
expect(stringWithDefault.parse(15)).toBe("default");
|
||||
});
|
||||
|
||||
test("continue on non-fatal errors", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.refine((c) => c === "1234", "A")
|
||||
.transform((val) => Number(val))
|
||||
.refine((c) => c === 1234, "B");
|
||||
|
||||
schema.parse("1234");
|
||||
|
||||
expect(schema.safeParse("4321")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "A"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "B"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("break on fatal errors", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.refine((c) => c === "1234", { message: "A", abort: true })
|
||||
.transform((val) => Number(val))
|
||||
.refine((c) => c === 1234, "B");
|
||||
|
||||
schema.parse("1234");
|
||||
|
||||
expect(schema.safeParse("4321")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "A"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
37
node_modules/zod/src/v4/classic/tests/prefault.test.ts
generated
vendored
Normal file
37
node_modules/zod/src/v4/classic/tests/prefault.test.ts
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
test("basic prefault", () => {
|
||||
const a = z.prefault(z.string().trim(), " default ");
|
||||
expect(a).toBeInstanceOf(z.ZodPrefault);
|
||||
expect(a.parse(" asdf ")).toEqual("asdf");
|
||||
expect(a.parse(undefined)).toEqual("default");
|
||||
|
||||
type inp = z.input<typeof a>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined>();
|
||||
type out = z.output<typeof a>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("prefault inside object", () => {
|
||||
// test optinality
|
||||
const a = z.object({
|
||||
name: z.string().optional(),
|
||||
age: z.number().default(1234),
|
||||
email: z.string().prefault("1234"),
|
||||
});
|
||||
|
||||
type inp = z.input<typeof a>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<{
|
||||
name?: string | undefined;
|
||||
age?: number | undefined;
|
||||
email?: string | undefined;
|
||||
}>();
|
||||
|
||||
type out = z.output<typeof a>;
|
||||
expectTypeOf<out>().toEqualTypeOf<{
|
||||
name?: string | undefined;
|
||||
age: number;
|
||||
email: string;
|
||||
}>();
|
||||
});
|
||||
298
node_modules/zod/src/v4/classic/tests/preprocess.test.ts
generated
vendored
Normal file
298
node_modules/zod/src/v4/classic/tests/preprocess.test.ts
generated
vendored
Normal file
@@ -0,0 +1,298 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("preprocess", () => {
|
||||
const schema = z.preprocess((data) => [data], z.string().array());
|
||||
const value = schema.parse("asdf");
|
||||
expect(value).toEqual(["asdf"]);
|
||||
expectTypeOf<(typeof schema)["_input"]>().toEqualTypeOf<unknown>();
|
||||
});
|
||||
|
||||
test("async preprocess", async () => {
|
||||
const schema = z.preprocess(async (data) => {
|
||||
return [data];
|
||||
}, z.string().array());
|
||||
const value = await schema.safeParseAsync("asdf");
|
||||
expect(value.data).toEqual(["asdf"]);
|
||||
expect(value).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": [
|
||||
"asdf",
|
||||
],
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("ctx.addIssue accepts string", () => {
|
||||
const schema = z.preprocess((_, ctx) => {
|
||||
ctx.addIssue("bad stuff");
|
||||
}, z.string());
|
||||
const result = schema.safeParse("asdf");
|
||||
expect(result.error!.issues).toHaveLength(1);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"message": "bad stuff",
|
||||
"code": "custom",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("preprocess ctx.addIssue with parse", () => {
|
||||
const a = z.preprocess((data, ctx) => {
|
||||
ctx.addIssue({
|
||||
input: data,
|
||||
code: "custom",
|
||||
message: `${data} is not one of our allowed strings`,
|
||||
});
|
||||
return data;
|
||||
}, z.string());
|
||||
|
||||
const result = a.safeParse("asdf");
|
||||
|
||||
// expect(result.error!.toJSON()).toContain("not one of our allowed strings");
|
||||
|
||||
expect(result.error!.issues).toHaveLength(1);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "asdf is not one of our allowed strings",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("preprocess ctx.addIssue non-fatal by default", () => {
|
||||
const schema = z.preprocess((data, ctx) => {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
});
|
||||
return data;
|
||||
}, z.string());
|
||||
const result = schema.safeParse(1234);
|
||||
|
||||
expect(result.error!.issues).toHaveLength(2);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("preprocess ctx.addIssue fatal true", () => {
|
||||
const schema = z.preprocess((data, ctx) => {
|
||||
ctx.addIssue({
|
||||
input: data,
|
||||
code: "custom",
|
||||
origin: "custom",
|
||||
message: `custom error`,
|
||||
fatal: true,
|
||||
});
|
||||
return data;
|
||||
}, z.string());
|
||||
|
||||
const result = schema.safeParse(1234);
|
||||
|
||||
expect(result.error!.issues).toHaveLength(1);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"origin": "custom",
|
||||
"message": "custom error",
|
||||
"fatal": true,
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("async preprocess ctx.addIssue with parseAsync", async () => {
|
||||
const schema = z.preprocess(async (data, ctx) => {
|
||||
ctx.addIssue({
|
||||
input: data,
|
||||
code: "custom",
|
||||
message: `${data} is not one of our allowed strings`,
|
||||
});
|
||||
return data;
|
||||
}, z.string());
|
||||
|
||||
const result = await schema.safeParseAsync("asdf");
|
||||
|
||||
expect(result.error!.issues).toHaveLength(1);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "asdf is not one of our allowed strings",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("z.NEVER in preprocess", () => {
|
||||
const foo = z.preprocess((val, ctx) => {
|
||||
if (!val) {
|
||||
ctx.addIssue({ input: val, code: "custom", message: "bad" });
|
||||
return z.NEVER;
|
||||
}
|
||||
return val;
|
||||
}, z.number());
|
||||
|
||||
type foo = z.infer<typeof foo>;
|
||||
expectTypeOf<foo>().toEqualTypeOf<number>();
|
||||
const result = foo.safeParse(undefined);
|
||||
|
||||
expect(result.error!.issues).toHaveLength(2);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "bad",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected number, received object"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("preprocess as the second property of object", () => {
|
||||
const schema = z.object({
|
||||
nonEmptyStr: z.string().min(1),
|
||||
positiveNum: z.preprocess((v) => Number(v), z.number().positive()),
|
||||
});
|
||||
const result = schema.safeParse({
|
||||
nonEmptyStr: "",
|
||||
positiveNum: "",
|
||||
});
|
||||
|
||||
expect(result.error!.issues).toHaveLength(2);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 1,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"nonEmptyStr"
|
||||
],
|
||||
"message": "Too small: expected string to have >=1 characters"
|
||||
},
|
||||
{
|
||||
"origin": "number",
|
||||
"code": "too_small",
|
||||
"minimum": 0,
|
||||
"inclusive": false,
|
||||
"path": [
|
||||
"positiveNum"
|
||||
],
|
||||
"message": "Too small: expected number to be >0"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("preprocess validates with sibling errors", () => {
|
||||
const schema = z.object({
|
||||
missing: z.string().refine(() => false),
|
||||
preprocess: z.preprocess((data: any) => data?.trim(), z.string().regex(/ asdf/)),
|
||||
});
|
||||
|
||||
const result = schema.safeParse({ preprocess: " asdf" });
|
||||
|
||||
expect(result.error!.issues).toHaveLength(2);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"missing"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
},
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "invalid_format",
|
||||
"format": "regex",
|
||||
"pattern": "/ asdf/",
|
||||
"path": [
|
||||
"preprocess"
|
||||
],
|
||||
"message": "Invalid string: must match pattern / asdf/"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("perform transform with non-fatal issues", () => {
|
||||
const A = z
|
||||
.string()
|
||||
.refine((_) => false)
|
||||
.min(4)
|
||||
.transform((val) => val.length)
|
||||
.pipe(z.number())
|
||||
.refine((_) => false);
|
||||
expect(A.safeParse("asdfasdf").error!.issues).toHaveLength(2);
|
||||
expect(A.safeParse("asdfasdf").error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
175
node_modules/zod/src/v4/classic/tests/primitive.test.ts
generated
vendored
Normal file
175
node_modules/zod/src/v4/classic/tests/primitive.test.ts
generated
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const literalStringSchema = z.literal("asdf");
|
||||
const literalNumberSchema = z.literal(12);
|
||||
const literalBooleanSchema = z.literal(true);
|
||||
const literalBigIntSchema = z.literal(BigInt(42));
|
||||
|
||||
const stringSchema = z.string();
|
||||
const numberSchema = z.number();
|
||||
const bigintSchema = z.bigint();
|
||||
const booleanSchema = z.boolean();
|
||||
const dateSchema = z.date();
|
||||
const symbolSchema = z.symbol();
|
||||
const nullSchema = z.null();
|
||||
const undefinedSchema = z.undefined();
|
||||
const stringSchemaOptional = z.string().optional();
|
||||
const stringSchemaNullable = z.string().nullable();
|
||||
const numberSchemaOptional = z.number().optional();
|
||||
const numberSchemaNullable = z.number().nullable();
|
||||
const bigintSchemaOptional = z.bigint().optional();
|
||||
const bigintSchemaNullable = z.bigint().nullable();
|
||||
const booleanSchemaOptional = z.boolean().optional();
|
||||
const booleanSchemaNullable = z.boolean().nullable();
|
||||
const dateSchemaOptional = z.date().optional();
|
||||
const dateSchemaNullable = z.date().nullable();
|
||||
const symbolSchemaOptional = z.symbol().optional();
|
||||
const symbolSchemaNullable = z.symbol().nullable();
|
||||
|
||||
test("literal string schema", () => {
|
||||
expect(literalStringSchema.parse("asdf")).toBe("asdf");
|
||||
expect(() => literalStringSchema.parse("not_asdf")).toThrow();
|
||||
expect(() => literalStringSchema.parse(123)).toThrow();
|
||||
expect(() => literalStringSchema.parse(true)).toThrow();
|
||||
expect(() => literalStringSchema.parse({})).toThrow();
|
||||
});
|
||||
|
||||
test("literal number schema", () => {
|
||||
expect(literalNumberSchema.parse(12)).toBe(12);
|
||||
expect(() => literalNumberSchema.parse(13)).toThrow();
|
||||
expect(() => literalNumberSchema.parse("foo")).toThrow();
|
||||
expect(() => literalNumberSchema.parse(true)).toThrow();
|
||||
expect(() => literalNumberSchema.parse({})).toThrow();
|
||||
});
|
||||
|
||||
test("literal boolean schema", () => {
|
||||
expect(literalBooleanSchema.parse(true)).toBe(true);
|
||||
expect(() => literalBooleanSchema.parse(false)).toThrow();
|
||||
expect(() => literalBooleanSchema.parse("asdf")).toThrow();
|
||||
expect(() => literalBooleanSchema.parse(123)).toThrow();
|
||||
expect(() => literalBooleanSchema.parse({})).toThrow();
|
||||
});
|
||||
|
||||
test("literal bigint schema", () => {
|
||||
expect(literalBigIntSchema.parse(BigInt(42))).toBe(BigInt(42));
|
||||
expect(() => literalBigIntSchema.parse(BigInt(43))).toThrow();
|
||||
expect(() => literalBigIntSchema.parse("asdf")).toThrow();
|
||||
expect(() => literalBigIntSchema.parse(123)).toThrow();
|
||||
expect(() => literalBigIntSchema.parse({})).toThrow();
|
||||
});
|
||||
|
||||
test("string schema", () => {
|
||||
stringSchema.parse("foo");
|
||||
expect(() => stringSchema.parse(Math.random())).toThrow();
|
||||
expect(() => stringSchema.parse(true)).toThrow();
|
||||
expect(() => stringSchema.parse(undefined)).toThrow();
|
||||
expect(() => stringSchema.parse(null)).toThrow();
|
||||
});
|
||||
|
||||
test("number schema", () => {
|
||||
numberSchema.parse(Math.random());
|
||||
expect(() => numberSchema.parse("foo")).toThrow();
|
||||
expect(() => numberSchema.parse(BigInt(17))).toThrow();
|
||||
expect(() => numberSchema.parse(true)).toThrow();
|
||||
expect(() => numberSchema.parse(undefined)).toThrow();
|
||||
expect(() => numberSchema.parse(null)).toThrow();
|
||||
});
|
||||
|
||||
test("bigint schema", () => {
|
||||
bigintSchema.parse(BigInt(17));
|
||||
expect(() => bigintSchema.parse("foo")).toThrow();
|
||||
expect(() => bigintSchema.parse(Math.random())).toThrow();
|
||||
expect(() => bigintSchema.parse(true)).toThrow();
|
||||
expect(() => bigintSchema.parse(undefined)).toThrow();
|
||||
expect(() => bigintSchema.parse(null)).toThrow();
|
||||
});
|
||||
|
||||
test("boolean schema", () => {
|
||||
booleanSchema.parse(true);
|
||||
expect(() => booleanSchema.parse("foo")).toThrow();
|
||||
expect(() => booleanSchema.parse(Math.random())).toThrow();
|
||||
expect(() => booleanSchema.parse(undefined)).toThrow();
|
||||
expect(() => booleanSchema.parse(null)).toThrow();
|
||||
});
|
||||
|
||||
test("date schema", async () => {
|
||||
dateSchema.parse(new Date());
|
||||
expect(() => dateSchema.parse("foo")).toThrow();
|
||||
expect(() => dateSchema.parse(Math.random())).toThrow();
|
||||
expect(() => dateSchema.parse(true)).toThrow();
|
||||
expect(() => dateSchema.parse(undefined)).toThrow();
|
||||
expect(() => dateSchema.parse(null)).toThrow();
|
||||
expect(await dateSchema.safeParseAsync(new Date("invalid"))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "date",
|
||||
"code": "invalid_type",
|
||||
"received": "Invalid Date",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected date, received Date"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("symbol schema", () => {
|
||||
symbolSchema.parse(Symbol("foo"));
|
||||
expect(() => symbolSchema.parse("foo")).toThrow();
|
||||
expect(() => symbolSchema.parse(Math.random())).toThrow();
|
||||
expect(() => symbolSchema.parse(true)).toThrow();
|
||||
expect(() => symbolSchema.parse(new Date())).toThrow();
|
||||
expect(() => symbolSchema.parse(undefined)).toThrow();
|
||||
expect(() => symbolSchema.parse(null)).toThrow();
|
||||
});
|
||||
|
||||
test("undefined schema", () => {
|
||||
undefinedSchema.parse(undefined);
|
||||
expect(() => undefinedSchema.parse("foo")).toThrow();
|
||||
expect(() => undefinedSchema.parse(Math.random())).toThrow();
|
||||
expect(() => undefinedSchema.parse(true)).toThrow();
|
||||
expect(() => undefinedSchema.parse(null)).toThrow();
|
||||
});
|
||||
|
||||
test("null schema", () => {
|
||||
nullSchema.parse(null);
|
||||
expect(() => nullSchema.parse("foo")).toThrow();
|
||||
expect(() => nullSchema.parse(Math.random())).toThrow();
|
||||
expect(() => nullSchema.parse(true)).toThrow();
|
||||
expect(() => nullSchema.parse(undefined)).toThrow();
|
||||
});
|
||||
|
||||
test("primitive inference", () => {
|
||||
expectTypeOf<z.TypeOf<typeof literalStringSchema>>().toEqualTypeOf<"asdf">();
|
||||
expectTypeOf<z.TypeOf<typeof literalNumberSchema>>().toEqualTypeOf<12>();
|
||||
expectTypeOf<z.TypeOf<typeof literalBooleanSchema>>().toEqualTypeOf<true>();
|
||||
expectTypeOf<z.TypeOf<typeof literalBigIntSchema>>().toEqualTypeOf<bigint>();
|
||||
expectTypeOf<z.TypeOf<typeof stringSchema>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.TypeOf<typeof numberSchema>>().toEqualTypeOf<number>();
|
||||
expectTypeOf<z.TypeOf<typeof bigintSchema>>().toEqualTypeOf<bigint>();
|
||||
expectTypeOf<z.TypeOf<typeof booleanSchema>>().toEqualTypeOf<boolean>();
|
||||
expectTypeOf<z.TypeOf<typeof dateSchema>>().toEqualTypeOf<Date>();
|
||||
expectTypeOf<z.TypeOf<typeof symbolSchema>>().toEqualTypeOf<symbol>();
|
||||
expectTypeOf<z.TypeOf<typeof nullSchema>>().toEqualTypeOf<null>();
|
||||
expectTypeOf<z.TypeOf<typeof undefinedSchema>>().toEqualTypeOf<undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof stringSchemaOptional>>().toEqualTypeOf<string | undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof stringSchemaNullable>>().toEqualTypeOf<string | null>();
|
||||
expectTypeOf<z.TypeOf<typeof numberSchemaOptional>>().toEqualTypeOf<number | undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof numberSchemaNullable>>().toEqualTypeOf<number | null>();
|
||||
expectTypeOf<z.TypeOf<typeof bigintSchemaOptional>>().toEqualTypeOf<bigint | undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof bigintSchemaNullable>>().toEqualTypeOf<bigint | null>();
|
||||
expectTypeOf<z.TypeOf<typeof booleanSchemaOptional>>().toEqualTypeOf<boolean | undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof booleanSchemaNullable>>().toEqualTypeOf<boolean | null>();
|
||||
expectTypeOf<z.TypeOf<typeof dateSchemaOptional>>().toEqualTypeOf<Date | undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof dateSchemaNullable>>().toEqualTypeOf<Date | null>();
|
||||
expectTypeOf<z.TypeOf<typeof symbolSchemaOptional>>().toEqualTypeOf<symbol | undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof symbolSchemaNullable>>().toEqualTypeOf<symbol | null>();
|
||||
});
|
||||
|
||||
test("get literal values", () => {
|
||||
expect(literalStringSchema.values).toEqual(new Set(["asdf"]));
|
||||
expect(literalStringSchema._zod.def.values).toEqual(["asdf"]);
|
||||
});
|
||||
81
node_modules/zod/src/v4/classic/tests/promise.test.ts
generated
vendored
Normal file
81
node_modules/zod/src/v4/classic/tests/promise.test.ts
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const promSchema = z.promise(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
})
|
||||
);
|
||||
|
||||
test("promise inference", () => {
|
||||
type promSchemaType = z.infer<typeof promSchema>;
|
||||
expectTypeOf<promSchemaType>().toEqualTypeOf<{ name: string; age: number }>();
|
||||
});
|
||||
|
||||
test("promise parsing success", async () => {
|
||||
// expect(() => promSchema.parse(Promise.resolve({ name: "Bobby", age: 10 }))).toThrow();
|
||||
const pr = promSchema.parseAsync(Promise.resolve({ name: "Bobby", age: 10 }));
|
||||
expect(pr).toBeInstanceOf(Promise);
|
||||
const result = await pr;
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"age": 10,
|
||||
"name": "Bobby",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("promise parsing fail", async () => {
|
||||
const bad = await promSchema.safeParseAsync(Promise.resolve({ name: "Bobby", age: "10" }));
|
||||
expect(bad.success).toBe(false);
|
||||
expect(bad.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
test("promise parsing fail 2", async () => {
|
||||
const result = await promSchema.safeParseAsync(Promise.resolve({ name: "Bobby", age: "10" }));
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
test("promise parsing fail", () => {
|
||||
const bad = () => promSchema.parse({ then: () => {}, catch: {} });
|
||||
expect(bad).toThrow();
|
||||
});
|
||||
|
||||
test("sync promise parsing", () => {
|
||||
expect(() => z.promise(z.string()).parse(Promise.resolve("asfd"))).toThrow();
|
||||
});
|
||||
|
||||
const asyncFunction = z.function({
|
||||
input: z.tuple([]),
|
||||
output: promSchema,
|
||||
});
|
||||
|
||||
test("async function pass", async () => {
|
||||
const validatedFunction = asyncFunction.implementAsync(async () => {
|
||||
return { name: "jimmy", age: 14 };
|
||||
});
|
||||
await expect(validatedFunction()).resolves.toEqual({
|
||||
name: "jimmy",
|
||||
age: 14,
|
||||
});
|
||||
});
|
||||
|
||||
test("async function fail", async () => {
|
||||
const validatedFunction = asyncFunction.implementAsync(() => {
|
||||
return Promise.resolve("asdf" as any);
|
||||
});
|
||||
await expect(validatedFunction()).rejects.toBeInstanceOf(z.core.$ZodError);
|
||||
});
|
||||
|
||||
test("async promise parsing", () => {
|
||||
const res = z.promise(z.number()).parseAsync(Promise.resolve(12));
|
||||
expect(res).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
test("resolves", () => {
|
||||
const foo = z.literal("foo");
|
||||
const res = z.promise(foo);
|
||||
expect(res.unwrap()).toEqual(foo);
|
||||
});
|
||||
23
node_modules/zod/src/v4/classic/tests/prototypes.test.ts
generated
vendored
Normal file
23
node_modules/zod/src/v4/classic/tests/prototypes.test.ts
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
declare module "zod/v4" {
|
||||
interface ZodType {
|
||||
/** @deprecated */
|
||||
_classic(): string;
|
||||
}
|
||||
}
|
||||
|
||||
test("prototype extension", () => {
|
||||
z.ZodType.prototype._classic = function () {
|
||||
return "_classic";
|
||||
};
|
||||
|
||||
// should pass
|
||||
const result = z.string()._classic();
|
||||
expect(result).toBe("_classic");
|
||||
// expectTypeOf<typeof result>().toEqualTypeOf<string>();
|
||||
|
||||
// clean up
|
||||
z.ZodType.prototype._classic = undefined;
|
||||
});
|
||||
252
node_modules/zod/src/v4/classic/tests/readonly.test.ts
generated
vendored
Normal file
252
node_modules/zod/src/v4/classic/tests/readonly.test.ts
generated
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
enum testEnum {
|
||||
A = 0,
|
||||
B = 1,
|
||||
}
|
||||
|
||||
test("flat inference", () => {
|
||||
const readonlyString = z.string().readonly();
|
||||
const readonlyNumber = z.number().readonly();
|
||||
const readonlyNaN = z.nan().readonly();
|
||||
const readonlyBigInt = z.bigint().readonly();
|
||||
const readonlyBoolean = z.boolean().readonly();
|
||||
const readonlyDate = z.date().readonly();
|
||||
const readonlyUndefined = z.undefined().readonly();
|
||||
const readonlyNull = z.null().readonly();
|
||||
const readonlyAny = z.any().readonly();
|
||||
const readonlyUnknown = z.unknown().readonly();
|
||||
const readonlyVoid = z.void().readonly();
|
||||
const readonlyStringArray = z.array(z.string()).readonly();
|
||||
const readonlyTuple = z.tuple([z.string(), z.number()]).readonly();
|
||||
const readonlyMap = z.map(z.string(), z.date()).readonly();
|
||||
const readonlySet = z.set(z.string()).readonly();
|
||||
const readonlyStringRecord = z.record(z.string(), z.string()).readonly();
|
||||
const readonlyNumberRecord = z.record(z.string(), z.number()).readonly();
|
||||
const readonlyObject = z.object({ a: z.string(), 1: z.number() }).readonly();
|
||||
const readonlyEnum = z.nativeEnum(testEnum).readonly();
|
||||
const readonlyPromise = z.promise(z.string()).readonly();
|
||||
|
||||
expectTypeOf<typeof readonlyString._output>().toEqualTypeOf<string>();
|
||||
expectTypeOf<typeof readonlyNumber._output>().toEqualTypeOf<number>();
|
||||
expectTypeOf<typeof readonlyNaN._output>().toEqualTypeOf<number>();
|
||||
expectTypeOf<typeof readonlyBigInt._output>().toEqualTypeOf<bigint>();
|
||||
expectTypeOf<typeof readonlyBoolean._output>().toEqualTypeOf<boolean>();
|
||||
expectTypeOf<typeof readonlyDate._output>().toEqualTypeOf<Date>();
|
||||
expectTypeOf<typeof readonlyUndefined._output>().toEqualTypeOf<undefined>();
|
||||
expectTypeOf<typeof readonlyNull._output>().toEqualTypeOf<null>();
|
||||
expectTypeOf<typeof readonlyAny._output>().toEqualTypeOf<any>();
|
||||
expectTypeOf<typeof readonlyUnknown._output>().toEqualTypeOf<Readonly<unknown>>();
|
||||
expectTypeOf<typeof readonlyVoid._output>().toEqualTypeOf<void>();
|
||||
expectTypeOf<typeof readonlyStringArray._output>().toEqualTypeOf<readonly string[]>();
|
||||
expectTypeOf<typeof readonlyTuple._output>().toEqualTypeOf<readonly [string, number]>();
|
||||
expectTypeOf<typeof readonlyMap._output>().toEqualTypeOf<ReadonlyMap<string, Date>>();
|
||||
expectTypeOf<typeof readonlySet._output>().toEqualTypeOf<ReadonlySet<string>>();
|
||||
expectTypeOf<typeof readonlyStringRecord._output>().toEqualTypeOf<Readonly<Record<string, string>>>();
|
||||
expectTypeOf<typeof readonlyNumberRecord._output>().toEqualTypeOf<Readonly<Record<string, number>>>();
|
||||
expectTypeOf<typeof readonlyObject._output>().toEqualTypeOf<{ readonly a: string; readonly 1: number }>();
|
||||
expectTypeOf<typeof readonlyEnum._output>().toEqualTypeOf<Readonly<testEnum>>();
|
||||
expectTypeOf<typeof readonlyPromise._output>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
// test("deep inference", () => {
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[0]>>().toEqualTypeOf<string>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[1]>>().toEqualTypeOf<number>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[2]>>().toEqualTypeOf<number>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[3]>>().toEqualTypeOf<bigint>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[4]>>().toEqualTypeOf<boolean>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[5]>>().toEqualTypeOf<Date>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[6]>>().toEqualTypeOf<undefined>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[7]>>().toEqualTypeOf<null>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[8]>>().toEqualTypeOf<any>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[9]>
|
||||
// >().toEqualTypeOf<Readonly<unknown>>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[10]>>().toEqualTypeOf<void>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[11]>
|
||||
// >().toEqualTypeOf<(args_0: string, args_1: number, ...args_2: unknown[]) => unknown>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[12]>
|
||||
// >().toEqualTypeOf<readonly string[]>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[13]>
|
||||
// >().toEqualTypeOf<readonly [string, number]>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[14]>
|
||||
// >().toEqualTypeOf<ReadonlyMap<string, Date>>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[15]>
|
||||
// >().toEqualTypeOf<ReadonlySet<Promise<string>>>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[16]>
|
||||
// >().toEqualTypeOf<Readonly<Record<string, string>>>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[17]>
|
||||
// >().toEqualTypeOf<Readonly<Record<string, number>>>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[18]>
|
||||
// >().toEqualTypeOf<{ readonly a: string; readonly 1: number }>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[19]>
|
||||
// >().toEqualTypeOf<Readonly<testEnum>>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[20]>
|
||||
// >().toEqualTypeOf<Promise<string>>();
|
||||
|
||||
// expectTypeOf<
|
||||
// z.infer<typeof crazyDeepReadonlySchema>
|
||||
// >().toEqualTypeOf<ReadonlyMap<
|
||||
// ReadonlySet<readonly [string, number]>,
|
||||
// {
|
||||
// readonly a: {
|
||||
// readonly [x: string]: readonly any[];
|
||||
// };
|
||||
// readonly b: {
|
||||
// readonly c: {
|
||||
// readonly d: {
|
||||
// readonly e: {
|
||||
// readonly f: {
|
||||
// readonly g?: {};
|
||||
// };
|
||||
// };
|
||||
// };
|
||||
// };
|
||||
// };
|
||||
// }
|
||||
// >>();
|
||||
// });
|
||||
|
||||
test("object freezing", async () => {
|
||||
expect(Object.isFrozen(z.array(z.string()).readonly().parse(["a"]))).toBe(true);
|
||||
expect(Object.isFrozen(z.tuple([z.string(), z.number()]).readonly().parse(["a", 1]))).toBe(true);
|
||||
expect(
|
||||
Object.isFrozen(
|
||||
z
|
||||
.map(z.string(), z.date())
|
||||
.readonly()
|
||||
.parse(new Map([["a", new Date()]]))
|
||||
)
|
||||
).toBe(true);
|
||||
|
||||
expect(Object.isFrozen(z.record(z.string(), z.string()).readonly().parse({ a: "b" }))).toBe(true);
|
||||
expect(Object.isFrozen(z.record(z.string(), z.number()).readonly().parse({ a: 1 }))).toBe(true);
|
||||
expect(Object.isFrozen(z.object({ a: z.string(), 1: z.number() }).readonly().parse({ a: "b", 1: 2 }))).toBe(true);
|
||||
expect(
|
||||
Object.isFrozen(
|
||||
await z
|
||||
.set(z.promise(z.string()))
|
||||
.readonly()
|
||||
.parseAsync(new Set([Promise.resolve("a")]))
|
||||
)
|
||||
).toBe(true);
|
||||
expect(Object.isFrozen(await z.promise(z.string()).readonly().parseAsync(Promise.resolve("a")))).toBe(true);
|
||||
});
|
||||
|
||||
test("async object freezing", async () => {
|
||||
expect(Object.isFrozen(await z.array(z.string()).readonly().parseAsync(["a"]))).toBe(true);
|
||||
expect(Object.isFrozen(await z.tuple([z.string(), z.number()]).readonly().parseAsync(["a", 1]))).toBe(true);
|
||||
expect(
|
||||
Object.isFrozen(
|
||||
await z
|
||||
.map(z.string(), z.date())
|
||||
.readonly()
|
||||
.parseAsync(new Map([["a", new Date()]]))
|
||||
)
|
||||
).toBe(true);
|
||||
expect(
|
||||
Object.isFrozen(
|
||||
await z
|
||||
.set(z.promise(z.string()))
|
||||
.readonly()
|
||||
.parseAsync(new Set([Promise.resolve("a")]))
|
||||
)
|
||||
).toBe(true);
|
||||
expect(Object.isFrozen(await z.record(z.string(), z.string()).readonly().parseAsync({ a: "b" }))).toBe(true);
|
||||
expect(Object.isFrozen(await z.record(z.string(), z.number()).readonly().parseAsync({ a: 1 }))).toBe(true);
|
||||
expect(
|
||||
Object.isFrozen(await z.object({ a: z.string(), 1: z.number() }).readonly().parseAsync({ a: "b", 1: 2 }))
|
||||
).toBe(true);
|
||||
expect(Object.isFrozen(await z.promise(z.string()).readonly().parseAsync(Promise.resolve("a")))).toBe(true);
|
||||
});
|
||||
|
||||
test("readonly inference", () => {
|
||||
const readonlyStringArray = z.string().array().readonly();
|
||||
const readonlyStringTuple = z.tuple([z.string()]).readonly();
|
||||
const deepReadonly = z.object({ a: z.string() }).readonly();
|
||||
|
||||
type readonlyStringArray = z.infer<typeof readonlyStringArray>;
|
||||
type readonlyStringTuple = z.infer<typeof readonlyStringTuple>;
|
||||
type deepReadonly = z.infer<typeof deepReadonly>;
|
||||
|
||||
expectTypeOf<readonlyStringArray>().toEqualTypeOf<readonly string[]>();
|
||||
expectTypeOf<readonlyStringTuple>().toEqualTypeOf<readonly [string]>();
|
||||
expectTypeOf<deepReadonly>().toEqualTypeOf<{ readonly a: string }>();
|
||||
});
|
||||
|
||||
test("readonly parse", () => {
|
||||
const schema = z.array(z.string()).readonly();
|
||||
const readonlyArray = ["a", "b", "c"] as const;
|
||||
const mutableArray = ["a", "b", "c"];
|
||||
const result1 = schema.parse(readonlyArray);
|
||||
const result2 = schema.parse(mutableArray);
|
||||
expect(result1).toEqual(readonlyArray);
|
||||
expect(result2).toEqual(mutableArray);
|
||||
});
|
||||
|
||||
test("readonly parse with tuples", () => {
|
||||
const schema = z.tuple([z.string(), z.number()]).readonly();
|
||||
schema.parse(["a", 1]);
|
||||
});
|
||||
|
||||
test("readonly and the get method", () => {
|
||||
const readonlyString = z.string().readonly();
|
||||
const readonlyNumber1 = z.number().readonly();
|
||||
const readonlyNumber2 = z.number().readonly();
|
||||
const readonlyBigInt = z.bigint().readonly();
|
||||
const readonlyBoolean = z.boolean().readonly();
|
||||
const readonlyDate = z.date().readonly();
|
||||
const readonlyUndefined = z.undefined().readonly();
|
||||
const readonlyNull = z.null().readonly();
|
||||
const readonlyAny = z.any().readonly();
|
||||
const readonlyUnknown = z.unknown().readonly();
|
||||
const readonlyVoid = z.void().readonly();
|
||||
// const readonlyFunction = z.function(z.tuple([z.string(), z.number()]), z.unknown()).readonly();
|
||||
const readonlyStringArray = z.string().array().readonly();
|
||||
const readonlyTuple = z.tuple([z.string(), z.number()]).readonly();
|
||||
|
||||
expectTypeOf<z.infer<typeof readonlyString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof readonlyNumber1>>().toEqualTypeOf<number>();
|
||||
expectTypeOf<z.infer<typeof readonlyNumber2>>().toEqualTypeOf<number>();
|
||||
expectTypeOf<z.infer<typeof readonlyBigInt>>().toEqualTypeOf<bigint>();
|
||||
expectTypeOf<z.infer<typeof readonlyBoolean>>().toEqualTypeOf<boolean>();
|
||||
expectTypeOf<z.infer<typeof readonlyDate>>().toEqualTypeOf<Date>();
|
||||
expectTypeOf<z.infer<typeof readonlyUndefined>>().toEqualTypeOf<undefined>();
|
||||
expectTypeOf<z.infer<typeof readonlyNull>>().toEqualTypeOf<null>();
|
||||
expectTypeOf<z.infer<typeof readonlyAny>>().toEqualTypeOf<any>();
|
||||
expectTypeOf<z.infer<typeof readonlyUnknown>>().toEqualTypeOf<Readonly<unknown>>();
|
||||
expectTypeOf<z.infer<typeof readonlyVoid>>().toEqualTypeOf<void>();
|
||||
// expectTypeOf<z.infer<typeof readonlyFunction>>().toEqualTypeOf<
|
||||
// (args_0: string, args_1: number, ...args_2: unknown[]) => unknown
|
||||
// >();
|
||||
expectTypeOf<z.infer<typeof readonlyStringArray>>().toEqualTypeOf<readonly string[]>();
|
||||
expectTypeOf<z.infer<typeof readonlyTuple>>().toEqualTypeOf<readonly [string, number]>();
|
||||
|
||||
expect(readonlyString.parse("asdf")).toEqual("asdf");
|
||||
expect(readonlyNumber1.parse(1234)).toEqual(1234);
|
||||
expect(readonlyNumber2.parse(1234)).toEqual(1234);
|
||||
const bigIntVal = BigInt(1);
|
||||
expect(readonlyBigInt.parse(bigIntVal)).toEqual(bigIntVal);
|
||||
expect(readonlyBoolean.parse(true)).toEqual(true);
|
||||
const dateVal = new Date();
|
||||
expect(readonlyDate.parse(dateVal)).toEqual(dateVal);
|
||||
expect(readonlyUndefined.parse(undefined)).toEqual(undefined);
|
||||
expect(readonlyNull.parse(null)).toEqual(null);
|
||||
expect(readonlyAny.parse("whatever")).toEqual("whatever");
|
||||
expect(readonlyUnknown.parse("whatever")).toEqual("whatever");
|
||||
expect(readonlyVoid.parse(undefined)).toEqual(undefined);
|
||||
// expect(readonlyFunction.parse(() => void 0)).toEqual(() => void 0);
|
||||
expect(readonlyStringArray.parse(["asdf"])).toEqual(["asdf"]);
|
||||
expect(readonlyTuple.parse(["asdf", 1234])).toEqual(["asdf", 1234]);
|
||||
});
|
||||
342
node_modules/zod/src/v4/classic/tests/record.test.ts
generated
vendored
Normal file
342
node_modules/zod/src/v4/classic/tests/record.test.ts
generated
vendored
Normal file
@@ -0,0 +1,342 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("type inference", () => {
|
||||
const booleanRecord = z.record(z.string(), z.boolean());
|
||||
type booleanRecord = typeof booleanRecord._output;
|
||||
|
||||
const recordWithEnumKeys = z.record(z.enum(["Tuna", "Salmon"]), z.string());
|
||||
type recordWithEnumKeys = z.infer<typeof recordWithEnumKeys>;
|
||||
|
||||
const recordWithLiteralKey = z.record(z.literal(["Tuna", "Salmon"]), z.string());
|
||||
type recordWithLiteralKey = z.infer<typeof recordWithLiteralKey>;
|
||||
|
||||
const recordWithLiteralUnionKeys = z.record(z.union([z.literal("Tuna"), z.literal("Salmon")]), z.string());
|
||||
type recordWithLiteralUnionKeys = z.infer<typeof recordWithLiteralUnionKeys>;
|
||||
|
||||
expectTypeOf<booleanRecord>().toEqualTypeOf<Record<string, boolean>>();
|
||||
expectTypeOf<recordWithEnumKeys>().toEqualTypeOf<Record<"Tuna" | "Salmon", string>>();
|
||||
expectTypeOf<recordWithLiteralKey>().toEqualTypeOf<Record<"Tuna" | "Salmon", string>>();
|
||||
expectTypeOf<recordWithLiteralUnionKeys>().toEqualTypeOf<Record<"Tuna" | "Salmon", string>>();
|
||||
});
|
||||
|
||||
test("enum exhaustiveness", () => {
|
||||
const schema = z.record(z.enum(["Tuna", "Salmon"]), z.string());
|
||||
expect(
|
||||
schema.parse({
|
||||
Tuna: "asdf",
|
||||
Salmon: "asdf",
|
||||
})
|
||||
).toEqual({
|
||||
Tuna: "asdf",
|
||||
Salmon: "asdf",
|
||||
});
|
||||
|
||||
expect(schema.safeParse({ Tuna: "asdf", Salmon: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": [
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Unrecognized key: \\"Trout\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse({ Tuna: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"Salmon"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("literal exhaustiveness", () => {
|
||||
const schema = z.record(z.literal(["Tuna", "Salmon"]), z.string());
|
||||
schema.parse({
|
||||
Tuna: "asdf",
|
||||
Salmon: "asdf",
|
||||
});
|
||||
|
||||
expect(schema.safeParse({ Tuna: "asdf", Salmon: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": [
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Unrecognized key: \\"Trout\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse({ Tuna: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"Salmon"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("pipe exhaustiveness", () => {
|
||||
const schema = z.record(z.enum(["Tuna", "Salmon"]).pipe(z.any()), z.string());
|
||||
expect(schema.parse({ Tuna: "asdf", Salmon: "asdf" })).toEqual({
|
||||
Tuna: "asdf",
|
||||
Salmon: "asdf",
|
||||
});
|
||||
|
||||
expect(schema.safeParse({ Tuna: "asdf", Salmon: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": [
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Unrecognized key: \\"Trout\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse({ Tuna: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"Salmon"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("union exhaustiveness", () => {
|
||||
const schema = z.record(z.union([z.literal("Tuna"), z.literal("Salmon")]), z.string());
|
||||
expect(schema.parse({ Tuna: "asdf", Salmon: "asdf" })).toEqual({
|
||||
Tuna: "asdf",
|
||||
Salmon: "asdf",
|
||||
});
|
||||
|
||||
expect(schema.safeParse({ Tuna: "asdf", Salmon: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": [
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Unrecognized key: \\"Trout\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse({ Tuna: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"Salmon"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("string record parse - pass", () => {
|
||||
const schema = z.record(z.string(), z.boolean());
|
||||
schema.parse({
|
||||
k1: true,
|
||||
k2: false,
|
||||
1234: false,
|
||||
});
|
||||
|
||||
expect(schema.safeParse({ asdf: 1234 }).success).toEqual(false);
|
||||
expect(schema.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "record",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected record, received string"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("key and value getters", () => {
|
||||
const rec = z.record(z.string(), z.number());
|
||||
|
||||
rec.keyType.parse("asdf");
|
||||
rec.valueType.parse(1234);
|
||||
});
|
||||
|
||||
test("is not vulnerable to prototype pollution", async () => {
|
||||
const rec = z.record(
|
||||
z.string(),
|
||||
z.object({
|
||||
a: z.string(),
|
||||
})
|
||||
);
|
||||
|
||||
const data = JSON.parse(`
|
||||
{
|
||||
"__proto__": {
|
||||
"a": "evil"
|
||||
},
|
||||
"b": {
|
||||
"a": "good"
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const obj1 = rec.parse(data);
|
||||
expect(obj1.a).toBeUndefined();
|
||||
|
||||
const obj2 = rec.safeParse(data);
|
||||
expect(obj2.success).toBe(true);
|
||||
if (obj2.success) {
|
||||
expect(obj2.data.a).toBeUndefined();
|
||||
}
|
||||
|
||||
const obj3 = await rec.parseAsync(data);
|
||||
expect(obj3.a).toBeUndefined();
|
||||
|
||||
const obj4 = await rec.safeParseAsync(data);
|
||||
expect(obj4.success).toBe(true);
|
||||
if (obj4.success) {
|
||||
expect(obj4.data.a).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
||||
test("dont remove undefined values", () => {
|
||||
const result1 = z.record(z.string(), z.any()).parse({ foo: undefined });
|
||||
|
||||
expect(result1).toEqual({
|
||||
foo: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
test("allow undefined values", () => {
|
||||
const schema = z.record(z.string(), z.undefined());
|
||||
|
||||
expect(
|
||||
Object.keys(
|
||||
schema.parse({
|
||||
_test: undefined,
|
||||
})
|
||||
)
|
||||
).toEqual(["_test"]);
|
||||
});
|
||||
|
||||
test("async parsing", async () => {
|
||||
const schema = z
|
||||
.record(
|
||||
z.string(),
|
||||
z
|
||||
.string()
|
||||
.optional()
|
||||
.refine(async () => true)
|
||||
)
|
||||
.refine(async () => true);
|
||||
|
||||
const data = {
|
||||
foo: "bar",
|
||||
baz: "qux",
|
||||
};
|
||||
const result = await schema.safeParseAsync(data);
|
||||
expect(result.data).toEqual(data);
|
||||
});
|
||||
|
||||
test("async parsing", async () => {
|
||||
const schema = z
|
||||
.record(
|
||||
z.string(),
|
||||
z
|
||||
.string()
|
||||
.optional()
|
||||
.refine(async () => false)
|
||||
)
|
||||
.refine(async () => false);
|
||||
|
||||
const data = {
|
||||
foo: "bar",
|
||||
baz: "qux",
|
||||
};
|
||||
const result = await schema.safeParseAsync(data);
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"foo"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"baz"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("partial record", () => {
|
||||
const schema = z.partialRecord(z.string(), z.string());
|
||||
type schema = z.infer<typeof schema>;
|
||||
expectTypeOf<schema>().toEqualTypeOf<Partial<Record<string, string>>>();
|
||||
|
||||
const Keys = z.enum(["id", "name", "email"]).or(z.never());
|
||||
const Person = z.partialRecord(Keys, z.string());
|
||||
expectTypeOf<z.infer<typeof Person>>().toEqualTypeOf<Partial<Record<"id" | "name" | "email", string>>>();
|
||||
});
|
||||
356
node_modules/zod/src/v4/classic/tests/recursive-types.test.ts
generated
vendored
Normal file
356
node_modules/zod/src/v4/classic/tests/recursive-types.test.ts
generated
vendored
Normal file
@@ -0,0 +1,356 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
test("recursion with z.lazy", () => {
|
||||
const data = {
|
||||
name: "I",
|
||||
subcategories: [
|
||||
{
|
||||
name: "A",
|
||||
subcategories: [
|
||||
{
|
||||
name: "1",
|
||||
subcategories: [
|
||||
{
|
||||
name: "a",
|
||||
subcategories: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const Category = z.object({
|
||||
name: z.string(),
|
||||
get subcategories() {
|
||||
return z.array(Category).optional().nullable();
|
||||
},
|
||||
});
|
||||
type Category = z.infer<typeof Category>;
|
||||
interface _Category {
|
||||
name: string;
|
||||
subcategories?: _Category[] | undefined | null;
|
||||
}
|
||||
expectTypeOf<Category>().toEqualTypeOf<_Category>();
|
||||
Category.parse(data);
|
||||
});
|
||||
|
||||
test("recursion involving union type", () => {
|
||||
const data = {
|
||||
value: 1,
|
||||
next: {
|
||||
value: 2,
|
||||
next: {
|
||||
value: 3,
|
||||
next: {
|
||||
value: 4,
|
||||
next: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const LL = z.object({
|
||||
value: z.number(),
|
||||
get next() {
|
||||
return LL.nullable();
|
||||
},
|
||||
});
|
||||
type LL = z.infer<typeof LL>;
|
||||
type _LL = {
|
||||
value: number;
|
||||
next: _LL | null;
|
||||
};
|
||||
expectTypeOf<LL>().toEqualTypeOf<_LL>();
|
||||
|
||||
LL.parse(data);
|
||||
});
|
||||
|
||||
test("mutual recursion - native", () => {
|
||||
const Alazy = z.object({
|
||||
val: z.number(),
|
||||
get b() {
|
||||
return Blazy;
|
||||
},
|
||||
});
|
||||
|
||||
const Blazy = z.object({
|
||||
val: z.number(),
|
||||
get a() {
|
||||
return Alazy.optional();
|
||||
},
|
||||
});
|
||||
const testData = {
|
||||
val: 1,
|
||||
b: {
|
||||
val: 5,
|
||||
a: {
|
||||
val: 3,
|
||||
b: {
|
||||
val: 4,
|
||||
a: {
|
||||
val: 2,
|
||||
b: {
|
||||
val: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
type Alazy = z.infer<typeof Alazy>;
|
||||
type Blazy = z.infer<typeof Blazy>;
|
||||
interface _Alazy {
|
||||
val: number;
|
||||
b: _Blazy;
|
||||
}
|
||||
interface _Blazy {
|
||||
val: number;
|
||||
a?: _Alazy | undefined;
|
||||
}
|
||||
expectTypeOf<Alazy>().toEqualTypeOf<_Alazy>();
|
||||
expectTypeOf<Blazy>().toEqualTypeOf<_Blazy>();
|
||||
Alazy.parse(testData);
|
||||
Blazy.parse(testData.b);
|
||||
|
||||
expect(() => Alazy.parse({ val: "asdf" })).toThrow();
|
||||
});
|
||||
|
||||
test("pick and omit with getter", () => {
|
||||
const Category = z.strictObject({
|
||||
name: z.string(),
|
||||
get subcategories() {
|
||||
return z.array(Category);
|
||||
},
|
||||
});
|
||||
|
||||
type Category = z.infer<typeof Category>;
|
||||
|
||||
interface _Category {
|
||||
name: string;
|
||||
subcategories: _Category[];
|
||||
}
|
||||
expectTypeOf<Category>().toEqualTypeOf<_Category>();
|
||||
|
||||
const PickedCategory = Category.pick({ name: true });
|
||||
const OmittedCategory = Category.omit({ subcategories: true });
|
||||
|
||||
const picked = { name: "test" };
|
||||
const omitted = { name: "test" };
|
||||
|
||||
PickedCategory.parse(picked);
|
||||
OmittedCategory.parse(omitted);
|
||||
|
||||
expect(() => PickedCategory.parse({ name: "test", subcategories: [] })).toThrow();
|
||||
expect(() => OmittedCategory.parse({ name: "test", subcategories: [] })).toThrow();
|
||||
});
|
||||
|
||||
test("deferred self-recursion", () => {
|
||||
const Feature = z.object({
|
||||
title: z.string(),
|
||||
get features(): z.ZodOptional<z.ZodArray<typeof Feature>> {
|
||||
return z.optional(z.array(Feature)); //.optional();
|
||||
},
|
||||
});
|
||||
// type Feature = z.infer<typeof Feature>;
|
||||
|
||||
const Output = z.object({
|
||||
id: z.int(), //.nonnegative(),
|
||||
name: z.string(),
|
||||
get features(): z.ZodArray<typeof Feature> {
|
||||
return Feature.array();
|
||||
},
|
||||
});
|
||||
type Output = z.output<typeof Output>;
|
||||
|
||||
type _Feature = {
|
||||
title: string;
|
||||
features?: _Feature[] | undefined;
|
||||
};
|
||||
|
||||
type _Output = {
|
||||
id: number;
|
||||
name: string;
|
||||
features: _Feature[];
|
||||
};
|
||||
|
||||
// expectTypeOf<Feature>().toEqualTypeOf<_Feature>();
|
||||
expectTypeOf<Output>().toEqualTypeOf<_Output>();
|
||||
});
|
||||
|
||||
test("deferred mutual recursion", () => {
|
||||
const Slot = z.object({
|
||||
slotCode: z.string(),
|
||||
|
||||
get blocks() {
|
||||
return z.array(Block);
|
||||
},
|
||||
});
|
||||
type Slot = z.infer<typeof Slot>;
|
||||
|
||||
const Block = z.object({
|
||||
blockCode: z.string(),
|
||||
get slots() {
|
||||
return z.array(Slot).optional();
|
||||
},
|
||||
});
|
||||
type Block = z.infer<typeof Block>;
|
||||
|
||||
const Page = z.object({
|
||||
slots: z.array(Slot),
|
||||
});
|
||||
type Page = z.infer<typeof Page>;
|
||||
|
||||
type _Slot = {
|
||||
slotCode: string;
|
||||
blocks: _Block[];
|
||||
};
|
||||
type _Block = {
|
||||
blockCode: string;
|
||||
slots?: _Slot[] | undefined;
|
||||
};
|
||||
type _Page = {
|
||||
slots: _Slot[];
|
||||
};
|
||||
expectTypeOf<Slot>().toEqualTypeOf<_Slot>();
|
||||
expectTypeOf<Block>().toEqualTypeOf<_Block>();
|
||||
expectTypeOf<Page>().toEqualTypeOf<_Page>();
|
||||
});
|
||||
|
||||
test("mutual recursion with meta", () => {
|
||||
const A = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
get b() {
|
||||
return B;
|
||||
},
|
||||
})
|
||||
.readonly()
|
||||
.meta({ id: "A" })
|
||||
.optional();
|
||||
|
||||
const B = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
get a() {
|
||||
return A;
|
||||
},
|
||||
})
|
||||
.readonly()
|
||||
.meta({ id: "B" });
|
||||
|
||||
type A = z.infer<typeof A>;
|
||||
type B = z.infer<typeof B>;
|
||||
|
||||
type _A =
|
||||
| Readonly<{
|
||||
name: string;
|
||||
b: _B;
|
||||
}>
|
||||
| undefined;
|
||||
// | undefined;
|
||||
type _B = Readonly<{
|
||||
name: string;
|
||||
a?: _A;
|
||||
}>;
|
||||
expectTypeOf<A>().toEqualTypeOf<_A>();
|
||||
expectTypeOf<B>().toEqualTypeOf<_B>();
|
||||
});
|
||||
|
||||
test("recursion compatibility", () => {
|
||||
// array
|
||||
const A = z.object({
|
||||
get array() {
|
||||
return A.array();
|
||||
},
|
||||
get optional() {
|
||||
return A.optional();
|
||||
},
|
||||
get nullable() {
|
||||
return A.nullable();
|
||||
},
|
||||
get nonoptional() {
|
||||
return A.nonoptional();
|
||||
},
|
||||
get readonly() {
|
||||
return A.readonly();
|
||||
},
|
||||
get describe() {
|
||||
return A.describe("A recursive type");
|
||||
},
|
||||
get meta() {
|
||||
return A.meta({ description: "A recursive type" });
|
||||
},
|
||||
get pipe() {
|
||||
return A.pipe(z.any());
|
||||
},
|
||||
get strict() {
|
||||
return A.strict();
|
||||
},
|
||||
get tuple() {
|
||||
return z.tuple([A, A]);
|
||||
},
|
||||
get object() {
|
||||
return z
|
||||
.object({
|
||||
subcategories: A,
|
||||
})
|
||||
.strict()
|
||||
.loose();
|
||||
},
|
||||
get union() {
|
||||
return z.union([A, A]);
|
||||
},
|
||||
get intersection() {
|
||||
return z.intersection(A, A);
|
||||
},
|
||||
get record() {
|
||||
return z.record(z.string(), A);
|
||||
},
|
||||
get map() {
|
||||
return z.map(z.string(), A);
|
||||
},
|
||||
get set() {
|
||||
return z.set(A);
|
||||
},
|
||||
get lazy() {
|
||||
return z.lazy(() => A);
|
||||
},
|
||||
get promise() {
|
||||
return z.promise(A);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
// biome-ignore lint: sadf
|
||||
export type RecursiveA = z.ZodUnion<
|
||||
[
|
||||
z.ZodObject<{
|
||||
a: z.ZodDefault<RecursiveA>;
|
||||
b: z.ZodPrefault<RecursiveA>;
|
||||
c: z.ZodNonOptional<RecursiveA>;
|
||||
d: z.ZodOptional<RecursiveA>;
|
||||
e: z.ZodNullable<RecursiveA>;
|
||||
g: z.ZodReadonly<RecursiveA>;
|
||||
h: z.ZodPipe<RecursiveA, z.ZodString>;
|
||||
i: z.ZodArray<RecursiveA>;
|
||||
j: z.ZodSet<RecursiveA>;
|
||||
k: z.ZodMap<RecursiveA, RecursiveA>;
|
||||
l: z.ZodRecord<z.ZodString, RecursiveA>;
|
||||
m: z.ZodUnion<[RecursiveA, RecursiveA]>;
|
||||
n: z.ZodIntersection<RecursiveA, RecursiveA>;
|
||||
o: z.ZodLazy<RecursiveA>;
|
||||
p: z.ZodPromise<RecursiveA>;
|
||||
q: z.ZodCatch<RecursiveA>;
|
||||
r: z.ZodSuccess<RecursiveA>;
|
||||
s: z.ZodTransform<RecursiveA, string>;
|
||||
t: z.ZodTuple<[RecursiveA, RecursiveA]>;
|
||||
u: z.ZodObject<{
|
||||
a: RecursiveA;
|
||||
}>;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
532
node_modules/zod/src/v4/classic/tests/refine.test.ts
generated
vendored
Normal file
532
node_modules/zod/src/v4/classic/tests/refine.test.ts
generated
vendored
Normal file
@@ -0,0 +1,532 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
describe("basic refinement functionality", () => {
|
||||
test("should create a new schema instance when refining", () => {
|
||||
const obj1 = z.object({
|
||||
first: z.string(),
|
||||
second: z.string(),
|
||||
});
|
||||
const obj2 = obj1.partial().strict();
|
||||
const obj3 = obj2.refine((data) => data.first || data.second, "Either first or second should be filled in.");
|
||||
|
||||
expect(obj1 === (obj2 as any)).toEqual(false);
|
||||
expect(obj2 === (obj3 as any)).toEqual(false);
|
||||
});
|
||||
|
||||
test("should validate according to refinement logic", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
first: z.string(),
|
||||
second: z.string(),
|
||||
})
|
||||
.partial()
|
||||
.strict()
|
||||
.refine((data) => data.first || data.second, "Either first or second should be filled in.");
|
||||
|
||||
// Should fail on empty object
|
||||
expect(() => schema.parse({})).toThrow();
|
||||
|
||||
// Should pass with first property
|
||||
expect(schema.parse({ first: "a" })).toEqual({ first: "a" });
|
||||
|
||||
// Should pass with second property
|
||||
expect(schema.parse({ second: "a" })).toEqual({ second: "a" });
|
||||
|
||||
// Should pass with both properties
|
||||
expect(schema.parse({ first: "a", second: "a" })).toEqual({ first: "a", second: "a" });
|
||||
});
|
||||
|
||||
test("should validate strict mode correctly", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
first: z.string(),
|
||||
second: z.string(),
|
||||
})
|
||||
.partial()
|
||||
.strict();
|
||||
|
||||
// Should throw on extra properties
|
||||
expect(() => schema.parse({ third: "adsf" })).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("refinement with custom error messages", () => {
|
||||
test("should use custom error message when validation fails", () => {
|
||||
const validationSchema = z
|
||||
.object({
|
||||
email: z.string().email(),
|
||||
password: z.string(),
|
||||
confirmPassword: z.string(),
|
||||
})
|
||||
.refine((data) => data.password === data.confirmPassword, "Both password and confirmation must match");
|
||||
|
||||
const result = validationSchema.safeParse({
|
||||
email: "aaaa@gmail.com",
|
||||
password: "aaaaaaaa",
|
||||
confirmPassword: "bbbbbbbb",
|
||||
});
|
||||
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues[0].message).toEqual("Both password and confirmation must match");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("async refinements", () => {
|
||||
test("should support async refinement functions", async () => {
|
||||
const validationSchema = z
|
||||
.object({
|
||||
email: z.string().email(),
|
||||
password: z.string(),
|
||||
confirmPassword: z.string(),
|
||||
})
|
||||
.refine(
|
||||
(data) => Promise.resolve().then(() => data.password === data.confirmPassword),
|
||||
"Both password and confirmation must match"
|
||||
);
|
||||
|
||||
// Should pass with matching passwords
|
||||
const validData = {
|
||||
email: "aaaa@gmail.com",
|
||||
password: "password",
|
||||
confirmPassword: "password",
|
||||
};
|
||||
|
||||
await expect(validationSchema.parseAsync(validData)).resolves.toEqual(validData);
|
||||
|
||||
// Should fail with non-matching passwords
|
||||
await expect(
|
||||
validationSchema.parseAsync({
|
||||
email: "aaaa@gmail.com",
|
||||
password: "password",
|
||||
confirmPassword: "different",
|
||||
})
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("early termination options", () => {
|
||||
test("should abort early with continue: false", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.superRefine((val, ctx) => {
|
||||
if (val.length < 2) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: "BAD",
|
||||
continue: false,
|
||||
});
|
||||
}
|
||||
})
|
||||
.refine((_) => false);
|
||||
|
||||
const result = schema.safeParse("");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(1);
|
||||
expect(result.error.issues[0].message).toEqual("BAD");
|
||||
}
|
||||
});
|
||||
|
||||
test("should abort early with fatal: true", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.superRefine((val, ctx) => {
|
||||
if (val.length < 2) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
fatal: true,
|
||||
message: "BAD",
|
||||
});
|
||||
}
|
||||
})
|
||||
.refine((_) => false);
|
||||
|
||||
const result = schema.safeParse("");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(1);
|
||||
expect(result.error.issues[0].message).toEqual("BAD");
|
||||
}
|
||||
});
|
||||
|
||||
test("should abort early with abort flag", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.refine((_) => false, { abort: true })
|
||||
.refine((_) => false);
|
||||
|
||||
const result = schema.safeParse("");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("custom error paths", () => {
|
||||
test("should use custom path in error message", async () => {
|
||||
const result = await z
|
||||
.object({ password: z.string(), confirm: z.string() })
|
||||
.refine((data) => data.confirm === data.password, { path: ["confirm"] })
|
||||
.safeParse({ password: "asdf", confirm: "qewr" });
|
||||
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues[0].path).toEqual(["confirm"]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("superRefine functionality", () => {
|
||||
test("should support multiple validation rules", () => {
|
||||
const Strings = z.array(z.string()).superRefine((val, ctx) => {
|
||||
if (val.length > 3) {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: "too_big",
|
||||
origin: "array",
|
||||
maximum: 3,
|
||||
inclusive: true,
|
||||
exact: true,
|
||||
message: "Too many items 😡",
|
||||
});
|
||||
}
|
||||
|
||||
if (val.length !== new Set(val).size) {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: "custom",
|
||||
message: `No duplicates allowed.`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Should fail with too many items and duplicates
|
||||
const result = Strings.safeParse(["asfd", "asfd", "asfd", "asfd"]);
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(2);
|
||||
expect(result.error.issues[0].message).toEqual("Too many items 😡");
|
||||
expect(result.error.issues[1].message).toEqual("No duplicates allowed.");
|
||||
}
|
||||
|
||||
// Should pass with valid input
|
||||
const validArray = ["asfd", "qwer"];
|
||||
expect(Strings.parse(validArray)).toEqual(validArray);
|
||||
});
|
||||
|
||||
test("should support async superRefine", async () => {
|
||||
const Strings = z.array(z.string()).superRefine(async (val, ctx) => {
|
||||
if (val.length > 3) {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: "too_big",
|
||||
origin: "array",
|
||||
maximum: 3,
|
||||
inclusive: true,
|
||||
message: "Too many items 😡",
|
||||
});
|
||||
}
|
||||
|
||||
if (val.length !== new Set(val).size) {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: "custom",
|
||||
message: `No duplicates allowed.`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Should fail with too many items and duplicates
|
||||
const result = await Strings.safeParseAsync(["asfd", "asfd", "asfd", "asfd"]);
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(2);
|
||||
}
|
||||
|
||||
// Should pass with valid input
|
||||
const validArray = ["asfd", "qwer"];
|
||||
await expect(Strings.parseAsync(validArray)).resolves.toEqual(validArray);
|
||||
});
|
||||
|
||||
test("should accept string as shorthand for custom error message", () => {
|
||||
const schema = z.string().superRefine((_, ctx) => {
|
||||
ctx.addIssue("bad stuff");
|
||||
});
|
||||
|
||||
const result = schema.safeParse("asdf");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues).toHaveLength(1);
|
||||
expect(result.error.issues[0].message).toEqual("bad stuff");
|
||||
}
|
||||
});
|
||||
|
||||
test("should respect fatal flag in superRefine", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.superRefine((val, ctx) => {
|
||||
if (val === "") {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: "custom",
|
||||
message: "foo",
|
||||
fatal: true,
|
||||
});
|
||||
}
|
||||
})
|
||||
.superRefine((val, ctx) => {
|
||||
if (val !== " ") {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: "custom",
|
||||
message: "bar",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const result = schema.safeParse("");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(1);
|
||||
expect(result.error.issues[0].message).toEqual("foo");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("chained refinements", () => {
|
||||
test("should collect all validation errors when appropriate", () => {
|
||||
const objectSchema = z
|
||||
.object({
|
||||
length: z.number(),
|
||||
size: z.number(),
|
||||
})
|
||||
.refine(({ length }) => length > 5, {
|
||||
path: ["length"],
|
||||
message: "length greater than 5",
|
||||
})
|
||||
.refine(({ size }) => size > 7, {
|
||||
path: ["size"],
|
||||
message: "size greater than 7",
|
||||
});
|
||||
|
||||
// Should fail with one error
|
||||
const r1 = objectSchema.safeParse({
|
||||
length: 4,
|
||||
size: 9,
|
||||
});
|
||||
expect(r1.success).toEqual(false);
|
||||
if (!r1.success) {
|
||||
expect(r1.error.issues.length).toEqual(1);
|
||||
expect(r1.error.issues[0].path).toEqual(["length"]);
|
||||
}
|
||||
|
||||
// Should fail with two errors
|
||||
const r2 = objectSchema.safeParse({
|
||||
length: 4,
|
||||
size: 3,
|
||||
});
|
||||
expect(r2.success).toEqual(false);
|
||||
if (!r2.success) {
|
||||
expect(r2.error.issues.length).toEqual(2);
|
||||
}
|
||||
|
||||
// Should pass with valid input
|
||||
const validData = {
|
||||
length: 6,
|
||||
size: 8,
|
||||
};
|
||||
expect(objectSchema.parse(validData)).toEqual(validData);
|
||||
});
|
||||
});
|
||||
|
||||
// Commented tests can be uncommented once type-checking issues are resolved
|
||||
/*
|
||||
describe("type refinement", () => {
|
||||
test("refinement type guard", () => {
|
||||
const validationSchema = z.object({
|
||||
a: z.string().refine((s): s is "a" => s === "a"),
|
||||
});
|
||||
type Input = z.input<typeof validationSchema>;
|
||||
type Schema = z.infer<typeof validationSchema>;
|
||||
|
||||
expectTypeOf<Input["a"]>().not.toEqualTypeOf<"a">();
|
||||
expectTypeOf<Input["a"]>().toEqualTypeOf<string>();
|
||||
|
||||
expectTypeOf<Schema["a"]>().toEqualTypeOf<"a">();
|
||||
expectTypeOf<Schema["a"]>().not.toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("superRefine - type narrowing", () => {
|
||||
type NarrowType = { type: string; age: number };
|
||||
const schema = z
|
||||
.object({
|
||||
type: z.string(),
|
||||
age: z.number(),
|
||||
})
|
||||
.nullable()
|
||||
.superRefine((arg, ctx): arg is NarrowType => {
|
||||
if (!arg) {
|
||||
// still need to make a call to ctx.addIssue
|
||||
ctx.addIssue({
|
||||
input: arg,
|
||||
code: "custom",
|
||||
message: "cannot be null",
|
||||
fatal: true,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<NarrowType>();
|
||||
|
||||
expect(schema.safeParse({ type: "test", age: 0 }).success).toEqual(true);
|
||||
expect(schema.safeParse(null).success).toEqual(false);
|
||||
});
|
||||
|
||||
test("chained mixed refining types", () => {
|
||||
type firstRefinement = { first: string; second: number; third: true };
|
||||
type secondRefinement = { first: "bob"; second: number; third: true };
|
||||
type thirdRefinement = { first: "bob"; second: 33; third: true };
|
||||
const schema = z
|
||||
.object({
|
||||
first: z.string(),
|
||||
second: z.number(),
|
||||
third: z.boolean(),
|
||||
})
|
||||
.nullable()
|
||||
.refine((arg): arg is firstRefinement => !!arg?.third)
|
||||
.superRefine((arg, ctx): arg is secondRefinement => {
|
||||
expectTypeOf<typeof arg>().toEqualTypeOf<firstRefinement>();
|
||||
if (arg.first !== "bob") {
|
||||
ctx.addIssue({
|
||||
input: arg,
|
||||
code: "custom",
|
||||
message: "`first` property must be `bob`",
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.refine((arg): arg is thirdRefinement => {
|
||||
expectTypeOf<typeof arg>().toEqualTypeOf<secondRefinement>();
|
||||
return arg.second === 33;
|
||||
});
|
||||
|
||||
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<thirdRefinement>();
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
test("when", () => {
|
||||
const schema = z
|
||||
.strictObject({
|
||||
password: z.string().min(8),
|
||||
confirmPassword: z.string(),
|
||||
other: z.string(),
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
console.log("running check...");
|
||||
console.log(data);
|
||||
console.log(data.password);
|
||||
return data.password === data.confirmPassword;
|
||||
},
|
||||
{
|
||||
message: "Passwords do not match",
|
||||
path: ["confirmPassword"],
|
||||
when(payload) {
|
||||
if (payload.value === undefined) return false;
|
||||
if (payload.value === null) return false;
|
||||
// no issues with confirmPassword or password
|
||||
return payload.issues.every((iss) => iss.path?.[0] !== "confirmPassword" && iss.path?.[0] !== "password");
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect(schema.safeParse(undefined)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "object",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected object, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse(null)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "object",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected object, received null"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(
|
||||
schema.safeParse({
|
||||
password: "asdf",
|
||||
confirmPassword: "asdfg",
|
||||
other: "qwer",
|
||||
})
|
||||
).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 8,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"password"
|
||||
],
|
||||
"message": "Too small: expected string to have >=8 characters"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(
|
||||
schema.safeParse({
|
||||
password: "asdf",
|
||||
confirmPassword: "asdfg",
|
||||
other: 1234,
|
||||
})
|
||||
).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 8,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"password"
|
||||
],
|
||||
"message": "Too small: expected string to have >=8 characters"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"other"
|
||||
],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
204
node_modules/zod/src/v4/classic/tests/registries.test.ts
generated
vendored
Normal file
204
node_modules/zod/src/v4/classic/tests/registries.test.ts
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("globalRegistry", () => {
|
||||
const reg = z.registry();
|
||||
|
||||
const a = z.string();
|
||||
reg.add(a);
|
||||
expect(reg.has(a)).toEqual(true);
|
||||
|
||||
reg.remove(a);
|
||||
expect(reg.has(a)).toEqual(false);
|
||||
|
||||
a.register(z.globalRegistry, { field: "sup" });
|
||||
expect(z.globalRegistry.has(a)).toEqual(true);
|
||||
expect(z.globalRegistry.get(a)).toEqual({ field: "sup" });
|
||||
|
||||
z.globalRegistry.remove(a);
|
||||
expect(z.globalRegistry.has(a)).toEqual(false);
|
||||
});
|
||||
|
||||
test("z.registry", () => {
|
||||
const fieldRegistry = z.registry<{ name: string; description: string }>();
|
||||
|
||||
const a = z.string();
|
||||
fieldRegistry.add(a, { name: "hello", description: "world" });
|
||||
const a_meta = fieldRegistry.get(a);
|
||||
expect(a_meta).toEqual({ name: "hello", description: "world" });
|
||||
|
||||
fieldRegistry.remove(a);
|
||||
expect(fieldRegistry.has(a)).toEqual(false);
|
||||
expect(fieldRegistry.get(a)).toEqual(undefined);
|
||||
});
|
||||
|
||||
test("z.registry no metadata", () => {
|
||||
const fieldRegistry = z.registry();
|
||||
|
||||
const a = z.string();
|
||||
fieldRegistry.add(a);
|
||||
fieldRegistry.add(z.number());
|
||||
expect(fieldRegistry.get(a)).toEqual(undefined);
|
||||
expect(fieldRegistry.has(a)).toEqual(true);
|
||||
});
|
||||
|
||||
test("z.registry with schema constraints", () => {
|
||||
const fieldRegistry = z.registry<{ name: string; description: string }, z.ZodString>();
|
||||
|
||||
const a = z.string();
|
||||
fieldRegistry.add(a, { name: "hello", description: "world" });
|
||||
// @ts-expect-error
|
||||
fieldRegistry.add(z.number(), { name: "test" });
|
||||
// @ts-expect-error
|
||||
z.number().register(fieldRegistry, { name: "test", description: "test" });
|
||||
});
|
||||
|
||||
// test("z.namedRegistry", () => {
|
||||
// const namedReg = z
|
||||
// .namedRegistry<{ name: string; description: string }>()
|
||||
// .add(z.string(), { name: "hello", description: "world" })
|
||||
// .add(z.number(), { name: "number", description: "number" });
|
||||
|
||||
// expect(namedReg.get("hello")).toEqual({
|
||||
// name: "hello",
|
||||
// description: "world",
|
||||
// });
|
||||
// expect(namedReg.has("hello")).toEqual(true);
|
||||
// expect(namedReg.get("number")).toEqual({
|
||||
// name: "number",
|
||||
// description: "number",
|
||||
// });
|
||||
|
||||
// // @ts-expect-error
|
||||
// namedReg.get("world");
|
||||
// // @ts-expect-error
|
||||
// expect(namedReg.get("world")).toEqual(undefined);
|
||||
|
||||
// const hello = namedReg.get("hello");
|
||||
// expect(hello).toEqual({ name: "hello", description: "world" });
|
||||
// expectTypeOf<typeof hello>().toEqualTypeOf<{
|
||||
// name: "hello";
|
||||
// description: "world";
|
||||
// }>();
|
||||
// expectTypeOf<typeof namedReg.items>().toEqualTypeOf<{
|
||||
// hello: { name: "hello"; description: "world" };
|
||||
// number: { name: "number"; description: "number" };
|
||||
// }>();
|
||||
// });
|
||||
|
||||
test("output type in registry meta", () => {
|
||||
const reg = z.registry<{ out: z.$output }>();
|
||||
const a = z.string();
|
||||
reg.add(a, { out: "asdf" });
|
||||
// @ts-expect-error
|
||||
reg.add(a, 1234);
|
||||
expectTypeOf(reg.get(a)).toEqualTypeOf<{ out: string } | undefined>();
|
||||
});
|
||||
|
||||
test("output type in registry meta - objects and arrays", () => {
|
||||
const reg = z.registry<{ name: string; examples: z.$output[] }>();
|
||||
const a = z.string();
|
||||
reg.add(a, { name: "hello", examples: ["world"] });
|
||||
|
||||
// @ts-expect-error
|
||||
reg.add(a, { name: "hello", examples: "world" });
|
||||
expectTypeOf(reg.get(a)).toEqualTypeOf<{ name: string; examples: string[] } | undefined>();
|
||||
});
|
||||
|
||||
test("input type in registry meta", () => {
|
||||
const reg = z.registry<{ in: z.$input }>();
|
||||
const a = z.pipe(z.number(), z.transform(String));
|
||||
reg.add(a, { in: 1234 });
|
||||
// @ts-expect-error
|
||||
reg.add(a, "1234");
|
||||
expectTypeOf(reg.get(a)).toEqualTypeOf<{ in: number } | undefined>();
|
||||
});
|
||||
|
||||
test("input type in registry meta - objects and arrays", () => {
|
||||
const reg = z.registry<{ name: string; examples: z.$input[] }>();
|
||||
const a = z.pipe(z.number(), z.transform(String));
|
||||
reg.add(a, { name: "hello", examples: [1234] });
|
||||
|
||||
// @ts-expect-error
|
||||
reg.add(a, { name: "hello", examples: "world" });
|
||||
expectTypeOf(reg.get(a)).toEqualTypeOf<{ name: string; examples: number[] } | undefined>();
|
||||
});
|
||||
|
||||
test(".meta method", () => {
|
||||
const a1 = z.string();
|
||||
const a2 = a1.meta({ name: "hello" });
|
||||
|
||||
expect(a1.meta()).toEqual(undefined);
|
||||
expect(a2.meta()).toEqual({ name: "hello" });
|
||||
expect(a1 === a2).toEqual(false);
|
||||
});
|
||||
|
||||
test(".meta metadata does not bubble up", () => {
|
||||
const a1 = z.string().meta({ name: "hello" });
|
||||
const a2 = a1.optional();
|
||||
|
||||
expect(a1.meta()).toEqual({ name: "hello" });
|
||||
expect(a2.meta()).toEqual(undefined);
|
||||
});
|
||||
|
||||
test(".describe", () => {
|
||||
const a1 = z.string();
|
||||
const a2 = a1.describe("Hello");
|
||||
|
||||
expect(a1.description).toEqual(undefined);
|
||||
expect(a2.description).toEqual("Hello");
|
||||
});
|
||||
|
||||
test("inherit across clone", () => {
|
||||
const A = z.string().meta({ a: true });
|
||||
expect(A.meta()).toEqual({ a: true });
|
||||
const B = A.meta({ b: true });
|
||||
expect(B.meta()).toEqual({ a: true, b: true });
|
||||
const C = B.describe("hello");
|
||||
expect(C.meta()).toEqual({ a: true, b: true, description: "hello" });
|
||||
});
|
||||
|
||||
test("loose examples", () => {
|
||||
z.string().register(z.globalRegistry, {
|
||||
examples: ["example"],
|
||||
});
|
||||
});
|
||||
|
||||
test("function meta witout replacement", () => {
|
||||
const myReg = z.registry<{
|
||||
defaulter: (arg: string, test: boolean) => number;
|
||||
}>();
|
||||
|
||||
const mySchema = z.date();
|
||||
myReg.add(mySchema, {
|
||||
defaulter: (arg, _test) => {
|
||||
return arg.length;
|
||||
},
|
||||
});
|
||||
|
||||
expect(myReg.get(mySchema)!.defaulter("hello", true)).toEqual(5);
|
||||
});
|
||||
|
||||
test("function meta with replacement", () => {
|
||||
const myReg = z.registry<{
|
||||
defaulter: (arg: z.$input, test: boolean) => z.$output;
|
||||
}>();
|
||||
|
||||
const mySchema = z.string().transform((val) => val.length);
|
||||
myReg.add(mySchema, {
|
||||
defaulter: (arg, _test) => {
|
||||
return arg.length;
|
||||
},
|
||||
});
|
||||
|
||||
expect(myReg.get(mySchema)!.defaulter("hello", true)).toEqual(5);
|
||||
});
|
||||
|
||||
test("test .clear()", () => {
|
||||
const reg = z.registry();
|
||||
const a = z.string();
|
||||
reg.add(a);
|
||||
expect(reg.has(a)).toEqual(true);
|
||||
reg.clear();
|
||||
expect(reg.has(a)).toEqual(false);
|
||||
});
|
||||
179
node_modules/zod/src/v4/classic/tests/set.test.ts
generated
vendored
Normal file
179
node_modules/zod/src/v4/classic/tests/set.test.ts
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const stringSet = z.set(z.string());
|
||||
type stringSet = z.infer<typeof stringSet>;
|
||||
|
||||
const minTwo = z.set(z.string()).min(2);
|
||||
const maxTwo = z.set(z.string()).max(2);
|
||||
const justTwo = z.set(z.string()).size(2);
|
||||
const nonEmpty = z.set(z.string()).nonempty();
|
||||
const nonEmptyMax = z.set(z.string()).nonempty().max(2);
|
||||
|
||||
test("type inference", () => {
|
||||
expectTypeOf<stringSet>().toEqualTypeOf<Set<string>>();
|
||||
});
|
||||
|
||||
test("valid parse", () => {
|
||||
const result = stringSet.safeParse(new Set(["first", "second"]));
|
||||
expect(result.success).toEqual(true);
|
||||
expect(result.data!.has("first")).toEqual(true);
|
||||
expect(result.data!.has("second")).toEqual(true);
|
||||
expect(result.data!.has("third")).toEqual(false);
|
||||
|
||||
expect(() => {
|
||||
minTwo.parse(new Set(["a", "b"]));
|
||||
minTwo.parse(new Set(["a", "b", "c"]));
|
||||
maxTwo.parse(new Set(["a", "b"]));
|
||||
maxTwo.parse(new Set(["a"]));
|
||||
justTwo.parse(new Set(["a", "b"]));
|
||||
nonEmpty.parse(new Set(["a"]));
|
||||
nonEmptyMax.parse(new Set(["a"]));
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
test("valid parse async", async () => {
|
||||
const result = await stringSet.spa(new Set(["first", "second"]));
|
||||
expect(result.success).toEqual(true);
|
||||
expect(result.data!.has("first")).toEqual(true);
|
||||
expect(result.data!.has("second")).toEqual(true);
|
||||
expect(result.data!.has("third")).toEqual(false);
|
||||
|
||||
const asyncResult = await stringSet.safeParse(new Set(["first", "second"]));
|
||||
expect(asyncResult.success).toEqual(true);
|
||||
expect(asyncResult.data!.has("first")).toEqual(true);
|
||||
expect(asyncResult.data!.has("second")).toEqual(true);
|
||||
expect(asyncResult.data!.has("third")).toEqual(false);
|
||||
});
|
||||
|
||||
test("valid parse: size-related methods", () => {
|
||||
expect(() => {
|
||||
minTwo.parse(new Set(["a", "b"]));
|
||||
minTwo.parse(new Set(["a", "b", "c"]));
|
||||
maxTwo.parse(new Set(["a", "b"]));
|
||||
maxTwo.parse(new Set(["a"]));
|
||||
justTwo.parse(new Set(["a", "b"]));
|
||||
nonEmpty.parse(new Set(["a"]));
|
||||
nonEmptyMax.parse(new Set(["a"]));
|
||||
}).not.toThrow();
|
||||
|
||||
const sizeZeroResult = stringSet.parse(new Set());
|
||||
expect(sizeZeroResult.size).toBe(0);
|
||||
|
||||
const sizeTwoResult = minTwo.parse(new Set(["a", "b"]));
|
||||
expect(sizeTwoResult.size).toBe(2);
|
||||
});
|
||||
|
||||
test("failing when parsing empty set in nonempty ", () => {
|
||||
const result = nonEmpty.safeParse(new Set());
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error!.issues[0].code).toEqual("too_small");
|
||||
});
|
||||
|
||||
test("failing when set is smaller than min() ", () => {
|
||||
const result = minTwo.safeParse(new Set(["just_one"]));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error!.issues[0].code).toEqual("too_small");
|
||||
});
|
||||
|
||||
test("failing when set is bigger than max() ", () => {
|
||||
const result = maxTwo.safeParse(new Set(["one", "two", "three"]));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error!.issues[0].code).toEqual("too_big");
|
||||
});
|
||||
|
||||
test("doesn’t throw when an empty set is given", () => {
|
||||
const result = stringSet.safeParse(new Set([]));
|
||||
expect(result.success).toEqual(true);
|
||||
});
|
||||
|
||||
test("throws when a Map is given", () => {
|
||||
const result = stringSet.safeParse(new Map([]));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "set",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected set, received Map"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("throws when the given set has invalid input", () => {
|
||||
const result = stringSet.safeParse(new Set([Symbol()]));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received symbol"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("throws when the given set has multiple invalid entries", () => {
|
||||
const result = stringSet.safeParse(new Set([1, 2] as any[]));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(2);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("min/max", async () => {
|
||||
const schema = z.set(z.string()).min(4).max(5);
|
||||
|
||||
const r1 = schema.safeParse(new Set(["a", "b", "c", "d"]));
|
||||
expect(r1.success).toEqual(true);
|
||||
|
||||
const r2 = schema.safeParse(new Set(["a", "b", "c"]));
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"message": "Too small: expected set to have >4 items",
|
||||
"minimum": 4,
|
||||
"origin": "set",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
||||
const r3 = schema.safeParse(new Set(["a", "b", "c", "d", "e", "f"]));
|
||||
expect(r3.success).toEqual(false);
|
||||
expect(r3.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"maximum": 5,
|
||||
"message": "Too big: expected set to have <5 items",
|
||||
"origin": "set",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
57
node_modules/zod/src/v4/classic/tests/standard-schema.test.ts
generated
vendored
Normal file
57
node_modules/zod/src/v4/classic/tests/standard-schema.test.ts
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("length checks", async () => {
|
||||
const schema = z.string();
|
||||
const result = await schema["~standard"].validate(12);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"issues": [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received number",
|
||||
"path": [],
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("length checks", async () => {
|
||||
const schema = z.string();
|
||||
const result = await schema["~standard"].validate("asdf");
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"value": "asdf",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("length checks", async () => {
|
||||
const schema = z.string().refine(async (val) => val.length > 5);
|
||||
const result = await schema["~standard"].validate(12);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"issues": [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received number",
|
||||
"path": [],
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("length checks", async () => {
|
||||
const schema = z.string().refine(async (val) => val.length > 5);
|
||||
const result = await schema["~standard"].validate("234134134");
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"value": "234134134",
|
||||
}
|
||||
`);
|
||||
});
|
||||
109
node_modules/zod/src/v4/classic/tests/string-formats.test.ts
generated
vendored
Normal file
109
node_modules/zod/src/v4/classic/tests/string-formats.test.ts
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("string format methods", () => {
|
||||
const a = z.email().min(10);
|
||||
const b = z.email().max(10);
|
||||
const c = z.email().length(10);
|
||||
const d = z.email().uppercase();
|
||||
const e = z.email().lowercase();
|
||||
|
||||
// Positive and negative cases for `a`
|
||||
expect(a.safeParse("longemail@example.com").success).toBe(true); // Positive
|
||||
expect(a.safeParse("ort@e.co").success).toBe(false); // Negative
|
||||
|
||||
// Positive and negative cases for `b`
|
||||
expect(b.safeParse("sho@e.co").success).toBe(true); // Positive
|
||||
expect(b.safeParse("longemail@example.com").success).toBe(false); // Negative
|
||||
|
||||
// Positive and negative cases for `c`
|
||||
expect(c.safeParse("56780@e.co").success).toBe(true); // Positive
|
||||
expect(c.safeParse("shoasdfasdfrt@e.co").success).toBe(false); // Negative
|
||||
|
||||
// Positive and negative cases for `d`
|
||||
expect(d.safeParse("EMAIL@EXAMPLE.COM").success).toBe(true); // Positive
|
||||
expect(d.safeParse("email@example.com").success).toBe(false); // Negative
|
||||
|
||||
// Positive and negative cases for `e`
|
||||
expect(e.safeParse("email@example.com").success).toBe(true); // Positive
|
||||
expect(e.safeParse("EMAIL@EXAMPLE.COM").success).toBe(false); // Negative
|
||||
});
|
||||
|
||||
test("z.stringFormat", () => {
|
||||
const ccRegex = /^(?:\d{14,19}|\d{4}(?: \d{3,6}){2,4}|\d{4}(?:-\d{3,6}){2,4})$/u;
|
||||
|
||||
const a = z
|
||||
.stringFormat("creditCard", (val) => ccRegex.test(val), {
|
||||
error: `Invalid credit card number`,
|
||||
})
|
||||
.refine((_) => false, "Also bad");
|
||||
|
||||
expect(a.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "creditCard",
|
||||
"path": [],
|
||||
"message": "Invalid credit card number"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Also bad"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(a.safeParse("1234-5678-9012-3456")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Also bad"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(a.def.pattern).toMatchInlineSnapshot(`undefined`);
|
||||
|
||||
const b = z
|
||||
.stringFormat("creditCard", ccRegex, {
|
||||
abort: true,
|
||||
error: `Invalid credit card number`,
|
||||
})
|
||||
.refine((_) => false, "Also bad");
|
||||
|
||||
expect(b.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "creditCard",
|
||||
"path": [],
|
||||
"message": "Invalid credit card number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(b.safeParse("1234-5678-9012-3456")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Also bad"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(b.def.pattern).toMatchInlineSnapshot(
|
||||
`/\\^\\(\\?:\\\\d\\{14,19\\}\\|\\\\d\\{4\\}\\(\\?: \\\\d\\{3,6\\}\\)\\{2,4\\}\\|\\\\d\\{4\\}\\(\\?:-\\\\d\\{3,6\\}\\)\\{2,4\\}\\)\\$/u`
|
||||
);
|
||||
});
|
||||
881
node_modules/zod/src/v4/classic/tests/string.test.ts
generated
vendored
Normal file
881
node_modules/zod/src/v4/classic/tests/string.test.ts
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
66
node_modules/zod/src/v4/classic/tests/stringbool.test.ts
generated
vendored
Normal file
66
node_modules/zod/src/v4/classic/tests/stringbool.test.ts
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("z.stringbool", () => {
|
||||
const a = z.stringbool();
|
||||
type a = z.infer<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<boolean>();
|
||||
type a_in = z.input<typeof a>;
|
||||
expectTypeOf<a_in>().toEqualTypeOf<string>();
|
||||
|
||||
expect(z.parse(a, "true")).toEqual(true);
|
||||
expect(z.parse(a, "yes")).toEqual(true);
|
||||
expect(z.parse(a, "1")).toEqual(true);
|
||||
expect(z.parse(a, "on")).toEqual(true);
|
||||
expect(z.parse(a, "y")).toEqual(true);
|
||||
expect(z.parse(a, "enabled")).toEqual(true);
|
||||
expect(z.parse(a, "TRUE")).toEqual(true);
|
||||
|
||||
expect(z.parse(a, "false")).toEqual(false);
|
||||
expect(z.parse(a, "no")).toEqual(false);
|
||||
expect(z.parse(a, "0")).toEqual(false);
|
||||
expect(z.parse(a, "off")).toEqual(false);
|
||||
expect(z.parse(a, "n")).toEqual(false);
|
||||
expect(z.parse(a, "disabled")).toEqual(false);
|
||||
expect(z.parse(a, "FALSE")).toEqual(false);
|
||||
|
||||
expect(z.safeParse(a, "other")).toMatchObject({ success: false });
|
||||
expect(z.safeParse(a, "")).toMatchObject({ success: false });
|
||||
expect(z.safeParse(a, undefined)).toMatchObject({ success: false });
|
||||
expect(z.safeParse(a, {})).toMatchObject({ success: false });
|
||||
expect(z.safeParse(a, true)).toMatchObject({ success: false });
|
||||
expect(z.safeParse(a, false)).toMatchObject({ success: false });
|
||||
});
|
||||
|
||||
test("custom values", () => {
|
||||
const b = z.stringbool({
|
||||
truthy: ["y"],
|
||||
falsy: ["N"],
|
||||
});
|
||||
expect(z.parse(b, "y")).toEqual(true);
|
||||
expect(z.parse(b, "Y")).toEqual(true);
|
||||
expect(z.parse(b, "n")).toEqual(false);
|
||||
expect(z.parse(b, "N")).toEqual(false);
|
||||
expect(z.safeParse(b, "true")).toMatchObject({ success: false });
|
||||
expect(z.safeParse(b, "false")).toMatchObject({ success: false });
|
||||
});
|
||||
|
||||
test("custom values - case sensitive", () => {
|
||||
const c = z.stringbool({
|
||||
truthy: ["y"],
|
||||
falsy: ["N"],
|
||||
case: "sensitive",
|
||||
});
|
||||
expect(z.parse(c, "y")).toEqual(true);
|
||||
expect(z.safeParse(c, "Y")).toMatchObject({ success: false });
|
||||
expect(z.parse(c, "N")).toEqual(false);
|
||||
expect(z.safeParse(c, "n")).toMatchObject({ success: false });
|
||||
expect(z.safeParse(c, "TRUE")).toMatchObject({ success: false });
|
||||
});
|
||||
|
||||
// test custom error messages
|
||||
test("z.stringbool with custom error messages", () => {
|
||||
const a = z.stringbool("wrong!");
|
||||
|
||||
expect(() => a.parse("")).toThrowError("wrong!");
|
||||
});
|
||||
758
node_modules/zod/src/v4/classic/tests/template-literal.test.ts
generated
vendored
Normal file
758
node_modules/zod/src/v4/classic/tests/template-literal.test.ts
generated
vendored
Normal file
@@ -0,0 +1,758 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const empty = z.templateLiteral([]);
|
||||
const hello = z.templateLiteral(["hello"]);
|
||||
const world = z.templateLiteral(["", z.literal("world")]);
|
||||
const one = z.templateLiteral([1]);
|
||||
const two = z.templateLiteral(["", z.literal(2)]);
|
||||
const truee = z.templateLiteral([true]);
|
||||
const anotherTrue = z.templateLiteral(["", z.literal(true)]);
|
||||
const falsee = z.templateLiteral([false]);
|
||||
const anotherFalse = z.templateLiteral(["", z.literal(false)]);
|
||||
const nulll = z.templateLiteral([null]);
|
||||
const anotherNull = z.templateLiteral(["", z.null()]);
|
||||
const undefinedd = z.templateLiteral([undefined]);
|
||||
const anotherUndefined = z.templateLiteral(["", z.undefined()]);
|
||||
const anyString = z.templateLiteral(["", z.string()]);
|
||||
const lazyString = z.templateLiteral(["", z.lazy(() => z.string())]);
|
||||
const anyNumber = z.templateLiteral(["", z.number()]);
|
||||
const anyInt = z.templateLiteral(["", z.number().int()]);
|
||||
// const anyFiniteNumber = z.templateLiteral(["", z.number().finite()]);
|
||||
// const anyNegativeNumber = z.templateLiteral(["", z.number().negative()]);
|
||||
// const anyPositiveNumber = z.templateLiteral(["", z.number().positive()]);
|
||||
// const zeroButInADumbWay = z.templateLiteral(["", z.number().nonnegative().nonpositive()]);
|
||||
// const finiteButInADumbWay = z.templateLiteral(["", z.number().min(5).max(10)]);
|
||||
const bool = z.templateLiteral(["", z.boolean()]);
|
||||
const bigone = z.templateLiteral(["", z.literal(BigInt(1))]);
|
||||
const anyBigint = z.templateLiteral(["", z.bigint()]);
|
||||
const nullableYo = z.templateLiteral(["", z.nullable(z.literal("yo"))]);
|
||||
const nullableString = z.templateLiteral(["", z.nullable(z.string())]);
|
||||
const optionalYeah = z.templateLiteral(["", z.literal("yeah").optional()]);
|
||||
|
||||
const optionalString = z.templateLiteral(["", z.string().optional()]);
|
||||
const optionalNumber = z.templateLiteral(["", z.number().optional()]);
|
||||
const nullishBruh = z.templateLiteral(["", z.literal("bruh").nullish()]);
|
||||
const nullishString = z.templateLiteral(["", z.string().nullish()]);
|
||||
const cuid = z.templateLiteral(["", z.string().cuid()]);
|
||||
const cuidZZZ = z.templateLiteral(["", z.string().cuid(), "ZZZ"]);
|
||||
const cuid2 = z.templateLiteral(["", z.string().cuid2()]);
|
||||
const datetime = z.templateLiteral(["", z.string().datetime()]);
|
||||
const email = z.templateLiteral(["", z.string().email()]);
|
||||
// const ip = z.templateLiteral(["", z.string().ip()]);
|
||||
const ipv4 = z.templateLiteral(["", z.string().ipv4()]);
|
||||
const ipv6 = z.templateLiteral(["", z.string().ipv6()]);
|
||||
const ulid = z.templateLiteral(["", z.string().ulid()]);
|
||||
const uuid = z.templateLiteral(["", z.string().uuid()]);
|
||||
const stringAToZ = z.templateLiteral(["", z.string().regex(/^[a-z]+$/)]);
|
||||
const stringStartsWith = z.templateLiteral(["", z.string().startsWith("hello")]);
|
||||
const stringEndsWith = z.templateLiteral(["", z.string().endsWith("world")]);
|
||||
const stringMax5 = z.templateLiteral(["", z.string().max(5)]);
|
||||
const stringMin5 = z.templateLiteral(["", z.string().min(5)]);
|
||||
const stringLen5 = z.templateLiteral(["", z.string().length(5)]);
|
||||
const stringMin5Max10 = z.templateLiteral(["", z.string().min(5).max(10)]);
|
||||
const stringStartsWithMax5 = z.templateLiteral(["", z.string().startsWith("hello").max(5)]);
|
||||
const brandedString = z.templateLiteral(["", z.string().min(1).brand("myBrand")]);
|
||||
// const anything = z.templateLiteral(["", z.any()]);
|
||||
|
||||
const url = z.templateLiteral(["https://", z.string().regex(/\w+/), ".", z.enum(["com", "net"])]);
|
||||
|
||||
const measurement = z.templateLiteral([
|
||||
"",
|
||||
z.number().finite(),
|
||||
z.enum(["px", "em", "rem", "vh", "vw", "vmin", "vmax"]).optional(),
|
||||
]);
|
||||
|
||||
const connectionString = z.templateLiteral([
|
||||
"mongodb://",
|
||||
z
|
||||
.templateLiteral([
|
||||
"",
|
||||
z.string().regex(/\w+/).describe("username"),
|
||||
":",
|
||||
z.string().regex(/\w+/).describe("password"),
|
||||
"@",
|
||||
])
|
||||
.optional(),
|
||||
z.string().regex(/\w+/).describe("host"),
|
||||
":",
|
||||
z.number().finite().int().positive().describe("port"),
|
||||
z
|
||||
.templateLiteral([
|
||||
"/",
|
||||
z.string().regex(/\w+/).optional().describe("defaultauthdb"),
|
||||
z
|
||||
.templateLiteral([
|
||||
"?",
|
||||
z
|
||||
.string()
|
||||
.regex(/^\w+=\w+(&\w+=\w+)*$/)
|
||||
.optional()
|
||||
.describe("options"),
|
||||
])
|
||||
.optional(),
|
||||
])
|
||||
.optional(),
|
||||
]);
|
||||
|
||||
test("template literal type inference", () => {
|
||||
expectTypeOf<z.infer<typeof empty>>().toEqualTypeOf<``>();
|
||||
expectTypeOf<z.infer<typeof hello>>().toEqualTypeOf<`hello`>();
|
||||
expectTypeOf<z.infer<typeof world>>().toEqualTypeOf<`world`>();
|
||||
expectTypeOf<z.infer<typeof one>>().toEqualTypeOf<`1`>();
|
||||
expectTypeOf<z.infer<typeof two>>().toEqualTypeOf<`2`>();
|
||||
expectTypeOf<z.infer<typeof truee>>().toEqualTypeOf<`true`>();
|
||||
expectTypeOf<z.infer<typeof anotherTrue>>().toEqualTypeOf<`true`>();
|
||||
expectTypeOf<z.infer<typeof falsee>>().toEqualTypeOf<`false`>();
|
||||
expectTypeOf<z.infer<typeof anotherFalse>>().toEqualTypeOf<`false`>();
|
||||
expectTypeOf<z.infer<typeof nulll>>().toEqualTypeOf<`null`>();
|
||||
expectTypeOf<z.infer<typeof anotherNull>>().toEqualTypeOf<`null`>();
|
||||
expectTypeOf<z.infer<typeof undefinedd>>().toEqualTypeOf<``>();
|
||||
expectTypeOf<z.infer<typeof anotherUndefined>>().toEqualTypeOf<``>();
|
||||
expectTypeOf<z.infer<typeof anyString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof lazyString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof anyNumber>>().toEqualTypeOf<`${number}`>();
|
||||
expectTypeOf<z.infer<typeof anyInt>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof anyFiniteNumber>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof anyNegativeNumber>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof anyPositiveNumber>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof zeroButInADumbWay>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof finiteButInADumbWay>>().toEqualTypeOf<`${number}`>();
|
||||
expectTypeOf<z.infer<typeof bool>>().toEqualTypeOf<`true` | `false`>();
|
||||
expectTypeOf<z.infer<typeof bigone>>().toEqualTypeOf<`${bigint}`>();
|
||||
expectTypeOf<z.infer<typeof anyBigint>>().toEqualTypeOf<`${bigint}`>();
|
||||
expectTypeOf<z.infer<typeof nullableYo>>().toEqualTypeOf<`yo` | `null`>();
|
||||
expectTypeOf<z.infer<typeof nullableString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof optionalYeah>>().toEqualTypeOf<`yeah` | ``>();
|
||||
expectTypeOf<z.infer<typeof optionalString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof optionalNumber>>().toEqualTypeOf<`${number}` | ``>();
|
||||
expectTypeOf<z.infer<typeof nullishBruh>>().toEqualTypeOf<`bruh` | `null` | ``>();
|
||||
expectTypeOf<z.infer<typeof nullishString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof cuid>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof cuidZZZ>>().toEqualTypeOf<`${string}ZZZ`>();
|
||||
expectTypeOf<z.infer<typeof cuid2>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof datetime>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof email>>().toEqualTypeOf<string>();
|
||||
// expectTypeOf<z.infer<typeof ip>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof ipv4>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof ipv6>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof ulid>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof uuid>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringAToZ>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringStartsWith>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringEndsWith>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringMax5>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringMin5>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringLen5>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringMin5Max10>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringStartsWithMax5>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof brandedString>>().toEqualTypeOf<`${string & z.core.$brand<"myBrand">}`>();
|
||||
|
||||
// expectTypeOf<z.infer<typeof anything>>().toEqualTypeOf<`${any}`>();
|
||||
|
||||
expectTypeOf<z.infer<typeof url>>().toEqualTypeOf<`https://${string}.com` | `https://${string}.net`>();
|
||||
|
||||
expectTypeOf<z.infer<typeof measurement>>().toEqualTypeOf<
|
||||
| `${number}`
|
||||
| `${number}px`
|
||||
| `${number}em`
|
||||
| `${number}rem`
|
||||
| `${number}vh`
|
||||
| `${number}vw`
|
||||
| `${number}vmin`
|
||||
| `${number}vmax`
|
||||
>();
|
||||
|
||||
expectTypeOf<z.infer<typeof connectionString>>().toEqualTypeOf<
|
||||
| `mongodb://${string}:${number}`
|
||||
| `mongodb://${string}:${number}/${string}`
|
||||
| `mongodb://${string}:${number}/${string}?${string}`
|
||||
| `mongodb://${string}:${string}@${string}:${number}`
|
||||
| `mongodb://${string}:${string}@${string}:${number}/${string}`
|
||||
| `mongodb://${string}:${string}@${string}:${number}/${string}?${string}`
|
||||
>();
|
||||
});
|
||||
|
||||
test("template literal unsupported args", () => {
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.object({})])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.array(z.object({}))])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.union([z.object({}), z.string()])])
|
||||
).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => z.templateLiteral([z.date()])).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.custom<object>((_) => true)])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
z.templateLiteral([
|
||||
// @ts-expect-error
|
||||
z.discriminatedUnion("discriminator", [z.object({}), z.object({})]),
|
||||
])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.function()])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.instanceof(class MyClass {})])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.intersection(z.object({}), z.object({}))])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.map(z.string(), z.string())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.nullable(z.object({}))])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.optional(z.object({}))])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.promise()])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.record(z.unknown())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.set(z.string())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.symbol()])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.tuple([z.string()])])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.unknown()])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.void()])
|
||||
).toThrow();
|
||||
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.never()])
|
||||
).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => z.templateLiteral([z.nan()])).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.pipe(z.string(), z.string())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.preprocess(() => true, z.boolean())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.object({}).brand("brand")])
|
||||
).toThrow();
|
||||
|
||||
// these constraints aren't enforced but they shouldn't throw
|
||||
z.templateLiteral([z.number().multipleOf(2)]);
|
||||
z.templateLiteral([z.string().emoji()]);
|
||||
z.templateLiteral([z.string().url()]);
|
||||
z.templateLiteral([z.string().url()]);
|
||||
z.templateLiteral([z.string().trim()]);
|
||||
z.templateLiteral([z.string().includes("train")]);
|
||||
z.templateLiteral([z.string().toLowerCase()]);
|
||||
z.templateLiteral([z.string().toUpperCase()]);
|
||||
});
|
||||
|
||||
test("template literal parsing - success - basic cases", () => {
|
||||
expect(() => z.templateLiteral([]).parse(7)).toThrow();
|
||||
|
||||
empty.parse("");
|
||||
hello.parse("hello");
|
||||
world.parse("world");
|
||||
one.parse("1");
|
||||
two.parse("2");
|
||||
truee.parse("true");
|
||||
anotherTrue.parse("true");
|
||||
falsee.parse("false");
|
||||
anotherFalse.parse("false");
|
||||
nulll.parse("null");
|
||||
anotherNull.parse("null");
|
||||
undefinedd.parse("undefined");
|
||||
anotherUndefined.parse("undefined");
|
||||
anyString.parse("blahblahblah");
|
||||
anyString.parse("");
|
||||
lazyString.parse("blahblahblah");
|
||||
lazyString.parse("");
|
||||
anyNumber.parse("123");
|
||||
anyNumber.parse("1.23");
|
||||
anyNumber.parse("0");
|
||||
anyNumber.parse("-1.23");
|
||||
anyNumber.parse("-123");
|
||||
// anyNumber.parse("Infinity");
|
||||
// anyNumber.parse("-Infinity");
|
||||
anyInt.parse("123");
|
||||
// anyInt.parse("-123");
|
||||
// anyFiniteNumber.parse("123");
|
||||
// anyFiniteNumber.parse("1.23");
|
||||
// anyFiniteNumber.parse("0");
|
||||
// anyFiniteNumber.parse("-1.23");
|
||||
// anyFiniteNumber.parse("-123");
|
||||
// anyNegativeNumber.parse("-123");
|
||||
// anyNegativeNumber.parse("-1.23");
|
||||
// anyNegativeNumber.parse("-Infinity");
|
||||
// anyPositiveNumber.parse("123");
|
||||
// anyPositiveNumber.parse("1.23");
|
||||
// anyPositiveNumber.parse("Infinity");
|
||||
// zeroButInADumbWay.parse("0");
|
||||
// zeroButInADumbWay.parse("00000");
|
||||
// finiteButInADumbWay.parse("5");
|
||||
// finiteButInADumbWay.parse("10");
|
||||
// finiteButInADumbWay.parse("6.66");
|
||||
bool.parse("true");
|
||||
bool.parse("false");
|
||||
bigone.parse("1");
|
||||
anyBigint.parse("123456");
|
||||
anyBigint.parse("0");
|
||||
// anyBigint.parse("-123456");
|
||||
nullableYo.parse("yo");
|
||||
nullableYo.parse("null");
|
||||
nullableString.parse("abc");
|
||||
nullableString.parse("null");
|
||||
optionalYeah.parse("yeah");
|
||||
optionalYeah.parse("");
|
||||
optionalString.parse("abc");
|
||||
optionalString.parse("");
|
||||
optionalNumber.parse("123");
|
||||
optionalNumber.parse("1.23");
|
||||
optionalNumber.parse("0");
|
||||
optionalNumber.parse("-1.23");
|
||||
optionalNumber.parse("-123");
|
||||
// optionalNumber.parse("Infinity");
|
||||
// optionalNumber.parse("-Infinity");
|
||||
nullishBruh.parse("bruh");
|
||||
nullishBruh.parse("null");
|
||||
nullishBruh.parse("");
|
||||
cuid.parse("cjld2cyuq0000t3rmniod1foy");
|
||||
cuidZZZ.parse("cjld2cyuq0000t3rmniod1foyZZZ");
|
||||
cuid2.parse("tz4a98xxat96iws9zmbrgj3a");
|
||||
datetime.parse(new Date().toISOString());
|
||||
email.parse("info@example.com");
|
||||
// ip.parse("213.174.246.205");
|
||||
// ip.parse("c359:f57c:21e5:39eb:1187:e501:f936:b452");
|
||||
ipv4.parse("213.174.246.205");
|
||||
ipv6.parse("c359:f57c:21e5:39eb:1187:e501:f936:b452");
|
||||
ulid.parse("01GW3D2QZJBYB6P1Z1AE997VPW");
|
||||
uuid.parse("808989fd-3a6e-4af2-b607-737323a176f6");
|
||||
stringAToZ.parse("asudgaskhdgashd");
|
||||
stringStartsWith.parse("hello world");
|
||||
stringEndsWith.parse("hello world");
|
||||
stringMax5.parse("hello");
|
||||
stringMin5.parse("hello");
|
||||
stringLen5.parse("hello");
|
||||
stringMin5Max10.parse("hello worl");
|
||||
stringStartsWithMax5.parse("hello");
|
||||
brandedString.parse("branded string");
|
||||
});
|
||||
|
||||
test("template literal parsing - failure - basic cases", () => {
|
||||
expect(() => empty.parse("a")).toThrow();
|
||||
expect(() => hello.parse("hello!")).toThrow();
|
||||
expect(() => hello.parse("!hello")).toThrow();
|
||||
expect(() => world.parse("world!")).toThrow();
|
||||
expect(() => world.parse("!world")).toThrow();
|
||||
expect(() => one.parse("2")).toThrow();
|
||||
expect(() => one.parse("12")).toThrow();
|
||||
expect(() => one.parse("21")).toThrow();
|
||||
expect(() => two.parse("1")).toThrow();
|
||||
expect(() => two.parse("21")).toThrow();
|
||||
expect(() => two.parse("12")).toThrow();
|
||||
expect(() => truee.parse("false")).toThrow();
|
||||
expect(() => truee.parse("1true")).toThrow();
|
||||
expect(() => truee.parse("true1")).toThrow();
|
||||
expect(() => anotherTrue.parse("false")).toThrow();
|
||||
expect(() => anotherTrue.parse("1true")).toThrow();
|
||||
expect(() => anotherTrue.parse("true1")).toThrow();
|
||||
expect(() => falsee.parse("true")).toThrow();
|
||||
expect(() => falsee.parse("1false")).toThrow();
|
||||
expect(() => falsee.parse("false1")).toThrow();
|
||||
expect(() => anotherFalse.parse("true")).toThrow();
|
||||
expect(() => anotherFalse.parse("1false")).toThrow();
|
||||
expect(() => anotherFalse.parse("false1")).toThrow();
|
||||
expect(() => nulll.parse("123")).toThrow();
|
||||
expect(() => nulll.parse("null1")).toThrow();
|
||||
expect(() => nulll.parse("1null")).toThrow();
|
||||
expect(() => anotherNull.parse("123")).toThrow();
|
||||
expect(() => anotherNull.parse("null1")).toThrow();
|
||||
expect(() => anotherNull.parse("1null")).toThrow();
|
||||
expect(() => undefinedd.parse("123")).toThrow();
|
||||
expect(() => undefinedd.parse("undefined1")).toThrow();
|
||||
expect(() => undefinedd.parse("1undefined")).toThrow();
|
||||
expect(() => anotherUndefined.parse("123")).toThrow();
|
||||
expect(() => anotherUndefined.parse("undefined1")).toThrow();
|
||||
expect(() => anotherUndefined.parse("1undefined")).toThrow();
|
||||
expect(() => anyNumber.parse("2a")).toThrow();
|
||||
expect(() => anyNumber.parse("a2")).toThrow();
|
||||
expect(() => anyNumber.parse("-2a")).toThrow();
|
||||
expect(() => anyNumber.parse("a-2")).toThrow();
|
||||
expect(() => anyNumber.parse("2.5a")).toThrow();
|
||||
expect(() => anyNumber.parse("a2.5")).toThrow();
|
||||
expect(() => anyNumber.parse("Infinitya")).toThrow();
|
||||
expect(() => anyNumber.parse("aInfinity")).toThrow();
|
||||
expect(() => anyNumber.parse("-Infinitya")).toThrow();
|
||||
expect(() => anyNumber.parse("a-Infinity")).toThrow();
|
||||
expect(() => anyNumber.parse("2e5")).toThrow();
|
||||
expect(() => anyNumber.parse("2e-5")).toThrow();
|
||||
expect(() => anyNumber.parse("2e+5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2e5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2e-5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2e+5")).toThrow();
|
||||
expect(() => anyNumber.parse("2.1e5")).toThrow();
|
||||
expect(() => anyNumber.parse("2.1e-5")).toThrow();
|
||||
expect(() => anyNumber.parse("2.1e+5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2.1e5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2.1e-5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2.1e+5")).toThrow();
|
||||
expect(() => anyNumber.parse("-Infinity")).toThrow();
|
||||
expect(() => anyNumber.parse("Infinity")).toThrow();
|
||||
expect(() => anyInt.parse("1.23")).toThrow();
|
||||
expect(() => anyInt.parse("-1.23")).toThrow();
|
||||
expect(() => anyInt.parse("d1")).toThrow();
|
||||
expect(() => anyInt.parse("1d")).toThrow();
|
||||
// expect(() => anyFiniteNumber.parse("Infinity")).toThrow();
|
||||
// expect(() => anyFiniteNumber.parse("-Infinity")).toThrow();
|
||||
// expect(() => anyFiniteNumber.parse("123a")).toThrow();
|
||||
// expect(() => anyFiniteNumber.parse("a123")).toThrow();
|
||||
// expect(() => anyNegativeNumber.parse("0")).toThrow();
|
||||
// expect(() => anyNegativeNumber.parse("1")).toThrow();
|
||||
// expect(() => anyNegativeNumber.parse("Infinity")).toThrow();
|
||||
// expect(() => anyPositiveNumber.parse("0")).toThrow();
|
||||
// expect(() => anyPositiveNumber.parse("-1")).toThrow();
|
||||
// expect(() => anyPositiveNumber.parse("-Infinity")).toThrow();
|
||||
// expect(() => zeroButInADumbWay.parse("1")).toThrow();
|
||||
// expect(() => zeroButInADumbWay.parse("-1")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("Infinity")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("-Infinity")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("-5")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("10a")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("a10")).toThrow();
|
||||
expect(() => bool.parse("123")).toThrow();
|
||||
expect(() => bigone.parse("2")).toThrow();
|
||||
expect(() => bigone.parse("c1")).toThrow();
|
||||
expect(() => anyBigint.parse("1.23")).toThrow();
|
||||
expect(() => anyBigint.parse("-1.23")).toThrow();
|
||||
expect(() => anyBigint.parse("c123")).toThrow();
|
||||
expect(() => nullableYo.parse("yo1")).toThrow();
|
||||
expect(() => nullableYo.parse("1yo")).toThrow();
|
||||
expect(() => nullableYo.parse("null1")).toThrow();
|
||||
expect(() => nullableYo.parse("1null")).toThrow();
|
||||
expect(() => optionalYeah.parse("yeah1")).toThrow();
|
||||
expect(() => optionalYeah.parse("1yeah")).toThrow();
|
||||
expect(() => optionalYeah.parse("undefined")).toThrow();
|
||||
expect(() => optionalNumber.parse("123a")).toThrow();
|
||||
expect(() => optionalNumber.parse("a123")).toThrow();
|
||||
// expect(() => optionalNumber.parse("Infinitya")).toThrow();
|
||||
// expect(() => optionalNumber.parse("aInfinity")).toThrow();
|
||||
expect(() => nullishBruh.parse("bruh1")).toThrow();
|
||||
expect(() => nullishBruh.parse("1bruh")).toThrow();
|
||||
expect(() => nullishBruh.parse("null1")).toThrow();
|
||||
expect(() => nullishBruh.parse("1null")).toThrow();
|
||||
expect(() => nullishBruh.parse("undefined")).toThrow();
|
||||
expect(() => cuid.parse("bjld2cyuq0000t3rmniod1foy")).toThrow();
|
||||
expect(() => cuid.parse("cjld2cyu")).toThrow();
|
||||
expect(() => cuid.parse("cjld2 cyu")).toThrow();
|
||||
expect(() => cuid.parse("cjld2cyuq0000t3rmniod1foy ")).toThrow();
|
||||
expect(() => cuid.parse("1cjld2cyuq0000t3rmniod1foy")).toThrow();
|
||||
expect(() => cuidZZZ.parse("cjld2cyuq0000t3rmniod1foy")).toThrow();
|
||||
expect(() => cuidZZZ.parse("cjld2cyuq0000t3rmniod1foyZZY")).toThrow();
|
||||
expect(() => cuidZZZ.parse("cjld2cyuq0000t3rmniod1foyZZZ1")).toThrow();
|
||||
expect(() => cuidZZZ.parse("1cjld2cyuq0000t3rmniod1foyZZZ")).toThrow();
|
||||
expect(() => cuid2.parse("A9z4a98xxat96iws9zmbrgj3a")).toThrow();
|
||||
expect(() => cuid2.parse("tz4a98xxat96iws9zmbrgj3!")).toThrow();
|
||||
expect(() => datetime.parse("2022-01-01 00:00:00")).toThrow();
|
||||
expect(() => email.parse("info@example.com@")).toThrow();
|
||||
// expect(() => ip.parse("213.174.246:205")).toThrow();
|
||||
// expect(() => ip.parse("c359.f57c:21e5:39eb:1187:e501:f936:b452")).toThrow();
|
||||
expect(() => ipv4.parse("1213.174.246.205")).toThrow();
|
||||
expect(() => ipv4.parse("c359:f57c:21e5:39eb:1187:e501:f936:b452")).toThrow();
|
||||
expect(() => ipv6.parse("c359:f57c:21e5:39eb:1187:e501:f936:b4521")).toThrow();
|
||||
expect(() => ipv6.parse("213.174.246.205")).toThrow();
|
||||
expect(() => ulid.parse("01GW3D2QZJBYB6P1Z1AE997VPW!")).toThrow();
|
||||
expect(() => uuid.parse("808989fd-3a6e-4af2-b607-737323a176f6Z")).toThrow();
|
||||
expect(() => uuid.parse("Z808989fd-3a6e-4af2-b607-737323a176f6")).toThrow();
|
||||
expect(() => stringAToZ.parse("asdasdasd1")).toThrow();
|
||||
expect(() => stringAToZ.parse("1asdasdasd")).toThrow();
|
||||
expect(() => stringStartsWith.parse("ahello")).toThrow();
|
||||
expect(() => stringEndsWith.parse("worlda")).toThrow();
|
||||
expect(() => stringMax5.parse("123456")).toThrow();
|
||||
expect(() => stringMin5.parse("1234")).toThrow();
|
||||
expect(() => stringLen5.parse("123456")).toThrow();
|
||||
expect(() => stringLen5.parse("1234")).toThrow();
|
||||
expect(() => stringMin5Max10.parse("1234")).toThrow();
|
||||
expect(() => stringMin5Max10.parse("12345678901")).toThrow();
|
||||
|
||||
// the "startswith" overrides the max length
|
||||
// expect(() => stringStartsWithMax5.parse("hello1")).toThrow();
|
||||
expect(() => stringStartsWithMax5.parse("1hell")).toThrow();
|
||||
expect(() => brandedString.parse("")).toThrow();
|
||||
});
|
||||
|
||||
test("regexes", () => {
|
||||
expect(empty._zod.pattern.source).toMatchInlineSnapshot(`"^$"`);
|
||||
expect(hello._zod.pattern.source).toMatchInlineSnapshot(`"^hello$"`);
|
||||
expect(world._zod.pattern.source).toMatchInlineSnapshot(`"^(world)$"`);
|
||||
expect(one._zod.pattern.source).toMatchInlineSnapshot(`"^1$"`);
|
||||
expect(two._zod.pattern.source).toMatchInlineSnapshot(`"^(2)$"`);
|
||||
expect(truee._zod.pattern.source).toMatchInlineSnapshot(`"^true$"`);
|
||||
expect(anotherTrue._zod.pattern.source).toMatchInlineSnapshot(`"^(true)$"`);
|
||||
expect(falsee._zod.pattern.source).toMatchInlineSnapshot(`"^false$"`);
|
||||
expect(anotherFalse._zod.pattern.source).toMatchInlineSnapshot(`"^(false)$"`);
|
||||
expect(nulll._zod.pattern.source).toMatchInlineSnapshot(`"^null$"`);
|
||||
expect(anotherNull._zod.pattern.source).toMatchInlineSnapshot(`"^null$"`);
|
||||
expect(undefinedd._zod.pattern.source).toMatchInlineSnapshot(`"^undefined$"`);
|
||||
expect(anotherUndefined._zod.pattern.source).toMatchInlineSnapshot(`"^undefined$"`);
|
||||
expect(anyString._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{0,}$"`);
|
||||
expect(lazyString._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{0,}$"`);
|
||||
expect(anyNumber._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
expect(anyInt._zod.pattern.source).toMatchInlineSnapshot(`"^\\d+$"`);
|
||||
// expect(anyFiniteNumber._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
// expect(anyNegativeNumber._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
// expect(anyPositiveNumber._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
// expect(zeroButInADumbWay._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
// expect(finiteButInADumbWay._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
expect(bool._zod.pattern.source).toMatchInlineSnapshot(`"^true|false$"`);
|
||||
expect(bigone._zod.pattern.source).toMatchInlineSnapshot(`"^(1)$"`);
|
||||
expect(anyBigint._zod.pattern.source).toMatchInlineSnapshot(`"^\\d+n?$"`);
|
||||
expect(nullableYo._zod.pattern.source).toMatchInlineSnapshot(`"^((yo)|null)$"`);
|
||||
expect(nullableString._zod.pattern.source).toMatchInlineSnapshot(`"^([\\s\\S]{0,}|null)$"`);
|
||||
expect(optionalYeah._zod.pattern.source).toMatchInlineSnapshot(`"^((yeah))?$"`);
|
||||
expect(optionalString._zod.pattern.source).toMatchInlineSnapshot(`"^([\\s\\S]{0,})?$"`);
|
||||
expect(optionalNumber._zod.pattern.source).toMatchInlineSnapshot(`"^(-?\\d+(?:\\.\\d+)?)?$"`);
|
||||
expect(nullishBruh._zod.pattern.source).toMatchInlineSnapshot(`"^(((bruh)|null))?$"`);
|
||||
expect(nullishString._zod.pattern.source).toMatchInlineSnapshot(`"^(([\\s\\S]{0,}|null))?$"`);
|
||||
expect(cuid._zod.pattern.source).toMatchInlineSnapshot(`"^[cC][^\\s-]{8,}$"`);
|
||||
expect(cuidZZZ._zod.pattern.source).toMatchInlineSnapshot(`"^[cC][^\\s-]{8,}ZZZ$"`);
|
||||
expect(cuid2._zod.pattern.source).toMatchInlineSnapshot(`"^[0-9a-z]+$"`);
|
||||
expect(datetime._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"`
|
||||
);
|
||||
expect(email._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"`
|
||||
);
|
||||
// expect(ip._zod.pattern.source).toMatchInlineSnapshot(
|
||||
// `"^(^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$)|(^(([a-fA-F0-9]{1,4}:){7}|::([a-fA-F0-9]{1,4}:){0,6}|([a-fA-F0-9]{1,4}:){1}:([a-fA-F0-9]{1,4}:){0,5}|([a-fA-F0-9]{1,4}:){2}:([a-fA-F0-9]{1,4}:){0,4}|([a-fA-F0-9]{1,4}:){3}:([a-fA-F0-9]{1,4}:){0,3}|([a-fA-F0-9]{1,4}:){4}:([a-fA-F0-9]{1,4}:){0,2}|([a-fA-F0-9]{1,4}:){5}:([a-fA-F0-9]{1,4}:){0,1})([a-fA-F0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$)$"`
|
||||
// );
|
||||
expect(ipv4._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$"`
|
||||
);
|
||||
expect(ipv6._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})$"`
|
||||
);
|
||||
expect(ulid._zod.pattern.source).toMatchInlineSnapshot(`"^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$"`);
|
||||
expect(uuid._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$"`
|
||||
);
|
||||
expect(stringAToZ._zod.pattern.source).toMatchInlineSnapshot(`"^[a-z]+$"`);
|
||||
expect(stringStartsWith._zod.pattern.source).toMatchInlineSnapshot(`"^hello.*$"`);
|
||||
expect(stringEndsWith._zod.pattern.source).toMatchInlineSnapshot(`"^.*world$"`);
|
||||
expect(stringMax5._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{0,5}$"`);
|
||||
expect(stringMin5._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{5,}$"`);
|
||||
expect(stringLen5._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{5,5}$"`);
|
||||
expect(stringMin5Max10._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{5,10}$"`);
|
||||
expect(brandedString._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{1,}$"`);
|
||||
expect(url._zod.pattern.source).toMatchInlineSnapshot(`"^https:\\/\\/\\w+\\.(com|net)$"`);
|
||||
expect(measurement._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?((px|em|rem|vh|vw|vmin|vmax))?$"`);
|
||||
expect(connectionString._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^mongodb:\\/\\/(\\w+:\\w+@)?\\w+:\\d+(\\/(\\w+)?(\\?(\\w+=\\w+(&\\w+=\\w+)*)?)?)?$"`
|
||||
);
|
||||
});
|
||||
|
||||
test("template literal parsing - success - complex cases", () => {
|
||||
url.parse("https://example.com");
|
||||
url.parse("https://speedtest.net");
|
||||
|
||||
// measurement.parse(1);
|
||||
// measurement.parse(1.1);
|
||||
// measurement.parse(0);
|
||||
// measurement.parse(-1.1);
|
||||
// measurement.parse(-1);
|
||||
measurement.parse("1");
|
||||
measurement.parse("1.1");
|
||||
measurement.parse("0");
|
||||
measurement.parse("-1");
|
||||
measurement.parse("-1.1");
|
||||
measurement.parse("1px");
|
||||
measurement.parse("1.1px");
|
||||
measurement.parse("0px");
|
||||
measurement.parse("-1px");
|
||||
measurement.parse("-1.1px");
|
||||
measurement.parse("1em");
|
||||
measurement.parse("1.1em");
|
||||
measurement.parse("0em");
|
||||
measurement.parse("-1em");
|
||||
measurement.parse("-1.1em");
|
||||
measurement.parse("1rem");
|
||||
measurement.parse("1.1rem");
|
||||
measurement.parse("0rem");
|
||||
measurement.parse("-1rem");
|
||||
measurement.parse("-1.1rem");
|
||||
measurement.parse("1vh");
|
||||
measurement.parse("1.1vh");
|
||||
measurement.parse("0vh");
|
||||
measurement.parse("-1vh");
|
||||
measurement.parse("-1.1vh");
|
||||
measurement.parse("1vw");
|
||||
measurement.parse("1.1vw");
|
||||
measurement.parse("0vw");
|
||||
measurement.parse("-1vw");
|
||||
measurement.parse("-1.1vw");
|
||||
measurement.parse("1vmin");
|
||||
measurement.parse("1.1vmin");
|
||||
measurement.parse("0vmin");
|
||||
measurement.parse("-1vmin");
|
||||
measurement.parse("-1.1vmin");
|
||||
measurement.parse("1vmax");
|
||||
measurement.parse("1.1vmax");
|
||||
measurement.parse("0vmax");
|
||||
measurement.parse("-1vmax");
|
||||
measurement.parse("-1.1vmax");
|
||||
|
||||
connectionString.parse("mongodb://host:1234");
|
||||
connectionString.parse("mongodb://host:1234/");
|
||||
connectionString.parse("mongodb://host:1234/defaultauthdb");
|
||||
connectionString.parse("mongodb://host:1234/defaultauthdb?authSource=admin");
|
||||
connectionString.parse("mongodb://host:1234/defaultauthdb?authSource=admin&connectTimeoutMS=300000");
|
||||
connectionString.parse("mongodb://host:1234/?authSource=admin");
|
||||
connectionString.parse("mongodb://host:1234/?authSource=admin&connectTimeoutMS=300000");
|
||||
connectionString.parse("mongodb://username:password@host:1234");
|
||||
connectionString.parse("mongodb://username:password@host:1234/");
|
||||
connectionString.parse("mongodb://username:password@host:1234/defaultauthdb");
|
||||
connectionString.parse("mongodb://username:password@host:1234/defaultauthdb?authSource=admin");
|
||||
connectionString.parse(
|
||||
"mongodb://username:password@host:1234/defaultauthdb?authSource=admin&connectTimeoutMS=300000"
|
||||
);
|
||||
connectionString.parse("mongodb://username:password@host:1234/?authSource=admin");
|
||||
connectionString.parse("mongodb://username:password@host:1234/?authSource=admin&connectTimeoutMS=300000");
|
||||
});
|
||||
|
||||
test("template literal parsing - failure - complex cases", () => {
|
||||
expect(() => url.parse("http://example.com")).toThrow();
|
||||
expect(() => url.parse("https://.com")).toThrow();
|
||||
expect(() => url.parse("https://examplecom")).toThrow();
|
||||
expect(() => url.parse("https://example.org")).toThrow();
|
||||
expect(() => url.parse("https://example.net.il")).toThrow();
|
||||
|
||||
expect(() => measurement.parse("1.1.1")).toThrow();
|
||||
expect(() => measurement.parse("Infinity")).toThrow();
|
||||
expect(() => measurement.parse("-Infinity")).toThrow();
|
||||
expect(() => measurement.parse("NaN")).toThrow();
|
||||
expect(() => measurement.parse("1%")).toThrow();
|
||||
|
||||
expect(() => connectionString.parse("mongod://host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:d234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:12.34")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:-1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:-12.34")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://:password@host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://usernamepassword@host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://username:@host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://@host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:1234/defaultauthdb?authSourceadmin")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:1234/?authSourceadmin")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:1234/defaultauthdb?&authSource=admin")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:1234/?&authSource=admin")).toThrow();
|
||||
});
|
||||
|
||||
test("template literal parsing - failure - issue format", () => {
|
||||
expect(anotherNull.safeParse("1null")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^null$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(cuidZZZ.safeParse("1cjld2cyuq0000t3rmniod1foyZZZ")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^[cC][^\\\\s-]{8,}ZZZ$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(stringMin5Max10.safeParse("1234")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^[\\\\s\\\\S]{5,10}$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(connectionString.safeParse("mongodb://host:1234/defaultauthdb?authSourceadmin")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^mongodb:\\\\/\\\\/(\\\\w+:\\\\w+@)?\\\\w+:\\\\d+(\\\\/(\\\\w+)?(\\\\?(\\\\w+=\\\\w+(&\\\\w+=\\\\w+)*)?)?)?$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(stringStartsWithMax5.safeParse("1hell")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^hello.*$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
2314
node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts
generated
vendored
Normal file
2314
node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
250
node_modules/zod/src/v4/classic/tests/transform.test.ts
generated
vendored
Normal file
250
node_modules/zod/src/v4/classic/tests/transform.test.ts
generated
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("transform ctx.addIssue with parse", () => {
|
||||
const strs = ["foo", "bar"];
|
||||
const schema = z.string().transform((data, ctx) => {
|
||||
const i = strs.indexOf(data);
|
||||
if (i === -1) {
|
||||
ctx.addIssue({
|
||||
input: data,
|
||||
code: "custom",
|
||||
message: `${data} is not one of our allowed strings`,
|
||||
});
|
||||
}
|
||||
return data.length;
|
||||
});
|
||||
const result = schema.safeParse("asdf");
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "asdf is not one of our allowed strings",
|
||||
"path": []
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("transform ctx.addIssue with parseAsync", async () => {
|
||||
const strs = ["foo", "bar"];
|
||||
|
||||
const result = await z
|
||||
.string()
|
||||
.transform(async (data, ctx) => {
|
||||
const i = strs.indexOf(data);
|
||||
if (i === -1) {
|
||||
ctx.addIssue({
|
||||
input: data,
|
||||
code: "custom",
|
||||
message: `${data} is not one of our allowed strings`,
|
||||
});
|
||||
}
|
||||
return data.length;
|
||||
})
|
||||
.safeParseAsync("asdf");
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "asdf is not one of our allowed strings",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("z.NEVER in transform", () => {
|
||||
const foo = z
|
||||
.number()
|
||||
.optional()
|
||||
.transform((val, ctx) => {
|
||||
if (!val) {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "bad",
|
||||
});
|
||||
return z.NEVER;
|
||||
}
|
||||
return val;
|
||||
});
|
||||
type foo = z.infer<typeof foo>;
|
||||
expectTypeOf<foo>().toEqualTypeOf<number>();
|
||||
const arg = foo.safeParse(undefined);
|
||||
if (!arg.success) {
|
||||
expect(arg.error.issues[0].message).toEqual("bad");
|
||||
}
|
||||
});
|
||||
|
||||
test("basic transformations", () => {
|
||||
const r1 = z
|
||||
.string()
|
||||
.transform((data) => data.length)
|
||||
.parse("asdf");
|
||||
expect(r1).toEqual(4);
|
||||
});
|
||||
|
||||
test("coercion", () => {
|
||||
const numToString = z.number().transform((n) => String(n));
|
||||
const data = z
|
||||
.object({
|
||||
id: numToString,
|
||||
})
|
||||
.parse({ id: 5 });
|
||||
|
||||
expect(data).toEqual({ id: "5" });
|
||||
});
|
||||
|
||||
test("async coercion", async () => {
|
||||
const numToString = z.number().transform(async (n) => String(n));
|
||||
const data = await z
|
||||
.object({
|
||||
id: numToString,
|
||||
})
|
||||
.parseAsync({ id: 5 });
|
||||
|
||||
expect(data).toEqual({ id: "5" });
|
||||
});
|
||||
|
||||
test("sync coercion async error", async () => {
|
||||
const asyncNumberToString = z.number().transform(async (n) => String(n));
|
||||
expect(() =>
|
||||
z
|
||||
.object({
|
||||
id: asyncNumberToString,
|
||||
})
|
||||
.parse({ id: 5 })
|
||||
).toThrow();
|
||||
// expect(data).toEqual({ id: '5' });
|
||||
});
|
||||
|
||||
test("default", () => {
|
||||
const data = z.string().default("asdf").parse(undefined); // => "asdf"
|
||||
expect(data).toEqual("asdf");
|
||||
});
|
||||
|
||||
test("dynamic default", () => {
|
||||
const data = z
|
||||
.string()
|
||||
.default(() => "string")
|
||||
.parse(undefined); // => "asdf"
|
||||
expect(data).toEqual("string");
|
||||
});
|
||||
|
||||
test("default when property is null or undefined", () => {
|
||||
const data = z
|
||||
.object({
|
||||
foo: z.boolean().nullable().default(true),
|
||||
bar: z.boolean().default(true),
|
||||
})
|
||||
.parse({ foo: null });
|
||||
|
||||
expect(data).toEqual({ foo: null, bar: true });
|
||||
});
|
||||
|
||||
test("default with falsy values", () => {
|
||||
const schema = z.object({
|
||||
emptyStr: z.string().default("def"),
|
||||
zero: z.number().default(5),
|
||||
falseBoolean: z.boolean().default(true),
|
||||
});
|
||||
const input = { emptyStr: "", zero: 0, falseBoolean: true };
|
||||
const output = schema.parse(input);
|
||||
// defaults are not supposed to be used
|
||||
expect(output).toEqual(input);
|
||||
});
|
||||
|
||||
test("object typing", () => {
|
||||
const stringToNumber = z.string().transform((arg) => Number.parseFloat(arg));
|
||||
|
||||
const t1 = z.object({
|
||||
stringToNumber,
|
||||
});
|
||||
|
||||
type t1 = z.input<typeof t1>;
|
||||
type t2 = z.output<typeof t1>;
|
||||
|
||||
expectTypeOf<t1>().toEqualTypeOf<{ stringToNumber: string }>();
|
||||
expectTypeOf<t2>().toEqualTypeOf<{ stringToNumber: number }>();
|
||||
});
|
||||
|
||||
test("transform method overloads", () => {
|
||||
const t1 = z.string().transform((val) => val.toUpperCase());
|
||||
expect(t1.parse("asdf")).toEqual("ASDF");
|
||||
|
||||
const t2 = z.string().transform((val) => val.length);
|
||||
expect(t2.parse("asdf")).toEqual(4);
|
||||
});
|
||||
|
||||
test("multiple transformers", () => {
|
||||
const stringToNumber = z.string().transform((arg) => Number.parseFloat(arg));
|
||||
|
||||
const doubler = stringToNumber.transform((val) => {
|
||||
return val * 2;
|
||||
});
|
||||
expect(doubler.parse("5")).toEqual(10);
|
||||
});
|
||||
|
||||
test("short circuit on dirty", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.refine(() => false)
|
||||
.transform((val) => val.toUpperCase());
|
||||
const result = schema.safeParse("asdf");
|
||||
expect(result.success).toEqual(false);
|
||||
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const result2 = schema.safeParse(1234);
|
||||
expect(result2.success).toEqual(false);
|
||||
if (!result2.success) {
|
||||
expect(result2.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_type);
|
||||
}
|
||||
});
|
||||
|
||||
test("async short circuit on dirty", async () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.refine(() => false)
|
||||
.transform((val) => val.toUpperCase());
|
||||
const result = await schema.spa("asdf");
|
||||
expect(result.success).toEqual(false);
|
||||
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const result2 = await schema.spa(1234);
|
||||
expect(result2.success).toEqual(false);
|
||||
|
||||
expect(result2.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
163
node_modules/zod/src/v4/classic/tests/tuple.test.ts
generated
vendored
Normal file
163
node_modules/zod/src/v4/classic/tests/tuple.test.ts
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("successful validation", () => {
|
||||
const testTuple = z.tuple([z.string(), z.number()]);
|
||||
expectTypeOf<typeof testTuple._output>().toEqualTypeOf<[string, number]>();
|
||||
|
||||
const val = testTuple.parse(["asdf", 1234]);
|
||||
expect(val).toEqual(val);
|
||||
|
||||
const r1 = testTuple.safeParse(["asdf", "asdf"]);
|
||||
expect(r1.success).toEqual(false);
|
||||
expect(r1.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
1
|
||||
],
|
||||
"message": "Invalid input: expected number, received string"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const r2 = testTuple.safeParse(["asdf", 1234, true]);
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"origin": "array",
|
||||
"code": "too_big",
|
||||
"maximum": 2,
|
||||
"path": [],
|
||||
"message": "Too big: expected array to have <2 items"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const r3 = testTuple.safeParse({});
|
||||
expect(r3.success).toEqual(false);
|
||||
expect(r3.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "tuple",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected tuple, received object"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("async validation", async () => {
|
||||
const testTuple = z
|
||||
.tuple([z.string().refine(async () => true), z.number().refine(async () => true)])
|
||||
.refine(async () => true);
|
||||
expectTypeOf<typeof testTuple._output>().toEqualTypeOf<[string, number]>();
|
||||
|
||||
const val = await testTuple.parseAsync(["asdf", 1234]);
|
||||
expect(val).toEqual(val);
|
||||
|
||||
const r1 = await testTuple.safeParseAsync(["asdf", "asdf"]);
|
||||
expect(r1.success).toEqual(false);
|
||||
expect(r1.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
1
|
||||
],
|
||||
"message": "Invalid input: expected number, received string"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const r2 = await testTuple.safeParseAsync(["asdf", 1234, true]);
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"origin": "array",
|
||||
"code": "too_big",
|
||||
"maximum": 2,
|
||||
"path": [],
|
||||
"message": "Too big: expected array to have <2 items"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const r3 = await testTuple.safeParseAsync({});
|
||||
expect(r3.success).toEqual(false);
|
||||
expect(r3.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "tuple",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected tuple, received object"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("tuple with optional elements", () => {
|
||||
const myTuple = z.tuple([z.string(), z.number().optional(), z.string().optional()]).rest(z.boolean());
|
||||
expectTypeOf<typeof myTuple._output>().toEqualTypeOf<[string, number?, string?, ...boolean[]]>();
|
||||
|
||||
const goodData = [["asdf"], ["asdf", 1234], ["asdf", 1234, "asdf"], ["asdf", 1234, "asdf", true, false, true]];
|
||||
for (const data of goodData) {
|
||||
expect(myTuple.parse(data)).toEqual(data);
|
||||
}
|
||||
|
||||
const badData = [
|
||||
["asdf", "asdf"],
|
||||
["asdf", 1234, "asdf", "asdf"],
|
||||
["asdf", 1234, "asdf", true, false, "asdf"],
|
||||
];
|
||||
for (const data of badData) {
|
||||
expect(() => myTuple.parse(data)).toThrow();
|
||||
}
|
||||
});
|
||||
|
||||
test("tuple with optional elements followed by required", () => {
|
||||
const myTuple = z.tuple([z.string(), z.number().optional(), z.string()]).rest(z.boolean());
|
||||
expectTypeOf<typeof myTuple._output>().toEqualTypeOf<[string, number | undefined, string, ...boolean[]]>();
|
||||
|
||||
const goodData = [
|
||||
["asdf", 1234, "asdf"],
|
||||
["asdf", 1234, "asdf", true, false, true],
|
||||
];
|
||||
for (const data of goodData) {
|
||||
expect(myTuple.parse(data)).toEqual(data);
|
||||
}
|
||||
|
||||
const badData = [
|
||||
["asdf"],
|
||||
["asdf", 1234],
|
||||
["asdf", 1234, "asdf", "asdf"],
|
||||
["asdf", 1234, "asdf", true, false, "asdf"],
|
||||
];
|
||||
for (const data of badData) {
|
||||
expect(() => myTuple.parse(data)).toThrow();
|
||||
}
|
||||
});
|
||||
|
||||
test("tuple with rest schema", () => {
|
||||
const myTuple = z.tuple([z.string(), z.number()]).rest(z.boolean());
|
||||
expect(myTuple.parse(["asdf", 1234, true, false, true])).toEqual(["asdf", 1234, true, false, true]);
|
||||
|
||||
expect(myTuple.parse(["asdf", 1234])).toEqual(["asdf", 1234]);
|
||||
|
||||
expect(() => myTuple.parse(["asdf", 1234, "asdf"])).toThrow();
|
||||
type t1 = z.output<typeof myTuple>;
|
||||
|
||||
expectTypeOf<t1>().toEqualTypeOf<[string, number, ...boolean[]]>();
|
||||
});
|
||||
|
||||
test("sparse array input", () => {
|
||||
const schema = z.tuple([z.string(), z.number()]);
|
||||
expect(() => schema.parse(new Array(2))).toThrow();
|
||||
});
|
||||
94
node_modules/zod/src/v4/classic/tests/union.test.ts
generated
vendored
Normal file
94
node_modules/zod/src/v4/classic/tests/union.test.ts
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("function parsing", () => {
|
||||
const schema = z.union([z.string().refine(() => false), z.number().refine(() => false)]);
|
||||
const result = schema.safeParse("asdf");
|
||||
expect(result.success).toEqual(false);
|
||||
});
|
||||
|
||||
test("union 2", () => {
|
||||
const result = z.union([z.number(), z.string().refine(() => false)]).safeParse("a");
|
||||
expect(result.success).toEqual(false);
|
||||
});
|
||||
|
||||
test("return valid over invalid", () => {
|
||||
const schema = z.union([
|
||||
z.object({
|
||||
email: z.string().email(),
|
||||
}),
|
||||
z.string(),
|
||||
]);
|
||||
expect(schema.parse("asdf")).toEqual("asdf");
|
||||
expect(schema.parse({ email: "asdlkjf@lkajsdf.com" })).toEqual({
|
||||
email: "asdlkjf@lkajsdf.com",
|
||||
});
|
||||
});
|
||||
|
||||
test("return errors from both union arms", () => {
|
||||
const result = z.union([z.number(), z.string().refine(() => false)]).safeParse("a");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_union",
|
||||
"errors": [
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "number",
|
||||
"message": "Invalid input: expected number, received string",
|
||||
"path": [],
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
],
|
||||
],
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("options getter", async () => {
|
||||
const union = z.union([z.string(), z.number()]);
|
||||
union.options[0].parse("asdf");
|
||||
union.options[1].parse(1234);
|
||||
await union.options[0].parseAsync("asdf");
|
||||
await union.options[1].parseAsync(1234);
|
||||
});
|
||||
|
||||
test("readonly union", async () => {
|
||||
const options = [z.string(), z.number()] as const;
|
||||
const union = z.union(options);
|
||||
union.parse("asdf");
|
||||
union.parse(12);
|
||||
});
|
||||
|
||||
test("union inferred types", () => {
|
||||
const test = z.object({}).or(z.array(z.object({})));
|
||||
|
||||
type Test = z.output<typeof test>; // <— any
|
||||
expectTypeOf<Test>().toEqualTypeOf<Record<string, never> | Array<Record<string, never>>>();
|
||||
});
|
||||
|
||||
test("union values", () => {
|
||||
const schema = z.union([z.literal("a"), z.literal("b"), z.literal("c")]);
|
||||
|
||||
expect(schema._zod.values).toMatchInlineSnapshot(`
|
||||
Set {
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
}
|
||||
`);
|
||||
});
|
||||
283
node_modules/zod/src/v4/classic/tests/validations.test.ts
generated
vendored
Normal file
283
node_modules/zod/src/v4/classic/tests/validations.test.ts
generated
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("string length", async () => {
|
||||
try {
|
||||
await z.string().length(4).parseAsync("asd");
|
||||
} catch (err) {
|
||||
// ("String must contain exactly 4 character(s)");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"exact": true,
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected string to have >=4 characters",
|
||||
"minimum": 4,
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
|
||||
try {
|
||||
await z.string().length(4).parseAsync("asdaa");
|
||||
} catch (err) {
|
||||
// ("String must contain exactly 4 character(s)");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"exact": true,
|
||||
"inclusive": true,
|
||||
"maximum": 4,
|
||||
"message": "Too big: expected string to have <=4 characters",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("string min/max", async () => {
|
||||
try {
|
||||
await z.string().min(4).parseAsync("asd");
|
||||
} catch (err) {
|
||||
// ("String must contain at least 4 character(s)");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected string to have >=4 characters",
|
||||
"minimum": 4,
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("string max", async () => {
|
||||
try {
|
||||
await z.string().max(4).parseAsync("aasdfsdfsd");
|
||||
} catch (err) {
|
||||
// ("String must contain at most 4 character(s)");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 4,
|
||||
"message": "Too big: expected string to have <=4 characters",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number min", async () => {
|
||||
try {
|
||||
await z.number().min(3).parseAsync(2);
|
||||
} catch (err) {
|
||||
// ("Number must be greater than or equal to 3");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected number to be >=3",
|
||||
"minimum": 3,
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number gte", async () => {
|
||||
try {
|
||||
await z.number().gte(3).parseAsync(2);
|
||||
} catch (err) {
|
||||
// ("Number must be greater than or equal to 3");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected number to be >=3",
|
||||
"minimum": 3,
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number gt", async () => {
|
||||
try {
|
||||
await z.number().gt(3).parseAsync(3);
|
||||
} catch (err) {
|
||||
// ("Number must be greater than or equal to 3");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": false,
|
||||
"message": "Too small: expected number to be >3",
|
||||
"minimum": 3,
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number max", async () => {
|
||||
try {
|
||||
await z.number().max(3).parseAsync(4);
|
||||
} catch (err) {
|
||||
// ("Number must be less than or equal to 3");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 3,
|
||||
"message": "Too big: expected number to be <=3",
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number lte", async () => {
|
||||
try {
|
||||
await z.number().lte(3).parseAsync(4);
|
||||
} catch (err) {
|
||||
// ("Number must be less than or equal to 3");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 3,
|
||||
"message": "Too big: expected number to be <=3",
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number lt", async () => {
|
||||
try {
|
||||
await z.number().lt(3).parseAsync(3);
|
||||
} catch (err) {
|
||||
// ("Number must be less than or equal to 3");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": false,
|
||||
"maximum": 3,
|
||||
"message": "Too big: expected number to be <3",
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number nonnegative", async () => {
|
||||
try {
|
||||
await z.number().nonnegative().parseAsync(-1);
|
||||
} catch (err) {
|
||||
// ("Number must be greater than or equal to 0");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected number to be >=0",
|
||||
"minimum": 0,
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number nonpositive", async () => {
|
||||
try {
|
||||
await z.number().nonpositive().parseAsync(1);
|
||||
} catch (err) {
|
||||
// ("Number must be less than or equal to 0");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 0,
|
||||
"message": "Too big: expected number to be <=0",
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number negative", async () => {
|
||||
try {
|
||||
await z.number().negative().parseAsync(1);
|
||||
} catch (err) {
|
||||
// ("Number must be less than 0");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": false,
|
||||
"maximum": 0,
|
||||
"message": "Too big: expected number to be <0",
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number positive", async () => {
|
||||
try {
|
||||
await z.number().positive().parseAsync(-1);
|
||||
} catch (err) {
|
||||
// ("Number must be greater than 0");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": false,
|
||||
"message": "Too small: expected number to be >0",
|
||||
"minimum": 0,
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
12
node_modules/zod/src/v4/classic/tests/void.test.ts
generated
vendored
Normal file
12
node_modules/zod/src/v4/classic/tests/void.test.ts
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
test("void", () => {
|
||||
const v = z.void();
|
||||
v.parse(undefined);
|
||||
|
||||
expect(() => v.parse(null)).toThrow();
|
||||
expect(() => v.parse("")).toThrow();
|
||||
|
||||
type v = z.infer<typeof v>;
|
||||
expectTypeOf<v>().toEqualTypeOf<void>();
|
||||
});
|
||||
1594
node_modules/zod/src/v4/core/api.ts
generated
vendored
Normal file
1594
node_modules/zod/src/v4/core/api.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1283
node_modules/zod/src/v4/core/checks.ts
generated
vendored
Normal file
1283
node_modules/zod/src/v4/core/checks.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
15
node_modules/zod/src/v4/core/config.ts
generated
vendored
Normal file
15
node_modules/zod/src/v4/core/config.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import type * as errors from "./errors.js";
|
||||
|
||||
export interface $ZodConfig {
|
||||
/** Custom error map. Overrides `config().localeError`. */
|
||||
customError?: errors.$ZodErrorMap | undefined;
|
||||
/** Localized error map. Lowest priority. */
|
||||
localeError?: errors.$ZodErrorMap | undefined;
|
||||
}
|
||||
|
||||
export const globalConfig: $ZodConfig = {};
|
||||
|
||||
export function config(config?: Partial<$ZodConfig>): $ZodConfig {
|
||||
if (config) Object.assign(globalConfig, config);
|
||||
return globalConfig;
|
||||
}
|
||||
134
node_modules/zod/src/v4/core/core.ts
generated
vendored
Normal file
134
node_modules/zod/src/v4/core/core.ts
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
import type * as errors from "./errors.js";
|
||||
import type * as schemas from "./schemas.js";
|
||||
import type { Class } from "./util.js";
|
||||
////////////////////////////// CONSTRUCTORS ///////////////////////////////////////
|
||||
|
||||
type ZodTrait = { _zod: { def: any; [k: string]: any } };
|
||||
export interface $constructor<T extends ZodTrait, D = T["_zod"]["def"]> {
|
||||
new (def: D): T;
|
||||
init(inst: T, def: D): asserts inst is T;
|
||||
}
|
||||
|
||||
/** A special constant with type `never` */
|
||||
export const NEVER: never = Object.freeze({
|
||||
status: "aborted",
|
||||
}) as never;
|
||||
|
||||
export /*@__NO_SIDE_EFFECTS__*/ function $constructor<T extends ZodTrait, D = T["_zod"]["def"]>(
|
||||
name: string,
|
||||
initializer: (inst: T, def: D) => void,
|
||||
params?: { Parent?: typeof Class }
|
||||
): $constructor<T, D> {
|
||||
function init(inst: T, def: D) {
|
||||
Object.defineProperty(inst, "_zod", {
|
||||
value: inst._zod ?? {},
|
||||
enumerable: false,
|
||||
});
|
||||
|
||||
inst._zod.traits ??= new Set();
|
||||
|
||||
inst._zod.traits.add(name);
|
||||
initializer(inst, def);
|
||||
// support prototype modifications
|
||||
for (const k in _.prototype) {
|
||||
if (!(k in inst)) Object.defineProperty(inst, k, { value: _.prototype[k].bind(inst) });
|
||||
}
|
||||
inst._zod.constr = _;
|
||||
inst._zod.def = def;
|
||||
}
|
||||
|
||||
// doesn't work if Parent has a constructor with arguments
|
||||
const Parent = params?.Parent ?? Object;
|
||||
class Definition extends Parent {}
|
||||
Object.defineProperty(Definition, "name", { value: name });
|
||||
|
||||
function _(this: any, def: D) {
|
||||
const inst = params?.Parent ? new Definition() : this;
|
||||
init(inst, def);
|
||||
inst._zod.deferred ??= [];
|
||||
for (const fn of inst._zod.deferred) {
|
||||
fn();
|
||||
}
|
||||
return inst;
|
||||
}
|
||||
|
||||
Object.defineProperty(_, "init", { value: init });
|
||||
Object.defineProperty(_, Symbol.hasInstance, {
|
||||
value: (inst: any) => {
|
||||
if (params?.Parent && inst instanceof params.Parent) return true;
|
||||
return inst?._zod?.traits?.has(name);
|
||||
},
|
||||
});
|
||||
Object.defineProperty(_, "name", { value: name });
|
||||
return _ as any;
|
||||
}
|
||||
|
||||
////////////////////////////// UTILITIES ///////////////////////////////////////
|
||||
export const $brand: unique symbol = Symbol("zod_brand");
|
||||
export type $brand<T extends string | number | symbol = string | number | symbol> = {
|
||||
[$brand]: { [k in T]: true };
|
||||
};
|
||||
|
||||
export type $ZodBranded<T extends schemas.SomeType, Brand extends string | number | symbol> = T &
|
||||
Record<"_zod", Record<"output", output<T> & $brand<Brand>>>;
|
||||
|
||||
export class $ZodAsyncError extends Error {
|
||||
constructor() {
|
||||
super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////// TYPE HELPERS ///////////////////////////////////
|
||||
|
||||
// export type input<T extends schemas.$ZodType> = T["_zod"]["input"];
|
||||
// export type output<T extends schemas.$ZodType> = T["_zod"]["output"];
|
||||
// export type input<T extends schemas.$ZodType> = T["_zod"]["input"];
|
||||
// export type output<T extends schemas.$ZodType> = T["_zod"]["output"];
|
||||
export type input<T> = T extends { _zod: { input: any } } ? Required<T["_zod"]>["input"] : unknown;
|
||||
export type output<T> = T extends { _zod: { output: any } } ? Required<T["_zod"]>["output"] : unknown;
|
||||
|
||||
// Mk2
|
||||
// export type input<T> = T extends { _zod: { "~input": any } }
|
||||
// ? T["_zod"]["~input"]
|
||||
// : T extends { _zod: { input: any } }
|
||||
// ? T["_zod"]["input"]
|
||||
// : never;
|
||||
// export type output<T> = T extends { _zod: { "~output": any } }
|
||||
// ? T["_zod"]["~output"]
|
||||
// : T extends { _zod: { output: any } }
|
||||
// ? T["_zod"]["output"]
|
||||
// : never;
|
||||
// Mk 3
|
||||
// export type input<T extends schemas.$ZodType> = T["_zod"]["input"];
|
||||
// export type output<T extends schemas.$ZodType> = T["_zod"]["output"];
|
||||
// Mk 4
|
||||
// export type input<T extends schemas.$ZodType> = T[] extends { _zod: { "~input": any } }
|
||||
// ? T["_zod"]["~input"]
|
||||
// : T extends { _zod: { input: any } }
|
||||
// ? T["_zod"]["input"]
|
||||
// : never;
|
||||
// export type output<T extends schemas.$ZodType> = T extends { _zod: { "~output": any } }
|
||||
// ? T["_zod"]["~output"]
|
||||
// : T extends { _zod: { output: any } }
|
||||
// ? T["_zod"]["output"]
|
||||
// : never;
|
||||
|
||||
export type { output as infer };
|
||||
|
||||
////////////////////////////// CONFIG ///////////////////////////////////////
|
||||
|
||||
export interface $ZodConfig {
|
||||
/** Custom error map. Overrides `config().localeError`. */
|
||||
customError?: errors.$ZodErrorMap | undefined;
|
||||
/** Localized error map. Lowest priority. */
|
||||
localeError?: errors.$ZodErrorMap | undefined;
|
||||
/** Disable JIT schema compilation. Useful in environments that disallow `eval`. */
|
||||
jitless?: boolean | undefined;
|
||||
}
|
||||
|
||||
export const globalConfig: $ZodConfig = {};
|
||||
|
||||
export function config(newConfig?: Partial<$ZodConfig>): $ZodConfig {
|
||||
if (newConfig) Object.assign(globalConfig, newConfig);
|
||||
return globalConfig;
|
||||
}
|
||||
44
node_modules/zod/src/v4/core/doc.ts
generated
vendored
Normal file
44
node_modules/zod/src/v4/core/doc.ts
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
type ModeWriter = (doc: Doc, modes: { execution: "sync" | "async" }) => void;
|
||||
|
||||
export class Doc {
|
||||
args!: string[];
|
||||
content: string[] = [];
|
||||
indent = 0;
|
||||
|
||||
constructor(args: string[] = []) {
|
||||
if (this) this.args = args;
|
||||
}
|
||||
|
||||
indented(fn: (doc: Doc) => void) {
|
||||
this.indent += 1;
|
||||
fn(this);
|
||||
this.indent -= 1;
|
||||
}
|
||||
|
||||
write(fn: ModeWriter): void;
|
||||
write(line: string): void;
|
||||
write(arg: any) {
|
||||
if (typeof arg === "function") {
|
||||
(arg as ModeWriter)(this, { execution: "sync" });
|
||||
(arg as ModeWriter)(this, { execution: "async" });
|
||||
return;
|
||||
}
|
||||
|
||||
const content = arg as string;
|
||||
const lines = content.split("\n").filter((x) => x);
|
||||
const minIndent = Math.min(...lines.map((x) => x.length - x.trimStart().length));
|
||||
const dedented = lines.map((x) => x.slice(minIndent)).map((x) => " ".repeat(this.indent * 2) + x);
|
||||
for (const line of dedented) {
|
||||
this.content.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
compile() {
|
||||
const F = Function;
|
||||
const args = this?.args;
|
||||
const content = this?.content ?? [``];
|
||||
const lines = [...content.map((x) => ` ${x}`)];
|
||||
// console.log(lines.join("\n"));
|
||||
return new F(...args, lines.join("\n"));
|
||||
}
|
||||
}
|
||||
424
node_modules/zod/src/v4/core/errors.ts
generated
vendored
Normal file
424
node_modules/zod/src/v4/core/errors.ts
generated
vendored
Normal file
@@ -0,0 +1,424 @@
|
||||
import type { $ZodCheck, $ZodStringFormats } from "./checks.js";
|
||||
import { $constructor } from "./core.js";
|
||||
import type { $ZodType } from "./schemas.js";
|
||||
import * as util from "./util.js";
|
||||
|
||||
///////////////////////////
|
||||
//// base type ////
|
||||
///////////////////////////
|
||||
export interface $ZodIssueBase {
|
||||
readonly code?: string;
|
||||
readonly input?: unknown;
|
||||
readonly path: PropertyKey[];
|
||||
readonly message: string;
|
||||
// [k: string]: unknown;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//// issue subtypes ////
|
||||
////////////////////////////////
|
||||
export interface $ZodIssueInvalidType<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "invalid_type";
|
||||
readonly expected: $ZodType["_zod"]["def"]["type"];
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueTooBig<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "too_big";
|
||||
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
|
||||
readonly maximum: number | bigint;
|
||||
readonly inclusive?: boolean;
|
||||
readonly exact?: boolean;
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueTooSmall<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "too_small";
|
||||
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
|
||||
readonly minimum: number | bigint;
|
||||
/** True if the allowable range includes the minimum */
|
||||
readonly inclusive?: boolean;
|
||||
/** True if the allowed value is fixed (e.g.` z.length(5)`), not a range (`z.minLength(5)`) */
|
||||
readonly exact?: boolean;
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueInvalidStringFormat extends $ZodIssueBase {
|
||||
readonly code: "invalid_format";
|
||||
readonly format: $ZodStringFormats | (string & {});
|
||||
readonly pattern?: string;
|
||||
readonly input: string;
|
||||
}
|
||||
|
||||
export interface $ZodIssueNotMultipleOf<Input extends number | bigint = number | bigint> extends $ZodIssueBase {
|
||||
readonly code: "not_multiple_of";
|
||||
readonly divisor: number;
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueUnrecognizedKeys extends $ZodIssueBase {
|
||||
readonly code: "unrecognized_keys";
|
||||
readonly keys: string[];
|
||||
readonly input: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface $ZodIssueInvalidUnion extends $ZodIssueBase {
|
||||
readonly code: "invalid_union";
|
||||
readonly errors: $ZodIssue[][];
|
||||
readonly input: unknown;
|
||||
}
|
||||
|
||||
export interface $ZodIssueInvalidKey<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "invalid_key";
|
||||
readonly origin: "map" | "record";
|
||||
readonly issues: $ZodIssue[];
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueInvalidElement<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "invalid_element";
|
||||
readonly origin: "map" | "set";
|
||||
readonly key: unknown;
|
||||
readonly issues: $ZodIssue[];
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueInvalidValue<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "invalid_value";
|
||||
readonly values: util.Primitive[];
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueCustom extends $ZodIssueBase {
|
||||
readonly code: "custom";
|
||||
readonly params?: Record<string, any> | undefined;
|
||||
readonly input: unknown;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
//// first-party string formats ////
|
||||
////////////////////////////////////////////
|
||||
|
||||
export interface $ZodIssueStringCommonFormats extends $ZodIssueInvalidStringFormat {
|
||||
format: Exclude<$ZodStringFormats, "regex" | "jwt" | "starts_with" | "ends_with" | "includes">;
|
||||
}
|
||||
|
||||
export interface $ZodIssueStringInvalidRegex extends $ZodIssueInvalidStringFormat {
|
||||
format: "regex";
|
||||
pattern: string;
|
||||
}
|
||||
|
||||
export interface $ZodIssueStringInvalidJWT extends $ZodIssueInvalidStringFormat {
|
||||
format: "jwt";
|
||||
algorithm?: string;
|
||||
}
|
||||
|
||||
export interface $ZodIssueStringStartsWith extends $ZodIssueInvalidStringFormat {
|
||||
format: "starts_with";
|
||||
prefix: string;
|
||||
}
|
||||
|
||||
export interface $ZodIssueStringEndsWith extends $ZodIssueInvalidStringFormat {
|
||||
format: "ends_with";
|
||||
suffix: string;
|
||||
}
|
||||
|
||||
export interface $ZodIssueStringIncludes extends $ZodIssueInvalidStringFormat {
|
||||
format: "includes";
|
||||
includes: string;
|
||||
}
|
||||
|
||||
export type $ZodStringFormatIssues =
|
||||
| $ZodIssueStringCommonFormats
|
||||
| $ZodIssueStringInvalidRegex
|
||||
| $ZodIssueStringInvalidJWT
|
||||
| $ZodIssueStringStartsWith
|
||||
| $ZodIssueStringEndsWith
|
||||
| $ZodIssueStringIncludes;
|
||||
|
||||
////////////////////////
|
||||
//// utils /////
|
||||
////////////////////////
|
||||
|
||||
export type $ZodIssue =
|
||||
| $ZodIssueInvalidType
|
||||
| $ZodIssueTooBig
|
||||
| $ZodIssueTooSmall
|
||||
| $ZodIssueInvalidStringFormat
|
||||
| $ZodIssueNotMultipleOf
|
||||
| $ZodIssueUnrecognizedKeys
|
||||
| $ZodIssueInvalidUnion
|
||||
| $ZodIssueInvalidKey
|
||||
| $ZodIssueInvalidElement
|
||||
| $ZodIssueInvalidValue
|
||||
| $ZodIssueCustom;
|
||||
|
||||
export type $ZodIssueCode = $ZodIssue["code"];
|
||||
|
||||
export type $ZodRawIssue<T extends $ZodIssueBase = $ZodIssue> = T extends any ? RawIssue<T> : never;
|
||||
type RawIssue<T extends $ZodIssueBase> = util.Flatten<
|
||||
util.MakePartial<T, "message" | "path"> & {
|
||||
/** The input data */
|
||||
readonly input?: unknown;
|
||||
/** The schema or check that originated this issue. */
|
||||
readonly inst?: $ZodType | $ZodCheck;
|
||||
/** @deprecated Internal use only. If `true`, Zod will continue executing validation despite this issue. */
|
||||
readonly continue?: boolean | undefined;
|
||||
} & Record<string, any>
|
||||
>;
|
||||
|
||||
export interface $ZodErrorMap<T extends $ZodIssueBase = $ZodIssue> {
|
||||
// biome-ignore lint:
|
||||
(issue: $ZodRawIssue<T>): { message: string } | string | undefined | null;
|
||||
}
|
||||
|
||||
//////////////////////// ERROR CLASS ////////////////////////
|
||||
|
||||
// const ZOD_ERROR: symbol = Symbol.for("{{zod.error}}");
|
||||
export interface $ZodError<T = unknown> extends Error {
|
||||
type: T;
|
||||
issues: $ZodIssue[];
|
||||
_zod: {
|
||||
output: T;
|
||||
def: $ZodIssue[];
|
||||
};
|
||||
stack?: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
const initializer = (inst: $ZodError, def: $ZodIssue[]): void => {
|
||||
inst.name = "$ZodError";
|
||||
Object.defineProperty(inst, "_zod", {
|
||||
value: inst._zod,
|
||||
enumerable: false,
|
||||
});
|
||||
Object.defineProperty(inst, "issues", {
|
||||
value: def,
|
||||
enumerable: false,
|
||||
});
|
||||
Object.defineProperty(inst, "message", {
|
||||
get() {
|
||||
return JSON.stringify(def, util.jsonStringifyReplacer, 2);
|
||||
},
|
||||
enumerable: true,
|
||||
// configurable: false,
|
||||
});
|
||||
Object.defineProperty(inst, "toString", {
|
||||
value: () => inst.message,
|
||||
enumerable: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const $ZodError: $constructor<$ZodError> = $constructor("$ZodError", initializer);
|
||||
interface $ZodRealError<T = any> extends $ZodError<T> {}
|
||||
export const $ZodRealError: $constructor<$ZodRealError> = $constructor("$ZodError", initializer, { Parent: Error });
|
||||
|
||||
/////////////////// ERROR UTILITIES ////////////////////////
|
||||
|
||||
// flatten
|
||||
export type $ZodFlattenedError<T, U = string> = _FlattenedError<T, U>;
|
||||
type _FlattenedError<T, U = string> = {
|
||||
formErrors: U[];
|
||||
fieldErrors: {
|
||||
[P in keyof T]?: U[];
|
||||
};
|
||||
};
|
||||
|
||||
export function flattenError<T>(error: $ZodError<T>): _FlattenedError<T>;
|
||||
export function flattenError<T, U>(error: $ZodError<T>, mapper?: (issue: $ZodIssue) => U): _FlattenedError<T, U>;
|
||||
export function flattenError(error: $ZodError, mapper = (issue: $ZodIssue) => issue.message): any {
|
||||
const fieldErrors: any = {};
|
||||
const formErrors: any[] = [];
|
||||
for (const sub of error.issues) {
|
||||
if (sub.path.length > 0) {
|
||||
fieldErrors[sub.path[0]!] = fieldErrors[sub.path[0]!] || [];
|
||||
fieldErrors[sub.path[0]!].push(mapper(sub));
|
||||
} else {
|
||||
formErrors.push(mapper(sub));
|
||||
}
|
||||
}
|
||||
return { formErrors, fieldErrors };
|
||||
}
|
||||
|
||||
type _ZodFormattedError<T, U = string> = T extends [any, ...any[]]
|
||||
? { [K in keyof T]?: $ZodFormattedError<T[K], U> }
|
||||
: T extends any[]
|
||||
? { [k: number]: $ZodFormattedError<T[number], U> }
|
||||
: T extends object
|
||||
? util.Flatten<{ [K in keyof T]?: $ZodFormattedError<T[K], U> }>
|
||||
: any;
|
||||
|
||||
export type $ZodFormattedError<T, U = string> = {
|
||||
_errors: U[];
|
||||
} & util.Flatten<_ZodFormattedError<T, U>>;
|
||||
|
||||
export function formatError<T>(error: $ZodError<T>): $ZodFormattedError<T>;
|
||||
export function formatError<T, U>(error: $ZodError<T>, mapper?: (issue: $ZodIssue) => U): $ZodFormattedError<T, U>;
|
||||
export function formatError<T>(error: $ZodError, _mapper?: any) {
|
||||
const mapper: (issue: $ZodIssue) => any =
|
||||
_mapper ||
|
||||
function (issue: $ZodIssue) {
|
||||
return issue.message;
|
||||
};
|
||||
const fieldErrors: $ZodFormattedError<T> = { _errors: [] } as any;
|
||||
const processError = (error: { issues: $ZodIssue[] }) => {
|
||||
for (const issue of error.issues) {
|
||||
if (issue.code === "invalid_union" && issue.errors.length) {
|
||||
issue.errors.map((issues) => processError({ issues }));
|
||||
} else if (issue.code === "invalid_key") {
|
||||
processError({ issues: issue.issues });
|
||||
} else if (issue.code === "invalid_element") {
|
||||
processError({ issues: issue.issues });
|
||||
} else if (issue.path.length === 0) {
|
||||
(fieldErrors as any)._errors.push(mapper(issue));
|
||||
} else {
|
||||
let curr: any = fieldErrors;
|
||||
let i = 0;
|
||||
while (i < issue.path.length) {
|
||||
const el = issue.path[i]!;
|
||||
const terminal = i === issue.path.length - 1;
|
||||
|
||||
if (!terminal) {
|
||||
curr[el] = curr[el] || { _errors: [] };
|
||||
} else {
|
||||
curr[el] = curr[el] || { _errors: [] };
|
||||
curr[el]._errors.push(mapper(issue));
|
||||
}
|
||||
|
||||
curr = curr[el];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
processError(error);
|
||||
return fieldErrors;
|
||||
}
|
||||
|
||||
export type $ZodErrorTree<T, U = string> = T extends [any, ...any[]]
|
||||
? { errors: U[]; items?: { [K in keyof T]?: $ZodErrorTree<T[K], U> } }
|
||||
: T extends any[]
|
||||
? { errors: U[]; items?: Array<$ZodErrorTree<T[number], U>> }
|
||||
: T extends object
|
||||
? { errors: U[]; properties?: { [K in keyof T]?: $ZodErrorTree<T[K], U> } }
|
||||
: { errors: U[] };
|
||||
|
||||
export function treeifyError<T>(error: $ZodError<T>): $ZodErrorTree<T>;
|
||||
export function treeifyError<T, U>(error: $ZodError<T>, mapper?: (issue: $ZodIssue) => U): $ZodErrorTree<T, U>;
|
||||
export function treeifyError<T>(error: $ZodError, _mapper?: any) {
|
||||
const mapper: (issue: $ZodIssue) => any =
|
||||
_mapper ||
|
||||
function (issue: $ZodIssue) {
|
||||
return issue.message;
|
||||
};
|
||||
const result: $ZodErrorTree<T> = { errors: [] } as any;
|
||||
const processError = (error: { issues: $ZodIssue[] }, path: PropertyKey[] = []) => {
|
||||
for (const issue of error.issues) {
|
||||
if (issue.code === "invalid_union" && issue.errors.length) {
|
||||
// regular union error
|
||||
issue.errors.map((issues) => processError({ issues }, issue.path));
|
||||
} else if (issue.code === "invalid_key") {
|
||||
processError({ issues: issue.issues }, issue.path);
|
||||
} else if (issue.code === "invalid_element") {
|
||||
processError({ issues: issue.issues }, issue.path);
|
||||
} else {
|
||||
const fullpath = [...path, ...issue.path];
|
||||
if (fullpath.length === 0) {
|
||||
result.errors.push(mapper(issue));
|
||||
continue;
|
||||
}
|
||||
|
||||
let curr: any = result;
|
||||
let i = 0;
|
||||
while (i < fullpath.length) {
|
||||
const el = fullpath[i]!;
|
||||
|
||||
const terminal = i === fullpath.length - 1;
|
||||
if (typeof el === "string") {
|
||||
curr.properties ??= {};
|
||||
curr.properties[el] ??= { errors: [] };
|
||||
curr = curr.properties[el];
|
||||
} else {
|
||||
curr.items ??= [];
|
||||
curr.items[el] ??= { errors: [] };
|
||||
curr = curr.items[el];
|
||||
}
|
||||
|
||||
if (terminal) {
|
||||
curr.errors.push(mapper(issue));
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
processError(error);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Format a ZodError as a human-readable string in the following form.
|
||||
*
|
||||
* From
|
||||
*
|
||||
* ```ts
|
||||
* ZodError {
|
||||
* issues: [
|
||||
* {
|
||||
* expected: 'string',
|
||||
* code: 'invalid_type',
|
||||
* path: [ 'username' ],
|
||||
* message: 'Invalid input: expected string'
|
||||
* },
|
||||
* {
|
||||
* expected: 'number',
|
||||
* code: 'invalid_type',
|
||||
* path: [ 'favoriteNumbers', 1 ],
|
||||
* message: 'Invalid input: expected number'
|
||||
* }
|
||||
* ];
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* to
|
||||
*
|
||||
* ```
|
||||
* username
|
||||
* ✖ Expected number, received string at "username
|
||||
* favoriteNumbers[0]
|
||||
* ✖ Invalid input: expected number
|
||||
* ```
|
||||
*/
|
||||
export function toDotPath(path: (string | number | symbol)[]): string {
|
||||
const segs: string[] = [];
|
||||
for (const seg of path) {
|
||||
if (typeof seg === "number") segs.push(`[${seg}]`);
|
||||
else if (typeof seg === "symbol") segs.push(`[${JSON.stringify(String(seg))}]`);
|
||||
else if (/[^\w$]/.test(seg)) segs.push(`[${JSON.stringify(seg)}]`);
|
||||
else {
|
||||
if (segs.length) segs.push(".");
|
||||
segs.push(seg);
|
||||
}
|
||||
}
|
||||
|
||||
return segs.join("");
|
||||
}
|
||||
|
||||
interface BaseError {
|
||||
issues: $ZodIssueBase[];
|
||||
}
|
||||
|
||||
export function prettifyError(error: BaseError): string {
|
||||
const lines: string[] = [];
|
||||
// sort by path length
|
||||
const issues = [...error.issues].sort((a, b) => a.path.length - b.path.length);
|
||||
|
||||
// Process each issue
|
||||
for (const issue of issues) {
|
||||
lines.push(`✖ ${issue.message}`);
|
||||
if (issue.path?.length) lines.push(` → at ${toDotPath(issue.path)}`);
|
||||
}
|
||||
|
||||
// Convert Map to formatted string
|
||||
return lines.join("\n");
|
||||
}
|
||||
176
node_modules/zod/src/v4/core/function.ts
generated
vendored
Normal file
176
node_modules/zod/src/v4/core/function.ts
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
import { _array, _tuple, _unknown } from "./api.js";
|
||||
import type * as core from "./core.js";
|
||||
import { parse, parseAsync } from "./parse.js";
|
||||
import * as schemas from "./schemas.js";
|
||||
import { $ZodTuple } from "./schemas.js";
|
||||
import type * as util from "./util.js";
|
||||
|
||||
//////////////////////////////////////////
|
||||
//////////////////////////////////////////
|
||||
////////// //////////
|
||||
////////// $ZodFunction //////////
|
||||
////////// //////////
|
||||
//////////////////////////////////////////
|
||||
//////////////////////////////////////////
|
||||
export interface $ZodFunctionDef<
|
||||
In extends $ZodFunctionIn = $ZodFunctionIn,
|
||||
Out extends $ZodFunctionOut = $ZodFunctionOut,
|
||||
> {
|
||||
type: "function";
|
||||
input: In;
|
||||
output: Out;
|
||||
}
|
||||
|
||||
export type $ZodFunctionArgs = schemas.$ZodType<unknown[], unknown[]>;
|
||||
export type $ZodFunctionIn = $ZodFunctionArgs;
|
||||
export type $ZodFunctionOut = schemas.$ZodType;
|
||||
|
||||
export type $InferInnerFunctionType<Args extends $ZodFunctionIn, Returns extends $ZodFunctionOut> = (
|
||||
...args: $ZodFunctionIn extends Args ? never[] : core.output<Args>
|
||||
) => core.input<Returns>;
|
||||
|
||||
export type $InferInnerFunctionTypeAsync<Args extends $ZodFunctionIn, Returns extends $ZodFunctionOut> = (
|
||||
...args: $ZodFunctionIn extends Args ? never[] : core.output<Args>
|
||||
) => util.MaybeAsync<core.input<Returns>>;
|
||||
|
||||
export type $InferOuterFunctionType<Args extends $ZodFunctionIn, Returns extends $ZodFunctionOut> = (
|
||||
...args: $ZodFunctionIn extends Args ? never[] : core.input<Args>
|
||||
) => core.output<Returns>;
|
||||
|
||||
export type $InferOuterFunctionTypeAsync<Args extends $ZodFunctionIn, Returns extends $ZodFunctionOut> = (
|
||||
...args: $ZodFunctionIn extends Args ? never[] : core.input<Args>
|
||||
) => util.MaybeAsync<core.output<Returns>>;
|
||||
|
||||
export class $ZodFunction<
|
||||
Args extends $ZodFunctionIn = $ZodFunctionIn,
|
||||
Returns extends $ZodFunctionOut = $ZodFunctionOut,
|
||||
> {
|
||||
def: $ZodFunctionDef<Args, Returns>;
|
||||
|
||||
/** @deprecated */
|
||||
_def!: $ZodFunctionDef<Args, Returns>;
|
||||
_input!: $InferInnerFunctionType<Args, Returns>;
|
||||
_output!: $InferOuterFunctionType<Args, Returns>;
|
||||
|
||||
constructor(def: $ZodFunctionDef<Args, Returns>) {
|
||||
this._def = def;
|
||||
this.def = def;
|
||||
}
|
||||
|
||||
implement<F extends $InferInnerFunctionType<Args, Returns>>(
|
||||
func: F
|
||||
): // allow for return type inference
|
||||
(
|
||||
...args: Parameters<this["_output"]>
|
||||
) => ReturnType<F> extends ReturnType<this["_output"]> ? ReturnType<F> : ReturnType<this["_output"]> {
|
||||
if (typeof func !== "function") {
|
||||
throw new Error("implement() must be called with a function");
|
||||
}
|
||||
const impl = ((...args: any[]) => {
|
||||
const parsedArgs = this._def.input ? parse(this._def.input, args, undefined, { callee: impl }) : args;
|
||||
if (!Array.isArray(parsedArgs)) {
|
||||
throw new Error("Invalid arguments schema: not an array or tuple schema.");
|
||||
}
|
||||
const output = func(...(parsedArgs as any));
|
||||
return this._def.output ? parse(this._def.output, output, undefined, { callee: impl }) : output;
|
||||
}) as any;
|
||||
return impl;
|
||||
}
|
||||
|
||||
implementAsync<F extends $InferInnerFunctionTypeAsync<Args, Returns>>(
|
||||
func: F
|
||||
): F extends $InferOuterFunctionTypeAsync<Args, Returns> ? F : $InferOuterFunctionTypeAsync<Args, Returns> {
|
||||
if (typeof func !== "function") {
|
||||
throw new Error("implement() must be called with a function");
|
||||
}
|
||||
|
||||
const impl = (async (...args: any[]) => {
|
||||
const parsedArgs = this._def.input ? await parseAsync(this._def.input, args, undefined, { callee: impl }) : args;
|
||||
if (!Array.isArray(parsedArgs)) {
|
||||
throw new Error("Invalid arguments schema: not an array or tuple schema.");
|
||||
}
|
||||
const output = await func(...(parsedArgs as any));
|
||||
return this._def.output ? parseAsync(this._def.output, output, undefined, { callee: impl }) : output;
|
||||
}) as any;
|
||||
return impl;
|
||||
}
|
||||
|
||||
input<const Items extends util.TupleItems, const Rest extends $ZodFunctionOut = $ZodFunctionOut>(
|
||||
args: Items,
|
||||
rest?: Rest
|
||||
): $ZodFunction<schemas.$ZodTuple<Items, Rest>, Returns>;
|
||||
input<NewArgs extends $ZodFunctionIn>(args: NewArgs): $ZodFunction<NewArgs, Returns>;
|
||||
input(...args: any[]): $ZodFunction<any, Returns> {
|
||||
const F: any = this.constructor;
|
||||
if (Array.isArray(args[0])) {
|
||||
return new F({
|
||||
type: "function",
|
||||
input: new $ZodTuple({
|
||||
type: "tuple",
|
||||
items: args[0],
|
||||
rest: args[1],
|
||||
}),
|
||||
output: this._def.output,
|
||||
});
|
||||
}
|
||||
|
||||
return new F({
|
||||
type: "function",
|
||||
input: args[0],
|
||||
output: this._def.output,
|
||||
});
|
||||
}
|
||||
|
||||
output<NewReturns extends schemas.$ZodType>(output: NewReturns): $ZodFunction<Args, NewReturns> {
|
||||
const F: any = this.constructor;
|
||||
return new F({
|
||||
type: "function",
|
||||
input: this._def.input,
|
||||
output,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export interface $ZodFunctionParams<I extends $ZodFunctionIn, O extends schemas.$ZodType> {
|
||||
input?: I;
|
||||
output?: O;
|
||||
}
|
||||
|
||||
function _function(): $ZodFunction;
|
||||
function _function<const In extends Array<schemas.$ZodType> = Array<schemas.$ZodType>>(params: {
|
||||
input: In;
|
||||
}): $ZodFunction<$ZodTuple<In, null>, $ZodFunctionOut>;
|
||||
function _function<
|
||||
const In extends Array<schemas.$ZodType> = Array<schemas.$ZodType>,
|
||||
const Out extends $ZodFunctionOut = $ZodFunctionOut,
|
||||
>(params: {
|
||||
input: In;
|
||||
output: Out;
|
||||
}): $ZodFunction<$ZodTuple<In, null>, Out>;
|
||||
function _function<const In extends $ZodFunctionIn = $ZodFunctionIn>(params: {
|
||||
input: In;
|
||||
}): $ZodFunction<In, $ZodFunctionOut>;
|
||||
function _function<const Out extends $ZodFunctionOut = $ZodFunctionOut>(params: {
|
||||
output: Out;
|
||||
}): $ZodFunction<$ZodFunctionIn, Out>;
|
||||
function _function<
|
||||
In extends $ZodFunctionIn = $ZodFunctionIn,
|
||||
Out extends schemas.$ZodType = schemas.$ZodType,
|
||||
>(params?: {
|
||||
input: In;
|
||||
output: Out;
|
||||
}): $ZodFunction<In, Out>;
|
||||
function _function(params?: {
|
||||
output?: schemas.$ZodType;
|
||||
input?: $ZodFunctionArgs | Array<schemas.$ZodType>;
|
||||
}): any {
|
||||
return new $ZodFunction({
|
||||
type: "function",
|
||||
input: Array.isArray(params?.input)
|
||||
? _tuple(schemas.$ZodTuple, params?.input as any)
|
||||
: (params?.input ?? _array(schemas.$ZodArray, _unknown(schemas.$ZodUnknown))),
|
||||
output: params?.output ?? _unknown(schemas.$ZodUnknown),
|
||||
});
|
||||
}
|
||||
|
||||
export { _function as function };
|
||||
15
node_modules/zod/src/v4/core/index.ts
generated
vendored
Normal file
15
node_modules/zod/src/v4/core/index.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
export * from "./core.js";
|
||||
export * from "./parse.js";
|
||||
export * from "./errors.js";
|
||||
export * from "./schemas.js";
|
||||
export * from "./checks.js";
|
||||
export * from "./versions.js";
|
||||
export * as util from "./util.js";
|
||||
export * as regexes from "./regexes.js";
|
||||
export * as locales from "../locales/index.js";
|
||||
export * from "./registries.js";
|
||||
export * from "./doc.js";
|
||||
export * from "./function.js";
|
||||
export * from "./api.js";
|
||||
export * from "./to-json-schema.js";
|
||||
export * as JSONSchema from "./json-schema.js";
|
||||
143
node_modules/zod/src/v4/core/json-schema.ts
generated
vendored
Normal file
143
node_modules/zod/src/v4/core/json-schema.ts
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
export type Schema =
|
||||
| ObjectSchema
|
||||
| ArraySchema
|
||||
| StringSchema
|
||||
| NumberSchema
|
||||
| IntegerSchema
|
||||
| BooleanSchema
|
||||
| NullSchema;
|
||||
|
||||
// export type JsonType = "object" | "array" | "string" | "number" | "boolean" | "null" | "integer";
|
||||
|
||||
// export interface JSONSchema {
|
||||
// type?: string ;
|
||||
// $id?: string ;
|
||||
// id?: string ;
|
||||
// $schema?: string ;
|
||||
// $ref?: string ;
|
||||
// $anchor?: string ;
|
||||
// $defs?: { [key: string]: JSONSchema } ;
|
||||
// definitions?: { [key: string]: JSONSchema } ;
|
||||
// $comment?: string ;
|
||||
// title?: string ;
|
||||
// description?: string ;
|
||||
// default?: unknown ;
|
||||
// examples?: unknown[] ;
|
||||
// readOnly?: boolean ;
|
||||
// writeOnly?: boolean ;
|
||||
// deprecated?: boolean ;
|
||||
// allOf?: JSONSchema[] ;
|
||||
// anyOf?: JSONSchema[] ;
|
||||
// oneOf?: JSONSchema[] ;
|
||||
// not?: JSONSchema ;
|
||||
// if?: JSONSchema ;
|
||||
// then?: JSONSchema ;
|
||||
// else?: JSONSchema ;
|
||||
// enum?: Array<string | number | boolean | null> ;
|
||||
// const?: string | number | boolean | null ;
|
||||
// [k: string]: unknown;
|
||||
|
||||
// /** A special key used as an intermediate representation of extends-style relationships. Omitted as a $ref with additional properties. */
|
||||
// // _ref?: JSONSchema;
|
||||
// _prefault?: unknown ;
|
||||
// }
|
||||
|
||||
export type _JSONSchema = boolean | JSONSchema;
|
||||
export type JSONSchema = {
|
||||
[k: string]: unknown;
|
||||
$schema?: "https://json-schema.org/draft/2020-12/schema" | "http://json-schema.org/draft-07/schema#";
|
||||
$id?: string;
|
||||
$anchor?: string;
|
||||
$ref?: string;
|
||||
$dynamicRef?: string;
|
||||
$dynamicAnchor?: string;
|
||||
$vocabulary?: Record<string, boolean>;
|
||||
$comment?: string;
|
||||
$defs?: Record<string, JSONSchema>;
|
||||
type?: "object" | "array" | "string" | "number" | "boolean" | "null" | "integer";
|
||||
additionalItems?: _JSONSchema;
|
||||
unevaluatedItems?: _JSONSchema;
|
||||
prefixItems?: _JSONSchema[];
|
||||
items?: _JSONSchema | _JSONSchema[];
|
||||
contains?: _JSONSchema;
|
||||
additionalProperties?: _JSONSchema;
|
||||
unevaluatedProperties?: _JSONSchema;
|
||||
properties?: Record<string, _JSONSchema>;
|
||||
patternProperties?: Record<string, _JSONSchema>;
|
||||
dependentSchemas?: Record<string, _JSONSchema>;
|
||||
propertyNames?: _JSONSchema;
|
||||
if?: _JSONSchema;
|
||||
then?: _JSONSchema;
|
||||
else?: _JSONSchema;
|
||||
allOf?: JSONSchema[];
|
||||
anyOf?: JSONSchema[];
|
||||
oneOf?: JSONSchema[];
|
||||
not?: _JSONSchema;
|
||||
multipleOf?: number;
|
||||
maximum?: number;
|
||||
exclusiveMaximum?: number;
|
||||
minimum?: number;
|
||||
exclusiveMinimum?: number;
|
||||
maxLength?: number;
|
||||
minLength?: number;
|
||||
pattern?: string;
|
||||
maxItems?: number;
|
||||
minItems?: number;
|
||||
uniqueItems?: boolean;
|
||||
maxContains?: number;
|
||||
minContains?: number;
|
||||
maxProperties?: number;
|
||||
minProperties?: number;
|
||||
required?: string[];
|
||||
dependentRequired?: Record<string, string[]>;
|
||||
enum?: Array<string | number | boolean | null>;
|
||||
const?: string | number | boolean | null;
|
||||
|
||||
// metadata
|
||||
id?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
default?: unknown;
|
||||
deprecated?: boolean;
|
||||
readOnly?: boolean;
|
||||
writeOnly?: boolean;
|
||||
examples?: unknown[];
|
||||
format?: string;
|
||||
contentMediaType?: string;
|
||||
contentEncoding?: string;
|
||||
contentSchema?: JSONSchema;
|
||||
|
||||
// internal
|
||||
_prefault?: unknown;
|
||||
};
|
||||
|
||||
// for backwards compatibility
|
||||
export type BaseSchema = JSONSchema;
|
||||
|
||||
export interface ObjectSchema extends JSONSchema {
|
||||
type: "object";
|
||||
}
|
||||
|
||||
export interface ArraySchema extends JSONSchema {
|
||||
type: "array";
|
||||
}
|
||||
|
||||
export interface StringSchema extends JSONSchema {
|
||||
type: "string";
|
||||
}
|
||||
|
||||
export interface NumberSchema extends JSONSchema {
|
||||
type: "number";
|
||||
}
|
||||
|
||||
export interface IntegerSchema extends JSONSchema {
|
||||
type: "integer";
|
||||
}
|
||||
|
||||
export interface BooleanSchema extends JSONSchema {
|
||||
type: "boolean";
|
||||
}
|
||||
|
||||
export interface NullSchema extends JSONSchema {
|
||||
type: "null";
|
||||
}
|
||||
94
node_modules/zod/src/v4/core/parse.ts
generated
vendored
Normal file
94
node_modules/zod/src/v4/core/parse.ts
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
import * as core from "./core.js";
|
||||
import * as errors from "./errors.js";
|
||||
import type * as schemas from "./schemas.js";
|
||||
import * as util from "./util.js";
|
||||
|
||||
export type $ZodErrorClass = { new (issues: errors.$ZodIssue[]): errors.$ZodError };
|
||||
|
||||
/////////// METHODS ///////////
|
||||
export type $Parse = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>,
|
||||
_params?: { callee?: util.AnyFunc; Err?: $ZodErrorClass }
|
||||
) => core.output<T>;
|
||||
|
||||
export const _parse: (_Err: $ZodErrorClass) => $Parse = (_Err) => (schema, value, _ctx, _params) => {
|
||||
const ctx: schemas.ParseContextInternal = _ctx ? Object.assign(_ctx, { async: false }) : { async: false };
|
||||
const result = schema._zod.run({ value, issues: [] }, ctx);
|
||||
if (result instanceof Promise) {
|
||||
throw new core.$ZodAsyncError();
|
||||
}
|
||||
if (result.issues.length) {
|
||||
const e = new (_params?.Err ?? _Err)(result.issues.map((iss) => util.finalizeIssue(iss, ctx, core.config())));
|
||||
util.captureStackTrace(e, _params?.callee);
|
||||
throw e;
|
||||
}
|
||||
return result.value as core.output<typeof schema>;
|
||||
};
|
||||
|
||||
export const parse: $Parse = /* @__PURE__*/ _parse(errors.$ZodRealError);
|
||||
|
||||
export type $ParseAsync = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>,
|
||||
_params?: { callee?: util.AnyFunc; Err?: $ZodErrorClass }
|
||||
) => Promise<core.output<T>>;
|
||||
|
||||
export const _parseAsync: (_Err: $ZodErrorClass) => $ParseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
||||
const ctx: schemas.ParseContextInternal = _ctx ? Object.assign(_ctx, { async: true }) : { async: true };
|
||||
let result = schema._zod.run({ value, issues: [] }, ctx);
|
||||
if (result instanceof Promise) result = await result;
|
||||
if (result.issues.length) {
|
||||
const e = new (params?.Err ?? _Err)(result.issues.map((iss) => util.finalizeIssue(iss, ctx, core.config())));
|
||||
util.captureStackTrace(e, params?.callee);
|
||||
throw e;
|
||||
}
|
||||
return result.value as core.output<typeof schema>;
|
||||
};
|
||||
|
||||
export const parseAsync: $ParseAsync = /* @__PURE__*/ _parseAsync(errors.$ZodRealError);
|
||||
|
||||
export type $SafeParse = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => util.SafeParseResult<core.output<T>>;
|
||||
|
||||
export const _safeParse: (_Err: $ZodErrorClass) => $SafeParse = (_Err) => (schema, value, _ctx) => {
|
||||
const ctx: schemas.ParseContextInternal = _ctx ? { ..._ctx, async: false } : { async: false };
|
||||
const result = schema._zod.run({ value, issues: [] }, ctx);
|
||||
if (result instanceof Promise) {
|
||||
throw new core.$ZodAsyncError();
|
||||
}
|
||||
|
||||
return result.issues.length
|
||||
? {
|
||||
success: false,
|
||||
error: new (_Err ?? errors.$ZodError)(result.issues.map((iss) => util.finalizeIssue(iss, ctx, core.config()))),
|
||||
}
|
||||
: ({ success: true, data: result.value } as any);
|
||||
};
|
||||
export const safeParse: $SafeParse = /* @__PURE__*/ _safeParse(errors.$ZodRealError);
|
||||
|
||||
export type $SafeParseAsync = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => Promise<util.SafeParseResult<core.output<T>>>;
|
||||
|
||||
export const _safeParseAsync: (_Err: $ZodErrorClass) => $SafeParseAsync = (_Err) => async (schema, value, _ctx) => {
|
||||
const ctx: schemas.ParseContextInternal = _ctx ? Object.assign(_ctx, { async: true }) : { async: true };
|
||||
let result = schema._zod.run({ value, issues: [] }, ctx);
|
||||
if (result instanceof Promise) result = await result;
|
||||
|
||||
return result.issues.length
|
||||
? {
|
||||
success: false,
|
||||
error: new _Err(result.issues.map((iss) => util.finalizeIssue(iss, ctx, core.config()))),
|
||||
}
|
||||
: ({ success: true, data: result.value } as any);
|
||||
};
|
||||
|
||||
export const safeParseAsync: $SafeParseAsync = /* @__PURE__*/ _safeParseAsync(errors.$ZodRealError);
|
||||
135
node_modules/zod/src/v4/core/regexes.ts
generated
vendored
Normal file
135
node_modules/zod/src/v4/core/regexes.ts
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
export const cuid: RegExp = /^[cC][^\s-]{8,}$/;
|
||||
export const cuid2: RegExp = /^[0-9a-z]+$/;
|
||||
export const ulid: RegExp = /^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/;
|
||||
export const xid: RegExp = /^[0-9a-vA-V]{20}$/;
|
||||
export const ksuid: RegExp = /^[A-Za-z0-9]{27}$/;
|
||||
export const nanoid: RegExp = /^[a-zA-Z0-9_-]{21}$/;
|
||||
|
||||
/** ISO 8601-1 duration regex. Does not support the 8601-2 extensions like negative durations or fractional/negative components. */
|
||||
export const duration: RegExp =
|
||||
/^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/;
|
||||
|
||||
/** Implements ISO 8601-2 extensions like explicit +- prefixes, mixing weeks with other units, and fractional/negative components. */
|
||||
export const extendedDuration: RegExp =
|
||||
/^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;
|
||||
|
||||
/** A regex for any UUID-like identifier: 8-4-4-4-12 hex pattern */
|
||||
export const guid: RegExp = /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/;
|
||||
|
||||
/** Returns a regex for validating an RFC 4122 UUID.
|
||||
*
|
||||
* @param version Optionally specify a version 1-8. If no version is specified, all versions are supported. */
|
||||
export const uuid = (version?: number | undefined): RegExp => {
|
||||
if (!version)
|
||||
return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000)$/;
|
||||
return new RegExp(
|
||||
`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`
|
||||
);
|
||||
};
|
||||
export const uuid4: RegExp = /*@__PURE__*/ uuid(4);
|
||||
export const uuid6: RegExp = /*@__PURE__*/ uuid(6);
|
||||
export const uuid7: RegExp = /*@__PURE__*/ uuid(7);
|
||||
|
||||
/** Practical email validation */
|
||||
export const email: RegExp =
|
||||
/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
|
||||
|
||||
/** Equivalent to the HTML5 input[type=email] validation implemented by browsers. Source: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email */
|
||||
export const html5Email: RegExp =
|
||||
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
||||
|
||||
/** The classic emailregex.com regex for RFC 5322-compliant emails */
|
||||
export const rfc5322Email =
|
||||
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
|
||||
/** A loose regex that allows Unicode characters, enforces length limits, and that's about it. */
|
||||
export const unicodeEmail = /^[^\s@"]{1,64}@[^\s@]{1,255}$/u;
|
||||
|
||||
export const browserEmail: RegExp =
|
||||
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
||||
// from https://thekevinscott.com/emojis-in-javascript/#writing-a-regular-expression
|
||||
|
||||
export const _emoji = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;
|
||||
export function emoji(): RegExp {
|
||||
return new RegExp(_emoji, "u");
|
||||
}
|
||||
|
||||
export const ipv4: RegExp =
|
||||
/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
|
||||
export const ipv6: RegExp =
|
||||
/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})$/;
|
||||
|
||||
export const cidrv4: RegExp =
|
||||
/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
|
||||
export const cidrv6: RegExp =
|
||||
/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
|
||||
|
||||
// https://stackoverflow.com/questions/7860392/determine-if-string-is-in-base64-using-javascript
|
||||
export const base64: RegExp = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
|
||||
export const base64url: RegExp = /^[A-Za-z0-9_-]*$/;
|
||||
|
||||
// based on https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address
|
||||
// export const hostname: RegExp =
|
||||
// /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)+([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/;
|
||||
export const hostname: RegExp = /^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+$/;
|
||||
export const domain: RegExp = /^([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
|
||||
|
||||
// https://blog.stevenlevithan.com/archives/validate-phone-number#r4-3 (regex sans spaces)
|
||||
export const e164: RegExp = /^\+(?:[0-9]){6,14}[0-9]$/;
|
||||
|
||||
// const dateSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))`;
|
||||
const dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`;
|
||||
export const date: RegExp = /*@__PURE__*/ new RegExp(`^${dateSource}$`);
|
||||
|
||||
function timeSource(args: { precision?: number | null | undefined }) {
|
||||
const hhmm = `(?:[01]\\d|2[0-3]):[0-5]\\d`;
|
||||
const regex =
|
||||
typeof args.precision === "number"
|
||||
? args.precision === -1
|
||||
? `${hhmm}`
|
||||
: args.precision === 0
|
||||
? `${hhmm}:[0-5]\\d`
|
||||
: `${hhmm}:[0-5]\\d\\.\\d{${args.precision}}`
|
||||
: `${hhmm}(?::[0-5]\\d(?:\\.\\d+)?)?`;
|
||||
return regex;
|
||||
}
|
||||
export function time(args: {
|
||||
precision?: number | null;
|
||||
// local?: boolean;
|
||||
}): RegExp {
|
||||
return new RegExp(`^${timeSource(args)}$`);
|
||||
}
|
||||
|
||||
// Adapted from https://stackoverflow.com/a/3143231
|
||||
export function datetime(args: {
|
||||
precision?: number | null;
|
||||
offset?: boolean;
|
||||
local?: boolean;
|
||||
}): RegExp {
|
||||
const time = timeSource({ precision: args.precision });
|
||||
const opts = ["Z"];
|
||||
if (args.local) opts.push("");
|
||||
if (args.offset) opts.push(`([+-]\\d{2}:\\d{2})`);
|
||||
const timeRegex = `${time}(?:${opts.join("|")})`;
|
||||
|
||||
return new RegExp(`^${dateSource}T(?:${timeRegex})$`);
|
||||
}
|
||||
|
||||
export const string = (params?: { minimum?: number | undefined; maximum?: number | undefined }): RegExp => {
|
||||
const regex = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
|
||||
return new RegExp(`^${regex}$`);
|
||||
};
|
||||
|
||||
export const bigint: RegExp = /^\d+n?$/;
|
||||
export const integer: RegExp = /^\d+$/;
|
||||
export const number: RegExp = /^-?\d+(?:\.\d+)?/i;
|
||||
export const boolean: RegExp = /true|false/i;
|
||||
const _null: RegExp = /null/i;
|
||||
export { _null as null };
|
||||
const _undefined: RegExp = /undefined/i;
|
||||
export { _undefined as undefined };
|
||||
|
||||
// regex for string with no uppercase letters
|
||||
export const lowercase: RegExp = /^[^A-Z]*$/;
|
||||
// regex for string with no lowercase letters
|
||||
export const uppercase: RegExp = /^[^a-z]*$/;
|
||||
96
node_modules/zod/src/v4/core/registries.ts
generated
vendored
Normal file
96
node_modules/zod/src/v4/core/registries.ts
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
import type * as core from "./core.js";
|
||||
import type { $ZodType } from "./schemas.js";
|
||||
|
||||
export const $output: unique symbol = Symbol("ZodOutput");
|
||||
export type $output = typeof $output;
|
||||
export const $input: unique symbol = Symbol("ZodInput");
|
||||
export type $input = typeof $input;
|
||||
|
||||
export type $replace<Meta, S extends $ZodType> = Meta extends $output
|
||||
? core.output<S>
|
||||
: Meta extends $input
|
||||
? core.input<S>
|
||||
: Meta extends (infer M)[]
|
||||
? $replace<M, S>[]
|
||||
: Meta extends (...args: infer P) => infer R
|
||||
? (
|
||||
...args: {
|
||||
[K in keyof P]: $replace<P[K], S>; // tuple
|
||||
}
|
||||
) => $replace<R, S>
|
||||
: // handle objects
|
||||
Meta extends object
|
||||
? { [K in keyof Meta]: $replace<Meta[K], S> }
|
||||
: Meta;
|
||||
|
||||
type MetadataType = Record<string, unknown> | undefined;
|
||||
export class $ZodRegistry<Meta extends MetadataType = MetadataType, Schema extends $ZodType = $ZodType> {
|
||||
_meta!: Meta;
|
||||
_schema!: Schema;
|
||||
_map: Map<Schema, $replace<Meta, Schema>> = new Map();
|
||||
_idmap: Map<string, Schema> = new Map();
|
||||
|
||||
add<S extends Schema>(
|
||||
schema: S,
|
||||
..._meta: undefined extends Meta ? [$replace<Meta, S>?] : [$replace<Meta, S>]
|
||||
): this {
|
||||
const meta: any = _meta[0];
|
||||
this._map.set(schema, meta!);
|
||||
if (meta && typeof meta === "object" && "id" in meta) {
|
||||
if (this._idmap.has(meta.id!)) {
|
||||
throw new Error(`ID ${meta.id} already exists in the registry`);
|
||||
}
|
||||
this._idmap.set(meta.id!, schema);
|
||||
}
|
||||
return this as any;
|
||||
}
|
||||
|
||||
clear(): this {
|
||||
this._map = new Map();
|
||||
this._idmap = new Map();
|
||||
return this;
|
||||
}
|
||||
|
||||
remove(schema: Schema): this {
|
||||
const meta: any = this._map.get(schema);
|
||||
if (meta && typeof meta === "object" && "id" in meta) {
|
||||
this._idmap.delete(meta.id!);
|
||||
}
|
||||
this._map.delete(schema);
|
||||
return this;
|
||||
}
|
||||
|
||||
get<S extends Schema>(schema: S): $replace<Meta, S> | undefined {
|
||||
// return this._map.get(schema) as any;
|
||||
|
||||
// inherit metadata
|
||||
const p = schema._zod.parent as Schema;
|
||||
if (p) {
|
||||
const pm: any = { ...(this.get(p) ?? {}) };
|
||||
delete pm.id; // do not inherit id
|
||||
return { ...pm, ...this._map.get(schema) } as any;
|
||||
}
|
||||
return this._map.get(schema) as any;
|
||||
}
|
||||
|
||||
has(schema: Schema): boolean {
|
||||
return this._map.has(schema);
|
||||
}
|
||||
}
|
||||
|
||||
export interface JSONSchemaMeta {
|
||||
id?: string | undefined;
|
||||
title?: string | undefined;
|
||||
description?: string | undefined;
|
||||
deprecated?: boolean | undefined;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
|
||||
export interface GlobalMeta extends JSONSchemaMeta {}
|
||||
|
||||
// registries
|
||||
export function registry<T extends MetadataType = MetadataType, S extends $ZodType = $ZodType>(): $ZodRegistry<T, S> {
|
||||
return new $ZodRegistry<T, S>();
|
||||
}
|
||||
|
||||
export const globalRegistry: $ZodRegistry<GlobalMeta> = /*@__PURE__*/ registry<GlobalMeta>();
|
||||
3842
node_modules/zod/src/v4/core/schemas.ts
generated
vendored
Normal file
3842
node_modules/zod/src/v4/core/schemas.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
64
node_modules/zod/src/v4/core/standard-schema.ts
generated
vendored
Normal file
64
node_modules/zod/src/v4/core/standard-schema.ts
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
/** The Standard Schema interface. */
|
||||
export interface StandardSchemaV1<Input = unknown, Output = Input> {
|
||||
/** The Standard Schema properties. */
|
||||
readonly "~standard": StandardSchemaV1.Props<Input, Output>;
|
||||
}
|
||||
|
||||
export declare namespace StandardSchemaV1 {
|
||||
/** The Standard Schema properties interface. */
|
||||
export interface Props<Input = unknown, Output = Input> {
|
||||
/** The version number of the standard. */
|
||||
readonly version: 1;
|
||||
/** The vendor name of the schema library. */
|
||||
readonly vendor: string;
|
||||
/** Validates unknown input values. */
|
||||
readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
|
||||
/** Inferred types associated with the schema. */
|
||||
readonly types?: Types<Input, Output> | undefined;
|
||||
}
|
||||
|
||||
/** The result interface of the validate function. */
|
||||
export type Result<Output> = SuccessResult<Output> | FailureResult;
|
||||
|
||||
/** The result interface if validation succeeds. */
|
||||
export interface SuccessResult<Output> {
|
||||
/** The typed output value. */
|
||||
readonly value: Output;
|
||||
/** The non-existent issues. */
|
||||
readonly issues?: undefined;
|
||||
}
|
||||
|
||||
/** The result interface if validation fails. */
|
||||
export interface FailureResult {
|
||||
/** The issues of failed validation. */
|
||||
readonly issues: ReadonlyArray<Issue>;
|
||||
}
|
||||
|
||||
/** The issue interface of the failure output. */
|
||||
export interface Issue {
|
||||
/** The error message of the issue. */
|
||||
readonly message: string;
|
||||
/** The path of the issue, if any. */
|
||||
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
|
||||
}
|
||||
|
||||
/** The path segment interface of the issue. */
|
||||
export interface PathSegment {
|
||||
/** The key representing a path segment. */
|
||||
readonly key: PropertyKey;
|
||||
}
|
||||
|
||||
/** The Standard Schema types interface. */
|
||||
export interface Types<Input = unknown, Output = Input> {
|
||||
/** The input type of the schema. */
|
||||
readonly input: Input;
|
||||
/** The output type of the schema. */
|
||||
readonly output: Output;
|
||||
}
|
||||
|
||||
/** Infers the input type of a Standard Schema. */
|
||||
export type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["input"];
|
||||
|
||||
/** Infers the output type of a Standard Schema. */
|
||||
export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["output"];
|
||||
}
|
||||
46
node_modules/zod/src/v4/core/tests/index.test.ts
generated
vendored
Normal file
46
node_modules/zod/src/v4/core/tests/index.test.ts
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v3";
|
||||
|
||||
test("test", () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
test("test2", () => {
|
||||
expect(() => z.string().parse(234)).toThrowErrorMatchingInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"received": "number",
|
||||
"path": [],
|
||||
"message": "Expected string, received number"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("async validation", async () => {
|
||||
const testTuple = z
|
||||
.tuple([z.string().refine(async () => true), z.number().refine(async () => true)])
|
||||
.refine(async () => true);
|
||||
expectTypeOf<typeof testTuple._output>().toEqualTypeOf<[string, number]>();
|
||||
|
||||
const val = await testTuple.parseAsync(["asdf", 1234]);
|
||||
expect(val).toEqual(val);
|
||||
|
||||
const r1 = await testTuple.safeParseAsync(["asdf", "asdf"]);
|
||||
expect(r1.success).toEqual(false);
|
||||
expect(r1.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "number",
|
||||
"received": "string",
|
||||
"path": [
|
||||
1
|
||||
],
|
||||
"message": "Expected number, received string"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
124
node_modules/zod/src/v4/core/tests/locales/be.test.ts
generated
vendored
Normal file
124
node_modules/zod/src/v4/core/tests/locales/be.test.ts
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import be from "../../../locales/be.js";
|
||||
|
||||
describe("Belarusian localization", () => {
|
||||
const localeError = be().localeError;
|
||||
|
||||
describe("pluralization rules", () => {
|
||||
for (const { type, cases } of TEST_CASES) {
|
||||
describe(`${type} pluralization`, () => {
|
||||
for (const { count, expected } of cases) {
|
||||
it(`correctly pluralizes ${count} ${type}`, () => {
|
||||
const error = localeError({
|
||||
code: "too_small",
|
||||
minimum: count,
|
||||
type: "number",
|
||||
inclusive: true,
|
||||
path: [],
|
||||
origin: type,
|
||||
input: count - 1,
|
||||
});
|
||||
expect(error).toContain(expected);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
it("handles negative numbers correctly", () => {
|
||||
const error = localeError({
|
||||
code: "too_small",
|
||||
minimum: -2,
|
||||
type: "number",
|
||||
inclusive: true,
|
||||
path: [],
|
||||
origin: "array",
|
||||
input: -3,
|
||||
});
|
||||
expect(error).toContain("-2 элементы");
|
||||
});
|
||||
|
||||
it("handles zero correctly", () => {
|
||||
const error = localeError({
|
||||
code: "too_small",
|
||||
minimum: 0,
|
||||
type: "number",
|
||||
inclusive: true,
|
||||
path: [],
|
||||
origin: "array",
|
||||
input: -1,
|
||||
});
|
||||
expect(error).toContain("0 элементаў");
|
||||
});
|
||||
|
||||
it("handles bigint values correctly", () => {
|
||||
const error = localeError({
|
||||
code: "too_small",
|
||||
minimum: BigInt(21),
|
||||
type: "number",
|
||||
inclusive: true,
|
||||
path: [],
|
||||
origin: "array",
|
||||
input: BigInt(20),
|
||||
});
|
||||
expect(error).toContain("21 элемент");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const TEST_CASES = [
|
||||
{
|
||||
type: "array",
|
||||
cases: [
|
||||
{ count: 1, expected: "1 элемент" },
|
||||
{ count: 2, expected: "2 элементы" },
|
||||
{ count: 5, expected: "5 элементаў" },
|
||||
{ count: 11, expected: "11 элементаў" },
|
||||
{ count: 21, expected: "21 элемент" },
|
||||
{ count: 22, expected: "22 элементы" },
|
||||
{ count: 25, expected: "25 элементаў" },
|
||||
{ count: 101, expected: "101 элемент" },
|
||||
{ count: 111, expected: "111 элементаў" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "set",
|
||||
cases: [
|
||||
{ count: 1, expected: "1 элемент" },
|
||||
{ count: 2, expected: "2 элементы" },
|
||||
{ count: 5, expected: "5 элементаў" },
|
||||
{ count: 11, expected: "11 элементаў" },
|
||||
{ count: 21, expected: "21 элемент" },
|
||||
{ count: 22, expected: "22 элементы" },
|
||||
{ count: 25, expected: "25 элементаў" },
|
||||
{ count: 101, expected: "101 элемент" },
|
||||
{ count: 111, expected: "111 элементаў" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
cases: [
|
||||
{ count: 1, expected: "1 сімвал" },
|
||||
{ count: 2, expected: "2 сімвалы" },
|
||||
{ count: 5, expected: "5 сімвалаў" },
|
||||
{ count: 11, expected: "11 сімвалаў" },
|
||||
{ count: 21, expected: "21 сімвал" },
|
||||
{ count: 22, expected: "22 сімвалы" },
|
||||
{ count: 25, expected: "25 сімвалаў" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "file",
|
||||
cases: [
|
||||
{ count: 0, expected: "0 байтаў" },
|
||||
{ count: 1, expected: "1 байт" },
|
||||
{ count: 2, expected: "2 байты" },
|
||||
{ count: 5, expected: "5 байтаў" },
|
||||
{ count: 11, expected: "11 байтаў" },
|
||||
{ count: 21, expected: "21 байт" },
|
||||
{ count: 22, expected: "22 байты" },
|
||||
{ count: 25, expected: "25 байтаў" },
|
||||
{ count: 101, expected: "101 байт" },
|
||||
{ count: 110, expected: "110 байтаў" },
|
||||
],
|
||||
},
|
||||
] as const;
|
||||
22
node_modules/zod/src/v4/core/tests/locales/en.test.ts
generated
vendored
Normal file
22
node_modules/zod/src/v4/core/tests/locales/en.test.ts
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import { expect, test } from "vitest";
|
||||
import { parsedType } from "../../../locales/en.js";
|
||||
|
||||
test("parsedType", () => {
|
||||
expect(parsedType("string")).toBe("string");
|
||||
expect(parsedType(1)).toBe("number");
|
||||
expect(parsedType(true)).toBe("boolean");
|
||||
expect(parsedType(null)).toBe("null");
|
||||
expect(parsedType(undefined)).toBe("undefined");
|
||||
expect(parsedType([])).toBe("array");
|
||||
expect(parsedType({})).toBe("object");
|
||||
expect(parsedType(new Date())).toBe("Date");
|
||||
expect(parsedType(new Map())).toBe("Map");
|
||||
expect(parsedType(new Set())).toBe("Set");
|
||||
expect(parsedType(new Error())).toBe("Error");
|
||||
|
||||
const nullPrototype = Object.create(null);
|
||||
expect(parsedType(nullPrototype)).toBe("object");
|
||||
|
||||
const doubleNullPrototype = Object.create(Object.create(null));
|
||||
expect(parsedType(doubleNullPrototype)).toBe("object");
|
||||
});
|
||||
128
node_modules/zod/src/v4/core/tests/locales/ru.test.ts
generated
vendored
Normal file
128
node_modules/zod/src/v4/core/tests/locales/ru.test.ts
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import ru from "../../../locales/ru.js";
|
||||
|
||||
describe("Russian localization", () => {
|
||||
const localeError = ru().localeError;
|
||||
|
||||
describe("pluralization rules", () => {
|
||||
for (const { type, cases } of TEST_CASES) {
|
||||
describe(`${type} pluralization`, () => {
|
||||
for (const { count, expected } of cases) {
|
||||
it(`correctly pluralizes ${count} ${type}`, () => {
|
||||
const error = localeError({
|
||||
code: "too_small",
|
||||
minimum: count,
|
||||
type: "number",
|
||||
inclusive: true,
|
||||
path: [],
|
||||
origin: type,
|
||||
input: count - 1,
|
||||
});
|
||||
|
||||
expect(error).toContain(expected);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
it("handles negative numbers correctly", () => {
|
||||
const error = localeError({
|
||||
code: "too_small",
|
||||
minimum: -2,
|
||||
type: "number",
|
||||
inclusive: true,
|
||||
path: [],
|
||||
origin: "array",
|
||||
input: -3,
|
||||
});
|
||||
|
||||
expect(error).toContain("-2 элемента");
|
||||
});
|
||||
|
||||
it("handles zero correctly", () => {
|
||||
const error = localeError({
|
||||
code: "too_small",
|
||||
minimum: 0,
|
||||
type: "number",
|
||||
inclusive: true,
|
||||
path: [],
|
||||
origin: "array",
|
||||
input: -1,
|
||||
});
|
||||
|
||||
expect(error).toContain("0 элементов");
|
||||
});
|
||||
|
||||
it("handles bigint values correctly", () => {
|
||||
const error = localeError({
|
||||
code: "too_small",
|
||||
minimum: BigInt(21),
|
||||
type: "number",
|
||||
inclusive: true,
|
||||
path: [],
|
||||
origin: "array",
|
||||
input: BigInt(20),
|
||||
});
|
||||
|
||||
expect(error).toContain("21 элемент");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const TEST_CASES = [
|
||||
{
|
||||
type: "array",
|
||||
cases: [
|
||||
{ count: 1, expected: "1 элемент" },
|
||||
{ count: 2, expected: "2 элемента" },
|
||||
{ count: 5, expected: "5 элементов" },
|
||||
{ count: 11, expected: "11 элементов" },
|
||||
{ count: 21, expected: "21 элемент" },
|
||||
{ count: 22, expected: "22 элемента" },
|
||||
{ count: 25, expected: "25 элементов" },
|
||||
{ count: 101, expected: "101 элемент" },
|
||||
{ count: 111, expected: "111 элементов" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "set",
|
||||
cases: [
|
||||
{ count: 1, expected: "1 элемент" },
|
||||
{ count: 2, expected: "2 элемента" },
|
||||
{ count: 5, expected: "5 элементов" },
|
||||
{ count: 11, expected: "11 элементов" },
|
||||
{ count: 21, expected: "21 элемент" },
|
||||
{ count: 22, expected: "22 элемента" },
|
||||
{ count: 25, expected: "25 элементов" },
|
||||
{ count: 101, expected: "101 элемент" },
|
||||
{ count: 111, expected: "111 элементов" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
cases: [
|
||||
{ count: 1, expected: "1 символ" },
|
||||
{ count: 2, expected: "2 символа" },
|
||||
{ count: 5, expected: "5 символов" },
|
||||
{ count: 11, expected: "11 символов" },
|
||||
{ count: 21, expected: "21 символ" },
|
||||
{ count: 22, expected: "22 символа" },
|
||||
{ count: 25, expected: "25 символов" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "file",
|
||||
cases: [
|
||||
{ count: 0, expected: "0 байт" },
|
||||
{ count: 1, expected: "1 байт" },
|
||||
{ count: 2, expected: "2 байта" },
|
||||
{ count: 5, expected: "5 байт" },
|
||||
{ count: 11, expected: "11 байт" },
|
||||
{ count: 21, expected: "21 байт" },
|
||||
{ count: 22, expected: "22 байта" },
|
||||
{ count: 25, expected: "25 байт" },
|
||||
{ count: 101, expected: "101 байт" },
|
||||
{ count: 110, expected: "110 байт" },
|
||||
],
|
||||
},
|
||||
] as const;
|
||||
69
node_modules/zod/src/v4/core/tests/locales/tr.test.ts
generated
vendored
Normal file
69
node_modules/zod/src/v4/core/tests/locales/tr.test.ts
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
import { parsedType } from "../../../locales/tr.js";
|
||||
|
||||
test("parsedType", () => {
|
||||
expect(parsedType("string")).toBe("string");
|
||||
expect(parsedType(1)).toBe("number");
|
||||
expect(parsedType(true)).toBe("boolean");
|
||||
expect(parsedType(null)).toBe("null");
|
||||
expect(parsedType(undefined)).toBe("undefined");
|
||||
expect(parsedType([])).toBe("array");
|
||||
expect(parsedType({})).toBe("object");
|
||||
expect(parsedType(new Date())).toBe("Date");
|
||||
expect(parsedType(new Map())).toBe("Map");
|
||||
expect(parsedType(new Set())).toBe("Set");
|
||||
expect(parsedType(new Error())).toBe("Error");
|
||||
|
||||
const nullPrototype = Object.create(null);
|
||||
expect(parsedType(nullPrototype)).toBe("object");
|
||||
|
||||
const doubleNullPrototype = Object.create(Object.create(null));
|
||||
expect(parsedType(doubleNullPrototype)).toBe("object");
|
||||
|
||||
expect(parsedType(Number.NaN)).toBe("NaN");
|
||||
});
|
||||
|
||||
test("locales - tr", () => {
|
||||
z.config(z.locales.tr());
|
||||
|
||||
const invalidType = z.number().safeParse("a");
|
||||
expect(invalidType.error!.issues[0].code).toBe("invalid_type");
|
||||
expect(invalidType.error!.issues[0].message).toBe("Geçersiz değer: beklenen number, alınan string");
|
||||
|
||||
const invalidType2 = z.string().safeParse(1);
|
||||
expect(invalidType2.error!.issues[0].code).toBe("invalid_type");
|
||||
expect(invalidType2.error!.issues[0].message).toBe("Geçersiz değer: beklenen string, alınan number");
|
||||
|
||||
const invalidValue = z.enum(["a", "b"]).safeParse(1);
|
||||
expect(invalidValue.error!.issues[0].code).toBe("invalid_value");
|
||||
expect(invalidValue.error!.issues[0].message).toBe('Geçersiz seçenek: aşağıdakilerden biri olmalı: "a"|"b"');
|
||||
|
||||
const tooBig = z.number().max(10).safeParse(15);
|
||||
expect(tooBig.error!.issues[0].code).toBe("too_big");
|
||||
expect(tooBig.error!.issues[0].message).toBe("Çok büyük: beklenen number <=10");
|
||||
|
||||
const tooSmall = z.number().min(10).safeParse(5);
|
||||
expect(tooSmall.error!.issues[0].code).toBe("too_small");
|
||||
expect(tooSmall.error!.issues[0].message).toBe("Çok küçük: beklenen number >=10");
|
||||
|
||||
const invalidFormatRegex = z.string().regex(/abcd/).safeParse("invalid-string");
|
||||
expect(invalidFormatRegex.error!.issues[0].code).toBe("invalid_format");
|
||||
expect(invalidFormatRegex.error!.issues[0].message).toBe("Geçersiz metin: /abcd/ desenine uymalı");
|
||||
|
||||
const invalidFormatStartsWith = z.string().startsWith("abcd").safeParse("invalid-string");
|
||||
expect(invalidFormatStartsWith.error!.issues[0].code).toBe("invalid_format");
|
||||
expect(invalidFormatStartsWith.error!.issues[0].message).toBe('Geçersiz metin: "abcd" ile başlamalı');
|
||||
|
||||
const notMultipleOf = z.number().multipleOf(3).safeParse(10);
|
||||
expect(notMultipleOf.error!.issues[0].code).toBe("not_multiple_of");
|
||||
expect(notMultipleOf.error!.issues[0].message).toBe("Geçersiz sayı: 3 ile tam bölünebilmeli");
|
||||
|
||||
const unrecognizedKeys = z.object({ a: z.string(), b: z.number() }).strict().safeParse({ a: "a", b: 1, c: 2 });
|
||||
expect(unrecognizedKeys.error!.issues[0].code).toBe("unrecognized_keys");
|
||||
expect(unrecognizedKeys.error!.issues[0].message).toBe('Tanınmayan anahtar: "c"');
|
||||
|
||||
const invalidUnion = z.union([z.string(), z.number()]).safeParse(true);
|
||||
expect(invalidUnion.error!.issues[0].code).toBe("invalid_union");
|
||||
expect(invalidUnion.error!.issues[0].message).toBe("Geçersiz değer");
|
||||
});
|
||||
977
node_modules/zod/src/v4/core/to-json-schema.ts
generated
vendored
Normal file
977
node_modules/zod/src/v4/core/to-json-schema.ts
generated
vendored
Normal file
@@ -0,0 +1,977 @@
|
||||
import type * as checks from "./checks.js";
|
||||
import type * as JSONSchema from "./json-schema.js";
|
||||
import { $ZodRegistry, globalRegistry } from "./registries.js";
|
||||
import type * as schemas from "./schemas.js";
|
||||
import { getEnumValues } from "./util.js";
|
||||
|
||||
interface JSONSchemaGeneratorParams {
|
||||
/** A registry used to look up metadata for each schema. Any schema with an `id` property will be extracted as a $def.
|
||||
* @default globalRegistry */
|
||||
metadata?: $ZodRegistry<Record<string, any>>;
|
||||
/** The JSON Schema version to target.
|
||||
* - `"draft-2020-12"` — Default. JSON Schema Draft 2020-12
|
||||
* - `"draft-7"` — JSON Schema Draft 7 */
|
||||
target?: "draft-7" | "draft-2020-12";
|
||||
/** How to handle unrepresentable types.
|
||||
* - `"throw"` — Default. Unrepresentable types throw an error
|
||||
* - `"any"` — Unrepresentable types become `{}` */
|
||||
unrepresentable?: "throw" | "any";
|
||||
/** Arbitrary custom logic that can be used to modify the generated JSON Schema. */
|
||||
override?: (ctx: {
|
||||
zodSchema: schemas.$ZodTypes;
|
||||
jsonSchema: JSONSchema.BaseSchema;
|
||||
path: (string | number)[];
|
||||
}) => void;
|
||||
/** Whether to extract the `"input"` or `"output"` type. Relevant to transforms, Error converting schema to JSONz, defaults, coerced primitives, etc.
|
||||
* - `"output"` — Default. Convert the output schema.
|
||||
* - `"input"` — Convert the input schema. */
|
||||
io?: "input" | "output";
|
||||
}
|
||||
|
||||
interface ProcessParams {
|
||||
schemaPath: schemas.$ZodType[];
|
||||
path: (string | number)[];
|
||||
}
|
||||
|
||||
interface EmitParams {
|
||||
/** How to handle cycles.
|
||||
* - `"ref"` — Default. Cycles will be broken using $defs
|
||||
* - `"throw"` — Cycles will throw an error if encountered */
|
||||
cycles?: "ref" | "throw";
|
||||
/* How to handle reused schemas.
|
||||
* - `"inline"` — Default. Reused schemas will be inlined
|
||||
* - `"ref"` — Reused schemas will be extracted as $defs */
|
||||
reused?: "ref" | "inline";
|
||||
|
||||
external?:
|
||||
| {
|
||||
/** */
|
||||
registry: $ZodRegistry<{ id?: string | undefined }>;
|
||||
uri?: ((id: string) => string) | undefined;
|
||||
defs: Record<string, JSONSchema.BaseSchema>;
|
||||
}
|
||||
| undefined;
|
||||
}
|
||||
|
||||
interface Seen {
|
||||
/** JSON Schema result for this Zod schema */
|
||||
schema: JSONSchema.BaseSchema;
|
||||
/** A cached version of the schema that doesn't get overwritten during ref resolution */
|
||||
def?: JSONSchema.BaseSchema;
|
||||
defId?: string | undefined;
|
||||
/** Number of times this schema was encountered during traversal */
|
||||
count: number;
|
||||
/** Cycle path */
|
||||
cycle?: (string | number)[] | undefined;
|
||||
isParent?: boolean | undefined;
|
||||
ref?: schemas.$ZodType | undefined | null;
|
||||
/** JSON Schema property path for this schema */
|
||||
path?: (string | number)[] | undefined;
|
||||
}
|
||||
|
||||
export class JSONSchemaGenerator {
|
||||
metadataRegistry: $ZodRegistry<Record<string, any>>;
|
||||
target: "draft-7" | "draft-2020-12";
|
||||
unrepresentable: "throw" | "any";
|
||||
override: (ctx: {
|
||||
zodSchema: schemas.$ZodTypes;
|
||||
jsonSchema: JSONSchema.BaseSchema;
|
||||
path: (string | number)[];
|
||||
}) => void;
|
||||
io: "input" | "output";
|
||||
|
||||
counter = 0;
|
||||
seen: Map<schemas.$ZodType, Seen>;
|
||||
|
||||
constructor(params?: JSONSchemaGeneratorParams) {
|
||||
this.metadataRegistry = params?.metadata ?? globalRegistry;
|
||||
this.target = params?.target ?? "draft-2020-12";
|
||||
this.unrepresentable = params?.unrepresentable ?? "throw";
|
||||
this.override = params?.override ?? (() => {});
|
||||
this.io = params?.io ?? "output";
|
||||
|
||||
this.seen = new Map();
|
||||
}
|
||||
|
||||
process(schema: schemas.$ZodType, _params: ProcessParams = { path: [], schemaPath: [] }): JSONSchema.BaseSchema {
|
||||
const def = (schema as schemas.$ZodTypes)._zod.def;
|
||||
|
||||
const formatMap: Partial<Record<checks.$ZodStringFormats, string | undefined>> = {
|
||||
guid: "uuid",
|
||||
url: "uri",
|
||||
datetime: "date-time",
|
||||
json_string: "json-string",
|
||||
regex: "", // do not set
|
||||
};
|
||||
|
||||
// check for schema in seens
|
||||
const seen = this.seen.get(schema);
|
||||
|
||||
if (seen) {
|
||||
seen.count++;
|
||||
|
||||
// check if cycle
|
||||
const isCycle = _params.schemaPath.includes(schema);
|
||||
if (isCycle) {
|
||||
seen.cycle = _params.path;
|
||||
}
|
||||
|
||||
return seen.schema;
|
||||
}
|
||||
|
||||
// initialize
|
||||
const result: Seen = { schema: {}, count: 1, cycle: undefined, path: _params.path };
|
||||
this.seen.set(schema, result);
|
||||
|
||||
// custom method overrides default behavior
|
||||
const overrideSchema = schema._zod.toJSONSchema?.();
|
||||
if (overrideSchema) {
|
||||
result.schema = overrideSchema as any;
|
||||
} else {
|
||||
const params = {
|
||||
..._params,
|
||||
schemaPath: [..._params.schemaPath, schema],
|
||||
path: _params.path,
|
||||
};
|
||||
|
||||
const parent = schema._zod.parent;
|
||||
|
||||
if (parent) {
|
||||
// schema was cloned from another schema
|
||||
result.ref = parent;
|
||||
this.process(parent, params);
|
||||
this.seen.get(parent)!.isParent = true;
|
||||
} else {
|
||||
const _json = result.schema;
|
||||
switch (def.type) {
|
||||
case "string": {
|
||||
const json: JSONSchema.StringSchema = _json as any;
|
||||
json.type = "string";
|
||||
const { minimum, maximum, format, patterns, contentEncoding } = schema._zod
|
||||
.bag as schemas.$ZodStringInternals<unknown>["bag"];
|
||||
if (typeof minimum === "number") json.minLength = minimum;
|
||||
if (typeof maximum === "number") json.maxLength = maximum;
|
||||
// custom pattern overrides format
|
||||
if (format) {
|
||||
json.format = formatMap[format as checks.$ZodStringFormats] ?? format;
|
||||
if (json.format === "") delete json.format; // empty format is not valid
|
||||
}
|
||||
if (contentEncoding) json.contentEncoding = contentEncoding;
|
||||
if (patterns && patterns.size > 0) {
|
||||
const regexes = [...patterns];
|
||||
if (regexes.length === 1) json.pattern = regexes[0]!.source;
|
||||
else if (regexes.length > 1) {
|
||||
result.schema.allOf = [
|
||||
...regexes.map((regex) => ({
|
||||
...(this.target === "draft-7" ? ({ type: "string" } as const) : {}),
|
||||
pattern: regex.source,
|
||||
})),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "number": {
|
||||
const json: JSONSchema.NumberSchema | JSONSchema.IntegerSchema = _json as any;
|
||||
const { minimum, maximum, format, multipleOf, exclusiveMaximum, exclusiveMinimum } = schema._zod.bag;
|
||||
if (typeof format === "string" && format.includes("int")) json.type = "integer";
|
||||
else json.type = "number";
|
||||
|
||||
if (typeof exclusiveMinimum === "number") json.exclusiveMinimum = exclusiveMinimum;
|
||||
if (typeof minimum === "number") {
|
||||
json.minimum = minimum;
|
||||
if (typeof exclusiveMinimum === "number") {
|
||||
if (exclusiveMinimum >= minimum) delete json.minimum;
|
||||
else delete json.exclusiveMinimum;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof exclusiveMaximum === "number") json.exclusiveMaximum = exclusiveMaximum;
|
||||
if (typeof maximum === "number") {
|
||||
json.maximum = maximum;
|
||||
if (typeof exclusiveMaximum === "number") {
|
||||
if (exclusiveMaximum <= maximum) delete json.maximum;
|
||||
else delete json.exclusiveMaximum;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof multipleOf === "number") json.multipleOf = multipleOf;
|
||||
|
||||
break;
|
||||
}
|
||||
case "boolean": {
|
||||
const json = _json as JSONSchema.BooleanSchema;
|
||||
json.type = "boolean";
|
||||
break;
|
||||
}
|
||||
case "bigint": {
|
||||
if (this.unrepresentable === "throw") {
|
||||
throw new Error("BigInt cannot be represented in JSON Schema");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "symbol": {
|
||||
if (this.unrepresentable === "throw") {
|
||||
throw new Error("Symbols cannot be represented in JSON Schema");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "null": {
|
||||
_json.type = "null";
|
||||
break;
|
||||
}
|
||||
case "any": {
|
||||
break;
|
||||
}
|
||||
case "unknown": {
|
||||
break;
|
||||
}
|
||||
case "undefined": {
|
||||
if (this.unrepresentable === "throw") {
|
||||
throw new Error("Undefined cannot be represented in JSON Schema");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "void": {
|
||||
if (this.unrepresentable === "throw") {
|
||||
throw new Error("Void cannot be represented in JSON Schema");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "never": {
|
||||
_json.not = {};
|
||||
break;
|
||||
}
|
||||
case "date": {
|
||||
if (this.unrepresentable === "throw") {
|
||||
throw new Error("Date cannot be represented in JSON Schema");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "array": {
|
||||
const json: JSONSchema.ArraySchema = _json as any;
|
||||
const { minimum, maximum } = schema._zod.bag;
|
||||
if (typeof minimum === "number") json.minItems = minimum;
|
||||
if (typeof maximum === "number") json.maxItems = maximum;
|
||||
|
||||
json.type = "array";
|
||||
json.items = this.process(def.element, { ...params, path: [...params.path, "items"] });
|
||||
break;
|
||||
}
|
||||
case "object": {
|
||||
const json: JSONSchema.ObjectSchema = _json as any;
|
||||
json.type = "object";
|
||||
json.properties = {};
|
||||
const shape = def.shape; // params.shapeCache.get(schema)!;
|
||||
|
||||
for (const key in shape) {
|
||||
json.properties[key] = this.process(shape[key]!, {
|
||||
...params,
|
||||
path: [...params.path, "properties", key],
|
||||
});
|
||||
}
|
||||
|
||||
// required keys
|
||||
const allKeys = new Set(Object.keys(shape));
|
||||
// const optionalKeys = new Set(def.optional);
|
||||
const requiredKeys = new Set(
|
||||
[...allKeys].filter((key) => {
|
||||
const v = def.shape[key]!._zod;
|
||||
if (this.io === "input") {
|
||||
return v.optin === undefined;
|
||||
} else {
|
||||
return v.optout === undefined;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
if (requiredKeys.size > 0) {
|
||||
json.required = Array.from(requiredKeys);
|
||||
}
|
||||
|
||||
// catchall
|
||||
if (def.catchall?._zod.def.type === "never") {
|
||||
// strict
|
||||
json.additionalProperties = false;
|
||||
} else if (!def.catchall) {
|
||||
// regular
|
||||
if (this.io === "output") json.additionalProperties = false;
|
||||
} else if (def.catchall) {
|
||||
json.additionalProperties = this.process(def.catchall, {
|
||||
...params,
|
||||
path: [...params.path, "additionalProperties"],
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "union": {
|
||||
const json: JSONSchema.BaseSchema = _json as any;
|
||||
json.anyOf = def.options.map((x, i) =>
|
||||
this.process(x, {
|
||||
...params,
|
||||
path: [...params.path, "anyOf", i],
|
||||
})
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "intersection": {
|
||||
const json: JSONSchema.BaseSchema = _json as any;
|
||||
const a = this.process(def.left, {
|
||||
...params,
|
||||
path: [...params.path, "allOf", 0],
|
||||
});
|
||||
const b = this.process(def.right, {
|
||||
...params,
|
||||
path: [...params.path, "allOf", 1],
|
||||
});
|
||||
|
||||
const isSimpleIntersection = (val: any) => "allOf" in val && Object.keys(val).length === 1;
|
||||
const allOf = [
|
||||
...(isSimpleIntersection(a) ? (a.allOf as any[]) : [a]),
|
||||
...(isSimpleIntersection(b) ? (b.allOf as any[]) : [b]),
|
||||
];
|
||||
json.allOf = allOf;
|
||||
break;
|
||||
}
|
||||
case "tuple": {
|
||||
const json: JSONSchema.ArraySchema = _json as any;
|
||||
json.type = "array";
|
||||
const prefixItems = def.items.map((x, i) =>
|
||||
this.process(x, { ...params, path: [...params.path, "prefixItems", i] })
|
||||
);
|
||||
if (this.target === "draft-2020-12") {
|
||||
json.prefixItems = prefixItems;
|
||||
} else {
|
||||
json.items = prefixItems;
|
||||
}
|
||||
|
||||
if (def.rest) {
|
||||
const rest = this.process(def.rest, {
|
||||
...params,
|
||||
path: [...params.path, "items"],
|
||||
});
|
||||
if (this.target === "draft-2020-12") {
|
||||
json.items = rest;
|
||||
} else {
|
||||
json.additionalItems = rest;
|
||||
}
|
||||
}
|
||||
|
||||
// additionalItems
|
||||
if (def.rest) {
|
||||
json.items = this.process(def.rest, {
|
||||
...params,
|
||||
path: [...params.path, "items"],
|
||||
});
|
||||
}
|
||||
|
||||
// length
|
||||
const { minimum, maximum } = schema._zod.bag as {
|
||||
minimum?: number;
|
||||
maximum?: number;
|
||||
};
|
||||
if (typeof minimum === "number") json.minItems = minimum;
|
||||
if (typeof maximum === "number") json.maxItems = maximum;
|
||||
break;
|
||||
}
|
||||
case "record": {
|
||||
const json: JSONSchema.ObjectSchema = _json as any;
|
||||
json.type = "object";
|
||||
json.propertyNames = this.process(def.keyType, { ...params, path: [...params.path, "propertyNames"] });
|
||||
json.additionalProperties = this.process(def.valueType, {
|
||||
...params,
|
||||
path: [...params.path, "additionalProperties"],
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "map": {
|
||||
if (this.unrepresentable === "throw") {
|
||||
throw new Error("Map cannot be represented in JSON Schema");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "set": {
|
||||
if (this.unrepresentable === "throw") {
|
||||
throw new Error("Set cannot be represented in JSON Schema");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "enum": {
|
||||
const json: JSONSchema.BaseSchema = _json as any;
|
||||
const values = getEnumValues(def.entries);
|
||||
// Number enums can have both string and number values
|
||||
if (values.every((v) => typeof v === "number")) json.type = "number";
|
||||
if (values.every((v) => typeof v === "string")) json.type = "string";
|
||||
json.enum = values;
|
||||
break;
|
||||
}
|
||||
case "literal": {
|
||||
const json: JSONSchema.BaseSchema = _json as any;
|
||||
const vals: (string | number | boolean | null)[] = [];
|
||||
for (const val of def.values) {
|
||||
if (val === undefined) {
|
||||
if (this.unrepresentable === "throw") {
|
||||
throw new Error("Literal `undefined` cannot be represented in JSON Schema");
|
||||
} else {
|
||||
// do not add to vals
|
||||
}
|
||||
} else if (typeof val === "bigint") {
|
||||
if (this.unrepresentable === "throw") {
|
||||
throw new Error("BigInt literals cannot be represented in JSON Schema");
|
||||
} else {
|
||||
vals.push(Number(val));
|
||||
}
|
||||
} else {
|
||||
vals.push(val);
|
||||
}
|
||||
}
|
||||
if (vals.length === 0) {
|
||||
// do nothing (an undefined literal was stripped)
|
||||
} else if (vals.length === 1) {
|
||||
const val = vals[0]!;
|
||||
json.type = val === null ? ("null" as const) : (typeof val as any);
|
||||
json.const = val;
|
||||
} else {
|
||||
if (vals.every((v) => typeof v === "number")) json.type = "number";
|
||||
if (vals.every((v) => typeof v === "string")) json.type = "string";
|
||||
if (vals.every((v) => typeof v === "boolean")) json.type = "string";
|
||||
if (vals.every((v) => v === null)) json.type = "null";
|
||||
json.enum = vals;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "file": {
|
||||
const json: JSONSchema.StringSchema = _json as any;
|
||||
const file: JSONSchema.StringSchema = {
|
||||
type: "string",
|
||||
format: "binary",
|
||||
contentEncoding: "binary",
|
||||
};
|
||||
|
||||
const { minimum, maximum, mime } = schema._zod.bag as schemas.$ZodFileInternals["bag"];
|
||||
if (minimum !== undefined) file.minLength = minimum;
|
||||
if (maximum !== undefined) file.maxLength = maximum;
|
||||
if (mime) {
|
||||
if (mime.length === 1) {
|
||||
file.contentMediaType = mime[0]!;
|
||||
Object.assign(json, file);
|
||||
} else {
|
||||
json.anyOf = mime.map((m) => {
|
||||
const mFile: JSONSchema.StringSchema = { ...file, contentMediaType: m };
|
||||
return mFile;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
Object.assign(json, file);
|
||||
}
|
||||
|
||||
// if (this.unrepresentable === "throw") {
|
||||
// throw new Error("File cannot be represented in JSON Schema");
|
||||
// }
|
||||
break;
|
||||
}
|
||||
case "transform": {
|
||||
if (this.unrepresentable === "throw") {
|
||||
throw new Error("Transforms cannot be represented in JSON Schema");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "nullable": {
|
||||
const inner = this.process(def.innerType, params);
|
||||
_json.anyOf = [inner, { type: "null" }];
|
||||
break;
|
||||
}
|
||||
case "nonoptional": {
|
||||
this.process(def.innerType, params);
|
||||
result.ref = def.innerType;
|
||||
break;
|
||||
}
|
||||
case "success": {
|
||||
const json = _json as JSONSchema.BooleanSchema;
|
||||
json.type = "boolean";
|
||||
break;
|
||||
}
|
||||
case "default": {
|
||||
this.process(def.innerType, params);
|
||||
result.ref = def.innerType;
|
||||
_json.default = JSON.parse(JSON.stringify(def.defaultValue));
|
||||
break;
|
||||
}
|
||||
case "prefault": {
|
||||
this.process(def.innerType, params);
|
||||
result.ref = def.innerType;
|
||||
if (this.io === "input") _json._prefault = JSON.parse(JSON.stringify(def.defaultValue));
|
||||
|
||||
break;
|
||||
}
|
||||
case "catch": {
|
||||
// use conditionals
|
||||
this.process(def.innerType, params);
|
||||
result.ref = def.innerType;
|
||||
let catchValue: any;
|
||||
try {
|
||||
catchValue = def.catchValue(undefined as any);
|
||||
} catch {
|
||||
throw new Error("Dynamic catch values are not supported in JSON Schema");
|
||||
}
|
||||
_json.default = catchValue;
|
||||
break;
|
||||
}
|
||||
case "nan": {
|
||||
if (this.unrepresentable === "throw") {
|
||||
throw new Error("NaN cannot be represented in JSON Schema");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "template_literal": {
|
||||
const json = _json as JSONSchema.StringSchema;
|
||||
const pattern = schema._zod.pattern;
|
||||
if (!pattern) throw new Error("Pattern not found in template literal");
|
||||
json.type = "string";
|
||||
json.pattern = pattern.source;
|
||||
break;
|
||||
}
|
||||
case "pipe": {
|
||||
const innerType = this.io === "input" ? (def.in._zod.def.type === "transform" ? def.out : def.in) : def.out;
|
||||
this.process(innerType, params);
|
||||
result.ref = innerType;
|
||||
break;
|
||||
}
|
||||
case "readonly": {
|
||||
this.process(def.innerType, params);
|
||||
result.ref = def.innerType;
|
||||
_json.readOnly = true;
|
||||
break;
|
||||
}
|
||||
// passthrough types
|
||||
case "promise": {
|
||||
this.process(def.innerType, params);
|
||||
result.ref = def.innerType;
|
||||
break;
|
||||
}
|
||||
case "optional": {
|
||||
this.process(def.innerType, params);
|
||||
result.ref = def.innerType;
|
||||
break;
|
||||
}
|
||||
case "lazy": {
|
||||
const innerType = (schema as schemas.$ZodLazy)._zod.innerType;
|
||||
this.process(innerType, params);
|
||||
result.ref = innerType;
|
||||
break;
|
||||
}
|
||||
case "custom": {
|
||||
if (this.unrepresentable === "throw") {
|
||||
throw new Error("Custom types cannot be represented in JSON Schema");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
def satisfies never;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// metadata
|
||||
const meta = this.metadataRegistry.get(schema);
|
||||
if (meta) Object.assign(result.schema, meta);
|
||||
|
||||
if (this.io === "input" && isTransforming(schema)) {
|
||||
// examples/defaults only apply to output type of pipe
|
||||
delete result.schema.examples;
|
||||
delete result.schema.default;
|
||||
}
|
||||
|
||||
// set prefault as default
|
||||
if (this.io === "input" && result.schema._prefault) result.schema.default ??= result.schema._prefault;
|
||||
delete result.schema._prefault;
|
||||
|
||||
// pulling fresh from this.seen in case it was overwritten
|
||||
const _result = this.seen.get(schema)!;
|
||||
|
||||
return _result.schema;
|
||||
}
|
||||
|
||||
emit(schema: schemas.$ZodType, _params?: EmitParams): JSONSchema.BaseSchema {
|
||||
const params = {
|
||||
cycles: _params?.cycles ?? "ref",
|
||||
reused: _params?.reused ?? "inline",
|
||||
// unrepresentable: _params?.unrepresentable ?? "throw",
|
||||
// uri: _params?.uri ?? ((id) => `${id}`),
|
||||
external: _params?.external ?? undefined,
|
||||
} satisfies EmitParams;
|
||||
|
||||
// iterate over seen map;
|
||||
const root = this.seen.get(schema);
|
||||
|
||||
if (!root) throw new Error("Unprocessed schema. This is a bug in Zod.");
|
||||
|
||||
// initialize result with root schema fields
|
||||
// Object.assign(result, seen.cached);
|
||||
|
||||
// returns a ref to the schema
|
||||
// defId will be empty if the ref points to an external schema (or #)
|
||||
const makeURI = (entry: [schemas.$ZodType<unknown, unknown>, Seen]): { ref: string; defId?: string } => {
|
||||
// comparing the seen objects because sometimes
|
||||
// multiple schemas map to the same seen object.
|
||||
// e.g. lazy
|
||||
|
||||
// external is configured
|
||||
const defsSegment = this.target === "draft-2020-12" ? "$defs" : "definitions";
|
||||
if (params.external) {
|
||||
const externalId = params.external.registry.get(entry[0])?.id; // ?? "__shared";// `__schema${this.counter++}`;
|
||||
|
||||
// check if schema is in the external registry
|
||||
const uriGenerator = params.external.uri ?? ((id) => id);
|
||||
if (externalId) {
|
||||
return { ref: uriGenerator(externalId) };
|
||||
}
|
||||
|
||||
// otherwise, add to __shared
|
||||
const id: string = entry[1].defId ?? (entry[1].schema.id as string) ?? `schema${this.counter++}`;
|
||||
entry[1].defId = id; // set defId so it will be reused if needed
|
||||
return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id}` };
|
||||
}
|
||||
|
||||
if (entry[1] === root) {
|
||||
return { ref: "#" };
|
||||
}
|
||||
|
||||
// self-contained schema
|
||||
const uriPrefix = `#`;
|
||||
const defUriPrefix = `${uriPrefix}/${defsSegment}/`;
|
||||
const defId = entry[1].schema.id ?? `__schema${this.counter++}`;
|
||||
return { defId, ref: defUriPrefix + defId };
|
||||
};
|
||||
|
||||
// stored cached version in `def` property
|
||||
// remove all properties, set $ref
|
||||
const extractToDef = (entry: [schemas.$ZodType<unknown, unknown>, Seen]): void => {
|
||||
// if the schema is already a reference, do not extract it
|
||||
if (entry[1].schema.$ref) {
|
||||
return;
|
||||
}
|
||||
const seen = entry[1];
|
||||
const { ref, defId } = makeURI(entry);
|
||||
|
||||
seen.def = { ...seen.schema };
|
||||
// defId won't be set if the schema is a reference to an external schema
|
||||
if (defId) seen.defId = defId;
|
||||
// wipe away all properties except $ref
|
||||
const schema = seen.schema;
|
||||
for (const key in schema) {
|
||||
delete schema[key];
|
||||
}
|
||||
schema.$ref = ref;
|
||||
};
|
||||
|
||||
// throw on cycles
|
||||
|
||||
// break cycles
|
||||
if (params.cycles === "throw") {
|
||||
for (const entry of this.seen.entries()) {
|
||||
const seen = entry[1];
|
||||
if (seen.cycle) {
|
||||
throw new Error(
|
||||
"Cycle detected: " +
|
||||
`#/${seen.cycle?.join("/")}/<root>` +
|
||||
'\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// extract schemas into $defs
|
||||
for (const entry of this.seen.entries()) {
|
||||
const seen = entry[1];
|
||||
|
||||
// convert root schema to # $ref
|
||||
if (schema === entry[0]) {
|
||||
extractToDef(entry); // this has special handling for the root schema
|
||||
continue;
|
||||
}
|
||||
|
||||
// extract schemas that are in the external registry
|
||||
if (params.external) {
|
||||
const ext = params.external.registry.get(entry[0])?.id;
|
||||
if (schema !== entry[0] && ext) {
|
||||
extractToDef(entry);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// extract schemas with `id` meta
|
||||
const id = this.metadataRegistry.get(entry[0])?.id;
|
||||
if (id) {
|
||||
extractToDef(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
// break cycles
|
||||
if (seen.cycle) {
|
||||
// any
|
||||
extractToDef(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
// extract reused schemas
|
||||
if (seen.count > 1) {
|
||||
if (params.reused === "ref") {
|
||||
extractToDef(entry);
|
||||
// biome-ignore lint:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// flatten _refs
|
||||
const flattenRef = (zodSchema: schemas.$ZodType, params: Pick<ToJSONSchemaParams, "target">) => {
|
||||
const seen = this.seen.get(zodSchema)!;
|
||||
const schema = seen.def ?? seen.schema;
|
||||
|
||||
const _cached = { ...schema };
|
||||
|
||||
// already seen
|
||||
if (seen.ref === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// flatten ref if defined
|
||||
const ref = seen.ref;
|
||||
seen.ref = null; // prevent recursion
|
||||
if (ref) {
|
||||
flattenRef(ref, params);
|
||||
|
||||
// merge referenced schema into current
|
||||
const refSchema = this.seen.get(ref)!.schema;
|
||||
if (refSchema.$ref && params.target === "draft-7") {
|
||||
schema.allOf = schema.allOf ?? [];
|
||||
schema.allOf.push(refSchema);
|
||||
} else {
|
||||
Object.assign(schema, refSchema);
|
||||
Object.assign(schema, _cached); // prevent overwriting any fields in the original schema
|
||||
}
|
||||
}
|
||||
|
||||
// execute overrides
|
||||
if (!seen.isParent)
|
||||
this.override({
|
||||
zodSchema: zodSchema as schemas.$ZodTypes,
|
||||
jsonSchema: schema,
|
||||
path: seen.path ?? [],
|
||||
});
|
||||
};
|
||||
|
||||
for (const entry of [...this.seen.entries()].reverse()) {
|
||||
flattenRef(entry[0], { target: this.target });
|
||||
}
|
||||
|
||||
const result: JSONSchema.BaseSchema = {};
|
||||
if (this.target === "draft-2020-12") {
|
||||
result.$schema = "https://json-schema.org/draft/2020-12/schema";
|
||||
} else if (this.target === "draft-7") {
|
||||
result.$schema = "http://json-schema.org/draft-07/schema#";
|
||||
} else {
|
||||
console.warn(`Invalid target: ${this.target}`);
|
||||
}
|
||||
|
||||
if (params.external?.uri) {
|
||||
const id = params.external.registry.get(schema)?.id;
|
||||
if (!id) throw new Error("Schema is missing an `id` property");
|
||||
result.$id = params.external.uri(id);
|
||||
}
|
||||
|
||||
Object.assign(result, root.def);
|
||||
|
||||
// build defs object
|
||||
const defs: JSONSchema.BaseSchema["$defs"] = params.external?.defs ?? {};
|
||||
for (const entry of this.seen.entries()) {
|
||||
const seen = entry[1];
|
||||
if (seen.def && seen.defId) {
|
||||
defs[seen.defId] = seen.def;
|
||||
}
|
||||
}
|
||||
|
||||
// set definitions in result
|
||||
if (params.external) {
|
||||
} else {
|
||||
if (Object.keys(defs).length > 0) {
|
||||
if (this.target === "draft-2020-12") {
|
||||
result.$defs = defs;
|
||||
} else {
|
||||
result.definitions = defs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// this "finalizes" this schema and ensures all cycles are removed
|
||||
// each call to .emit() is functionally independent
|
||||
// though the seen map is shared
|
||||
return JSON.parse(JSON.stringify(result));
|
||||
} catch (_err) {
|
||||
throw new Error("Error converting schema to JSON.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ToJSONSchemaParams extends Omit<JSONSchemaGeneratorParams & EmitParams, "external"> {}
|
||||
interface RegistryToJSONSchemaParams extends Omit<JSONSchemaGeneratorParams & EmitParams, "external"> {
|
||||
uri?: (id: string) => string;
|
||||
}
|
||||
|
||||
export function toJSONSchema(schema: schemas.$ZodType, _params?: ToJSONSchemaParams): JSONSchema.BaseSchema;
|
||||
export function toJSONSchema(
|
||||
registry: $ZodRegistry<{ id?: string | undefined }>,
|
||||
_params?: RegistryToJSONSchemaParams
|
||||
): { schemas: Record<string, JSONSchema.BaseSchema> };
|
||||
export function toJSONSchema(
|
||||
input: schemas.$ZodType | $ZodRegistry<{ id?: string | undefined }>,
|
||||
_params?: ToJSONSchemaParams
|
||||
): any {
|
||||
if (input instanceof $ZodRegistry) {
|
||||
const gen = new JSONSchemaGenerator(_params);
|
||||
const defs: any = {};
|
||||
for (const entry of input._idmap.entries()) {
|
||||
const [_, schema] = entry;
|
||||
gen.process(schema);
|
||||
}
|
||||
|
||||
const schemas: Record<string, JSONSchema.BaseSchema> = {};
|
||||
const external = {
|
||||
registry: input,
|
||||
uri: (_params as RegistryToJSONSchemaParams)?.uri,
|
||||
defs,
|
||||
};
|
||||
for (const entry of input._idmap.entries()) {
|
||||
const [key, schema] = entry;
|
||||
schemas[key] = gen.emit(schema, {
|
||||
..._params,
|
||||
external,
|
||||
});
|
||||
}
|
||||
|
||||
if (Object.keys(defs).length > 0) {
|
||||
const defsSegment = gen.target === "draft-2020-12" ? "$defs" : "definitions";
|
||||
schemas.__shared = {
|
||||
[defsSegment]: defs,
|
||||
};
|
||||
}
|
||||
|
||||
return { schemas };
|
||||
}
|
||||
|
||||
const gen = new JSONSchemaGenerator(_params);
|
||||
gen.process(input);
|
||||
|
||||
return gen.emit(input, _params);
|
||||
}
|
||||
|
||||
function isTransforming(
|
||||
_schema: schemas.$ZodType,
|
||||
_ctx?: {
|
||||
seen: Set<schemas.$ZodType>;
|
||||
}
|
||||
): boolean {
|
||||
const ctx = _ctx ?? { seen: new Set() };
|
||||
|
||||
if (ctx.seen.has(_schema)) return false;
|
||||
ctx.seen.add(_schema);
|
||||
|
||||
const schema = _schema as schemas.$ZodTypes;
|
||||
const def = schema._zod.def;
|
||||
switch (def.type) {
|
||||
case "string":
|
||||
case "number":
|
||||
case "bigint":
|
||||
case "boolean":
|
||||
case "date":
|
||||
case "symbol":
|
||||
case "undefined":
|
||||
case "null":
|
||||
case "any":
|
||||
case "unknown":
|
||||
case "never":
|
||||
case "void":
|
||||
case "literal":
|
||||
case "enum":
|
||||
case "nan":
|
||||
case "file":
|
||||
case "template_literal":
|
||||
return false;
|
||||
case "array": {
|
||||
return isTransforming(def.element, ctx);
|
||||
}
|
||||
case "object": {
|
||||
for (const key in def.shape) {
|
||||
if (isTransforming(def.shape[key]!, ctx)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case "union": {
|
||||
for (const option of def.options) {
|
||||
if (isTransforming(option, ctx)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case "intersection": {
|
||||
return isTransforming(def.left, ctx) || isTransforming(def.right, ctx);
|
||||
}
|
||||
case "tuple": {
|
||||
for (const item of def.items) {
|
||||
if (isTransforming(item, ctx)) return true;
|
||||
}
|
||||
if (def.rest && isTransforming(def.rest, ctx)) return true;
|
||||
return false;
|
||||
}
|
||||
case "record": {
|
||||
return isTransforming(def.keyType, ctx) || isTransforming(def.valueType, ctx);
|
||||
}
|
||||
case "map": {
|
||||
return isTransforming(def.keyType, ctx) || isTransforming(def.valueType, ctx);
|
||||
}
|
||||
case "set": {
|
||||
return isTransforming(def.valueType, ctx);
|
||||
}
|
||||
|
||||
// inner types
|
||||
case "promise":
|
||||
case "optional":
|
||||
case "nonoptional":
|
||||
case "nullable":
|
||||
case "readonly":
|
||||
return isTransforming(def.innerType, ctx);
|
||||
case "lazy":
|
||||
return isTransforming(def.getter(), ctx);
|
||||
case "default": {
|
||||
return isTransforming(def.innerType, ctx);
|
||||
}
|
||||
case "prefault": {
|
||||
return isTransforming(def.innerType, ctx);
|
||||
}
|
||||
case "custom": {
|
||||
return false;
|
||||
}
|
||||
case "transform": {
|
||||
return true;
|
||||
}
|
||||
case "pipe": {
|
||||
return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);
|
||||
}
|
||||
case "success": {
|
||||
return false;
|
||||
}
|
||||
case "catch": {
|
||||
return false;
|
||||
}
|
||||
|
||||
default:
|
||||
def satisfies never;
|
||||
}
|
||||
throw new Error(`Unknown schema type: ${(def as any).type}`);
|
||||
}
|
||||
775
node_modules/zod/src/v4/core/util.ts
generated
vendored
Normal file
775
node_modules/zod/src/v4/core/util.ts
generated
vendored
Normal file
@@ -0,0 +1,775 @@
|
||||
import type * as checks from "./checks.js";
|
||||
import type { $ZodConfig } from "./core.js";
|
||||
import type * as errors from "./errors.js";
|
||||
import type * as schemas from "./schemas.js";
|
||||
|
||||
// json
|
||||
export type JSONType = string | number | boolean | null | JSONType[] | { [key: string]: JSONType };
|
||||
export type JWTAlgorithm =
|
||||
| "HS256"
|
||||
| "HS384"
|
||||
| "HS512"
|
||||
| "RS256"
|
||||
| "RS384"
|
||||
| "RS512"
|
||||
| "ES256"
|
||||
| "ES384"
|
||||
| "ES512"
|
||||
| "PS256"
|
||||
| "PS384"
|
||||
| "PS512"
|
||||
| "EdDSA"
|
||||
| (string & {});
|
||||
export type IPVersion = "v4" | "v6";
|
||||
export type MimeTypes =
|
||||
| "application/json"
|
||||
| "application/xml"
|
||||
| "application/x-www-form-urlencoded"
|
||||
| "application/javascript"
|
||||
| "application/pdf"
|
||||
| "application/zip"
|
||||
| "application/vnd.ms-excel"
|
||||
| "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
| "application/msword"
|
||||
| "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
||||
| "application/vnd.ms-powerpoint"
|
||||
| "application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
||||
| "application/octet-stream"
|
||||
| "application/graphql"
|
||||
| "text/html"
|
||||
| "text/plain"
|
||||
| "text/css"
|
||||
| "text/javascript"
|
||||
| "text/csv"
|
||||
| "image/png"
|
||||
| "image/jpeg"
|
||||
| "image/gif"
|
||||
| "image/svg+xml"
|
||||
| "image/webp"
|
||||
| "audio/mpeg"
|
||||
| "audio/ogg"
|
||||
| "audio/wav"
|
||||
| "audio/webm"
|
||||
| "video/mp4"
|
||||
| "video/webm"
|
||||
| "video/ogg"
|
||||
| "font/woff"
|
||||
| "font/woff2"
|
||||
| "font/ttf"
|
||||
| "font/otf"
|
||||
| "multipart/form-data"
|
||||
| (string & {});
|
||||
export type ParsedTypes =
|
||||
| "string"
|
||||
| "number"
|
||||
| "bigint"
|
||||
| "boolean"
|
||||
| "symbol"
|
||||
| "undefined"
|
||||
| "object"
|
||||
| "function"
|
||||
| "file"
|
||||
| "date"
|
||||
| "array"
|
||||
| "map"
|
||||
| "set"
|
||||
| "nan"
|
||||
| "null"
|
||||
| "promise";
|
||||
|
||||
// utils
|
||||
export type AssertEqual<T, U> = (<V>() => V extends T ? 1 : 2) extends <V>() => V extends U ? 1 : 2 ? true : false;
|
||||
export type AssertNotEqual<T, U> = (<V>() => V extends T ? 1 : 2) extends <V>() => V extends U ? 1 : 2 ? false : true;
|
||||
export type AssertExtends<T, U> = T extends U ? T : never;
|
||||
export type IsAny<T> = 0 extends 1 & T ? true : false;
|
||||
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
||||
export type OmitKeys<T, K extends string> = Pick<T, Exclude<keyof T, K>>;
|
||||
export type MakePartial<T, K extends keyof T> = Omit<T, K> & InexactPartial<Pick<T, K>>;
|
||||
export type MakeRequired<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
|
||||
|
||||
export type Exactly<T, X> = T & Record<Exclude<keyof X, keyof T>, never>;
|
||||
export type NoUndefined<T> = T extends undefined ? never : T;
|
||||
export type Whatever = {} | undefined | null;
|
||||
export type LoosePartial<T extends object> = InexactPartial<T> & {
|
||||
[k: string]: unknown;
|
||||
};
|
||||
export type Mask<Keys extends PropertyKey> = { [K in Keys]?: true };
|
||||
export type Writeable<T> = { -readonly [P in keyof T]: T[P] } & {};
|
||||
export type InexactPartial<T> = {
|
||||
[P in keyof T]?: T[P] | undefined;
|
||||
};
|
||||
export type EmptyObject = Record<string, never>;
|
||||
export type BuiltIn =
|
||||
| (((...args: any[]) => any) | (new (...args: any[]) => any))
|
||||
| { readonly [Symbol.toStringTag]: string }
|
||||
| Date
|
||||
| Error
|
||||
| Generator
|
||||
| Promise<unknown>
|
||||
| RegExp;
|
||||
export type MakeReadonly<T> = T extends Map<infer K, infer V>
|
||||
? ReadonlyMap<K, V>
|
||||
: T extends Set<infer V>
|
||||
? ReadonlySet<V>
|
||||
: T extends [infer Head, ...infer Tail]
|
||||
? readonly [Head, ...Tail]
|
||||
: T extends Array<infer V>
|
||||
? ReadonlyArray<V>
|
||||
: T extends BuiltIn
|
||||
? T
|
||||
: Readonly<T>;
|
||||
export type SomeObject = Record<PropertyKey, any>;
|
||||
export type Identity<T> = T;
|
||||
export type Flatten<T> = Identity<{ [k in keyof T]: T[k] }>;
|
||||
export type Mapped<T> = { [k in keyof T]: T[k] };
|
||||
export type Prettify<T> = {
|
||||
[K in keyof T]: T[K];
|
||||
} & {};
|
||||
|
||||
export type NoNeverKeys<T> = {
|
||||
[k in keyof T]: [T[k]] extends [never] ? never : k;
|
||||
}[keyof T];
|
||||
export type NoNever<T> = Identity<{
|
||||
[k in NoNeverKeys<T>]: k extends keyof T ? T[k] : never;
|
||||
}>;
|
||||
export type Extend<A extends SomeObject, B extends SomeObject> = Flatten<
|
||||
// fast path when there is no keys overlap
|
||||
keyof A & keyof B extends never
|
||||
? A & B
|
||||
: {
|
||||
[K in keyof A as K extends keyof B ? never : K]: A[K];
|
||||
} & {
|
||||
[K in keyof B]: B[K];
|
||||
}
|
||||
>;
|
||||
|
||||
export type TupleItems = ReadonlyArray<schemas.SomeType>;
|
||||
export type AnyFunc = (...args: any[]) => any;
|
||||
export type IsProp<T, K extends keyof T> = T[K] extends AnyFunc ? never : K;
|
||||
export type MaybeAsync<T> = T | Promise<T>;
|
||||
export type KeyOf<T> = keyof OmitIndexSignature<T>;
|
||||
export type OmitIndexSignature<T> = {
|
||||
[K in keyof T as string extends K ? never : K extends string ? K : never]: T[K];
|
||||
};
|
||||
export type ExtractIndexSignature<T> = {
|
||||
[K in keyof T as string extends K ? K : K extends string ? never : K]: T[K];
|
||||
};
|
||||
export type Keys<T extends object> = keyof OmitIndexSignature<T>;
|
||||
|
||||
export type SchemaClass<T extends schemas.SomeType> = {
|
||||
new (def: T["_zod"]["def"]): T;
|
||||
};
|
||||
export type EnumValue = string | number; // | bigint | boolean | symbol;
|
||||
export type EnumLike = Readonly<Record<string, EnumValue>>;
|
||||
export type ToEnum<T extends EnumValue> = Flatten<{ [k in T]: k }>;
|
||||
export type KeysEnum<T extends object> = ToEnum<Exclude<keyof T, symbol>>;
|
||||
export type KeysArray<T extends object> = Flatten<(keyof T & string)[]>;
|
||||
export type Literal = string | number | bigint | boolean | null | undefined;
|
||||
export type LiteralArray = Array<Literal>;
|
||||
export type Primitive = string | number | symbol | bigint | boolean | null | undefined;
|
||||
export type PrimitiveArray = Array<Primitive>;
|
||||
export type HasSize = { size: number };
|
||||
export type HasLength = { length: number }; // string | Array<unknown> | Set<unknown> | File;
|
||||
export type Numeric = number | bigint | Date;
|
||||
export type SafeParseResult<T> = SafeParseSuccess<T> | SafeParseError<T>;
|
||||
export type SafeParseSuccess<T> = { success: true; data: T; error?: never };
|
||||
export type SafeParseError<T> = {
|
||||
success: false;
|
||||
data?: never;
|
||||
error: errors.$ZodError<T>;
|
||||
};
|
||||
|
||||
export type PropValues = Record<string, Set<Primitive>>;
|
||||
export type PrimitiveSet = Set<Primitive>;
|
||||
|
||||
// functions
|
||||
export function assertEqual<A, B>(val: AssertEqual<A, B>): AssertEqual<A, B> {
|
||||
return val;
|
||||
}
|
||||
|
||||
export function assertNotEqual<A, B>(val: AssertNotEqual<A, B>): AssertNotEqual<A, B> {
|
||||
return val;
|
||||
}
|
||||
|
||||
export function assertIs<T>(_arg: T): void {}
|
||||
|
||||
export function assertNever(_x: never): never {
|
||||
throw new Error();
|
||||
}
|
||||
export function assert<T>(_: any): asserts _ is T {}
|
||||
|
||||
export function getEnumValues(entries: EnumLike): EnumValue[] {
|
||||
const numericValues = Object.values(entries).filter((v) => typeof v === "number");
|
||||
const values = Object.entries(entries)
|
||||
.filter(([k, _]) => numericValues.indexOf(+k) === -1)
|
||||
.map(([_, v]) => v);
|
||||
return values;
|
||||
}
|
||||
|
||||
export function joinValues<T extends Primitive[]>(array: T, separator = "|"): string {
|
||||
return array.map((val) => stringifyPrimitive(val)).join(separator);
|
||||
}
|
||||
|
||||
export function jsonStringifyReplacer(_: string, value: any): any {
|
||||
if (typeof value === "bigint") return value.toString();
|
||||
return value;
|
||||
}
|
||||
|
||||
export function cached<T>(getter: () => T): { value: T } {
|
||||
const set = false;
|
||||
return {
|
||||
get value() {
|
||||
if (!set) {
|
||||
const value = getter();
|
||||
Object.defineProperty(this, "value", { value });
|
||||
return value;
|
||||
}
|
||||
throw new Error("cached value already set");
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function nullish(input: any): boolean {
|
||||
return input === null || input === undefined;
|
||||
}
|
||||
|
||||
export function cleanRegex(source: string): string {
|
||||
const start = source.startsWith("^") ? 1 : 0;
|
||||
const end = source.endsWith("$") ? source.length - 1 : source.length;
|
||||
return source.slice(start, end);
|
||||
}
|
||||
|
||||
export function floatSafeRemainder(val: number, step: number): number {
|
||||
const valDecCount = (val.toString().split(".")[1] || "").length;
|
||||
const stepDecCount = (step.toString().split(".")[1] || "").length;
|
||||
const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;
|
||||
const valInt = Number.parseInt(val.toFixed(decCount).replace(".", ""));
|
||||
const stepInt = Number.parseInt(step.toFixed(decCount).replace(".", ""));
|
||||
return (valInt % stepInt) / 10 ** decCount;
|
||||
}
|
||||
|
||||
export function defineLazy<T, K extends keyof T>(object: T, key: K, getter: () => T[K]): void {
|
||||
const set = false;
|
||||
Object.defineProperty(object, key, {
|
||||
get() {
|
||||
if (!set) {
|
||||
const value = getter();
|
||||
object[key] = value;
|
||||
return value;
|
||||
}
|
||||
throw new Error("cached value already set");
|
||||
},
|
||||
set(v) {
|
||||
Object.defineProperty(object, key, {
|
||||
value: v,
|
||||
// configurable: true,
|
||||
});
|
||||
// object[key] = v;
|
||||
},
|
||||
configurable: true,
|
||||
});
|
||||
}
|
||||
|
||||
export function assignProp<T extends object, K extends PropertyKey>(
|
||||
target: T,
|
||||
prop: K,
|
||||
value: K extends keyof T ? T[K] : any
|
||||
): void {
|
||||
Object.defineProperty(target, prop, {
|
||||
value,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
});
|
||||
}
|
||||
|
||||
export function getElementAtPath(obj: any, path: (string | number)[] | null | undefined): any {
|
||||
if (!path) return obj;
|
||||
return path.reduce((acc, key) => acc?.[key], obj);
|
||||
}
|
||||
|
||||
export function promiseAllObject<T extends object>(promisesObj: T): Promise<{ [k in keyof T]: Awaited<T[k]> }> {
|
||||
const keys = Object.keys(promisesObj);
|
||||
const promises = keys.map((key) => (promisesObj as any)[key]);
|
||||
|
||||
return Promise.all(promises).then((results) => {
|
||||
const resolvedObj: any = {};
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
resolvedObj[keys[i]!] = results[i];
|
||||
}
|
||||
return resolvedObj;
|
||||
});
|
||||
}
|
||||
|
||||
export function randomString(length = 10): string {
|
||||
const chars = "abcdefghijklmnopqrstuvwxyz";
|
||||
let str = "";
|
||||
for (let i = 0; i < length; i++) {
|
||||
str += chars[Math.floor(Math.random() * chars.length)];
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
export function esc(str: string): string {
|
||||
return JSON.stringify(str);
|
||||
}
|
||||
|
||||
export const captureStackTrace: (targetObject: object, constructorOpt?: Function) => void = Error.captureStackTrace
|
||||
? Error.captureStackTrace
|
||||
: (..._args) => {};
|
||||
|
||||
export function isObject(data: any): data is Record<PropertyKey, unknown> {
|
||||
return typeof data === "object" && data !== null && !Array.isArray(data);
|
||||
}
|
||||
|
||||
export const allowsEval: { value: boolean } = cached(() => {
|
||||
if (typeof navigator !== "undefined" && navigator?.userAgent?.includes("Cloudflare")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const F = Function;
|
||||
new F("");
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
export function isPlainObject(o: any): o is Record<PropertyKey, unknown> {
|
||||
if (isObject(o) === false) return false;
|
||||
|
||||
// modified constructor
|
||||
const ctor = o.constructor;
|
||||
if (ctor === undefined) return true;
|
||||
|
||||
// modified prototype
|
||||
const prot = ctor.prototype;
|
||||
if (isObject(prot) === false) return false;
|
||||
|
||||
// ctor doesn't have static `isPrototypeOf`
|
||||
if (Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf") === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
export function numKeys(data: any): number {
|
||||
let keyCount = 0;
|
||||
for (const key in data) {
|
||||
if (Object.prototype.hasOwnProperty.call(data, key)) {
|
||||
keyCount++;
|
||||
}
|
||||
}
|
||||
return keyCount;
|
||||
}
|
||||
|
||||
export const getParsedType = (data: any): ParsedTypes => {
|
||||
const t = typeof data;
|
||||
|
||||
switch (t) {
|
||||
case "undefined":
|
||||
return "undefined";
|
||||
|
||||
case "string":
|
||||
return "string";
|
||||
|
||||
case "number":
|
||||
return Number.isNaN(data) ? "nan" : "number";
|
||||
|
||||
case "boolean":
|
||||
return "boolean";
|
||||
|
||||
case "function":
|
||||
return "function";
|
||||
|
||||
case "bigint":
|
||||
return "bigint";
|
||||
|
||||
case "symbol":
|
||||
return "symbol";
|
||||
|
||||
case "object":
|
||||
if (Array.isArray(data)) {
|
||||
return "array";
|
||||
}
|
||||
if (data === null) {
|
||||
return "null";
|
||||
}
|
||||
if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") {
|
||||
return "promise";
|
||||
}
|
||||
if (typeof Map !== "undefined" && data instanceof Map) {
|
||||
return "map";
|
||||
}
|
||||
if (typeof Set !== "undefined" && data instanceof Set) {
|
||||
return "set";
|
||||
}
|
||||
if (typeof Date !== "undefined" && data instanceof Date) {
|
||||
return "date";
|
||||
}
|
||||
if (typeof File !== "undefined" && data instanceof File) {
|
||||
return "file";
|
||||
}
|
||||
return "object";
|
||||
|
||||
default:
|
||||
throw new Error(`Unknown data type: ${t}`);
|
||||
}
|
||||
};
|
||||
|
||||
export const propertyKeyTypes: Set<string> = new Set(["string", "number", "symbol"]);
|
||||
export const primitiveTypes: Set<string> = new Set(["string", "number", "bigint", "boolean", "symbol", "undefined"]);
|
||||
export function escapeRegex(str: string): string {
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
}
|
||||
|
||||
// zod-specific utils
|
||||
export function clone<T extends schemas.$ZodType>(inst: T, def?: T["_zod"]["def"], params?: { parent: boolean }): T {
|
||||
const cl = new inst._zod.constr(def ?? inst._zod.def);
|
||||
if (!def || params?.parent) cl._zod.parent = inst;
|
||||
return cl as any;
|
||||
}
|
||||
|
||||
export type EmptyToNever<T> = keyof T extends never ? never : T;
|
||||
|
||||
export type Normalize<T> = T extends undefined
|
||||
? never
|
||||
: T extends Record<any, any>
|
||||
? Flatten<
|
||||
{
|
||||
[k in keyof Omit<T, "error" | "message">]: T[k];
|
||||
} & ("error" extends keyof T
|
||||
? {
|
||||
error?: Exclude<T["error"], string>;
|
||||
// path?: PropertyKey[] | undefined;
|
||||
// message?: string | undefined;
|
||||
}
|
||||
: unknown)
|
||||
>
|
||||
: never;
|
||||
|
||||
export function normalizeParams<T>(_params: T): Normalize<T> {
|
||||
const params: any = _params;
|
||||
|
||||
if (!params) return {} as any;
|
||||
if (typeof params === "string") return { error: () => params } as any;
|
||||
if (params?.message !== undefined) {
|
||||
if (params?.error !== undefined) throw new Error("Cannot specify both `message` and `error` params");
|
||||
params.error = params.message;
|
||||
}
|
||||
delete params.message;
|
||||
if (typeof params.error === "string") return { ...params, error: () => params.error } as any;
|
||||
return params;
|
||||
}
|
||||
|
||||
export function createTransparentProxy<T extends object>(getter: () => T): T {
|
||||
let target: T;
|
||||
return new Proxy(
|
||||
{},
|
||||
{
|
||||
get(_, prop, receiver) {
|
||||
target ??= getter();
|
||||
return Reflect.get(target, prop, receiver);
|
||||
},
|
||||
set(_, prop, value, receiver) {
|
||||
target ??= getter();
|
||||
return Reflect.set(target, prop, value, receiver);
|
||||
},
|
||||
has(_, prop) {
|
||||
target ??= getter();
|
||||
return Reflect.has(target, prop);
|
||||
},
|
||||
deleteProperty(_, prop) {
|
||||
target ??= getter();
|
||||
return Reflect.deleteProperty(target, prop);
|
||||
},
|
||||
ownKeys(_) {
|
||||
target ??= getter();
|
||||
return Reflect.ownKeys(target);
|
||||
},
|
||||
getOwnPropertyDescriptor(_, prop) {
|
||||
target ??= getter();
|
||||
return Reflect.getOwnPropertyDescriptor(target, prop);
|
||||
},
|
||||
defineProperty(_, prop, descriptor) {
|
||||
target ??= getter();
|
||||
return Reflect.defineProperty(target, prop, descriptor);
|
||||
},
|
||||
}
|
||||
) as T;
|
||||
}
|
||||
|
||||
export function stringifyPrimitive(value: any): string {
|
||||
if (typeof value === "bigint") return value.toString() + "n";
|
||||
if (typeof value === "string") return `"${value}"`;
|
||||
return `${value}`;
|
||||
}
|
||||
|
||||
export function optionalKeys(shape: schemas.$ZodShape): string[] {
|
||||
return Object.keys(shape).filter((k) => {
|
||||
return shape[k]!._zod.optin === "optional" && shape[k]!._zod.optout === "optional";
|
||||
});
|
||||
}
|
||||
|
||||
export type CleanKey<T extends PropertyKey> = T extends `?${infer K}` ? K : T extends `${infer K}?` ? K : T;
|
||||
export type ToCleanMap<T extends schemas.$ZodLooseShape> = {
|
||||
[k in keyof T]: k extends `?${infer K}` ? K : k extends `${infer K}?` ? K : k;
|
||||
};
|
||||
export type FromCleanMap<T extends schemas.$ZodLooseShape> = {
|
||||
[k in keyof T as k extends `?${infer K}` ? K : k extends `${infer K}?` ? K : k]: k;
|
||||
};
|
||||
|
||||
export const NUMBER_FORMAT_RANGES: Record<checks.$ZodNumberFormats, [number, number]> = {
|
||||
safeint: [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER],
|
||||
int32: [-2147483648, 2147483647],
|
||||
uint32: [0, 4294967295],
|
||||
float32: [-3.4028234663852886e38, 3.4028234663852886e38],
|
||||
float64: [-Number.MAX_VALUE, Number.MAX_VALUE],
|
||||
};
|
||||
|
||||
export const BIGINT_FORMAT_RANGES: Record<checks.$ZodBigIntFormats, [bigint, bigint]> = {
|
||||
int64: [/* @__PURE__*/ BigInt("-9223372036854775808"), /* @__PURE__*/ BigInt("9223372036854775807")],
|
||||
uint64: [/* @__PURE__*/ BigInt(0), /* @__PURE__*/ BigInt("18446744073709551615")],
|
||||
};
|
||||
|
||||
export function pick(schema: schemas.$ZodObject, mask: Record<string, unknown>): any {
|
||||
const newShape: Writeable<schemas.$ZodShape> = {};
|
||||
const currDef = schema._zod.def; //.shape;
|
||||
|
||||
for (const key in mask) {
|
||||
if (!(key in currDef.shape)) {
|
||||
throw new Error(`Unrecognized key: "${key}"`);
|
||||
}
|
||||
if (!mask[key]) continue;
|
||||
|
||||
// pick key
|
||||
newShape[key] = currDef.shape[key]!;
|
||||
}
|
||||
|
||||
return clone(schema, {
|
||||
...schema._zod.def,
|
||||
shape: newShape,
|
||||
checks: [],
|
||||
}) as any;
|
||||
}
|
||||
|
||||
export function omit(schema: schemas.$ZodObject, mask: object): any {
|
||||
const newShape: Writeable<schemas.$ZodShape> = { ...schema._zod.def.shape };
|
||||
const currDef = schema._zod.def; //.shape;
|
||||
for (const key in mask) {
|
||||
if (!(key in currDef.shape)) {
|
||||
throw new Error(`Unrecognized key: "${key}"`);
|
||||
}
|
||||
if (!(mask as any)[key]) continue;
|
||||
|
||||
delete newShape[key];
|
||||
}
|
||||
return clone(schema, {
|
||||
...schema._zod.def,
|
||||
shape: newShape,
|
||||
checks: [],
|
||||
});
|
||||
}
|
||||
|
||||
export function extend(schema: schemas.$ZodObject, shape: schemas.$ZodShape): any {
|
||||
if (!isPlainObject(shape)) {
|
||||
throw new Error("Invalid input to extend: expected a plain object");
|
||||
}
|
||||
const def = {
|
||||
...schema._zod.def,
|
||||
get shape() {
|
||||
const _shape = { ...schema._zod.def.shape, ...shape };
|
||||
assignProp(this, "shape", _shape); // self-caching
|
||||
return _shape;
|
||||
},
|
||||
checks: [], // delete existing checks
|
||||
} as any;
|
||||
return clone(schema, def) as any;
|
||||
}
|
||||
|
||||
export function merge(a: schemas.$ZodObject, b: schemas.$ZodObject): any {
|
||||
return clone(a, {
|
||||
...a._zod.def,
|
||||
get shape() {
|
||||
const _shape = { ...a._zod.def.shape, ...b._zod.def.shape };
|
||||
assignProp(this, "shape", _shape); // self-caching
|
||||
return _shape;
|
||||
},
|
||||
catchall: b._zod.def.catchall,
|
||||
checks: [], // delete existing checks
|
||||
}) as any;
|
||||
}
|
||||
|
||||
export function partial(
|
||||
Class: SchemaClass<schemas.$ZodOptional> | null,
|
||||
schema: schemas.$ZodObject,
|
||||
mask: object | undefined
|
||||
): any {
|
||||
const oldShape = schema._zod.def.shape;
|
||||
const shape: Writeable<schemas.$ZodShape> = { ...oldShape };
|
||||
|
||||
if (mask) {
|
||||
for (const key in mask) {
|
||||
if (!(key in oldShape)) {
|
||||
throw new Error(`Unrecognized key: "${key}"`);
|
||||
}
|
||||
if (!(mask as any)[key]) continue;
|
||||
// if (oldShape[key]!._zod.optin === "optional") continue;
|
||||
shape[key] = Class
|
||||
? new Class({
|
||||
type: "optional",
|
||||
innerType: oldShape[key]!,
|
||||
})
|
||||
: oldShape[key]!;
|
||||
}
|
||||
} else {
|
||||
for (const key in oldShape) {
|
||||
// if (oldShape[key]!._zod.optin === "optional") continue;
|
||||
shape[key] = Class
|
||||
? new Class({
|
||||
type: "optional",
|
||||
innerType: oldShape[key]!,
|
||||
})
|
||||
: oldShape[key]!;
|
||||
}
|
||||
}
|
||||
|
||||
return clone(schema, {
|
||||
...schema._zod.def,
|
||||
shape,
|
||||
checks: [],
|
||||
}) as any;
|
||||
}
|
||||
|
||||
export function required(
|
||||
Class: SchemaClass<schemas.$ZodNonOptional>,
|
||||
schema: schemas.$ZodObject,
|
||||
mask: object | undefined
|
||||
): any {
|
||||
const oldShape = schema._zod.def.shape;
|
||||
const shape: Writeable<schemas.$ZodShape> = { ...oldShape };
|
||||
|
||||
if (mask) {
|
||||
for (const key in mask) {
|
||||
if (!(key in shape)) {
|
||||
throw new Error(`Unrecognized key: "${key}"`);
|
||||
}
|
||||
if (!(mask as any)[key]) continue;
|
||||
// overwrite with non-optional
|
||||
shape[key] = new Class({
|
||||
type: "nonoptional",
|
||||
innerType: oldShape[key]!,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
for (const key in oldShape) {
|
||||
// overwrite with non-optional
|
||||
shape[key] = new Class({
|
||||
type: "nonoptional",
|
||||
innerType: oldShape[key]!,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return clone(schema, {
|
||||
...schema._zod.def,
|
||||
shape,
|
||||
// optional: [],
|
||||
checks: [],
|
||||
}) as any;
|
||||
}
|
||||
|
||||
export type Constructor<T, Def extends any[] = any[]> = new (...args: Def) => T;
|
||||
|
||||
export function aborted(x: schemas.ParsePayload, startIndex = 0): boolean {
|
||||
for (let i = startIndex; i < x.issues.length; i++) {
|
||||
if (x.issues[i]?.continue !== true) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function prefixIssues(path: PropertyKey, issues: errors.$ZodRawIssue[]): errors.$ZodRawIssue[] {
|
||||
return issues.map((iss) => {
|
||||
(iss as any).path ??= [];
|
||||
(iss as any).path.unshift(path);
|
||||
return iss;
|
||||
});
|
||||
}
|
||||
|
||||
export function unwrapMessage(message: string | { message: string } | undefined | null): string | undefined {
|
||||
return typeof message === "string" ? message : message?.message;
|
||||
}
|
||||
|
||||
export function finalizeIssue(
|
||||
iss: errors.$ZodRawIssue,
|
||||
ctx: schemas.ParseContextInternal | undefined,
|
||||
config: $ZodConfig
|
||||
): errors.$ZodIssue {
|
||||
const full = { ...iss, path: iss.path ?? [] } as errors.$ZodIssue;
|
||||
|
||||
// for backwards compatibility
|
||||
if (!iss.message) {
|
||||
const message =
|
||||
unwrapMessage(iss.inst?._zod.def?.error?.(iss as never)) ??
|
||||
unwrapMessage(ctx?.error?.(iss as never)) ??
|
||||
unwrapMessage(config.customError?.(iss)) ??
|
||||
unwrapMessage(config.localeError?.(iss)) ??
|
||||
"Invalid input";
|
||||
(full as any).message = message;
|
||||
}
|
||||
|
||||
// delete (full as any).def;
|
||||
delete (full as any).inst;
|
||||
delete (full as any).continue;
|
||||
if (!ctx?.reportInput) {
|
||||
delete (full as any).input;
|
||||
}
|
||||
|
||||
return full;
|
||||
}
|
||||
|
||||
export function getSizableOrigin(input: any): "set" | "map" | "file" | "unknown" {
|
||||
if (input instanceof Set) return "set";
|
||||
if (input instanceof Map) return "map";
|
||||
if (input instanceof File) return "file";
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
export function getLengthableOrigin(input: any): "array" | "string" | "unknown" {
|
||||
if (Array.isArray(input)) return "array";
|
||||
if (typeof input === "string") return "string";
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
////////// REFINES //////////
|
||||
export function issue(_iss: string, input: any, inst: any): errors.$ZodRawIssue;
|
||||
export function issue(_iss: errors.$ZodRawIssue): errors.$ZodRawIssue;
|
||||
export function issue(...args: [string | errors.$ZodRawIssue, any?, any?]): errors.$ZodRawIssue {
|
||||
const [iss, input, inst] = args;
|
||||
if (typeof iss === "string") {
|
||||
return {
|
||||
message: iss,
|
||||
code: "custom",
|
||||
input,
|
||||
inst,
|
||||
};
|
||||
}
|
||||
|
||||
return { ...iss };
|
||||
}
|
||||
|
||||
export function cleanEnum(obj: Record<string, EnumValue>): EnumValue[] {
|
||||
return Object.entries(obj)
|
||||
.filter(([k, _]) => {
|
||||
// return true if NaN, meaning it's not a number, thus a string key
|
||||
return Number.isNaN(Number.parseInt(k, 10));
|
||||
})
|
||||
.map((el) => el[1]);
|
||||
}
|
||||
|
||||
// instanceof
|
||||
export abstract class Class {
|
||||
constructor(..._args: any[]) {}
|
||||
}
|
||||
5
node_modules/zod/src/v4/core/versions.ts
generated
vendored
Normal file
5
node_modules/zod/src/v4/core/versions.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
export const version = {
|
||||
major: 4,
|
||||
minor: 0,
|
||||
patch: 0 as number,
|
||||
} as const;
|
||||
323
node_modules/zod/src/v4/core/zsf.ts
generated
vendored
Normal file
323
node_modules/zod/src/v4/core/zsf.ts
generated
vendored
Normal file
@@ -0,0 +1,323 @@
|
||||
///////////////////////////////////////////////////
|
||||
//////////////// TYPES ///////////////////
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
export interface $ZSF {
|
||||
$zsf: { version: number };
|
||||
type: string;
|
||||
// default value if not defined
|
||||
default: unknown;
|
||||
// fallback value if validation fails
|
||||
fallback: unknown;
|
||||
}
|
||||
|
||||
export interface $ZSFString extends $ZSF {
|
||||
type: "string";
|
||||
min_length?: number;
|
||||
max_length?: number;
|
||||
pattern?: string;
|
||||
}
|
||||
|
||||
export type NumberTypes = "float32" | "int32" | "uint32" | "float64" | "int64" | "uint64" | "bigint" | "bigdecimal";
|
||||
|
||||
export interface $ZSFNumber extends $ZSF {
|
||||
type: "number";
|
||||
format?: NumberTypes;
|
||||
minimum?: number;
|
||||
maximum?: number;
|
||||
multiple_of?: number;
|
||||
}
|
||||
|
||||
export interface $ZSFBoolean extends $ZSF {
|
||||
type: "boolean";
|
||||
}
|
||||
|
||||
export interface $ZSFNull extends $ZSF {
|
||||
type: "null";
|
||||
}
|
||||
|
||||
export interface $ZSFUndefined extends $ZSF {
|
||||
type: "undefined";
|
||||
}
|
||||
|
||||
export interface $ZSFOptional<T extends $ZSF = $ZSF> extends $ZSF {
|
||||
type: "optional";
|
||||
inner: T;
|
||||
}
|
||||
|
||||
export interface $ZSFNever extends $ZSF {
|
||||
type: "never";
|
||||
}
|
||||
|
||||
export interface $ZSFAny extends $ZSF {
|
||||
type: "any";
|
||||
}
|
||||
|
||||
/** Supports */
|
||||
export interface $ZSFEnum<Elements extends { [k: string]: $ZSFLiteral } = { [k: string]: $ZSFLiteral }> extends $ZSF {
|
||||
type: "enum";
|
||||
elements: Elements;
|
||||
}
|
||||
|
||||
export interface $ZSFArray<PrefixItems extends $ZSF[] = $ZSF[], Items extends $ZSF = $ZSF> extends $ZSF {
|
||||
type: "array";
|
||||
prefixItems: PrefixItems;
|
||||
items: Items;
|
||||
}
|
||||
|
||||
// type $ZSFObjectProperties = { [k: string]: $ZSF };
|
||||
type $ZSFObjectProperties = Array<{
|
||||
key: string;
|
||||
value: $ZSF;
|
||||
format?: "literal" | "pattern";
|
||||
ordering?: number;
|
||||
}>;
|
||||
export interface $ZSFObject<Properties extends $ZSFObjectProperties = $ZSFObjectProperties> extends $ZSF {
|
||||
type: "object";
|
||||
properties: Properties;
|
||||
}
|
||||
|
||||
// export interface $ZSFTuple<
|
||||
// Items extends $ZSF[] = $ZSF[],
|
||||
// Rest extends $ZSF = $ZSF,
|
||||
// > extends $ZSF {
|
||||
// type: "array";
|
||||
// items: Items;
|
||||
// rest: Rest;
|
||||
// }
|
||||
|
||||
/** Supports arbitrary literal values */
|
||||
export interface $ZSFLiteral<T extends $ZSF = $ZSF> extends $ZSF {
|
||||
type: "literal";
|
||||
schema: T;
|
||||
value: unknown;
|
||||
}
|
||||
|
||||
export interface $ZSFUnion<Elements extends $ZSF[] = $ZSF[]> extends $ZSF {
|
||||
type: "union";
|
||||
elements: Elements;
|
||||
}
|
||||
|
||||
export interface $ZSFIntersection extends $ZSF {
|
||||
type: "intersection";
|
||||
elements: $ZSF[];
|
||||
}
|
||||
|
||||
export interface $ZSFMap<K extends $ZSF = $ZSF, V extends $ZSF = $ZSF> extends $ZSF {
|
||||
type: "map";
|
||||
keys: K;
|
||||
values: V;
|
||||
}
|
||||
|
||||
export interface $ZSFConditional<If extends $ZSF, Then extends $ZSF, Else extends $ZSF> extends $ZSF {
|
||||
type: "conditional";
|
||||
if: If;
|
||||
then: Then;
|
||||
else: Else;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
//////////////// CHECKS ////////////////
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
// export interface $ZSFCheckRegex {
|
||||
// check: "regex";
|
||||
// pattern: string;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckEmail {
|
||||
// check: "email";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckURL {
|
||||
// check: "url";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckEmoji {
|
||||
// check: "emoji";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckUUID {
|
||||
// check: "uuid";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckUUIDv4 {
|
||||
// check: "uuidv4";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckUUIDv6 {
|
||||
// check: "uuidv6";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckNanoid {
|
||||
// check: "nanoid";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckGUID {
|
||||
// check: "guid";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckCUID {
|
||||
// check: "cuid";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckCUID2 {
|
||||
// check: "cuid2";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckULID {
|
||||
// check: "ulid";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckXID {
|
||||
// check: "xid";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckKSUID {
|
||||
// check: "ksuid";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckISODateTime {
|
||||
// check: "datetime";
|
||||
// precision?: number;
|
||||
// local?: boolean;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckISODate {
|
||||
// check: "date";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckISOTime {
|
||||
// check: "time";
|
||||
// precision?: number;
|
||||
// local?: boolean;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckDuration {
|
||||
// check: "duration";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckIP {
|
||||
// check: "ip";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckIPv4 {
|
||||
// check: "ipv4";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckIPv6 {
|
||||
// check: "ipv6";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckBase64 {
|
||||
// check: "base64";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckJWT {
|
||||
// check: "jwt";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckJSONString {
|
||||
// check: "json_string";
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckPrefix {
|
||||
// check: "prefix";
|
||||
// prefix: string;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckSuffix {
|
||||
// check: "suffix";
|
||||
// suffix: string;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckIncludes {
|
||||
// check: "includes";
|
||||
// includes: string;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckMinSize {
|
||||
// check: "min_size";
|
||||
// minimum: number;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckMaxSize {
|
||||
// check: "max_size";
|
||||
// maximum: number;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckSizeEquals {
|
||||
// check: "size_equals";
|
||||
// size: number;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckLessThan {
|
||||
// check: "less_than";
|
||||
// maximum: number | bigint | Date;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckLessThanOrEqual {
|
||||
// check: "less_than_or_equal";
|
||||
// maximum: number | bigint | Date;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckGreaterThan {
|
||||
// check: "greater_than";
|
||||
// minimum: number | bigint | Date;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckGreaterThanOrEqual {
|
||||
// check: "greater_than_or_equal";
|
||||
// minimum: number | bigint | Date;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckEquals {
|
||||
// check: "equals";
|
||||
// value: number | bigint | Date;
|
||||
// }
|
||||
|
||||
// export interface $ZSFCheckMultipleOf {
|
||||
// check: "multiple_of";
|
||||
// multipleOf: number;
|
||||
// }
|
||||
|
||||
// export type $ZSFStringFormatChecks =
|
||||
// | $ZSFCheckRegex
|
||||
// | $ZSFCheckEmail
|
||||
// | $ZSFCheckURL
|
||||
// | $ZSFCheckEmoji
|
||||
// | $ZSFCheckUUID
|
||||
// | $ZSFCheckUUIDv4
|
||||
// | $ZSFCheckUUIDv6
|
||||
// | $ZSFCheckNanoid
|
||||
// | $ZSFCheckGUID
|
||||
// | $ZSFCheckCUID
|
||||
// | $ZSFCheckCUID2
|
||||
// | $ZSFCheckULID
|
||||
// | $ZSFCheckXID
|
||||
// | $ZSFCheckKSUID
|
||||
// | $ZSFCheckISODateTime
|
||||
// | $ZSFCheckISODate
|
||||
// | $ZSFCheckISOTime
|
||||
// | $ZSFCheckDuration
|
||||
// | $ZSFCheckIP
|
||||
// | $ZSFCheckIPv4
|
||||
// | $ZSFCheckIPv6
|
||||
// | $ZSFCheckBase64
|
||||
// | $ZSFCheckJWT
|
||||
// | $ZSFCheckJSONString
|
||||
// | $ZSFCheckPrefix
|
||||
// | $ZSFCheckSuffix
|
||||
// | $ZSFCheckIncludes;
|
||||
|
||||
// export type $ZSFCheck =
|
||||
// | $ZSFStringFormatChecks
|
||||
// | $ZSFCheckMinSize
|
||||
// | $ZSFCheckMaxSize
|
||||
// | $ZSFCheckSizeEquals
|
||||
// | $ZSFCheckLessThan
|
||||
// | $ZSFCheckLessThanOrEqual
|
||||
// | $ZSFCheckGreaterThan
|
||||
// | $ZSFCheckGreaterThanOrEqual
|
||||
// | $ZSFCheckEquals
|
||||
// | $ZSFCheckMultipleOf;
|
||||
4
node_modules/zod/src/v4/index.ts
generated
vendored
Normal file
4
node_modules/zod/src/v4/index.ts
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
import z4 from "./classic/index.js";
|
||||
export * from "./classic/index.js";
|
||||
|
||||
export default z4;
|
||||
125
node_modules/zod/src/v4/locales/ar.ts
generated
vendored
Normal file
125
node_modules/zod/src/v4/locales/ar.ts
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
import type { $ZodStringFormats } from "../core/checks.js";
|
||||
import type * as errors from "../core/errors.js";
|
||||
import * as util from "../core/util.js";
|
||||
|
||||
const error: () => errors.$ZodErrorMap = () => {
|
||||
const Sizable: Record<string, { unit: string; verb: string }> = {
|
||||
string: { unit: "حرف", verb: "أن يحوي" },
|
||||
file: { unit: "بايت", verb: "أن يحوي" },
|
||||
array: { unit: "عنصر", verb: "أن يحوي" },
|
||||
set: { unit: "عنصر", verb: "أن يحوي" },
|
||||
};
|
||||
|
||||
function getSizing(origin: string): { unit: string; verb: string } | null {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
|
||||
const parsedType = (data: any): string => {
|
||||
const t = typeof data;
|
||||
|
||||
switch (t) {
|
||||
case "number": {
|
||||
return Number.isNaN(data) ? "NaN" : "number";
|
||||
}
|
||||
case "object": {
|
||||
if (Array.isArray(data)) {
|
||||
return "array";
|
||||
}
|
||||
if (data === null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
if (Object.getPrototypeOf(data) !== Object.prototype && data.constructor) {
|
||||
return data.constructor.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return t;
|
||||
};
|
||||
|
||||
const Nouns: {
|
||||
[k in $ZodStringFormats | (string & {})]?: string;
|
||||
} = {
|
||||
regex: "مدخل",
|
||||
email: "بريد إلكتروني",
|
||||
url: "رابط",
|
||||
emoji: "إيموجي",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "تاريخ ووقت بمعيار ISO",
|
||||
date: "تاريخ بمعيار ISO",
|
||||
time: "وقت بمعيار ISO",
|
||||
duration: "مدة بمعيار ISO",
|
||||
ipv4: "عنوان IPv4",
|
||||
ipv6: "عنوان IPv6",
|
||||
cidrv4: "مدى عناوين بصيغة IPv4",
|
||||
cidrv6: "مدى عناوين بصيغة IPv6",
|
||||
base64: "نَص بترميز base64-encoded",
|
||||
base64url: "نَص بترميز base64url-encoded",
|
||||
json_string: "نَص على هيئة JSON",
|
||||
e164: "رقم هاتف بمعيار E.164",
|
||||
jwt: "JWT",
|
||||
template_literal: "مدخل",
|
||||
};
|
||||
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type":
|
||||
return `مدخلات غير مقبولة: يفترض إدخال ${issue.expected}، ولكن تم إدخال ${parsedType(issue.input)}`;
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
return `مدخلات غير مقبولة: يفترض إدخال ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `اختيار غير مقبول: يتوقع انتقاء أحد هذه الخيارات: ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return ` أكبر من اللازم: يفترض أن تكون ${issue.origin ?? "القيمة"} ${adj} ${issue.maximum.toString()} ${sizing.unit ?? "عنصر"}`;
|
||||
return `أكبر من اللازم: يفترض أن تكون ${issue.origin ?? "القيمة"} ${adj} ${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `أصغر من اللازم: يفترض لـ ${issue.origin} أن يكون ${adj} ${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
|
||||
return `أصغر من اللازم: يفترض لـ ${issue.origin} أن يكون ${adj} ${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue as errors.$ZodStringFormatIssues;
|
||||
if (_issue.format === "starts_with") return `نَص غير مقبول: يجب أن يبدأ بـ "${issue.prefix}"`;
|
||||
if (_issue.format === "ends_with") return `نَص غير مقبول: يجب أن ينتهي بـ "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes") return `نَص غير مقبول: يجب أن يتضمَّن "${_issue.includes}"`;
|
||||
if (_issue.format === "regex") return `نَص غير مقبول: يجب أن يطابق النمط ${_issue.pattern}`;
|
||||
return `${Nouns[_issue.format] ?? issue.format} غير مقبول`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `رقم غير مقبول: يجب أن يكون من مضاعفات ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `معرف${issue.keys.length > 1 ? "ات" : ""} غريب${issue.keys.length > 1 ? "ة" : ""}: ${util.joinValues(issue.keys, "، ")}`;
|
||||
case "invalid_key":
|
||||
return `معرف غير مقبول في ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "مدخل غير مقبول";
|
||||
case "invalid_element":
|
||||
return `مدخل غير مقبول في ${issue.origin}`;
|
||||
default:
|
||||
return "مدخل غير مقبول";
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
121
node_modules/zod/src/v4/locales/az.ts
generated
vendored
Normal file
121
node_modules/zod/src/v4/locales/az.ts
generated
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
import type { $ZodStringFormats } from "../core/checks.js";
|
||||
import type * as errors from "../core/errors.js";
|
||||
import * as util from "../core/util.js";
|
||||
|
||||
const error: () => errors.$ZodErrorMap = () => {
|
||||
const Sizable: Record<string, { unit: string; verb: string }> = {
|
||||
string: { unit: "simvol", verb: "olmalıdır" },
|
||||
file: { unit: "bayt", verb: "olmalıdır" },
|
||||
array: { unit: "element", verb: "olmalıdır" },
|
||||
set: { unit: "element", verb: "olmalıdır" },
|
||||
};
|
||||
|
||||
function getSizing(origin: string): { unit: string; verb: string } | null {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
|
||||
const parsedType = (data: any): string => {
|
||||
const t = typeof data;
|
||||
|
||||
switch (t) {
|
||||
case "number": {
|
||||
return Number.isNaN(data) ? "NaN" : "number";
|
||||
}
|
||||
case "object": {
|
||||
if (Array.isArray(data)) {
|
||||
return "array";
|
||||
}
|
||||
if (data === null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
if (Object.getPrototypeOf(data) !== Object.prototype && data.constructor) {
|
||||
return data.constructor.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return t;
|
||||
};
|
||||
|
||||
const Nouns: {
|
||||
[k in $ZodStringFormats | (string & {})]?: string;
|
||||
} = {
|
||||
regex: "input",
|
||||
email: "email address",
|
||||
url: "URL",
|
||||
emoji: "emoji",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "ISO datetime",
|
||||
date: "ISO date",
|
||||
time: "ISO time",
|
||||
duration: "ISO duration",
|
||||
ipv4: "IPv4 address",
|
||||
ipv6: "IPv6 address",
|
||||
cidrv4: "IPv4 range",
|
||||
cidrv6: "IPv6 range",
|
||||
base64: "base64-encoded string",
|
||||
base64url: "base64url-encoded string",
|
||||
json_string: "JSON string",
|
||||
e164: "E.164 number",
|
||||
jwt: "JWT",
|
||||
template_literal: "input",
|
||||
};
|
||||
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type":
|
||||
return `Yanlış dəyər: gözlənilən ${issue.expected}, daxil olan ${parsedType(issue.input)}`;
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1) return `Yanlış dəyər: gözlənilən ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Yanlış seçim: aşağıdakılardan biri olmalıdır: ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Çox böyük: gözlənilən ${issue.origin ?? "dəyər"} ${adj}${issue.maximum.toString()} ${sizing.unit ?? "element"}`;
|
||||
return `Çox böyük: gözlənilən ${issue.origin ?? "dəyər"} ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) return `Çox kiçik: gözlənilən ${issue.origin} ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
return `Çox kiçik: gözlənilən ${issue.origin} ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue as errors.$ZodStringFormatIssues;
|
||||
if (_issue.format === "starts_with") return `Yanlış mətn: "${_issue.prefix}" ilə başlamalıdır`;
|
||||
if (_issue.format === "ends_with") return `Yanlış mətn: "${_issue.suffix}" ilə bitməlidir`;
|
||||
if (_issue.format === "includes") return `Yanlış mətn: "${_issue.includes}" daxil olmalıdır`;
|
||||
if (_issue.format === "regex") return `Yanlış mətn: ${_issue.pattern} şablonuna uyğun olmalıdır`;
|
||||
return `Yanlış ${Nouns[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Yanlış ədəd: ${issue.divisor} ilə bölünə bilən olmalıdır`;
|
||||
case "unrecognized_keys":
|
||||
return `Tanınmayan açar${issue.keys.length > 1 ? "lar" : ""}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `${issue.origin} daxilində yanlış açar`;
|
||||
case "invalid_union":
|
||||
return "Yanlış dəyər";
|
||||
case "invalid_element":
|
||||
return `${issue.origin} daxilində yanlış dəyər`;
|
||||
default:
|
||||
return `Yanlış dəyər`;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
184
node_modules/zod/src/v4/locales/be.ts
generated
vendored
Normal file
184
node_modules/zod/src/v4/locales/be.ts
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
import type { $ZodStringFormats } from "../core/checks.js";
|
||||
import type * as errors from "../core/errors.js";
|
||||
import * as util from "../core/util.js";
|
||||
|
||||
function getBelarusianPlural(count: number, one: string, few: string, many: string): string {
|
||||
const absCount = Math.abs(count);
|
||||
const lastDigit = absCount % 10;
|
||||
const lastTwoDigits = absCount % 100;
|
||||
|
||||
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
||||
return many;
|
||||
}
|
||||
|
||||
if (lastDigit === 1) {
|
||||
return one;
|
||||
}
|
||||
|
||||
if (lastDigit >= 2 && lastDigit <= 4) {
|
||||
return few;
|
||||
}
|
||||
|
||||
return many;
|
||||
}
|
||||
|
||||
interface BelarusianSizable {
|
||||
unit: {
|
||||
one: string;
|
||||
few: string;
|
||||
many: string;
|
||||
};
|
||||
verb: string;
|
||||
}
|
||||
const error: () => errors.$ZodErrorMap = () => {
|
||||
const Sizable: Record<string, BelarusianSizable> = {
|
||||
string: {
|
||||
unit: {
|
||||
one: "сімвал",
|
||||
few: "сімвалы",
|
||||
many: "сімвалаў",
|
||||
},
|
||||
verb: "мець",
|
||||
},
|
||||
array: {
|
||||
unit: {
|
||||
one: "элемент",
|
||||
few: "элементы",
|
||||
many: "элементаў",
|
||||
},
|
||||
verb: "мець",
|
||||
},
|
||||
set: {
|
||||
unit: {
|
||||
one: "элемент",
|
||||
few: "элементы",
|
||||
many: "элементаў",
|
||||
},
|
||||
verb: "мець",
|
||||
},
|
||||
file: {
|
||||
unit: {
|
||||
one: "байт",
|
||||
few: "байты",
|
||||
many: "байтаў",
|
||||
},
|
||||
verb: "мець",
|
||||
},
|
||||
};
|
||||
|
||||
function getSizing(origin: string): BelarusianSizable | null {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
|
||||
const parsedType = (data: any): string => {
|
||||
const t = typeof data;
|
||||
|
||||
switch (t) {
|
||||
case "number": {
|
||||
return Number.isNaN(data) ? "NaN" : "лік";
|
||||
}
|
||||
case "object": {
|
||||
if (Array.isArray(data)) {
|
||||
return "масіў";
|
||||
}
|
||||
if (data === null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
if (Object.getPrototypeOf(data) !== Object.prototype && data.constructor) {
|
||||
return data.constructor.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return t;
|
||||
};
|
||||
|
||||
const Nouns: {
|
||||
[k in $ZodStringFormats | (string & {})]?: string;
|
||||
} = {
|
||||
regex: "увод",
|
||||
email: "email адрас",
|
||||
url: "URL",
|
||||
emoji: "эмодзі",
|
||||
uuid: "UUID",
|
||||
uuidv4: "UUIDv4",
|
||||
uuidv6: "UUIDv6",
|
||||
nanoid: "nanoid",
|
||||
guid: "GUID",
|
||||
cuid: "cuid",
|
||||
cuid2: "cuid2",
|
||||
ulid: "ULID",
|
||||
xid: "XID",
|
||||
ksuid: "KSUID",
|
||||
datetime: "ISO дата і час",
|
||||
date: "ISO дата",
|
||||
time: "ISO час",
|
||||
duration: "ISO працягласць",
|
||||
ipv4: "IPv4 адрас",
|
||||
ipv6: "IPv6 адрас",
|
||||
cidrv4: "IPv4 дыяпазон",
|
||||
cidrv6: "IPv6 дыяпазон",
|
||||
base64: "радок у фармаце base64",
|
||||
base64url: "радок у фармаце base64url",
|
||||
json_string: "JSON радок",
|
||||
e164: "нумар E.164",
|
||||
jwt: "JWT",
|
||||
template_literal: "увод",
|
||||
};
|
||||
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type":
|
||||
return `Няправільны ўвод: чакаўся ${issue.expected}, атрымана ${parsedType(issue.input)}`;
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1) return `Няправільны ўвод: чакалася ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
return `Няправільны варыянт: чакаўся адзін з ${util.joinValues(issue.values, "|")}`;
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
const maxValue = Number(issue.maximum);
|
||||
const unit = getBelarusianPlural(maxValue, sizing.unit.one, sizing.unit.few, sizing.unit.many);
|
||||
return `Занадта вялікі: чакалася, што ${issue.origin ?? "значэнне"} павінна ${sizing.verb} ${adj}${issue.maximum.toString()} ${unit}`;
|
||||
}
|
||||
return `Занадта вялікі: чакалася, што ${issue.origin ?? "значэнне"} павінна быць ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
const minValue = Number(issue.minimum);
|
||||
const unit = getBelarusianPlural(minValue, sizing.unit.one, sizing.unit.few, sizing.unit.many);
|
||||
return `Занадта малы: чакалася, што ${issue.origin} павінна ${sizing.verb} ${adj}${issue.minimum.toString()} ${unit}`;
|
||||
}
|
||||
return `Занадта малы: чакалася, што ${issue.origin} павінна быць ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue as errors.$ZodStringFormatIssues;
|
||||
if (_issue.format === "starts_with") return `Няправільны радок: павінен пачынацца з "${_issue.prefix}"`;
|
||||
if (_issue.format === "ends_with") return `Няправільны радок: павінен заканчвацца на "${_issue.suffix}"`;
|
||||
if (_issue.format === "includes") return `Няправільны радок: павінен змяшчаць "${_issue.includes}"`;
|
||||
if (_issue.format === "regex") return `Няправільны радок: павінен адпавядаць шаблону ${_issue.pattern}`;
|
||||
return `Няправільны ${Nouns[_issue.format] ?? issue.format}`;
|
||||
}
|
||||
case "not_multiple_of":
|
||||
return `Няправільны лік: павінен быць кратным ${issue.divisor}`;
|
||||
case "unrecognized_keys":
|
||||
return `Нераспазнаны ${issue.keys.length > 1 ? "ключы" : "ключ"}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Няправільны ключ у ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Няправільны ўвод";
|
||||
case "invalid_element":
|
||||
return `Няправільнае значэнне ў ${issue.origin}`;
|
||||
default:
|
||||
return `Няправільны ўвод`;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user