feat(planning): grille hebdomadaire complète avec API et filtres
- Connexion API via proxy Angular (résolution CORS, base path /api) - Import CSS ng-zorro global pour les modales et composants - Filtres Camion/Show câblés sur l'affichage de la grille - Camions affichés via TrucksService (linkés au show du même créneau) - Panneau de détails : spectacles + camions du jour sélectionné - Modale de création de spectacle stylisée avec fond et centrage - Positionnement précis des events à la minute dans leur créneau - Auto-scroll vers l'heure courante au chargement - Ligne "maintenant" sur la colonne du jour actuel - Régénération des services OpenAPI (nouveaux noms de types) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+4
-4
@@ -10,7 +10,7 @@
|
||||
<br/>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/colinhacks/zod/actions?query=branch%3Amain"><img src="https://github.com/colinhacks/zod/actions/workflows/test.yml/badge.svg?event=push&branch=main" alt="Zod CI status" /></a>
|
||||
<a href="https://github.com/colinhacks/zod/actions?query=branch%3Amaster"><img src="https://github.com/colinhacks/zod/actions/workflows/test.yml/badge.svg?event=push&branch=master" alt="Zod CI status" /></a>
|
||||
<a href="https://opensource.org/licenses/MIT" rel="nofollow"><img src="https://img.shields.io/github/license/colinhacks/zod" alt="License"></a>
|
||||
<a href="https://www.npmjs.com/package/zod" rel="nofollow"><img src="https://img.shields.io/npm/dw/zod.svg" alt="npm"></a>
|
||||
<a href="https://discord.gg/KaSRdyX2vc" rel="nofollow"><img src="https://img.shields.io/discord/893487829802418277?label=Discord&logo=discord&logoColor=white" alt="discord server"></a>
|
||||
@@ -58,7 +58,7 @@
|
||||
Zod is a TypeScript-first validation library. Define a schema and parse some data with it. You'll get back a strongly typed, validated result.
|
||||
|
||||
```ts
|
||||
import * as z from "zod";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const User = z.object({
|
||||
name: z.string(),
|
||||
@@ -104,7 +104,7 @@ npm install zod
|
||||
Before you can do anything else, you need to define a schema. For the purposes of this guide, we'll use a simple object schema.
|
||||
|
||||
```ts
|
||||
import * as z from "zod";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const Player = z.object({
|
||||
username: z.string(),
|
||||
@@ -121,7 +121,7 @@ Player.parse({ username: "billie", xp: 100 });
|
||||
// => returns { username: "billie", xp: 100 }
|
||||
```
|
||||
|
||||
**Note** — If your schema uses certain asynchronous APIs like `async` [refinements](https://zod.dev/api#refinements) or [transforms](https://zod.dev/api#transforms), you'll need to use the `.parseAsync()` method instead.
|
||||
**Note** — If your schema uses certain asynchronous APIs like `async` [refinements](#refine) or [transforms](#transform), you'll need to use the `.parseAsync()` method instead.
|
||||
|
||||
```ts
|
||||
const schema = z.string().refine(async (val) => val.length <= 8);
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.z = void 0;
|
||||
const z = __importStar(require("./v4/classic/external.cjs"));
|
||||
const z = __importStar(require("./v3/external.cjs"));
|
||||
exports.z = z;
|
||||
__exportStar(require("./v4/classic/external.cjs"), exports);
|
||||
__exportStar(require("./v3/external.cjs"), exports);
|
||||
exports.default = z;
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import * as z from "./v4/classic/external.cjs";
|
||||
export * from "./v4/classic/external.cjs";
|
||||
import * as z from "./v3/external.cjs";
|
||||
export * from "./v3/external.cjs";
|
||||
export { z };
|
||||
export default z;
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import * as z from "./v4/classic/external.js";
|
||||
export * from "./v4/classic/external.js";
|
||||
import * as z from "./v3/external.js";
|
||||
export * from "./v3/external.js";
|
||||
export { z };
|
||||
export default z;
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import * as z from "./v4/classic/external.js";
|
||||
export * from "./v4/classic/external.js";
|
||||
import * as z from "./v3/external.js";
|
||||
export * from "./v3/external.js";
|
||||
export { z };
|
||||
export default z;
|
||||
|
||||
+12
-29
@@ -1,16 +1,9 @@
|
||||
{
|
||||
"name": "zod",
|
||||
"version": "4.1.13",
|
||||
"version": "3.25.76",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"author": "Colin McDonnell <zod@colinhacks.com>",
|
||||
"description": "TypeScript-first schema declaration and validation library with static type inference",
|
||||
"homepage": "https://zod.dev",
|
||||
"llms": "https://zod.dev/llms.txt",
|
||||
"llmsFull": "https://zod.dev/llms-full.txt",
|
||||
"mcpServer": "https://mcp.inkeep.com/zod/mcp",
|
||||
"funding": "https://github.com/sponsors/colinhacks",
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"src",
|
||||
"**/*.js",
|
||||
@@ -18,9 +11,10 @@
|
||||
"**/*.cjs",
|
||||
"**/*.d.ts",
|
||||
"**/*.d.mts",
|
||||
"**/*.d.cts",
|
||||
"**/package.json"
|
||||
"**/*.d.cts"
|
||||
],
|
||||
"funding": "https://github.com/sponsors/colinhacks",
|
||||
"homepage": "https://zod.dev",
|
||||
"keywords": [
|
||||
"typescript",
|
||||
"schema",
|
||||
@@ -28,6 +22,8 @@
|
||||
"type",
|
||||
"inference"
|
||||
],
|
||||
"license": "MIT",
|
||||
"sideEffects": false,
|
||||
"main": "./index.cjs",
|
||||
"types": "./index.d.cts",
|
||||
"module": "./index.js",
|
||||
@@ -35,8 +31,6 @@
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": "./src/index.ts",
|
||||
"./mini": "./src/mini/index.ts",
|
||||
"./locales": "./src/locales/index.ts",
|
||||
"./v3": "./src/v3/index.ts",
|
||||
"./v4": "./src/v4/index.ts",
|
||||
"./v4-mini": "./src/v4-mini/index.ts",
|
||||
@@ -45,9 +39,9 @@
|
||||
"./v4/locales": "./src/v4/locales/index.ts",
|
||||
"./v4/locales/*": "./src/v4/locales/*"
|
||||
},
|
||||
"conditions": {
|
||||
"@zod/source": "src"
|
||||
}
|
||||
"sourceDialects": [
|
||||
"@zod/source"
|
||||
]
|
||||
},
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
@@ -57,18 +51,6 @@
|
||||
"import": "./index.js",
|
||||
"require": "./index.cjs"
|
||||
},
|
||||
"./mini": {
|
||||
"@zod/source": "./src/mini/index.ts",
|
||||
"types": "./mini/index.d.cts",
|
||||
"import": "./mini/index.js",
|
||||
"require": "./mini/index.cjs"
|
||||
},
|
||||
"./locales": {
|
||||
"@zod/source": "./src/locales/index.ts",
|
||||
"types": "./locales/index.d.cts",
|
||||
"import": "./locales/index.js",
|
||||
"require": "./locales/index.cjs"
|
||||
},
|
||||
"./v3": {
|
||||
"@zod/source": "./src/v3/index.ts",
|
||||
"types": "./v3/index.d.cts",
|
||||
@@ -127,9 +109,10 @@
|
||||
"scripts": {
|
||||
"clean": "git clean -xdf . -e node_modules",
|
||||
"build": "zshy --project tsconfig.build.json",
|
||||
"postbuild": "tsx ../../scripts/write-stub-package-jsons.ts && pnpm biome check --write .",
|
||||
"postbuild": "pnpm biome check --write .",
|
||||
"test:watch": "pnpm vitest",
|
||||
"test": "pnpm vitest run",
|
||||
"prepublishOnly": "tsx ../../scripts/check-versions.ts"
|
||||
"bump:beta": "pnpm version \"v$(pnpm pkg get version | jq -r)-beta.$(date +%Y%m%dT%H%M%S)\"",
|
||||
"pub:beta": "pnpm bump:beta && pnpm publish --tag next --publish-branch v4 --no-git-checks --dry-run"
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import * as z from "./v4/classic/external.js";
|
||||
export * from "./v4/classic/external.js";
|
||||
import * as z from "./v3/external.js";
|
||||
export * from "./v3/external.js";
|
||||
export { z };
|
||||
export default z;
|
||||
|
||||
+1
-1
@@ -296,7 +296,7 @@ export class ZodError<T = any> extends Error {
|
||||
flatten(): typeToFlattenedError<T>;
|
||||
flatten<U>(mapper?: (issue: ZodIssue) => U): typeToFlattenedError<T, U>;
|
||||
flatten<U = string>(mapper: (issue: ZodIssue) => U = (issue: ZodIssue) => issue.message as any): any {
|
||||
const fieldErrors: any = Object.create(null);
|
||||
const fieldErrors: any = {};
|
||||
const formErrors: U[] = [];
|
||||
for (const sub of this.issues) {
|
||||
if (sub.path.length > 0) {
|
||||
|
||||
+2
-2
@@ -152,13 +152,13 @@ test("catchall overrides strict", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("test that optional keys are unset", () => {
|
||||
test("test that optional keys are unset", async () => {
|
||||
const SNamedEntity = z.object({
|
||||
id: z.string(),
|
||||
set: z.string().optional(),
|
||||
unset: z.string().optional(),
|
||||
});
|
||||
const result = SNamedEntity.parse({
|
||||
const result = await SNamedEntity.parse({
|
||||
id: "asdf",
|
||||
set: undefined,
|
||||
});
|
||||
|
||||
+2
-2
@@ -342,8 +342,8 @@ test("uuid", () => {
|
||||
uuid.parse("9491d710-3185-4e06-bea0-6a2f275345e0");
|
||||
uuid.parse("d89e7b01-7598-ed11-9d7a-0022489382fd"); // new sequential id
|
||||
uuid.parse("00000000-0000-0000-0000-000000000000");
|
||||
uuid.parse("b3ce60f8-e8b9-40f5-1150-172ede56ff74"); // Variant 0 - RFC 9562/4122: Reserved, NCS backward compatibility
|
||||
uuid.parse("92e76bf9-28b3-4730-cd7f-cb6bc51f8c09"); // Variant 2 - RFC 9562/4122: Reserved, Microsoft Corporation backward compatibility
|
||||
uuid.parse("b3ce60f8-e8b9-40f5-1150-172ede56ff74"); // Variant 0 - RFC 4122: Reserved, NCS backward compatibility
|
||||
uuid.parse("92e76bf9-28b3-4730-cd7f-cb6bc51f8c09"); // Variant 2 - RFC 4122: Reserved, Microsoft Corporation backward compatibility
|
||||
const result = uuid.safeParse("9491d710-3185-4e06-bea0-6a2f275345e0X");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
|
||||
+1
-3
@@ -705,7 +705,6 @@ function isValidJWT(jwt: string, alg?: string): boolean {
|
||||
.replace(/-/g, "+")
|
||||
.replace(/_/g, "/")
|
||||
.padEnd(header.length + ((4 - (header.length % 4)) % 4), "=");
|
||||
// @ts-ignore
|
||||
const decoded = JSON.parse(atob(base64));
|
||||
if (typeof decoded !== "object" || decoded === null) return false;
|
||||
if ("typ" in decoded && decoded?.typ !== "JWT") return false;
|
||||
@@ -876,7 +875,6 @@ export class ZodString extends ZodType<string, ZodStringDef, string> {
|
||||
}
|
||||
} else if (check.kind === "url") {
|
||||
try {
|
||||
// @ts-ignore
|
||||
new URL(input.data);
|
||||
} catch {
|
||||
ctx = this._getOrReturnCtx(input, ctx);
|
||||
@@ -2456,7 +2454,7 @@ export class ZodObject<
|
||||
Output = objectOutputType<T, Catchall, UnknownKeys>,
|
||||
Input = objectInputType<T, Catchall, UnknownKeys>,
|
||||
> extends ZodType<Output, ZodObjectDef<T, UnknownKeys, Catchall>, Input> {
|
||||
_cached: { shape: T; keys: string[] } | null = null;
|
||||
private _cached: { shape: T; keys: string[] } | null = null;
|
||||
|
||||
_getCached(): { shape: T; keys: string[] } {
|
||||
if (this._cached !== null) return this._cached;
|
||||
|
||||
-2
@@ -27,6 +27,4 @@ export {
|
||||
_trim as trim,
|
||||
_toLowerCase as toLowerCase,
|
||||
_toUpperCase as toUpperCase,
|
||||
_slugify as slugify,
|
||||
type $RefinementCtx as RefinementCtx,
|
||||
} from "../core/index.js";
|
||||
|
||||
-4
@@ -63,8 +63,4 @@ export type {
|
||||
ZodType as Schema,
|
||||
};
|
||||
|
||||
/** Included for Zod 3 compatibility */
|
||||
export type ZodRawShape = core.$ZodShape;
|
||||
|
||||
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
||||
export enum ZodFirstPartyTypeKind {}
|
||||
|
||||
+2
-9
@@ -1,6 +1,5 @@
|
||||
import * as core from "../core/index.js";
|
||||
import { $ZodError } from "../core/index.js";
|
||||
import * as util from "../core/util.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;
|
||||
@@ -35,17 +34,11 @@ const initializer = (inst: ZodError, issues: core.$ZodIssue[]) => {
|
||||
// enumerable: false,
|
||||
},
|
||||
addIssue: {
|
||||
value: (issue: any) => {
|
||||
inst.issues.push(issue);
|
||||
inst.message = JSON.stringify(inst.issues, util.jsonStringifyReplacer, 2);
|
||||
},
|
||||
value: (issue: any) => inst.issues.push(issue),
|
||||
// enumerable: false,
|
||||
},
|
||||
addIssues: {
|
||||
value: (issues: any) => {
|
||||
inst.issues.push(...issues);
|
||||
inst.message = JSON.stringify(inst.issues, util.jsonStringifyReplacer, 2);
|
||||
},
|
||||
value: (issues: any) => inst.issues.push(...issues),
|
||||
// enumerable: false,
|
||||
},
|
||||
isEmpty: {
|
||||
|
||||
+1
-1
@@ -16,6 +16,7 @@ export {
|
||||
type GlobalMeta,
|
||||
registry,
|
||||
config,
|
||||
function,
|
||||
$output,
|
||||
$input,
|
||||
$brand,
|
||||
@@ -27,7 +28,6 @@ export {
|
||||
flattenError,
|
||||
toJSONSchema,
|
||||
TimePrecision,
|
||||
util,
|
||||
NEVER,
|
||||
} from "../core/index.js";
|
||||
|
||||
|
||||
-49
@@ -31,52 +31,3 @@ export const safeParseAsync: <T extends core.$ZodType>(
|
||||
value: unknown,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => Promise<ZodSafeParseResult<core.output<T>>> = /* @__PURE__ */ core._safeParseAsync(ZodRealError) as any;
|
||||
|
||||
// Codec functions
|
||||
export const encode: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => core.input<T> = /* @__PURE__ */ core._encode(ZodRealError) as any;
|
||||
|
||||
export const decode: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => core.output<T> = /* @__PURE__ */ core._decode(ZodRealError) as any;
|
||||
|
||||
export const encodeAsync: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => Promise<core.input<T>> = /* @__PURE__ */ core._encodeAsync(ZodRealError) as any;
|
||||
|
||||
export const decodeAsync: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => Promise<core.output<T>> = /* @__PURE__ */ core._decodeAsync(ZodRealError) as any;
|
||||
|
||||
export const safeEncode: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => ZodSafeParseResult<core.input<T>> = /* @__PURE__ */ core._safeEncode(ZodRealError) as any;
|
||||
|
||||
export const safeDecode: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => ZodSafeParseResult<core.output<T>> = /* @__PURE__ */ core._safeDecode(ZodRealError) as any;
|
||||
|
||||
export const safeEncodeAsync: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => Promise<ZodSafeParseResult<core.input<T>>> = /* @__PURE__ */ core._safeEncodeAsync(ZodRealError) as any;
|
||||
|
||||
export const safeDecodeAsync: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => Promise<ZodSafeParseResult<core.output<T>>> = /* @__PURE__ */ core._safeDecodeAsync(ZodRealError) as any;
|
||||
|
||||
+81
-244
@@ -13,6 +13,10 @@ import * as parse from "./parse.js";
|
||||
///////////////////////////////////////////
|
||||
///////////////////////////////////////////
|
||||
|
||||
export interface RefinementCtx<T = unknown> extends core.ParsePayload<T> {
|
||||
addIssue(arg: string | core.$ZodRawIssue | Partial<core.$ZodIssueCustom>): void;
|
||||
}
|
||||
|
||||
export interface ZodType<
|
||||
out Output = unknown,
|
||||
out Input = unknown,
|
||||
@@ -55,32 +59,11 @@ export interface ZodType<
|
||||
params?: core.ParseContext<core.$ZodIssue>
|
||||
) => Promise<parse.ZodSafeParseResult<core.output<this>>>;
|
||||
|
||||
// encoding/decoding
|
||||
encode(data: core.output<this>, params?: core.ParseContext<core.$ZodIssue>): core.input<this>;
|
||||
decode(data: core.input<this>, params?: core.ParseContext<core.$ZodIssue>): core.output<this>;
|
||||
encodeAsync(data: core.output<this>, params?: core.ParseContext<core.$ZodIssue>): Promise<core.input<this>>;
|
||||
decodeAsync(data: core.input<this>, params?: core.ParseContext<core.$ZodIssue>): Promise<core.output<this>>;
|
||||
safeEncode(
|
||||
data: core.output<this>,
|
||||
params?: core.ParseContext<core.$ZodIssue>
|
||||
): parse.ZodSafeParseResult<core.input<this>>;
|
||||
safeDecode(
|
||||
data: core.input<this>,
|
||||
params?: core.ParseContext<core.$ZodIssue>
|
||||
): parse.ZodSafeParseResult<core.output<this>>;
|
||||
safeEncodeAsync(
|
||||
data: core.output<this>,
|
||||
params?: core.ParseContext<core.$ZodIssue>
|
||||
): Promise<parse.ZodSafeParseResult<core.input<this>>>;
|
||||
safeDecodeAsync(
|
||||
data: core.input<this>,
|
||||
params?: core.ParseContext<core.$ZodIssue>
|
||||
): Promise<parse.ZodSafeParseResult<core.output<this>>>;
|
||||
|
||||
// refinements
|
||||
refine(check: (arg: core.output<this>) => unknown | Promise<unknown>, params?: string | core.$ZodCustomParams): this;
|
||||
/** @deprecated Use `.check()` instead. */
|
||||
superRefine(
|
||||
refinement: (arg: core.output<this>, ctx: core.$RefinementCtx<core.output<this>>) => void | Promise<void>
|
||||
refinement: (arg: core.output<this>, ctx: RefinementCtx<core.output<this>>) => void | Promise<void>
|
||||
): this;
|
||||
overwrite(fn: (x: core.output<this>) => core.output<this>): this;
|
||||
|
||||
@@ -89,7 +72,7 @@ export interface ZodType<
|
||||
nonoptional(params?: string | core.$ZodNonOptionalParams): ZodNonOptional<this>;
|
||||
nullable(): ZodNullable<this>;
|
||||
nullish(): ZodOptional<ZodNullable<this>>;
|
||||
default(def: util.NoUndefined<core.output<this>>): ZodDefault<this>;
|
||||
default(def: core.output<this>): ZodDefault<this>;
|
||||
default(def: () => util.NoUndefined<core.output<this>>): ZodDefault<this>;
|
||||
prefault(def: () => core.input<this>): ZodPrefault<this>;
|
||||
prefault(def: core.input<this>): ZodPrefault<this>;
|
||||
@@ -97,7 +80,7 @@ export interface ZodType<
|
||||
or<T extends core.SomeType>(option: T): ZodUnion<[this, T]>;
|
||||
and<T extends core.SomeType>(incoming: T): ZodIntersection<this, T>;
|
||||
transform<NewOut>(
|
||||
transform: (arg: core.output<this>, ctx: core.$RefinementCtx<core.output<this>>) => NewOut | Promise<NewOut>
|
||||
transform: (arg: core.output<this>, ctx: RefinementCtx<core.output<this>>) => NewOut | Promise<NewOut>
|
||||
): ZodPipe<this, ZodTransform<Awaited<NewOut>, core.output<this>>>;
|
||||
catch(def: core.output<this>): ZodCatch<this>;
|
||||
catch(def: (ctx: core.$ZodCatchCtx) => core.output<this>): ZodCatch<this>;
|
||||
@@ -140,20 +123,21 @@ export interface _ZodType<out Internals extends core.$ZodTypeInternals = core.$Z
|
||||
export const ZodType: core.$constructor<ZodType> = /*@__PURE__*/ core.$constructor("ZodType", (inst, def) => {
|
||||
core.$ZodType.init(inst, def);
|
||||
inst.def = def;
|
||||
inst.type = def.type;
|
||||
Object.defineProperty(inst, "_def", { value: def });
|
||||
|
||||
// base methods
|
||||
inst.check = (...checks) => {
|
||||
return inst.clone(
|
||||
util.mergeDefs(def, {
|
||||
{
|
||||
...def,
|
||||
checks: [
|
||||
...(def.checks ?? []),
|
||||
...checks.map((ch) =>
|
||||
typeof ch === "function" ? { _zod: { check: ch, def: { check: "custom" }, onattach: [] } } : ch
|
||||
),
|
||||
],
|
||||
})
|
||||
}
|
||||
// { parent: true }
|
||||
);
|
||||
};
|
||||
inst.clone = (def, params) => core.clone(inst, def, params);
|
||||
@@ -170,16 +154,6 @@ export const ZodType: core.$constructor<ZodType> = /*@__PURE__*/ core.$construct
|
||||
inst.safeParseAsync = async (data, params) => parse.safeParseAsync(inst, data, params);
|
||||
inst.spa = inst.safeParseAsync;
|
||||
|
||||
// encoding/decoding
|
||||
inst.encode = (data, params) => parse.encode(inst, data, params);
|
||||
inst.decode = (data, params) => parse.decode(inst, data, params);
|
||||
inst.encodeAsync = async (data, params) => parse.encodeAsync(inst, data, params);
|
||||
inst.decodeAsync = async (data, params) => parse.decodeAsync(inst, data, params);
|
||||
inst.safeEncode = (data, params) => parse.safeEncode(inst, data, params);
|
||||
inst.safeDecode = (data, params) => parse.safeDecode(inst, data, params);
|
||||
inst.safeEncodeAsync = async (data, params) => parse.safeEncodeAsync(inst, data, params);
|
||||
inst.safeDecodeAsync = async (data, params) => parse.safeDecodeAsync(inst, data, params);
|
||||
|
||||
// refinements
|
||||
inst.refine = (check, params) => inst.check(refine(check, params));
|
||||
inst.superRefine = (refinement) => inst.check(superRefine(refinement));
|
||||
@@ -252,7 +226,6 @@ export interface _ZodString<T extends core.$ZodStringInternals<unknown> = core.$
|
||||
normalize(form?: "NFC" | "NFD" | "NFKC" | "NFKD" | (string & {})): this;
|
||||
toLowerCase(): this;
|
||||
toUpperCase(): this;
|
||||
slugify(): this;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@@ -282,7 +255,6 @@ export const _ZodString: core.$constructor<_ZodString> = /*@__PURE__*/ core.$con
|
||||
inst.normalize = (...args) => inst.check(checks.normalize(...args));
|
||||
inst.toLowerCase = () => inst.check(checks.toLowerCase());
|
||||
inst.toUpperCase = () => inst.check(checks.toUpperCase());
|
||||
inst.slugify = () => inst.check(checks.slugify());
|
||||
});
|
||||
|
||||
export interface ZodString extends _ZodString<core.$ZodStringInternals<string>> {
|
||||
@@ -482,14 +454,6 @@ export function url(params?: string | core.$ZodURLParams): ZodURL {
|
||||
return core._url(ZodURL, params);
|
||||
}
|
||||
|
||||
export function httpUrl(params?: string | Omit<core.$ZodURLParams, "protocol" | "hostname">): ZodURL {
|
||||
return core._url(ZodURL, {
|
||||
protocol: /^https?$/,
|
||||
hostname: core.regexes.domain,
|
||||
...util.normalizeParams(params),
|
||||
});
|
||||
}
|
||||
|
||||
// ZodEmoji
|
||||
export interface ZodEmoji extends ZodStringFormat<"emoji"> {
|
||||
_zod: core.$ZodEmojiInternals;
|
||||
@@ -616,19 +580,6 @@ export function ipv4(params?: string | core.$ZodIPv4Params): ZodIPv4 {
|
||||
return core._ipv4(ZodIPv4, params);
|
||||
}
|
||||
|
||||
// ZodMAC
|
||||
export interface ZodMAC extends ZodStringFormat<"mac"> {
|
||||
_zod: core.$ZodMACInternals;
|
||||
}
|
||||
export const ZodMAC: core.$constructor<ZodMAC> = /*@__PURE__*/ core.$constructor("ZodMAC", (inst, def) => {
|
||||
// ZodStringFormat.init(inst, def);
|
||||
core.$ZodMAC.init(inst, def);
|
||||
ZodStringFormat.init(inst, def);
|
||||
});
|
||||
export function mac(params?: string | core.$ZodMACParams): ZodMAC {
|
||||
return core._mac(ZodMAC, params);
|
||||
}
|
||||
|
||||
// ZodIPv6
|
||||
export interface ZodIPv6 extends ZodStringFormat<"ipv6"> {
|
||||
_zod: core.$ZodIPv6Internals;
|
||||
@@ -747,27 +698,6 @@ export function stringFormat<Format extends string>(
|
||||
return core._stringFormat(ZodCustomStringFormat, format, fnOrRegex, _params) as any;
|
||||
}
|
||||
|
||||
export function hostname(_params?: string | core.$ZodStringFormatParams): ZodCustomStringFormat<"hostname"> {
|
||||
return core._stringFormat(ZodCustomStringFormat, "hostname", core.regexes.hostname, _params) as any;
|
||||
}
|
||||
|
||||
export function hex(_params?: string | core.$ZodStringFormatParams): ZodCustomStringFormat<"hex"> {
|
||||
return core._stringFormat(ZodCustomStringFormat, "hex", core.regexes.hex, _params) as any;
|
||||
}
|
||||
|
||||
export function hash<Alg extends util.HashAlgorithm, Enc extends util.HashEncoding = "hex">(
|
||||
alg: Alg,
|
||||
params?: {
|
||||
enc?: Enc;
|
||||
} & core.$ZodStringFormatParams
|
||||
): ZodCustomStringFormat<`${Alg}_${Enc}`> {
|
||||
const enc = params?.enc ?? "hex";
|
||||
const format = `${alg}_${enc}` as const;
|
||||
const regex = core.regexes[format as keyof typeof core.regexes] as RegExp;
|
||||
if (!regex) throw new Error(`Unrecognized hash format: ${format}`);
|
||||
return core._stringFormat(ZodCustomStringFormat, format, regex, params) as any;
|
||||
}
|
||||
|
||||
// ZodNumber
|
||||
export interface _ZodNumber<Internals extends core.$ZodNumberInternals = core.$ZodNumberInternals>
|
||||
extends _ZodType<Internals> {
|
||||
@@ -807,7 +737,6 @@ export interface ZodNumber extends _ZodNumber<core.$ZodNumberInternals<number>>
|
||||
|
||||
export const ZodNumber: core.$constructor<ZodNumber> = /*@__PURE__*/ core.$constructor("ZodNumber", (inst, def) => {
|
||||
core.$ZodNumber.init(inst, def);
|
||||
|
||||
ZodType.init(inst, def);
|
||||
|
||||
inst.gt = (value, params) => inst.check(checks.gt(value, params));
|
||||
@@ -1110,23 +1039,13 @@ export function array<T extends core.SomeType>(element: T, params?: string | cor
|
||||
}
|
||||
|
||||
// .keyof
|
||||
export function keyof<T extends ZodObject>(schema: T): ZodEnum<util.KeysEnum<T["_zod"]["output"]>> {
|
||||
export function keyof<T extends ZodObject>(schema: T): ZodLiteral<Exclude<keyof T["_zod"]["output"], symbol>> {
|
||||
const shape = schema._zod.def.shape;
|
||||
return _enum(Object.keys(shape)) as any;
|
||||
return literal(Object.keys(shape)) as any;
|
||||
}
|
||||
|
||||
// ZodObject
|
||||
|
||||
export type SafeExtendShape<Base extends core.$ZodShape, Ext extends core.$ZodLooseShape> = {
|
||||
[K in keyof Ext]: K extends keyof Base
|
||||
? core.output<Ext[K]> extends core.output<Base[K]>
|
||||
? core.input<Ext[K]> extends core.input<Base[K]>
|
||||
? Ext[K]
|
||||
: never
|
||||
: never
|
||||
: Ext[K];
|
||||
};
|
||||
|
||||
export interface ZodObject<
|
||||
/** @ts-ignore Cast variance */
|
||||
out Shape extends core.$ZodShape = core.$ZodLooseShape,
|
||||
@@ -1150,14 +1069,22 @@ export interface ZodObject<
|
||||
/** This is the default behavior. This method call is likely unnecessary. */
|
||||
strip(): ZodObject<Shape, core.$strip>;
|
||||
|
||||
extend<U extends core.$ZodLooseShape>(shape: U): ZodObject<util.Extend<Shape, U>, Config>;
|
||||
|
||||
safeExtend<U extends core.$ZodLooseShape>(
|
||||
shape: SafeExtendShape<Shape, U> & Partial<Record<keyof Shape, core.SomeType>>
|
||||
extend<U extends core.$ZodLooseShape & Partial<Record<keyof Shape, core.SomeType>>>(
|
||||
shape: U
|
||||
): ZodObject<util.Extend<Shape, U>, Config>;
|
||||
|
||||
/**
|
||||
* @deprecated Use [`A.extend(B.shape)`](https://zod.dev/api?id=extend) instead.
|
||||
* @deprecated Use spread syntax and the `.shape` property to combine two object schemas:
|
||||
*
|
||||
* ```ts
|
||||
* const A = z.object({ a: z.string() });
|
||||
* const B = z.object({ b: z.number() });
|
||||
*
|
||||
* const C = z.object({
|
||||
* ...A.shape,
|
||||
* ...B.shape
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
merge<U extends ZodObject>(other: U): ZodObject<util.Extend<Shape, U["shape"]>, U["_zod"]["config"]>;
|
||||
|
||||
@@ -1207,16 +1134,14 @@ export interface ZodObject<
|
||||
}
|
||||
|
||||
export const ZodObject: core.$constructor<ZodObject> = /*@__PURE__*/ core.$constructor("ZodObject", (inst, def) => {
|
||||
core.$ZodObjectJIT.init(inst, def);
|
||||
core.$ZodObject.init(inst, def);
|
||||
ZodType.init(inst, def);
|
||||
|
||||
util.defineLazy(inst, "shape", () => {
|
||||
return def.shape;
|
||||
});
|
||||
|
||||
util.defineLazy(inst, "shape", () => def.shape);
|
||||
inst.keyof = () => _enum(Object.keys(inst._zod.def.shape)) as any;
|
||||
inst.catchall = (catchall) => inst.clone({ ...inst._zod.def, catchall: catchall as any as core.$ZodType }) as any;
|
||||
inst.passthrough = () => inst.clone({ ...inst._zod.def, catchall: unknown() });
|
||||
// inst.nonstrict = () => inst.clone({ ...inst._zod.def, catchall: api.unknown() });
|
||||
inst.loose = () => inst.clone({ ...inst._zod.def, catchall: unknown() });
|
||||
inst.strict = () => inst.clone({ ...inst._zod.def, catchall: never() });
|
||||
inst.strip = () => inst.clone({ ...inst._zod.def, catchall: undefined });
|
||||
@@ -1224,9 +1149,6 @@ export const ZodObject: core.$constructor<ZodObject> = /*@__PURE__*/ core.$const
|
||||
inst.extend = (incoming: any) => {
|
||||
return util.extend(inst, incoming);
|
||||
};
|
||||
inst.safeExtend = (incoming: any) => {
|
||||
return util.safeExtend(inst, incoming);
|
||||
};
|
||||
inst.merge = (other) => util.merge(inst, other);
|
||||
inst.pick = (mask) => util.pick(inst, mask);
|
||||
inst.omit = (mask) => util.omit(inst, mask);
|
||||
@@ -1240,7 +1162,10 @@ export function object<T extends core.$ZodLooseShape = Partial<Record<never, cor
|
||||
): ZodObject<util.Writeable<T>, core.$strip> {
|
||||
const def: core.$ZodObjectDef = {
|
||||
type: "object",
|
||||
shape: shape ?? {},
|
||||
get shape() {
|
||||
util.assignProp(this, "shape", { ...shape });
|
||||
return this.shape;
|
||||
},
|
||||
...util.normalizeParams(params),
|
||||
};
|
||||
return new ZodObject(def) as any;
|
||||
@@ -1254,7 +1179,10 @@ export function strictObject<T extends core.$ZodLooseShape>(
|
||||
): ZodObject<T, core.$strict> {
|
||||
return new ZodObject({
|
||||
type: "object",
|
||||
shape,
|
||||
get shape() {
|
||||
util.assignProp(this, "shape", { ...shape });
|
||||
return this.shape;
|
||||
},
|
||||
catchall: never(),
|
||||
...util.normalizeParams(params),
|
||||
}) as any;
|
||||
@@ -1268,7 +1196,10 @@ export function looseObject<T extends core.$ZodLooseShape>(
|
||||
): ZodObject<T, core.$loose> {
|
||||
return new ZodObject({
|
||||
type: "object",
|
||||
shape,
|
||||
get shape() {
|
||||
util.assignProp(this, "shape", { ...shape });
|
||||
return this.shape;
|
||||
},
|
||||
catchall: unknown(),
|
||||
...util.normalizeParams(params),
|
||||
}) as any;
|
||||
@@ -1298,13 +1229,10 @@ export function union<const T extends readonly core.SomeType[]>(
|
||||
}
|
||||
|
||||
// ZodDiscriminatedUnion
|
||||
export interface ZodDiscriminatedUnion<
|
||||
Options extends readonly core.SomeType[] = readonly core.$ZodType[],
|
||||
Disc extends string = string,
|
||||
> extends ZodUnion<Options>,
|
||||
core.$ZodDiscriminatedUnion<Options, Disc> {
|
||||
_zod: core.$ZodDiscriminatedUnionInternals<Options, Disc>;
|
||||
def: core.$ZodDiscriminatedUnionDef<Options, Disc>;
|
||||
export interface ZodDiscriminatedUnion<Options extends readonly core.SomeType[] = readonly core.$ZodType[]>
|
||||
extends ZodUnion<Options>,
|
||||
core.$ZodDiscriminatedUnion<Options> {
|
||||
_zod: core.$ZodDiscriminatedUnionInternals<Options>;
|
||||
}
|
||||
export const ZodDiscriminatedUnion: core.$constructor<ZodDiscriminatedUnion> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodDiscriminatedUnion",
|
||||
@@ -1316,12 +1244,11 @@ export const ZodDiscriminatedUnion: core.$constructor<ZodDiscriminatedUnion> = /
|
||||
|
||||
export function discriminatedUnion<
|
||||
Types extends readonly [core.$ZodTypeDiscriminable, ...core.$ZodTypeDiscriminable[]],
|
||||
Disc extends string,
|
||||
>(
|
||||
discriminator: Disc,
|
||||
discriminator: string,
|
||||
options: Types,
|
||||
params?: string | core.$ZodDiscriminatedUnionParams
|
||||
): ZodDiscriminatedUnion<Types, Disc> {
|
||||
): ZodDiscriminatedUnion<Types> {
|
||||
// const [options, params] = args;
|
||||
return new ZodDiscriminatedUnion({
|
||||
type: "union",
|
||||
@@ -1433,11 +1360,9 @@ export function partialRecord<Key extends core.$ZodRecordKey, Value extends core
|
||||
valueType: Value,
|
||||
params?: string | core.$ZodRecordParams
|
||||
): ZodRecord<Key & core.$partial, Value> {
|
||||
const k = core.clone(keyType);
|
||||
k._zod.values = undefined;
|
||||
return new ZodRecord({
|
||||
type: "record",
|
||||
keyType: k,
|
||||
keyType: union([keyType, never()]),
|
||||
valueType: valueType as any,
|
||||
...util.normalizeParams(params),
|
||||
}) as any;
|
||||
@@ -1475,6 +1400,7 @@ export interface ZodSet<T extends core.SomeType = core.$ZodType>
|
||||
extends _ZodType<core.$ZodSetInternals<T>>,
|
||||
core.$ZodSet<T> {
|
||||
min(minSize: number, params?: string | core.$ZodCheckMinSizeParams): this;
|
||||
/** */
|
||||
nonempty(params?: string | core.$ZodCheckMinSizeParams): this;
|
||||
max(maxSize: number, params?: string | core.$ZodCheckMaxSizeParams): this;
|
||||
size(size: number, params?: string | core.$ZodCheckSizeEqualsParams): this;
|
||||
@@ -1657,11 +1583,7 @@ export const ZodTransform: core.$constructor<ZodTransform> = /*@__PURE__*/ core.
|
||||
ZodType.init(inst, def);
|
||||
|
||||
inst._zod.parse = (payload, _ctx) => {
|
||||
if (_ctx.direction === "backward") {
|
||||
throw new core.$ZodEncodeError(inst.constructor.name);
|
||||
}
|
||||
|
||||
(payload as core.$RefinementCtx).addIssue = (issue) => {
|
||||
(payload as RefinementCtx).addIssue = (issue) => {
|
||||
if (typeof issue === "string") {
|
||||
payload.issues.push(util.issue(issue, payload.value, def));
|
||||
} else {
|
||||
@@ -1672,7 +1594,7 @@ export const ZodTransform: core.$constructor<ZodTransform> = /*@__PURE__*/ core.
|
||||
_issue.code ??= "custom";
|
||||
_issue.input ??= payload.value;
|
||||
_issue.inst ??= inst;
|
||||
// _issue.continue ??= true;
|
||||
_issue.continue ??= true;
|
||||
payload.issues.push(util.issue(_issue));
|
||||
}
|
||||
};
|
||||
@@ -1774,7 +1696,7 @@ export function _default<T extends core.SomeType>(
|
||||
type: "default",
|
||||
innerType: innerType as any as core.$ZodType,
|
||||
get defaultValue() {
|
||||
return typeof defaultValue === "function" ? (defaultValue as Function)() : util.shallowClone(defaultValue);
|
||||
return typeof defaultValue === "function" ? (defaultValue as Function)() : defaultValue;
|
||||
},
|
||||
}) as any;
|
||||
}
|
||||
@@ -1802,7 +1724,7 @@ export function prefault<T extends core.SomeType>(
|
||||
type: "prefault",
|
||||
innerType: innerType as any as core.$ZodType,
|
||||
get defaultValue() {
|
||||
return typeof defaultValue === "function" ? (defaultValue as Function)() : util.shallowClone(defaultValue);
|
||||
return typeof defaultValue === "function" ? (defaultValue as Function)() : defaultValue;
|
||||
},
|
||||
}) as any;
|
||||
}
|
||||
@@ -1923,48 +1845,15 @@ export function pipe(in_: core.SomeType, out: core.SomeType) {
|
||||
});
|
||||
}
|
||||
|
||||
// ZodCodec
|
||||
export interface ZodCodec<A extends core.SomeType = core.$ZodType, B extends core.SomeType = core.$ZodType>
|
||||
extends ZodPipe<A, B>,
|
||||
core.$ZodCodec<A, B> {
|
||||
_zod: core.$ZodCodecInternals<A, B>;
|
||||
def: core.$ZodCodecDef<A, B>;
|
||||
}
|
||||
export const ZodCodec: core.$constructor<ZodCodec> = /*@__PURE__*/ core.$constructor("ZodCodec", (inst, def) => {
|
||||
ZodPipe.init(inst, def);
|
||||
core.$ZodCodec.init(inst, def);
|
||||
});
|
||||
|
||||
export function codec<const A extends core.SomeType, B extends core.SomeType = core.$ZodType>(
|
||||
in_: A,
|
||||
out: B,
|
||||
params: {
|
||||
decode: (value: core.output<A>, payload: core.ParsePayload<core.output<A>>) => core.util.MaybeAsync<core.input<B>>;
|
||||
encode: (value: core.input<B>, payload: core.ParsePayload<core.input<B>>) => core.util.MaybeAsync<core.output<A>>;
|
||||
}
|
||||
): ZodCodec<A, B> {
|
||||
return new ZodCodec({
|
||||
type: "pipe",
|
||||
in: in_ as any as core.$ZodType,
|
||||
out: out as any as core.$ZodType,
|
||||
transform: params.decode as any,
|
||||
reverseTransform: params.encode as any,
|
||||
}) as any;
|
||||
}
|
||||
|
||||
// ZodReadonly
|
||||
export interface ZodReadonly<T extends core.SomeType = core.$ZodType>
|
||||
extends _ZodType<core.$ZodReadonlyInternals<T>>,
|
||||
core.$ZodReadonly<T> {
|
||||
unwrap(): T;
|
||||
}
|
||||
core.$ZodReadonly<T> {}
|
||||
export const ZodReadonly: core.$constructor<ZodReadonly> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodReadonly",
|
||||
(inst, def) => {
|
||||
core.$ZodReadonly.init(inst, def);
|
||||
ZodType.init(inst, def);
|
||||
|
||||
inst.unwrap = () => inst._zod.def.innerType;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -2038,71 +1927,6 @@ export function promise<T extends core.SomeType>(innerType: T): ZodPromise<T> {
|
||||
}) as any;
|
||||
}
|
||||
|
||||
// ZodFunction
|
||||
export interface ZodFunction<
|
||||
Args extends core.$ZodFunctionIn = core.$ZodFunctionIn,
|
||||
Returns extends core.$ZodFunctionOut = core.$ZodFunctionOut,
|
||||
> extends _ZodType<core.$ZodFunctionInternals<Args, Returns>>,
|
||||
core.$ZodFunction<Args, Returns> {
|
||||
_def: core.$ZodFunctionDef<Args, Returns>;
|
||||
_input: core.$InferInnerFunctionType<Args, Returns>;
|
||||
_output: core.$InferOuterFunctionType<Args, Returns>;
|
||||
|
||||
input<const Items extends util.TupleItems, const Rest extends core.$ZodFunctionOut = core.$ZodFunctionOut>(
|
||||
args: Items,
|
||||
rest?: Rest
|
||||
): ZodFunction<core.$ZodTuple<Items, Rest>, Returns>;
|
||||
input<NewArgs extends core.$ZodFunctionIn>(args: NewArgs): ZodFunction<NewArgs, Returns>;
|
||||
input(...args: any[]): ZodFunction<any, Returns>;
|
||||
|
||||
output<NewReturns extends core.$ZodType>(output: NewReturns): ZodFunction<Args, NewReturns>;
|
||||
}
|
||||
|
||||
export const ZodFunction: core.$constructor<ZodFunction> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodFunction",
|
||||
(inst, def) => {
|
||||
core.$ZodFunction.init(inst, def);
|
||||
ZodType.init(inst, def);
|
||||
}
|
||||
);
|
||||
|
||||
export function _function(): ZodFunction;
|
||||
export function _function<const In extends ReadonlyArray<core.$ZodType>>(params: {
|
||||
input: In;
|
||||
}): ZodFunction<ZodTuple<In, null>, core.$ZodFunctionOut>;
|
||||
export function _function<
|
||||
const In extends ReadonlyArray<core.$ZodType>,
|
||||
const Out extends core.$ZodFunctionOut = core.$ZodFunctionOut,
|
||||
>(params: {
|
||||
input: In;
|
||||
output: Out;
|
||||
}): ZodFunction<ZodTuple<In, null>, Out>;
|
||||
export function _function<const In extends core.$ZodFunctionIn = core.$ZodFunctionIn>(params: {
|
||||
input: In;
|
||||
}): ZodFunction<In, core.$ZodFunctionOut>;
|
||||
export function _function<const Out extends core.$ZodFunctionOut = core.$ZodFunctionOut>(params: {
|
||||
output: Out;
|
||||
}): ZodFunction<core.$ZodFunctionIn, Out>;
|
||||
export function _function<
|
||||
In extends core.$ZodFunctionIn = core.$ZodFunctionIn,
|
||||
Out extends core.$ZodType = core.$ZodType,
|
||||
>(params?: {
|
||||
input: In;
|
||||
output: Out;
|
||||
}): ZodFunction<In, Out>;
|
||||
export function _function(params?: {
|
||||
output?: core.$ZodType;
|
||||
input?: core.$ZodFunctionArgs | Array<core.$ZodType>;
|
||||
}): ZodFunction {
|
||||
return new ZodFunction({
|
||||
type: "function",
|
||||
input: Array.isArray(params?.input) ? tuple(params?.input as any) : (params?.input ?? array(unknown())),
|
||||
output: params?.output ?? unknown(),
|
||||
});
|
||||
}
|
||||
|
||||
export { _function as function };
|
||||
|
||||
// ZodCustom
|
||||
export interface ZodCustom<O = unknown, I = unknown>
|
||||
extends _ZodType<core.$ZodCustomInternals<O, I>>,
|
||||
@@ -2138,15 +1962,27 @@ export function refine<T>(
|
||||
}
|
||||
|
||||
// superRefine
|
||||
export function superRefine<T>(
|
||||
fn: (arg: T, payload: core.$RefinementCtx<T>) => void | Promise<void>
|
||||
): core.$ZodCheck<T> {
|
||||
return core._superRefine(fn);
|
||||
}
|
||||
export function superRefine<T>(fn: (arg: T, payload: RefinementCtx<T>) => void | Promise<void>): core.$ZodCheck<T> {
|
||||
const ch = check<T>((payload) => {
|
||||
(payload as RefinementCtx).addIssue = (issue) => {
|
||||
if (typeof issue === "string") {
|
||||
payload.issues.push(util.issue(issue, payload.value, ch._zod.def));
|
||||
} else {
|
||||
// for Zod 3 backwards compatibility
|
||||
const _issue: any = issue;
|
||||
if (_issue.fatal) _issue.continue = false;
|
||||
_issue.code ??= "custom";
|
||||
_issue.input ??= payload.value;
|
||||
_issue.inst ??= ch;
|
||||
_issue.continue ??= !ch._zod.def.abort;
|
||||
payload.issues.push(util.issue(_issue));
|
||||
}
|
||||
};
|
||||
|
||||
// Re-export describe and meta from core
|
||||
export const describe = core.describe;
|
||||
export const meta = core.meta;
|
||||
return fn(payload.value, payload as RefinementCtx<T>);
|
||||
});
|
||||
return ch;
|
||||
}
|
||||
|
||||
type ZodInstanceOfParams = core.Params<
|
||||
ZodCustom,
|
||||
@@ -2172,14 +2008,15 @@ function _instanceof<T extends typeof util.Class>(
|
||||
export { _instanceof as instanceof };
|
||||
|
||||
// stringbool
|
||||
export const stringbool: (_params?: string | core.$ZodStringBoolParams) => ZodCodec<ZodString, ZodBoolean> = (
|
||||
...args
|
||||
) =>
|
||||
export const stringbool: (
|
||||
_params?: string | core.$ZodStringBoolParams
|
||||
) => ZodPipe<ZodPipe<ZodString, ZodTransform<boolean, string>>, ZodBoolean> = (...args) =>
|
||||
core._stringbool(
|
||||
{
|
||||
Codec: ZodCodec,
|
||||
Pipe: ZodPipe,
|
||||
Boolean: ZodBoolean,
|
||||
String: ZodString,
|
||||
Transform: ZodTransform,
|
||||
},
|
||||
...args
|
||||
) as any;
|
||||
@@ -2210,7 +2047,7 @@ export function json(params?: string | core.$ZodCustomParams): ZodJSONSchema {
|
||||
|
||||
// /** @deprecated Use `z.pipe()` and `z.transform()` instead. */
|
||||
export function preprocess<A, U extends core.SomeType, B = unknown>(
|
||||
fn: (arg: B, ctx: core.$RefinementCtx) => A,
|
||||
fn: (arg: B, ctx: RefinementCtx) => A,
|
||||
schema: U
|
||||
): ZodPipe<ZodTransform<A, B>, U> {
|
||||
return pipe(transform(fn as any), schema as any) as any;
|
||||
|
||||
+6
-6
@@ -6,9 +6,9 @@ test("type inference", () => {
|
||||
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<string[]>();
|
||||
});
|
||||
|
||||
test("array min/max", () => {
|
||||
test("array min/max", async () => {
|
||||
const schema = z.array(z.string()).min(2).max(2);
|
||||
const r1 = schema.safeParse(["asdf"]);
|
||||
const r1 = await schema.safeParse(["asdf"]);
|
||||
expect(r1.success).toEqual(false);
|
||||
expect(r1.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
@@ -23,7 +23,7 @@ test("array min/max", () => {
|
||||
]
|
||||
`);
|
||||
|
||||
const r2 = schema.safeParse(["asdf", "asdf", "asdf"]);
|
||||
const r2 = await schema.safeParse(["asdf", "asdf", "asdf"]);
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
@@ -39,11 +39,11 @@ test("array min/max", () => {
|
||||
`);
|
||||
});
|
||||
|
||||
test("array length", () => {
|
||||
test("array length", async () => {
|
||||
const schema = z.array(z.string()).length(2);
|
||||
schema.parse(["asdf", "asdf"]);
|
||||
|
||||
const r1 = schema.safeParse(["asdf"]);
|
||||
const r1 = await schema.safeParse(["asdf"]);
|
||||
expect(r1.success).toEqual(false);
|
||||
expect(r1.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
@@ -59,7 +59,7 @@ test("array length", () => {
|
||||
]
|
||||
`);
|
||||
|
||||
const r2 = schema.safeParse(["asdf", "asdf", "asdf"]);
|
||||
const r2 = await schema.safeParse(["asdf", "asdf", "asdf"]);
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
|
||||
+5
-29
@@ -1,5 +1,6 @@
|
||||
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");
|
||||
@@ -44,7 +45,7 @@ test("catch with transform", () => {
|
||||
expect(stringWithDefault.unwrap().out).toBeInstanceOf(z.ZodTransform);
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string>();
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | util.Whatever>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
@@ -58,7 +59,7 @@ test("catch on existing optional", () => {
|
||||
expect(stringWithDefault.unwrap().unwrap()).toBeInstanceOf(z.ZodString);
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined>();
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined | util.Whatever>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string | undefined>();
|
||||
});
|
||||
@@ -67,7 +68,7 @@ test("optional on catch", () => {
|
||||
const stringWithDefault = z.string().catch("asdf").optional();
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined>();
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | util.Whatever>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string | undefined>();
|
||||
});
|
||||
@@ -101,7 +102,7 @@ test("nested", () => {
|
||||
inner: "asdf",
|
||||
});
|
||||
type input = z.input<typeof outer>;
|
||||
expectTypeOf<input>().toEqualTypeOf<{ inner: string }>();
|
||||
expectTypeOf<input>().toEqualTypeOf<{ inner: string | util.Whatever } | util.Whatever>();
|
||||
type out = z.output<typeof outer>;
|
||||
|
||||
expectTypeOf<out>().toEqualTypeOf<{ inner: string }>();
|
||||
@@ -249,28 +250,3 @@ test("ctx.input", () => {
|
||||
|
||||
expect(schema.parse(123)).toEqual("123");
|
||||
});
|
||||
|
||||
test("direction-aware catch", () => {
|
||||
const schema = z.string().catch("fallback");
|
||||
|
||||
// Forward direction (regular parse): catch should be applied
|
||||
expect(schema.parse(123)).toBe("fallback");
|
||||
|
||||
// Reverse direction (encode): catch should NOT be applied, invalid value should fail validation
|
||||
expect(z.safeEncode(schema, 123 as any)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
// But valid values should still work in reverse
|
||||
expect(z.encode(schema, "world")).toBe("world");
|
||||
});
|
||||
|
||||
+1
-23
@@ -62,7 +62,7 @@ test("continuability", () => {
|
||||
"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|ffffffff-ffff-ffff-ffff-ffffffffffff)$/",
|
||||
"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",
|
||||
@@ -195,28 +195,6 @@ test("continuability", () => {
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.mac()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "mac",
|
||||
"message": "Invalid MAC address",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^(?:[0-9A-F]{2}:){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}:){5}[0-9a-f]{2}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.emoji()
|
||||
|
||||
-6
@@ -62,12 +62,6 @@ test("datetime parsing with offset", () => {
|
||||
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();
|
||||
|
||||
// Invalid offset tests
|
||||
expect(() => datetimeOffset.parse("2020-10-14T17:42:29+24:00")).toThrow(); // out of range hours
|
||||
expect(() => datetimeOffset.parse("2020-10-14T17:42:29+00:60")).toThrow(); // out of range minutes
|
||||
expect(() => datetimeOffset.parse("2020-10-14T17:42:29+1:30")).toThrow(); // single digit hours
|
||||
expect(() => datetimeOffset.parse("2020-10-14T17:42:29+00:")).toThrow(); // incomplete offset
|
||||
});
|
||||
|
||||
test("datetime parsing with offset and precision 0", () => {
|
||||
|
||||
-52
@@ -311,55 +311,3 @@ test("partial should not clobber defaults", () => {
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("defaulted object schema returns shallow clone", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.string(),
|
||||
})
|
||||
.default({ a: "x" });
|
||||
const result1 = schema.parse(undefined);
|
||||
const result2 = schema.parse(undefined);
|
||||
expect(result1).not.toBe(result2);
|
||||
expect(result1).toEqual(result2);
|
||||
});
|
||||
|
||||
test("defaulted array schema returns shallow clone", () => {
|
||||
const schema = z.array(z.string()).default(["x"]);
|
||||
const result1 = schema.parse(undefined);
|
||||
const result2 = schema.parse(undefined);
|
||||
expect(result1).not.toBe(result2);
|
||||
expect(result1).toEqual(result2);
|
||||
});
|
||||
|
||||
test("direction-aware defaults", () => {
|
||||
const schema = z.string().default("hello");
|
||||
|
||||
// Forward direction (regular parse): defaults should be applied
|
||||
expect(schema.parse(undefined)).toBe("hello");
|
||||
expect(schema.parse("hello")).toBe("hello");
|
||||
|
||||
// Reverse direction (encode): defaults should NOT be applied, undefined should fail validation
|
||||
expect(() => z.encode(schema, undefined as any)).toThrow();
|
||||
|
||||
// But valid values should still work in reverse
|
||||
expect(z.safeEncode(schema, "world")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": "world",
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
expect(z.safeEncode(schema, undefined as any)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
-42
@@ -157,7 +157,6 @@ test("invalid discriminator value", () => {
|
||||
"code": "invalid_union",
|
||||
"errors": [],
|
||||
"note": "No matching discriminator",
|
||||
"discriminator": "type",
|
||||
"path": [
|
||||
"type"
|
||||
],
|
||||
@@ -618,44 +617,3 @@ test("readonly literal discriminator", () => {
|
||||
discUnion.parse({ type: "c", a: "hello" });
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test("pipes", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
type: z.literal("foo"),
|
||||
})
|
||||
.transform((s) => ({ ...s, v: 2 }));
|
||||
|
||||
expect(schema._zod.propValues).toMatchInlineSnapshot(`
|
||||
{
|
||||
"type": Set {
|
||||
"foo",
|
||||
},
|
||||
}
|
||||
`);
|
||||
|
||||
const schema2 = z.object({
|
||||
type: z.literal("bar"),
|
||||
});
|
||||
|
||||
const combinedSchema = z.discriminatedUnion("type", [schema, schema2], {
|
||||
unionFallback: false,
|
||||
});
|
||||
|
||||
combinedSchema.parse({
|
||||
type: "foo",
|
||||
v: 2,
|
||||
});
|
||||
});
|
||||
|
||||
test("def", () => {
|
||||
const schema = z.discriminatedUnion(
|
||||
"type",
|
||||
[z.object({ type: z.literal("play") }), z.object({ type: z.literal("pause") })],
|
||||
{ unionFallback: true }
|
||||
);
|
||||
|
||||
expect(schema.def).toBeDefined();
|
||||
expect(schema.def.discriminator).toEqual("type");
|
||||
expect(schema.def.unionFallback).toEqual(true);
|
||||
});
|
||||
|
||||
+2
-70
@@ -321,7 +321,7 @@ test("all errors", () => {
|
||||
});
|
||||
|
||||
const schema = z.strictObject({
|
||||
username: z.string().brand<"username">(),
|
||||
username: z.string(),
|
||||
favoriteNumbers: z.array(z.number()),
|
||||
nesting: z.object({
|
||||
a: z.string(),
|
||||
@@ -336,33 +336,8 @@ const result = schema.safeParse({
|
||||
extra: 1234,
|
||||
});
|
||||
|
||||
const tree = z.treeifyError(result.error!);
|
||||
|
||||
expectTypeOf(tree).toEqualTypeOf<{
|
||||
errors: string[];
|
||||
properties?: {
|
||||
username?: {
|
||||
errors: string[];
|
||||
};
|
||||
favoriteNumbers?: {
|
||||
errors: string[];
|
||||
items?: {
|
||||
errors: string[];
|
||||
}[];
|
||||
};
|
||||
nesting?: {
|
||||
errors: string[];
|
||||
properties?: {
|
||||
a?: {
|
||||
errors: string[];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}>();
|
||||
|
||||
test("z.treeifyError", () => {
|
||||
expect(tree).toMatchInlineSnapshot(`
|
||||
expect(z.treeifyError(result.error!)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"errors": [
|
||||
"Unrecognized key: "extra"",
|
||||
@@ -550,46 +525,3 @@ test("disc union treeify/format", () => {
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("update message after adding issues", () => {
|
||||
const e = new z.ZodError([]);
|
||||
e.addIssue({
|
||||
code: "custom",
|
||||
message: "message",
|
||||
input: "asdf",
|
||||
path: [],
|
||||
});
|
||||
expect(e.message).toMatchInlineSnapshot(`
|
||||
"[
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "message",
|
||||
"input": "asdf",
|
||||
"path": []
|
||||
}
|
||||
]"
|
||||
`);
|
||||
|
||||
e.addIssue({
|
||||
code: "custom",
|
||||
message: "message",
|
||||
input: "asdf",
|
||||
path: [],
|
||||
});
|
||||
expect(e.message).toMatchInlineSnapshot(`
|
||||
"[
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "message",
|
||||
"input": "asdf",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "message",
|
||||
"input": "asdf",
|
||||
"path": []
|
||||
}
|
||||
]"
|
||||
`);
|
||||
});
|
||||
|
||||
+4
-9
@@ -1,6 +1,7 @@
|
||||
// @ts-ignore
|
||||
import { File as WebFile } from "@web-std/file";
|
||||
|
||||
import { afterEach, beforeEach, expect, expectTypeOf, test } from "vitest";
|
||||
import { afterEach, beforeEach, expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
@@ -26,10 +27,6 @@ test("passing validations", () => {
|
||||
expect(() => mimeCheck.parse(new File([""], "test.txt", { type: "text/csv" }))).toThrow();
|
||||
});
|
||||
|
||||
test("types", () => {
|
||||
expectTypeOf(z.file().parse(new File([], "test.txt"))).toEqualTypeOf(new File([], "test.txt"));
|
||||
});
|
||||
|
||||
test("failing validations", () => {
|
||||
expect(minCheck.safeParse(new File(["1234"], "test.txt"))).toMatchInlineSnapshot(`
|
||||
{
|
||||
@@ -38,9 +35,8 @@ test("failing validations", () => {
|
||||
"origin": "file",
|
||||
"code": "too_small",
|
||||
"minimum": 5,
|
||||
"inclusive": true,
|
||||
"path": [],
|
||||
"message": "Too small: expected file to have >=5 bytes"
|
||||
"message": "Too small: expected file to have >5 bytes"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
@@ -53,9 +49,8 @@ test("failing validations", () => {
|
||||
"origin": "file",
|
||||
"code": "too_big",
|
||||
"maximum": 8,
|
||||
"inclusive": true,
|
||||
"path": [],
|
||||
"message": "Too big: expected file to have <=8 bytes"
|
||||
"message": "Too big: expected file to have <8 bytes"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
|
||||
-4
@@ -82,8 +82,6 @@ test("first party switch", () => {
|
||||
break;
|
||||
case "lazy":
|
||||
break;
|
||||
case "function":
|
||||
break;
|
||||
default:
|
||||
expectTypeOf(def).toEqualTypeOf<never>();
|
||||
}
|
||||
@@ -170,8 +168,6 @@ test("$ZodSchemaTypes", () => {
|
||||
break;
|
||||
case "lazy":
|
||||
break;
|
||||
case "function":
|
||||
break;
|
||||
|
||||
default:
|
||||
expectTypeOf(type).toEqualTypeOf<never>();
|
||||
|
||||
+31
-71
@@ -32,38 +32,38 @@ test("function inference 1", () => {
|
||||
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("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("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();
|
||||
@@ -130,46 +130,6 @@ test("valid function run", () => {
|
||||
});
|
||||
});
|
||||
|
||||
const args3 = [
|
||||
z.object({
|
||||
f1: z.number(),
|
||||
f2: z.string().nullable(),
|
||||
f3: z.array(z.boolean().optional()).optional(),
|
||||
}),
|
||||
] as const;
|
||||
const returns3 = z.union([z.string(), z.number()]);
|
||||
|
||||
const func3 = z.function({
|
||||
input: args3,
|
||||
output: returns3,
|
||||
});
|
||||
|
||||
test("function inference 3", () => {
|
||||
type func3 = (typeof func3)["_input"];
|
||||
|
||||
expectTypeOf<func3>().toEqualTypeOf<
|
||||
(arg: {
|
||||
f3?: (boolean | undefined)[] | undefined;
|
||||
f1: number;
|
||||
f2: string | null;
|
||||
}) => string | number
|
||||
>();
|
||||
});
|
||||
|
||||
test("valid function run", () => {
|
||||
const validFunc3Instance = func3.implement((_x) => {
|
||||
_x.f2;
|
||||
_x.f3![0];
|
||||
return "adf" as any;
|
||||
});
|
||||
|
||||
validFunc3Instance({
|
||||
f1: 21,
|
||||
f2: "asdf",
|
||||
f3: [true, false],
|
||||
});
|
||||
});
|
||||
|
||||
test("input validation error", () => {
|
||||
const schema = z.function({
|
||||
input: z.tuple([z.string()]),
|
||||
|
||||
+1
-70
@@ -302,29 +302,6 @@ test("z.record", () => {
|
||||
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>>();
|
||||
|
||||
// literal union keys
|
||||
const e = z.record(z.union([z.literal("a"), z.literal(0)]), z.string());
|
||||
type e = z.output<typeof e>;
|
||||
expectTypeOf<e>().toEqualTypeOf<Record<"a" | 0, string>>();
|
||||
expect(z.parse(e, { a: "hello", 0: "world" })).toEqual({
|
||||
a: "hello",
|
||||
0: "world",
|
||||
});
|
||||
|
||||
// TypeScript enum keys
|
||||
enum Enum {
|
||||
A = 0,
|
||||
B = "hi",
|
||||
}
|
||||
|
||||
const f = z.record(z.enum(Enum), z.string());
|
||||
type f = z.output<typeof f>;
|
||||
expectTypeOf<f>().toEqualTypeOf<Record<Enum, string>>();
|
||||
expect(z.parse(f, { [Enum.A]: "hello", [Enum.B]: "world" })).toEqual({
|
||||
[Enum.A]: "hello",
|
||||
[Enum.B]: "world",
|
||||
});
|
||||
});
|
||||
|
||||
test("z.map", () => {
|
||||
@@ -772,7 +749,7 @@ test("z.json", () => {
|
||||
test("z.promise", async () => {
|
||||
const a = z.promise(z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<Promise<string>>();
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
|
||||
expect(await z.safeParseAsync(a, Promise.resolve("hello"))).toMatchObject({
|
||||
success: true,
|
||||
@@ -809,37 +786,6 @@ test("isPlainObject", () => {
|
||||
expect(z.core.util.isPlainObject("string")).toEqual(false);
|
||||
expect(z.core.util.isPlainObject(123)).toEqual(false);
|
||||
expect(z.core.util.isPlainObject(Symbol())).toEqual(false);
|
||||
expect(z.core.util.isPlainObject({ constructor: "string" })).toEqual(true);
|
||||
expect(z.core.util.isPlainObject({ constructor: 123 })).toEqual(true);
|
||||
expect(z.core.util.isPlainObject({ constructor: null })).toEqual(true);
|
||||
expect(z.core.util.isPlainObject({ constructor: undefined })).toEqual(true);
|
||||
expect(z.core.util.isPlainObject({ constructor: true })).toEqual(true);
|
||||
expect(z.core.util.isPlainObject({ constructor: {} })).toEqual(true);
|
||||
expect(z.core.util.isPlainObject({ constructor: [] })).toEqual(true);
|
||||
});
|
||||
|
||||
test("shallowClone with constructor field", () => {
|
||||
const objWithConstructor = { constructor: "string", key: "value" };
|
||||
const cloned = z.core.util.shallowClone(objWithConstructor);
|
||||
|
||||
expect(cloned).toEqual(objWithConstructor);
|
||||
expect(cloned).not.toBe(objWithConstructor);
|
||||
expect(cloned.constructor).toBe("string");
|
||||
expect(cloned.key).toBe("value");
|
||||
|
||||
const testCases = [
|
||||
{ constructor: 123, data: "test" },
|
||||
{ constructor: null, data: "test" },
|
||||
{ constructor: true, data: "test" },
|
||||
{ constructor: {}, data: "test" },
|
||||
{ constructor: [], data: "test" },
|
||||
];
|
||||
|
||||
for (const testCase of testCases) {
|
||||
const clonedCase = z.core.util.shallowClone(testCase);
|
||||
expect(clonedCase).toEqual(testCase);
|
||||
expect(clonedCase).not.toBe(testCase);
|
||||
}
|
||||
});
|
||||
|
||||
test("def typing", () => {
|
||||
@@ -881,18 +827,3 @@ test("def typing", () => {
|
||||
z.string().catch("fallback").def.type satisfies "catch";
|
||||
z.file().def.type satisfies "file";
|
||||
});
|
||||
|
||||
test("runtime type property exists and returns correct values", () => {
|
||||
const stringSchema = z.string();
|
||||
expect(stringSchema.type).toBe("string");
|
||||
});
|
||||
|
||||
test("type narrowing works with type property", () => {
|
||||
type ArrayOrRecord = z.ZodArray<z.ZodString> | z.ZodRecord<z.ZodString, z.ZodAny>;
|
||||
const arraySchema = z.array(z.string()) as ArrayOrRecord;
|
||||
|
||||
if (arraySchema.type === "array") {
|
||||
expectTypeOf(arraySchema).toEqualTypeOf<z.ZodArray<z.ZodString>>();
|
||||
expect(arraySchema.element).toBeDefined();
|
||||
}
|
||||
});
|
||||
|
||||
-25
@@ -90,28 +90,3 @@ test("readonly", () => {
|
||||
const a = ["asdf"] as const;
|
||||
z.literal(a);
|
||||
});
|
||||
|
||||
test("literal pattern", () => {
|
||||
expect(z.literal(1.1)._zod.pattern).toMatchInlineSnapshot(`/\\^\\(1\\\\\\.1\\)\\$/`);
|
||||
|
||||
expect(z.templateLiteral([z.literal(1.1)]).safeParse("1.1")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": "1.1",
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
expect(z.templateLiteral([z.literal(1.1)]).safeParse("1n1")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^(1\\\\.1)$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
-15
@@ -84,18 +84,3 @@ test("nonoptional in object", () => {
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("encoding", () => {
|
||||
const schema = z.string().optional().nonoptional();
|
||||
expect(z.encode(schema, "hello")).toEqual("hello");
|
||||
expect(() => z.encode(schema, undefined as any)).toThrowErrorMatchingInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "nonoptional",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected nonoptional, received undefined"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
-23
@@ -114,29 +114,6 @@ test(".nonnegative() validation", () => {
|
||||
expect(() => schema.parse(-1)).toThrow();
|
||||
});
|
||||
|
||||
test("multipleOf", () => {
|
||||
const numbers = {
|
||||
number3: 5.123,
|
||||
number6: 5.123456,
|
||||
number7: 5.1234567,
|
||||
number8: 5.12345678,
|
||||
};
|
||||
|
||||
const schemas = {
|
||||
schema6: z.number().multipleOf(0.000001),
|
||||
schema7: z.number().multipleOf(0.0000001),
|
||||
};
|
||||
|
||||
expect(() => schemas.schema6.parse(numbers.number3)).not.toThrow();
|
||||
expect(() => schemas.schema6.parse(numbers.number6)).not.toThrow();
|
||||
expect(() => schemas.schema6.parse(numbers.number7)).toThrow();
|
||||
expect(() => schemas.schema6.parse(numbers.number8)).toThrow();
|
||||
expect(() => schemas.schema7.parse(numbers.number3)).not.toThrow();
|
||||
expect(() => schemas.schema7.parse(numbers.number6)).not.toThrow();
|
||||
expect(() => schemas.schema7.parse(numbers.number7)).not.toThrow();
|
||||
expect(() => schemas.schema7.parse(numbers.number8)).toThrow();
|
||||
});
|
||||
|
||||
test(".multipleOf() with positive divisor", () => {
|
||||
const schema = z.number().multipleOf(5);
|
||||
expect(schema.parse(15)).toEqual(15);
|
||||
|
||||
+2
-48
@@ -162,13 +162,13 @@ test("catchall overrides strict", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("optional keys are unset", () => {
|
||||
test("optional keys are unset", async () => {
|
||||
const SNamedEntity = z.object({
|
||||
id: z.string(),
|
||||
set: z.string().optional(),
|
||||
unset: z.string().optional(),
|
||||
});
|
||||
const result = SNamedEntity.parse({
|
||||
const result = await SNamedEntity.parse({
|
||||
id: "asdf",
|
||||
set: undefined,
|
||||
});
|
||||
@@ -261,21 +261,6 @@ test("inferred enum type", async () => {
|
||||
expectTypeOf<Enum>().toEqualTypeOf<"a" | "b">();
|
||||
});
|
||||
|
||||
test("z.keyof returns enum", () => {
|
||||
const User = z.object({ name: z.string(), age: z.number() });
|
||||
const keysSchema = z.keyof(User);
|
||||
expect(keysSchema.enum).toEqual({
|
||||
name: "name",
|
||||
age: "age",
|
||||
});
|
||||
expect(keysSchema._zod.def.entries).toEqual({
|
||||
name: "name",
|
||||
age: "age",
|
||||
});
|
||||
type Keys = z.infer<typeof keysSchema>;
|
||||
expectTypeOf<Keys>().toEqualTypeOf<"name" | "age">();
|
||||
});
|
||||
|
||||
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>;
|
||||
@@ -435,17 +420,6 @@ test("extend() should have power to override existing key", () => {
|
||||
expectTypeOf<PersonWithNumberAsLastName>().toEqualTypeOf<{ firstName: string; lastName: number }>();
|
||||
});
|
||||
|
||||
test("safeExtend() maintains refinements", () => {
|
||||
const schema = z.object({ name: z.string().min(1) });
|
||||
const extended = schema.safeExtend({ name: z.string().min(2) });
|
||||
expect(() => extended.parse({ name: "" })).toThrow();
|
||||
expect(extended.parse({ name: "ab" })).toEqual({ name: "ab" });
|
||||
type Extended = z.infer<typeof extended>;
|
||||
expectTypeOf<Extended>().toEqualTypeOf<{ name: string }>();
|
||||
// @ts-expect-error
|
||||
schema.safeExtend({ name: z.number() });
|
||||
});
|
||||
|
||||
test("passthrough index signature", () => {
|
||||
const a = z.object({ a: z.string() });
|
||||
type a = z.infer<typeof a>;
|
||||
@@ -587,23 +561,3 @@ test("index signature in shape", () => {
|
||||
|
||||
expectTypeOf<schema>().toEqualTypeOf<Record<string, string>>();
|
||||
});
|
||||
|
||||
test("extent() on object with refinements should throw", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.string(),
|
||||
})
|
||||
.refine(() => true);
|
||||
|
||||
expect(() => schema.extend({ b: z.string() })).toThrow();
|
||||
});
|
||||
|
||||
test("safeExtend() on object with refinements should not throw", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.string(),
|
||||
})
|
||||
.refine(() => true);
|
||||
|
||||
expect(() => schema.safeExtend({ b: z.string() })).not.toThrow();
|
||||
});
|
||||
|
||||
-13
@@ -121,16 +121,3 @@ test("pipe optionality inside objects", () => {
|
||||
e: string;
|
||||
}>();
|
||||
});
|
||||
|
||||
test("optional prop with pipe", () => {
|
||||
const schema = z.object({
|
||||
id: z
|
||||
.union([z.number(), z.string().nullish()])
|
||||
.transform((val) => (val === null || val === undefined ? val : Number(val)))
|
||||
.pipe(z.number())
|
||||
.optional(),
|
||||
});
|
||||
|
||||
schema.parse({});
|
||||
schema.parse({}, { jitless: true });
|
||||
});
|
||||
|
||||
-193
@@ -145,196 +145,3 @@ test("partial with mask -- ignore falsy values", async () => {
|
||||
masked.parse({ country: "US" });
|
||||
await masked.parseAsync({ country: "US" });
|
||||
});
|
||||
|
||||
test("catch/prefault/default", () => {
|
||||
const mySchema = z.object({
|
||||
a: z.string().catch("catch value").optional(),
|
||||
b: z.string().default("default value").optional(),
|
||||
c: z.string().prefault("prefault value").optional(),
|
||||
d: z.string().catch("catch value"),
|
||||
e: z.string().default("default value"),
|
||||
f: z.string().prefault("prefault value"),
|
||||
});
|
||||
|
||||
expect(mySchema.parse({})).toMatchInlineSnapshot(`
|
||||
{
|
||||
"b": "default value",
|
||||
"c": "prefault value",
|
||||
"d": "catch value",
|
||||
"e": "default value",
|
||||
"f": "prefault value",
|
||||
}
|
||||
`);
|
||||
|
||||
expect(mySchema.parse({}, { jitless: true })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"b": "default value",
|
||||
"c": "prefault value",
|
||||
"d": "catch value",
|
||||
"e": "default value",
|
||||
"f": "prefault value",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("handleOptionalObjectResult branches", () => {
|
||||
const mySchema = z.object({
|
||||
// Branch: input[key] === undefined, key not in input, caught error
|
||||
caughtMissing: z.string().catch("caught").optional(),
|
||||
// Branch: input[key] === undefined, key in input, caught error
|
||||
caughtUndefined: z.string().catch("caught").optional(),
|
||||
// Branch: input[key] === undefined, key not in input, validation issues
|
||||
issueMissing: z.string().min(5).optional(),
|
||||
// Branch: input[key] === undefined, key in input, validation issues
|
||||
issueUndefined: z.string().min(5).optional(),
|
||||
// Branch: input[key] === undefined, validation returns undefined
|
||||
validUndefined: z.string().optional(),
|
||||
// Branch: input[key] === undefined, non-undefined result (default/transform)
|
||||
defaultValue: z.string().default("default").optional(),
|
||||
// Branch: input[key] defined, caught error
|
||||
caughtDefined: z.string().catch("caught").optional(),
|
||||
// Branch: input[key] defined, validation issues
|
||||
issueDefined: z.string().min(5).optional(),
|
||||
// Branch: input[key] defined, validation returns undefined
|
||||
validDefinedUndefined: z
|
||||
.string()
|
||||
.transform(() => undefined)
|
||||
.optional(),
|
||||
// Branch: input[key] defined, non-undefined value
|
||||
validDefined: z.string().optional(),
|
||||
});
|
||||
|
||||
// Test input[key] === undefined cases
|
||||
const result1 = mySchema.parse(
|
||||
{
|
||||
// caughtMissing: not present (key not in input)
|
||||
caughtUndefined: undefined, // key in input
|
||||
// issueMissing: not present (key not in input)
|
||||
issueUndefined: undefined, // key in input
|
||||
validUndefined: undefined,
|
||||
// defaultValue: not present, will get default
|
||||
},
|
||||
{ jitless: true }
|
||||
);
|
||||
|
||||
expect(result1).toEqual({
|
||||
caughtUndefined: undefined,
|
||||
issueUndefined: undefined,
|
||||
validUndefined: undefined,
|
||||
defaultValue: "default",
|
||||
});
|
||||
|
||||
// Test input[key] defined cases (successful)
|
||||
const result2 = mySchema.parse(
|
||||
{
|
||||
caughtDefined: 123, // invalid type, should catch
|
||||
validDefinedUndefined: "test", // transforms to undefined
|
||||
validDefined: "valid", // valid value
|
||||
},
|
||||
{ jitless: true }
|
||||
);
|
||||
|
||||
expect(result2).toEqual({
|
||||
caughtDefined: "caught",
|
||||
validDefinedUndefined: undefined,
|
||||
validDefined: "valid",
|
||||
defaultValue: "default",
|
||||
});
|
||||
|
||||
// Test validation issues are properly reported (input[key] defined, validation fails)
|
||||
expect(() =>
|
||||
mySchema.parse(
|
||||
{
|
||||
issueDefined: "abc", // too short
|
||||
},
|
||||
{ jitless: true }
|
||||
)
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
test("fastpass vs non-fastpass consistency", () => {
|
||||
const mySchema = z.object({
|
||||
caughtMissing: z.string().catch("caught").optional(),
|
||||
caughtUndefined: z.string().catch("caught").optional(),
|
||||
issueMissing: z.string().min(5).optional(),
|
||||
issueUndefined: z.string().min(5).optional(),
|
||||
validUndefined: z.string().optional(),
|
||||
defaultValue: z.string().default("default").optional(),
|
||||
caughtDefined: z.string().catch("caught").optional(),
|
||||
validDefinedUndefined: z
|
||||
.string()
|
||||
.transform(() => undefined)
|
||||
.optional(),
|
||||
validDefined: z.string().optional(),
|
||||
});
|
||||
|
||||
const input = {
|
||||
caughtUndefined: undefined,
|
||||
issueUndefined: undefined,
|
||||
validUndefined: undefined,
|
||||
caughtDefined: 123,
|
||||
validDefinedUndefined: "test",
|
||||
validDefined: "valid",
|
||||
};
|
||||
|
||||
// Test both paths produce identical results
|
||||
const jitlessResult = mySchema.parse(input, { jitless: true });
|
||||
const fastpassResult = mySchema.parse(input);
|
||||
|
||||
expect(jitlessResult).toEqual(fastpassResult);
|
||||
expect(jitlessResult).toEqual({
|
||||
caughtUndefined: undefined,
|
||||
issueUndefined: undefined,
|
||||
validUndefined: undefined,
|
||||
defaultValue: "default",
|
||||
caughtDefined: "caught",
|
||||
validDefinedUndefined: undefined,
|
||||
validDefined: "valid",
|
||||
});
|
||||
});
|
||||
|
||||
test("optional with check", () => {
|
||||
const baseSchema = z
|
||||
.string()
|
||||
.optional()
|
||||
.check(({ value, ...ctx }) => {
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
input: value,
|
||||
message: "message",
|
||||
});
|
||||
});
|
||||
|
||||
// this correctly fails
|
||||
expect(baseSchema.safeParse(undefined)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "message",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
const schemaObject = z.object({
|
||||
date: baseSchema,
|
||||
});
|
||||
|
||||
expect(schemaObject.safeParse({ date: undefined })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "message",
|
||||
"path": [
|
||||
"date"
|
||||
]
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
+5
-5
@@ -114,14 +114,14 @@ test("pick/omit/required/partial - do not allow unknown keys", () => {
|
||||
age: z.number(),
|
||||
});
|
||||
|
||||
expect(() => schema.pick({ name: true, asdf: true }).safeParse({})).toThrow();
|
||||
expect(() => schema.pick({ name: true, asdf: true })).toThrow();
|
||||
|
||||
// @ts-expect-error
|
||||
expect(() => schema.pick({ $unknown: true }).safeParse({})).toThrow();
|
||||
expect(() => schema.pick({ $unknown: true })).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => schema.omit({ $unknown: true }).safeParse({})).toThrow();
|
||||
expect(() => schema.omit({ $unknown: true })).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => schema.required({ $unknown: true }).safeParse({})).toThrow();
|
||||
expect(() => schema.required({ $unknown: true })).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => schema.partial({ $unknown: true }).safeParse({})).toThrow();
|
||||
expect(() => schema.partial({ $unknown: true })).toThrow();
|
||||
});
|
||||
|
||||
+5
-25
@@ -45,6 +45,11 @@ test("continue on non-fatal errors", () => {
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "A"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "B"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
@@ -74,28 +79,3 @@ test("break on fatal errors", () => {
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("reverse parsing with pipe", () => {
|
||||
const schema = z.string().pipe(z.string());
|
||||
|
||||
// Reverse direction: default should NOT be applied
|
||||
expect(z.safeDecode(schema, "asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": "asdf",
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
expect(z.safeEncode(schema, "asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": "asdf",
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("reverse parsing with pipe", () => {
|
||||
const schema = z.string().transform((val) => val.length);
|
||||
|
||||
// should throw
|
||||
expect(() => z.encode(schema, 1234)).toThrow();
|
||||
});
|
||||
|
||||
-37
@@ -35,40 +35,3 @@ test("prefault inside object", () => {
|
||||
email: string;
|
||||
}>();
|
||||
});
|
||||
|
||||
test("object schema with prefault should return shallow clone", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.string(),
|
||||
})
|
||||
.default({ a: "x" });
|
||||
const result1 = schema.parse(undefined);
|
||||
const result2 = schema.parse(undefined);
|
||||
expect(result1).not.toBe(result2);
|
||||
expect(result1).toEqual(result2);
|
||||
});
|
||||
|
||||
test("direction-aware prefault", () => {
|
||||
const schema = z.string().prefault("hello");
|
||||
|
||||
// Forward direction (regular parse): prefault should be applied
|
||||
expect(schema.parse(undefined)).toBe("hello");
|
||||
|
||||
// Reverse direction (encode): prefault should NOT be applied, undefined should fail validation
|
||||
expect(z.safeEncode(schema, undefined as any)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
// But valid values should still work in reverse
|
||||
expect(z.encode(schema, "world")).toBe("world");
|
||||
});
|
||||
|
||||
+21
-5
@@ -73,18 +73,17 @@ test("preprocess ctx.addIssue with parse", () => {
|
||||
`);
|
||||
});
|
||||
|
||||
test("preprocess ctx.addIssue fatal by default", () => {
|
||||
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(1);
|
||||
expect(result.error!.issues).toHaveLength(2);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
@@ -92,6 +91,12 @@ test("preprocess ctx.addIssue fatal by default", () => {
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
@@ -170,7 +175,7 @@ test("z.NEVER in preprocess", () => {
|
||||
expectTypeOf<foo>().toEqualTypeOf<number>();
|
||||
const result = foo.safeParse(undefined);
|
||||
|
||||
expect(result.error!.issues).toHaveLength(1);
|
||||
expect(result.error!.issues).toHaveLength(2);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
@@ -178,6 +183,12 @@ test("z.NEVER in preprocess", () => {
|
||||
"code": "custom",
|
||||
"message": "bad",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected number, received object"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
@@ -269,9 +280,14 @@ test("perform transform with non-fatal issues", () => {
|
||||
.transform((val) => val.length)
|
||||
.pipe(z.number())
|
||||
.refine((_) => false);
|
||||
expect(A.safeParse("asdfasdf").error!.issues).toHaveLength(1);
|
||||
expect(A.safeParse("asdfasdf").error!.issues).toHaveLength(2);
|
||||
expect(A.safeParse("asdfasdf").error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ const promSchema = z.promise(
|
||||
|
||||
test("promise inference", () => {
|
||||
type promSchemaType = z.infer<typeof promSchema>;
|
||||
expectTypeOf<promSchemaType>().toEqualTypeOf<Promise<{ name: string; age: number }>>();
|
||||
expectTypeOf<promSchemaType>().toEqualTypeOf<{ name: string; age: number }>();
|
||||
});
|
||||
|
||||
test("promise parsing success", async () => {
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ test("flat inference", () => {
|
||||
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<Promise<string>>();
|
||||
expectTypeOf<typeof readonlyPromise._output>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
// test("deep inference", () => {
|
||||
|
||||
+10
-156
@@ -8,28 +8,16 @@ test("type inference", () => {
|
||||
const recordWithEnumKeys = z.record(z.enum(["Tuna", "Salmon"]), z.string());
|
||||
type recordWithEnumKeys = z.infer<typeof recordWithEnumKeys>;
|
||||
|
||||
const recordWithLiteralKey = z.record(z.literal(["Tuna", "Salmon", 21]), z.string());
|
||||
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.literal(21)]),
|
||||
z.string()
|
||||
);
|
||||
const recordWithLiteralUnionKeys = z.record(z.union([z.literal("Tuna"), z.literal("Salmon")]), z.string());
|
||||
type recordWithLiteralUnionKeys = z.infer<typeof recordWithLiteralUnionKeys>;
|
||||
|
||||
enum Enum {
|
||||
Tuna = 0,
|
||||
Salmon = "Shark",
|
||||
}
|
||||
|
||||
const recordWithTypescriptEnum = z.record(z.enum(Enum), z.string());
|
||||
type recordWithTypescriptEnum = z.infer<typeof recordWithTypescriptEnum>;
|
||||
|
||||
expectTypeOf<booleanRecord>().toEqualTypeOf<Record<string, boolean>>();
|
||||
expectTypeOf<recordWithEnumKeys>().toEqualTypeOf<Record<"Tuna" | "Salmon", string>>();
|
||||
expectTypeOf<recordWithLiteralKey>().toEqualTypeOf<Record<"Tuna" | "Salmon" | 21, string>>();
|
||||
expectTypeOf<recordWithLiteralUnionKeys>().toEqualTypeOf<Record<"Tuna" | "Salmon" | 21, string>>();
|
||||
expectTypeOf<recordWithTypescriptEnum>().toEqualTypeOf<Record<Enum, string>>();
|
||||
expectTypeOf<recordWithLiteralKey>().toEqualTypeOf<Record<"Tuna" | "Salmon", string>>();
|
||||
expectTypeOf<recordWithLiteralUnionKeys>().toEqualTypeOf<Record<"Tuna" | "Salmon", string>>();
|
||||
});
|
||||
|
||||
test("enum exhaustiveness", () => {
|
||||
@@ -76,76 +64,14 @@ test("enum exhaustiveness", () => {
|
||||
`);
|
||||
});
|
||||
|
||||
test("typescript enum exhaustiveness", () => {
|
||||
enum BigFish {
|
||||
Tuna = 0,
|
||||
Salmon = "Shark",
|
||||
}
|
||||
|
||||
const schema = z.record(z.enum(BigFish), z.string());
|
||||
const value = {
|
||||
[BigFish.Tuna]: "asdf",
|
||||
[BigFish.Salmon]: "asdf",
|
||||
};
|
||||
|
||||
expect(schema.parse(value)).toEqual(value);
|
||||
|
||||
expect(schema.safeParse({ [BigFish.Tuna]: "asdf", [BigFish.Salmon]: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": [
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Unrecognized key: \\"Trout\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse({ [BigFish.Tuna]: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"Shark"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse({ [BigFish.Salmon]: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
0
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("literal exhaustiveness", () => {
|
||||
const schema = z.record(z.literal(["Tuna", "Salmon", 21]), z.string());
|
||||
const schema = z.record(z.literal(["Tuna", "Salmon"]), z.string());
|
||||
schema.parse({
|
||||
Tuna: "asdf",
|
||||
Salmon: "asdf",
|
||||
21: "asdf",
|
||||
});
|
||||
|
||||
expect(schema.safeParse({ Tuna: "asdf", Salmon: "asdf", 21: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
expect(schema.safeParse({ Tuna: "asdf", Salmon: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
@@ -170,14 +96,6 @@ test("literal exhaustiveness", () => {
|
||||
"Salmon"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
21
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
@@ -225,14 +143,13 @@ test("pipe exhaustiveness", () => {
|
||||
});
|
||||
|
||||
test("union exhaustiveness", () => {
|
||||
const schema = z.record(z.union([z.literal("Tuna"), z.literal("Salmon"), z.literal(21)]), z.string());
|
||||
expect(schema.parse({ Tuna: "asdf", Salmon: "asdf", 21: "asdf" })).toEqual({
|
||||
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",
|
||||
21: "asdf",
|
||||
});
|
||||
|
||||
expect(schema.safeParse({ Tuna: "asdf", Salmon: "asdf", 21: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
expect(schema.safeParse({ Tuna: "asdf", Salmon: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
@@ -257,14 +174,6 @@ test("union exhaustiveness", () => {
|
||||
"Salmon"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
21
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
@@ -427,62 +336,7 @@ test("partial record", () => {
|
||||
type schema = z.infer<typeof schema>;
|
||||
expectTypeOf<schema>().toEqualTypeOf<Partial<Record<string, string>>>();
|
||||
|
||||
const Keys = z.enum(["id", "name", "email"]); //.or(z.never());
|
||||
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>>>();
|
||||
|
||||
Person.parse({
|
||||
id: "123",
|
||||
// name: "John",
|
||||
// email: "john@example.com",
|
||||
});
|
||||
|
||||
Person.parse({
|
||||
// id: "123",
|
||||
// name: "John",
|
||||
email: "john@example.com",
|
||||
});
|
||||
|
||||
expect(Person.def.keyType._zod.def.type).toEqual("enum");
|
||||
});
|
||||
|
||||
test("partialRecord with z.literal([key, ...])", () => {
|
||||
const Keys = z.literal(["id", "name", "email"]);
|
||||
const schema = z.partialRecord(Keys, z.string());
|
||||
type Schema = z.infer<typeof schema>;
|
||||
expectTypeOf<Schema>().toEqualTypeOf<Partial<Record<"id" | "name" | "email", string>>>();
|
||||
|
||||
// Should parse valid partials
|
||||
expect(schema.parse({})).toEqual({});
|
||||
expect(schema.parse({ id: "1" })).toEqual({ id: "1" });
|
||||
expect(schema.parse({ name: "n", email: "e@example.com" })).toEqual({ name: "n", email: "e@example.com" });
|
||||
|
||||
// Should fail with unrecognized key, error checked via inline snapshot
|
||||
expect(schema.safeParse({ foo: "bar" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_key",
|
||||
"origin": "record",
|
||||
"issues": [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"id",
|
||||
"name",
|
||||
"email"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid option: expected one of \\"id\\"|\\"name\\"|\\"email\\""
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
"foo"
|
||||
],
|
||||
"message": "Invalid key in record"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
-226
@@ -260,127 +260,6 @@ test("mutual recursion with meta", () => {
|
||||
expectTypeOf<B>().toEqualTypeOf<_B>();
|
||||
});
|
||||
|
||||
test("intersection with recursive types", () => {
|
||||
const A = z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal("CONTAINER"),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("SCREEN"),
|
||||
config: z.object({ x: z.number(), y: z.number() }),
|
||||
}),
|
||||
]);
|
||||
// type A = z.infer<typeof A>;
|
||||
|
||||
const B = z.object({
|
||||
get children() {
|
||||
return z.array(C).optional();
|
||||
},
|
||||
});
|
||||
// type B = z.infer<typeof B>;
|
||||
|
||||
const C = z.intersection(A, B);
|
||||
type C = z.infer<typeof C>;
|
||||
|
||||
type _C = (
|
||||
| {
|
||||
type: "CONTAINER";
|
||||
}
|
||||
| {
|
||||
type: "SCREEN";
|
||||
config: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
}
|
||||
) & {
|
||||
children?: _C[] | undefined;
|
||||
};
|
||||
expectTypeOf<C>().toEqualTypeOf<_C>();
|
||||
});
|
||||
|
||||
test("object utilities with recursive types", () => {
|
||||
const NodeBase = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
get children() {
|
||||
return z.array(Node).optional();
|
||||
},
|
||||
});
|
||||
|
||||
// Test extend
|
||||
const NodeOne = NodeBase.extend({
|
||||
name: z.literal("nodeOne"),
|
||||
get children() {
|
||||
return z.array(Node);
|
||||
},
|
||||
});
|
||||
|
||||
const NodeTwo = NodeBase.extend({
|
||||
name: z.literal("nodeTwo"),
|
||||
get children() {
|
||||
return z.array(Node);
|
||||
},
|
||||
});
|
||||
|
||||
// Test pick
|
||||
const PickedNode = NodeBase.pick({ id: true, name: true });
|
||||
|
||||
// Test omit
|
||||
const OmittedNode = NodeBase.omit({ children: true });
|
||||
|
||||
// Test merge
|
||||
const ExtraProps = {
|
||||
metadata: z.string(),
|
||||
get parent() {
|
||||
return Node.optional();
|
||||
},
|
||||
};
|
||||
const MergedNode = NodeBase.extend(ExtraProps);
|
||||
|
||||
// Test partial
|
||||
const PartialNode = NodeBase.partial();
|
||||
const PartialMaskedNode = NodeBase.partial({ name: true });
|
||||
|
||||
// Test required (assuming NodeBase has optional fields)
|
||||
const OptionalNodeBase = z.object({
|
||||
id: z.string().optional(),
|
||||
name: z.string().optional(),
|
||||
get children() {
|
||||
return z.array(Node).optional();
|
||||
},
|
||||
});
|
||||
const RequiredNode = OptionalNodeBase.required();
|
||||
const RequiredMaskedNode = OptionalNodeBase.required({ id: true });
|
||||
|
||||
const Node = z.union([
|
||||
NodeOne,
|
||||
NodeTwo,
|
||||
PickedNode,
|
||||
OmittedNode,
|
||||
MergedNode,
|
||||
PartialNode,
|
||||
PartialMaskedNode,
|
||||
RequiredNode,
|
||||
RequiredMaskedNode,
|
||||
]);
|
||||
});
|
||||
|
||||
test("tuple with recursive types", () => {
|
||||
const TaskListNodeSchema = z.strictObject({
|
||||
type: z.literal("taskList"),
|
||||
get content() {
|
||||
return z.array(z.tuple([TaskListNodeSchema, z.union([TaskListNodeSchema])])).min(1);
|
||||
},
|
||||
});
|
||||
type TaskListNodeSchema = z.infer<typeof TaskListNodeSchema>;
|
||||
type _TaskListNodeSchema = {
|
||||
type: "taskList";
|
||||
content: [_TaskListNodeSchema, _TaskListNodeSchema][];
|
||||
};
|
||||
expectTypeOf<TaskListNodeSchema>().toEqualTypeOf<_TaskListNodeSchema>();
|
||||
});
|
||||
|
||||
test("recursion compatibility", () => {
|
||||
// array
|
||||
const A = z.object({
|
||||
@@ -446,68 +325,6 @@ test("recursion compatibility", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("recursive object with .check()", () => {
|
||||
const Category = z
|
||||
.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
get subcategories() {
|
||||
return z.array(Category).optional();
|
||||
},
|
||||
})
|
||||
.check((ctx) => {
|
||||
// Check for duplicate IDs among direct subcategories
|
||||
if (ctx.value.subcategories) {
|
||||
const siblingIds = new Set<string>();
|
||||
ctx.value.subcategories.forEach((sub, index) => {
|
||||
if (siblingIds.has(sub.id)) {
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
message: `Duplicate sibling ID found: ${sub.id}`,
|
||||
path: ["subcategories", index, "id"],
|
||||
input: ctx.value,
|
||||
});
|
||||
}
|
||||
siblingIds.add(sub.id);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Valid - siblings have unique IDs
|
||||
const validData = {
|
||||
id: "electronics",
|
||||
name: "Electronics",
|
||||
subcategories: [
|
||||
{
|
||||
id: "computers",
|
||||
name: "Computers",
|
||||
subcategories: [
|
||||
{ id: "laptops", name: "Laptops" },
|
||||
{ id: "desktops", name: "Desktops" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "phones",
|
||||
name: "Phones",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Invalid - duplicate sibling IDs
|
||||
const invalidData = {
|
||||
id: "electronics",
|
||||
name: "Electronics",
|
||||
subcategories: [
|
||||
{ id: "computers", name: "Computers" },
|
||||
{ id: "phones", name: "Phones" },
|
||||
{ id: "computers", name: "Computers Again" }, // Duplicate at index 2
|
||||
],
|
||||
};
|
||||
|
||||
expect(() => Category.parse(validData)).not.toThrow();
|
||||
expect(() => Category.parse(invalidData)).toThrow();
|
||||
});
|
||||
|
||||
// biome-ignore lint: sadf
|
||||
export type RecursiveA = z.ZodUnion<
|
||||
[
|
||||
@@ -537,46 +354,3 @@ export type RecursiveA = z.ZodUnion<
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
test("recursive type with `id` meta", () => {
|
||||
const AType = z.object({
|
||||
type: z.literal("a"),
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const BType = z.object({
|
||||
type: z.literal("b"),
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const CType = z.object({
|
||||
type: z.literal("c"),
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const Schema = z.object({
|
||||
type: z.literal("special").meta({ description: "Type" }),
|
||||
config: z.object({
|
||||
title: z.string().meta({ description: "Title" }),
|
||||
get elements() {
|
||||
return z.array(z.discriminatedUnion("type", [AType, BType, CType])).meta({
|
||||
id: "SpecialElements",
|
||||
title: "SpecialElements",
|
||||
description: "Array of elements",
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
Schema.parse({
|
||||
type: "special",
|
||||
config: {
|
||||
title: "Special",
|
||||
elements: [
|
||||
{ type: "a", name: "John" },
|
||||
{ type: "b", name: "Jane" },
|
||||
{ type: "c", name: "Jim" },
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
+5
-78
@@ -167,8 +167,8 @@ describe("early termination options", () => {
|
||||
});
|
||||
|
||||
describe("custom error paths", () => {
|
||||
test("should use custom path in error message", () => {
|
||||
const result = z
|
||||
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" });
|
||||
@@ -252,79 +252,6 @@ describe("superRefine functionality", () => {
|
||||
await expect(Strings.parseAsync(validArray)).resolves.toEqual(validArray);
|
||||
});
|
||||
|
||||
test("should test continuability of custom issues", () => {
|
||||
// Default continue behavior - allows subsequent refinements
|
||||
const defaultContinue = z
|
||||
.string()
|
||||
.superRefine((_, ctx) => {
|
||||
ctx.addIssue({ code: "custom", message: "First issue" });
|
||||
})
|
||||
.refine(() => false, "Second issue");
|
||||
|
||||
expect(defaultContinue.safeParse("test")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "First issue",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Second issue"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
// Explicit continue: false - prevents subsequent refinements
|
||||
const explicitContinueFalse = z
|
||||
.string()
|
||||
.superRefine((_, ctx) => {
|
||||
ctx.addIssue({ code: "custom", message: "First issue", continue: false });
|
||||
})
|
||||
.refine(() => false, "Second issue");
|
||||
|
||||
expect(explicitContinueFalse.safeParse("test")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "First issue",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
// Multiple issues in same refinement - both always added regardless of continue
|
||||
const multipleInSame = z.string().superRefine((_, ctx) => {
|
||||
ctx.addIssue({ code: "custom", message: "First", continue: false });
|
||||
ctx.addIssue({ code: "custom", message: "Second" });
|
||||
});
|
||||
|
||||
expect(multipleInSame.safeParse("test")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "First",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Second",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("should accept string as shorthand for custom error message", () => {
|
||||
const schema = z.string().superRefine((_, ctx) => {
|
||||
ctx.addIssue("bad stuff");
|
||||
@@ -504,9 +431,9 @@ test("when", () => {
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
// console.log("running check...");
|
||||
// console.log(data);
|
||||
// console.log(data.password);
|
||||
console.log("running check...");
|
||||
console.log(data);
|
||||
console.log(data.password);
|
||||
return data.password === data.confirmPassword;
|
||||
},
|
||||
{
|
||||
|
||||
+1
-5
@@ -19,10 +19,6 @@ test("globalRegistry", () => {
|
||||
expect(z.globalRegistry.has(a)).toEqual(false);
|
||||
});
|
||||
|
||||
test("globalRegistry is singleton and attached to globalThis", () => {
|
||||
expect(z.globalRegistry).toBe((globalThis as any).__zod_globalRegistry);
|
||||
});
|
||||
|
||||
test("z.registry", () => {
|
||||
const fieldRegistry = z.registry<{ name: string; description: string }>();
|
||||
|
||||
@@ -168,7 +164,7 @@ test("loose examples", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("function meta without replacement", () => {
|
||||
test("function meta witout replacement", () => {
|
||||
const myReg = z.registry<{
|
||||
defaulter: (arg: string, test: boolean) => number;
|
||||
}>();
|
||||
|
||||
+3
-5
@@ -39,7 +39,7 @@ test("valid parse async", async () => {
|
||||
expect(result.data!.has("second")).toEqual(true);
|
||||
expect(result.data!.has("third")).toEqual(false);
|
||||
|
||||
const asyncResult = stringSet.safeParse(new Set(["first", "second"]));
|
||||
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);
|
||||
@@ -155,8 +155,7 @@ test("min/max", async () => {
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected set to have >=4 items",
|
||||
"message": "Too small: expected set to have >4 items",
|
||||
"minimum": 4,
|
||||
"origin": "set",
|
||||
"path": [],
|
||||
@@ -170,9 +169,8 @@ test("min/max", async () => {
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 5,
|
||||
"message": "Too big: expected set to have <=5 items",
|
||||
"message": "Too big: expected set to have <5 items",
|
||||
"origin": "set",
|
||||
"path": [],
|
||||
},
|
||||
|
||||
-16
@@ -107,19 +107,3 @@ test("z.stringFormat", () => {
|
||||
`/\\^\\(\\?:\\\\d\\{14,19\\}\\|\\\\d\\{4\\}\\(\\?: \\\\d\\{3,6\\}\\)\\{2,4\\}\\|\\\\d\\{4\\}\\(\\?:-\\\\d\\{3,6\\}\\)\\{2,4\\}\\)\\$/u`
|
||||
);
|
||||
});
|
||||
|
||||
test("z.hex", () => {
|
||||
const hexSchema = z.hex();
|
||||
|
||||
// Valid hex strings
|
||||
expect(hexSchema.safeParse("").success).toBe(true); // Empty string is valid hex
|
||||
expect(hexSchema.safeParse("123abc").success).toBe(true);
|
||||
expect(hexSchema.safeParse("DEADBEEF").success).toBe(true);
|
||||
expect(hexSchema.safeParse("0123456789abcdefABCDEF").success).toBe(true);
|
||||
|
||||
// Invalid hex strings
|
||||
expect(hexSchema.safeParse("xyz").success).toBe(false);
|
||||
expect(hexSchema.safeParse("123g").success).toBe(false);
|
||||
expect(hexSchema.safeParse("hello world").success).toBe(false);
|
||||
expect(hexSchema.safeParse("123-abc").success).toBe(false);
|
||||
});
|
||||
|
||||
+5
-276
@@ -318,83 +318,6 @@ test("url validations", () => {
|
||||
expect(() => url.parse("https://")).toThrow();
|
||||
});
|
||||
|
||||
test("url preserves original input", () => {
|
||||
const url = z.string().url();
|
||||
|
||||
// Test the specific case from the user report
|
||||
const input = "https://example.com?key=NUXOmHqWNVTapJkJJHw8BfD155AuqhH_qju_5fNmQ4ZHV7u8";
|
||||
const output = url.parse(input);
|
||||
expect(output).toBe(input); // Should preserve the original input exactly
|
||||
|
||||
// Test other cases where URL constructor would normalize
|
||||
expect(url.parse("https://example.com?foo=bar")).toBe("https://example.com?foo=bar");
|
||||
expect(url.parse("http://example.com?test=123")).toBe("http://example.com?test=123");
|
||||
expect(url.parse("https://sub.example.com?param=value&other=data")).toBe(
|
||||
"https://sub.example.com?param=value&other=data"
|
||||
);
|
||||
|
||||
// Test cases with trailing slashes are preserved
|
||||
expect(url.parse("https://example.com/")).toBe("https://example.com/");
|
||||
expect(url.parse("https://example.com/path/")).toBe("https://example.com/path/");
|
||||
|
||||
// Test cases with paths and query parameters
|
||||
expect(url.parse("https://example.com/path?query=param")).toBe("https://example.com/path?query=param");
|
||||
});
|
||||
|
||||
test("url trims whitespace", () => {
|
||||
const url = z.string().url();
|
||||
|
||||
// Test trimming whitespace from URLs
|
||||
expect(url.parse(" https://example.com ")).toBe("https://example.com");
|
||||
expect(url.parse(" https://example.com/path?query=param ")).toBe("https://example.com/path?query=param");
|
||||
expect(url.parse("\t\nhttps://example.com\t\n")).toBe("https://example.com");
|
||||
expect(url.parse(" https://example.com?key=value ")).toBe("https://example.com?key=value");
|
||||
|
||||
// Test that URLs without extra whitespace are unchanged
|
||||
expect(url.parse("https://example.com")).toBe("https://example.com");
|
||||
expect(url.parse("https://example.com/path")).toBe("https://example.com/path");
|
||||
});
|
||||
|
||||
test("url normalize flag", () => {
|
||||
const normalizeUrl = z.url({ normalize: true });
|
||||
const preserveUrl = z.url(); // normalize: false/undefined by default
|
||||
|
||||
// Test that normalize flag causes URL normalization
|
||||
expect(normalizeUrl.parse("https://example.com?key=value")).toBe("https://example.com/?key=value");
|
||||
expect(normalizeUrl.parse("http://example.com?test=123")).toBe("http://example.com/?test=123");
|
||||
|
||||
// Test with already normalized URLs
|
||||
expect(normalizeUrl.parse("https://example.com/")).toBe("https://example.com/");
|
||||
expect(normalizeUrl.parse("https://example.com/path?query=param")).toBe("https://example.com/path?query=param");
|
||||
|
||||
// Test complex URLs with normalization
|
||||
expect(normalizeUrl.parse("https://example.com/../?key=value")).toBe("https://example.com/?key=value");
|
||||
expect(normalizeUrl.parse("https://example.com/./path?key=value")).toBe("https://example.com/path?key=value");
|
||||
|
||||
// Compare with non-normalize behavior
|
||||
expect(preserveUrl.parse("https://example.com?key=value")).toBe("https://example.com?key=value");
|
||||
expect(preserveUrl.parse("http://example.com?test=123")).toBe("http://example.com?test=123");
|
||||
|
||||
// Test trimming with normalize
|
||||
expect(normalizeUrl.parse(" https://example.com?key=value ")).toBe("https://example.com/?key=value");
|
||||
expect(preserveUrl.parse(" https://example.com?key=value ")).toBe("https://example.com?key=value");
|
||||
});
|
||||
|
||||
test("url normalize with hostname and protocol constraints", () => {
|
||||
const constrainedNormalizeUrl = z.url({
|
||||
normalize: true,
|
||||
protocol: /^https$/,
|
||||
hostname: /^example\.com$/,
|
||||
});
|
||||
|
||||
// Test that normalization works with constraints
|
||||
expect(constrainedNormalizeUrl.parse("https://example.com?key=value")).toBe("https://example.com/?key=value");
|
||||
|
||||
// Test that constraints are still enforced
|
||||
expect(() => constrainedNormalizeUrl.parse("http://example.com?key=value")).toThrow();
|
||||
expect(() => constrainedNormalizeUrl.parse("https://other.com?key=value")).toThrow();
|
||||
});
|
||||
|
||||
test("httpurl", () => {
|
||||
const httpUrl = z.url({
|
||||
protocol: /^https?$/,
|
||||
@@ -527,7 +450,6 @@ test("good uuid", () => {
|
||||
"9491d710-3185-5e06-8ea0-6a2f275345e0",
|
||||
"9491d710-3185-5e06-9ea0-6a2f275345e0",
|
||||
"00000000-0000-0000-0000-000000000000",
|
||||
"ffffffff-ffff-ffff-ffff-ffffffffffff",
|
||||
];
|
||||
|
||||
for (const goodUuid of goodUuids) {
|
||||
@@ -542,10 +464,11 @@ test(`bad uuid`, () => {
|
||||
"9491d710-3185-0e06-bea0-6a2f275345e0",
|
||||
"9491d710-3185-5e06-0ea0-6a2f275345e0",
|
||||
"d89e7b01-7598-ed11-9d7a-0022489382fd", // new sequential id
|
||||
"b3ce60f8-e8b9-40f5-1150-172ede56ff74", // Variant 0 - RFC 9562/4122: Reserved, NCS backward compatibility
|
||||
"92e76bf9-28b3-4730-cd7f-cb6bc51f8c09", // Variant 2 - RFC 9562/4122: Reserved, Microsoft Corporation backward compatibility
|
||||
"b3ce60f8-e8b9-40f5-1150-172ede56ff74", // Variant 0 - RFC 4122: Reserved, NCS backward compatibility
|
||||
"92e76bf9-28b3-4730-cd7f-cb6bc51f8c09", // Variant 2 - RFC 4122: Reserved, Microsoft Corporation backward compatibility
|
||||
"invalid uuid",
|
||||
"9491d710-3185-4e06-bea0-6a2f275345e0X",
|
||||
"ffffffff-ffff-ffff-ffff-ffffffffffff",
|
||||
]) {
|
||||
const result = uuid.safeParse(badUuid);
|
||||
expect(result).toMatchObject({ success: false });
|
||||
@@ -558,8 +481,8 @@ test("good guid", () => {
|
||||
for (const goodGuid of [
|
||||
"9491d710-3185-4e06-bea0-6a2f275345e0",
|
||||
"d89e7b01-7598-ed11-9d7a-0022489382fd", // new sequential id
|
||||
"b3ce60f8-e8b9-40f5-1150-172ede56ff74", // Variant 0 - RFC 9562/4122: Reserved, NCS backward compatibility
|
||||
"92e76bf9-28b3-4730-cd7f-cb6bc51f8c09", // Variant 2 - RFC 9562/4122: Reserved, Microsoft Corporation backward compatibility
|
||||
"b3ce60f8-e8b9-40f5-1150-172ede56ff74", // Variant 0 - RFC 4122: Reserved, NCS backward compatibility
|
||||
"92e76bf9-28b3-4730-cd7f-cb6bc51f8c09", // Variant 2 - RFC 4122: Reserved, Microsoft Corporation backward compatibility
|
||||
"00000000-0000-0000-0000-000000000000",
|
||||
"ffffffff-ffff-ffff-ffff-ffffffffffff",
|
||||
]) {
|
||||
@@ -775,8 +698,6 @@ test("format", () => {
|
||||
expect(z.string().date().format).toEqual("date");
|
||||
expect(z.string().time().format).toEqual("time");
|
||||
expect(z.string().duration().format).toEqual("duration");
|
||||
|
||||
expect(z.mac().format).toEqual("mac");
|
||||
});
|
||||
|
||||
test("min max getters", () => {
|
||||
@@ -803,24 +724,6 @@ test("lowerCase", () => {
|
||||
expect(z.string().toUpperCase().parse("asdf")).toEqual("ASDF");
|
||||
});
|
||||
|
||||
test("slugify", () => {
|
||||
expect(z.string().slugify().parse("Hello World")).toEqual("hello-world");
|
||||
expect(z.string().slugify().parse(" Hello World ")).toEqual("hello-world");
|
||||
expect(z.string().slugify().parse("Hello@World#123")).toEqual("helloworld123");
|
||||
expect(z.string().slugify().parse("Hello-World")).toEqual("hello-world");
|
||||
expect(z.string().slugify().parse("Hello_World")).toEqual("hello-world");
|
||||
expect(z.string().slugify().parse("---Hello---World---")).toEqual("hello-world");
|
||||
expect(z.string().slugify().parse("Hello World")).toEqual("hello-world");
|
||||
expect(z.string().slugify().parse("Hello!@#$%^&*()World")).toEqual("helloworld");
|
||||
|
||||
// can be used with check
|
||||
expect(z.string().check(z.slugify()).parse("Hello World")).toEqual("hello-world");
|
||||
|
||||
// can be chained with other methods
|
||||
expect(z.string().slugify().min(5).parse("Hello World")).toEqual("hello-world");
|
||||
expect(() => z.string().slugify().min(20).parse("Hello World")).toThrow();
|
||||
});
|
||||
|
||||
// test("IP validation", () => {
|
||||
// const ipSchema = z.string().ip();
|
||||
|
||||
@@ -905,58 +808,6 @@ test("IPv6 validation", () => {
|
||||
expect(() => ipv6.parse("254.164.77.1")).toThrow();
|
||||
});
|
||||
|
||||
test("MAC validation", () => {
|
||||
const mac = z.mac();
|
||||
|
||||
// Valid MAC addresses
|
||||
expect(mac.safeParse("00:1A:2B:3C:4D:5E").success).toBe(true);
|
||||
expect(mac.safeParse("FF:FF:FF:FF:FF:FF").success).toBe(true);
|
||||
expect(mac.safeParse("00:11:22:33:44:55").success).toBe(true);
|
||||
expect(mac.safeParse("A1:B2:C3:D4:E5:F6").success).toBe(true);
|
||||
expect(mac.safeParse("10:20:30:40:50:60").success).toBe(true);
|
||||
expect(mac.safeParse("0a:1b:2c:3d:4e:5f").success).toBe(true);
|
||||
expect(mac.safeParse("12:34:56:78:9A:BC").success).toBe(true);
|
||||
|
||||
// Invalid MAC addresses
|
||||
expect(mac.safeParse("00:1A-2B:3C-4D:5E").success).toBe(false);
|
||||
expect(mac.safeParse("00:1A:2B:3C:4D").success).toBe(false);
|
||||
expect(mac.safeParse("00:1A:2B:3C:4D").success).toBe(false);
|
||||
expect(mac.safeParse("00-1A-2B-3C-4D").success).toBe(false);
|
||||
expect(mac.safeParse("01-23-45-67-89-AB").success).toBe(false); // Dash delimiter not accepted by default
|
||||
expect(mac.safeParse("AA-BB-CC-DD-EE-FF").success).toBe(false); // Dash delimiter not accepted by default
|
||||
expect(mac.safeParse("DE-AD-BE-EF-00-01").success).toBe(false); // Dash delimiter not accepted by default
|
||||
expect(mac.safeParse("98-76-54-32-10-FF").success).toBe(false); // Dash delimiter not accepted by default
|
||||
expect(mac.safeParse("00:1A:2B:3C:4D:GZ").success).toBe(false);
|
||||
expect(mac.safeParse("00:1A:2B:3C:4D:5E:GG").success).toBe(false);
|
||||
expect(mac.safeParse("123:45:67:89:AB:CD").success).toBe(false);
|
||||
expect(mac.safeParse("00--1A:2B:3C:4D:5E").success).toBe(false);
|
||||
expect(mac.safeParse("00:1A::2B:3C:4D:5E").success).toBe(false);
|
||||
expect(mac.safeParse("00:1A:2B:3C:3C:2B:1A:00").success).toBe(false); // Disallow EUI-64
|
||||
expect(mac.safeParse("00:1a:2B:3c:4D:5e").success).toBe(false); // Disallow mixed-case
|
||||
|
||||
// MAC formats that are nonstandard but occassionally referenced, ex. https://www.postgresql.org/docs/17/datatype-net-types.html#DATATYPE-MACADDR
|
||||
expect(mac.safeParse("00:1A:2B:3C:4D:5E:FF").success).toBe(false);
|
||||
expect(mac.safeParse("001A2B:3C4D5E").success).toBe(false);
|
||||
expect(mac.safeParse("001A:2B3C:4D5E").success).toBe(false);
|
||||
expect(mac.safeParse("001A.2B3C.4D5E").success).toBe(false);
|
||||
expect(mac.safeParse("001A2B3C4D5E").success).toBe(false);
|
||||
expect(mac.safeParse("00.1A.2B.3C.4D.5E").success).toBe(false);
|
||||
});
|
||||
|
||||
test("MAC validation with custom delimiter", () => {
|
||||
const colonMac = z.mac({ delimiter: ":" });
|
||||
expect(colonMac.safeParse("00:1A:2B:3C:4D:5E").success).toBe(true);
|
||||
expect(colonMac.safeParse("00-1A-2B-3C-4D-5E").success).toBe(false);
|
||||
|
||||
const dashMac = z.mac({ delimiter: "-" });
|
||||
expect(dashMac.safeParse("00-1A-2B-3C-4D-5E").success).toBe(true);
|
||||
expect(dashMac.safeParse("00:1A:2B:3C:4D:5E").success).toBe(false);
|
||||
|
||||
const colonOnlyMac = z.mac({ delimiter: ":" });
|
||||
expect(colonOnlyMac.safeParse("00:1A:2B:3C:4D:5E").success).toBe(true);
|
||||
expect(colonOnlyMac.safeParse("00-1A-2B-3C-4D-5E").success).toBe(false);
|
||||
});
|
||||
|
||||
test("CIDR v4 validation", () => {
|
||||
const cidrV4 = z.string().cidrv4();
|
||||
|
||||
@@ -991,9 +842,6 @@ test("CIDR v6 validation", () => {
|
||||
expect(cidrV6.safeParse("2001:db8::/abc").success).toBe(false); // Invalid prefix format
|
||||
expect(cidrV6.safeParse("not a cidr").success).toBe(false); // Invalid format
|
||||
expect(cidrV6.safeParse("192.168.0.0/24").success).toBe(false); // IPv4 CIDR in v6 validation
|
||||
expect(cidrV6.safeParse("2001:0db8:85a3::/64/whatever-after").success).toBe(false);
|
||||
expect(cidrV6.safeParse("22d9:f4a8:6a90:f3bf:dcaa:2beb:5fba:0000/112").success).toBe(true);
|
||||
expect(cidrV6.safeParse("22d9:f4a8:6a90:f3bf:dcaa:2beb:5fba:0000/112/268").success).toBe(false);
|
||||
});
|
||||
|
||||
test("E.164 validation", () => {
|
||||
@@ -1031,122 +879,3 @@ test("E.164 validation", () => {
|
||||
expect(validE164Numbers.every((number) => e164Number.safeParse(number).success)).toBe(true);
|
||||
expect(invalidE164Numbers.every((number) => e164Number.safeParse(number).success === false)).toBe(true);
|
||||
});
|
||||
|
||||
test("hostname", () => {
|
||||
const hostname = z.hostname();
|
||||
|
||||
// Valid hostnames
|
||||
hostname.parse("localhost");
|
||||
hostname.parse("example.com");
|
||||
hostname.parse("sub.example.com");
|
||||
hostname.parse("a-b-c.example.com");
|
||||
hostname.parse("123.example.com");
|
||||
hostname.parse("example-123.com");
|
||||
hostname.parse("example-123.1234");
|
||||
hostname.parse("developer.mozilla.org");
|
||||
hostname.parse("hello.world.example.com");
|
||||
hostname.parse("www.google.com");
|
||||
hostname.parse("192.168.1.1");
|
||||
hostname.parse("xn--d1acj3b.com");
|
||||
hostname.parse("xn--d1acj3b.org");
|
||||
hostname.parse("xn--d1acj3b");
|
||||
|
||||
// Invalid hostnames
|
||||
expect(() => hostname.parse("")).toThrow();
|
||||
expect(() => hostname.parse("example..com")).toThrow();
|
||||
expect(() => hostname.parse("example-.com")).toThrow();
|
||||
expect(() => hostname.parse("-example.com")).toThrow();
|
||||
expect(() => hostname.parse("example.com-")).toThrow();
|
||||
expect(() => hostname.parse("example_com")).toThrow();
|
||||
expect(() => hostname.parse("example.com:8080")).toThrow();
|
||||
expect(() => hostname.parse("http://example.com")).toThrow();
|
||||
expect(() => hostname.parse("ht!tp://invalid.com")).toThrow();
|
||||
|
||||
expect(() => hostname.parse("xn--d1acj3b..com")).toThrow();
|
||||
expect(() => hostname.parse("ex@mple.com")).toThrow();
|
||||
expect(() => hostname.parse("[2001:db8::zzzz]")).toThrow();
|
||||
expect(() => hostname.parse("exa mple.com")).toThrow();
|
||||
expect(() => hostname.parse("-example.com")).toThrow();
|
||||
expect(() => hostname.parse("example..com")).toThrow();
|
||||
});
|
||||
|
||||
test("hash validation", () => {
|
||||
// MD5 tests
|
||||
const md5hex = z.hash("md5");
|
||||
const md5base64 = z.hash("md5", { enc: "base64" });
|
||||
const md5base64url = z.hash("md5", { enc: "base64url" });
|
||||
|
||||
// Valid MD5 hashes
|
||||
expect(md5hex.parse("5d41402abc4b2a76b9719d911017c592")).toBe("5d41402abc4b2a76b9719d911017c592");
|
||||
expect(md5hex.parse("5D41402ABC4B2A76B9719D911017C592")).toBe("5D41402ABC4B2A76B9719D911017C592"); // uppercase
|
||||
expect(md5base64.parse("XUFAKrxLKna5cZ2REBfFkg==")).toBe("XUFAKrxLKna5cZ2REBfFkg==");
|
||||
expect(md5base64url.parse("XUFAKrxLKna5cZ2REBfFkg")).toBe("XUFAKrxLKna5cZ2REBfFkg");
|
||||
|
||||
// Invalid MD5 hashes
|
||||
expect(() => md5hex.parse("5d41402abc4b2a76b9719d911017c59")).toThrow(); // too short
|
||||
expect(() => md5hex.parse("5d41402abc4b2a76b9719d911017c592x")).toThrow(); // too long
|
||||
expect(() => md5base64.parse("XUFAKrxLKna5cZ2REBfFkg=")).toThrow(); // wrong padding
|
||||
expect(() => md5base64url.parse("XUFAKrxLKna5cZ2REBfFkg=")).toThrow(); // has padding
|
||||
|
||||
// SHA1 tests
|
||||
const sha1hex = z.hash("sha1");
|
||||
const sha1base64 = z.hash("sha1", { enc: "base64" });
|
||||
const sha1base64url = z.hash("sha1", { enc: "base64url" });
|
||||
|
||||
// Valid SHA1 hashes
|
||||
expect(sha1hex.parse("aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d")).toBe("aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d");
|
||||
expect(sha1base64.parse("qvTGHdzF6KLavt4PO0gs2a6pQ00=")).toBe("qvTGHdzF6KLavt4PO0gs2a6pQ00=");
|
||||
expect(sha1base64url.parse("qvTGHdzF6KLavt4PO0gs2a6pQ00")).toBe("qvTGHdzF6KLavt4PO0gs2a6pQ00");
|
||||
|
||||
// SHA256 tests
|
||||
const sha256hex = z.hash("sha256");
|
||||
const sha256base64 = z.hash("sha256", { enc: "base64" });
|
||||
const sha256base64url = z.hash("sha256", { enc: "base64url" });
|
||||
|
||||
// Valid SHA256 hashes
|
||||
expect(sha256hex.parse("2cf24dba4f21d4288094c4a2e2c2d6c6b0c3e0c8f0e0c8f0e0c8f0e0c8f0e0c8")).toBe(
|
||||
"2cf24dba4f21d4288094c4a2e2c2d6c6b0c3e0c8f0e0c8f0e0c8f0e0c8f0e0c8"
|
||||
);
|
||||
expect(sha256base64.parse("LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ=")).toBe(
|
||||
"LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="
|
||||
);
|
||||
expect(sha256base64url.parse("LPJNul-wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ")).toBe(
|
||||
"LPJNul-wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ"
|
||||
);
|
||||
|
||||
// SHA384 tests (no padding in base64)
|
||||
const sha384hex = z.hash("sha384");
|
||||
const sha384base64 = z.hash("sha384", { enc: "base64" });
|
||||
|
||||
expect(
|
||||
sha384hex.parse("59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f")
|
||||
).toBe("59e1748777448c69de6b800d7a33bbfb9ff1b463e44354c3553bcdb9c666fa90125a3c79f90397bdf5f6a13de828684f");
|
||||
expect(sha384base64.parse("WeF0h3dEjGneawDXozO7+5/xtGPkQ1TDVTvNucZm+pASWjx5+QOXvfX2oT3oKGhP")).toBe(
|
||||
"WeF0h3dEjGneawDXozO7+5/xtGPkQ1TDVTvNucZm+pASWjx5+QOXvfX2oT3oKGhP"
|
||||
);
|
||||
|
||||
// SHA512 tests
|
||||
const sha512hex = z.hash("sha512");
|
||||
const sha512base64 = z.hash("sha512", { enc: "base64" });
|
||||
|
||||
expect(
|
||||
sha512hex.parse(
|
||||
"9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043"
|
||||
)
|
||||
).toBe(
|
||||
"9b71d224bd62f3785d96d46ad3ea3d73319bfbc2890caadae2dff72519673ca72323c3d99ba5c11d7c7acc6e14b8c5da0c4663475c2e5c3adef46f73bcdec043"
|
||||
);
|
||||
expect(
|
||||
sha512base64.parse("m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==")
|
||||
).toBe("m3HSJL1i83hdltRq0+o9czGb+8KJDKra4t/3JRlnPKcjI8PZm6XBHXx6zG4UuMXaDEZjR1wuXDre9G9zvN7AQw==");
|
||||
|
||||
// Test default encoding (hex)
|
||||
const defaultHash = z.hash("sha256");
|
||||
expect(defaultHash.parse("2cf24dba4f21d4288094c4a2e2c2d6c6b0c3e0c8f0e0c8f0e0c8f0e0c8f0e0c8")).toBe(
|
||||
"2cf24dba4f21d4288094c4a2e2c2d6c6b0c3e0c8f0e0c8f0e0c8f0e0c8f0e0c8"
|
||||
);
|
||||
|
||||
// Test with custom error message
|
||||
const hashWithMessage = z.hash("md5", { message: "Invalid MD5 hash" });
|
||||
expect(() => hashWithMessage.parse("invalid")).toThrow("Invalid MD5 hash");
|
||||
});
|
||||
|
||||
-40
@@ -64,43 +64,3 @@ test("z.stringbool with custom error messages", () => {
|
||||
|
||||
expect(() => a.parse("")).toThrowError("wrong!");
|
||||
});
|
||||
|
||||
test("z.stringbool codec encoding", () => {
|
||||
const schema = z.stringbool();
|
||||
|
||||
// Test encoding with default values
|
||||
expect(z.encode(schema, true)).toEqual("true");
|
||||
expect(z.encode(schema, false)).toEqual("false");
|
||||
});
|
||||
|
||||
test("z.stringbool codec encoding with custom values", () => {
|
||||
const schema = z.stringbool({
|
||||
truthy: ["yes", "on", "1"],
|
||||
falsy: ["no", "off", "0"],
|
||||
});
|
||||
|
||||
// Should return first element of custom arrays
|
||||
expect(z.encode(schema, true)).toEqual("yes");
|
||||
expect(z.encode(schema, false)).toEqual("no");
|
||||
});
|
||||
|
||||
test("z.stringbool codec round trip", () => {
|
||||
const schema = z.stringbool({
|
||||
truthy: ["enabled", "active"],
|
||||
falsy: ["disabled", "inactive"],
|
||||
});
|
||||
|
||||
// Test round trip: string -> boolean -> string
|
||||
const decoded = z.decode(schema, "enabled");
|
||||
expect(decoded).toEqual(true);
|
||||
|
||||
const encoded = z.encode(schema, decoded);
|
||||
expect(encoded).toEqual("enabled"); // First element of truthy array
|
||||
|
||||
// Test with falsy value
|
||||
const decodedFalse = z.decode(schema, "inactive");
|
||||
expect(decodedFalse).toEqual(false);
|
||||
|
||||
const encodedFalse = z.encode(schema, decodedFalse);
|
||||
expect(encodedFalse).toEqual("disabled"); // First element of falsy array
|
||||
});
|
||||
|
||||
+9
-22
@@ -6,7 +6,6 @@ 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 onePointOne = z.templateLiteral([z.literal(1.1)]);
|
||||
const truee = z.templateLiteral([true]);
|
||||
const anotherTrue = z.templateLiteral(["", z.literal(true)]);
|
||||
const falsee = z.templateLiteral([false]);
|
||||
@@ -43,7 +42,6 @@ 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 mac = z.templateLiteral(["", z.mac()]);
|
||||
const ulid = z.templateLiteral(["", z.string().ulid()]);
|
||||
const uuid = z.templateLiteral(["", z.string().uuid()]);
|
||||
const stringAToZ = z.templateLiteral(["", z.string().regex(/^[a-z]+$/)]);
|
||||
@@ -138,7 +136,6 @@ test("template literal type inference", () => {
|
||||
// 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 mac>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof ulid>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof uuid>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringAToZ>>().toEqualTypeOf<string>();
|
||||
@@ -292,7 +289,6 @@ test("template literal parsing - success - basic cases", () => {
|
||||
world.parse("world");
|
||||
one.parse("1");
|
||||
two.parse("2");
|
||||
onePointOne.parse("1.1");
|
||||
truee.parse("true");
|
||||
anotherTrue.parse("true");
|
||||
falsee.parse("false");
|
||||
@@ -363,7 +359,6 @@ test("template literal parsing - success - basic cases", () => {
|
||||
// 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");
|
||||
mac.parse("00:1A:2B:3C:4D:5E");
|
||||
ulid.parse("01GW3D2QZJBYB6P1Z1AE997VPW");
|
||||
uuid.parse("808989fd-3a6e-4af2-b607-737323a176f6");
|
||||
stringAToZ.parse("asudgaskhdgashd");
|
||||
@@ -386,7 +381,6 @@ test("template literal parsing - failure - basic cases", () => {
|
||||
expect(() => one.parse("2")).toThrow();
|
||||
expect(() => one.parse("12")).toThrow();
|
||||
expect(() => one.parse("21")).toThrow();
|
||||
expect(() => onePointOne.parse("1s1")).toThrow();
|
||||
expect(() => two.parse("1")).toThrow();
|
||||
expect(() => two.parse("21")).toThrow();
|
||||
expect(() => two.parse("12")).toThrow();
|
||||
@@ -500,8 +494,6 @@ test("template literal parsing - failure - basic cases", () => {
|
||||
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(() => mac.parse("00:1A:2B:3C:4D:5E:6A:7B")).toThrow();
|
||||
expect(() => mac.parse("00:1A:2B:3C")).toThrow();
|
||||
expect(() => ulid.parse("01GW3D2QZJBYB6P1Z1AE997VPW!")).toThrow();
|
||||
expect(() => uuid.parse("808989fd-3a6e-4af2-b607-737323a176f6Z")).toThrow();
|
||||
expect(() => uuid.parse("Z808989fd-3a6e-4af2-b607-737323a176f6")).toThrow();
|
||||
@@ -539,15 +531,15 @@ test("regexes", () => {
|
||||
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(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(bool._zod.pattern.source).toMatchInlineSnapshot(`"^true|false$"`);
|
||||
expect(bigone._zod.pattern.source).toMatchInlineSnapshot(`"^(1)$"`);
|
||||
expect(anyBigint._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+n?$"`);
|
||||
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))?$"`);
|
||||
@@ -571,14 +563,11 @@ test("regexes", () => {
|
||||
`"^(?:(?: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}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$"`
|
||||
);
|
||||
expect(mac._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(?:[0-9A-F]{2}:){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}:){5}[0-9a-f]{2}$"`
|
||||
`"^(([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|ffffffff-ffff-ffff-ffff-ffffffffffff)$"`
|
||||
`"^([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.*$"`);
|
||||
@@ -591,7 +580,7 @@ test("regexes", () => {
|
||||
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+)*)?)?)?$"`
|
||||
`"^mongodb:\\/\\/(\\w+:\\w+@)?\\w+:\\d+(\\/(\\w+)?(\\?(\\w+=\\w+(&\\w+=\\w+)*)?)?)?$"`
|
||||
);
|
||||
});
|
||||
|
||||
@@ -681,10 +670,8 @@ test("template literal parsing - failure - complex cases", () => {
|
||||
expect(() => connectionString.parse("mongodb://host1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:d234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:12.34")).toThrow();
|
||||
// Note: template literal regex currently allows negative numbers despite .positive() constraint
|
||||
// This is a known limitation where template literals use regex patterns directly
|
||||
// expect(() => connectionString.parse("mongodb://host:-1234")).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();
|
||||
@@ -745,7 +732,7 @@ test("template literal parsing - failure - issue format", () => {
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^mongodb:\\\\/\\\\/(\\\\w+:\\\\w+@)?\\\\w+:-?\\\\d+(\\\\/(\\\\w+)?(\\\\?(\\\\w+=\\\\w+(&\\\\w+=\\\\w+)*)?)?)?$",
|
||||
"pattern": "^mongodb:\\\\/\\\\/(\\\\w+:\\\\w+@)?\\\\w+:\\\\d+(\\\\/(\\\\w+)?(\\\\?(\\\\w+=\\\\w+(&\\\\w+=\\\\w+)*)?)?)?$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
|
||||
+7
-412
@@ -1,34 +1,7 @@
|
||||
import { Validator } from "@seriousme/openapi-schema-validator";
|
||||
import { describe, expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
// import * as zCore from "zod/v4/core";
|
||||
|
||||
const openAPI30Validator = new Validator();
|
||||
/** @see https://github.com/colinhacks/zod/issues/5147 */
|
||||
const validateOpenAPI30Schema = async (zodJSONSchema: Record<string, unknown>): Promise<true> => {
|
||||
const res = await openAPI30Validator.validate({
|
||||
openapi: "3.0.0",
|
||||
info: {
|
||||
title: "SampleApi",
|
||||
description: "Sample backend service",
|
||||
version: "1.0.0",
|
||||
},
|
||||
components: { schemas: { test: zodJSONSchema } },
|
||||
paths: {},
|
||||
});
|
||||
|
||||
if (!res.valid) {
|
||||
// `console.error` should make `vitest` trow an unhandled error
|
||||
// printing the validation messages in consoles
|
||||
console.error(
|
||||
`OpenAPI schema is not valid against ${openAPI30Validator.version}`,
|
||||
JSON.stringify(res.errors, null, 2)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
describe("toJSONSchema", () => {
|
||||
test("primitive types", () => {
|
||||
expect(z.toJSONSchema(z.string())).toMatchInlineSnapshot(`
|
||||
@@ -128,31 +101,7 @@ describe("toJSONSchema", () => {
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"format": "ipv6",
|
||||
"pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$",
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
expect(z.toJSONSchema(z.mac())).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"format": "mac",
|
||||
"pattern": "^(?:[0-9A-F]{2}:){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}:){5}[0-9a-f]{2}$",
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
expect(z.toJSONSchema(z.mac({ delimiter: ":" }))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"format": "mac",
|
||||
"pattern": "^(?:[0-9A-F]{2}:){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}:){5}[0-9a-f]{2}$",
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
expect(z.toJSONSchema(z.mac({ delimiter: "-" }))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"format": "mac",
|
||||
"pattern": "^(?:[0-9A-F]{2}-){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}-){5}[0-9a-f]{2}$",
|
||||
"pattern": "^(([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})$",
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
@@ -160,7 +109,7 @@ describe("toJSONSchema", () => {
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"format": "uuid",
|
||||
"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|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
|
||||
"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)$",
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
@@ -320,7 +269,7 @@ describe("toJSONSchema", () => {
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"format": "uuid",
|
||||
"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|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
|
||||
"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)$",
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
@@ -376,32 +325,7 @@ describe("toJSONSchema", () => {
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"format": "ipv6",
|
||||
"pattern": "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$",
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
|
||||
expect(z.toJSONSchema(z.mac())).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"format": "mac",
|
||||
"pattern": "^(?:[0-9A-F]{2}:){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}:){5}[0-9a-f]{2}$",
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
expect(z.toJSONSchema(z.mac({ delimiter: ":" }))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"format": "mac",
|
||||
"pattern": "^(?:[0-9A-F]{2}:){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}:){5}[0-9a-f]{2}$",
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
expect(z.toJSONSchema(z.mac({ delimiter: "-" }))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"format": "mac",
|
||||
"pattern": "^(?:[0-9A-F]{2}-){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}-){5}[0-9a-f]{2}$",
|
||||
"pattern": "^(([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})$",
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
@@ -615,68 +539,6 @@ describe("toJSONSchema", () => {
|
||||
`);
|
||||
});
|
||||
|
||||
test("number constraints draft-4", () => {
|
||||
expect(z.toJSONSchema(z.number().gt(5).lt(10), { target: "draft-4" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"exclusiveMaximum": true,
|
||||
"exclusiveMinimum": true,
|
||||
"maximum": 10,
|
||||
"minimum": 5,
|
||||
"type": "number",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("nullable openapi-3.0", () => {
|
||||
const schema = z.string().nullable();
|
||||
const jsonSchema = z.toJSONSchema(schema, { target: "openapi-3.0" });
|
||||
validateOpenAPI30Schema(jsonSchema);
|
||||
expect(jsonSchema).toMatchInlineSnapshot(`
|
||||
{
|
||||
"nullable": true,
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("union with null openapi-3.0", () => {
|
||||
const schema = z.union([z.string(), z.null()]);
|
||||
const jsonSchema = z.toJSONSchema(schema, { target: "openapi-3.0" });
|
||||
validateOpenAPI30Schema(jsonSchema);
|
||||
expect(jsonSchema).toMatchInlineSnapshot(`
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
null,
|
||||
],
|
||||
"nullable": true,
|
||||
"type": "string",
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("number with exclusive min-max openapi-3.0", () => {
|
||||
const schema = z.number().lt(100).gt(1);
|
||||
const jsonSchema = z.toJSONSchema(schema, { target: "openapi-3.0" });
|
||||
validateOpenAPI30Schema(jsonSchema);
|
||||
expect(jsonSchema).toMatchInlineSnapshot(`
|
||||
{
|
||||
"exclusiveMaximum": true,
|
||||
"exclusiveMinimum": true,
|
||||
"maximum": 100,
|
||||
"minimum": 1,
|
||||
"type": "number",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("arrays", () => {
|
||||
expect(z.toJSONSchema(z.array(z.string()))).toMatchInlineSnapshot(`
|
||||
{
|
||||
@@ -706,54 +568,6 @@ describe("toJSONSchema", () => {
|
||||
`);
|
||||
});
|
||||
|
||||
test("discriminated unions", () => {
|
||||
const schema = z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("success"), data: z.string() }),
|
||||
z.object({ type: z.literal("error"), message: z.string() }),
|
||||
]);
|
||||
expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"oneOf": [
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"data": {
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"const": "success",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"data",
|
||||
],
|
||||
"type": "object",
|
||||
},
|
||||
{
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string",
|
||||
},
|
||||
"type": {
|
||||
"const": "error",
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"message",
|
||||
],
|
||||
"type": "object",
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("intersections", () => {
|
||||
const schema = z.intersection(z.object({ name: z.string() }), z.object({ age: z.number() }));
|
||||
|
||||
@@ -806,39 +620,7 @@ describe("toJSONSchema", () => {
|
||||
`);
|
||||
});
|
||||
|
||||
test("record openapi-3.0", () => {
|
||||
const schema = z.record(z.string(), z.boolean());
|
||||
const jsonSchema = z.toJSONSchema(schema, { target: "openapi-3.0" });
|
||||
validateOpenAPI30Schema(jsonSchema);
|
||||
expect(jsonSchema).toMatchInlineSnapshot(`
|
||||
{
|
||||
"additionalProperties": {
|
||||
"type": "boolean",
|
||||
},
|
||||
"type": "object",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("tuple", () => {
|
||||
const schema = z.tuple([z.string(), z.number()]);
|
||||
expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"prefixItems": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
},
|
||||
],
|
||||
"type": "array",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("tuple with rest", () => {
|
||||
const schema = z.tuple([z.string(), z.number()]).rest(z.boolean());
|
||||
expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
|
||||
{
|
||||
@@ -859,173 +641,6 @@ describe("toJSONSchema", () => {
|
||||
`);
|
||||
});
|
||||
|
||||
test("tuple openapi-3.0", () => {
|
||||
const schema = z.tuple([z.string(), z.number()]);
|
||||
const jsonSchema = z.toJSONSchema(schema, { target: "openapi-3.0" });
|
||||
validateOpenAPI30Schema(jsonSchema);
|
||||
expect(jsonSchema).toMatchInlineSnapshot(`
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
},
|
||||
],
|
||||
},
|
||||
"maxItems": 2,
|
||||
"minItems": 2,
|
||||
"type": "array",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("tuple with rest openapi-3.0", () => {
|
||||
const schema = z.tuple([z.string(), z.number()]).rest(z.boolean());
|
||||
const jsonSchema = z.toJSONSchema(schema, { target: "openapi-3.0" });
|
||||
validateOpenAPI30Schema(jsonSchema);
|
||||
expect(jsonSchema).toMatchInlineSnapshot(`
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
},
|
||||
],
|
||||
},
|
||||
"minItems": 3,
|
||||
"type": "array",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("tuple with null openapi-3.0", () => {
|
||||
const schema = z.tuple([z.string(), z.number(), z.null()]);
|
||||
const jsonSchema = z.toJSONSchema(schema, { target: "openapi-3.0" });
|
||||
validateOpenAPI30Schema(jsonSchema);
|
||||
expect(jsonSchema).toMatchInlineSnapshot(`
|
||||
{
|
||||
"items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
null,
|
||||
],
|
||||
"nullable": true,
|
||||
"type": "string",
|
||||
},
|
||||
],
|
||||
},
|
||||
"maxItems": 3,
|
||||
"minItems": 3,
|
||||
"type": "array",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("tuple draft-7", () => {
|
||||
const schema = z.tuple([z.string(), z.number()]);
|
||||
expect(z.toJSONSchema(schema, { target: "draft-7", io: "input" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"items": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
},
|
||||
],
|
||||
"type": "array",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("tuple with rest draft-7", () => {
|
||||
const schema = z.tuple([z.string(), z.number()]).rest(z.boolean());
|
||||
expect(z.toJSONSchema(schema, { target: "draft-7", io: "input" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"additionalItems": {
|
||||
"type": "boolean",
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"type": "string",
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
},
|
||||
],
|
||||
"type": "array",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("tuple with rest draft-7 - issue #5151 regression test", () => {
|
||||
// This test addresses issue #5151: tuple with rest elements and ids
|
||||
// in draft-7 had incorrect internal path handling affecting complex scenarios
|
||||
const primarySchema = z.string().meta({ id: "primary" });
|
||||
const restSchema = z.number().meta({ id: "rest" });
|
||||
const testSchema = z.tuple([primarySchema], restSchema);
|
||||
|
||||
// Test both final output structure AND internal path handling
|
||||
const capturedPaths: string[] = [];
|
||||
const result = z.toJSONSchema(testSchema, {
|
||||
target: "draft-7",
|
||||
override: (ctx) => capturedPaths.push(ctx.path.join("/")),
|
||||
});
|
||||
|
||||
// Verify correct draft-7 structure with metadata extraction
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"additionalItems": {
|
||||
"$ref": "#/definitions/rest",
|
||||
},
|
||||
"definitions": {
|
||||
"primary": {
|
||||
"id": "primary",
|
||||
"type": "string",
|
||||
},
|
||||
"rest": {
|
||||
"id": "rest",
|
||||
"type": "number",
|
||||
},
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"$ref": "#/definitions/primary",
|
||||
},
|
||||
],
|
||||
"type": "array",
|
||||
}
|
||||
`);
|
||||
|
||||
// Verify internal paths are correct (this was the actual bug)
|
||||
expect(capturedPaths).toContain("items/0"); // prefix items should use "items" path
|
||||
expect(capturedPaths).toContain("additionalItems"); // rest should use "additionalItems" path
|
||||
expect(capturedPaths).not.toContain("prefixItems/0"); // should not use draft-2020-12 paths
|
||||
|
||||
// Structural validations
|
||||
expect(Array.isArray(result.items)).toBe(true);
|
||||
expect(result.additionalItems).toBeDefined();
|
||||
});
|
||||
|
||||
test("promise", () => {
|
||||
const schema = z.promise(z.string());
|
||||
expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
|
||||
@@ -1130,19 +745,6 @@ describe("toJSONSchema", () => {
|
||||
`);
|
||||
});
|
||||
|
||||
test("literal draft-4", () => {
|
||||
const a = z.literal("hello");
|
||||
expect(z.toJSONSchema(a, { target: "draft-4" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"enum": [
|
||||
"hello",
|
||||
],
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
// pipe
|
||||
test("pipe", () => {
|
||||
const schema = z
|
||||
@@ -1849,9 +1451,7 @@ test("unrepresentable literal values are ignored", () => {
|
||||
}
|
||||
`);
|
||||
|
||||
const b = z.z.toJSONSchema(z.literal([undefined, null, 5, BigInt(1324)]), {
|
||||
unrepresentable: "any",
|
||||
});
|
||||
const b = z.z.toJSONSchema(z.literal([undefined, null, 5, BigInt(1324)]), { unrepresentable: "any" });
|
||||
expect(b).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
@@ -1863,9 +1463,7 @@ test("unrepresentable literal values are ignored", () => {
|
||||
}
|
||||
`);
|
||||
|
||||
const c = z.z.toJSONSchema(z.literal([undefined]), {
|
||||
unrepresentable: "any",
|
||||
});
|
||||
const c = z.z.toJSONSchema(z.literal([undefined]), { unrepresentable: "any" });
|
||||
expect(c).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
@@ -2148,9 +1746,7 @@ test("basic registry", () => {
|
||||
myRegistry.add(User, { id: "User" });
|
||||
myRegistry.add(Post, { id: "Post" });
|
||||
|
||||
const result = z.z.toJSONSchema(myRegistry, {
|
||||
uri: (id) => `https://example.com/${id}.json`,
|
||||
});
|
||||
const result = z.z.toJSONSchema(myRegistry, { uri: (id) => `https://example.com/${id}.json` });
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"schemas": {
|
||||
@@ -2356,7 +1952,6 @@ test("input type", () => {
|
||||
"required": [
|
||||
"a",
|
||||
"d",
|
||||
"f",
|
||||
"g",
|
||||
],
|
||||
"type": "object",
|
||||
|
||||
-111
@@ -248,114 +248,3 @@ test("async short circuit on dirty", async () => {
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("do not continue by default", () => {
|
||||
const A = z
|
||||
.string()
|
||||
.transform((val, ctx) => {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
});
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
});
|
||||
return val;
|
||||
})
|
||||
.pipe(z.number() as any);
|
||||
expect(A.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
const B = z
|
||||
.string()
|
||||
.transform((val, ctx) => {
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
input: val,
|
||||
});
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
input: val,
|
||||
});
|
||||
return val;
|
||||
})
|
||||
.pipe(z.number() as any);
|
||||
expect(B.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
const C = z
|
||||
.string()
|
||||
.transform((val, ctx) => {
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
input: val,
|
||||
continue: true,
|
||||
});
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
input: val,
|
||||
continue: true,
|
||||
});
|
||||
return val;
|
||||
})
|
||||
.pipe(z.number() as any);
|
||||
expect(C.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("encode error", () => {
|
||||
const schema = z.string().transform((val) => val.length);
|
||||
expect(() => z.encode(schema, 1234)).toThrowErrorMatchingInlineSnapshot(
|
||||
`[ZodEncodeError: Encountered unidirectional transform during encode: ZodTransform]`
|
||||
);
|
||||
});
|
||||
|
||||
+2
-20
@@ -28,9 +28,9 @@ test("successful validation", () => {
|
||||
expect(r2.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"origin": "array",
|
||||
"code": "too_big",
|
||||
"maximum": 2,
|
||||
"origin": "array",
|
||||
"path": [],
|
||||
"message": "Too big: expected array to have <2 items"
|
||||
}
|
||||
@@ -80,9 +80,9 @@ test("async validation", async () => {
|
||||
expect(r2.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"origin": "array",
|
||||
"code": "too_big",
|
||||
"maximum": 2,
|
||||
"origin": "array",
|
||||
"path": [],
|
||||
"message": "Too big: expected array to have <2 items"
|
||||
}
|
||||
@@ -145,24 +145,6 @@ test("tuple with optional elements followed by required", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("tuple with all optional elements", () => {
|
||||
const allOptionalTuple = z.tuple([z.string().optional(), z.number().optional(), z.boolean().optional()]);
|
||||
expectTypeOf<typeof allOptionalTuple._output>().toEqualTypeOf<[string?, number?, boolean?]>();
|
||||
|
||||
// Empty array should be valid (all items optional)
|
||||
expect(allOptionalTuple.parse([])).toEqual([]);
|
||||
|
||||
// Partial arrays should be valid
|
||||
expect(allOptionalTuple.parse(["hello"])).toEqual(["hello"]);
|
||||
expect(allOptionalTuple.parse(["hello", 42])).toEqual(["hello", 42]);
|
||||
|
||||
// Full array should be valid
|
||||
expect(allOptionalTuple.parse(["hello", 42, true])).toEqual(["hello", 42, true]);
|
||||
|
||||
// Array that's too long should fail
|
||||
expect(() => allOptionalTuple.parse(["hello", 42, true, "extra"])).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]);
|
||||
|
||||
+3
-90
@@ -27,7 +27,7 @@ test("return valid over invalid", () => {
|
||||
});
|
||||
|
||||
test("return errors from both union arms", () => {
|
||||
const result = z.union([z.number(), z.boolean()]).safeParse("a");
|
||||
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(`
|
||||
@@ -45,9 +45,8 @@ test("return errors from both union arms", () => {
|
||||
],
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "boolean",
|
||||
"message": "Invalid input: expected boolean, received string",
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
],
|
||||
@@ -93,89 +92,3 @@ test("union values", () => {
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("non-aborted errors", () => {
|
||||
const zItemTest = z.union([
|
||||
z.object({
|
||||
date: z.number(),
|
||||
startDate: z.optional(z.null()),
|
||||
endDate: z.optional(z.null()),
|
||||
}),
|
||||
z
|
||||
.object({
|
||||
date: z.optional(z.null()),
|
||||
startDate: z.number(),
|
||||
endDate: z.number(),
|
||||
})
|
||||
.refine((data) => data.startDate !== data.endDate, {
|
||||
error: "startDate and endDate must be different",
|
||||
path: ["endDate"],
|
||||
}),
|
||||
]);
|
||||
|
||||
const res = zItemTest.safeParse({
|
||||
date: null,
|
||||
startDate: 1,
|
||||
endDate: 1,
|
||||
});
|
||||
|
||||
expect(res).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"endDate"
|
||||
],
|
||||
"message": "startDate and endDate must be different"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("surface continuable errors only if they exist", () => {
|
||||
const schema = z.union([z.boolean(), z.uuid(), z.jwt()]);
|
||||
|
||||
expect(schema.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_union",
|
||||
"errors": [
|
||||
[
|
||||
{
|
||||
"expected": "boolean",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected boolean, received string"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "invalid_format",
|
||||
"format": "uuid",
|
||||
"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|ffffffff-ffff-ffff-ffff-ffffffffffff)$/",
|
||||
"path": [],
|
||||
"message": "Invalid UUID"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "jwt",
|
||||
"path": [],
|
||||
"message": "Invalid JWT"
|
||||
}
|
||||
]
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
+133
-205
@@ -1,7 +1,6 @@
|
||||
import * as checks from "./checks.js";
|
||||
import type * as core from "./core.js";
|
||||
import type * as errors from "./errors.js";
|
||||
import * as registries from "./registries.js";
|
||||
import * as schemas from "./schemas.js";
|
||||
import * as util from "./util.js";
|
||||
|
||||
@@ -80,16 +79,13 @@ export function _coercedString<T extends schemas.$ZodString>(
|
||||
});
|
||||
}
|
||||
|
||||
export type $ZodStringFormatParams = CheckTypeParams<
|
||||
schemas.$ZodStringFormat,
|
||||
"format" | "coerce" | "when" | "pattern"
|
||||
>;
|
||||
export type $ZodStringFormatParams = CheckTypeParams<schemas.$ZodStringFormat, "format" | "coerce">;
|
||||
export type $ZodCheckStringFormatParams = CheckParams<checks.$ZodCheckStringFormat, "format">;
|
||||
// custom format
|
||||
|
||||
// Email
|
||||
export type $ZodEmailParams = StringFormatParams<schemas.$ZodEmail, "when">;
|
||||
export type $ZodCheckEmailParams = CheckStringFormatParams<schemas.$ZodEmail, "when">;
|
||||
export type $ZodEmailParams = StringFormatParams<schemas.$ZodEmail>;
|
||||
export type $ZodCheckEmailParams = CheckStringFormatParams<schemas.$ZodEmail>;
|
||||
export function _email<T extends schemas.$ZodEmail>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodEmailParams | $ZodCheckEmailParams
|
||||
@@ -104,8 +100,8 @@ export function _email<T extends schemas.$ZodEmail>(
|
||||
}
|
||||
|
||||
// GUID
|
||||
export type $ZodGUIDParams = StringFormatParams<schemas.$ZodGUID, "pattern" | "when">;
|
||||
export type $ZodCheckGUIDParams = CheckStringFormatParams<schemas.$ZodGUID, "pattern" | "when">;
|
||||
export type $ZodGUIDParams = StringFormatParams<schemas.$ZodGUID, "pattern">;
|
||||
export type $ZodCheckGUIDParams = CheckStringFormatParams<schemas.$ZodGUID, "pattern">;
|
||||
export function _guid<T extends schemas.$ZodGUID>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodGUIDParams | $ZodCheckGUIDParams
|
||||
@@ -120,8 +116,8 @@ export function _guid<T extends schemas.$ZodGUID>(
|
||||
}
|
||||
|
||||
// UUID
|
||||
export type $ZodUUIDParams = StringFormatParams<schemas.$ZodUUID, "pattern" | "when">;
|
||||
export type $ZodCheckUUIDParams = CheckStringFormatParams<schemas.$ZodUUID, "pattern" | "when">;
|
||||
export type $ZodUUIDParams = StringFormatParams<schemas.$ZodUUID, "pattern">;
|
||||
export type $ZodCheckUUIDParams = CheckStringFormatParams<schemas.$ZodUUID, "pattern">;
|
||||
export function _uuid<T extends schemas.$ZodUUID>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodUUIDParams | $ZodCheckUUIDParams
|
||||
@@ -136,8 +132,8 @@ export function _uuid<T extends schemas.$ZodUUID>(
|
||||
}
|
||||
|
||||
// UUIDv4
|
||||
export type $ZodUUIDv4Params = StringFormatParams<schemas.$ZodUUID, "pattern" | "when">;
|
||||
export type $ZodCheckUUIDv4Params = CheckStringFormatParams<schemas.$ZodUUID, "pattern" | "when">;
|
||||
export type $ZodUUIDv4Params = StringFormatParams<schemas.$ZodUUID, "pattern">;
|
||||
export type $ZodCheckUUIDv4Params = CheckStringFormatParams<schemas.$ZodUUID, "pattern">;
|
||||
export function _uuidv4<T extends schemas.$ZodUUID>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodUUIDv4Params | $ZodCheckUUIDv4Params
|
||||
@@ -153,8 +149,8 @@ export function _uuidv4<T extends schemas.$ZodUUID>(
|
||||
}
|
||||
|
||||
// UUIDv6
|
||||
export type $ZodUUIDv6Params = StringFormatParams<schemas.$ZodUUID, "pattern" | "when">;
|
||||
export type $ZodCheckUUIDv6Params = CheckStringFormatParams<schemas.$ZodUUID, "pattern" | "when">;
|
||||
export type $ZodUUIDv6Params = StringFormatParams<schemas.$ZodUUID, "pattern">;
|
||||
export type $ZodCheckUUIDv6Params = CheckStringFormatParams<schemas.$ZodUUID, "pattern">;
|
||||
export function _uuidv6<T extends schemas.$ZodUUID>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodUUIDv6Params | $ZodCheckUUIDv6Params
|
||||
@@ -170,8 +166,8 @@ export function _uuidv6<T extends schemas.$ZodUUID>(
|
||||
}
|
||||
|
||||
// UUIDv7
|
||||
export type $ZodUUIDv7Params = StringFormatParams<schemas.$ZodUUID, "pattern" | "when">;
|
||||
export type $ZodCheckUUIDv7Params = CheckStringFormatParams<schemas.$ZodUUID, "pattern" | "when">;
|
||||
export type $ZodUUIDv7Params = StringFormatParams<schemas.$ZodUUID, "pattern">;
|
||||
export type $ZodCheckUUIDv7Params = CheckStringFormatParams<schemas.$ZodUUID, "pattern">;
|
||||
export function _uuidv7<T extends schemas.$ZodUUID>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodUUIDv7Params | $ZodCheckUUIDv7Params
|
||||
@@ -187,8 +183,8 @@ export function _uuidv7<T extends schemas.$ZodUUID>(
|
||||
}
|
||||
|
||||
// URL
|
||||
export type $ZodURLParams = StringFormatParams<schemas.$ZodURL, "when">;
|
||||
export type $ZodCheckURLParams = CheckStringFormatParams<schemas.$ZodURL, "when">;
|
||||
export type $ZodURLParams = StringFormatParams<schemas.$ZodURL>;
|
||||
export type $ZodCheckURLParams = CheckStringFormatParams<schemas.$ZodURL>;
|
||||
export function _url<T extends schemas.$ZodURL>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodURLParams | $ZodCheckURLParams
|
||||
@@ -203,8 +199,8 @@ export function _url<T extends schemas.$ZodURL>(
|
||||
}
|
||||
|
||||
// Emoji
|
||||
export type $ZodEmojiParams = StringFormatParams<schemas.$ZodEmoji, "when">;
|
||||
export type $ZodCheckEmojiParams = CheckStringFormatParams<schemas.$ZodEmoji, "when">;
|
||||
export type $ZodEmojiParams = StringFormatParams<schemas.$ZodEmoji>;
|
||||
export type $ZodCheckEmojiParams = CheckStringFormatParams<schemas.$ZodEmoji>;
|
||||
export function _emoji<T extends schemas.$ZodEmoji>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodEmojiParams | $ZodCheckEmojiParams
|
||||
@@ -219,8 +215,8 @@ export function _emoji<T extends schemas.$ZodEmoji>(
|
||||
}
|
||||
|
||||
// NanoID
|
||||
export type $ZodNanoIDParams = StringFormatParams<schemas.$ZodNanoID, "when">;
|
||||
export type $ZodCheckNanoIDParams = CheckStringFormatParams<schemas.$ZodNanoID, "when">;
|
||||
export type $ZodNanoIDParams = StringFormatParams<schemas.$ZodNanoID>;
|
||||
export type $ZodCheckNanoIDParams = CheckStringFormatParams<schemas.$ZodNanoID>;
|
||||
export function _nanoid<T extends schemas.$ZodNanoID>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodNanoIDParams | $ZodCheckNanoIDParams
|
||||
@@ -235,8 +231,8 @@ export function _nanoid<T extends schemas.$ZodNanoID>(
|
||||
}
|
||||
|
||||
// CUID
|
||||
export type $ZodCUIDParams = StringFormatParams<schemas.$ZodCUID, "when">;
|
||||
export type $ZodCheckCUIDParams = CheckStringFormatParams<schemas.$ZodCUID, "when">;
|
||||
export type $ZodCUIDParams = StringFormatParams<schemas.$ZodCUID>;
|
||||
export type $ZodCheckCUIDParams = CheckStringFormatParams<schemas.$ZodCUID>;
|
||||
export function _cuid<T extends schemas.$ZodCUID>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodCUIDParams | $ZodCheckCUIDParams
|
||||
@@ -251,8 +247,8 @@ export function _cuid<T extends schemas.$ZodCUID>(
|
||||
}
|
||||
|
||||
// CUID2
|
||||
export type $ZodCUID2Params = StringFormatParams<schemas.$ZodCUID2, "when">;
|
||||
export type $ZodCheckCUID2Params = CheckStringFormatParams<schemas.$ZodCUID2, "when">;
|
||||
export type $ZodCUID2Params = StringFormatParams<schemas.$ZodCUID2>;
|
||||
export type $ZodCheckCUID2Params = CheckStringFormatParams<schemas.$ZodCUID2>;
|
||||
export function _cuid2<T extends schemas.$ZodCUID2>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodCUID2Params | $ZodCheckCUID2Params
|
||||
@@ -267,8 +263,8 @@ export function _cuid2<T extends schemas.$ZodCUID2>(
|
||||
}
|
||||
|
||||
// ULID
|
||||
export type $ZodULIDParams = StringFormatParams<schemas.$ZodULID, "when">;
|
||||
export type $ZodCheckULIDParams = CheckStringFormatParams<schemas.$ZodULID, "when">;
|
||||
export type $ZodULIDParams = StringFormatParams<schemas.$ZodULID>;
|
||||
export type $ZodCheckULIDParams = CheckStringFormatParams<schemas.$ZodULID>;
|
||||
export function _ulid<T extends schemas.$ZodULID>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodULIDParams | $ZodCheckULIDParams
|
||||
@@ -283,8 +279,8 @@ export function _ulid<T extends schemas.$ZodULID>(
|
||||
}
|
||||
|
||||
// XID
|
||||
export type $ZodXIDParams = StringFormatParams<schemas.$ZodXID, "when">;
|
||||
export type $ZodCheckXIDParams = CheckStringFormatParams<schemas.$ZodXID, "when">;
|
||||
export type $ZodXIDParams = StringFormatParams<schemas.$ZodXID>;
|
||||
export type $ZodCheckXIDParams = CheckStringFormatParams<schemas.$ZodXID>;
|
||||
export function _xid<T extends schemas.$ZodXID>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodXIDParams | $ZodCheckXIDParams
|
||||
@@ -299,8 +295,8 @@ export function _xid<T extends schemas.$ZodXID>(
|
||||
}
|
||||
|
||||
// KSUID
|
||||
export type $ZodKSUIDParams = StringFormatParams<schemas.$ZodKSUID, "when">;
|
||||
export type $ZodCheckKSUIDParams = CheckStringFormatParams<schemas.$ZodKSUID, "when">;
|
||||
export type $ZodKSUIDParams = StringFormatParams<schemas.$ZodKSUID>;
|
||||
export type $ZodCheckKSUIDParams = CheckStringFormatParams<schemas.$ZodKSUID>;
|
||||
export function _ksuid<T extends schemas.$ZodKSUID>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodKSUIDParams | $ZodCheckKSUIDParams
|
||||
@@ -314,9 +310,25 @@ export function _ksuid<T extends schemas.$ZodKSUID>(
|
||||
});
|
||||
}
|
||||
|
||||
// IP
|
||||
// export type $ZodIPParams = StringFormatParams<schemas.$ZodIP, "pattern">;
|
||||
// export type $ZodCheckIPParams = CheckStringFormatParams<schemas.$ZodIP, "pattern">;
|
||||
// export function _ip<T extends schemas.$ZodIP>(
|
||||
// Class: util.SchemaClass<T>,
|
||||
// params?: string | $ZodIPParams | $ZodCheckIPParams
|
||||
// ): T {
|
||||
// return new Class({
|
||||
// type: "string",
|
||||
// format: "ip",
|
||||
// check: "string_format",
|
||||
// abort: false,
|
||||
// ...util.normalizeParams(params),
|
||||
// });
|
||||
// }
|
||||
|
||||
// IPv4
|
||||
export type $ZodIPv4Params = StringFormatParams<schemas.$ZodIPv4, "pattern" | "when" | "version">;
|
||||
export type $ZodCheckIPv4Params = CheckStringFormatParams<schemas.$ZodIPv4, "pattern" | "when" | "version">;
|
||||
export type $ZodIPv4Params = StringFormatParams<schemas.$ZodIPv4, "pattern">;
|
||||
export type $ZodCheckIPv4Params = CheckStringFormatParams<schemas.$ZodIPv4, "pattern">;
|
||||
export function _ipv4<T extends schemas.$ZodIPv4>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodIPv4Params | $ZodCheckIPv4Params
|
||||
@@ -331,8 +343,8 @@ export function _ipv4<T extends schemas.$ZodIPv4>(
|
||||
}
|
||||
|
||||
// IPv6
|
||||
export type $ZodIPv6Params = StringFormatParams<schemas.$ZodIPv6, "pattern" | "when" | "version">;
|
||||
export type $ZodCheckIPv6Params = CheckStringFormatParams<schemas.$ZodIPv6, "pattern" | "when" | "version">;
|
||||
export type $ZodIPv6Params = StringFormatParams<schemas.$ZodIPv6, "pattern">;
|
||||
export type $ZodCheckIPv6Params = CheckStringFormatParams<schemas.$ZodIPv6, "pattern">;
|
||||
export function _ipv6<T extends schemas.$ZodIPv6>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodIPv6Params | $ZodCheckIPv6Params
|
||||
@@ -346,25 +358,9 @@ export function _ipv6<T extends schemas.$ZodIPv6>(
|
||||
});
|
||||
}
|
||||
|
||||
// MAC
|
||||
export type $ZodMACParams = StringFormatParams<schemas.$ZodMAC, "pattern" | "when">;
|
||||
export type $ZodCheckMACParams = CheckStringFormatParams<schemas.$ZodMAC, "pattern" | "when">;
|
||||
export function _mac<T extends schemas.$ZodMAC>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodMACParams | $ZodCheckMACParams
|
||||
): T {
|
||||
return new Class({
|
||||
type: "string",
|
||||
format: "mac",
|
||||
check: "string_format",
|
||||
abort: false,
|
||||
...util.normalizeParams(params),
|
||||
});
|
||||
}
|
||||
|
||||
// CIDRv4
|
||||
export type $ZodCIDRv4Params = StringFormatParams<schemas.$ZodCIDRv4, "pattern" | "when">;
|
||||
export type $ZodCheckCIDRv4Params = CheckStringFormatParams<schemas.$ZodCIDRv4, "pattern" | "when">;
|
||||
export type $ZodCIDRv4Params = StringFormatParams<schemas.$ZodCIDRv4, "pattern">;
|
||||
export type $ZodCheckCIDRv4Params = CheckStringFormatParams<schemas.$ZodCIDRv4, "pattern">;
|
||||
export function _cidrv4<T extends schemas.$ZodCIDRv4>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodCIDRv4Params | $ZodCheckCIDRv4Params
|
||||
@@ -379,8 +375,8 @@ export function _cidrv4<T extends schemas.$ZodCIDRv4>(
|
||||
}
|
||||
|
||||
// CIDRv6
|
||||
export type $ZodCIDRv6Params = StringFormatParams<schemas.$ZodCIDRv6, "pattern" | "when">;
|
||||
export type $ZodCheckCIDRv6Params = CheckStringFormatParams<schemas.$ZodCIDRv6, "pattern" | "when">;
|
||||
export type $ZodCIDRv6Params = StringFormatParams<schemas.$ZodCIDRv6, "pattern">;
|
||||
export type $ZodCheckCIDRv6Params = CheckStringFormatParams<schemas.$ZodCIDRv6, "pattern">;
|
||||
export function _cidrv6<T extends schemas.$ZodCIDRv6>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodCIDRv6Params | $ZodCheckCIDRv6Params
|
||||
@@ -395,8 +391,8 @@ export function _cidrv6<T extends schemas.$ZodCIDRv6>(
|
||||
}
|
||||
|
||||
// Base64
|
||||
export type $ZodBase64Params = StringFormatParams<schemas.$ZodBase64, "pattern" | "when">;
|
||||
export type $ZodCheckBase64Params = CheckStringFormatParams<schemas.$ZodBase64, "pattern" | "when">;
|
||||
export type $ZodBase64Params = StringFormatParams<schemas.$ZodBase64, "pattern">;
|
||||
export type $ZodCheckBase64Params = CheckStringFormatParams<schemas.$ZodBase64, "pattern">;
|
||||
export function _base64<T extends schemas.$ZodBase64>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodBase64Params | $ZodCheckBase64Params
|
||||
@@ -411,8 +407,8 @@ export function _base64<T extends schemas.$ZodBase64>(
|
||||
}
|
||||
|
||||
// base64url
|
||||
export type $ZodBase64URLParams = StringFormatParams<schemas.$ZodBase64URL, "pattern" | "when">;
|
||||
export type $ZodCheckBase64URLParams = CheckStringFormatParams<schemas.$ZodBase64URL, "pattern" | "when">;
|
||||
export type $ZodBase64URLParams = StringFormatParams<schemas.$ZodBase64URL, "pattern">;
|
||||
export type $ZodCheckBase64URLParams = CheckStringFormatParams<schemas.$ZodBase64URL, "pattern">;
|
||||
export function _base64url<T extends schemas.$ZodBase64URL>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodBase64URLParams | $ZodCheckBase64URLParams
|
||||
@@ -427,8 +423,8 @@ export function _base64url<T extends schemas.$ZodBase64URL>(
|
||||
}
|
||||
|
||||
// E164
|
||||
export type $ZodE164Params = StringFormatParams<schemas.$ZodE164, "when">;
|
||||
export type $ZodCheckE164Params = CheckStringFormatParams<schemas.$ZodE164, "when">;
|
||||
export type $ZodE164Params = StringFormatParams<schemas.$ZodE164>;
|
||||
export type $ZodCheckE164Params = CheckStringFormatParams<schemas.$ZodE164>;
|
||||
export function _e164<T extends schemas.$ZodE164>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodE164Params | $ZodCheckE164Params
|
||||
@@ -443,8 +439,8 @@ export function _e164<T extends schemas.$ZodE164>(
|
||||
}
|
||||
|
||||
// JWT
|
||||
export type $ZodJWTParams = StringFormatParams<schemas.$ZodJWT, "pattern" | "when">;
|
||||
export type $ZodCheckJWTParams = CheckStringFormatParams<schemas.$ZodJWT, "pattern" | "when">;
|
||||
export type $ZodJWTParams = StringFormatParams<schemas.$ZodJWT, "pattern">;
|
||||
export type $ZodCheckJWTParams = CheckStringFormatParams<schemas.$ZodJWT, "pattern">;
|
||||
export function _jwt<T extends schemas.$ZodJWT>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodJWTParams | $ZodCheckJWTParams
|
||||
@@ -466,8 +462,8 @@ export const TimePrecision = {
|
||||
Microsecond: 6,
|
||||
} as const;
|
||||
// ISODateTime
|
||||
export type $ZodISODateTimeParams = StringFormatParams<schemas.$ZodISODateTime, "pattern" | "when">;
|
||||
export type $ZodCheckISODateTimeParams = CheckStringFormatParams<schemas.$ZodISODateTime, "pattern" | "when">;
|
||||
export type $ZodISODateTimeParams = StringFormatParams<schemas.$ZodISODateTime, "pattern">;
|
||||
export type $ZodCheckISODateTimeParams = CheckStringFormatParams<schemas.$ZodISODateTime, "pattern">;
|
||||
export function _isoDateTime<T extends schemas.$ZodISODateTime>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodISODateTimeParams | $ZodCheckISODateTimeParams
|
||||
@@ -484,8 +480,8 @@ export function _isoDateTime<T extends schemas.$ZodISODateTime>(
|
||||
}
|
||||
|
||||
// ISODate
|
||||
export type $ZodISODateParams = StringFormatParams<schemas.$ZodISODate, "pattern" | "when">;
|
||||
export type $ZodCheckISODateParams = CheckStringFormatParams<schemas.$ZodISODate, "pattern" | "when">;
|
||||
export type $ZodISODateParams = StringFormatParams<schemas.$ZodISODate, "pattern">;
|
||||
export type $ZodCheckISODateParams = CheckStringFormatParams<schemas.$ZodISODate, "pattern">;
|
||||
export function _isoDate<T extends schemas.$ZodISODate>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodISODateParams | $ZodCheckISODateParams
|
||||
@@ -499,8 +495,8 @@ export function _isoDate<T extends schemas.$ZodISODate>(
|
||||
}
|
||||
|
||||
// ISOTime
|
||||
export type $ZodISOTimeParams = StringFormatParams<schemas.$ZodISOTime, "pattern" | "when">;
|
||||
export type $ZodCheckISOTimeParams = CheckStringFormatParams<schemas.$ZodISOTime, "pattern" | "when">;
|
||||
export type $ZodISOTimeParams = StringFormatParams<schemas.$ZodISOTime, "pattern">;
|
||||
export type $ZodCheckISOTimeParams = CheckStringFormatParams<schemas.$ZodISOTime, "pattern">;
|
||||
export function _isoTime<T extends schemas.$ZodISOTime>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodISOTimeParams | $ZodCheckISOTimeParams
|
||||
@@ -515,8 +511,8 @@ export function _isoTime<T extends schemas.$ZodISOTime>(
|
||||
}
|
||||
|
||||
// ISODuration
|
||||
export type $ZodISODurationParams = StringFormatParams<schemas.$ZodISODuration, "when">;
|
||||
export type $ZodCheckISODurationParams = CheckStringFormatParams<schemas.$ZodISODuration, "when">;
|
||||
export type $ZodISODurationParams = StringFormatParams<schemas.$ZodISODuration>;
|
||||
export type $ZodCheckISODurationParams = CheckStringFormatParams<schemas.$ZodISODuration>;
|
||||
export function _isoDuration<T extends schemas.$ZodISODuration>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodISODurationParams | $ZodCheckISODurationParams
|
||||
@@ -532,7 +528,7 @@ export function _isoDuration<T extends schemas.$ZodISODuration>(
|
||||
// Number
|
||||
export type $ZodNumberParams = TypeParams<schemas.$ZodNumber<number>, "coerce">;
|
||||
export type $ZodNumberFormatParams = CheckTypeParams<schemas.$ZodNumberFormat, "format" | "coerce">;
|
||||
export type $ZodCheckNumberFormatParams = CheckParams<checks.$ZodCheckNumberFormat, "format" | "when">;
|
||||
export type $ZodCheckNumberFormatParams = CheckParams<checks.$ZodCheckNumberFormat, "format">;
|
||||
export function _number<T extends schemas.$ZodNumber>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodNumberParams
|
||||
@@ -642,7 +638,7 @@ export function _coercedBoolean<T extends schemas.$ZodBoolean>(
|
||||
// BigInt
|
||||
export type $ZodBigIntParams = TypeParams<schemas.$ZodBigInt<bigint>>;
|
||||
export type $ZodBigIntFormatParams = CheckTypeParams<schemas.$ZodBigIntFormat, "format" | "coerce">;
|
||||
export type $ZodCheckBigIntFormatParams = CheckParams<checks.$ZodCheckBigIntFormat, "format" | "when">;
|
||||
export type $ZodCheckBigIntFormatParams = CheckParams<checks.$ZodCheckBigIntFormat, "format">;
|
||||
export function _bigint<T extends schemas.$ZodBigInt>(
|
||||
Class: util.SchemaClass<T>,
|
||||
params?: string | $ZodBigIntParams
|
||||
@@ -783,9 +779,9 @@ export function _nan<T extends schemas.$ZodNaN>(Class: util.SchemaClass<T>, para
|
||||
});
|
||||
}
|
||||
|
||||
// export type $ZodCheckParams = CheckParams<checks.$ZodCheck, "abort" | "when">;
|
||||
// export type $ZodCheckParams = CheckParams<checks.$ZodCheck, "abort">;
|
||||
|
||||
export type $ZodCheckLessThanParams = CheckParams<checks.$ZodCheckLessThan, "inclusive" | "value" | "when">;
|
||||
export type $ZodCheckLessThanParams = CheckParams<checks.$ZodCheckLessThan, "inclusive" | "value">;
|
||||
export function _lt(
|
||||
value: util.Numeric,
|
||||
params?: string | $ZodCheckLessThanParams
|
||||
@@ -816,7 +812,7 @@ export {
|
||||
};
|
||||
|
||||
// ZodCheckGreaterThan
|
||||
export type $ZodCheckGreaterThanParams = CheckParams<checks.$ZodCheckGreaterThan, "inclusive" | "value" | "when">;
|
||||
export type $ZodCheckGreaterThanParams = CheckParams<checks.$ZodCheckGreaterThan, "inclusive" | "value">;
|
||||
export function _gt(value: util.Numeric, params?: string | $ZodCheckGreaterThanParams): checks.$ZodCheckGreaterThan {
|
||||
return new checks.$ZodCheckGreaterThan({
|
||||
check: "greater_than",
|
||||
@@ -860,7 +856,7 @@ export function _nonnegative(params?: string | $ZodCheckGreaterThanParams): chec
|
||||
return _gte(0, params);
|
||||
}
|
||||
|
||||
export type $ZodCheckMultipleOfParams = CheckParams<checks.$ZodCheckMultipleOf, "value" | "when">;
|
||||
export type $ZodCheckMultipleOfParams = CheckParams<checks.$ZodCheckMultipleOf, "value">;
|
||||
export function _multipleOf(
|
||||
value: number | bigint,
|
||||
params?: string | $ZodCheckMultipleOfParams
|
||||
@@ -872,7 +868,7 @@ export function _multipleOf(
|
||||
});
|
||||
}
|
||||
|
||||
export type $ZodCheckMaxSizeParams = CheckParams<checks.$ZodCheckMaxSize, "maximum" | "when">;
|
||||
export type $ZodCheckMaxSizeParams = CheckParams<checks.$ZodCheckMaxSize, "maximum">;
|
||||
export function _maxSize(
|
||||
maximum: number,
|
||||
params?: string | $ZodCheckMaxSizeParams
|
||||
@@ -884,7 +880,7 @@ export function _maxSize(
|
||||
});
|
||||
}
|
||||
|
||||
export type $ZodCheckMinSizeParams = CheckParams<checks.$ZodCheckMinSize, "minimum" | "when">;
|
||||
export type $ZodCheckMinSizeParams = CheckParams<checks.$ZodCheckMinSize, "minimum">;
|
||||
export function _minSize(
|
||||
minimum: number,
|
||||
params?: string | $ZodCheckMinSizeParams
|
||||
@@ -896,7 +892,7 @@ export function _minSize(
|
||||
});
|
||||
}
|
||||
|
||||
export type $ZodCheckSizeEqualsParams = CheckParams<checks.$ZodCheckSizeEquals, "size" | "when">;
|
||||
export type $ZodCheckSizeEqualsParams = CheckParams<checks.$ZodCheckSizeEquals, "size">;
|
||||
export function _size(
|
||||
size: number,
|
||||
params?: string | $ZodCheckSizeEqualsParams
|
||||
@@ -908,7 +904,7 @@ export function _size(
|
||||
});
|
||||
}
|
||||
|
||||
export type $ZodCheckMaxLengthParams = CheckParams<checks.$ZodCheckMaxLength, "maximum" | "when">;
|
||||
export type $ZodCheckMaxLengthParams = CheckParams<checks.$ZodCheckMaxLength, "maximum">;
|
||||
export function _maxLength(
|
||||
maximum: number,
|
||||
params?: string | $ZodCheckMaxLengthParams
|
||||
@@ -921,7 +917,7 @@ export function _maxLength(
|
||||
return ch;
|
||||
}
|
||||
|
||||
export type $ZodCheckMinLengthParams = CheckParams<checks.$ZodCheckMinLength, "minimum" | "when">;
|
||||
export type $ZodCheckMinLengthParams = CheckParams<checks.$ZodCheckMinLength, "minimum">;
|
||||
export function _minLength(
|
||||
minimum: number,
|
||||
params?: string | $ZodCheckMinLengthParams
|
||||
@@ -933,7 +929,7 @@ export function _minLength(
|
||||
});
|
||||
}
|
||||
|
||||
export type $ZodCheckLengthEqualsParams = CheckParams<checks.$ZodCheckLengthEquals, "length" | "when">;
|
||||
export type $ZodCheckLengthEqualsParams = CheckParams<checks.$ZodCheckLengthEquals, "length">;
|
||||
export function _length(
|
||||
length: number,
|
||||
params?: string | $ZodCheckLengthEqualsParams
|
||||
@@ -945,7 +941,7 @@ export function _length(
|
||||
});
|
||||
}
|
||||
|
||||
export type $ZodCheckRegexParams = CheckParams<checks.$ZodCheckRegex, "format" | "pattern" | "when">;
|
||||
export type $ZodCheckRegexParams = CheckParams<checks.$ZodCheckRegex, "format" | "pattern">;
|
||||
export function _regex(pattern: RegExp, params?: string | $ZodCheckRegexParams): checks.$ZodCheckRegex {
|
||||
return new checks.$ZodCheckRegex({
|
||||
check: "string_format",
|
||||
@@ -955,7 +951,7 @@ export function _regex(pattern: RegExp, params?: string | $ZodCheckRegexParams):
|
||||
});
|
||||
}
|
||||
|
||||
export type $ZodCheckLowerCaseParams = CheckParams<checks.$ZodCheckLowerCase, "format" | "when">;
|
||||
export type $ZodCheckLowerCaseParams = CheckParams<checks.$ZodCheckLowerCase, "format">;
|
||||
export function _lowercase(params?: string | $ZodCheckLowerCaseParams): checks.$ZodCheckLowerCase {
|
||||
return new checks.$ZodCheckLowerCase({
|
||||
check: "string_format",
|
||||
@@ -964,7 +960,7 @@ export function _lowercase(params?: string | $ZodCheckLowerCaseParams): checks.$
|
||||
});
|
||||
}
|
||||
|
||||
export type $ZodCheckUpperCaseParams = CheckParams<checks.$ZodCheckUpperCase, "format" | "when">;
|
||||
export type $ZodCheckUpperCaseParams = CheckParams<checks.$ZodCheckUpperCase, "format">;
|
||||
|
||||
export function _uppercase(params?: string | $ZodCheckUpperCaseParams): checks.$ZodCheckUpperCase {
|
||||
return new checks.$ZodCheckUpperCase({
|
||||
@@ -974,7 +970,7 @@ export function _uppercase(params?: string | $ZodCheckUpperCaseParams): checks.$
|
||||
});
|
||||
}
|
||||
|
||||
export type $ZodCheckIncludesParams = CheckParams<checks.$ZodCheckIncludes, "includes" | "format" | "when" | "pattern">;
|
||||
export type $ZodCheckIncludesParams = CheckParams<checks.$ZodCheckIncludes, "includes" | "format" | "pattern">;
|
||||
export function _includes(includes: string, params?: string | $ZodCheckIncludesParams): checks.$ZodCheckIncludes {
|
||||
return new checks.$ZodCheckIncludes({
|
||||
check: "string_format",
|
||||
@@ -983,10 +979,7 @@ export function _includes(includes: string, params?: string | $ZodCheckIncludesP
|
||||
includes,
|
||||
});
|
||||
}
|
||||
export type $ZodCheckStartsWithParams = CheckParams<
|
||||
checks.$ZodCheckStartsWith,
|
||||
"prefix" | "format" | "when" | "pattern"
|
||||
>;
|
||||
export type $ZodCheckStartsWithParams = CheckParams<checks.$ZodCheckStartsWith, "prefix" | "format" | "pattern">;
|
||||
export function _startsWith(prefix: string, params?: string | $ZodCheckStartsWithParams): checks.$ZodCheckStartsWith {
|
||||
return new checks.$ZodCheckStartsWith({
|
||||
check: "string_format",
|
||||
@@ -996,7 +989,7 @@ export function _startsWith(prefix: string, params?: string | $ZodCheckStartsWit
|
||||
});
|
||||
}
|
||||
|
||||
export type $ZodCheckEndsWithParams = CheckParams<checks.$ZodCheckEndsWith, "suffix" | "format" | "pattern" | "when">;
|
||||
export type $ZodCheckEndsWithParams = CheckParams<checks.$ZodCheckEndsWith, "suffix" | "format" | "pattern">;
|
||||
|
||||
export function _endsWith(suffix: string, params?: string | $ZodCheckEndsWithParams): checks.$ZodCheckEndsWith {
|
||||
return new checks.$ZodCheckEndsWith({
|
||||
@@ -1007,7 +1000,7 @@ export function _endsWith(suffix: string, params?: string | $ZodCheckEndsWithPar
|
||||
});
|
||||
}
|
||||
|
||||
export type $ZodCheckPropertyParams = CheckParams<checks.$ZodCheckProperty, "property" | "schema" | "when">;
|
||||
export type $ZodCheckPropertyParams = CheckParams<checks.$ZodCheckProperty, "property" | "schema">;
|
||||
export function _property<K extends string, T extends schemas.$ZodType>(
|
||||
property: K,
|
||||
schema: T,
|
||||
@@ -1021,7 +1014,7 @@ export function _property<K extends string, T extends schemas.$ZodType>(
|
||||
});
|
||||
}
|
||||
|
||||
export type $ZodCheckMimeTypeParams = CheckParams<checks.$ZodCheckMimeType, "mime" | "when">;
|
||||
export type $ZodCheckMimeTypeParams = CheckParams<checks.$ZodCheckMimeType, "mime">;
|
||||
export function _mime(types: util.MimeTypes[], params?: string | $ZodCheckMimeTypeParams): checks.$ZodCheckMimeType {
|
||||
return new checks.$ZodCheckMimeType({
|
||||
check: "mime_type",
|
||||
@@ -1053,10 +1046,6 @@ export function _toLowerCase(): checks.$ZodCheckOverwrite<string> {
|
||||
export function _toUpperCase(): checks.$ZodCheckOverwrite<string> {
|
||||
return _overwrite((input) => input.toUpperCase());
|
||||
}
|
||||
// slugify
|
||||
export function _slugify(): checks.$ZodCheckOverwrite<string> {
|
||||
return _overwrite((input) => util.slugify(input));
|
||||
}
|
||||
|
||||
/////// collections ///////
|
||||
|
||||
@@ -1102,15 +1091,12 @@ export interface $ZodTypeDiscriminable extends schemas.$ZodType {
|
||||
_zod: $ZodTypeDiscriminableInternals;
|
||||
}
|
||||
export type $ZodDiscriminatedUnionParams = TypeParams<schemas.$ZodDiscriminatedUnion, "options" | "discriminator">;
|
||||
export function _discriminatedUnion<
|
||||
Types extends [$ZodTypeDiscriminable, ...$ZodTypeDiscriminable[]],
|
||||
Disc extends string,
|
||||
>(
|
||||
export function _discriminatedUnion<Types extends [$ZodTypeDiscriminable, ...$ZodTypeDiscriminable[]]>(
|
||||
Class: util.SchemaClass<schemas.$ZodDiscriminatedUnion>,
|
||||
discriminator: Disc,
|
||||
discriminator: string,
|
||||
options: Types,
|
||||
params?: string | $ZodDiscriminatedUnionParams
|
||||
): schemas.$ZodDiscriminatedUnion<Types, Disc> {
|
||||
): schemas.$ZodDiscriminatedUnion<Types> {
|
||||
return new Class({
|
||||
type: "union",
|
||||
options,
|
||||
@@ -1342,7 +1328,7 @@ export function _default<T extends schemas.$ZodObject>(
|
||||
type: "default",
|
||||
innerType,
|
||||
get defaultValue() {
|
||||
return typeof defaultValue === "function" ? (defaultValue as Function)() : util.shallowClone(defaultValue);
|
||||
return typeof defaultValue === "function" ? (defaultValue as Function)() : defaultValue;
|
||||
},
|
||||
}) as any;
|
||||
}
|
||||
@@ -1473,6 +1459,13 @@ export function _custom<O = unknown, I = O>(
|
||||
return schema as any;
|
||||
}
|
||||
|
||||
// export function _refine<T>(
|
||||
// Class: util.SchemaClass<schemas.$ZodCustom>,
|
||||
// fn: (arg: NoInfer<T>) => util.MaybeAsync<unknown>,
|
||||
// _params: string | $ZodCustomParams = {}
|
||||
// ): checks.$ZodCheck<T> {
|
||||
// return _custom(Class, fn, _params);
|
||||
// }
|
||||
// same as _custom but defaults to abort:false
|
||||
export function _refine<O = unknown, I = O>(
|
||||
Class: util.SchemaClass<schemas.$ZodCustom>,
|
||||
@@ -1489,80 +1482,6 @@ export function _refine<O = unknown, I = O>(
|
||||
return schema as any;
|
||||
}
|
||||
|
||||
export type $ZodSuperRefineIssue<T extends errors.$ZodIssueBase = errors.$ZodIssue> = T extends any
|
||||
? RawIssue<T>
|
||||
: never;
|
||||
type RawIssue<T extends errors.$ZodIssueBase> = T extends any
|
||||
? util.Flatten<
|
||||
util.MakePartial<T, "message" | "path"> & {
|
||||
/** The schema or check that originated this issue. */
|
||||
readonly inst?: schemas.$ZodType | checks.$ZodCheck;
|
||||
/** If `true`, Zod will execute subsequent checks/refinements instead of immediately aborting */
|
||||
readonly continue?: boolean | undefined;
|
||||
} & Record<string, unknown>
|
||||
>
|
||||
: never;
|
||||
|
||||
export interface $RefinementCtx<T = unknown> extends schemas.ParsePayload<T> {
|
||||
addIssue(arg: string | $ZodSuperRefineIssue): void;
|
||||
}
|
||||
|
||||
export function _superRefine<T>(fn: (arg: T, payload: $RefinementCtx<T>) => void | Promise<void>): checks.$ZodCheck<T> {
|
||||
const ch = _check<T>((payload) => {
|
||||
(payload as $RefinementCtx).addIssue = (issue) => {
|
||||
if (typeof issue === "string") {
|
||||
payload.issues.push(util.issue(issue, payload.value, ch._zod.def));
|
||||
} else {
|
||||
// for Zod 3 backwards compatibility
|
||||
const _issue: any = issue;
|
||||
if (_issue.fatal) _issue.continue = false;
|
||||
_issue.code ??= "custom";
|
||||
_issue.input ??= payload.value;
|
||||
_issue.inst ??= ch;
|
||||
_issue.continue ??= !ch._zod.def.abort; // abort is always undefined, so this is always true...
|
||||
payload.issues.push(util.issue(_issue));
|
||||
}
|
||||
};
|
||||
|
||||
return fn(payload.value, payload as $RefinementCtx<T>);
|
||||
});
|
||||
return ch;
|
||||
}
|
||||
|
||||
export function _check<O = unknown>(fn: schemas.CheckFn<O>, params?: string | $ZodCustomParams): checks.$ZodCheck<O> {
|
||||
const ch = new checks.$ZodCheck({
|
||||
check: "custom",
|
||||
...util.normalizeParams(params),
|
||||
});
|
||||
|
||||
ch._zod.check = fn;
|
||||
return ch;
|
||||
}
|
||||
|
||||
export function describe<T>(description: string): checks.$ZodCheck<T> {
|
||||
const ch = new checks.$ZodCheck({ check: "describe" });
|
||||
ch._zod.onattach = [
|
||||
(inst) => {
|
||||
const existing = registries.globalRegistry.get(inst) ?? {};
|
||||
registries.globalRegistry.add(inst, { ...existing, description });
|
||||
},
|
||||
];
|
||||
ch._zod.check = () => {}; // no-op check
|
||||
return ch;
|
||||
}
|
||||
|
||||
export function meta<T>(metadata: registries.GlobalMeta): checks.$ZodCheck<T> {
|
||||
const ch = new checks.$ZodCheck({ check: "meta" });
|
||||
ch._zod.onattach = [
|
||||
(inst) => {
|
||||
const existing = registries.globalRegistry.get(inst) ?? {};
|
||||
registries.globalRegistry.add(inst, { ...existing, ...metadata });
|
||||
},
|
||||
];
|
||||
ch._zod.check = () => {}; // no-op check
|
||||
return ch;
|
||||
}
|
||||
|
||||
// export type $ZodCustomParams = CheckTypeParams<schemas.$ZodCustom, "fn">
|
||||
|
||||
///////// STRINGBOOL /////////
|
||||
@@ -1581,12 +1500,16 @@ export interface $ZodStringBoolParams extends TypeParams {
|
||||
|
||||
export function _stringbool(
|
||||
Classes: {
|
||||
Codec?: typeof schemas.$ZodCodec;
|
||||
Pipe?: typeof schemas.$ZodPipe;
|
||||
Boolean?: typeof schemas.$ZodBoolean;
|
||||
Transform?: typeof schemas.$ZodTransform;
|
||||
String?: typeof schemas.$ZodString;
|
||||
},
|
||||
_params?: string | $ZodStringBoolParams
|
||||
): schemas.$ZodCodec<schemas.$ZodString, schemas.$ZodBoolean> {
|
||||
): schemas.$ZodPipe<
|
||||
schemas.$ZodPipe<schemas.$ZodString, schemas.$ZodTransform<boolean, string>>,
|
||||
schemas.$ZodBoolean<boolean>
|
||||
> {
|
||||
const params = util.normalizeParams(_params);
|
||||
|
||||
let truthyArray = params.truthy ?? ["true", "1", "yes", "on", "y", "enabled"];
|
||||
@@ -1599,19 +1522,15 @@ export function _stringbool(
|
||||
const truthySet = new Set(truthyArray);
|
||||
const falsySet = new Set(falsyArray);
|
||||
|
||||
const _Codec = Classes.Codec ?? schemas.$ZodCodec;
|
||||
const _Pipe = Classes.Pipe ?? schemas.$ZodPipe;
|
||||
const _Boolean = Classes.Boolean ?? schemas.$ZodBoolean;
|
||||
const _String = Classes.String ?? schemas.$ZodString;
|
||||
const _Transform = Classes.Transform ?? schemas.$ZodTransform;
|
||||
|
||||
const stringSchema = new _String({ type: "string", error: params.error });
|
||||
const booleanSchema = new _Boolean({ type: "boolean", error: params.error });
|
||||
|
||||
const codec = new _Codec({
|
||||
type: "pipe",
|
||||
in: stringSchema as any,
|
||||
out: booleanSchema as any,
|
||||
transform: ((input: string, payload: schemas.ParsePayload<string>) => {
|
||||
let data: string = input;
|
||||
const tx = new _Transform({
|
||||
type: "transform",
|
||||
transform: (input, payload: schemas.ParsePayload<unknown>) => {
|
||||
let data: string = input as string;
|
||||
if (params.case !== "sensitive") data = data.toLowerCase();
|
||||
if (truthySet.has(data)) {
|
||||
return true;
|
||||
@@ -1623,23 +1542,32 @@ export function _stringbool(
|
||||
expected: "stringbool",
|
||||
values: [...truthySet, ...falsySet],
|
||||
input: payload.value,
|
||||
inst: codec,
|
||||
continue: false,
|
||||
inst: tx,
|
||||
});
|
||||
return {} as never;
|
||||
}
|
||||
}) as any,
|
||||
reverseTransform: ((input: boolean, _payload: schemas.ParsePayload<boolean>) => {
|
||||
if (input === true) {
|
||||
return truthyArray[0] || "true";
|
||||
} else {
|
||||
return falsyArray[0] || "false";
|
||||
}
|
||||
}) as any,
|
||||
},
|
||||
error: params.error,
|
||||
}) as any;
|
||||
});
|
||||
// params.error;
|
||||
|
||||
return codec;
|
||||
const innerPipe = new _Pipe({
|
||||
type: "pipe",
|
||||
in: new _String({ type: "string", error: params.error }),
|
||||
out: tx,
|
||||
error: params.error,
|
||||
});
|
||||
|
||||
const outerPipe = new _Pipe({
|
||||
type: "pipe",
|
||||
in: innerPipe,
|
||||
out: new _Boolean({
|
||||
type: "boolean",
|
||||
error: params.error,
|
||||
}),
|
||||
error: params.error,
|
||||
});
|
||||
return outerPipe as any;
|
||||
}
|
||||
|
||||
export function _stringFormat<Format extends string>(
|
||||
|
||||
+2
-6
@@ -297,7 +297,6 @@ export const $ZodCheckNumberFormat: core.$constructor<$ZodCheckNumberFormat> = /
|
||||
expected: origin,
|
||||
format: def.format,
|
||||
code: "invalid_type",
|
||||
continue: false,
|
||||
input,
|
||||
inst,
|
||||
});
|
||||
@@ -470,7 +469,6 @@ export const $ZodCheckMaxSize: core.$constructor<$ZodCheckMaxSize> = /*@__PURE__
|
||||
origin: util.getSizableOrigin(input),
|
||||
code: "too_big",
|
||||
maximum: def.maximum,
|
||||
inclusive: true,
|
||||
input,
|
||||
inst,
|
||||
continue: !def.abort,
|
||||
@@ -520,7 +518,6 @@ export const $ZodCheckMinSize: core.$constructor<$ZodCheckMinSize> = /*@__PURE__
|
||||
origin: util.getSizableOrigin(input),
|
||||
code: "too_small",
|
||||
minimum: def.minimum,
|
||||
inclusive: true,
|
||||
input,
|
||||
inst,
|
||||
continue: !def.abort,
|
||||
@@ -1131,12 +1128,12 @@ export interface $ZodCheckMimeTypeDef extends $ZodCheckDef {
|
||||
mime: util.MimeTypes[];
|
||||
}
|
||||
|
||||
export interface $ZodCheckMimeTypeInternals<T extends schemas.File = schemas.File> extends $ZodCheckInternals<T> {
|
||||
export interface $ZodCheckMimeTypeInternals<T extends File = File> extends $ZodCheckInternals<T> {
|
||||
def: $ZodCheckMimeTypeDef;
|
||||
issc: errors.$ZodIssueInvalidValue;
|
||||
}
|
||||
|
||||
export interface $ZodCheckMimeType<T extends schemas.File = schemas.File> extends $ZodCheck<T> {
|
||||
export interface $ZodCheckMimeType<T extends File = File> extends $ZodCheck<T> {
|
||||
_zod: $ZodCheckMimeTypeInternals<T>;
|
||||
}
|
||||
|
||||
@@ -1155,7 +1152,6 @@ export const $ZodCheckMimeType: core.$constructor<$ZodCheckMimeType> = /*@__PURE
|
||||
values: def.mime,
|
||||
input: payload.value.type,
|
||||
inst,
|
||||
continue: !def.abort,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
+37
-31
@@ -20,34 +20,21 @@ export /*@__NO_SIDE_EFFECTS__*/ function $constructor<T extends ZodTrait, D = T[
|
||||
params?: { Parent?: typeof Class }
|
||||
): $constructor<T, D> {
|
||||
function init(inst: T, def: D) {
|
||||
if (!inst._zod) {
|
||||
Object.defineProperty(inst, "_zod", {
|
||||
value: {
|
||||
def,
|
||||
constr: _,
|
||||
traits: new Set(),
|
||||
},
|
||||
enumerable: false,
|
||||
});
|
||||
}
|
||||
Object.defineProperty(inst, "_zod", {
|
||||
value: inst._zod ?? {},
|
||||
enumerable: false,
|
||||
});
|
||||
|
||||
if (inst._zod.traits.has(name)) {
|
||||
return;
|
||||
}
|
||||
inst._zod.traits ??= new Set();
|
||||
|
||||
inst._zod.traits.add(name);
|
||||
|
||||
initializer(inst, def);
|
||||
|
||||
// support prototype modifications
|
||||
const proto = _.prototype;
|
||||
const keys = Object.keys(proto);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const k = keys[i]!;
|
||||
if (!(k in inst)) {
|
||||
(inst as any)[k] = proto[k].bind(inst);
|
||||
}
|
||||
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
|
||||
@@ -91,21 +78,40 @@ export class $ZodAsyncError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
export class $ZodEncodeError extends Error {
|
||||
constructor(name: string) {
|
||||
super(`Encountered unidirectional transform during encode: ${name}`);
|
||||
this.name = "ZodEncodeError";
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////// 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 } } ? T["_zod"]["input"] : unknown;
|
||||
export type output<T> = T extends { _zod: { output: any } } ? T["_zod"]["output"] : unknown;
|
||||
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 };
|
||||
|
||||
|
||||
+2
-2
@@ -33,12 +33,12 @@ export class Doc {
|
||||
}
|
||||
}
|
||||
|
||||
compile(): any {
|
||||
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")) as any;
|
||||
return new F(...args, lines.join("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
+60
-49
@@ -1,7 +1,6 @@
|
||||
import type { $ZodCheck, $ZodStringFormats } from "./checks.js";
|
||||
import { $constructor } from "./core.js";
|
||||
import type { $ZodType } from "./schemas.js";
|
||||
import type { StandardSchemaV1 } from "./standard-schema.js";
|
||||
import * as util from "./util.js";
|
||||
|
||||
///////////////////////////
|
||||
@@ -12,6 +11,7 @@ export interface $ZodIssueBase {
|
||||
readonly input?: unknown;
|
||||
readonly path: PropertyKey[];
|
||||
readonly message: string;
|
||||
// [k: string]: unknown;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -20,7 +20,7 @@ export interface $ZodIssueBase {
|
||||
export interface $ZodIssueInvalidType<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "invalid_type";
|
||||
readonly expected: $ZodType["_zod"]["def"]["type"];
|
||||
readonly input?: Input;
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueTooBig<Input = unknown> extends $ZodIssueBase {
|
||||
@@ -29,7 +29,7 @@ export interface $ZodIssueTooBig<Input = unknown> extends $ZodIssueBase {
|
||||
readonly maximum: number | bigint;
|
||||
readonly inclusive?: boolean;
|
||||
readonly exact?: boolean;
|
||||
readonly input?: Input;
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueTooSmall<Input = unknown> extends $ZodIssueBase {
|
||||
@@ -40,40 +40,39 @@ export interface $ZodIssueTooSmall<Input = unknown> extends $ZodIssueBase {
|
||||
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;
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueInvalidStringFormat extends $ZodIssueBase {
|
||||
readonly code: "invalid_format";
|
||||
readonly format: $ZodStringFormats | (string & {});
|
||||
readonly pattern?: string;
|
||||
readonly input?: 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;
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueUnrecognizedKeys extends $ZodIssueBase {
|
||||
readonly code: "unrecognized_keys";
|
||||
readonly keys: string[];
|
||||
readonly input?: Record<string, unknown>;
|
||||
readonly input: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface $ZodIssueInvalidUnion extends $ZodIssueBase {
|
||||
readonly code: "invalid_union";
|
||||
readonly errors: $ZodIssue[][];
|
||||
readonly input?: unknown;
|
||||
readonly discriminator?: string | undefined;
|
||||
readonly input: unknown;
|
||||
}
|
||||
|
||||
export interface $ZodIssueInvalidKey<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "invalid_key";
|
||||
readonly origin: "map" | "record";
|
||||
readonly issues: $ZodIssue[];
|
||||
readonly input?: Input;
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueInvalidElement<Input = unknown> extends $ZodIssueBase {
|
||||
@@ -81,19 +80,19 @@ export interface $ZodIssueInvalidElement<Input = unknown> extends $ZodIssueBase
|
||||
readonly origin: "map" | "set";
|
||||
readonly key: unknown;
|
||||
readonly issues: $ZodIssue[];
|
||||
readonly input?: Input;
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueInvalidValue<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "invalid_value";
|
||||
readonly values: util.Primitive[];
|
||||
readonly input?: Input;
|
||||
readonly input: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueCustom extends $ZodIssueBase {
|
||||
readonly code: "custom";
|
||||
readonly params?: Record<string, any> | undefined;
|
||||
readonly input?: unknown;
|
||||
readonly input: unknown;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
@@ -156,21 +155,17 @@ export type $ZodIssue =
|
||||
|
||||
export type $ZodIssueCode = $ZodIssue["code"];
|
||||
|
||||
export type $ZodInternalIssue<T extends $ZodIssueBase = $ZodIssue> = T extends any ? RawIssue<T> : never;
|
||||
type RawIssue<T extends $ZodIssueBase> = T extends any
|
||||
? 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;
|
||||
/** If `true`, Zod will continue executing checks/refinements after this issue. */
|
||||
readonly continue?: boolean | undefined;
|
||||
} & Record<string, unknown>
|
||||
>
|
||||
: never;
|
||||
|
||||
export type $ZodRawIssue<T extends $ZodIssueBase = $ZodIssue> = $ZodInternalIssue<T>;
|
||||
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:
|
||||
@@ -201,8 +196,13 @@ const initializer = (inst: $ZodError, def: $ZodIssue[]): void => {
|
||||
value: def,
|
||||
enumerable: false,
|
||||
});
|
||||
inst.message = JSON.stringify(def, util.jsonStringifyReplacer, 2);
|
||||
|
||||
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,
|
||||
@@ -226,9 +226,9 @@ type _FlattenedError<T, U = string> = {
|
||||
|
||||
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<T, U>(error: $ZodError<T>, mapper = (issue: $ZodIssue) => issue.message as U) {
|
||||
const fieldErrors: Record<PropertyKey, any> = {};
|
||||
const formErrors: 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]!] || [];
|
||||
@@ -254,7 +254,12 @@ export type $ZodFormattedError<T, U = string> = {
|
||||
|
||||
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, U>(error: $ZodError<T>, mapper = (issue: $ZodIssue) => issue.message as 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) {
|
||||
@@ -290,20 +295,23 @@ export function formatError<T, U>(error: $ZodError<T>, mapper = (issue: $ZodIssu
|
||||
return fieldErrors;
|
||||
}
|
||||
|
||||
export type $ZodErrorTree<T, U = string> = T extends util.Primitive
|
||||
? { errors: U[] }
|
||||
: 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 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, U>(error: $ZodError<T>, mapper = (issue: $ZodIssue) => issue.message as U) {
|
||||
const result: $ZodErrorTree<T, U> = { errors: [] } as any;
|
||||
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) {
|
||||
@@ -381,9 +389,8 @@ export function treeifyError<T, U>(error: $ZodError<T>, mapper = (issue: $ZodIss
|
||||
* ✖ Invalid input: expected number
|
||||
* ```
|
||||
*/
|
||||
export function toDotPath(_path: readonly (string | number | symbol | StandardSchemaV1.PathSegment)[]): string {
|
||||
export function toDotPath(path: (string | number | symbol)[]): string {
|
||||
const segs: string[] = [];
|
||||
const path: PropertyKey[] = _path.map((seg: any) => (typeof seg === "object" ? seg.key : seg));
|
||||
for (const seg of path) {
|
||||
if (typeof seg === "number") segs.push(`[${seg}]`);
|
||||
else if (typeof seg === "symbol") segs.push(`[${JSON.stringify(String(seg))}]`);
|
||||
@@ -397,10 +404,14 @@ export function toDotPath(_path: readonly (string | number | symbol | StandardSc
|
||||
return segs.join("");
|
||||
}
|
||||
|
||||
export function prettifyError(error: StandardSchemaV1.FailureResult): string {
|
||||
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);
|
||||
const issues = [...error.issues].sort((a, b) => a.path.length - b.path.length);
|
||||
|
||||
// Process each issue
|
||||
for (const issue of issues) {
|
||||
|
||||
+1
@@ -9,6 +9,7 @@ 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";
|
||||
|
||||
+3
-7
@@ -45,10 +45,7 @@ export type Schema =
|
||||
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#"
|
||||
| "http://json-schema.org/draft-04/schema#";
|
||||
$schema?: "https://json-schema.org/draft/2020-12/schema" | "http://json-schema.org/draft-07/schema#";
|
||||
$id?: string;
|
||||
$anchor?: string;
|
||||
$ref?: string;
|
||||
@@ -78,9 +75,9 @@ export type JSONSchema = {
|
||||
not?: _JSONSchema;
|
||||
multipleOf?: number;
|
||||
maximum?: number;
|
||||
exclusiveMaximum?: number | boolean;
|
||||
exclusiveMaximum?: number;
|
||||
minimum?: number;
|
||||
exclusiveMinimum?: number | boolean;
|
||||
exclusiveMinimum?: number;
|
||||
maxLength?: number;
|
||||
minLength?: number;
|
||||
pattern?: string;
|
||||
@@ -104,7 +101,6 @@ export type JSONSchema = {
|
||||
deprecated?: boolean;
|
||||
readOnly?: boolean;
|
||||
writeOnly?: boolean;
|
||||
nullable?: boolean;
|
||||
examples?: unknown[];
|
||||
format?: string;
|
||||
contentMediaType?: string;
|
||||
|
||||
-101
@@ -92,104 +92,3 @@ export const _safeParseAsync: (_Err: $ZodErrorClass) => $SafeParseAsync = (_Err)
|
||||
};
|
||||
|
||||
export const safeParseAsync: $SafeParseAsync = /* @__PURE__*/ _safeParseAsync(errors.$ZodRealError);
|
||||
|
||||
// Codec functions
|
||||
export type $Encode = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => core.input<T>;
|
||||
|
||||
export const _encode: (_Err: $ZodErrorClass) => $Encode = (_Err) => (schema, value, _ctx) => {
|
||||
const ctx = _ctx ? Object.assign(_ctx, { direction: "backward" as const }) : { direction: "backward" as const };
|
||||
return _parse(_Err)(schema, value, ctx as any) as any;
|
||||
};
|
||||
|
||||
export const encode: $Encode = /* @__PURE__*/ _encode(errors.$ZodRealError);
|
||||
|
||||
export type $Decode = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => core.output<T>;
|
||||
|
||||
export const _decode: (_Err: $ZodErrorClass) => $Decode = (_Err) => (schema, value, _ctx) => {
|
||||
return _parse(_Err)(schema, value, _ctx);
|
||||
};
|
||||
|
||||
export const decode: $Decode = /* @__PURE__*/ _decode(errors.$ZodRealError);
|
||||
|
||||
export type $EncodeAsync = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => Promise<core.input<T>>;
|
||||
|
||||
export const _encodeAsync: (_Err: $ZodErrorClass) => $EncodeAsync = (_Err) => async (schema, value, _ctx) => {
|
||||
const ctx = _ctx ? Object.assign(_ctx, { direction: "backward" as const }) : { direction: "backward" as const };
|
||||
return _parseAsync(_Err)(schema, value, ctx as any) as any;
|
||||
};
|
||||
|
||||
export const encodeAsync: $EncodeAsync = /* @__PURE__*/ _encodeAsync(errors.$ZodRealError);
|
||||
|
||||
export type $DecodeAsync = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => Promise<core.output<T>>;
|
||||
|
||||
export const _decodeAsync: (_Err: $ZodErrorClass) => $DecodeAsync = (_Err) => async (schema, value, _ctx) => {
|
||||
return _parseAsync(_Err)(schema, value, _ctx);
|
||||
};
|
||||
|
||||
export const decodeAsync: $DecodeAsync = /* @__PURE__*/ _decodeAsync(errors.$ZodRealError);
|
||||
|
||||
export type $SafeEncode = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => util.SafeParseResult<core.input<T>>;
|
||||
|
||||
export const _safeEncode: (_Err: $ZodErrorClass) => $SafeEncode = (_Err) => (schema, value, _ctx) => {
|
||||
const ctx = _ctx ? Object.assign(_ctx, { direction: "backward" as const }) : { direction: "backward" as const };
|
||||
return _safeParse(_Err)(schema, value, ctx as any) as any;
|
||||
};
|
||||
|
||||
export const safeEncode: $SafeEncode = /* @__PURE__*/ _safeEncode(errors.$ZodRealError);
|
||||
|
||||
export type $SafeDecode = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => util.SafeParseResult<core.output<T>>;
|
||||
|
||||
export const _safeDecode: (_Err: $ZodErrorClass) => $SafeDecode = (_Err) => (schema, value, _ctx) => {
|
||||
return _safeParse(_Err)(schema, value, _ctx);
|
||||
};
|
||||
|
||||
export const safeDecode: $SafeDecode = /* @__PURE__*/ _safeDecode(errors.$ZodRealError);
|
||||
|
||||
export type $SafeEncodeAsync = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => Promise<util.SafeParseResult<core.input<T>>>;
|
||||
|
||||
export const _safeEncodeAsync: (_Err: $ZodErrorClass) => $SafeEncodeAsync = (_Err) => async (schema, value, _ctx) => {
|
||||
const ctx = _ctx ? Object.assign(_ctx, { direction: "backward" as const }) : { direction: "backward" as const };
|
||||
return _safeParseAsync(_Err)(schema, value, ctx as any) as any;
|
||||
};
|
||||
|
||||
export const safeEncodeAsync: $SafeEncodeAsync = /* @__PURE__*/ _safeEncodeAsync(errors.$ZodRealError);
|
||||
|
||||
export type $SafeDecodeAsync = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => Promise<util.SafeParseResult<core.output<T>>>;
|
||||
|
||||
export const _safeDecodeAsync: (_Err: $ZodErrorClass) => $SafeDecodeAsync = (_Err) => async (schema, value, _ctx) => {
|
||||
return _safeParseAsync(_Err)(schema, value, _ctx);
|
||||
};
|
||||
|
||||
export const safeDecodeAsync: $SafeDecodeAsync = /* @__PURE__*/ _safeDecodeAsync(errors.$ZodRealError);
|
||||
|
||||
+15
-62
@@ -1,5 +1,3 @@
|
||||
import * as util from "./util.js";
|
||||
|
||||
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}$/;
|
||||
@@ -18,12 +16,12 @@ export const extendedDuration: RegExp =
|
||||
/** 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 9562/4122 UUID.
|
||||
/** 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|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;
|
||||
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})$`
|
||||
);
|
||||
@@ -46,13 +44,12 @@ export const rfc5322Email =
|
||||
|
||||
/** 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 idnEmail = unicodeEmail;
|
||||
|
||||
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
|
||||
|
||||
const _emoji: string = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;
|
||||
export const _emoji = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;
|
||||
export function emoji(): RegExp {
|
||||
return new RegExp(_emoji, "u");
|
||||
}
|
||||
@@ -60,11 +57,8 @@ export function emoji(): RegExp {
|
||||
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}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
|
||||
export const mac = (delimiter?: string): RegExp => {
|
||||
const escapedDelim = util.escapeRegex(delimiter ?? ":");
|
||||
return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
|
||||
};
|
||||
/^(([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 =
|
||||
@@ -75,10 +69,9 @@ export const base64: RegExp = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==
|
||||
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-]+$/;
|
||||
export const hostname: RegExp =
|
||||
/^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
|
||||
|
||||
// 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)
|
||||
@@ -116,8 +109,7 @@ export function datetime(args: {
|
||||
const time = timeSource({ precision: args.precision });
|
||||
const opts = ["Z"];
|
||||
if (args.local) opts.push("");
|
||||
// if (args.offset) opts.push(`([+-]\\d{2}:\\d{2})`);
|
||||
if (args.offset) opts.push(`([+-](?:[01]\\d|2[0-3]):[0-5]\\d)`);
|
||||
if (args.offset) opts.push(`([+-]\\d{2}:\\d{2})`);
|
||||
const timeRegex = `${time}(?:${opts.join("|")})`;
|
||||
|
||||
return new RegExp(`^${dateSource}T(?:${timeRegex})$`);
|
||||
@@ -128,55 +120,16 @@ export const string = (params?: { minimum?: number | undefined; maximum?: number
|
||||
return new RegExp(`^${regex}$`);
|
||||
};
|
||||
|
||||
export const bigint: RegExp = /^-?\d+n?$/;
|
||||
export const integer: RegExp = /^-?\d+$/;
|
||||
export const number: RegExp = /^-?\d+(?:\.\d+)?/;
|
||||
export const boolean: RegExp = /^(?:true|false)$/i;
|
||||
const _null: RegExp = /^null$/i;
|
||||
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;
|
||||
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]*$/;
|
||||
|
||||
// regex for hexadecimal strings (any length)
|
||||
export const hex: RegExp = /^[0-9a-fA-F]*$/;
|
||||
|
||||
// Hash regexes for different algorithms and encodings
|
||||
// Helper function to create base64 regex with exact length and padding
|
||||
function fixedBase64(bodyLength: number, padding: "" | "=" | "=="): RegExp {
|
||||
return new RegExp(`^[A-Za-z0-9+/]{${bodyLength}}${padding}$`);
|
||||
}
|
||||
|
||||
// Helper function to create base64url regex with exact length (no padding)
|
||||
function fixedBase64url(length: number): RegExp {
|
||||
return new RegExp(`^[A-Za-z0-9_-]{${length}}$`);
|
||||
}
|
||||
|
||||
// MD5 (16 bytes): base64 = 24 chars total (22 + "==")
|
||||
export const md5_hex: RegExp = /^[0-9a-fA-F]{32}$/;
|
||||
export const md5_base64: RegExp = /*@__PURE__*/ fixedBase64(22, "==");
|
||||
export const md5_base64url: RegExp = /*@__PURE__*/ fixedBase64url(22);
|
||||
|
||||
// SHA1 (20 bytes): base64 = 28 chars total (27 + "=")
|
||||
export const sha1_hex: RegExp = /^[0-9a-fA-F]{40}$/;
|
||||
export const sha1_base64: RegExp = /*@__PURE__*/ fixedBase64(27, "=");
|
||||
export const sha1_base64url: RegExp = /*@__PURE__*/ fixedBase64url(27);
|
||||
|
||||
// SHA256 (32 bytes): base64 = 44 chars total (43 + "=")
|
||||
export const sha256_hex: RegExp = /^[0-9a-fA-F]{64}$/;
|
||||
export const sha256_base64: RegExp = /*@__PURE__*/ fixedBase64(43, "=");
|
||||
export const sha256_base64url: RegExp = /*@__PURE__*/ fixedBase64url(43);
|
||||
|
||||
// SHA384 (48 bytes): base64 = 64 chars total (no padding)
|
||||
export const sha384_hex: RegExp = /^[0-9a-fA-F]{96}$/;
|
||||
export const sha384_base64: RegExp = /*@__PURE__*/ fixedBase64(64, "");
|
||||
export const sha384_base64url: RegExp = /*@__PURE__*/ fixedBase64url(64);
|
||||
|
||||
// SHA512 (64 bytes): base64 = 88 chars total (86 + "==")
|
||||
export const sha512_hex: RegExp = /^[0-9a-fA-F]{128}$/;
|
||||
export const sha512_base64: RegExp = /*@__PURE__*/ fixedBase64(86, "==");
|
||||
export const sha512_base64url: RegExp = /*@__PURE__*/ fixedBase64url(86);
|
||||
|
||||
+5
-17
@@ -23,11 +23,11 @@ export type $replace<Meta, S extends $ZodType> = Meta extends $output
|
||||
? { [K in keyof Meta]: $replace<Meta[K], S> }
|
||||
: Meta;
|
||||
|
||||
type MetadataType = object | undefined;
|
||||
type MetadataType = Record<string, unknown> | undefined;
|
||||
export class $ZodRegistry<Meta extends MetadataType = MetadataType, Schema extends $ZodType = $ZodType> {
|
||||
_meta!: Meta;
|
||||
_schema!: Schema;
|
||||
_map: WeakMap<Schema, $replace<Meta, Schema>> = new WeakMap();
|
||||
_map: Map<Schema, $replace<Meta, Schema>> = new Map();
|
||||
_idmap: Map<string, Schema> = new Map();
|
||||
|
||||
add<S extends Schema>(
|
||||
@@ -46,7 +46,7 @@ export class $ZodRegistry<Meta extends MetadataType = MetadataType, Schema exten
|
||||
}
|
||||
|
||||
clear(): this {
|
||||
this._map = new WeakMap();
|
||||
this._map = new Map();
|
||||
this._idmap = new Map();
|
||||
return this;
|
||||
}
|
||||
@@ -68,8 +68,7 @@ export class $ZodRegistry<Meta extends MetadataType = MetadataType, Schema exten
|
||||
if (p) {
|
||||
const pm: any = { ...(this.get(p) ?? {}) };
|
||||
delete pm.id; // do not inherit id
|
||||
const f = { ...pm, ...this._map.get(schema) } as any;
|
||||
return Object.keys(f).length ? f : undefined;
|
||||
return { ...pm, ...this._map.get(schema) } as any;
|
||||
}
|
||||
return this._map.get(schema) as any;
|
||||
}
|
||||
@@ -94,15 +93,4 @@ export function registry<T extends MetadataType = MetadataType, S extends $ZodTy
|
||||
return new $ZodRegistry<T, S>();
|
||||
}
|
||||
|
||||
interface GlobalThisWithRegistry {
|
||||
/**
|
||||
* The globalRegistry instance shared across both CommonJS and ESM builds.
|
||||
* By attaching the registry to `globalThis`, this property ensures a single, deduplicated instance
|
||||
* is used regardless of whether the package is loaded via `require` (CJS) or `import` (ESM).
|
||||
* This prevents dual package hazards and keeps registry state consistent.
|
||||
*/
|
||||
__zod_globalRegistry?: $ZodRegistry<GlobalMeta>;
|
||||
}
|
||||
|
||||
(globalThis as GlobalThisWithRegistry).__zod_globalRegistry ??= registry<GlobalMeta>();
|
||||
export const globalRegistry: $ZodRegistry<GlobalMeta> = (globalThis as GlobalThisWithRegistry).__zod_globalRegistry!;
|
||||
export const globalRegistry: $ZodRegistry<GlobalMeta> = /*@__PURE__*/ registry<GlobalMeta>();
|
||||
|
||||
+261
-753
File diff suppressed because it is too large
Load Diff
+121
-152
@@ -10,10 +10,8 @@ interface JSONSchemaGeneratorParams {
|
||||
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
|
||||
* - `"draft-4"` — JSON Schema Draft 4
|
||||
* - `"openapi-3.0"` — OpenAPI 3.0 Schema Object */
|
||||
target?: "draft-4" | "draft-7" | "draft-2020-12" | "openapi-3.0";
|
||||
* - `"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 `{}` */
|
||||
@@ -73,7 +71,7 @@ interface Seen {
|
||||
|
||||
export class JSONSchemaGenerator {
|
||||
metadataRegistry: $ZodRegistry<Record<string, any>>;
|
||||
target: "draft-4" | "draft-7" | "draft-2020-12" | "openapi-3.0";
|
||||
target: "draft-7" | "draft-2020-12";
|
||||
unrepresentable: "throw" | "any";
|
||||
override: (ctx: {
|
||||
zodSchema: schemas.$ZodTypes;
|
||||
@@ -165,9 +163,7 @@ export class JSONSchemaGenerator {
|
||||
else if (regexes.length > 1) {
|
||||
result.schema.allOf = [
|
||||
...regexes.map((regex) => ({
|
||||
...(this.target === "draft-7" || this.target === "draft-4" || this.target === "openapi-3.0"
|
||||
? ({ type: "string" } as const)
|
||||
: {}),
|
||||
...(this.target === "draft-7" ? ({ type: "string" } as const) : {}),
|
||||
pattern: regex.source,
|
||||
})),
|
||||
];
|
||||
@@ -182,33 +178,19 @@ export class JSONSchemaGenerator {
|
||||
if (typeof format === "string" && format.includes("int")) json.type = "integer";
|
||||
else json.type = "number";
|
||||
|
||||
if (typeof exclusiveMinimum === "number") {
|
||||
if (this.target === "draft-4" || this.target === "openapi-3.0") {
|
||||
json.minimum = exclusiveMinimum;
|
||||
json.exclusiveMinimum = true;
|
||||
} else {
|
||||
json.exclusiveMinimum = exclusiveMinimum;
|
||||
}
|
||||
}
|
||||
if (typeof exclusiveMinimum === "number") json.exclusiveMinimum = exclusiveMinimum;
|
||||
if (typeof minimum === "number") {
|
||||
json.minimum = minimum;
|
||||
if (typeof exclusiveMinimum === "number" && this.target !== "draft-4") {
|
||||
if (typeof exclusiveMinimum === "number") {
|
||||
if (exclusiveMinimum >= minimum) delete json.minimum;
|
||||
else delete json.exclusiveMinimum;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof exclusiveMaximum === "number") {
|
||||
if (this.target === "draft-4" || this.target === "openapi-3.0") {
|
||||
json.maximum = exclusiveMaximum;
|
||||
json.exclusiveMaximum = true;
|
||||
} else {
|
||||
json.exclusiveMaximum = exclusiveMaximum;
|
||||
}
|
||||
}
|
||||
if (typeof exclusiveMaximum === "number") json.exclusiveMaximum = exclusiveMaximum;
|
||||
if (typeof maximum === "number") {
|
||||
json.maximum = maximum;
|
||||
if (typeof exclusiveMaximum === "number" && this.target !== "draft-4") {
|
||||
if (typeof exclusiveMaximum === "number") {
|
||||
if (exclusiveMaximum <= maximum) delete json.maximum;
|
||||
else delete json.exclusiveMaximum;
|
||||
}
|
||||
@@ -236,11 +218,7 @@ export class JSONSchemaGenerator {
|
||||
break;
|
||||
}
|
||||
case "null": {
|
||||
if (this.target === "openapi-3.0") {
|
||||
_json.type = "string";
|
||||
_json.nullable = true;
|
||||
_json.enum = [null];
|
||||
} else _json.type = "null";
|
||||
_json.type = "null";
|
||||
break;
|
||||
}
|
||||
case "any": {
|
||||
@@ -330,20 +308,12 @@ export class JSONSchemaGenerator {
|
||||
}
|
||||
case "union": {
|
||||
const json: JSONSchema.BaseSchema = _json as any;
|
||||
// Discriminated unions use oneOf (exactly one match) instead of anyOf (one or more matches)
|
||||
// because the discriminator field ensures mutual exclusivity between options in JSON Schema
|
||||
const isDiscriminated = (def as any).discriminator !== undefined;
|
||||
const options = def.options.map((x, i) =>
|
||||
json.anyOf = def.options.map((x, i) =>
|
||||
this.process(x, {
|
||||
...params,
|
||||
path: [...params.path, isDiscriminated ? "oneOf" : "anyOf", i],
|
||||
path: [...params.path, "anyOf", i],
|
||||
})
|
||||
);
|
||||
if (isDiscriminated) {
|
||||
json.oneOf = options;
|
||||
} else {
|
||||
json.anyOf = options;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "intersection": {
|
||||
@@ -368,48 +338,35 @@ export class JSONSchemaGenerator {
|
||||
case "tuple": {
|
||||
const json: JSONSchema.ArraySchema = _json as any;
|
||||
json.type = "array";
|
||||
|
||||
const prefixPath = this.target === "draft-2020-12" ? "prefixItems" : "items";
|
||||
const restPath =
|
||||
this.target === "draft-2020-12" ? "items" : this.target === "openapi-3.0" ? "items" : "additionalItems";
|
||||
|
||||
const prefixItems = def.items.map((x, i) =>
|
||||
this.process(x, {
|
||||
...params,
|
||||
path: [...params.path, prefixPath, i],
|
||||
})
|
||||
this.process(x, { ...params, path: [...params.path, "prefixItems", i] })
|
||||
);
|
||||
const rest = def.rest
|
||||
? this.process(def.rest, {
|
||||
...params,
|
||||
path: [...params.path, restPath, ...(this.target === "openapi-3.0" ? [def.items.length] : [])],
|
||||
})
|
||||
: null;
|
||||
|
||||
if (this.target === "draft-2020-12") {
|
||||
json.prefixItems = prefixItems;
|
||||
if (rest) {
|
||||
json.items = rest;
|
||||
}
|
||||
} else if (this.target === "openapi-3.0") {
|
||||
json.items = {
|
||||
anyOf: prefixItems,
|
||||
};
|
||||
|
||||
if (rest) {
|
||||
json.items.anyOf!.push(rest);
|
||||
}
|
||||
json.minItems = prefixItems.length;
|
||||
if (!rest) {
|
||||
json.maxItems = prefixItems.length;
|
||||
}
|
||||
} else {
|
||||
json.items = prefixItems;
|
||||
if (rest) {
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -422,12 +379,7 @@ export class JSONSchemaGenerator {
|
||||
case "record": {
|
||||
const json: JSONSchema.ObjectSchema = _json as any;
|
||||
json.type = "object";
|
||||
if (this.target === "draft-7" || this.target === "draft-2020-12") {
|
||||
json.propertyNames = this.process(def.keyType, {
|
||||
...params,
|
||||
path: [...params.path, "propertyNames"],
|
||||
});
|
||||
}
|
||||
json.propertyNames = this.process(def.keyType, { ...params, path: [...params.path, "propertyNames"] });
|
||||
json.additionalProperties = this.process(def.valueType, {
|
||||
...params,
|
||||
path: [...params.path, "additionalProperties"],
|
||||
@@ -480,11 +432,7 @@ export class JSONSchemaGenerator {
|
||||
} else if (vals.length === 1) {
|
||||
const val = vals[0]!;
|
||||
json.type = val === null ? ("null" as const) : (typeof val as any);
|
||||
if (this.target === "draft-4" || this.target === "openapi-3.0") {
|
||||
json.enum = [val];
|
||||
} else {
|
||||
json.const = val;
|
||||
}
|
||||
json.const = val;
|
||||
} else {
|
||||
if (vals.every((v) => typeof v === "number")) json.type = "number";
|
||||
if (vals.every((v) => typeof v === "string")) json.type = "string";
|
||||
@@ -534,12 +482,7 @@ export class JSONSchemaGenerator {
|
||||
|
||||
case "nullable": {
|
||||
const inner = this.process(def.innerType, params);
|
||||
if (this.target === "openapi-3.0") {
|
||||
result.ref = def.innerType;
|
||||
_json.nullable = true;
|
||||
} else {
|
||||
_json.anyOf = [inner, { type: "null" }];
|
||||
}
|
||||
_json.anyOf = [inner, { type: "null" }];
|
||||
break;
|
||||
}
|
||||
case "nonoptional": {
|
||||
@@ -627,12 +570,6 @@ export class JSONSchemaGenerator {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "function": {
|
||||
if (this.unrepresentable === "throw") {
|
||||
throw new Error("Function types cannot be represented in JSON Schema");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
def satisfies never;
|
||||
}
|
||||
@@ -812,10 +749,7 @@ export class JSONSchemaGenerator {
|
||||
|
||||
// merge referenced schema into current
|
||||
const refSchema = this.seen.get(ref)!.schema;
|
||||
if (
|
||||
refSchema.$ref &&
|
||||
(params.target === "draft-7" || params.target === "draft-4" || params.target === "openapi-3.0")
|
||||
) {
|
||||
if (refSchema.$ref && params.target === "draft-7") {
|
||||
schema.allOf = schema.allOf ?? [];
|
||||
schema.allOf.push(refSchema);
|
||||
} else {
|
||||
@@ -842,12 +776,7 @@ export class JSONSchemaGenerator {
|
||||
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 if (this.target === "draft-4") {
|
||||
result.$schema = "http://json-schema.org/draft-04/schema#";
|
||||
} else if (this.target === "openapi-3.0") {
|
||||
// OpenAPI 3.0 schema objects should not include a $schema property
|
||||
} else {
|
||||
// @ts-ignore
|
||||
console.warn(`Invalid target: ${this.target}`);
|
||||
}
|
||||
|
||||
@@ -954,55 +883,95 @@ function isTransforming(
|
||||
if (ctx.seen.has(_schema)) return false;
|
||||
ctx.seen.add(_schema);
|
||||
|
||||
const def = (_schema as schemas.$ZodTypes)._zod.def;
|
||||
|
||||
if (def.type === "transform") return true;
|
||||
|
||||
if (def.type === "array") return isTransforming(def.element, ctx);
|
||||
if (def.type === "set") return isTransforming(def.valueType, ctx);
|
||||
if (def.type === "lazy") return isTransforming(def.getter(), ctx);
|
||||
|
||||
if (
|
||||
def.type === "promise" ||
|
||||
def.type === "optional" ||
|
||||
def.type === "nonoptional" ||
|
||||
def.type === "nullable" ||
|
||||
def.type === "readonly" ||
|
||||
def.type === "default" ||
|
||||
def.type === "prefault"
|
||||
) {
|
||||
return isTransforming(def.innerType, ctx);
|
||||
}
|
||||
|
||||
if (def.type === "intersection") {
|
||||
return isTransforming(def.left, ctx) || isTransforming(def.right, ctx);
|
||||
}
|
||||
if (def.type === "record" || def.type === "map") {
|
||||
return isTransforming(def.keyType, ctx) || isTransforming(def.valueType, ctx);
|
||||
}
|
||||
if (def.type === "pipe") {
|
||||
return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);
|
||||
}
|
||||
|
||||
if (def.type === "object") {
|
||||
for (const key in def.shape) {
|
||||
if (isTransforming(def.shape[key]!, ctx)) return true;
|
||||
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);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (def.type === "union") {
|
||||
for (const option of def.options) {
|
||||
if (isTransforming(option, ctx)) return true;
|
||||
case "object": {
|
||||
for (const key in def.shape) {
|
||||
if (isTransforming(def.shape[key]!, ctx)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (def.type === "tuple") {
|
||||
for (const item of def.items) {
|
||||
if (isTransforming(item, ctx)) return true;
|
||||
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);
|
||||
}
|
||||
if (def.rest && isTransforming(def.rest, ctx)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
// 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}`);
|
||||
}
|
||||
|
||||
+100
-246
@@ -20,10 +20,6 @@ export type JWTAlgorithm =
|
||||
| "PS512"
|
||||
| "EdDSA"
|
||||
| (string & {});
|
||||
|
||||
export type HashAlgorithm = "md5" | "sha1" | "sha256" | "sha384" | "sha512";
|
||||
export type HashEncoding = "hex" | "base64" | "base64url";
|
||||
export type HashFormat = `${HashAlgorithm}_${HashEncoding}`;
|
||||
export type IPVersion = "v4" | "v6";
|
||||
export type MimeTypes =
|
||||
| "application/json"
|
||||
@@ -127,7 +123,6 @@ 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> = {
|
||||
// @ts-ignore
|
||||
[K in keyof T]: T[K];
|
||||
} & {};
|
||||
|
||||
@@ -246,36 +241,23 @@ export function cleanRegex(source: string): string {
|
||||
|
||||
export function floatSafeRemainder(val: number, step: number): number {
|
||||
const valDecCount = (val.toString().split(".")[1] || "").length;
|
||||
const stepString = step.toString();
|
||||
let stepDecCount = (stepString.split(".")[1] || "").length;
|
||||
if (stepDecCount === 0 && /\d?e-\d?/.test(stepString)) {
|
||||
const match = stepString.match(/\d?e-(\d?)/);
|
||||
if (match?.[1]) {
|
||||
stepDecCount = Number.parseInt(match[1]);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const EVALUATING = Symbol("evaluating");
|
||||
|
||||
export function defineLazy<T, K extends keyof T>(object: T, key: K, getter: () => T[K]): void {
|
||||
let value: T[K] | typeof EVALUATING | undefined = undefined;
|
||||
const set = false;
|
||||
Object.defineProperty(object, key, {
|
||||
get() {
|
||||
if (value === EVALUATING) {
|
||||
// Circular reference detected, return undefined to break the cycle
|
||||
return undefined as T[K];
|
||||
if (!set) {
|
||||
const value = getter();
|
||||
object[key] = value;
|
||||
return value;
|
||||
}
|
||||
if (value === undefined) {
|
||||
value = EVALUATING;
|
||||
value = getter();
|
||||
}
|
||||
return value;
|
||||
throw new Error("cached value already set");
|
||||
},
|
||||
set(v) {
|
||||
Object.defineProperty(object, key, {
|
||||
@@ -288,10 +270,6 @@ export function defineLazy<T, K extends keyof T>(object: T, key: K, getter: () =
|
||||
});
|
||||
}
|
||||
|
||||
export function objectClone(obj: object) {
|
||||
return Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
|
||||
}
|
||||
|
||||
export function assignProp<T extends object, K extends PropertyKey>(
|
||||
target: T,
|
||||
prop: K,
|
||||
@@ -305,21 +283,6 @@ export function assignProp<T extends object, K extends PropertyKey>(
|
||||
});
|
||||
}
|
||||
|
||||
export function mergeDefs(...defs: Record<string, any>[]): any {
|
||||
const mergedDescriptors: Record<string, PropertyDescriptor> = {};
|
||||
|
||||
for (const def of defs) {
|
||||
const descriptors = Object.getOwnPropertyDescriptors(def);
|
||||
Object.assign(mergedDescriptors, descriptors);
|
||||
}
|
||||
|
||||
return Object.defineProperties({}, mergedDescriptors);
|
||||
}
|
||||
|
||||
export function cloneDef(schema: schemas.$ZodType): any {
|
||||
return mergeDefs(schema._zod.def);
|
||||
}
|
||||
|
||||
export function getElementAtPath(obj: any, path: (string | number)[] | null | undefined): any {
|
||||
if (!path) return obj;
|
||||
return path.reduce((acc, key) => acc?.[key], obj);
|
||||
@@ -351,25 +314,15 @@ export function esc(str: string): string {
|
||||
return JSON.stringify(str);
|
||||
}
|
||||
|
||||
export function slugify(input: string): string {
|
||||
return input
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.replace(/[^\w\s-]/g, "")
|
||||
.replace(/[\s_-]+/g, "-")
|
||||
.replace(/^-+|-+$/g, "");
|
||||
}
|
||||
|
||||
export const captureStackTrace: (targetObject: object, constructorOpt?: Function) => void = (
|
||||
"captureStackTrace" in Error ? Error.captureStackTrace : (..._args: any[]) => {}
|
||||
) as any;
|
||||
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(() => {
|
||||
// @ts-ignore
|
||||
if (typeof navigator !== "undefined" && navigator?.userAgent?.includes("Cloudflare")) {
|
||||
return false;
|
||||
}
|
||||
@@ -390,8 +343,6 @@ export function isPlainObject(o: any): o is Record<PropertyKey, unknown> {
|
||||
const ctor = o.constructor;
|
||||
if (ctor === undefined) return true;
|
||||
|
||||
if (typeof ctor !== "function") return true;
|
||||
|
||||
// modified prototype
|
||||
const prot = ctor.prototype;
|
||||
if (isObject(prot) === false) return false;
|
||||
@@ -404,12 +355,6 @@ export function isPlainObject(o: any): o is Record<PropertyKey, unknown> {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function shallowClone(o: any): any {
|
||||
if (isPlainObject(o)) return { ...o };
|
||||
if (Array.isArray(o)) return [...o];
|
||||
return o;
|
||||
}
|
||||
|
||||
export function numKeys(data: any): number {
|
||||
let keyCount = 0;
|
||||
for (const key in data) {
|
||||
@@ -464,7 +409,6 @@ export const getParsedType = (data: any): ParsedTypes => {
|
||||
if (typeof Date !== "undefined" && data instanceof Date) {
|
||||
return "date";
|
||||
}
|
||||
// @ts-ignore
|
||||
if (typeof File !== "undefined" && data instanceof File) {
|
||||
return "file";
|
||||
}
|
||||
@@ -591,77 +535,48 @@ export const BIGINT_FORMAT_RANGES: Record<checks.$ZodBigIntFormats, [bigint, big
|
||||
};
|
||||
|
||||
export function pick(schema: schemas.$ZodObject, mask: Record<string, unknown>): any {
|
||||
const currDef = schema._zod.def;
|
||||
const newShape: Writeable<schemas.$ZodShape> = {};
|
||||
const currDef = schema._zod.def; //.shape;
|
||||
|
||||
const def = mergeDefs(schema._zod.def, {
|
||||
get shape() {
|
||||
const newShape: Writeable<schemas.$ZodShape> = {};
|
||||
for (const key in mask) {
|
||||
if (!(key in currDef.shape)) {
|
||||
throw new Error(`Unrecognized key: "${key}"`);
|
||||
}
|
||||
if (!mask[key]) continue;
|
||||
newShape[key] = currDef.shape[key]!;
|
||||
}
|
||||
for (const key in mask) {
|
||||
if (!(key in currDef.shape)) {
|
||||
throw new Error(`Unrecognized key: "${key}"`);
|
||||
}
|
||||
if (!mask[key]) continue;
|
||||
|
||||
assignProp(this, "shape", newShape); // self-caching
|
||||
return newShape;
|
||||
},
|
||||
// pick key
|
||||
newShape[key] = currDef.shape[key]!;
|
||||
}
|
||||
|
||||
return clone(schema, {
|
||||
...schema._zod.def,
|
||||
shape: newShape,
|
||||
checks: [],
|
||||
});
|
||||
|
||||
return clone(schema, def) as any;
|
||||
}) as any;
|
||||
}
|
||||
|
||||
export function omit(schema: schemas.$ZodObject, mask: object): any {
|
||||
const currDef = schema._zod.def;
|
||||
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;
|
||||
|
||||
const def = mergeDefs(schema._zod.def, {
|
||||
get shape() {
|
||||
const newShape: Writeable<schemas.$ZodShape> = { ...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];
|
||||
}
|
||||
assignProp(this, "shape", newShape); // self-caching
|
||||
return newShape;
|
||||
},
|
||||
delete newShape[key];
|
||||
}
|
||||
return clone(schema, {
|
||||
...schema._zod.def,
|
||||
shape: newShape,
|
||||
checks: [],
|
||||
});
|
||||
|
||||
return clone(schema, def);
|
||||
}
|
||||
|
||||
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 checks = schema._zod.def.checks;
|
||||
const hasChecks = checks && checks.length > 0;
|
||||
if (hasChecks) {
|
||||
throw new Error("Object schemas containing refinements cannot be extended. Use `.safeExtend()` instead.");
|
||||
}
|
||||
|
||||
const def = mergeDefs(schema._zod.def, {
|
||||
get shape() {
|
||||
const _shape = { ...schema._zod.def.shape, ...shape };
|
||||
assignProp(this, "shape", _shape); // self-caching
|
||||
return _shape;
|
||||
},
|
||||
checks: [],
|
||||
});
|
||||
return clone(schema, def) as any;
|
||||
}
|
||||
|
||||
export function safeExtend(schema: schemas.$ZodObject, shape: schemas.$ZodShape): any {
|
||||
if (!isPlainObject(shape)) {
|
||||
throw new Error("Invalid input to safeExtend: expected a plain object");
|
||||
}
|
||||
const def = {
|
||||
...schema._zod.def,
|
||||
get shape() {
|
||||
@@ -669,25 +584,22 @@ export function safeExtend(schema: schemas.$ZodObject, shape: schemas.$ZodShape)
|
||||
assignProp(this, "shape", _shape); // self-caching
|
||||
return _shape;
|
||||
},
|
||||
checks: schema._zod.def.checks,
|
||||
checks: [], // delete existing checks
|
||||
} as any;
|
||||
return clone(schema, def) as any;
|
||||
}
|
||||
|
||||
export function merge(a: schemas.$ZodObject, b: schemas.$ZodObject): any {
|
||||
const def = mergeDefs(a._zod.def, {
|
||||
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;
|
||||
},
|
||||
get catchall() {
|
||||
return b._zod.def.catchall;
|
||||
},
|
||||
catchall: b._zod.def.catchall,
|
||||
checks: [], // delete existing checks
|
||||
});
|
||||
|
||||
return clone(a, def) as any;
|
||||
}) as any;
|
||||
}
|
||||
|
||||
export function partial(
|
||||
@@ -695,44 +607,40 @@ export function partial(
|
||||
schema: schemas.$ZodObject,
|
||||
mask: object | undefined
|
||||
): any {
|
||||
const def = mergeDefs(schema._zod.def, {
|
||||
get shape() {
|
||||
const oldShape = schema._zod.def.shape;
|
||||
const shape: Writeable<schemas.$ZodShape> = { ...oldShape };
|
||||
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]!;
|
||||
}
|
||||
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]!;
|
||||
}
|
||||
}
|
||||
|
||||
assignProp(this, "shape", shape); // self-caching
|
||||
return shape;
|
||||
},
|
||||
return clone(schema, {
|
||||
...schema._zod.def,
|
||||
shape,
|
||||
checks: [],
|
||||
});
|
||||
|
||||
return clone(schema, def) as any;
|
||||
}) as any;
|
||||
}
|
||||
|
||||
export function required(
|
||||
@@ -740,51 +648,44 @@ export function required(
|
||||
schema: schemas.$ZodObject,
|
||||
mask: object | undefined
|
||||
): any {
|
||||
const def = mergeDefs(schema._zod.def, {
|
||||
get shape() {
|
||||
const oldShape = schema._zod.def.shape;
|
||||
const shape: Writeable<schemas.$ZodShape> = { ...oldShape };
|
||||
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]!,
|
||||
});
|
||||
}
|
||||
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]!,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
assignProp(this, "shape", shape); // self-caching
|
||||
return shape;
|
||||
},
|
||||
return clone(schema, {
|
||||
...schema._zod.def,
|
||||
shape,
|
||||
// optional: [],
|
||||
checks: [],
|
||||
});
|
||||
|
||||
return clone(schema, def) as any;
|
||||
}) as any;
|
||||
}
|
||||
|
||||
export type Constructor<T, Def extends any[] = any[]> = new (...args: Def) => T;
|
||||
|
||||
// invalid_type | too_big | too_small | invalid_format | not_multiple_of | unrecognized_keys | invalid_union | invalid_key | invalid_element | invalid_value | custom
|
||||
export function aborted(x: schemas.ParsePayload, startIndex = 0): boolean {
|
||||
if (x.aborted === true) return true;
|
||||
for (let i = startIndex; i < x.issues.length; i++) {
|
||||
if (x.issues[i]?.continue !== true) {
|
||||
return true;
|
||||
}
|
||||
if (x.issues[i]?.continue !== true) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -832,7 +733,6 @@ export function finalizeIssue(
|
||||
export function getSizableOrigin(input: any): "set" | "map" | "file" | "unknown" {
|
||||
if (input instanceof Set) return "set";
|
||||
if (input instanceof Map) return "map";
|
||||
// @ts-ignore
|
||||
if (input instanceof File) return "file";
|
||||
return "unknown";
|
||||
}
|
||||
@@ -869,52 +769,6 @@ export function cleanEnum(obj: Record<string, EnumValue>): EnumValue[] {
|
||||
.map((el) => el[1]);
|
||||
}
|
||||
|
||||
// Codec utility functions
|
||||
export function base64ToUint8Array(base64: string): InstanceType<typeof Uint8Array> {
|
||||
const binaryString = atob(base64);
|
||||
const bytes = new Uint8Array(binaryString.length);
|
||||
for (let i = 0; i < binaryString.length; i++) {
|
||||
bytes[i] = binaryString.charCodeAt(i);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
export function uint8ArrayToBase64(bytes: Uint8Array): string {
|
||||
let binaryString = "";
|
||||
for (let i = 0; i < bytes.length; i++) {
|
||||
binaryString += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
return btoa(binaryString);
|
||||
}
|
||||
|
||||
export function base64urlToUint8Array(base64url: string): InstanceType<typeof Uint8Array> {
|
||||
const base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
|
||||
const padding = "=".repeat((4 - (base64.length % 4)) % 4);
|
||||
return base64ToUint8Array(base64 + padding);
|
||||
}
|
||||
|
||||
export function uint8ArrayToBase64url(bytes: Uint8Array): string {
|
||||
return uint8ArrayToBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
||||
}
|
||||
|
||||
export function hexToUint8Array(hex: string): InstanceType<typeof Uint8Array> {
|
||||
const cleanHex = hex.replace(/^0x/, "");
|
||||
if (cleanHex.length % 2 !== 0) {
|
||||
throw new Error("Invalid hex string length");
|
||||
}
|
||||
const bytes = new Uint8Array(cleanHex.length / 2);
|
||||
for (let i = 0; i < cleanHex.length; i += 2) {
|
||||
bytes[i / 2] = Number.parseInt(cleanHex.slice(i, i + 2), 16);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
export function uint8ArrayToHex(bytes: Uint8Array): string {
|
||||
return Array.from(bytes)
|
||||
.map((b) => b.toString(16).padStart(2, "0"))
|
||||
.join("");
|
||||
}
|
||||
|
||||
// instanceof
|
||||
export abstract class Class {
|
||||
constructor(..._args: any[]) {}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
export const version = {
|
||||
major: 4,
|
||||
minor: 1,
|
||||
patch: 13 as number,
|
||||
minor: 0,
|
||||
patch: 0 as number,
|
||||
} as const;
|
||||
|
||||
-1
@@ -60,7 +60,6 @@ const error: () => errors.$ZodErrorMap = () => {
|
||||
duration: "ISO duration",
|
||||
ipv4: "IPv4 address",
|
||||
ipv6: "IPv6 address",
|
||||
mac: "MAC address",
|
||||
cidrv4: "IPv4 range",
|
||||
cidrv6: "IPv6 range",
|
||||
base64: "base64-encoded string",
|
||||
|
||||
+10
-44
@@ -10,59 +10,27 @@ const error: () => errors.$ZodErrorMap = () => {
|
||||
set: { unit: "elementos", verb: "tener" },
|
||||
};
|
||||
|
||||
const TypeNames: Record<string, string> = {
|
||||
string: "texto",
|
||||
number: "número",
|
||||
boolean: "booleano",
|
||||
array: "arreglo",
|
||||
object: "objeto",
|
||||
set: "conjunto",
|
||||
file: "archivo",
|
||||
date: "fecha",
|
||||
bigint: "número grande",
|
||||
symbol: "símbolo",
|
||||
undefined: "indefinido",
|
||||
null: "nulo",
|
||||
function: "función",
|
||||
map: "mapa",
|
||||
record: "registro",
|
||||
tuple: "tupla",
|
||||
enum: "enumeración",
|
||||
union: "unión",
|
||||
literal: "literal",
|
||||
promise: "promesa",
|
||||
void: "vacío",
|
||||
never: "nunca",
|
||||
unknown: "desconocido",
|
||||
any: "cualquiera",
|
||||
};
|
||||
|
||||
function getSizing(origin: string): { unit: string; verb: string } | null {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
|
||||
function getTypeName(type: string): string {
|
||||
return TypeNames[type] ?? type;
|
||||
}
|
||||
|
||||
const parsedType = (data: any): string => {
|
||||
const t = typeof data;
|
||||
|
||||
switch (t) {
|
||||
case "number": {
|
||||
return Number.isNaN(data) ? "NaN" : "number";
|
||||
return Number.isNaN(data) ? "NaN" : "número";
|
||||
}
|
||||
case "object": {
|
||||
if (Array.isArray(data)) {
|
||||
return "array";
|
||||
return "arreglo";
|
||||
}
|
||||
if (data === null) {
|
||||
return "null";
|
||||
return "nulo";
|
||||
}
|
||||
if (Object.getPrototypeOf(data) !== Object.prototype) {
|
||||
return data.constructor.name;
|
||||
}
|
||||
return "object";
|
||||
}
|
||||
}
|
||||
return t;
|
||||
@@ -104,7 +72,7 @@ const error: () => errors.$ZodErrorMap = () => {
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type":
|
||||
return `Entrada inválida: se esperaba ${getTypeName(issue.expected)}, recibido ${getTypeName(parsedType(issue.input))}`;
|
||||
return `Entrada inválida: se esperaba ${issue.expected}, recibido ${parsedType(issue.input)}`;
|
||||
// return `Entrada inválida: se esperaba ${issue.expected}, recibido ${util.getParsedType(issue.input)}`;
|
||||
case "invalid_value":
|
||||
if (issue.values.length === 1)
|
||||
@@ -113,20 +81,18 @@ const error: () => errors.$ZodErrorMap = () => {
|
||||
case "too_big": {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
const origin = getTypeName(issue.origin);
|
||||
if (sizing)
|
||||
return `Demasiado grande: se esperaba que ${origin ?? "valor"} tuviera ${adj}${issue.maximum.toString()} ${sizing.unit ?? "elementos"}`;
|
||||
return `Demasiado grande: se esperaba que ${origin ?? "valor"} fuera ${adj}${issue.maximum.toString()}`;
|
||||
return `Demasiado grande: se esperaba que ${issue.origin ?? "valor"} tuviera ${adj}${issue.maximum.toString()} ${sizing.unit ?? "elementos"}`;
|
||||
return `Demasiado grande: se esperaba que ${issue.origin ?? "valor"} fuera ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
const origin = getTypeName(issue.origin);
|
||||
if (sizing) {
|
||||
return `Demasiado pequeño: se esperaba que ${origin} tuviera ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
return `Demasiado pequeño: se esperaba que ${issue.origin} tuviera ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
|
||||
return `Demasiado pequeño: se esperaba que ${origin} fuera ${adj}${issue.minimum.toString()}`;
|
||||
return `Demasiado pequeño: se esperaba que ${issue.origin} fuera ${adj}${issue.minimum.toString()}`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue as errors.$ZodStringFormatIssues;
|
||||
@@ -141,11 +107,11 @@ const error: () => errors.$ZodErrorMap = () => {
|
||||
case "unrecognized_keys":
|
||||
return `Llave${issue.keys.length > 1 ? "s" : ""} desconocida${issue.keys.length > 1 ? "s" : ""}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Llave inválida en ${getTypeName(issue.origin)}`;
|
||||
return `Llave inválida en ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Entrada inválida";
|
||||
case "invalid_element":
|
||||
return `Valor inválido en ${getTypeName(issue.origin)}`;
|
||||
return `Valor inválido en ${issue.origin}`;
|
||||
default:
|
||||
return `Entrada inválida`;
|
||||
}
|
||||
|
||||
+77
-208
@@ -3,246 +3,115 @@ import type * as errors from "../core/errors.js";
|
||||
import * as util from "../core/util.js";
|
||||
|
||||
const error: () => errors.$ZodErrorMap = () => {
|
||||
// Hebrew labels + grammatical gender
|
||||
const TypeNames: Record<string, { label: string; gender: "m" | "f" }> = {
|
||||
string: { label: "מחרוזת", gender: "f" },
|
||||
number: { label: "מספר", gender: "m" },
|
||||
boolean: { label: "ערך בוליאני", gender: "m" },
|
||||
bigint: { label: "BigInt", gender: "m" },
|
||||
date: { label: "תאריך", gender: "m" },
|
||||
array: { label: "מערך", gender: "m" },
|
||||
object: { label: "אובייקט", gender: "m" },
|
||||
null: { label: "ערך ריק (null)", gender: "m" },
|
||||
undefined: { label: "ערך לא מוגדר (undefined)", gender: "m" },
|
||||
symbol: { label: "סימבול (Symbol)", gender: "m" },
|
||||
function: { label: "פונקציה", gender: "f" },
|
||||
map: { label: "מפה (Map)", gender: "f" },
|
||||
set: { label: "קבוצה (Set)", gender: "f" },
|
||||
file: { label: "קובץ", gender: "m" },
|
||||
promise: { label: "Promise", gender: "m" },
|
||||
NaN: { label: "NaN", gender: "m" },
|
||||
unknown: { label: "ערך לא ידוע", gender: "m" },
|
||||
value: { label: "ערך", gender: "m" },
|
||||
const Sizable: Record<string, { unit: string; verb: string }> = {
|
||||
string: { unit: "אותיות", verb: "לכלול" },
|
||||
file: { unit: "בייטים", verb: "לכלול" },
|
||||
array: { unit: "פריטים", verb: "לכלול" },
|
||||
set: { unit: "פריטים", verb: "לכלול" },
|
||||
};
|
||||
|
||||
// Sizing units for size-related messages + localized origin labels
|
||||
const Sizable: Record<string, { unit: string; shortLabel?: string; longLabel?: string }> = {
|
||||
string: { unit: "תווים", shortLabel: "קצר", longLabel: "ארוך" },
|
||||
file: { unit: "בייטים", shortLabel: "קטן", longLabel: "גדול" },
|
||||
array: { unit: "פריטים", shortLabel: "קטן", longLabel: "גדול" },
|
||||
set: { unit: "פריטים", shortLabel: "קטן", longLabel: "גדול" },
|
||||
number: { unit: "", shortLabel: "קטן", longLabel: "גדול" }, // no unit
|
||||
};
|
||||
|
||||
// Helpers — labels, articles, and verbs
|
||||
const typeEntry = (t?: string | null) => (t ? TypeNames[t] : undefined);
|
||||
|
||||
const typeLabel = (t?: string | null): string => {
|
||||
const e = typeEntry(t);
|
||||
if (e) return e.label;
|
||||
// fallback: show raw string if unknown
|
||||
return t ?? TypeNames.unknown.label;
|
||||
};
|
||||
|
||||
const withDefinite = (t?: string | null): string => `ה${typeLabel(t)}`;
|
||||
|
||||
const verbFor = (t?: string | null): string => {
|
||||
const e = typeEntry(t);
|
||||
const gender = e?.gender ?? "m";
|
||||
return gender === "f" ? "צריכה להיות" : "צריך להיות";
|
||||
};
|
||||
|
||||
const getSizing = (origin?: string | null) => {
|
||||
if (!origin) return null;
|
||||
function getSizing(origin: string): { unit: string; verb: string } | null {
|
||||
return Sizable[origin] ?? null;
|
||||
};
|
||||
}
|
||||
|
||||
// Robust type parser for "received" — returns a key we understand or a constructor name
|
||||
const parsedType = (data: any): string => {
|
||||
const t = typeof data;
|
||||
|
||||
switch (t) {
|
||||
case "number":
|
||||
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; // keep as-is (e.g., "Date")
|
||||
}
|
||||
return "object";
|
||||
}
|
||||
default:
|
||||
return t;
|
||||
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]: { label: string; gender: "m" | "f" };
|
||||
[k in $ZodStringFormats | (string & {})]?: string;
|
||||
} = {
|
||||
regex: { label: "קלט", gender: "m" },
|
||||
email: { label: "כתובת אימייל", gender: "f" },
|
||||
url: { label: "כתובת רשת", gender: "f" },
|
||||
emoji: { label: "אימוג'י", gender: "m" },
|
||||
uuid: { label: "UUID", gender: "m" },
|
||||
nanoid: { label: "nanoid", gender: "m" },
|
||||
guid: { label: "GUID", gender: "m" },
|
||||
cuid: { label: "cuid", gender: "m" },
|
||||
cuid2: { label: "cuid2", gender: "m" },
|
||||
ulid: { label: "ULID", gender: "m" },
|
||||
xid: { label: "XID", gender: "m" },
|
||||
ksuid: { label: "KSUID", gender: "m" },
|
||||
datetime: { label: "תאריך וזמן ISO", gender: "m" },
|
||||
date: { label: "תאריך ISO", gender: "m" },
|
||||
time: { label: "זמן ISO", gender: "m" },
|
||||
duration: { label: "משך זמן ISO", gender: "m" },
|
||||
ipv4: { label: "כתובת IPv4", gender: "f" },
|
||||
ipv6: { label: "כתובת IPv6", gender: "f" },
|
||||
cidrv4: { label: "טווח IPv4", gender: "m" },
|
||||
cidrv6: { label: "טווח IPv6", gender: "m" },
|
||||
base64: { label: "מחרוזת בבסיס 64", gender: "f" },
|
||||
base64url: { label: "מחרוזת בבסיס 64 לכתובות רשת", gender: "f" },
|
||||
json_string: { label: "מחרוזת JSON", gender: "f" },
|
||||
e164: { label: "מספר E.164", gender: "m" },
|
||||
jwt: { label: "JWT", gender: "m" },
|
||||
ends_with: { label: "קלט", gender: "m" },
|
||||
includes: { label: "קלט", gender: "m" },
|
||||
lowercase: { label: "קלט", gender: "m" },
|
||||
starts_with: { label: "קלט", gender: "m" },
|
||||
uppercase: { label: "קלט", gender: "m" },
|
||||
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: "מחרוזת בבסיס 64",
|
||||
base64url: "מחרוזת בבסיס 64 לכתובות רשת",
|
||||
json_string: "מחרוזת JSON",
|
||||
e164: "מספר E.164",
|
||||
jwt: "JWT",
|
||||
template_literal: "קלט",
|
||||
};
|
||||
|
||||
return (issue) => {
|
||||
switch (issue.code) {
|
||||
case "invalid_type": {
|
||||
// Expected type: show without definite article for clearer Hebrew
|
||||
const expectedKey = issue.expected as string | undefined;
|
||||
const expected = typeLabel(expectedKey);
|
||||
// Received: show localized label if known, otherwise constructor/raw
|
||||
const receivedKey = parsedType(issue.input);
|
||||
const received = TypeNames[receivedKey]?.label ?? receivedKey;
|
||||
return `קלט לא תקין: צריך להיות ${expected}, התקבל ${received}`;
|
||||
}
|
||||
|
||||
case "invalid_value": {
|
||||
if (issue.values.length === 1) {
|
||||
return `ערך לא תקין: הערך חייב להיות ${util.stringifyPrimitive(issue.values[0])}`;
|
||||
}
|
||||
// Join values with proper Hebrew formatting
|
||||
const stringified = issue.values.map((v) => util.stringifyPrimitive(v));
|
||||
if (issue.values.length === 2) {
|
||||
return `ערך לא תקין: האפשרויות המתאימות הן ${stringified[0]} או ${stringified[1]}`;
|
||||
}
|
||||
// For 3+ values: "a", "b" או "c"
|
||||
const lastValue = stringified[stringified.length - 1];
|
||||
const restValues = stringified.slice(0, -1).join(", ");
|
||||
return `ערך לא תקין: האפשרויות המתאימות הן ${restValues} או ${lastValue}`;
|
||||
}
|
||||
|
||||
case "invalid_type":
|
||||
return `קלט לא תקין: צריך ${issue.expected}, התקבל ${parsedType(issue.input)}`;
|
||||
// return `Invalid input: expected ${issue.expected}, received ${util.getParsedType(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 sizing = getSizing(issue.origin);
|
||||
const subject = withDefinite(issue.origin ?? "value");
|
||||
|
||||
if (issue.origin === "string") {
|
||||
// Special handling for strings - more natural Hebrew
|
||||
return `${sizing?.longLabel ?? "ארוך"} מדי: ${subject} צריכה להכיל ${issue.maximum.toString()} ${sizing?.unit ?? ""} ${issue.inclusive ? "או פחות" : "לכל היותר"}`.trim();
|
||||
}
|
||||
|
||||
if (issue.origin === "number") {
|
||||
// Natural Hebrew for numbers
|
||||
const comparison = issue.inclusive ? `קטן או שווה ל-${issue.maximum}` : `קטן מ-${issue.maximum}`;
|
||||
return `גדול מדי: ${subject} צריך להיות ${comparison}`;
|
||||
}
|
||||
|
||||
if (issue.origin === "array" || issue.origin === "set") {
|
||||
// Natural Hebrew for arrays and sets
|
||||
const verb = issue.origin === "set" ? "צריכה" : "צריך";
|
||||
const comparison = issue.inclusive
|
||||
? `${issue.maximum} ${sizing?.unit ?? ""} או פחות`
|
||||
: `פחות מ-${issue.maximum} ${sizing?.unit ?? ""}`;
|
||||
return `גדול מדי: ${subject} ${verb} להכיל ${comparison}`.trim();
|
||||
}
|
||||
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const be = verbFor(issue.origin ?? "value");
|
||||
if (sizing?.unit) {
|
||||
return `${sizing.longLabel} מדי: ${subject} ${be} ${adj}${issue.maximum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
return `${sizing?.longLabel ?? "גדול"} מדי: ${subject} ${be} ${adj}${issue.maximum.toString()}`;
|
||||
}
|
||||
|
||||
case "too_small": {
|
||||
const sizing = getSizing(issue.origin);
|
||||
const subject = withDefinite(issue.origin ?? "value");
|
||||
|
||||
if (issue.origin === "string") {
|
||||
// Special handling for strings - more natural Hebrew
|
||||
return `${sizing?.shortLabel ?? "קצר"} מדי: ${subject} צריכה להכיל ${issue.minimum.toString()} ${sizing?.unit ?? ""} ${issue.inclusive ? "או יותר" : "לפחות"}`.trim();
|
||||
}
|
||||
|
||||
if (issue.origin === "number") {
|
||||
// Natural Hebrew for numbers
|
||||
const comparison = issue.inclusive ? `גדול או שווה ל-${issue.minimum}` : `גדול מ-${issue.minimum}`;
|
||||
return `קטן מדי: ${subject} צריך להיות ${comparison}`;
|
||||
}
|
||||
|
||||
if (issue.origin === "array" || issue.origin === "set") {
|
||||
// Natural Hebrew for arrays and sets
|
||||
const verb = issue.origin === "set" ? "צריכה" : "צריך";
|
||||
|
||||
// Special case for singular (minimum === 1)
|
||||
if (issue.minimum === 1 && issue.inclusive) {
|
||||
const singularPhrase = issue.origin === "set" ? "לפחות פריט אחד" : "לפחות פריט אחד";
|
||||
return `קטן מדי: ${subject} ${verb} להכיל ${singularPhrase}`;
|
||||
}
|
||||
|
||||
const comparison = issue.inclusive
|
||||
? `${issue.minimum} ${sizing?.unit ?? ""} או יותר`
|
||||
: `יותר מ-${issue.minimum} ${sizing?.unit ?? ""}`;
|
||||
return `קטן מדי: ${subject} ${verb} להכיל ${comparison}`.trim();
|
||||
}
|
||||
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const be = verbFor(issue.origin ?? "value");
|
||||
if (sizing?.unit) {
|
||||
return `${sizing.shortLabel} מדי: ${subject} ${be} ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
}
|
||||
return `${sizing?.shortLabel ?? "קטן"} מדי: ${subject} ${be} ${adj}${issue.minimum.toString()}`;
|
||||
if (sizing)
|
||||
return `גדול מדי: ${issue.origin ?? "value"} צריך להיות ${adj}${issue.maximum.toString()} ${sizing.unit ?? "elements"}`;
|
||||
return `גדול מדי: ${issue.origin ?? "value"} צריך להיות ${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;
|
||||
// These apply to strings — use feminine grammar + ה׳ הידיעה
|
||||
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}`;
|
||||
|
||||
// Handle gender agreement for formats
|
||||
const nounEntry = Nouns[_issue.format];
|
||||
const noun = nounEntry?.label ?? _issue.format;
|
||||
const gender = nounEntry?.gender ?? "m";
|
||||
const adjective = gender === "f" ? "תקינה" : "תקין";
|
||||
return `${noun} לא ${adjective}`;
|
||||
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 `שדה לא תקין באובייקט`;
|
||||
}
|
||||
|
||||
case "invalid_key":
|
||||
return `מפתח לא תקין ב${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "קלט לא תקין";
|
||||
|
||||
case "invalid_element": {
|
||||
const place = withDefinite(issue.origin ?? "array");
|
||||
return `ערך לא תקין ב${place}`;
|
||||
}
|
||||
|
||||
case "invalid_element":
|
||||
return `ערך לא תקין ב${issue.origin}`;
|
||||
default:
|
||||
return `קלט לא תקין`;
|
||||
}
|
||||
|
||||
-8
@@ -1,10 +1,8 @@
|
||||
export { default as ar } from "./ar.js";
|
||||
export { default as az } from "./az.js";
|
||||
export { default as be } from "./be.js";
|
||||
export { default as bg } from "./bg.js";
|
||||
export { default as ca } from "./ca.js";
|
||||
export { default as cs } from "./cs.js";
|
||||
export { default as da } from "./da.js";
|
||||
export { default as de } from "./de.js";
|
||||
export { default as en } from "./en.js";
|
||||
export { default as eo } from "./eo.js";
|
||||
@@ -16,14 +14,10 @@ export { default as frCA } from "./fr-CA.js";
|
||||
export { default as he } from "./he.js";
|
||||
export { default as hu } from "./hu.js";
|
||||
export { default as id } from "./id.js";
|
||||
export { default as is } from "./is.js";
|
||||
export { default as it } from "./it.js";
|
||||
export { default as ja } from "./ja.js";
|
||||
export { default as ka } from "./ka.js";
|
||||
export { default as kh } from "./kh.js";
|
||||
export { default as km } from "./km.js";
|
||||
export { default as ko } from "./ko.js";
|
||||
export { default as lt } from "./lt.js";
|
||||
export { default as mk } from "./mk.js";
|
||||
export { default as ms } from "./ms.js";
|
||||
export { default as nl } from "./nl.js";
|
||||
@@ -39,9 +33,7 @@ export { default as ta } from "./ta.js";
|
||||
export { default as th } from "./th.js";
|
||||
export { default as tr } from "./tr.js";
|
||||
export { default as ua } from "./ua.js";
|
||||
export { default as uk } from "./uk.js";
|
||||
export { default as ur } from "./ur.js";
|
||||
export { default as vi } from "./vi.js";
|
||||
export { default as zhCN } from "./zh-CN.js";
|
||||
export { default as zhTW } from "./zh-TW.js";
|
||||
export { default as yo } from "./yo.js";
|
||||
|
||||
+122
-3
@@ -1,7 +1,126 @@
|
||||
import type { $ZodStringFormats } from "../core/checks.js";
|
||||
import type * as errors from "../core/errors.js";
|
||||
import km from "./km.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)" : "លេខ";
|
||||
}
|
||||
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: "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)
|
||||
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 `រកឃើញសោមិនស្គាល់៖ ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `សោមិនត្រឹមត្រូវនៅក្នុង ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return `ទិន្នន័យមិនត្រឹមត្រូវ`;
|
||||
case "invalid_element":
|
||||
return `ទិន្នន័យមិនត្រឹមត្រូវនៅក្នុង ${issue.origin}`;
|
||||
default:
|
||||
return `ទិន្នន័យមិនត្រឹមត្រូវ`;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** @deprecated Use `km` instead. */
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return km();
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
|
||||
+10
-10
@@ -3,14 +3,14 @@ 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: "tekens", verb: "te hebben" },
|
||||
file: { unit: "bytes", verb: "te hebben" },
|
||||
array: { unit: "elementen", verb: "te hebben" },
|
||||
set: { unit: "elementen", verb: "te hebben" },
|
||||
const Sizable: Record<string, { unit: string }> = {
|
||||
string: { unit: "tekens" },
|
||||
file: { unit: "bytes" },
|
||||
array: { unit: "elementen" },
|
||||
set: { unit: "elementen" },
|
||||
};
|
||||
|
||||
function getSizing(origin: string): { unit: string; verb: string } | null {
|
||||
function getSizing(origin: string): { unit: string } | null {
|
||||
return Sizable[origin] ?? null;
|
||||
}
|
||||
|
||||
@@ -81,17 +81,17 @@ const error: () => errors.$ZodErrorMap = () => {
|
||||
const adj = issue.inclusive ? "<=" : "<";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing)
|
||||
return `Te groot: verwacht dat ${issue.origin ?? "waarde"} ${sizing.verb} ${adj}${issue.maximum.toString()} ${sizing.unit ?? "elementen"}`;
|
||||
return `Te groot: verwacht dat ${issue.origin ?? "waarde"} ${adj}${issue.maximum.toString()} is`;
|
||||
return `Te lang: verwacht dat ${issue.origin ?? "waarde"} ${adj}${issue.maximum.toString()} ${sizing.unit ?? "elementen"} bevat`;
|
||||
return `Te lang: verwacht dat ${issue.origin ?? "waarde"} ${adj}${issue.maximum.toString()} is`;
|
||||
}
|
||||
case "too_small": {
|
||||
const adj = issue.inclusive ? ">=" : ">";
|
||||
const sizing = getSizing(issue.origin);
|
||||
if (sizing) {
|
||||
return `Te klein: verwacht dat ${issue.origin} ${sizing.verb} ${adj}${issue.minimum.toString()} ${sizing.unit}`;
|
||||
return `Te kort: verwacht dat ${issue.origin} ${adj}${issue.minimum.toString()} ${sizing.unit} bevat`;
|
||||
}
|
||||
|
||||
return `Te klein: verwacht dat ${issue.origin} ${adj}${issue.minimum.toString()} is`;
|
||||
return `Te kort: verwacht dat ${issue.origin} ${adj}${issue.minimum.toString()} is`;
|
||||
}
|
||||
case "invalid_format": {
|
||||
const _issue = issue as errors.$ZodStringFormatIssues;
|
||||
|
||||
+122
-3
@@ -1,7 +1,126 @@
|
||||
import type { $ZodStringFormats } from "../core/checks.js";
|
||||
import type * as errors from "../core/errors.js";
|
||||
import uk from "./uk.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" : "число";
|
||||
}
|
||||
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: "адреса електронної пошти",
|
||||
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)}`;
|
||||
// return `Неправильні вхідні дані: очікується ${issue.expected}, отримано ${util.getParsedType(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 ?? "значення"} ${sizing.verb} ${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} ${sizing.verb} ${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 ? "і" : ""}: ${util.joinValues(issue.keys, ", ")}`;
|
||||
case "invalid_key":
|
||||
return `Неправильний ключ у ${issue.origin}`;
|
||||
case "invalid_union":
|
||||
return "Неправильні вхідні дані";
|
||||
case "invalid_element":
|
||||
return `Неправильне значення у ${issue.origin}`;
|
||||
default:
|
||||
return `Неправильні вхідні дані`;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** @deprecated Use `uk` instead. */
|
||||
export default function (): { localeError: errors.$ZodErrorMap } {
|
||||
return uk();
|
||||
return {
|
||||
localeError: error(),
|
||||
};
|
||||
}
|
||||
|
||||
+1
-1
@@ -11,6 +11,7 @@ export {
|
||||
$output,
|
||||
$input,
|
||||
$brand,
|
||||
function,
|
||||
clone,
|
||||
regexes,
|
||||
treeifyError,
|
||||
@@ -19,7 +20,6 @@ export {
|
||||
flattenError,
|
||||
toJSONSchema,
|
||||
TimePrecision,
|
||||
util,
|
||||
NEVER,
|
||||
} from "../core/index.js";
|
||||
|
||||
|
||||
+4
-4
@@ -6,7 +6,7 @@ export interface ZodMiniISODateTime extends schemas.ZodMiniStringFormat<"datetim
|
||||
_zod: core.$ZodISODateTimeInternals;
|
||||
}
|
||||
export const ZodMiniISODateTime: core.$constructor<ZodMiniISODateTime> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodMiniISODateTime",
|
||||
"$ZodISODateTime",
|
||||
(inst, def) => {
|
||||
core.$ZodISODateTime.init(inst, def);
|
||||
schemas.ZodMiniStringFormat.init(inst, def);
|
||||
@@ -21,7 +21,7 @@ export interface ZodMiniISODate extends schemas.ZodMiniStringFormat<"date"> {
|
||||
_zod: core.$ZodISODateInternals;
|
||||
}
|
||||
export const ZodMiniISODate: core.$constructor<ZodMiniISODate> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodMiniISODate",
|
||||
"$ZodISODate",
|
||||
(inst, def) => {
|
||||
core.$ZodISODate.init(inst, def);
|
||||
schemas.ZodMiniStringFormat.init(inst, def);
|
||||
@@ -36,7 +36,7 @@ export interface ZodMiniISOTime extends schemas.ZodMiniStringFormat<"time"> {
|
||||
_zod: core.$ZodISOTimeInternals;
|
||||
}
|
||||
export const ZodMiniISOTime: core.$constructor<ZodMiniISOTime> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodMiniISOTime",
|
||||
"$ZodISOTime",
|
||||
(inst, def) => {
|
||||
core.$ZodISOTime.init(inst, def);
|
||||
schemas.ZodMiniStringFormat.init(inst, def);
|
||||
@@ -51,7 +51,7 @@ export interface ZodMiniISODuration extends schemas.ZodMiniStringFormat<"duratio
|
||||
_zod: core.$ZodISODurationInternals;
|
||||
}
|
||||
export const ZodMiniISODuration: core.$constructor<ZodMiniISODuration> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodMiniISODuration",
|
||||
"$ZodISODuration",
|
||||
(inst, def) => {
|
||||
core.$ZodISODuration.init(inst, def);
|
||||
schemas.ZodMiniStringFormat.init(inst, def);
|
||||
|
||||
+1
-14
@@ -1,14 +1 @@
|
||||
export {
|
||||
parse,
|
||||
safeParse,
|
||||
parseAsync,
|
||||
safeParseAsync,
|
||||
encode,
|
||||
decode,
|
||||
encodeAsync,
|
||||
decodeAsync,
|
||||
safeEncode,
|
||||
safeDecode,
|
||||
safeEncodeAsync,
|
||||
safeDecodeAsync,
|
||||
} from "../core/index.js";
|
||||
export { parse, safeParse, parseAsync, safeParseAsync } from "../core/index.js";
|
||||
|
||||
+40
-203
@@ -9,7 +9,6 @@ export interface ZodMiniType<
|
||||
out Input = unknown,
|
||||
out Internals extends core.$ZodTypeInternals<Output, Input> = core.$ZodTypeInternals<Output, Input>,
|
||||
> extends core.$ZodType<Output, Input, Internals> {
|
||||
type: Internals["def"]["type"];
|
||||
check(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
|
||||
clone(def?: Internals["def"], params?: { parent: boolean }): this;
|
||||
register<R extends core.$ZodRegistry>(
|
||||
@@ -44,9 +43,7 @@ export const ZodMiniType: core.$constructor<ZodMiniType> = /*@__PURE__*/ core.$c
|
||||
if (!inst._zod) throw new Error("Uninitialized schema in ZodMiniType.");
|
||||
|
||||
core.$ZodType.init(inst, def);
|
||||
|
||||
inst.def = def;
|
||||
inst.type = def.type;
|
||||
inst.parse = (data, params) => parse.parse(inst, data, params, { callee: inst.parse });
|
||||
inst.safeParse = (data, params) => parse.safeParse(inst, data, params);
|
||||
inst.parseAsync = async (data, params) => parse.parseAsync(inst, data, params, { callee: inst.parseAsync });
|
||||
@@ -185,14 +182,6 @@ export function url(params?: string | core.$ZodURLParams): ZodMiniURL {
|
||||
return core._url(ZodMiniURL, params);
|
||||
}
|
||||
|
||||
export function httpUrl(params?: string | Omit<core.$ZodURLParams, "protocol" | "hostname">): ZodMiniURL {
|
||||
return core._url(ZodMiniURL, {
|
||||
protocol: /^https?$/,
|
||||
hostname: core.regexes.domain,
|
||||
...util.normalizeParams(params),
|
||||
});
|
||||
}
|
||||
|
||||
// ZodMiniEmoji
|
||||
export interface ZodMiniEmoji extends _ZodMiniString<core.$ZodEmojiInternals> {
|
||||
// _zod: core.$ZodEmojiInternals;
|
||||
@@ -366,19 +355,6 @@ export function cidrv6(params?: string | core.$ZodCIDRv6Params): ZodMiniCIDRv6 {
|
||||
return core._cidrv6(ZodMiniCIDRv6, params);
|
||||
}
|
||||
|
||||
// ZodMiniMAC
|
||||
export interface ZodMiniMAC extends _ZodMiniString<core.$ZodMACInternals> {
|
||||
// _zod: core.$ZodMACInternals;
|
||||
}
|
||||
export const ZodMiniMAC: core.$constructor<ZodMiniMAC> = /*@__PURE__*/ core.$constructor("ZodMiniMAC", (inst, def) => {
|
||||
core.$ZodMAC.init(inst, def);
|
||||
ZodMiniStringFormat.init(inst, def);
|
||||
});
|
||||
|
||||
export function mac(params?: string | core.$ZodMACParams): ZodMiniMAC {
|
||||
return core._mac(ZodMiniMAC, params);
|
||||
}
|
||||
|
||||
// ZodMiniBase64
|
||||
export interface ZodMiniBase64 extends _ZodMiniString<core.$ZodBase64Internals> {
|
||||
// _zod: core.$ZodBase64Internals;
|
||||
@@ -460,28 +436,6 @@ export function stringFormat<Format extends string>(
|
||||
return core._stringFormat(ZodMiniCustomStringFormat, format, fnOrRegex, _params) as any;
|
||||
}
|
||||
|
||||
export function hostname(_params?: string | core.$ZodStringFormatParams): ZodMiniCustomStringFormat<"hostname"> {
|
||||
return core._stringFormat(ZodMiniCustomStringFormat, "hostname", core.regexes.hostname, _params) as any;
|
||||
}
|
||||
|
||||
export function hex(_params?: string | core.$ZodStringFormatParams): ZodMiniCustomStringFormat<"hex"> {
|
||||
return core._stringFormat(ZodMiniCustomStringFormat, "hex", core.regexes.hex, _params) as any;
|
||||
}
|
||||
|
||||
export function hash<Alg extends util.HashAlgorithm, Enc extends util.HashEncoding = "hex">(
|
||||
alg: Alg,
|
||||
params?: {
|
||||
enc?: Enc;
|
||||
} & core.$ZodStringFormatParams
|
||||
): ZodMiniCustomStringFormat<`${Alg}_${Enc}`> {
|
||||
const enc = params?.enc ?? "hex";
|
||||
const format = `${alg}_${enc}` as const;
|
||||
const regex = core.regexes[format as keyof typeof core.regexes] as RegExp;
|
||||
// check for unrecognized format
|
||||
if (!regex) throw new Error(`Unrecognized hash format: ${format}`);
|
||||
return core._stringFormat(ZodMiniCustomStringFormat, format, regex, params) as any;
|
||||
}
|
||||
|
||||
// ZodMiniNumber
|
||||
interface _ZodMiniNumber<T extends core.$ZodNumberInternals<unknown> = core.$ZodNumberInternals<unknown>>
|
||||
extends _ZodMiniType<T>,
|
||||
@@ -754,9 +708,9 @@ export function array<T extends SomeType>(element: SomeType, params?: any): ZodM
|
||||
}
|
||||
|
||||
// .keyof
|
||||
export function keyof<T extends ZodMiniObject>(schema: T): ZodMiniEnum<util.KeysEnum<T["shape"]>> {
|
||||
export function keyof<T extends ZodMiniObject>(schema: T): ZodMiniLiteral<Exclude<keyof T["shape"], symbol>> {
|
||||
const shape = schema._zod.def.shape;
|
||||
return _enum(Object.keys(shape)) as any;
|
||||
return literal(Object.keys(shape)) as any;
|
||||
}
|
||||
|
||||
// ZodMiniObject
|
||||
@@ -782,7 +736,10 @@ export function object<T extends core.$ZodLooseShape = Record<never, SomeType>>(
|
||||
): ZodMiniObject<T, core.$strip> {
|
||||
const def: core.$ZodObjectDef = {
|
||||
type: "object",
|
||||
shape: shape ?? {},
|
||||
get shape() {
|
||||
util.assignProp(this, "shape", { ...shape });
|
||||
return this.shape;
|
||||
},
|
||||
...util.normalizeParams(params),
|
||||
};
|
||||
return new ZodMiniObject(def) as any;
|
||||
@@ -795,7 +752,11 @@ export function strictObject<T extends core.$ZodLooseShape>(
|
||||
): ZodMiniObject<T, core.$strict> {
|
||||
return new ZodMiniObject({
|
||||
type: "object",
|
||||
shape,
|
||||
// shape: shape as core.$ZodLooseShape,
|
||||
get shape() {
|
||||
util.assignProp(this, "shape", { ...shape });
|
||||
return this.shape;
|
||||
},
|
||||
catchall: never(),
|
||||
...util.normalizeParams(params),
|
||||
}) as any;
|
||||
@@ -808,7 +769,14 @@ export function looseObject<T extends core.$ZodLooseShape>(
|
||||
): ZodMiniObject<T, core.$loose> {
|
||||
return new ZodMiniObject({
|
||||
type: "object",
|
||||
shape,
|
||||
// shape: shape as core.$ZodLooseShape,
|
||||
get shape() {
|
||||
util.assignProp(this, "shape", { ...shape });
|
||||
return this.shape;
|
||||
},
|
||||
// get optional() {
|
||||
// return util.optionalKeys(shape);
|
||||
// },
|
||||
catchall: unknown(),
|
||||
...util.normalizeParams(params),
|
||||
}) as any;
|
||||
@@ -822,23 +790,6 @@ export function extend<T extends ZodMiniObject, U extends core.$ZodLooseShape>(
|
||||
return util.extend(schema, shape);
|
||||
}
|
||||
|
||||
export type SafeExtendShape<Base extends core.$ZodShape, Ext extends core.$ZodLooseShape> = {
|
||||
[K in keyof Ext]: K extends keyof Base
|
||||
? core.output<Ext[K]> extends core.output<Base[K]>
|
||||
? core.input<Ext[K]> extends core.input<Base[K]>
|
||||
? Ext[K]
|
||||
: never
|
||||
: never
|
||||
: Ext[K];
|
||||
};
|
||||
|
||||
export function safeExtend<T extends ZodMiniObject, U extends core.$ZodLooseShape>(
|
||||
schema: T,
|
||||
shape: SafeExtendShape<T["shape"], U>
|
||||
): ZodMiniObject<util.Extend<T["shape"], U>, T["_zod"]["config"]> {
|
||||
return util.safeExtend(schema, shape as any);
|
||||
}
|
||||
|
||||
/** @deprecated Identical to `z.extend(A, B)` */
|
||||
export function merge<T extends ZodMiniObject, U extends ZodMiniObject>(
|
||||
a: T,
|
||||
@@ -952,11 +903,9 @@ export function union<const T extends readonly SomeType[]>(
|
||||
}
|
||||
|
||||
// ZodMiniDiscriminatedUnion
|
||||
export interface ZodMiniDiscriminatedUnion<
|
||||
Options extends readonly SomeType[] = readonly core.$ZodType[],
|
||||
Disc extends string = string,
|
||||
> extends ZodMiniUnion<Options> {
|
||||
_zod: core.$ZodDiscriminatedUnionInternals<Options, Disc>;
|
||||
export interface ZodMiniDiscriminatedUnion<Options extends readonly SomeType[] = readonly core.$ZodType[]>
|
||||
extends ZodMiniUnion<Options> {
|
||||
_zod: core.$ZodDiscriminatedUnionInternals<Options>;
|
||||
}
|
||||
export const ZodMiniDiscriminatedUnion: core.$constructor<ZodMiniDiscriminatedUnion> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodMiniDiscriminatedUnion",
|
||||
@@ -968,18 +917,17 @@ export const ZodMiniDiscriminatedUnion: core.$constructor<ZodMiniDiscriminatedUn
|
||||
|
||||
export function discriminatedUnion<
|
||||
Types extends readonly [core.$ZodTypeDiscriminable, ...core.$ZodTypeDiscriminable[]],
|
||||
Disc extends string,
|
||||
>(
|
||||
discriminator: Disc,
|
||||
discriminator: string,
|
||||
options: Types,
|
||||
params?: string | core.$ZodDiscriminatedUnionParams
|
||||
): ZodMiniDiscriminatedUnion<Types, Disc> {
|
||||
): ZodMiniDiscriminatedUnion<Types> {
|
||||
return new ZodMiniDiscriminatedUnion({
|
||||
type: "union",
|
||||
options,
|
||||
discriminator,
|
||||
...util.normalizeParams(params),
|
||||
}) as ZodMiniDiscriminatedUnion<Types, Disc>;
|
||||
}) as ZodMiniDiscriminatedUnion<Types>;
|
||||
}
|
||||
|
||||
// ZodMiniIntersection
|
||||
@@ -1076,11 +1024,9 @@ export function partialRecord<Key extends core.$ZodRecordKey, Value extends Some
|
||||
valueType: Value,
|
||||
params?: string | core.$ZodRecordParams
|
||||
): ZodMiniRecord<Key & core.$partial, Value> {
|
||||
const k = core.clone(keyType);
|
||||
k._zod.values = undefined;
|
||||
return new ZodMiniRecord({
|
||||
type: "record",
|
||||
keyType: k,
|
||||
keyType: union([keyType, never()]),
|
||||
valueType: valueType as any,
|
||||
...util.normalizeParams(params),
|
||||
}) as any;
|
||||
@@ -1129,15 +1075,12 @@ export function set<Value extends SomeType>(valueType: Value, params?: string |
|
||||
// ZodMiniEnum
|
||||
export interface ZodMiniEnum<T extends util.EnumLike = util.EnumLike> extends _ZodMiniType<core.$ZodEnumInternals<T>> {
|
||||
// _zod: core.$ZodEnumInternals<T>;
|
||||
options: Array<T[keyof T]>;
|
||||
}
|
||||
export const ZodMiniEnum: core.$constructor<ZodMiniEnum> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodMiniEnum",
|
||||
(inst, def) => {
|
||||
core.$ZodEnum.init(inst, def);
|
||||
ZodMiniType.init(inst, def);
|
||||
|
||||
inst.options = Object.values(def.entries);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1304,7 +1247,7 @@ export function _default<T extends SomeType>(
|
||||
type: "default",
|
||||
innerType: innerType as any as core.$ZodType,
|
||||
get defaultValue() {
|
||||
return typeof defaultValue === "function" ? (defaultValue as Function)() : util.shallowClone(defaultValue);
|
||||
return typeof defaultValue === "function" ? (defaultValue as Function)() : defaultValue;
|
||||
},
|
||||
}) as any;
|
||||
}
|
||||
@@ -1329,7 +1272,7 @@ export function prefault<T extends SomeType>(
|
||||
type: "prefault",
|
||||
innerType: innerType as any as core.$ZodType,
|
||||
get defaultValue() {
|
||||
return typeof defaultValue === "function" ? (defaultValue as Function)() : util.shallowClone(defaultValue);
|
||||
return typeof defaultValue === "function" ? (defaultValue as Function)() : defaultValue;
|
||||
},
|
||||
}) as any;
|
||||
}
|
||||
@@ -1440,38 +1383,6 @@ export function pipe<
|
||||
}) as any;
|
||||
}
|
||||
|
||||
// ZodMiniCodec
|
||||
export interface ZodMiniCodec<A extends SomeType = core.$ZodType, B extends SomeType = core.$ZodType>
|
||||
extends ZodMiniPipe<A, B>,
|
||||
core.$ZodCodec<A, B> {
|
||||
_zod: core.$ZodCodecInternals<A, B>;
|
||||
def: core.$ZodCodecDef<A, B>;
|
||||
}
|
||||
export const ZodMiniCodec: core.$constructor<ZodMiniCodec> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodMiniCodec",
|
||||
(inst, def) => {
|
||||
ZodMiniPipe.init(inst, def);
|
||||
core.$ZodCodec.init(inst, def);
|
||||
}
|
||||
);
|
||||
|
||||
export function codec<const A extends SomeType, B extends core.SomeType = core.$ZodType>(
|
||||
in_: A,
|
||||
out: B,
|
||||
params: {
|
||||
decode: (value: core.output<A>, payload: core.ParsePayload<core.output<A>>) => core.util.MaybeAsync<core.input<B>>;
|
||||
encode: (value: core.input<B>, payload: core.ParsePayload<core.input<B>>) => core.util.MaybeAsync<core.output<A>>;
|
||||
}
|
||||
): ZodMiniCodec<A, B> {
|
||||
return new ZodMiniCodec({
|
||||
type: "pipe",
|
||||
in: in_ as any as core.$ZodType,
|
||||
out: out as any as core.$ZodType,
|
||||
transform: params.decode as any,
|
||||
reverseTransform: params.encode as any,
|
||||
}) as any;
|
||||
}
|
||||
|
||||
// /** @deprecated Use `z.pipe()` and `z.transform()` instead. */
|
||||
// export function preprocess<A, U extends core.$ZodType>(
|
||||
// fn: (arg: unknown, ctx: core.ParsePayload) => A,
|
||||
@@ -1607,17 +1518,6 @@ export function refine<T>(
|
||||
return core._refine(ZodMiniCustom, fn, _params);
|
||||
}
|
||||
|
||||
// superRefine
|
||||
export function superRefine<T>(
|
||||
fn: (arg: T, payload: core.$RefinementCtx<T>) => void | Promise<void>
|
||||
): core.$ZodCheck<T> {
|
||||
return core._superRefine(fn);
|
||||
}
|
||||
|
||||
// Re-export describe and meta from core
|
||||
export const describe = core.describe;
|
||||
export const meta = core.meta;
|
||||
|
||||
// instanceof
|
||||
abstract class Class {
|
||||
constructor(..._args: any[]) {}
|
||||
@@ -1635,16 +1535,18 @@ function _instanceof<T extends typeof Class>(
|
||||
export { _instanceof as instanceof };
|
||||
|
||||
// stringbool
|
||||
export const stringbool: (_params?: string | core.$ZodStringBoolParams) => ZodMiniCodec<ZodMiniString, ZodMiniBoolean> =
|
||||
(...args) =>
|
||||
core._stringbool(
|
||||
{
|
||||
Codec: ZodMiniCodec,
|
||||
Boolean: ZodMiniBoolean,
|
||||
String: ZodMiniString,
|
||||
},
|
||||
...args
|
||||
) as any;
|
||||
export const stringbool: (
|
||||
_params?: string | core.$ZodStringBoolParams
|
||||
) => ZodMiniPipe<ZodMiniPipe<ZodMiniString, ZodMiniTransform<boolean, string>>, ZodMiniBoolean> = (...args) =>
|
||||
core._stringbool(
|
||||
{
|
||||
Pipe: ZodMiniPipe,
|
||||
Boolean: ZodMiniBoolean,
|
||||
String: ZodMiniString,
|
||||
Transform: ZodMiniTransform,
|
||||
},
|
||||
...args
|
||||
) as any;
|
||||
|
||||
// json
|
||||
|
||||
@@ -1675,68 +1577,3 @@ export function json(): ZodMiniJSONSchema {
|
||||
});
|
||||
return jsonSchema;
|
||||
}
|
||||
|
||||
// ZodMiniFunction
|
||||
export interface ZodMiniFunction<
|
||||
Args extends core.$ZodFunctionIn = core.$ZodFunctionIn,
|
||||
Returns extends core.$ZodFunctionOut = core.$ZodFunctionOut,
|
||||
> extends _ZodMiniType<core.$ZodFunctionInternals<Args, Returns>>,
|
||||
core.$ZodFunction<Args, Returns> {
|
||||
_def: core.$ZodFunctionDef<Args, Returns>;
|
||||
_input: core.$InferInnerFunctionType<Args, Returns>;
|
||||
_output: core.$InferOuterFunctionType<Args, Returns>;
|
||||
|
||||
input<const Items extends util.TupleItems, const Rest extends core.$ZodFunctionOut = core.$ZodFunctionOut>(
|
||||
args: Items,
|
||||
rest?: Rest
|
||||
): ZodMiniFunction<ZodMiniTuple<Items, Rest>, Returns>;
|
||||
input<NewArgs extends core.$ZodFunctionIn>(args: NewArgs): ZodMiniFunction<NewArgs, Returns>;
|
||||
input(...args: any[]): ZodMiniFunction<any, Returns>;
|
||||
|
||||
output<NewReturns extends core.$ZodFunctionOut>(output: NewReturns): ZodMiniFunction<Args, NewReturns>;
|
||||
}
|
||||
|
||||
export const ZodMiniFunction: core.$constructor<ZodMiniFunction> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodMiniFunction",
|
||||
(inst, def) => {
|
||||
core.$ZodFunction.init(inst, def);
|
||||
ZodMiniType.init(inst, def);
|
||||
}
|
||||
);
|
||||
|
||||
export function _function(): ZodMiniFunction;
|
||||
export function _function<const In extends Array<SomeType> = Array<SomeType>>(params: {
|
||||
input: In;
|
||||
}): ZodMiniFunction<ZodMiniTuple<In, null>, core.$ZodFunctionOut>;
|
||||
export function _function<
|
||||
const In extends Array<SomeType> = Array<SomeType>,
|
||||
const Out extends core.$ZodFunctionOut = core.$ZodFunctionOut,
|
||||
>(params: {
|
||||
input: In;
|
||||
output: Out;
|
||||
}): ZodMiniFunction<ZodMiniTuple<In, null>, Out>;
|
||||
export function _function<const In extends core.$ZodFunctionIn = core.$ZodFunctionIn>(params: {
|
||||
input: In;
|
||||
}): ZodMiniFunction<In, core.$ZodFunctionOut>;
|
||||
export function _function<const Out extends core.$ZodFunctionOut = core.$ZodFunctionOut>(params: {
|
||||
output: Out;
|
||||
}): ZodMiniFunction<core.$ZodFunctionIn, Out>;
|
||||
export function _function<
|
||||
In extends core.$ZodFunctionIn = core.$ZodFunctionIn,
|
||||
Out extends core.$ZodFunctionOut = core.$ZodFunctionOut,
|
||||
>(params?: {
|
||||
input: In;
|
||||
output: Out;
|
||||
}): ZodMiniFunction<In, Out>;
|
||||
export function _function(params?: {
|
||||
output?: core.$ZodFunctionOut;
|
||||
input?: core.$ZodFunctionArgs | Array<SomeType>;
|
||||
}): ZodMiniFunction {
|
||||
return new ZodMiniFunction({
|
||||
type: "function",
|
||||
input: Array.isArray(params?.input) ? tuple(params?.input as any) : (params?.input ?? array(unknown())),
|
||||
output: params?.output ?? unknown(),
|
||||
});
|
||||
}
|
||||
|
||||
export { _function as function };
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { test } from "vitest";
|
||||
|
||||
import * as z from "zod/mini";
|
||||
import * as z from "zod/v4-mini";
|
||||
|
||||
test("assignability", () => {
|
||||
// $ZodString
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/mini";
|
||||
import * as z from "zod/v4-mini";
|
||||
import { util as zc } from "zod/v4/core";
|
||||
|
||||
test("min/max", () => {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/mini";
|
||||
import * as z from "zod/v4-mini";
|
||||
|
||||
test("no locale by default", () => {
|
||||
const result = z.safeParse(z.string(), 12);
|
||||
|
||||
+38
@@ -1,5 +1,43 @@
|
||||
import { expect, test } from "vitest";
|
||||
// import * as z from "zod/v4/core";
|
||||
|
||||
test("z.function", () => {
|
||||
expect(true).toEqual(true);
|
||||
});
|
||||
|
||||
// test("z.function", () => {
|
||||
// const a = z.function({
|
||||
// args: z.tuple([z.string()]),
|
||||
// returns: z.string(),
|
||||
// });
|
||||
|
||||
// const myFunc = a.implement((name: string | number) => `Hello, ${name}!`);
|
||||
|
||||
// expect(myFunc("world")).toEqual("Hello, world!");
|
||||
// expect(() => myFunc(123 as any)).toThrow();
|
||||
|
||||
// // this won't run
|
||||
// () => {
|
||||
// // @ts-expect-error
|
||||
// const r = myFunc(123);
|
||||
// expectTypeOf(r).toEqualTypeOf<string>();
|
||||
// };
|
||||
// });
|
||||
|
||||
// test("z.function async", async () => {
|
||||
// const b = z.function({
|
||||
// args: z.tuple([z.string()]).$check(async (_) => {}),
|
||||
// returns: z.string().$check(async (_) => {}),
|
||||
// });
|
||||
// const myFuncAsync = b.implementAsync(async (name) => `Hello, ${name}!`);
|
||||
|
||||
// expect(await myFuncAsync("world")).toEqual("Hello, world!");
|
||||
// expect(myFuncAsync(123 as any)).rejects.toThrow();
|
||||
|
||||
// // this won't run
|
||||
// () => {
|
||||
// // @ts-expect-error
|
||||
// const r = myFuncAsync(123);
|
||||
// expectTypeOf(r).toEqualTypeOf<Promise<string>>();
|
||||
// };
|
||||
// });
|
||||
|
||||
+2
-53
@@ -1,5 +1,5 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/mini";
|
||||
import * as z from "zod/v4-mini";
|
||||
import type { util } from "zod/v4/core";
|
||||
|
||||
test("z.boolean", () => {
|
||||
@@ -296,29 +296,6 @@ test("z.record", () => {
|
||||
expect(() => z.parse(c, { a: "hello", b: "world" })).toThrow();
|
||||
// extra keys
|
||||
expect(() => z.parse(c, { a: "hello", b: "world", c: "world", d: "world" })).toThrow();
|
||||
|
||||
// literal union keys
|
||||
const d = z.record(z.union([z.literal("a"), z.literal(0)]), z.string());
|
||||
type d = z.output<typeof d>;
|
||||
expectTypeOf<d>().toEqualTypeOf<Record<"a" | 0, string>>();
|
||||
expect(z.parse(d, { a: "hello", 0: "world" })).toEqual({
|
||||
a: "hello",
|
||||
0: "world",
|
||||
});
|
||||
|
||||
// TypeScript enum keys
|
||||
enum Enum {
|
||||
A = 0,
|
||||
B = "hi",
|
||||
}
|
||||
|
||||
const e = z.record(z.enum(Enum), z.string());
|
||||
type e = z.output<typeof e>;
|
||||
expectTypeOf<e>().toEqualTypeOf<Record<Enum, string>>();
|
||||
expect(z.parse(e, { [Enum.A]: "hello", [Enum.B]: "world" })).toEqual({
|
||||
[Enum.A]: "hello",
|
||||
[Enum.B]: "world",
|
||||
});
|
||||
});
|
||||
|
||||
test("z.map", () => {
|
||||
@@ -812,7 +789,7 @@ test("z.stringbool", () => {
|
||||
test("z.promise", async () => {
|
||||
const a = z.promise(z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<Promise<string>>();
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
|
||||
expect(await z.safeParseAsync(a, Promise.resolve("hello"))).toMatchObject({
|
||||
success: true,
|
||||
@@ -892,31 +869,3 @@ test("def typing", () => {
|
||||
z.catch(z.string(), "fallback").def.type satisfies "catch";
|
||||
z.file().def.type satisfies "file";
|
||||
});
|
||||
|
||||
test("defaulted object schema returns shallow clone", () => {
|
||||
const schema = z._default(
|
||||
z.object({
|
||||
a: z.string(),
|
||||
}),
|
||||
{ a: "x" }
|
||||
);
|
||||
const result1 = schema.parse(undefined);
|
||||
const result2 = schema.parse(undefined);
|
||||
expect(result1).not.toBe(result2);
|
||||
expect(result1).toEqual(result2);
|
||||
});
|
||||
|
||||
test("runtime type property exists and returns correct values", () => {
|
||||
const stringSchema = z.string();
|
||||
expect(stringSchema.type).toBe("string");
|
||||
});
|
||||
|
||||
test("type narrowing works with type property", () => {
|
||||
type ArrayOrRecord = z.ZodMiniArray<z.ZodMiniString> | z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniAny>;
|
||||
const arraySchema = z.array(z.string()) as ArrayOrRecord;
|
||||
|
||||
if (arraySchema.type === "array") {
|
||||
expectTypeOf(arraySchema).toEqualTypeOf<z.ZodMiniArray<z.ZodMiniString<unknown>>>();
|
||||
expect(arraySchema.def.element).toBeDefined();
|
||||
}
|
||||
});
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/mini";
|
||||
import * as z from "zod/v4-mini";
|
||||
|
||||
test("z.number", () => {
|
||||
const a = z.number();
|
||||
|
||||
+1
-16
@@ -1,5 +1,5 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/mini";
|
||||
import * as z from "zod/v4-mini";
|
||||
|
||||
test("z.object", () => {
|
||||
const a = z.object({
|
||||
@@ -89,12 +89,6 @@ test("z.keyof", () => {
|
||||
type UserKeys = z.infer<typeof userKeysSchema>;
|
||||
expectTypeOf<UserKeys>().toEqualTypeOf<"name" | "age" | "email">();
|
||||
expect(userKeysSchema).toBeDefined();
|
||||
expect(userKeysSchema._zod.def.type).toBe("enum");
|
||||
expect(userKeysSchema._zod.def.entries).toEqual({
|
||||
name: "name",
|
||||
age: "age",
|
||||
email: "email",
|
||||
});
|
||||
expect(z.safeParse(userKeysSchema, "name").success).toBe(true);
|
||||
expect(z.safeParse(userKeysSchema, "age").success).toBe(true);
|
||||
expect(z.safeParse(userKeysSchema, "email").success).toBe(true);
|
||||
@@ -116,15 +110,6 @@ test("z.extend", () => {
|
||||
expect(z.safeParse(extendedSchema, { name: "John", age: 30, isAdmin: true }).success).toBe(true);
|
||||
});
|
||||
|
||||
test("z.safeExtend", () => {
|
||||
const extended = z.safeExtend(userSchema, { name: z.string() });
|
||||
expect(z.safeParse(extended, { name: "John", age: 30 }).success).toBe(true);
|
||||
type Extended = z.infer<typeof extended>;
|
||||
expectTypeOf<Extended>().toEqualTypeOf<{ name: string; age: number; email?: string }>();
|
||||
// @ts-expect-error
|
||||
z.safeExtend(userSchema, { name: z.number() });
|
||||
});
|
||||
|
||||
test("z.pick", () => {
|
||||
const pickedSchema = z.pick(userSchema, { name: true, email: true });
|
||||
type PickedUser = z.infer<typeof pickedSchema>;
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/mini";
|
||||
import * as z from "zod/v4-mini";
|
||||
|
||||
declare module "zod/v4/core" {
|
||||
interface $ZodType {
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/mini";
|
||||
import { z } from "zod/v4-mini";
|
||||
|
||||
test("recursion with z.lazy", () => {
|
||||
const data = {
|
||||
|
||||
+1
-49
@@ -1,5 +1,5 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/mini";
|
||||
import * as z from "zod/v4-mini";
|
||||
|
||||
const FAIL = { success: false };
|
||||
|
||||
@@ -241,38 +241,6 @@ test("z.ipv6", () => {
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.mac", () => {
|
||||
const a = z.mac();
|
||||
// valid mac
|
||||
expect(z.parse(a, "00:1A:2B:3C:4D:5E")).toEqual("00:1A:2B:3C:4D:5E");
|
||||
// invalid mac (dash delimiter not accepted by default)
|
||||
expect(() => z.parse(a, "01-23-45-67-89-AB")).toThrow();
|
||||
expect(() => z.parse(a, "00:1A:2B::4D:5E")).toThrow();
|
||||
expect(() => z.parse(a, "00:1a-2B:3c-4D:5e")).toThrow();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
// wrong type
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.mac with custom delimiter", () => {
|
||||
const a = z.mac({ delimiter: ":" });
|
||||
// valid mac with colon
|
||||
expect(z.parse(a, "00:1A:2B:3C:4D:5E")).toEqual("00:1A:2B:3C:4D:5E");
|
||||
// invalid mac with dash
|
||||
expect(() => z.parse(a, "00-1A-2B-3C-4D-5E")).toThrow();
|
||||
|
||||
const b = z.mac({ delimiter: "-" });
|
||||
// valid mac with dash
|
||||
expect(z.parse(b, "00-1A-2B-3C-4D-5E")).toEqual("00-1A-2B-3C-4D-5E");
|
||||
// invalid mac with colon
|
||||
expect(() => z.parse(b, "00:1A:2B:3C:4D:5E")).toThrow();
|
||||
|
||||
const c = z.mac({ delimiter: ":" });
|
||||
// colon-only mac
|
||||
expect(z.parse(c, "00:1A:2B:3C:4D:5E")).toEqual("00:1A:2B:3C:4D:5E");
|
||||
expect(() => z.parse(c, "00-1A-2B-3C-4D-5E")).toThrow();
|
||||
});
|
||||
|
||||
test("z.base64", () => {
|
||||
const a = z.base64();
|
||||
// valid base64
|
||||
@@ -329,19 +297,3 @@ test("z.jwt", () => {
|
||||
// wrong type
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.hash generic format", () => {
|
||||
expect(z.hash("sha256").parse("a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3")).toBe(
|
||||
"a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3"
|
||||
);
|
||||
|
||||
// --- Type-level checks (ensure the literal format string is encoded in the return type)
|
||||
expectTypeOf(z.hash("md5")).toEqualTypeOf<z.ZodMiniCustomStringFormat<"md5_hex">>();
|
||||
expectTypeOf(z.hash("sha1")).toEqualTypeOf<z.ZodMiniCustomStringFormat<"sha1_hex">>();
|
||||
expectTypeOf(z.hash("sha256", { enc: "base64" as const })).toEqualTypeOf<
|
||||
z.ZodMiniCustomStringFormat<"sha256_base64">
|
||||
>();
|
||||
expectTypeOf(z.hash("sha384", { enc: "base64url" as const })).toEqualTypeOf<
|
||||
z.ZodMiniCustomStringFormat<"sha384_base64url">
|
||||
>();
|
||||
});
|
||||
|
||||
+1
-1
@@ -113,7 +113,7 @@ class ZodError extends Error {
|
||||
return this.issues.length === 0;
|
||||
}
|
||||
flatten(mapper = (issue) => issue.message) {
|
||||
const fieldErrors = Object.create(null);
|
||||
const fieldErrors = {};
|
||||
const formErrors = [];
|
||||
for (const sub of this.issues) {
|
||||
if (sub.path.length > 0) {
|
||||
|
||||
+6
-6
@@ -10,21 +10,21 @@ export type typeToFlattenedError<T, U = string> = {
|
||||
};
|
||||
};
|
||||
export declare const ZodIssueCode: {
|
||||
custom: "custom";
|
||||
invalid_type: "invalid_type";
|
||||
too_big: "too_big";
|
||||
too_small: "too_small";
|
||||
not_multiple_of: "not_multiple_of";
|
||||
unrecognized_keys: "unrecognized_keys";
|
||||
invalid_union: "invalid_union";
|
||||
invalid_literal: "invalid_literal";
|
||||
custom: "custom";
|
||||
invalid_union: "invalid_union";
|
||||
invalid_union_discriminator: "invalid_union_discriminator";
|
||||
invalid_enum_value: "invalid_enum_value";
|
||||
unrecognized_keys: "unrecognized_keys";
|
||||
invalid_arguments: "invalid_arguments";
|
||||
invalid_return_type: "invalid_return_type";
|
||||
invalid_date: "invalid_date";
|
||||
invalid_string: "invalid_string";
|
||||
too_small: "too_small";
|
||||
too_big: "too_big";
|
||||
invalid_intersection_types: "invalid_intersection_types";
|
||||
not_multiple_of: "not_multiple_of";
|
||||
not_finite: "not_finite";
|
||||
};
|
||||
export type ZodIssueCode = keyof typeof ZodIssueCode;
|
||||
|
||||
+6
-6
@@ -10,21 +10,21 @@ export type typeToFlattenedError<T, U = string> = {
|
||||
};
|
||||
};
|
||||
export declare const ZodIssueCode: {
|
||||
custom: "custom";
|
||||
invalid_type: "invalid_type";
|
||||
too_big: "too_big";
|
||||
too_small: "too_small";
|
||||
not_multiple_of: "not_multiple_of";
|
||||
unrecognized_keys: "unrecognized_keys";
|
||||
invalid_union: "invalid_union";
|
||||
invalid_literal: "invalid_literal";
|
||||
custom: "custom";
|
||||
invalid_union: "invalid_union";
|
||||
invalid_union_discriminator: "invalid_union_discriminator";
|
||||
invalid_enum_value: "invalid_enum_value";
|
||||
unrecognized_keys: "unrecognized_keys";
|
||||
invalid_arguments: "invalid_arguments";
|
||||
invalid_return_type: "invalid_return_type";
|
||||
invalid_date: "invalid_date";
|
||||
invalid_string: "invalid_string";
|
||||
too_small: "too_small";
|
||||
too_big: "too_big";
|
||||
invalid_intersection_types: "invalid_intersection_types";
|
||||
not_multiple_of: "not_multiple_of";
|
||||
not_finite: "not_finite";
|
||||
};
|
||||
export type ZodIssueCode = keyof typeof ZodIssueCode;
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ export class ZodError extends Error {
|
||||
return this.issues.length === 0;
|
||||
}
|
||||
flatten(mapper = (issue) => issue.message) {
|
||||
const fieldErrors = Object.create(null);
|
||||
const fieldErrors = {};
|
||||
const formErrors = [];
|
||||
for (const sub of this.issues) {
|
||||
if (sub.path.length > 0) {
|
||||
|
||||
-1
@@ -109,4 +109,3 @@ const errorMap = (issue, _ctx) => {
|
||||
return { message };
|
||||
};
|
||||
exports.default = errorMap;
|
||||
module.exports = exports.default;
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
import { type ZodErrorMap } from "../ZodError.cjs";
|
||||
declare const errorMap: ZodErrorMap;
|
||||
export = errorMap;
|
||||
export default errorMap;
|
||||
|
||||
-2
@@ -459,7 +459,6 @@ function isValidJWT(jwt, alg) {
|
||||
.replace(/-/g, "+")
|
||||
.replace(/_/g, "/")
|
||||
.padEnd(header.length + ((4 - (header.length % 4)) % 4), "=");
|
||||
// @ts-ignore
|
||||
const decoded = JSON.parse(atob(base64));
|
||||
if (typeof decoded !== "object" || decoded === null)
|
||||
return false;
|
||||
@@ -640,7 +639,6 @@ class ZodString extends ZodType {
|
||||
}
|
||||
else if (check.kind === "url") {
|
||||
try {
|
||||
// @ts-ignore
|
||||
new URL(input.data);
|
||||
}
|
||||
catch {
|
||||
|
||||
+1
-4
@@ -527,10 +527,7 @@ export type noUnrecognized<Obj extends object, Shape extends object> = {
|
||||
[k in keyof Obj]: k extends keyof Shape ? Obj[k] : never;
|
||||
};
|
||||
export declare class ZodObject<T extends ZodRawShape, UnknownKeys extends UnknownKeysParam = UnknownKeysParam, Catchall extends ZodTypeAny = ZodTypeAny, Output = objectOutputType<T, Catchall, UnknownKeys>, Input = objectInputType<T, Catchall, UnknownKeys>> extends ZodType<Output, ZodObjectDef<T, UnknownKeys, Catchall>, Input> {
|
||||
_cached: {
|
||||
shape: T;
|
||||
keys: string[];
|
||||
} | null;
|
||||
private _cached;
|
||||
_getCached(): {
|
||||
shape: T;
|
||||
keys: string[];
|
||||
|
||||
+1
-4
@@ -527,10 +527,7 @@ export type noUnrecognized<Obj extends object, Shape extends object> = {
|
||||
[k in keyof Obj]: k extends keyof Shape ? Obj[k] : never;
|
||||
};
|
||||
export declare class ZodObject<T extends ZodRawShape, UnknownKeys extends UnknownKeysParam = UnknownKeysParam, Catchall extends ZodTypeAny = ZodTypeAny, Output = objectOutputType<T, Catchall, UnknownKeys>, Input = objectInputType<T, Catchall, UnknownKeys>> extends ZodType<Output, ZodObjectDef<T, UnknownKeys, Catchall>, Input> {
|
||||
_cached: {
|
||||
shape: T;
|
||||
keys: string[];
|
||||
} | null;
|
||||
private _cached;
|
||||
_getCached(): {
|
||||
shape: T;
|
||||
keys: string[];
|
||||
|
||||
-2
@@ -450,7 +450,6 @@ function isValidJWT(jwt, alg) {
|
||||
.replace(/-/g, "+")
|
||||
.replace(/_/g, "/")
|
||||
.padEnd(header.length + ((4 - (header.length % 4)) % 4), "=");
|
||||
// @ts-ignore
|
||||
const decoded = JSON.parse(atob(base64));
|
||||
if (typeof decoded !== "object" || decoded === null)
|
||||
return false;
|
||||
@@ -631,7 +630,6 @@ export class ZodString extends ZodType {
|
||||
}
|
||||
else if (check.kind === "url") {
|
||||
try {
|
||||
// @ts-ignore
|
||||
new URL(input.data);
|
||||
}
|
||||
catch {
|
||||
|
||||
+1
-2
@@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.slugify = exports.toUpperCase = exports.toLowerCase = exports.trim = exports.normalize = exports.overwrite = exports.mime = exports.property = exports.endsWith = exports.startsWith = exports.includes = exports.uppercase = exports.lowercase = exports.regex = exports.length = exports.minLength = exports.maxLength = exports.size = exports.minSize = exports.maxSize = exports.multipleOf = exports.nonnegative = exports.nonpositive = exports.negative = exports.positive = exports.gte = exports.gt = exports.lte = exports.lt = void 0;
|
||||
exports.toUpperCase = exports.toLowerCase = exports.trim = exports.normalize = exports.overwrite = exports.mime = exports.property = exports.endsWith = exports.startsWith = exports.includes = exports.uppercase = exports.lowercase = exports.regex = exports.length = exports.minLength = exports.maxLength = exports.size = exports.minSize = exports.maxSize = exports.multipleOf = exports.nonnegative = exports.nonpositive = exports.negative = exports.positive = exports.gte = exports.gt = exports.lte = exports.lt = void 0;
|
||||
var index_js_1 = require("../core/index.cjs");
|
||||
Object.defineProperty(exports, "lt", { enumerable: true, get: function () { return index_js_1._lt; } });
|
||||
Object.defineProperty(exports, "lte", { enumerable: true, get: function () { return index_js_1._lte; } });
|
||||
@@ -30,4 +30,3 @@ Object.defineProperty(exports, "normalize", { enumerable: true, get: function ()
|
||||
Object.defineProperty(exports, "trim", { enumerable: true, get: function () { return index_js_1._trim; } });
|
||||
Object.defineProperty(exports, "toLowerCase", { enumerable: true, get: function () { return index_js_1._toLowerCase; } });
|
||||
Object.defineProperty(exports, "toUpperCase", { enumerable: true, get: function () { return index_js_1._toUpperCase; } });
|
||||
Object.defineProperty(exports, "slugify", { enumerable: true, get: function () { return index_js_1._slugify; } });
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
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, _slugify as slugify, type $RefinementCtx as RefinementCtx, } from "../core/index.cjs";
|
||||
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.cjs";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user