removed node_modules

This commit is contained in:
Mat12143 2025-08-01 22:17:26 +02:00
parent 51aafb9771
commit b265529a8d
630 changed files with 60 additions and 101669 deletions

View file

@ -1,45 +1,21 @@
<script lang="ts">
import QueueSlider from "$lib/components/QueueSlider.svelte"
import SuggestionInput from "$lib/components/SuggestionInput.svelte"
import SuggestionList from "$lib/components/SuggestionList.svelte"
import { onMount } from "svelte"
let songs = $state([
{
name: "Cisco PT - Cantarex",
image: "https://s2.qwant.com/thumbr/474x474/5/9/bcbd0c0aeb1838f6916bf452c557251d7be985a13449e49fccb567a3374d4e/OIP.pmqEiKWv47zViDGgPgbbQAHaHa.jpg?u=https%3A%2F%2Ftse.mm.bing.net%2Fth%2Fid%2FOIP.pmqEiKWv47zViDGgPgbbQAHaHa%3Fr%3D0%26pid%3DApi&q=0&b=1&p=0&a=0",
points: 0,
},
{
name: "Io e i miei banchi - Paul Ham",
image: "https://i.prcdn.co/img?regionKey=RbtvKb5E1Cv4j1VWm2uGrw%3D%3D",
points: 0,
},
{
name: "Ragatthi - Bersatetthi",
image: "https://s2.qwant.com/thumbr/474x474/5/9/bcbd0c0aeb1838f6916bf452c557251d7be985a13449e49fccb567a3374d4e/OIP.pmqEiKWv47zViDGgPgbbQAHaHa.jpg?u=https%3A%2F%2Ftse.mm.bing.net%2Fth%2Fid%2FOIP.pmqEiKWv47zViDGgPgbbQAHaHa%3Fr%3D0%26pid%3DApi&q=0&b=1&p=0&a=0",
points: 0,
},
{
name: "Quarta",
image: "https://s2.qwant.com/thumbr/474x474/5/9/bcbd0c0aeb1838f6916bf452c557251d7be985a13449e49fccb567a3374d4e/OIP.pmqEiKWv47zViDGgPgbbQAHaHa.jpg?u=https%3A%2F%2Ftse.mm.bing.net%2Fth%2Fid%2FOIP.pmqEiKWv47zViDGgPgbbQAHaHa%3Fr%3D0%26pid%3DApi&q=0&b=1&p=0&a=0",
points: 0,
},
{
name: "Quinta",
image: "https://s2.qwant.com/thumbr/474x474/5/9/bcbd0c0aeb1838f6916bf452c557251d7be985a13449e49fccb567a3374d4e/OIP.pmqEiKWv47zViDGgPgbbQAHaHa.jpg?u=https%3A%2F%2Ftse.mm.bing.net%2Fth%2Fid%2FOIP.pmqEiKWv47zViDGgPgbbQAHaHa%3Fr%3D0%26pid%3DApi&q=0&b=1&p=0&a=0",
points: 0,
},
])
let pos = $state()
let playing = $state(1)
function onGPS(t: GeolocationPosition) {
pos = t.coords
}
function failGPS(t: GeolocationPositionError) {
console.log(t)
}
onMount(() => {
navigator.geolocation.getCurrentPosition(onGPS, failGPS)
})
</script>
<div class="flex w-full flex-col items-center justify-center p-4 lg:p-10">
<QueueSlider {songs} {playing} />
<div class="w-full py-6 lg:w-[30vw]">
<SuggestionInput />
</div>
<div class="w-full py-6 lg:w-[30vw]">
<SuggestionList suggestions={songs} />
</div>
<div class="flex h-full w-full items-center justify-center">
<div></div>
</div>

View file

@ -0,0 +1,45 @@
<script lang="ts">
import QueueSlider from "$lib/components/QueueSlider.svelte"
import SuggestionInput from "$lib/components/SuggestionInput.svelte"
import SuggestionList from "$lib/components/SuggestionList.svelte"
let songs = $state([
{
name: "Cisco PT - Cantarex",
image: "https://s2.qwant.com/thumbr/474x474/5/9/bcbd0c0aeb1838f6916bf452c557251d7be985a13449e49fccb567a3374d4e/OIP.pmqEiKWv47zViDGgPgbbQAHaHa.jpg?u=https%3A%2F%2Ftse.mm.bing.net%2Fth%2Fid%2FOIP.pmqEiKWv47zViDGgPgbbQAHaHa%3Fr%3D0%26pid%3DApi&q=0&b=1&p=0&a=0",
points: 0,
},
{
name: "Io e i miei banchi - Paul Ham",
image: "https://i.prcdn.co/img?regionKey=RbtvKb5E1Cv4j1VWm2uGrw%3D%3D",
points: 0,
},
{
name: "Ragatthi - Bersatetthi",
image: "https://s2.qwant.com/thumbr/474x474/5/9/bcbd0c0aeb1838f6916bf452c557251d7be985a13449e49fccb567a3374d4e/OIP.pmqEiKWv47zViDGgPgbbQAHaHa.jpg?u=https%3A%2F%2Ftse.mm.bing.net%2Fth%2Fid%2FOIP.pmqEiKWv47zViDGgPgbbQAHaHa%3Fr%3D0%26pid%3DApi&q=0&b=1&p=0&a=0",
points: 0,
},
{
name: "Quarta",
image: "https://s2.qwant.com/thumbr/474x474/5/9/bcbd0c0aeb1838f6916bf452c557251d7be985a13449e49fccb567a3374d4e/OIP.pmqEiKWv47zViDGgPgbbQAHaHa.jpg?u=https%3A%2F%2Ftse.mm.bing.net%2Fth%2Fid%2FOIP.pmqEiKWv47zViDGgPgbbQAHaHa%3Fr%3D0%26pid%3DApi&q=0&b=1&p=0&a=0",
points: 0,
},
{
name: "Quinta",
image: "https://s2.qwant.com/thumbr/474x474/5/9/bcbd0c0aeb1838f6916bf452c557251d7be985a13449e49fccb567a3374d4e/OIP.pmqEiKWv47zViDGgPgbbQAHaHa.jpg?u=https%3A%2F%2Ftse.mm.bing.net%2Fth%2Fid%2FOIP.pmqEiKWv47zViDGgPgbbQAHaHa%3Fr%3D0%26pid%3DApi&q=0&b=1&p=0&a=0",
points: 0,
},
])
let playing = $state(1)
</script>
<div class="flex w-full flex-col items-center justify-center p-4 lg:p-10">
<QueueSlider {songs} {playing} />
<div class="w-full py-6 lg:w-[30vw]">
<SuggestionInput />
</div>
<div class="w-full py-6 lg:w-[30vw]">
<SuggestionList suggestions={songs} />
</div>
</div>

16
node_modules/.package-lock.json generated vendored
View file

@ -1,16 +0,0 @@
{
"name": "team-1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"node_modules/zod": {
"version": "4.0.14",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.0.14.tgz",
"integrity": "sha512-nGFJTnJN6cM2v9kXL+SOBq3AtjQby3Mv5ySGFof5UGRHrRioSJ5iG680cYNjE/yWk671nROcpPj4hAS8nyLhSw==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}
}
}
}

21
node_modules/zod/LICENSE generated vendored
View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2025 Colin McDonnell
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

208
node_modules/zod/README.md generated vendored
View file

@ -1,208 +0,0 @@
<p align="center">
<img src="logo.svg" width="200px" align="center" alt="Zod logo" />
<h1 align="center">Zod</h1>
<p align="center">
TypeScript-first schema validation with static type inference
<br/>
by <a href="https://x.com/colinhacks">@colinhacks</a>
</p>
</p>
<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://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>
<a href="https://github.com/colinhacks/zod" rel="nofollow"><img src="https://img.shields.io/github/stars/colinhacks/zod" alt="stars"></a>
</p>
<div align="center">
<a href="https://zod.dev/api">Docs</a>
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
<a href="https://discord.gg/RcG33DQJdf">Discord</a>
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
<a href="https://twitter.com/colinhacks">𝕏</a>
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
<a href="https://bsky.app/profile/zod.dev">Bluesky</a>
<br />
</div>
<br/>
<br/>
<h2 align="center">Featured sponsor: Jazz</h2>
<div align="center">
<a href="https://jazz.tools/?utm_source=zod">
<picture width="85%" >
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/garden-co/jazz/938f6767e46cdfded60e50d99bf3b533f4809c68/homepage/homepage/public/Zod%20sponsor%20message.png">
<img alt="jazz logo" src="https://raw.githubusercontent.com/garden-co/jazz/938f6767e46cdfded60e50d99bf3b533f4809c68/homepage/homepage/public/Zod%20sponsor%20message.png" width="85%">
</picture>
</a>
<br/>
<p><sub>Learn more about <a target="_blank" rel="noopener noreferrer" href="mailto:sponsorship@colinhacks.com">featured sponsorships</a></sub></p>
</div>
<br/>
<br/>
<br/>
### [Read the docs →](https://zod.dev/api)
<br/>
<br/>
## What is Zod?
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";
const User = z.object({
name: z.string(),
});
// some untrusted data...
const input = {
/* stuff */
};
// the parsed result is validated and type safe!
const data = User.parse(input);
// so you can use it with confidence :)
console.log(data.name);
```
<br/>
## Features
- Zero external dependencies
- Works in Node.js and all modern browsers
- Tiny: `2kb` core bundle (gzipped)
- Immutable API: methods return a new instance
- Concise interface
- Works with TypeScript and plain JS
- Built-in JSON Schema conversion
- Extensive ecosystem
<br/>
## Installation
```sh
npm install zod
```
<br/>
## Basic usage
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";
const Player = z.object({
username: z.string(),
xp: z.number(),
});
```
### Parsing data
Given any Zod schema, use `.parse` to validate an input. If it's valid, Zod returns a strongly-typed _deep clone_ of the input.
```ts
Player.parse({ username: "billie", xp: 100 });
// => returns { username: "billie", xp: 100 }
```
**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);
await schema.parseAsync("hello");
// => "hello"
```
### Handling errors
When validation fails, the `.parse()` method will throw a `ZodError` instance with granular information about the validation issues.
```ts
try {
Player.parse({ username: 42, xp: "100" });
} catch (err) {
if (err instanceof z.ZodError) {
err.issues;
/* [
{
expected: 'string',
code: 'invalid_type',
path: [ 'username' ],
message: 'Invalid input: expected string'
},
{
expected: 'number',
code: 'invalid_type',
path: [ 'xp' ],
message: 'Invalid input: expected number'
}
] */
}
}
```
To avoid a `try/catch` block, you can use the `.safeParse()` method to get back a plain result object containing either the successfully parsed data or a `ZodError`. The result type is a [discriminated union](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#discriminated-unions), so you can handle both cases conveniently.
```ts
const result = Player.safeParse({ username: 42, xp: "100" });
if (!result.success) {
result.error; // ZodError instance
} else {
result.data; // { username: string; xp: number }
}
```
**Note** — If your schema uses certain asynchronous APIs like `async` [refinements](#refine) or [transforms](#transform), you'll need to use the `.safeParseAsync()` method instead.
```ts
const schema = z.string().refine(async (val) => val.length <= 8);
await schema.safeParseAsync("hello");
// => { success: true; data: "hello" }
```
### Inferring types
Zod infers a static type from your schema definitions. You can extract this type with the `z.infer<>` utility and use it however you like.
```ts
const Player = z.object({
username: z.string(),
xp: z.number(),
});
// extract the inferred type
type Player = z.infer<typeof Player>;
// use it in your code
const player: Player = { username: "billie", xp: 100 };
```
In some cases, the input & output types of a schema can diverge. For instance, the `.transform()` API can convert the input from one type to another. In these cases, you can extract the input and output types independently:
```ts
const mySchema = z.string().transform((val) => val.length);
type MySchemaIn = z.input<typeof mySchema>;
// => string
type MySchemaOut = z.output<typeof mySchema>; // equivalent to z.infer<typeof mySchema>
// number
```

33
node_modules/zod/index.cjs generated vendored
View file

@ -1,33 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.z = void 0;
const z = __importStar(require("./v4/classic/external.cjs"));
exports.z = z;
__exportStar(require("./v4/classic/external.cjs"), exports);
exports.default = z;

4
node_modules/zod/index.d.cts generated vendored
View file

@ -1,4 +0,0 @@
import * as z from "./v4/classic/external.cjs";
export * from "./v4/classic/external.cjs";
export { z };
export default z;

4
node_modules/zod/index.d.ts generated vendored
View file

@ -1,4 +0,0 @@
import * as z from "./v4/classic/external.js";
export * from "./v4/classic/external.js";
export { z };
export default z;

4
node_modules/zod/index.js generated vendored
View file

@ -1,4 +0,0 @@
import * as z from "./v4/classic/external.js";
export * from "./v4/classic/external.js";
export { z };
export default z;

17
node_modules/zod/locales/index.cjs generated vendored
View file

@ -1,17 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("../v4/locales/index.cjs"), exports);

View file

@ -1 +0,0 @@
export * from "../v4/locales/index.cjs";

View file

@ -1 +0,0 @@
export * from "../v4/locales/index.js";

1
node_modules/zod/locales/index.js generated vendored
View file

@ -1 +0,0 @@
export * from "../v4/locales/index.js";

17
node_modules/zod/mini/index.cjs generated vendored
View file

@ -1,17 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("../v4/mini/index.cjs"), exports);

1
node_modules/zod/mini/index.d.cts generated vendored
View file

@ -1 +0,0 @@
export * from "../v4/mini/index.cjs";

1
node_modules/zod/mini/index.d.ts generated vendored
View file

@ -1 +0,0 @@
export * from "../v4/mini/index.js";

1
node_modules/zod/mini/index.js generated vendored
View file

@ -1 +0,0 @@
export * from "../v4/mini/index.js";

134
node_modules/zod/package.json generated vendored
View file

@ -1,134 +0,0 @@
{
"name": "zod",
"version": "4.0.14",
"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",
"**/*.mjs",
"**/*.cjs",
"**/*.d.ts",
"**/*.d.mts",
"**/*.d.cts"
],
"keywords": [
"typescript",
"schema",
"validation",
"type",
"inference"
],
"main": "./index.cjs",
"types": "./index.d.cts",
"module": "./index.js",
"zshy": {
"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",
"./v4/mini": "./src/v4/mini/index.ts",
"./v4/core": "./src/v4/core/index.ts",
"./v4/locales": "./src/v4/locales/index.ts",
"./v4/locales/*": "./src/v4/locales/*"
},
"conditions": {
"@zod/source": "src"
}
},
"exports": {
"./package.json": "./package.json",
".": {
"@zod/source": "./src/index.ts",
"types": "./index.d.cts",
"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",
"import": "./v3/index.js",
"require": "./v3/index.cjs"
},
"./v4": {
"@zod/source": "./src/v4/index.ts",
"types": "./v4/index.d.cts",
"import": "./v4/index.js",
"require": "./v4/index.cjs"
},
"./v4-mini": {
"@zod/source": "./src/v4-mini/index.ts",
"types": "./v4-mini/index.d.cts",
"import": "./v4-mini/index.js",
"require": "./v4-mini/index.cjs"
},
"./v4/mini": {
"@zod/source": "./src/v4/mini/index.ts",
"types": "./v4/mini/index.d.cts",
"import": "./v4/mini/index.js",
"require": "./v4/mini/index.cjs"
},
"./v4/core": {
"@zod/source": "./src/v4/core/index.ts",
"types": "./v4/core/index.d.cts",
"import": "./v4/core/index.js",
"require": "./v4/core/index.cjs"
},
"./v4/locales": {
"@zod/source": "./src/v4/locales/index.ts",
"types": "./v4/locales/index.d.cts",
"import": "./v4/locales/index.js",
"require": "./v4/locales/index.cjs"
},
"./v4/locales/*": {
"@zod/source": "./src/v4/locales/*",
"types": "./v4/locales/*",
"import": "./v4/locales/*",
"require": "./v4/locales/*"
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/colinhacks/zod.git"
},
"bugs": {
"url": "https://github.com/colinhacks/zod/issues"
},
"support": {
"backing": {
"npm-funding": true
}
},
"scripts": {
"clean": "git clean -xdf . -e node_modules",
"build": "zshy --project tsconfig.build.json",
"postbuild": "pnpm biome check --write .",
"test:watch": "pnpm vitest",
"test": "pnpm vitest run",
"prepublishOnly": "tsx ../../scripts/check-versions.ts"
}
}

4
node_modules/zod/src/index.ts generated vendored
View file

@ -1,4 +0,0 @@
import * as z from "./v4/classic/external.js";
export * from "./v4/classic/external.js";
export { z };
export default z;

View file

@ -1 +0,0 @@
export * from "../v4/locales/index.js";

1
node_modules/zod/src/mini/index.ts generated vendored
View file

@ -1 +0,0 @@
export * from "../v4/mini/index.js";

330
node_modules/zod/src/v3/ZodError.ts generated vendored
View file

@ -1,330 +0,0 @@
import type { Primitive } from "./helpers/typeAliases.js";
import { util, type ZodParsedType } from "./helpers/util.js";
import type { TypeOf, ZodType } from "./index.js";
type allKeys<T> = T extends any ? keyof T : never;
export type inferFlattenedErrors<T extends ZodType<any, any, any>, U = string> = typeToFlattenedError<TypeOf<T>, U>;
export type typeToFlattenedError<T, U = string> = {
formErrors: U[];
fieldErrors: {
[P in allKeys<T>]?: U[];
};
};
export const ZodIssueCode = util.arrayToEnum([
"invalid_type",
"invalid_literal",
"custom",
"invalid_union",
"invalid_union_discriminator",
"invalid_enum_value",
"unrecognized_keys",
"invalid_arguments",
"invalid_return_type",
"invalid_date",
"invalid_string",
"too_small",
"too_big",
"invalid_intersection_types",
"not_multiple_of",
"not_finite",
]);
export type ZodIssueCode = keyof typeof ZodIssueCode;
export type ZodIssueBase = {
path: (string | number)[];
message?: string | undefined;
};
export interface ZodInvalidTypeIssue extends ZodIssueBase {
code: typeof ZodIssueCode.invalid_type;
expected: ZodParsedType;
received: ZodParsedType;
}
export interface ZodInvalidLiteralIssue extends ZodIssueBase {
code: typeof ZodIssueCode.invalid_literal;
expected: unknown;
received: unknown;
}
export interface ZodUnrecognizedKeysIssue extends ZodIssueBase {
code: typeof ZodIssueCode.unrecognized_keys;
keys: string[];
}
export interface ZodInvalidUnionIssue extends ZodIssueBase {
code: typeof ZodIssueCode.invalid_union;
unionErrors: ZodError[];
}
export interface ZodInvalidUnionDiscriminatorIssue extends ZodIssueBase {
code: typeof ZodIssueCode.invalid_union_discriminator;
options: Primitive[];
}
export interface ZodInvalidEnumValueIssue extends ZodIssueBase {
received: string | number;
code: typeof ZodIssueCode.invalid_enum_value;
options: (string | number)[];
}
export interface ZodInvalidArgumentsIssue extends ZodIssueBase {
code: typeof ZodIssueCode.invalid_arguments;
argumentsError: ZodError;
}
export interface ZodInvalidReturnTypeIssue extends ZodIssueBase {
code: typeof ZodIssueCode.invalid_return_type;
returnTypeError: ZodError;
}
export interface ZodInvalidDateIssue extends ZodIssueBase {
code: typeof ZodIssueCode.invalid_date;
}
export type StringValidation =
| "email"
| "url"
| "emoji"
| "uuid"
| "nanoid"
| "regex"
| "cuid"
| "cuid2"
| "ulid"
| "datetime"
| "date"
| "time"
| "duration"
| "ip"
| "cidr"
| "base64"
| "jwt"
| "base64url"
| { includes: string; position?: number | undefined }
| { startsWith: string }
| { endsWith: string };
export interface ZodInvalidStringIssue extends ZodIssueBase {
code: typeof ZodIssueCode.invalid_string;
validation: StringValidation;
}
export interface ZodTooSmallIssue extends ZodIssueBase {
code: typeof ZodIssueCode.too_small;
minimum: number | bigint;
inclusive: boolean;
exact?: boolean;
type: "array" | "string" | "number" | "set" | "date" | "bigint";
}
export interface ZodTooBigIssue extends ZodIssueBase {
code: typeof ZodIssueCode.too_big;
maximum: number | bigint;
inclusive: boolean;
exact?: boolean;
type: "array" | "string" | "number" | "set" | "date" | "bigint";
}
export interface ZodInvalidIntersectionTypesIssue extends ZodIssueBase {
code: typeof ZodIssueCode.invalid_intersection_types;
}
export interface ZodNotMultipleOfIssue extends ZodIssueBase {
code: typeof ZodIssueCode.not_multiple_of;
multipleOf: number | bigint;
}
export interface ZodNotFiniteIssue extends ZodIssueBase {
code: typeof ZodIssueCode.not_finite;
}
export interface ZodCustomIssue extends ZodIssueBase {
code: typeof ZodIssueCode.custom;
params?: { [k: string]: any };
}
export type DenormalizedError = { [k: string]: DenormalizedError | string[] };
export type ZodIssueOptionalMessage =
| ZodInvalidTypeIssue
| ZodInvalidLiteralIssue
| ZodUnrecognizedKeysIssue
| ZodInvalidUnionIssue
| ZodInvalidUnionDiscriminatorIssue
| ZodInvalidEnumValueIssue
| ZodInvalidArgumentsIssue
| ZodInvalidReturnTypeIssue
| ZodInvalidDateIssue
| ZodInvalidStringIssue
| ZodTooSmallIssue
| ZodTooBigIssue
| ZodInvalidIntersectionTypesIssue
| ZodNotMultipleOfIssue
| ZodNotFiniteIssue
| ZodCustomIssue;
export type ZodIssue = ZodIssueOptionalMessage & {
fatal?: boolean | undefined;
message: string;
};
export const quotelessJson = (obj: any) => {
const json = JSON.stringify(obj, null, 2);
return json.replace(/"([^"]+)":/g, "$1:");
};
type recursiveZodFormattedError<T> = T extends [any, ...any[]]
? { [K in keyof T]?: ZodFormattedError<T[K]> }
: T extends any[]
? { [k: number]: ZodFormattedError<T[number]> }
: T extends object
? { [K in keyof T]?: ZodFormattedError<T[K]> }
: unknown;
export type ZodFormattedError<T, U = string> = {
_errors: U[];
} & recursiveZodFormattedError<NonNullable<T>>;
export type inferFormattedError<T extends ZodType<any, any, any>, U = string> = ZodFormattedError<TypeOf<T>, U>;
export class ZodError<T = any> extends Error {
issues: ZodIssue[] = [];
get errors() {
return this.issues;
}
constructor(issues: ZodIssue[]) {
super();
const actualProto = new.target.prototype;
if (Object.setPrototypeOf) {
// eslint-disable-next-line ban/ban
Object.setPrototypeOf(this, actualProto);
} else {
(this as any).__proto__ = actualProto;
}
this.name = "ZodError";
this.issues = issues;
}
format(): ZodFormattedError<T>;
format<U>(mapper: (issue: ZodIssue) => U): ZodFormattedError<T, U>;
format(_mapper?: any) {
const mapper: (issue: ZodIssue) => any =
_mapper ||
function (issue: ZodIssue) {
return issue.message;
};
const fieldErrors: ZodFormattedError<T> = { _errors: [] } as any;
const processError = (error: ZodError) => {
for (const issue of error.issues) {
if (issue.code === "invalid_union") {
issue.unionErrors.map(processError);
} else if (issue.code === "invalid_return_type") {
processError(issue.returnTypeError);
} else if (issue.code === "invalid_arguments") {
processError(issue.argumentsError);
} else if (issue.path.length === 0) {
(fieldErrors as any)._errors.push(mapper(issue));
} else {
let curr: any = fieldErrors;
let i = 0;
while (i < issue.path.length) {
const el = issue.path[i]!;
const terminal = i === issue.path.length - 1;
if (!terminal) {
curr[el] = curr[el] || { _errors: [] };
// if (typeof el === "string") {
// curr[el] = curr[el] || { _errors: [] };
// } else if (typeof el === "number") {
// const errorArray: any = [];
// errorArray._errors = [];
// curr[el] = curr[el] || errorArray;
// }
} else {
curr[el] = curr[el] || { _errors: [] };
curr[el]._errors.push(mapper(issue));
}
curr = curr[el];
i++;
}
}
}
};
processError(this);
return fieldErrors;
}
static create = (issues: ZodIssue[]) => {
const error = new ZodError(issues);
return error;
};
static assert(value: unknown): asserts value is ZodError {
if (!(value instanceof ZodError)) {
throw new Error(`Not a ZodError: ${value}`);
}
}
override toString() {
return this.message;
}
override get message() {
return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2);
}
get isEmpty(): boolean {
return this.issues.length === 0;
}
addIssue = (sub: ZodIssue) => {
this.issues = [...this.issues, sub];
};
addIssues = (subs: ZodIssue[] = []) => {
this.issues = [...this.issues, ...subs];
};
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 = {};
const formErrors: U[] = [];
for (const sub of this.issues) {
if (sub.path.length > 0) {
const firstEl = sub.path[0]!;
fieldErrors[firstEl] = fieldErrors[firstEl] || [];
fieldErrors[firstEl].push(mapper(sub));
} else {
formErrors.push(mapper(sub));
}
}
return { formErrors, fieldErrors };
}
get formErrors() {
return this.flatten();
}
}
type stripPath<T extends object> = T extends any ? util.OmitKeys<T, "path"> : never;
export type IssueData = stripPath<ZodIssueOptionalMessage> & {
path?: (string | number)[];
fatal?: boolean | undefined;
};
export type ErrorMapCtx = {
defaultError: string;
data: any;
};
export type ZodErrorMap = (issue: ZodIssueOptionalMessage, _ctx: ErrorMapCtx) => { message: string };

View file

@ -1,58 +0,0 @@
import Benchmark from "benchmark";
const datetimeValidationSuite = new Benchmark.Suite("datetime");
const DATA = "2021-01-01";
const MONTHS_31 = new Set([1, 3, 5, 7, 8, 10, 12]);
const MONTHS_30 = new Set([4, 6, 9, 11]);
const simpleDatetimeRegex = /^(\d{4})-(\d{2})-(\d{2})$/;
const datetimeRegexNoLeapYearValidation =
/^\d{4}-((0[13578]|10|12)-31|(0[13-9]|1[0-2])-30|(0[1-9]|1[0-2])-(0[1-9]|1\d|2\d))$/;
const datetimeRegexWithLeapYearValidation =
/^((\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\d|3[01])|(0[469]|11)-(0[1-9]|[12]\d|30)|(02)-(0[1-9]|1\d|2[0-8])))$/;
datetimeValidationSuite
.add("new Date()", () => {
return !Number.isNaN(new Date(DATA).getTime());
})
.add("regex (no validation)", () => {
return simpleDatetimeRegex.test(DATA);
})
.add("regex (no leap year)", () => {
return datetimeRegexNoLeapYearValidation.test(DATA);
})
.add("regex (w/ leap year)", () => {
return datetimeRegexWithLeapYearValidation.test(DATA);
})
.add("capture groups + code", () => {
const match = DATA.match(simpleDatetimeRegex);
if (!match) return false;
// Extract year, month, and day from the capture groups
const year = Number.parseInt(match[1], 10);
const month = Number.parseInt(match[2], 10); // month is 0-indexed in JavaScript Date, so subtract 1
const day = Number.parseInt(match[3], 10);
if (month === 2) {
if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
return day <= 29;
}
return day <= 28;
}
if (MONTHS_30.has(month)) {
return day <= 30;
}
if (MONTHS_31.has(month)) {
return day <= 31;
}
return false;
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`${datetimeValidationSuite.name!}: ${e.target}`);
});
export default {
suites: [datetimeValidationSuite],
};

View file

@ -1,80 +0,0 @@
import Benchmark from "benchmark";
import { z } from "zod/v3";
const doubleSuite = new Benchmark.Suite("z.discriminatedUnion: double");
const manySuite = new Benchmark.Suite("z.discriminatedUnion: many");
const aSchema = z.object({
type: z.literal("a"),
});
const objA = {
type: "a",
};
const bSchema = z.object({
type: z.literal("b"),
});
const objB = {
type: "b",
};
const cSchema = z.object({
type: z.literal("c"),
});
const objC = {
type: "c",
};
const dSchema = z.object({
type: z.literal("d"),
});
const double = z.discriminatedUnion("type", [aSchema, bSchema]);
const many = z.discriminatedUnion("type", [aSchema, bSchema, cSchema, dSchema]);
doubleSuite
.add("valid: a", () => {
double.parse(objA);
})
.add("valid: b", () => {
double.parse(objB);
})
.add("invalid: null", () => {
try {
double.parse(null);
} catch (_err) {}
})
.add("invalid: wrong shape", () => {
try {
double.parse(objC);
} catch (_err) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`${(doubleSuite as any).name}: ${e.target}`);
});
manySuite
.add("valid: a", () => {
many.parse(objA);
})
.add("valid: c", () => {
many.parse(objC);
})
.add("invalid: null", () => {
try {
many.parse(null);
} catch (_err) {}
})
.add("invalid: wrong shape", () => {
try {
many.parse({ type: "unknown" });
} catch (_err) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`${(manySuite as any).name}: ${e.target}`);
});
export default {
suites: [doubleSuite, manySuite],
};

View file

@ -1,59 +0,0 @@
import type Benchmark from "benchmark";
import datetimeBenchmarks from "./datetime.js";
import discriminatedUnionBenchmarks from "./discriminatedUnion.js";
import ipv4Benchmarks from "./ipv4.js";
import objectBenchmarks from "./object.js";
import primitiveBenchmarks from "./primitives.js";
import realworld from "./realworld.js";
import stringBenchmarks from "./string.js";
import unionBenchmarks from "./union.js";
const argv = process.argv.slice(2);
let suites: Benchmark.Suite[] = [];
if (!argv.length) {
suites = [
...realworld.suites,
...primitiveBenchmarks.suites,
...stringBenchmarks.suites,
...objectBenchmarks.suites,
...unionBenchmarks.suites,
...discriminatedUnionBenchmarks.suites,
];
} else {
if (argv.includes("--realworld")) {
suites.push(...realworld.suites);
}
if (argv.includes("--primitives")) {
suites.push(...primitiveBenchmarks.suites);
}
if (argv.includes("--string")) {
suites.push(...stringBenchmarks.suites);
}
if (argv.includes("--object")) {
suites.push(...objectBenchmarks.suites);
}
if (argv.includes("--union")) {
suites.push(...unionBenchmarks.suites);
}
if (argv.includes("--discriminatedUnion")) {
suites.push(...datetimeBenchmarks.suites);
}
if (argv.includes("--datetime")) {
suites.push(...datetimeBenchmarks.suites);
}
if (argv.includes("--ipv4")) {
suites.push(...ipv4Benchmarks.suites);
}
}
for (const suite of suites) {
suite.run({});
}
// exit on Ctrl-C
process.on("SIGINT", function () {
console.log("Exiting...");
process.exit();
});

View file

@ -1,57 +0,0 @@
import Benchmark from "benchmark";
const suite = new Benchmark.Suite("ipv4");
const DATA = "127.0.0.1";
const ipv4RegexA =
/^(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))$/;
const ipv4RegexB =
/^(?:(?:(?=(25[0-5]))\1|(?=(2[0-4][0-9]))\2|(?=(1[0-9]{2}))\3|(?=([0-9]{1,2}))\4)\.){3}(?:(?=(25[0-5]))\5|(?=(2[0-4][0-9]))\6|(?=(1[0-9]{2}))\7|(?=([0-9]{1,2}))\8)$/;
const ipv4RegexC = /^(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)$/;
const ipv4RegexD = /^(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/;
const ipv4RegexE = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.){3}(25[0-5]|(2[0-4]|1\d|[1-9]|)\d)$/;
const ipv4RegexF = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/;
const ipv4RegexG = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)(\.(?!$)|$)){4}$/;
const ipv4RegexH = /^((25[0-5]|(2[0-4]|1[0-9]|[1-9]|)[0-9])(\.(?!$)|$)){4}$/;
const ipv4RegexI =
/^(?:(?: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])$/;
suite
.add("A", () => {
return ipv4RegexA.test(DATA);
})
.add("B", () => {
return ipv4RegexB.test(DATA);
})
.add("C", () => {
return ipv4RegexC.test(DATA);
})
.add("D", () => {
return ipv4RegexD.test(DATA);
})
.add("E", () => {
return ipv4RegexE.test(DATA);
})
.add("F", () => {
return ipv4RegexF.test(DATA);
})
.add("G", () => {
return ipv4RegexG.test(DATA);
})
.add("H", () => {
return ipv4RegexH.test(DATA);
})
.add("I", () => {
return ipv4RegexI.test(DATA);
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`${suite.name!}: ${e.target}`);
});
export default {
suites: [suite],
};
if (require.main === module) {
suite.run();
}

View file

@ -1,69 +0,0 @@
import Benchmark from "benchmark";
import { z } from "zod/v3";
const emptySuite = new Benchmark.Suite("z.object: empty");
const shortSuite = new Benchmark.Suite("z.object: short");
const longSuite = new Benchmark.Suite("z.object: long");
const empty = z.object({});
const short = z.object({
string: z.string(),
});
const long = z.object({
string: z.string(),
number: z.number(),
boolean: z.boolean(),
});
emptySuite
.add("valid", () => {
empty.parse({});
})
.add("valid: extra keys", () => {
empty.parse({ string: "string" });
})
.add("invalid: null", () => {
try {
empty.parse(null);
} catch (_err) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`${(emptySuite as any).name}: ${e.target}`);
});
shortSuite
.add("valid", () => {
short.parse({ string: "string" });
})
.add("valid: extra keys", () => {
short.parse({ string: "string", number: 42 });
})
.add("invalid: null", () => {
try {
short.parse(null);
} catch (_err) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`${(shortSuite as any).name}: ${e.target}`);
});
longSuite
.add("valid", () => {
long.parse({ string: "string", number: 42, boolean: true });
})
.add("valid: extra keys", () => {
long.parse({ string: "string", number: 42, boolean: true, list: [] });
})
.add("invalid: null", () => {
try {
long.parse(null);
} catch (_err) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`${(longSuite as any).name}: ${e.target}`);
});
export default {
suites: [emptySuite, shortSuite, longSuite],
};

View file

@ -1,162 +0,0 @@
import Benchmark from "benchmark";
import { z } from "zod/v3";
import { Mocker } from "../tests/Mocker.js";
const val = new Mocker();
const enumSuite = new Benchmark.Suite("z.enum");
const enumSchema = z.enum(["a", "b", "c"]);
enumSuite
.add("valid", () => {
enumSchema.parse("a");
})
.add("invalid", () => {
try {
enumSchema.parse("x");
} catch (_e: any) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`z.enum: ${e.target}`);
});
const longEnumSuite = new Benchmark.Suite("long z.enum");
const longEnumSchema = z.enum([
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"ten",
"eleven",
"twelve",
"thirteen",
"fourteen",
"fifteen",
"sixteen",
"seventeen",
]);
longEnumSuite
.add("valid", () => {
longEnumSchema.parse("five");
})
.add("invalid", () => {
try {
longEnumSchema.parse("invalid");
} catch (_e: any) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`long z.enum: ${e.target}`);
});
const undefinedSuite = new Benchmark.Suite("z.undefined");
const undefinedSchema = z.undefined();
undefinedSuite
.add("valid", () => {
undefinedSchema.parse(undefined);
})
.add("invalid", () => {
try {
undefinedSchema.parse(1);
} catch (_e: any) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`z.undefined: ${e.target}`);
});
const literalSuite = new Benchmark.Suite("z.literal");
const short = "short";
const bad = "bad";
const literalSchema = z.literal("short");
literalSuite
.add("valid", () => {
literalSchema.parse(short);
})
.add("invalid", () => {
try {
literalSchema.parse(bad);
} catch (_e: any) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`z.literal: ${e.target}`);
});
const numberSuite = new Benchmark.Suite("z.number");
const numberSchema = z.number().int();
numberSuite
.add("valid", () => {
numberSchema.parse(1);
})
.add("invalid type", () => {
try {
numberSchema.parse("bad");
} catch (_e: any) {}
})
.add("invalid number", () => {
try {
numberSchema.parse(0.5);
} catch (_e: any) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`z.number: ${e.target}`);
});
const dateSuite = new Benchmark.Suite("z.date");
const plainDate = z.date();
const minMaxDate = z.date().min(new Date("2021-01-01")).max(new Date("2030-01-01"));
dateSuite
.add("valid", () => {
plainDate.parse(new Date());
})
.add("invalid", () => {
try {
plainDate.parse(1);
} catch (_e: any) {}
})
.add("valid min and max", () => {
minMaxDate.parse(new Date("2023-01-01"));
})
.add("invalid min", () => {
try {
minMaxDate.parse(new Date("2019-01-01"));
} catch (_e: any) {}
})
.add("invalid max", () => {
try {
minMaxDate.parse(new Date("2031-01-01"));
} catch (_e: any) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`z.date: ${e.target}`);
});
const symbolSuite = new Benchmark.Suite("z.symbol");
const symbolSchema = z.symbol();
symbolSuite
.add("valid", () => {
symbolSchema.parse(val.symbol);
})
.add("invalid", () => {
try {
symbolSchema.parse(1);
} catch (_e: any) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`z.symbol: ${e.target}`);
});
export default {
suites: [enumSuite, longEnumSuite, undefinedSuite, literalSuite, numberSuite, dateSuite, symbolSuite],
};

View file

@ -1,63 +0,0 @@
import Benchmark from "benchmark";
import { z } from "zod/v3";
const shortSuite = new Benchmark.Suite("realworld");
const People = z.array(
z.object({
type: z.literal("person"),
hair: z.enum(["blue", "brown"]),
active: z.boolean(),
name: z.string(),
age: z.number().int(),
hobbies: z.array(z.string()),
address: z.object({
street: z.string(),
zip: z.string(),
country: z.string(),
}),
})
);
let i = 0;
function num() {
return ++i;
}
function str() {
return (++i % 100).toString(16);
}
function array<T>(fn: () => T): T[] {
return Array.from({ length: ++i % 10 }, () => fn());
}
const people = Array.from({ length: 100 }, () => {
return {
type: "person",
hair: i % 2 ? "blue" : "brown",
active: !!(i % 2),
name: str(),
age: num(),
hobbies: array(str),
address: {
street: str(),
zip: str(),
country: str(),
},
};
});
shortSuite
.add("valid", () => {
People.parse(people);
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`${(shortSuite as any).name}: ${e.target}`);
});
export default {
suites: [shortSuite],
};

View file

@ -1,55 +0,0 @@
import Benchmark from "benchmark";
import { z } from "zod/v3";
const SUITE_NAME = "z.string";
const suite = new Benchmark.Suite(SUITE_NAME);
const empty = "";
const short = "short";
const long = "long".repeat(256);
const manual = (str: unknown) => {
if (typeof str !== "string") {
throw new Error("Not a string");
}
return str;
};
const stringSchema = z.string();
const optionalStringSchema = z.string().optional();
const optionalNullableStringSchema = z.string().optional().nullable();
suite
.add("empty string", () => {
stringSchema.parse(empty);
})
.add("short string", () => {
stringSchema.parse(short);
})
.add("long string", () => {
stringSchema.parse(long);
})
.add("optional string", () => {
optionalStringSchema.parse(long);
})
.add("nullable string", () => {
optionalNullableStringSchema.parse(long);
})
.add("nullable (null) string", () => {
optionalNullableStringSchema.parse(null);
})
.add("invalid: null", () => {
try {
stringSchema.parse(null);
} catch (_err) {}
})
.add("manual parser: long", () => {
manual(long);
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`${SUITE_NAME}: ${e.target}`);
});
export default {
suites: [suite],
};

View file

@ -1,80 +0,0 @@
import Benchmark from "benchmark";
import { z } from "zod/v3";
const doubleSuite = new Benchmark.Suite("z.union: double");
const manySuite = new Benchmark.Suite("z.union: many");
const aSchema = z.object({
type: z.literal("a"),
});
const objA = {
type: "a",
};
const bSchema = z.object({
type: z.literal("b"),
});
const objB = {
type: "b",
};
const cSchema = z.object({
type: z.literal("c"),
});
const objC = {
type: "c",
};
const dSchema = z.object({
type: z.literal("d"),
});
const double = z.union([aSchema, bSchema]);
const many = z.union([aSchema, bSchema, cSchema, dSchema]);
doubleSuite
.add("valid: a", () => {
double.parse(objA);
})
.add("valid: b", () => {
double.parse(objB);
})
.add("invalid: null", () => {
try {
double.parse(null);
} catch (_err) {}
})
.add("invalid: wrong shape", () => {
try {
double.parse(objC);
} catch (_err) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`${(doubleSuite as any).name}: ${e.target}`);
});
manySuite
.add("valid: a", () => {
many.parse(objA);
})
.add("valid: c", () => {
many.parse(objC);
})
.add("invalid: null", () => {
try {
many.parse(null);
} catch (_err) {}
})
.add("invalid: wrong shape", () => {
try {
many.parse({ type: "unknown" });
} catch (_err) {}
})
.on("cycle", (e: Benchmark.Event) => {
console.log(`${(manySuite as any).name}: ${e.target}`);
});
export default {
suites: [doubleSuite, manySuite],
};

13
node_modules/zod/src/v3/errors.ts generated vendored
View file

@ -1,13 +0,0 @@
import type { ZodErrorMap } from "./ZodError.js";
import defaultErrorMap from "./locales/en.js";
let overrideErrorMap = defaultErrorMap;
export { defaultErrorMap };
export function setErrorMap(map: ZodErrorMap) {
overrideErrorMap = map;
}
export function getErrorMap() {
return overrideErrorMap;
}

View file

@ -1,6 +0,0 @@
export * from "./errors.js";
export * from "./helpers/parseUtil.js";
export * from "./helpers/typeAliases.js";
export * from "./helpers/util.js";
export * from "./types.js";
export * from "./ZodError.js";

View file

@ -1,17 +0,0 @@
export namespace enumUtil {
type UnionToIntersectionFn<T> = (T extends unknown ? (k: () => T) => void : never) extends (
k: infer Intersection
) => void
? Intersection
: never;
type GetUnionLast<T> = UnionToIntersectionFn<T> extends () => infer Last ? Last : never;
type UnionToTuple<T, Tuple extends unknown[] = []> = [T] extends [never]
? Tuple
: UnionToTuple<Exclude<T, GetUnionLast<T>>, [GetUnionLast<T>, ...Tuple]>;
type CastToStringTuple<T> = T extends [string, ...string[]] ? T : never;
export type UnionToTupleString<T> = CastToStringTuple<UnionToTuple<T>>;
}

View file

@ -1,8 +0,0 @@
export namespace errorUtil {
export type ErrMessage = string | { message?: string | undefined };
export const errToObj = (message?: ErrMessage): { message?: string | undefined } =>
typeof message === "string" ? { message } : message || {};
// biome-ignore lint:
export const toString = (message?: ErrMessage): string | undefined =>
typeof message === "string" ? message : message?.message;
}

View file

@ -1,176 +0,0 @@
import type { IssueData, ZodErrorMap, ZodIssue } from "../ZodError.js";
import { getErrorMap } from "../errors.js";
import defaultErrorMap from "../locales/en.js";
import type { ZodParsedType } from "./util.js";
export const makeIssue = (params: {
data: any;
path: (string | number)[];
errorMaps: ZodErrorMap[];
issueData: IssueData;
}): ZodIssue => {
const { data, path, errorMaps, issueData } = params;
const fullPath = [...path, ...(issueData.path || [])];
const fullIssue = {
...issueData,
path: fullPath,
};
if (issueData.message !== undefined) {
return {
...issueData,
path: fullPath,
message: issueData.message,
};
}
let errorMessage = "";
const maps = errorMaps
.filter((m) => !!m)
.slice()
.reverse();
for (const map of maps) {
errorMessage = map(fullIssue, { data, defaultError: errorMessage }).message;
}
return {
...issueData,
path: fullPath,
message: errorMessage,
};
};
export type ParseParams = {
path: (string | number)[];
errorMap: ZodErrorMap;
async: boolean;
};
export type ParsePathComponent = string | number;
export type ParsePath = ParsePathComponent[];
export const EMPTY_PATH: ParsePath = [];
export interface ParseContext {
readonly common: {
readonly issues: ZodIssue[];
readonly contextualErrorMap?: ZodErrorMap | undefined;
readonly async: boolean;
};
readonly path: ParsePath;
readonly schemaErrorMap?: ZodErrorMap | undefined;
readonly parent: ParseContext | null;
readonly data: any;
readonly parsedType: ZodParsedType;
}
export type ParseInput = {
data: any;
path: (string | number)[];
parent: ParseContext;
};
export function addIssueToContext(ctx: ParseContext, issueData: IssueData): void {
const overrideMap = getErrorMap();
const issue = makeIssue({
issueData: issueData,
data: ctx.data,
path: ctx.path,
errorMaps: [
ctx.common.contextualErrorMap, // contextual error map is first priority
ctx.schemaErrorMap, // then schema-bound map if available
overrideMap, // then global override map
overrideMap === defaultErrorMap ? undefined : defaultErrorMap, // then global default map
].filter((x) => !!x),
});
ctx.common.issues.push(issue);
}
export type ObjectPair = {
key: SyncParseReturnType<any>;
value: SyncParseReturnType<any>;
};
export class ParseStatus {
value: "aborted" | "dirty" | "valid" = "valid";
dirty(): void {
if (this.value === "valid") this.value = "dirty";
}
abort(): void {
if (this.value !== "aborted") this.value = "aborted";
}
static mergeArray(status: ParseStatus, results: SyncParseReturnType<any>[]): SyncParseReturnType {
const arrayValue: any[] = [];
for (const s of results) {
if (s.status === "aborted") return INVALID;
if (s.status === "dirty") status.dirty();
arrayValue.push(s.value);
}
return { status: status.value, value: arrayValue };
}
static async mergeObjectAsync(
status: ParseStatus,
pairs: { key: ParseReturnType<any>; value: ParseReturnType<any> }[]
): Promise<SyncParseReturnType<any>> {
const syncPairs: ObjectPair[] = [];
for (const pair of pairs) {
const key = await pair.key;
const value = await pair.value;
syncPairs.push({
key,
value,
});
}
return ParseStatus.mergeObjectSync(status, syncPairs);
}
static mergeObjectSync(
status: ParseStatus,
pairs: {
key: SyncParseReturnType<any>;
value: SyncParseReturnType<any>;
alwaysSet?: boolean;
}[]
): SyncParseReturnType {
const finalObject: any = {};
for (const pair of pairs) {
const { key, value } = pair;
if (key.status === "aborted") return INVALID;
if (value.status === "aborted") return INVALID;
if (key.status === "dirty") status.dirty();
if (value.status === "dirty") status.dirty();
if (key.value !== "__proto__" && (typeof value.value !== "undefined" || pair.alwaysSet)) {
finalObject[key.value] = value.value;
}
}
return { status: status.value, value: finalObject };
}
}
export interface ParseResult {
status: "aborted" | "dirty" | "valid";
data: any;
}
export type INVALID = { status: "aborted" };
export const INVALID: INVALID = Object.freeze({
status: "aborted",
});
export type DIRTY<T> = { status: "dirty"; value: T };
export const DIRTY = <T>(value: T): DIRTY<T> => ({ status: "dirty", value });
export type OK<T> = { status: "valid"; value: T };
export const OK = <T>(value: T): OK<T> => ({ status: "valid", value });
export type SyncParseReturnType<T = any> = OK<T> | DIRTY<T> | INVALID;
export type AsyncParseReturnType<T> = Promise<SyncParseReturnType<T>>;
export type ParseReturnType<T> = SyncParseReturnType<T> | AsyncParseReturnType<T>;
export const isAborted = (x: ParseReturnType<any>): x is INVALID => (x as any).status === "aborted";
export const isDirty = <T>(x: ParseReturnType<T>): x is OK<T> | DIRTY<T> => (x as any).status === "dirty";
export const isValid = <T>(x: ParseReturnType<T>): x is OK<T> => (x as any).status === "valid";
export const isAsync = <T>(x: ParseReturnType<T>): x is AsyncParseReturnType<T> =>
typeof Promise !== "undefined" && x instanceof Promise;

View file

@ -1,34 +0,0 @@
import type {
ZodArray,
ZodNullable,
ZodObject,
ZodOptional,
ZodRawShape,
ZodTuple,
ZodTupleItems,
ZodTypeAny,
} from "../types.js";
export namespace partialUtil {
export type DeepPartial<T extends ZodTypeAny> = T extends ZodObject<ZodRawShape>
? ZodObject<
{ [k in keyof T["shape"]]: ZodOptional<DeepPartial<T["shape"][k]>> },
T["_def"]["unknownKeys"],
T["_def"]["catchall"]
>
: T extends ZodArray<infer Type, infer Card>
? ZodArray<DeepPartial<Type>, Card>
: T extends ZodOptional<infer Type>
? ZodOptional<DeepPartial<Type>>
: T extends ZodNullable<infer Type>
? ZodNullable<DeepPartial<Type>>
: T extends ZodTuple<infer Items>
? {
[k in keyof Items]: Items[k] extends ZodTypeAny ? DeepPartial<Items[k]> : never;
} extends infer PI
? PI extends ZodTupleItems
? ZodTuple<PI>
: never
: never
: T;
}

View file

@ -1,2 +0,0 @@
export type Primitive = string | number | symbol | bigint | boolean | null | undefined;
export type Scalars = Primitive | Primitive[];

View file

@ -1,224 +0,0 @@
export namespace util {
type AssertEqual<T, U> = (<V>() => V extends T ? 1 : 2) extends <V>() => V extends U ? 1 : 2 ? true : false;
export type isAny<T> = 0 extends 1 & T ? true : false;
export const assertEqual = <A, B>(_: AssertEqual<A, B>): void => {};
export function assertIs<T>(_arg: T): void {}
export function assertNever(_x: never): never {
throw new Error();
}
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
export type OmitKeys<T, K extends string> = Pick<T, Exclude<keyof T, K>>;
export type MakePartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
export type Exactly<T, X> = T & Record<Exclude<keyof X, keyof T>, never>;
export type InexactPartial<T> = { [k in keyof T]?: T[k] | undefined };
export const arrayToEnum = <T extends string, U extends [T, ...T[]]>(items: U): { [k in U[number]]: k } => {
const obj: any = {};
for (const item of items) {
obj[item] = item;
}
return obj;
};
export const getValidEnumValues = (obj: any): any[] => {
const validKeys = objectKeys(obj).filter((k: any) => typeof obj[obj[k]] !== "number");
const filtered: any = {};
for (const k of validKeys) {
filtered[k] = obj[k];
}
return objectValues(filtered);
};
export const objectValues = (obj: any): any[] => {
return objectKeys(obj).map(function (e) {
return obj[e];
});
};
export const objectKeys: ObjectConstructor["keys"] =
typeof Object.keys === "function" // eslint-disable-line ban/ban
? (obj: any) => Object.keys(obj) // eslint-disable-line ban/ban
: (object: any) => {
const keys = [];
for (const key in object) {
if (Object.prototype.hasOwnProperty.call(object, key)) {
keys.push(key);
}
}
return keys;
};
export const find = <T>(arr: T[], checker: (arg: T) => any): T | undefined => {
for (const item of arr) {
if (checker(item)) return item;
}
return undefined;
};
export type identity<T> = objectUtil.identity<T>;
export type flatten<T> = objectUtil.flatten<T>;
export type noUndefined<T> = T extends undefined ? never : T;
export const isInteger: NumberConstructor["isInteger"] =
typeof Number.isInteger === "function"
? (val) => Number.isInteger(val) // eslint-disable-line ban/ban
: (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val;
export function joinValues<T extends any[]>(array: T, separator = " | "): string {
return array.map((val) => (typeof val === "string" ? `'${val}'` : val)).join(separator);
}
export const jsonStringifyReplacer = (_: string, value: any): any => {
if (typeof value === "bigint") {
return value.toString();
}
return value;
};
}
export namespace objectUtil {
export type MergeShapes<U, V> =
// fast path when there is no keys overlap
keyof U & keyof V extends never
? U & V
: {
[k in Exclude<keyof U, keyof V>]: U[k];
} & V;
type optionalKeys<T extends object> = {
[k in keyof T]: undefined extends T[k] ? k : never;
}[keyof T];
type requiredKeys<T extends object> = {
[k in keyof T]: undefined extends T[k] ? never : k;
}[keyof T];
export type addQuestionMarks<T extends object, _O = any> = {
[K in requiredKeys<T>]: T[K];
} & {
[K in optionalKeys<T>]?: T[K];
} & { [k in keyof T]?: unknown };
export type identity<T> = T;
export type flatten<T> = identity<{ [k in keyof T]: T[k] }>;
export type noNeverKeys<T> = {
[k in keyof T]: [T[k]] extends [never] ? never : k;
}[keyof T];
export type noNever<T> = identity<{
[k in noNeverKeys<T>]: k extends keyof T ? T[k] : never;
}>;
export const mergeShapes = <U, T>(first: U, second: T): T & U => {
return {
...first,
...second, // second overwrites first
};
};
export type extendShape<A extends object, B extends object> = keyof A & keyof B extends never // fast path when there is no keys overlap
? A & B
: {
[K in keyof A as K extends keyof B ? never : K]: A[K];
} & {
[K in keyof B]: B[K];
};
}
export const ZodParsedType: {
string: "string";
nan: "nan";
number: "number";
integer: "integer";
float: "float";
boolean: "boolean";
date: "date";
bigint: "bigint";
symbol: "symbol";
function: "function";
undefined: "undefined";
null: "null";
array: "array";
object: "object";
unknown: "unknown";
promise: "promise";
void: "void";
never: "never";
map: "map";
set: "set";
} = util.arrayToEnum([
"string",
"nan",
"number",
"integer",
"float",
"boolean",
"date",
"bigint",
"symbol",
"function",
"undefined",
"null",
"array",
"object",
"unknown",
"promise",
"void",
"never",
"map",
"set",
]);
export type ZodParsedType = keyof typeof ZodParsedType;
export const getParsedType = (data: any): ZodParsedType => {
const t = typeof data;
switch (t) {
case "undefined":
return ZodParsedType.undefined;
case "string":
return ZodParsedType.string;
case "number":
return Number.isNaN(data) ? ZodParsedType.nan : ZodParsedType.number;
case "boolean":
return ZodParsedType.boolean;
case "function":
return ZodParsedType.function;
case "bigint":
return ZodParsedType.bigint;
case "symbol":
return ZodParsedType.symbol;
case "object":
if (Array.isArray(data)) {
return ZodParsedType.array;
}
if (data === null) {
return ZodParsedType.null;
}
if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") {
return ZodParsedType.promise;
}
if (typeof Map !== "undefined" && data instanceof Map) {
return ZodParsedType.map;
}
if (typeof Set !== "undefined" && data instanceof Set) {
return ZodParsedType.set;
}
if (typeof Date !== "undefined" && data instanceof Date) {
return ZodParsedType.date;
}
return ZodParsedType.object;
default:
return ZodParsedType.unknown;
}
};

4
node_modules/zod/src/v3/index.ts generated vendored
View file

@ -1,4 +0,0 @@
import * as z from "./external.js";
export * from "./external.js";
export { z };
export default z;

124
node_modules/zod/src/v3/locales/en.ts generated vendored
View file

@ -1,124 +0,0 @@
import { type ZodErrorMap, ZodIssueCode } from "../ZodError.js";
import { util, ZodParsedType } from "../helpers/util.js";
const errorMap: ZodErrorMap = (issue, _ctx) => {
let message: string;
switch (issue.code) {
case ZodIssueCode.invalid_type:
if (issue.received === ZodParsedType.undefined) {
message = "Required";
} else {
message = `Expected ${issue.expected}, received ${issue.received}`;
}
break;
case ZodIssueCode.invalid_literal:
message = `Invalid literal value, expected ${JSON.stringify(issue.expected, util.jsonStringifyReplacer)}`;
break;
case ZodIssueCode.unrecognized_keys:
message = `Unrecognized key(s) in object: ${util.joinValues(issue.keys, ", ")}`;
break;
case ZodIssueCode.invalid_union:
message = `Invalid input`;
break;
case ZodIssueCode.invalid_union_discriminator:
message = `Invalid discriminator value. Expected ${util.joinValues(issue.options)}`;
break;
case ZodIssueCode.invalid_enum_value:
message = `Invalid enum value. Expected ${util.joinValues(issue.options)}, received '${issue.received}'`;
break;
case ZodIssueCode.invalid_arguments:
message = `Invalid function arguments`;
break;
case ZodIssueCode.invalid_return_type:
message = `Invalid function return type`;
break;
case ZodIssueCode.invalid_date:
message = `Invalid date`;
break;
case ZodIssueCode.invalid_string:
if (typeof issue.validation === "object") {
if ("includes" in issue.validation) {
message = `Invalid input: must include "${issue.validation.includes}"`;
if (typeof issue.validation.position === "number") {
message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`;
}
} else if ("startsWith" in issue.validation) {
message = `Invalid input: must start with "${issue.validation.startsWith}"`;
} else if ("endsWith" in issue.validation) {
message = `Invalid input: must end with "${issue.validation.endsWith}"`;
} else {
util.assertNever(issue.validation);
}
} else if (issue.validation !== "regex") {
message = `Invalid ${issue.validation}`;
} else {
message = "Invalid";
}
break;
case ZodIssueCode.too_small:
if (issue.type === "array")
message = `Array must contain ${
issue.exact ? "exactly" : issue.inclusive ? `at least` : `more than`
} ${issue.minimum} element(s)`;
else if (issue.type === "string")
message = `String must contain ${
issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`
} ${issue.minimum} character(s)`;
else if (issue.type === "number")
message = `Number must be ${
issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `
}${issue.minimum}`;
else if (issue.type === "bigint")
message = `Number must be ${
issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `
}${issue.minimum}`;
else if (issue.type === "date")
message = `Date must be ${
issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `
}${new Date(Number(issue.minimum))}`;
else message = "Invalid input";
break;
case ZodIssueCode.too_big:
if (issue.type === "array")
message = `Array must contain ${
issue.exact ? `exactly` : issue.inclusive ? `at most` : `less than`
} ${issue.maximum} element(s)`;
else if (issue.type === "string")
message = `String must contain ${
issue.exact ? `exactly` : issue.inclusive ? `at most` : `under`
} ${issue.maximum} character(s)`;
else if (issue.type === "number")
message = `Number must be ${
issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`
} ${issue.maximum}`;
else if (issue.type === "bigint")
message = `BigInt must be ${
issue.exact ? `exactly` : issue.inclusive ? `less than or equal to` : `less than`
} ${issue.maximum}`;
else if (issue.type === "date")
message = `Date must be ${
issue.exact ? `exactly` : issue.inclusive ? `smaller than or equal to` : `smaller than`
} ${new Date(Number(issue.maximum))}`;
else message = "Invalid input";
break;
case ZodIssueCode.custom:
message = `Invalid input`;
break;
case ZodIssueCode.invalid_intersection_types:
message = `Intersection results could not be merged`;
break;
case ZodIssueCode.not_multiple_of:
message = `Number must be a multiple of ${issue.multipleOf}`;
break;
case ZodIssueCode.not_finite:
message = "Number must be finite";
break;
default:
message = _ctx.defaultError;
util.assertNever(issue);
}
return { message };
};
export default errorMap;

View file

@ -1,113 +0,0 @@
/**
* The Standard Schema interface.
*/
export type StandardSchemaV1<Input = unknown, Output = Input> = {
/**
* The Standard Schema properties.
*/
readonly "~standard": StandardSchemaV1.Props<Input, Output>;
};
export declare namespace StandardSchemaV1 {
/**
* The Standard Schema properties interface.
*/
export interface Props<Input = unknown, Output = Input> {
/**
* The version number of the standard.
*/
readonly version: 1;
/**
* The vendor name of the schema library.
*/
readonly vendor: string;
/**
* Validates unknown input values.
*/
readonly validate: (value: unknown) => Result<Output> | Promise<Result<Output>>;
/**
* Inferred types associated with the schema.
*/
readonly types?: Types<Input, Output> | undefined;
}
/**
* The result interface of the validate function.
*/
export type Result<Output> = SuccessResult<Output> | FailureResult;
/**
* The result interface if validation succeeds.
*/
export interface SuccessResult<Output> {
/**
* The typed output value.
*/
readonly value: Output;
/**
* The non-existent issues.
*/
readonly issues?: undefined;
}
/**
* The result interface if validation fails.
*/
export interface FailureResult {
/**
* The issues of failed validation.
*/
readonly issues: ReadonlyArray<Issue>;
}
/**
* The issue interface of the failure output.
*/
export interface Issue {
/**
* The error message of the issue.
*/
readonly message: string;
/**
* The path of the issue, if any.
*/
readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
}
/**
* The path segment interface of the issue.
*/
export interface PathSegment {
/**
* The key representing a path segment.
*/
readonly key: PropertyKey;
}
/**
* The Standard Schema types interface.
*/
export interface Types<Input = unknown, Output = Input> {
/**
* The input type of the schema.
*/
readonly input: Input;
/**
* The output type of the schema.
*/
readonly output: Output;
}
/**
* Infers the input type of a Standard Schema.
*/
export type InferInput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["input"];
/**
* Infers the output type of a Standard Schema.
*/
export type InferOutput<Schema extends StandardSchemaV1> = NonNullable<Schema["~standard"]["types"]>["output"];
// biome-ignore lint/complexity/noUselessEmptyExport: needed for granular visibility control of TS namespace
export {};
}

View file

@ -1,54 +0,0 @@
function getRandomInt(max: number) {
return Math.floor(Math.random() * Math.floor(max));
}
const testSymbol = Symbol("test");
export class Mocker {
pick = (...args: any[]): any => {
return args[getRandomInt(args.length)];
};
get string(): string {
return Math.random().toString(36).substring(7);
}
get number(): number {
return Math.random() * 100;
}
get bigint(): bigint {
return BigInt(Math.floor(Math.random() * 10000));
}
get boolean(): boolean {
return Math.random() < 0.5;
}
get date(): Date {
return new Date(Math.floor(Date.now() * Math.random()));
}
get symbol(): symbol {
return testSymbol;
}
get null(): null {
return null;
}
get undefined(): undefined {
return undefined;
}
get stringOptional(): string | undefined {
return this.pick(this.string, this.undefined);
}
get stringNullable(): string | null {
return this.pick(this.string, this.null);
}
get numberOptional(): number | undefined {
return this.pick(this.number, this.undefined);
}
get numberNullable(): number | null {
return this.pick(this.number, this.null);
}
get booleanOptional(): boolean | undefined {
return this.pick(this.boolean, this.undefined);
}
get booleanNullable(): boolean | null {
return this.pick(this.boolean, this.null);
}
}

View file

@ -1,157 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
const Test = z.object({
f1: z.number(),
f2: z.string().optional(),
f3: z.string().nullable(),
f4: z.array(z.object({ t: z.union([z.string(), z.boolean()]) })),
});
type TestFlattenedErrors = z.inferFlattenedErrors<typeof Test, { message: string; code: number }>;
type TestFormErrors = z.inferFlattenedErrors<typeof Test>;
test("default flattened errors type inference", () => {
type TestTypeErrors = {
formErrors: string[];
fieldErrors: { [P in keyof z.TypeOf<typeof Test>]?: string[] | undefined };
};
util.assertEqual<z.inferFlattenedErrors<typeof Test>, TestTypeErrors>(true);
util.assertEqual<z.inferFlattenedErrors<typeof Test, { message: string }>, TestTypeErrors>(false);
});
test("custom flattened errors type inference", () => {
type ErrorType = { message: string; code: number };
type TestTypeErrors = {
formErrors: ErrorType[];
fieldErrors: {
[P in keyof z.TypeOf<typeof Test>]?: ErrorType[] | undefined;
};
};
util.assertEqual<z.inferFlattenedErrors<typeof Test>, TestTypeErrors>(false);
util.assertEqual<z.inferFlattenedErrors<typeof Test, { message: string; code: number }>, TestTypeErrors>(true);
util.assertEqual<z.inferFlattenedErrors<typeof Test, { message: string }>, TestTypeErrors>(false);
});
test("form errors type inference", () => {
type TestTypeErrors = {
formErrors: string[];
fieldErrors: { [P in keyof z.TypeOf<typeof Test>]?: string[] | undefined };
};
util.assertEqual<z.inferFlattenedErrors<typeof Test>, TestTypeErrors>(true);
});
test(".flatten() type assertion", () => {
const parsed = Test.safeParse({}) as z.SafeParseError<void>;
const validFlattenedErrors: TestFlattenedErrors = parsed.error.flatten(() => ({ message: "", code: 0 }));
// @ts-expect-error should fail assertion between `TestFlattenedErrors` and unmapped `flatten()`.
const invalidFlattenedErrors: TestFlattenedErrors = parsed.error.flatten();
const validFormErrors: TestFormErrors = parsed.error.flatten();
// @ts-expect-error should fail assertion between `TestFormErrors` and mapped `flatten()`.
const invalidFormErrors: TestFormErrors = parsed.error.flatten(() => ({
message: "string",
code: 0,
}));
[validFlattenedErrors, invalidFlattenedErrors, validFormErrors, invalidFormErrors];
});
test(".formErrors type assertion", () => {
const parsed = Test.safeParse({}) as z.SafeParseError<void>;
const validFormErrors: TestFormErrors = parsed.error.formErrors;
// @ts-expect-error should fail assertion between `TestFlattenedErrors` and `.formErrors`.
const invalidFlattenedErrors: TestFlattenedErrors = parsed.error.formErrors;
[validFormErrors, invalidFlattenedErrors];
});
test("all errors", () => {
const propertySchema = z.string();
const schema = z
.object({
a: propertySchema,
b: propertySchema,
})
.refine(
(val) => {
return val.a === val.b;
},
{ message: "Must be equal" }
);
try {
schema.parse({
a: "asdf",
b: "qwer",
});
} catch (error) {
if (error instanceof z.ZodError) {
expect(error.flatten()).toEqual({
formErrors: ["Must be equal"],
fieldErrors: {},
});
}
}
try {
schema.parse({
a: null,
b: null,
});
} catch (_error) {
const error = _error as z.ZodError;
expect(error.flatten()).toEqual({
formErrors: [],
fieldErrors: {
a: ["Expected string, received null"],
b: ["Expected string, received null"],
},
});
expect(error.flatten((iss) => iss.message.toUpperCase())).toEqual({
formErrors: [],
fieldErrors: {
a: ["EXPECTED STRING, RECEIVED NULL"],
b: ["EXPECTED STRING, RECEIVED NULL"],
},
});
// Test identity
expect(error.flatten((i: z.ZodIssue) => i)).toEqual({
formErrors: [],
fieldErrors: {
a: [
{
code: "invalid_type",
expected: "string",
message: "Expected string, received null",
path: ["a"],
received: "null",
},
],
b: [
{
code: "invalid_type",
expected: "string",
message: "Expected string, received null",
path: ["b"],
received: "null",
},
],
},
});
// Test mapping
expect(error.flatten((i: z.ZodIssue) => i.message.length)).toEqual({
formErrors: [],
fieldErrors: {
a: ["Expected string, received null".length],
b: ["Expected string, received null".length],
},
});
}
});

View file

@ -1,28 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
test("check any inference", () => {
const t1 = z.any();
t1.optional();
t1.nullable();
type t1 = z.infer<typeof t1>;
util.assertEqual<t1, any>(true);
});
test("check unknown inference", () => {
const t1 = z.unknown();
t1.optional();
t1.nullable();
type t1 = z.infer<typeof t1>;
util.assertEqual<t1, unknown>(true);
});
test("check never inference", () => {
const t1 = z.never();
expect(() => t1.parse(undefined)).toThrow();
expect(() => t1.parse("asdf")).toThrow();
expect(() => t1.parse(null)).toThrow();
});

View file

@ -1,71 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
const minTwo = z.string().array().min(2);
const maxTwo = z.string().array().max(2);
const justTwo = z.string().array().length(2);
const intNum = z.string().array().nonempty();
const nonEmptyMax = z.string().array().nonempty().max(2);
type t1 = z.infer<typeof nonEmptyMax>;
util.assertEqual<[string, ...string[]], t1>(true);
type t2 = z.infer<typeof minTwo>;
util.assertEqual<string[], t2>(true);
test("passing validations", () => {
minTwo.parse(["a", "a"]);
minTwo.parse(["a", "a", "a"]);
maxTwo.parse(["a", "a"]);
maxTwo.parse(["a"]);
justTwo.parse(["a", "a"]);
intNum.parse(["a"]);
nonEmptyMax.parse(["a"]);
});
test("failing validations", () => {
expect(() => minTwo.parse(["a"])).toThrow();
expect(() => maxTwo.parse(["a", "a", "a"])).toThrow();
expect(() => justTwo.parse(["a"])).toThrow();
expect(() => justTwo.parse(["a", "a", "a"])).toThrow();
expect(() => intNum.parse([])).toThrow();
expect(() => nonEmptyMax.parse([])).toThrow();
expect(() => nonEmptyMax.parse(["a", "a", "a"])).toThrow();
});
test("parse empty array in nonempty", () => {
expect(() =>
z
.array(z.string())
.nonempty()
.parse([] as any)
).toThrow();
});
test("get element", () => {
justTwo.element.parse("asdf");
expect(() => justTwo.element.parse(12)).toThrow();
});
test("continue parsing despite array size error", () => {
const schema = z.object({
people: z.string().array().min(2),
});
const result = schema.safeParse({
people: [123],
});
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues.length).toEqual(2);
}
});
test("parse should fail given sparse array", () => {
const schema = z.array(z.string()).nonempty().min(1).max(3);
expect(() => schema.parse(new Array(3))).toThrow();
});

View file

@ -1,388 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
/// string
const stringSchema = z.string();
test("string async parse", async () => {
const goodData = "XXX";
const badData = 12;
const goodResult = await stringSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await stringSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// number
const numberSchema = z.number();
test("number async parse", async () => {
const goodData = 1234.2353;
const badData = "1234";
const goodResult = await numberSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await numberSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// bigInt
const bigIntSchema = z.bigint();
test("bigInt async parse", async () => {
const goodData = BigInt(145);
const badData = 134;
const goodResult = await bigIntSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await bigIntSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// boolean
const booleanSchema = z.boolean();
test("boolean async parse", async () => {
const goodData = true;
const badData = 1;
const goodResult = await booleanSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await booleanSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// date
const dateSchema = z.date();
test("date async parse", async () => {
const goodData = new Date();
const badData = new Date().toISOString();
const goodResult = await dateSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await dateSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// undefined
const undefinedSchema = z.undefined();
test("undefined async parse", async () => {
const goodData = undefined;
const badData = "XXX";
const goodResult = await undefinedSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(undefined);
const badResult = await undefinedSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// null
const nullSchema = z.null();
test("null async parse", async () => {
const goodData = null;
const badData = undefined;
const goodResult = await nullSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await nullSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// any
const anySchema = z.any();
test("any async parse", async () => {
const goodData = [{}];
// const badData = 'XXX';
const goodResult = await anySchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
// const badResult = await anySchema.safeParseAsync(badData);
// expect(badResult.success).toBe(false);
// if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// unknown
const unknownSchema = z.unknown();
test("unknown async parse", async () => {
const goodData = ["asdf", 124, () => {}];
// const badData = 'XXX';
const goodResult = await unknownSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
// const badResult = await unknownSchema.safeParseAsync(badData);
// expect(badResult.success).toBe(false);
// if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// void
const voidSchema = z.void();
test("void async parse", async () => {
const goodData = undefined;
const badData = 0;
const goodResult = await voidSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await voidSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// array
const arraySchema = z.array(z.string());
test("array async parse", async () => {
const goodData = ["XXX"];
const badData = "XXX";
const goodResult = await arraySchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await arraySchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// object
const objectSchema = z.object({ string: z.string() });
test("object async parse", async () => {
const goodData = { string: "XXX" };
const badData = { string: 12 };
const goodResult = await objectSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await objectSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// union
const unionSchema = z.union([z.string(), z.undefined()]);
test("union async parse", async () => {
const goodData = undefined;
const badData = null;
const goodResult = await unionSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await unionSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// record
const recordSchema = z.record(z.object({}));
test("record async parse", async () => {
const goodData = { adsf: {}, asdf: {} };
const badData = [{}];
const goodResult = await recordSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await recordSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// function
const functionSchema = z.function();
test("function async parse", async () => {
const goodData = () => {};
const badData = "XXX";
const goodResult = await functionSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(typeof goodResult.data).toEqual("function");
const badResult = await functionSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// literal
const literalSchema = z.literal("asdf");
test("literal async parse", async () => {
const goodData = "asdf";
const badData = "asdff";
const goodResult = await literalSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await literalSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// enum
const enumSchema = z.enum(["fish", "whale"]);
test("enum async parse", async () => {
const goodData = "whale";
const badData = "leopard";
const goodResult = await enumSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await enumSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// nativeEnum
enum nativeEnumTest {
asdf = "qwer",
}
// @ts-ignore
const nativeEnumSchema = z.nativeEnum(nativeEnumTest);
test("nativeEnum async parse", async () => {
const goodData = nativeEnumTest.asdf;
const badData = "asdf";
const goodResult = await nativeEnumSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
const badResult = await nativeEnumSchema.safeParseAsync(badData);
expect(badResult.success).toBe(false);
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
});
/// promise
const promiseSchema = z.promise(z.number());
test("promise async parse good", async () => {
const goodData = Promise.resolve(123);
const goodResult = await promiseSchema.safeParseAsync(goodData);
expect(goodResult.success).toBe(true);
if (goodResult.success) {
expect(goodResult.data).toBeInstanceOf(Promise);
const data = await goodResult.data;
expect(data).toEqual(123);
// expect(goodResult.data).resolves.toEqual(124);
// return goodResult.data;
} else {
throw new Error("success should be true");
}
});
test("promise async parse bad", async () => {
const badData = Promise.resolve("XXX");
const badResult = await promiseSchema.safeParseAsync(badData);
expect(badResult.success).toBe(true);
if (badResult.success) {
await expect(badResult.data).rejects.toBeInstanceOf(z.ZodError);
} else {
throw new Error("success should be true");
}
});
test("async validation non-empty strings", async () => {
const base = z.object({
hello: z.string().refine((x) => x && x.length > 0),
foo: z.string().refine((x) => x && x.length > 0),
});
const testval = { hello: "", foo: "" };
const result1 = base.safeParse(testval);
const result2 = base.safeParseAsync(testval);
const r1 = result1;
await result2.then((r2) => {
if (r1.success === false && r2.success === false) expect(r1.error.issues.length).toBe(r2.error.issues.length); // <--- r1 has length 2, r2 has length 1
});
});
test("async validation multiple errors 1", async () => {
const base = z.object({
hello: z.string(),
foo: z.number(),
});
const testval = { hello: 3, foo: "hello" };
const result1 = base.safeParse(testval);
const result2 = base.safeParseAsync(testval);
const r1 = result1;
await result2.then((r2) => {
if (r1.success === false && r2.success === false) expect(r2.error.issues.length).toBe(r1.error.issues.length);
});
});
test("async validation multiple errors 2", async () => {
const base = (is_async?: boolean) =>
z.object({
hello: z.string(),
foo: z.object({
bar: z.number().refine(is_async ? async () => false : () => false),
}),
});
const testval = { hello: 3, foo: { bar: 4 } };
const result1 = base().safeParse(testval);
const result2 = base(true).safeParseAsync(testval);
const r1 = result1;
await result2.then((r2) => {
if (r1.success === false && r2.success === false) expect(r2.error.issues.length).toBe(r1.error.issues.length);
});
});
test("ensure early async failure prevents follow-up refinement checks", async () => {
let count = 0;
const base = z.object({
hello: z.string(),
foo: z
.number()
.refine(async () => {
count++;
return true;
})
.refine(async () => {
count++;
return true;
}, "Good"),
});
const testval = { hello: "bye", foo: 3 };
const result = await base.safeParseAsync(testval);
if (result.success === false) {
expect(result.error.issues.length).toBe(1);
expect(count).toBe(1);
}
// await result.then((r) => {
// if (r.success === false) expect(r.error.issues.length).toBe(1);
// expect(count).toBe(2);
// });
});

View file

@ -1,46 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
test("parse async test", async () => {
const schema1 = z.string().refine(async (_val) => false);
expect(() => schema1.parse("asdf")).toThrow();
const schema2 = z.string().refine((_val) => Promise.resolve(true));
return await expect(() => schema2.parse("asdf")).toThrow();
});
test("parseAsync async test", async () => {
const schema1 = z.string().refine(async (_val) => true);
await schema1.parseAsync("asdf");
const schema2 = z.string().refine(async (_val) => false);
return await expect(schema2.parseAsync("asdf")).rejects.toBeDefined();
// expect(async () => await schema2.parseAsync('asdf')).toThrow();
});
test("parseAsync async test", async () => {
// expect.assertions(2);
const schema1 = z.string().refine((_val) => Promise.resolve(true));
const v1 = await schema1.parseAsync("asdf");
expect(v1).toEqual("asdf");
const schema2 = z.string().refine((_val) => Promise.resolve(false));
await expect(schema2.parseAsync("asdf")).rejects.toBeDefined();
const schema3 = z.string().refine((_val) => Promise.resolve(true));
await expect(schema3.parseAsync("asdf")).resolves.toEqual("asdf");
return await expect(schema3.parseAsync("qwer")).resolves.toEqual("qwer");
});
test("parseAsync async with value", async () => {
const schema1 = z.string().refine(async (val) => {
return val.length > 5;
});
await expect(schema1.parseAsync("asdf")).rejects.toBeDefined();
const v = await schema1.parseAsync("asdf123");
return await expect(v).toEqual("asdf123");
});

View file

@ -1,29 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
test("type guard", () => {
const stringToNumber = z.string().transform((arg) => arg.length);
const s1 = z.object({
stringToNumber,
});
type t1 = z.input<typeof s1>;
const data = { stringToNumber: "asdf" };
const parsed = s1.safeParse(data);
if (parsed.success) {
util.assertEqual<typeof data, t1>(true);
}
});
test("test this binding", () => {
const callback = (predicate: (val: string) => boolean) => {
return predicate("hello");
};
expect(callback((value) => z.string().safeParse(value).success)).toBe(true); // true
expect(callback((value) => z.string().safeParse(value).success)).toBe(true); // true
});

View file

@ -1,55 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
const gtFive = z.bigint().gt(BigInt(5));
const gteFive = z.bigint().gte(BigInt(5));
const ltFive = z.bigint().lt(BigInt(5));
const lteFive = z.bigint().lte(BigInt(5));
const positive = z.bigint().positive();
const negative = z.bigint().negative();
const nonnegative = z.bigint().nonnegative();
const nonpositive = z.bigint().nonpositive();
const multipleOfFive = z.bigint().multipleOf(BigInt(5));
test("passing validations", () => {
z.bigint().parse(BigInt(1));
z.bigint().parse(BigInt(0));
z.bigint().parse(BigInt(-1));
gtFive.parse(BigInt(6));
gteFive.parse(BigInt(5));
gteFive.parse(BigInt(6));
ltFive.parse(BigInt(4));
lteFive.parse(BigInt(5));
lteFive.parse(BigInt(4));
positive.parse(BigInt(3));
negative.parse(BigInt(-2));
nonnegative.parse(BigInt(0));
nonnegative.parse(BigInt(7));
nonpositive.parse(BigInt(0));
nonpositive.parse(BigInt(-12));
multipleOfFive.parse(BigInt(15));
});
test("failing validations", () => {
expect(() => gtFive.parse(BigInt(5))).toThrow();
expect(() => gteFive.parse(BigInt(4))).toThrow();
expect(() => ltFive.parse(BigInt(5))).toThrow();
expect(() => lteFive.parse(BigInt(6))).toThrow();
expect(() => positive.parse(BigInt(0))).toThrow();
expect(() => positive.parse(BigInt(-2))).toThrow();
expect(() => negative.parse(BigInt(0))).toThrow();
expect(() => negative.parse(BigInt(3))).toThrow();
expect(() => nonnegative.parse(BigInt(-1))).toThrow();
expect(() => nonpositive.parse(BigInt(1))).toThrow();
expect(() => multipleOfFive.parse(BigInt(13))).toThrow();
});
test("min max getters", () => {
expect(z.bigint().min(BigInt(5)).minValue).toEqual(BigInt(5));
expect(z.bigint().min(BigInt(5)).min(BigInt(10)).minValue).toEqual(BigInt(10));
expect(z.bigint().max(BigInt(5)).maxValue).toEqual(BigInt(5));
expect(z.bigint().max(BigInt(5)).max(BigInt(1)).maxValue).toEqual(BigInt(1));
});

View file

@ -1,53 +0,0 @@
// @ts-ignore TS6133
import { test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
test("branded types", () => {
const mySchema = z
.object({
name: z.string(),
})
.brand<"superschema">();
// simple branding
type MySchema = z.infer<typeof mySchema>;
util.assertEqual<MySchema, { name: string } & { [z.BRAND]: { superschema: true } }>(true);
const doStuff = (arg: MySchema) => arg;
doStuff(mySchema.parse({ name: "hello there" }));
// inheritance
const extendedSchema = mySchema.brand<"subschema">();
type ExtendedSchema = z.infer<typeof extendedSchema>;
util.assertEqual<ExtendedSchema, { name: string } & z.BRAND<"superschema"> & z.BRAND<"subschema">>(true);
doStuff(extendedSchema.parse({ name: "hello again" }));
// number branding
const numberSchema = z.number().brand<42>();
type NumberSchema = z.infer<typeof numberSchema>;
util.assertEqual<NumberSchema, number & { [z.BRAND]: { 42: true } }>(true);
// symbol branding
const MyBrand: unique symbol = Symbol("hello");
type MyBrand = typeof MyBrand;
const symbolBrand = z.number().brand<"sup">().brand<typeof MyBrand>();
type SymbolBrand = z.infer<typeof symbolBrand>;
// number & { [z.BRAND]: { sup: true, [MyBrand]: true } }
util.assertEqual<SymbolBrand, number & z.BRAND<"sup"> & z.BRAND<MyBrand>>(true);
// keeping brands out of input types
const age = z.number().brand<"age">();
type Age = z.infer<typeof age>;
type AgeInput = z.input<typeof age>;
util.assertEqual<AgeInput, Age>(false);
util.assertEqual<number, AgeInput>(true);
util.assertEqual<number & z.BRAND<"age">, Age>(true);
// @ts-expect-error
doStuff({ name: "hello there!" });
});

View file

@ -1,220 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import { z } from "zod/v3";
import { util } from "../helpers/util.js";
test("basic catch", () => {
expect(z.string().catch("default").parse(undefined)).toBe("default");
});
test("catch fn does not run when parsing succeeds", () => {
let isCalled = false;
const cb = () => {
isCalled = true;
return "asdf";
};
expect(z.string().catch(cb).parse("test")).toBe("test");
expect(isCalled).toEqual(false);
});
test("basic catch async", async () => {
const result = await z.string().catch("default").parseAsync(1243);
expect(result).toBe("default");
});
test("catch replace wrong types", () => {
expect(z.string().catch("default").parse(true)).toBe("default");
expect(z.string().catch("default").parse(true)).toBe("default");
expect(z.string().catch("default").parse(15)).toBe("default");
expect(z.string().catch("default").parse([])).toBe("default");
expect(z.string().catch("default").parse(new Map())).toBe("default");
expect(z.string().catch("default").parse(new Set())).toBe("default");
expect(z.string().catch("default").parse({})).toBe("default");
});
test("catch with transform", () => {
const stringWithDefault = z
.string()
.transform((val) => val.toUpperCase())
.catch("default");
expect(stringWithDefault.parse(undefined)).toBe("default");
expect(stringWithDefault.parse(15)).toBe("default");
expect(stringWithDefault).toBeInstanceOf(z.ZodCatch);
expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodEffects);
expect(stringWithDefault._def.innerType._def.schema).toBeInstanceOf(z.ZodSchema);
type inp = z.input<typeof stringWithDefault>;
util.assertEqual<inp, unknown>(true);
type out = z.output<typeof stringWithDefault>;
util.assertEqual<out, string>(true);
});
test("catch on existing optional", () => {
const stringWithDefault = z.string().optional().catch("asdf");
expect(stringWithDefault.parse(undefined)).toBe(undefined);
expect(stringWithDefault.parse(15)).toBe("asdf");
expect(stringWithDefault).toBeInstanceOf(z.ZodCatch);
expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodOptional);
expect(stringWithDefault._def.innerType._def.innerType).toBeInstanceOf(z.ZodString);
type inp = z.input<typeof stringWithDefault>;
util.assertEqual<inp, unknown>(true);
type out = z.output<typeof stringWithDefault>;
util.assertEqual<out, string | undefined>(true);
});
test("optional on catch", () => {
const stringWithDefault = z.string().catch("asdf").optional();
type inp = z.input<typeof stringWithDefault>;
util.assertEqual<inp, unknown>(true);
type out = z.output<typeof stringWithDefault>;
util.assertEqual<out, string | undefined>(true);
});
test("complex chain example", () => {
const complex = z
.string()
.catch("asdf")
.transform((val) => val + "!")
.transform((val) => val.toUpperCase())
.catch("qwer")
.removeCatch()
.optional()
.catch("asdfasdf");
expect(complex.parse("qwer")).toBe("QWER!");
expect(complex.parse(15)).toBe("ASDF!");
expect(complex.parse(true)).toBe("ASDF!");
});
test("removeCatch", () => {
const stringWithRemovedDefault = z.string().catch("asdf").removeCatch();
type out = z.output<typeof stringWithRemovedDefault>;
util.assertEqual<out, string>(true);
});
test("nested", () => {
const inner = z.string().catch("asdf");
const outer = z.object({ inner }).catch({
inner: "asdf",
});
type input = z.input<typeof outer>;
util.assertEqual<input, unknown>(true);
type out = z.output<typeof outer>;
util.assertEqual<out, { inner: string }>(true);
expect(outer.parse(undefined)).toEqual({ inner: "asdf" });
expect(outer.parse({})).toEqual({ inner: "asdf" });
expect(outer.parse({ inner: undefined })).toEqual({ inner: "asdf" });
});
test("chained catch", () => {
const stringWithDefault = z.string().catch("inner").catch("outer");
const result = stringWithDefault.parse(undefined);
expect(result).toEqual("inner");
const resultDiff = stringWithDefault.parse(5);
expect(resultDiff).toEqual("inner");
});
test("factory", () => {
z.ZodCatch.create(z.string(), {
catch: "asdf",
}).parse(undefined);
});
test("native enum", () => {
enum Fruits {
apple = "apple",
orange = "orange",
}
const schema = z.object({
fruit: z.nativeEnum(Fruits).catch(Fruits.apple),
});
expect(schema.parse({})).toEqual({ fruit: Fruits.apple });
expect(schema.parse({ fruit: 15 })).toEqual({ fruit: Fruits.apple });
});
test("enum", () => {
const schema = z.object({
fruit: z.enum(["apple", "orange"]).catch("apple"),
});
expect(schema.parse({})).toEqual({ fruit: "apple" });
expect(schema.parse({ fruit: true })).toEqual({ fruit: "apple" });
expect(schema.parse({ fruit: 15 })).toEqual({ fruit: "apple" });
});
test("reported issues with nested usage", () => {
const schema = z.object({
string: z.string(),
obj: z.object({
sub: z.object({
lit: z.literal("a"),
subCatch: z.number().catch(23),
}),
midCatch: z.number().catch(42),
}),
number: z.number().catch(0),
bool: z.boolean(),
});
try {
schema.parse({
string: {},
obj: {
sub: {
lit: "b",
subCatch: "24",
},
midCatch: 444,
},
number: "",
bool: "yes",
});
} catch (error) {
const issues = (error as z.ZodError).issues;
expect(issues.length).toEqual(3);
expect(issues[0].message).toMatch("string");
expect(issues[1].message).toMatch("literal");
expect(issues[2].message).toMatch("boolean");
}
});
test("catch error", () => {
let catchError: z.ZodError | undefined = undefined;
const schema = z.object({
age: z.number(),
name: z.string().catch((ctx) => {
catchError = ctx.error;
return "John Doe";
}),
});
const result = schema.safeParse({
age: null,
name: null,
});
expect(result.success).toEqual(false);
expect(!result.success && result.error.issues.length).toEqual(1);
expect(!result.success && result.error.issues[0].message).toMatch("number");
expect(catchError).toBeInstanceOf(z.ZodError);
expect(catchError !== undefined && (catchError as z.ZodError).issues.length).toEqual(1);
expect(catchError !== undefined && (catchError as z.ZodError).issues[0].message).toMatch("string");
});
test("ctx.input", () => {
const schema = z.string().catch((ctx) => {
return String(ctx.input);
});
expect(schema.parse(123)).toEqual("123");
});

View file

@ -1,133 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
test("string coercion", () => {
const schema = z.coerce.string();
expect(schema.parse("sup")).toEqual("sup");
expect(schema.parse("")).toEqual("");
expect(schema.parse(12)).toEqual("12");
expect(schema.parse(0)).toEqual("0");
expect(schema.parse(-12)).toEqual("-12");
expect(schema.parse(3.14)).toEqual("3.14");
expect(schema.parse(BigInt(15))).toEqual("15");
expect(schema.parse(Number.NaN)).toEqual("NaN");
expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual("Infinity");
expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual("-Infinity");
expect(schema.parse(true)).toEqual("true");
expect(schema.parse(false)).toEqual("false");
expect(schema.parse(null)).toEqual("null");
expect(schema.parse(undefined)).toEqual("undefined");
expect(schema.parse({ hello: "world!" })).toEqual("[object Object]");
expect(schema.parse(["item", "another_item"])).toEqual("item,another_item");
expect(schema.parse([])).toEqual("");
expect(schema.parse(new Date("2022-01-01T00:00:00.000Z"))).toEqual(new Date("2022-01-01T00:00:00.000Z").toString());
});
test("number coercion", () => {
const schema = z.coerce.number();
expect(schema.parse("12")).toEqual(12);
expect(schema.parse("0")).toEqual(0);
expect(schema.parse("-12")).toEqual(-12);
expect(schema.parse("3.14")).toEqual(3.14);
expect(schema.parse("")).toEqual(0);
expect(() => schema.parse("NOT_A_NUMBER")).toThrow(); // z.ZodError
expect(schema.parse(12)).toEqual(12);
expect(schema.parse(0)).toEqual(0);
expect(schema.parse(-12)).toEqual(-12);
expect(schema.parse(3.14)).toEqual(3.14);
expect(schema.parse(BigInt(15))).toEqual(15);
expect(() => schema.parse(Number.NaN)).toThrow(); // z.ZodError
expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual(Number.POSITIVE_INFINITY);
expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual(Number.NEGATIVE_INFINITY);
expect(schema.parse(true)).toEqual(1);
expect(schema.parse(false)).toEqual(0);
expect(schema.parse(null)).toEqual(0);
expect(() => schema.parse(undefined)).toThrow(); // z.ZodError
expect(() => schema.parse({ hello: "world!" })).toThrow(); // z.ZodError
expect(() => schema.parse(["item", "another_item"])).toThrow(); // z.ZodError
expect(schema.parse([])).toEqual(0);
expect(schema.parse(new Date(1670139203496))).toEqual(1670139203496);
});
test("boolean coercion", () => {
const schema = z.coerce.boolean();
expect(schema.parse("true")).toEqual(true);
expect(schema.parse("false")).toEqual(true);
expect(schema.parse("0")).toEqual(true);
expect(schema.parse("1")).toEqual(true);
expect(schema.parse("")).toEqual(false);
expect(schema.parse(1)).toEqual(true);
expect(schema.parse(0)).toEqual(false);
expect(schema.parse(-1)).toEqual(true);
expect(schema.parse(3.14)).toEqual(true);
expect(schema.parse(BigInt(15))).toEqual(true);
expect(schema.parse(Number.NaN)).toEqual(false);
expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual(true);
expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual(true);
expect(schema.parse(true)).toEqual(true);
expect(schema.parse(false)).toEqual(false);
expect(schema.parse(null)).toEqual(false);
expect(schema.parse(undefined)).toEqual(false);
expect(schema.parse({ hello: "world!" })).toEqual(true);
expect(schema.parse(["item", "another_item"])).toEqual(true);
expect(schema.parse([])).toEqual(true);
expect(schema.parse(new Date(1670139203496))).toEqual(true);
});
test("bigint coercion", () => {
const schema = z.coerce.bigint();
expect(schema.parse("5")).toEqual(BigInt(5));
expect(schema.parse("0")).toEqual(BigInt(0));
expect(schema.parse("-5")).toEqual(BigInt(-5));
expect(() => schema.parse("3.14")).toThrow(); // not a z.ZodError!
expect(schema.parse("")).toEqual(BigInt(0));
expect(() => schema.parse("NOT_A_NUMBER")).toThrow(); // not a z.ZodError!
expect(schema.parse(5)).toEqual(BigInt(5));
expect(schema.parse(0)).toEqual(BigInt(0));
expect(schema.parse(-5)).toEqual(BigInt(-5));
expect(() => schema.parse(3.14)).toThrow(); // not a z.ZodError!
expect(schema.parse(BigInt(5))).toEqual(BigInt(5));
expect(() => schema.parse(Number.NaN)).toThrow(); // not a z.ZodError!
expect(() => schema.parse(Number.POSITIVE_INFINITY)).toThrow(); // not a z.ZodError!
expect(() => schema.parse(Number.NEGATIVE_INFINITY)).toThrow(); // not a z.ZodError!
expect(schema.parse(true)).toEqual(BigInt(1));
expect(schema.parse(false)).toEqual(BigInt(0));
expect(() => schema.parse(null)).toThrow(); // not a z.ZodError!
expect(() => schema.parse(undefined)).toThrow(); // not a z.ZodError!
expect(() => schema.parse({ hello: "world!" })).toThrow(); // not a z.ZodError!
expect(() => schema.parse(["item", "another_item"])).toThrow(); // not a z.ZodError!
expect(schema.parse([])).toEqual(BigInt(0));
expect(schema.parse(new Date(1670139203496))).toEqual(BigInt(1670139203496));
});
test("date coercion", () => {
const schema = z.coerce.date();
expect(schema.parse(new Date().toDateString())).toBeInstanceOf(Date);
expect(schema.parse(new Date().toISOString())).toBeInstanceOf(Date);
expect(schema.parse(new Date().toUTCString())).toBeInstanceOf(Date);
expect(schema.parse("5")).toBeInstanceOf(Date);
expect(schema.parse("2000-01-01")).toBeInstanceOf(Date);
// expect(schema.parse("0")).toBeInstanceOf(Date);
// expect(schema.parse("-5")).toBeInstanceOf(Date);
// expect(schema.parse("3.14")).toBeInstanceOf(Date);
expect(() => schema.parse("")).toThrow(); // z.ZodError
expect(() => schema.parse("NOT_A_DATE")).toThrow(); // z.ZodError
expect(schema.parse(5)).toBeInstanceOf(Date);
expect(schema.parse(0)).toBeInstanceOf(Date);
expect(schema.parse(-5)).toBeInstanceOf(Date);
expect(schema.parse(3.14)).toBeInstanceOf(Date);
expect(() => schema.parse(BigInt(5))).toThrow(); // not a z.ZodError!
expect(() => schema.parse(Number.NaN)).toThrow(); // z.ZodError
expect(() => schema.parse(Number.POSITIVE_INFINITY)).toThrow(); // z.ZodError
expect(() => schema.parse(Number.NEGATIVE_INFINITY)).toThrow(); // z.ZodError
expect(schema.parse(true)).toBeInstanceOf(Date);
expect(schema.parse(false)).toBeInstanceOf(Date);
expect(schema.parse(null)).toBeInstanceOf(Date);
expect(() => schema.parse(undefined)).toThrow(); // z.ZodError
expect(() => schema.parse({ hello: "world!" })).toThrow(); // z.ZodError
expect(() => schema.parse(["item", "another_item"])).toThrow(); // z.ZodError
expect(() => schema.parse([])).toThrow(); // z.ZodError
expect(schema.parse(new Date())).toBeInstanceOf(Date);
});

View file

@ -1,56 +0,0 @@
import { test } from "vitest";
import * as z from "zod/v3";
const crazySchema = z.object({
tuple: z.tuple([
z.string().nullable().optional(),
z.number().nullable().optional(),
z.boolean().nullable().optional(),
z.null().nullable().optional(),
z.undefined().nullable().optional(),
z.literal("1234").nullable().optional(),
]),
merged: z
.object({
k1: z.string().optional(),
})
.merge(z.object({ k1: z.string().nullable(), k2: z.number() })),
union: z.array(z.union([z.literal("asdf"), z.literal(12)])).nonempty(),
array: z.array(z.number()),
// sumTransformer: z.transformer(z.array(z.number()), z.number(), (arg) => {
// return arg.reduce((a, b) => a + b, 0);
// }),
sumMinLength: z.array(z.number()).refine((arg) => arg.length > 5),
intersection: z.intersection(z.object({ p1: z.string().optional() }), z.object({ p1: z.number().optional() })),
enum: z.intersection(z.enum(["zero", "one"]), z.enum(["one", "two"])),
nonstrict: z.object({ points: z.number() }).nonstrict(),
numProm: z.promise(z.number()),
lenfun: z.function(z.tuple([z.string()]), z.boolean()),
});
// const asyncCrazySchema = crazySchema.extend({
// // async_transform: z.transformer(
// // z.array(z.number()),
// // z.number(),
// // async (arg) => {
// // return arg.reduce((a, b) => a + b, 0);
// // }
// // ),
// async_refine: z.array(z.number()).refine(async (arg) => arg.length > 5),
// });
test("parse", () => {
crazySchema.parse({
tuple: ["asdf", 1234, true, null, undefined, "1234"],
merged: { k1: "asdf", k2: 12 },
union: ["asdf", 12, "asdf", 12, "asdf", 12],
array: [12, 15, 16],
// sumTransformer: [12, 15, 16],
sumMinLength: [12, 15, 16, 98, 24, 63],
intersection: {},
enum: "one",
nonstrict: { points: 1234 },
numProm: Promise.resolve(12),
lenfun: (x: string) => x.length,
});
});

View file

@ -1,31 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
test("passing validations", () => {
const example1 = z.custom<number>((x) => typeof x === "number");
example1.parse(1234);
expect(() => example1.parse({})).toThrow();
});
test("string params", () => {
const example1 = z.custom<number>((x) => typeof x !== "number", "customerr");
const result = example1.safeParse(1234);
expect(result.success).toEqual(false);
// @ts-ignore
expect(JSON.stringify(result.error).includes("customerr")).toEqual(true);
});
test("async validations", async () => {
const example1 = z.custom<number>(async (x) => {
return typeof x === "number";
});
const r1 = await example1.safeParseAsync(1234);
expect(r1.success).toEqual(true);
expect(r1.data).toEqual(1234);
const r2 = await example1.safeParseAsync("asdf");
expect(r2.success).toEqual(false);
expect(r2.error!.issues.length).toEqual(1);
});

View file

@ -1,32 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
const beforeBenchmarkDate = new Date(2022, 10, 4);
const benchmarkDate = new Date(2022, 10, 5);
const afterBenchmarkDate = new Date(2022, 10, 6);
const minCheck = z.date().min(benchmarkDate);
const maxCheck = z.date().max(benchmarkDate);
test("passing validations", () => {
minCheck.parse(benchmarkDate);
minCheck.parse(afterBenchmarkDate);
maxCheck.parse(benchmarkDate);
maxCheck.parse(beforeBenchmarkDate);
});
test("failing validations", () => {
expect(() => minCheck.parse(beforeBenchmarkDate)).toThrow();
expect(() => maxCheck.parse(afterBenchmarkDate)).toThrow();
});
test("min max getters", () => {
expect(minCheck.minDate).toEqual(benchmarkDate);
expect(minCheck.min(afterBenchmarkDate).minDate).toEqual(afterBenchmarkDate);
expect(maxCheck.maxDate).toEqual(benchmarkDate);
expect(maxCheck.max(beforeBenchmarkDate).maxDate).toEqual(beforeBenchmarkDate);
});

View file

@ -1,186 +0,0 @@
// @ts-ignore TS6133
import { test } from "vitest";
import * as z from "zod/v3";
test("test", () => {
z;
});
// const fish = z.object({
// name: z.string(),
// props: z.object({
// color: z.string(),
// numScales: z.number(),
// }),
// });
// const nonStrict = z
// .object({
// name: z.string(),
// color: z.string(),
// })
// .nonstrict();
// test('object pick type', () => {
// const modNonStrictFish = nonStrict.omit({ name: true });
// modNonStrictFish.parse({ color: 'asdf' });
// const bad1 = () => fish.pick({ props: { unknown: true } } as any);
// const bad2 = () => fish.omit({ name: true, props: { unknown: true } } as any);
// expect(bad1).toThrow();
// expect(bad2).toThrow();
// });
// test('f1', () => {
// const f1 = fish.pick(true);
// f1.parse({ name: 'a', props: { color: 'b', numScales: 3 } });
// });
// test('f2', () => {
// const f2 = fish.pick({ props: true });
// f2.parse({ props: { color: 'asdf', numScales: 1 } });
// const badcheck2 = () => f2.parse({ name: 'a', props: { color: 'b', numScales: 3 } } as any);
// expect(badcheck2).toThrow();
// });
// test('f3', () => {
// const f3 = fish.pick({ props: { color: true } });
// f3.parse({ props: { color: 'b' } });
// const badcheck3 = () => f3.parse({ name: 'a', props: { color: 'b', numScales: 3 } } as any);
// expect(badcheck3).toThrow();
// });
// test('f4', () => {
// const badcheck4 = () => fish.pick({ props: { color: true, unknown: true } });
// expect(badcheck4).toThrow();
// });
// test('f6', () => {
// const f6 = fish.omit({ props: true });
// const badcheck6 = () => f6.parse({ name: 'a', props: { color: 'b', numScales: 3 } } as any);
// f6.parse({ name: 'adsf' });
// expect(badcheck6).toThrow();
// });
// test('f7', () => {
// const f7 = fish.omit({ props: { color: true } });
// f7.parse({ name: 'a', props: { numScales: 3 } });
// const badcheck7 = () => f7.parse({ name: 'a', props: { color: 'b', numScales: 3 } } as any);
// expect(badcheck7).toThrow();
// });
// test('f8', () => {
// const badcheck8 = () => fish.omit({ props: { color: true, unknown: true } });
// expect(badcheck8).toThrow();
// });
// test('f9', () => {
// const f9 = nonStrict.pick(true);
// f9.parse({ name: 'a', color: 'asdf' });
// });
// test('f10', () => {
// const f10 = nonStrict.pick({ name: true });
// f10.parse({ name: 'a' });
// const val = f10.parse({ name: 'a', color: 'b' });
// expect(val).toEqual({ name: 'a' });
// });
// test('f12', () => {
// const badfcheck12 = () => nonStrict.omit({ color: true, asdf: true });
// expect(badfcheck12).toThrow();
// });
// test('array masking', () => {
// const fishArray = z.array(fish);
// const modFishArray = fishArray.pick({
// name: true,
// props: {
// numScales: true,
// },
// });
// modFishArray.parse([{ name: 'fish', props: { numScales: 12 } }]);
// const bad1 = () => modFishArray.parse([{ name: 'fish', props: { numScales: 12, color: 'asdf' } }] as any);
// expect(bad1).toThrow();
// });
// test('array masking', () => {
// const fishArray = z.array(fish);
// const fail = () =>
// fishArray.pick({
// name: true,
// props: {
// whatever: true,
// },
// } as any);
// expect(fail).toThrow();
// });
// test('array masking', () => {
// const fishArray = z.array(fish);
// const fail = () =>
// fishArray.omit({
// whateve: true,
// } as any);
// expect(fail).toThrow();
// });
// test('array masking', () => {
// const fishArray = z.array(fish);
// const modFishList = fishArray.omit({
// name: true,
// props: {
// color: true,
// },
// });
// modFishList.parse([{ props: { numScales: 12 } }]);
// const fail = () => modFishList.parse([{ name: 'hello', props: { numScales: 12 } }] as any);
// expect(fail).toThrow();
// });
// test('primitive array masking', () => {
// const fishArray = z.array(z.number());
// const fail = () => fishArray.pick({} as any);
// expect(fail).toThrow();
// });
// test('other array masking', () => {
// const fishArray = z.array(z.array(z.number()));
// const fail = () => fishArray.pick({} as any);
// expect(fail).toThrow();
// });
// test('invalid mask #1', () => {
// const fail = () => fish.pick(1 as any);
// expect(fail).toThrow();
// });
// test('invalid mask #2', () => {
// const fail = () => fish.pick([] as any);
// expect(fail).toThrow();
// });
// test('invalid mask #3', () => {
// const fail = () => fish.pick(false as any);
// expect(fail).toThrow();
// });
// test('invalid mask #4', () => {
// const fail = () => fish.pick('asdf' as any);
// expect(fail).toThrow();
// });
// test('invalid mask #5', () => {
// const fail = () => fish.omit(1 as any);
// expect(fail).toThrow();
// });
// test('invalid mask #6', () => {
// const fail = () => fish.omit([] as any);
// expect(fail).toThrow();
// });
// test('invalid mask #7', () => {
// const fail = () => fish.omit(false as any);
// expect(fail).toThrow();
// });
// test('invalid mask #8', () => {
// const fail = () => fish.omit('asdf' as any);
// expect(fail).toThrow();
// });

View file

@ -1,112 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import { z } from "zod/v3";
import { util } from "../helpers/util.js";
test("basic defaults", () => {
expect(z.string().default("default").parse(undefined)).toBe("default");
});
test("default with transform", () => {
const stringWithDefault = z
.string()
.transform((val) => val.toUpperCase())
.default("default");
expect(stringWithDefault.parse(undefined)).toBe("DEFAULT");
expect(stringWithDefault).toBeInstanceOf(z.ZodDefault);
expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodEffects);
expect(stringWithDefault._def.innerType._def.schema).toBeInstanceOf(z.ZodSchema);
type inp = z.input<typeof stringWithDefault>;
util.assertEqual<inp, string | undefined>(true);
type out = z.output<typeof stringWithDefault>;
util.assertEqual<out, string>(true);
});
test("default on existing optional", () => {
const stringWithDefault = z.string().optional().default("asdf");
expect(stringWithDefault.parse(undefined)).toBe("asdf");
expect(stringWithDefault).toBeInstanceOf(z.ZodDefault);
expect(stringWithDefault._def.innerType).toBeInstanceOf(z.ZodOptional);
expect(stringWithDefault._def.innerType._def.innerType).toBeInstanceOf(z.ZodString);
type inp = z.input<typeof stringWithDefault>;
util.assertEqual<inp, string | undefined>(true);
type out = z.output<typeof stringWithDefault>;
util.assertEqual<out, string>(true);
});
test("optional on default", () => {
const stringWithDefault = z.string().default("asdf").optional();
type inp = z.input<typeof stringWithDefault>;
util.assertEqual<inp, string | undefined>(true);
type out = z.output<typeof stringWithDefault>;
util.assertEqual<out, string | undefined>(true);
});
test("complex chain example", () => {
const complex = z
.string()
.default("asdf")
.transform((val) => val.toUpperCase())
.default("qwer")
.removeDefault()
.optional()
.default("asdfasdf");
expect(complex.parse(undefined)).toBe("ASDFASDF");
});
test("removeDefault", () => {
const stringWithRemovedDefault = z.string().default("asdf").removeDefault();
type out = z.output<typeof stringWithRemovedDefault>;
util.assertEqual<out, string>(true);
});
test("nested", () => {
const inner = z.string().default("asdf");
const outer = z.object({ inner }).default({
inner: undefined,
});
type input = z.input<typeof outer>;
util.assertEqual<input, { inner?: string | undefined } | undefined>(true);
type out = z.output<typeof outer>;
util.assertEqual<out, { inner: string }>(true);
expect(outer.parse(undefined)).toEqual({ inner: "asdf" });
expect(outer.parse({})).toEqual({ inner: "asdf" });
expect(outer.parse({ inner: undefined })).toEqual({ inner: "asdf" });
});
test("chained defaults", () => {
const stringWithDefault = z.string().default("inner").default("outer");
const result = stringWithDefault.parse(undefined);
expect(result).toEqual("outer");
});
test("factory", () => {
expect(z.ZodDefault.create(z.string(), { default: "asdf" }).parse(undefined)).toEqual("asdf");
});
test("native enum", () => {
enum Fruits {
apple = "apple",
orange = "orange",
}
const schema = z.object({
fruit: z.nativeEnum(Fruits).default(Fruits.apple),
});
expect(schema.parse({})).toEqual({ fruit: Fruits.apple });
});
test("enum", () => {
const schema = z.object({
fruit: z.enum(["apple", "orange"]).default("apple"),
});
expect(schema.parse({})).toEqual({ fruit: "apple" });
});

View file

@ -1,33 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
const description = "a description";
test("passing `description` to schema should add a description", () => {
expect(z.string({ description }).description).toEqual(description);
expect(z.number({ description }).description).toEqual(description);
expect(z.boolean({ description }).description).toEqual(description);
});
test("`.describe` should add a description", () => {
expect(z.string().describe(description).description).toEqual(description);
expect(z.number().describe(description).description).toEqual(description);
expect(z.boolean().describe(description).description).toEqual(description);
});
test("description should carry over to chained schemas", () => {
const schema = z.string({ description });
expect(schema.description).toEqual(description);
expect(schema.optional().description).toEqual(description);
expect(schema.optional().nullable().default("default").description).toEqual(description);
});
test("description should not carry over to chained array schema", () => {
const schema = z.string().describe(description);
expect(schema.description).toEqual(description);
expect(schema.array().description).toEqual(undefined);
expect(z.array(schema).description).toEqual(undefined);
});

View file

@ -1,315 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
test("valid", () => {
expect(
z
.discriminatedUnion("type", [
z.object({ type: z.literal("a"), a: z.string() }),
z.object({ type: z.literal("b"), b: z.string() }),
])
.parse({ type: "a", a: "abc" })
).toEqual({ type: "a", a: "abc" });
});
test("valid - discriminator value of various primitive types", () => {
const schema = z.discriminatedUnion("type", [
z.object({ type: z.literal("1"), val: z.literal(1) }),
z.object({ type: z.literal(1), val: z.literal(2) }),
z.object({ type: z.literal(BigInt(1)), val: z.literal(3) }),
z.object({ type: z.literal("true"), val: z.literal(4) }),
z.object({ type: z.literal(true), val: z.literal(5) }),
z.object({ type: z.literal("null"), val: z.literal(6) }),
z.object({ type: z.literal(null), val: z.literal(7) }),
z.object({ type: z.literal("undefined"), val: z.literal(8) }),
z.object({ type: z.literal(undefined), val: z.literal(9) }),
z.object({ type: z.literal("transform"), val: z.literal(10) }),
z.object({ type: z.literal("refine"), val: z.literal(11) }),
z.object({ type: z.literal("superRefine"), val: z.literal(12) }),
]);
expect(schema.parse({ type: "1", val: 1 })).toEqual({ type: "1", val: 1 });
expect(schema.parse({ type: 1, val: 2 })).toEqual({ type: 1, val: 2 });
expect(schema.parse({ type: BigInt(1), val: 3 })).toEqual({
type: BigInt(1),
val: 3,
});
expect(schema.parse({ type: "true", val: 4 })).toEqual({
type: "true",
val: 4,
});
expect(schema.parse({ type: true, val: 5 })).toEqual({
type: true,
val: 5,
});
expect(schema.parse({ type: "null", val: 6 })).toEqual({
type: "null",
val: 6,
});
expect(schema.parse({ type: null, val: 7 })).toEqual({
type: null,
val: 7,
});
expect(schema.parse({ type: "undefined", val: 8 })).toEqual({
type: "undefined",
val: 8,
});
expect(schema.parse({ type: undefined, val: 9 })).toEqual({
type: undefined,
val: 9,
});
});
test("invalid - null", () => {
try {
z.discriminatedUnion("type", [
z.object({ type: z.literal("a"), a: z.string() }),
z.object({ type: z.literal("b"), b: z.string() }),
]).parse(null);
throw new Error();
} catch (e: any) {
expect(JSON.parse(e.message)).toEqual([
{
code: z.ZodIssueCode.invalid_type,
expected: z.ZodParsedType.object,
message: "Expected object, received null",
received: z.ZodParsedType.null,
path: [],
},
]);
}
});
test("invalid discriminator value", () => {
try {
z.discriminatedUnion("type", [
z.object({ type: z.literal("a"), a: z.string() }),
z.object({ type: z.literal("b"), b: z.string() }),
]).parse({ type: "x", a: "abc" });
throw new Error();
} catch (e: any) {
expect(JSON.parse(e.message)).toEqual([
{
code: z.ZodIssueCode.invalid_union_discriminator,
options: ["a", "b"],
message: "Invalid discriminator value. Expected 'a' | 'b'",
path: ["type"],
},
]);
}
});
test("valid discriminator value, invalid data", () => {
try {
z.discriminatedUnion("type", [
z.object({ type: z.literal("a"), a: z.string() }),
z.object({ type: z.literal("b"), b: z.string() }),
]).parse({ type: "a", b: "abc" });
throw new Error();
} catch (e: any) {
expect(JSON.parse(e.message)).toEqual([
{
code: z.ZodIssueCode.invalid_type,
expected: z.ZodParsedType.string,
message: "Required",
path: ["a"],
received: z.ZodParsedType.undefined,
},
]);
}
});
test("wrong schema - missing discriminator", () => {
try {
z.discriminatedUnion("type", [
z.object({ type: z.literal("a"), a: z.string() }),
z.object({ b: z.string() }) as any,
]);
throw new Error();
} catch (e: any) {
expect(e.message.includes("could not be extracted")).toBe(true);
}
});
test("wrong schema - duplicate discriminator values", () => {
try {
z.discriminatedUnion("type", [
z.object({ type: z.literal("a"), a: z.string() }),
z.object({ type: z.literal("a"), b: z.string() }),
]);
throw new Error();
} catch (e: any) {
expect(e.message.includes("has duplicate value")).toEqual(true);
}
});
test("async - valid", async () => {
expect(
await z
.discriminatedUnion("type", [
z.object({
type: z.literal("a"),
a: z
.string()
.refine(async () => true)
.transform(async (val) => Number(val)),
}),
z.object({
type: z.literal("b"),
b: z.string(),
}),
])
.parseAsync({ type: "a", a: "1" })
).toEqual({ type: "a", a: 1 });
});
test("async - invalid", async () => {
try {
await z
.discriminatedUnion("type", [
z.object({
type: z.literal("a"),
a: z
.string()
.refine(async () => true)
.transform(async (val) => val),
}),
z.object({
type: z.literal("b"),
b: z.string(),
}),
])
.parseAsync({ type: "a", a: 1 });
throw new Error();
} catch (e: any) {
expect(JSON.parse(e.message)).toEqual([
{
code: "invalid_type",
expected: "string",
received: "number",
path: ["a"],
message: "Expected string, received number",
},
]);
}
});
test("valid - literals with .default or .preprocess", () => {
const schema = z.discriminatedUnion("type", [
z.object({
type: z.literal("foo").default("foo"),
a: z.string(),
}),
z.object({
type: z.literal("custom"),
method: z.string(),
}),
z.object({
type: z.preprocess((val) => String(val), z.literal("bar")),
c: z.string(),
}),
]);
expect(schema.parse({ type: "foo", a: "foo" })).toEqual({
type: "foo",
a: "foo",
});
});
test("enum and nativeEnum", () => {
enum MyEnum {
d = 0,
e = "e",
}
const schema = z.discriminatedUnion("key", [
z.object({
key: z.literal("a"),
// Add other properties specific to this option
}),
z.object({
key: z.enum(["b", "c"]),
// Add other properties specific to this option
}),
z.object({
key: z.nativeEnum(MyEnum),
// Add other properties specific to this option
}),
]);
// type schema = z.infer<typeof schema>;
schema.parse({ key: "a" });
schema.parse({ key: "b" });
schema.parse({ key: "c" });
schema.parse({ key: MyEnum.d });
schema.parse({ key: MyEnum.e });
schema.parse({ key: "e" });
});
test("branded", () => {
const schema = z.discriminatedUnion("key", [
z.object({
key: z.literal("a"),
// Add other properties specific to this option
}),
z.object({
key: z.literal("b").brand("asdfaf"),
// Add other properties specific to this option
}),
]);
// type schema = z.infer<typeof schema>;
schema.parse({ key: "a" });
schema.parse({ key: "b" });
expect(() => {
schema.parse({ key: "c" });
}).toThrow();
});
test("optional and nullable", () => {
const schema = z.discriminatedUnion("key", [
z.object({
key: z.literal("a").optional(),
a: z.literal(true),
}),
z.object({
key: z.literal("b").nullable(),
b: z.literal(true),
// Add other properties specific to this option
}),
]);
type schema = z.infer<typeof schema>;
z.util.assertEqual<schema, { key?: "a" | undefined; a: true } | { key: "b" | null; b: true }>(true);
schema.parse({ key: "a", a: true });
schema.parse({ key: undefined, a: true });
schema.parse({ key: "b", b: true });
schema.parse({ key: null, b: true });
expect(() => {
schema.parse({ key: null, a: true });
}).toThrow();
expect(() => {
schema.parse({ key: "b", a: true });
}).toThrow();
const value = schema.parse({ key: null, b: true });
if (!("key" in value)) value.a;
if (value.key === undefined) value.a;
if (value.key === "a") value.a;
if (value.key === "b") value.b;
if (value.key === null) value.b;
});
test("readonly array of options", () => {
const options = [
z.object({ type: z.literal("x"), val: z.literal(1) }),
z.object({ type: z.literal("y"), val: z.literal(2) }),
] as const;
expect(z.discriminatedUnion("type", options).parse({ type: "x", val: 1 })).toEqual({ type: "x", val: 1 });
});

View file

@ -1,80 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
test("create enum", () => {
const MyEnum = z.enum(["Red", "Green", "Blue"]);
expect(MyEnum.Values.Red).toEqual("Red");
expect(MyEnum.Enum.Red).toEqual("Red");
expect(MyEnum.enum.Red).toEqual("Red");
});
test("infer enum", () => {
const MyEnum = z.enum(["Red", "Green", "Blue"]);
type MyEnum = z.infer<typeof MyEnum>;
util.assertEqual<MyEnum, "Red" | "Green" | "Blue">(true);
});
test("get options", () => {
expect(z.enum(["tuna", "trout"]).options).toEqual(["tuna", "trout"]);
});
test("readonly enum", () => {
const HTTP_SUCCESS = ["200", "201"] as const;
const arg = z.enum(HTTP_SUCCESS);
type arg = z.infer<typeof arg>;
util.assertEqual<arg, "200" | "201">(true);
arg.parse("201");
expect(() => arg.parse("202")).toThrow();
});
test("error params", () => {
const result = z.enum(["test"], { required_error: "REQUIRED" }).safeParse(undefined);
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual("REQUIRED");
}
});
test("extract/exclude", () => {
const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"] as const;
const FoodEnum = z.enum(foods);
const ItalianEnum = FoodEnum.extract(["Pasta", "Pizza"]);
const UnhealthyEnum = FoodEnum.exclude(["Salad"]);
const EmptyFoodEnum = FoodEnum.exclude(foods);
util.assertEqual<z.infer<typeof ItalianEnum>, "Pasta" | "Pizza">(true);
util.assertEqual<z.infer<typeof UnhealthyEnum>, "Pasta" | "Pizza" | "Tacos" | "Burgers">(true);
// @ts-expect-error TS2344
util.assertEqual<typeof EmptyFoodEnum, z.ZodEnum<[]>>(true);
util.assertEqual<z.infer<typeof EmptyFoodEnum>, never>(true);
});
test("error map in extract/exclude", () => {
const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"] as const;
const FoodEnum = z.enum(foods, {
errorMap: () => ({ message: "This is not food!" }),
});
const ItalianEnum = FoodEnum.extract(["Pasta", "Pizza"]);
const foodsError = FoodEnum.safeParse("Cucumbers");
const italianError = ItalianEnum.safeParse("Tacos");
if (!foodsError.success && !italianError.success) {
expect(foodsError.error.issues[0].message).toEqual(italianError.error.issues[0].message);
}
const UnhealthyEnum = FoodEnum.exclude(["Salad"], {
errorMap: () => ({ message: "This is not healthy food!" }),
});
const unhealthyError = UnhealthyEnum.safeParse("Salad");
if (!unhealthyError.success) {
expect(unhealthyError.error.issues[0].message).toEqual("This is not healthy food!");
}
});
test("readonly in ZodEnumDef", () => {
let _t!: z.ZodEnumDef<readonly ["a", "b"]>;
_t;
});

View file

@ -1,551 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { ZodError, ZodIssueCode } from "../ZodError.js";
import { ZodParsedType } from "../helpers/util.js";
test("error creation", () => {
const err1 = ZodError.create([]);
err1.addIssue({
code: ZodIssueCode.invalid_type,
expected: ZodParsedType.object,
received: ZodParsedType.string,
path: [],
message: "",
fatal: true,
});
err1.isEmpty;
const err2 = ZodError.create(err1.issues);
const err3 = new ZodError([]);
err3.addIssues(err1.issues);
err3.addIssue(err1.issues[0]);
err1.message;
err2.message;
err3.message;
});
const errorMap: z.ZodErrorMap = (error, ctx) => {
if (error.code === ZodIssueCode.invalid_type) {
if (error.expected === "string") {
return { message: "bad type!" };
}
}
if (error.code === ZodIssueCode.custom) {
return { message: `less-than-${error.params?.minimum}` };
}
return { message: ctx.defaultError };
};
test("type error with custom error map", () => {
try {
z.string().parse(234, { errorMap });
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues[0].code).toEqual(z.ZodIssueCode.invalid_type);
expect(zerr.issues[0].message).toEqual(`bad type!`);
}
});
test("refinement fail with params", () => {
try {
z.number()
.refine((val) => val >= 3, {
params: { minimum: 3 },
})
.parse(2, { errorMap });
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues[0].code).toEqual(z.ZodIssueCode.custom);
expect(zerr.issues[0].message).toEqual(`less-than-3`);
}
});
test("custom error with custom errormap", () => {
try {
z.string()
.refine((val) => val.length > 12, {
params: { minimum: 13 },
message: "override",
})
.parse("asdf", { errorMap });
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues[0].message).toEqual("override");
}
});
test("default error message", () => {
try {
z.number()
.refine((x) => x > 3)
.parse(2);
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual("Invalid input");
}
});
test("override error in refine", () => {
try {
z.number()
.refine((x) => x > 3, "override")
.parse(2);
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual("override");
}
});
test("override error in refinement", () => {
try {
z.number()
.refine((x) => x > 3, {
message: "override",
})
.parse(2);
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual("override");
}
});
test("array minimum", () => {
try {
z.array(z.string()).min(3, "tooshort").parse(["asdf", "qwer"]);
} catch (err) {
const zerr: ZodError = err as any;
expect(zerr.issues[0].code).toEqual(ZodIssueCode.too_small);
expect(zerr.issues[0].message).toEqual("tooshort");
}
try {
z.array(z.string()).min(3).parse(["asdf", "qwer"]);
} catch (err) {
const zerr: ZodError = err as any;
expect(zerr.issues[0].code).toEqual(ZodIssueCode.too_small);
expect(zerr.issues[0].message).toEqual(`Array must contain at least 3 element(s)`);
}
});
// implement test for semi-smart union logic that checks for type error on either left or right
// test("union smart errors", () => {
// // expect.assertions(2);
// const p1 = z
// .union([z.string(), z.number().refine((x) => x > 0)])
// .safeParse(-3.2);
// if (p1.success === true) throw new Error();
// expect(p1.success).toBe(false);
// expect(p1.error.issues[0].code).toEqual(ZodIssueCode.custom);
// const p2 = z.union([z.string(), z.number()]).safeParse(false);
// // .catch(err => expect(err.issues[0].code).toEqual(ZodIssueCode.invalid_union));
// if (p2.success === true) throw new Error();
// expect(p2.success).toBe(false);
// expect(p2.error.issues[0].code).toEqual(ZodIssueCode.invalid_union);
// });
test("custom path in custom error map", () => {
const schema = z.object({
items: z.array(z.string()).refine((data) => data.length > 3, {
path: ["items-too-few"],
}),
});
const errorMap: z.ZodErrorMap = (error) => {
expect(error.path.length).toBe(2);
return { message: "doesnt matter" };
};
const result = schema.safeParse({ items: ["first"] }, { errorMap });
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].path).toEqual(["items", "items-too-few"]);
}
});
test("error metadata from value", () => {
const dynamicRefine = z.string().refine(
(val) => val === val.toUpperCase(),
(val) => ({ params: { val } })
);
const result = dynamicRefine.safeParse("asdf");
expect(result.success).toEqual(false);
if (!result.success) {
const sub = result.error.issues[0];
expect(result.error.issues[0].code).toEqual("custom");
if (sub.code === "custom") {
expect(sub.params!.val).toEqual("asdf");
}
}
});
// test("don't call refine after validation failed", () => {
// const asdf = z
// .union([
// z.number(),
// z.string().transform(z.number(), (val) => {
// return parseFloat(val);
// }),
// ])
// .refine((v) => v >= 1);
// expect(() => asdf.safeParse("foo")).not.toThrow();
// });
test("root level formatting", () => {
const schema = z.string().email();
const result = schema.safeParse("asdfsdf");
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.format()._errors).toEqual(["Invalid email"]);
}
});
test("custom path", () => {
const schema = z
.object({
password: z.string(),
confirm: z.string(),
})
.refine((val) => val.confirm === val.password, { path: ["confirm"] });
const result = schema.safeParse({
password: "peanuts",
confirm: "qeanuts",
});
expect(result.success).toEqual(false);
if (!result.success) {
// nested errors
const error = result.error.format();
expect(error._errors).toEqual([]);
expect(error.password?._errors).toEqual(undefined);
expect(error.confirm?._errors).toEqual(["Invalid input"]);
}
});
test("custom path", () => {
const schema = z
.object({
password: z.string().min(6),
confirm: z.string().min(6),
})
.refine((val) => val.confirm === val.password);
const result = schema.safeParse({
password: "qwer",
confirm: "asdf",
});
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues.length).toEqual(3);
}
});
const schema = z.object({
inner: z.object({
name: z
.string()
.refine((val) => val.length > 5)
.array()
.refine((val) => val.length <= 1),
}),
});
test("no abort early on refinements", () => {
const invalidItem = {
inner: { name: ["aasd", "asdfasdfasfd"] },
};
const result1 = schema.safeParse(invalidItem);
expect(result1.success).toEqual(false);
if (!result1.success) {
expect(result1.error.issues.length).toEqual(2);
}
});
test("formatting", () => {
const invalidItem = {
inner: { name: ["aasd", "asdfasdfasfd"] },
};
const invalidArray = {
inner: { name: ["asdfasdf", "asdfasdfasfd"] },
};
const result1 = schema.safeParse(invalidItem);
const result2 = schema.safeParse(invalidArray);
expect(result1.success).toEqual(false);
expect(result2.success).toEqual(false);
if (!result1.success) {
const error = result1.error.format();
expect(error._errors).toEqual([]);
expect(error.inner?._errors).toEqual([]);
// expect(error.inner?.name?._errors).toEqual(["Invalid input"]);
// expect(error.inner?.name?.[0]._errors).toEqual(["Invalid input"]);
expect(error.inner?.name?.[1]).toEqual(undefined);
}
if (!result2.success) {
type FormattedError = z.inferFormattedError<typeof schema>;
const error: FormattedError = result2.error.format();
expect(error._errors).toEqual([]);
expect(error.inner?._errors).toEqual([]);
expect(error.inner?.name?._errors).toEqual(["Invalid input"]);
expect(error.inner?.name?.[0]).toEqual(undefined);
expect(error.inner?.name?.[1]).toEqual(undefined);
expect(error.inner?.name?.[2]).toEqual(undefined);
}
// test custom mapper
if (!result2.success) {
type FormattedError = z.inferFormattedError<typeof schema, number>;
const error: FormattedError = result2.error.format(() => 5);
expect(error._errors).toEqual([]);
expect(error.inner?._errors).toEqual([]);
expect(error.inner?.name?._errors).toEqual([5]);
}
});
test("formatting with nullable and optional fields", () => {
const nameSchema = z.string().refine((val) => val.length > 5);
const schema = z.object({
nullableObject: z.object({ name: nameSchema }).nullable(),
nullableArray: z.array(nameSchema).nullable(),
nullableTuple: z.tuple([nameSchema, nameSchema, z.number()]).nullable(),
optionalObject: z.object({ name: nameSchema }).optional(),
optionalArray: z.array(nameSchema).optional(),
optionalTuple: z.tuple([nameSchema, nameSchema, z.number()]).optional(),
});
const invalidItem = {
nullableObject: { name: "abcd" },
nullableArray: ["abcd"],
nullableTuple: ["abcd", "abcd", 1],
optionalObject: { name: "abcd" },
optionalArray: ["abcd"],
optionalTuple: ["abcd", "abcd", 1],
};
const result = schema.safeParse(invalidItem);
expect(result.success).toEqual(false);
if (!result.success) {
type FormattedError = z.inferFormattedError<typeof schema>;
const error: FormattedError = result.error.format();
expect(error._errors).toEqual([]);
expect(error.nullableObject?._errors).toEqual([]);
expect(error.nullableObject?.name?._errors).toEqual(["Invalid input"]);
expect(error.nullableArray?._errors).toEqual([]);
expect(error.nullableArray?.[0]?._errors).toEqual(["Invalid input"]);
expect(error.nullableTuple?._errors).toEqual([]);
expect(error.nullableTuple?.[0]?._errors).toEqual(["Invalid input"]);
expect(error.nullableTuple?.[1]?._errors).toEqual(["Invalid input"]);
expect(error.optionalObject?._errors).toEqual([]);
expect(error.optionalObject?.name?._errors).toEqual(["Invalid input"]);
expect(error.optionalArray?._errors).toEqual([]);
expect(error.optionalArray?.[0]?._errors).toEqual(["Invalid input"]);
expect(error.optionalTuple?._errors).toEqual([]);
expect(error.optionalTuple?.[0]?._errors).toEqual(["Invalid input"]);
expect(error.optionalTuple?.[1]?._errors).toEqual(["Invalid input"]);
}
});
const stringWithCustomError = z.string({
errorMap: (issue, ctx) => ({
message: issue.code === "invalid_type" ? (ctx.data ? "Invalid name" : "Name is required") : ctx.defaultError,
}),
});
test("schema-bound error map", () => {
const result = stringWithCustomError.safeParse(1234);
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual("Invalid name");
}
const result2 = stringWithCustomError.safeParse(undefined);
expect(result2.success).toEqual(false);
if (!result2.success) {
expect(result2.error.issues[0].message).toEqual("Name is required");
}
// support contextual override
const result3 = stringWithCustomError.safeParse(undefined, {
errorMap: () => ({ message: "OVERRIDE" }),
});
expect(result3.success).toEqual(false);
if (!result3.success) {
expect(result3.error.issues[0].message).toEqual("OVERRIDE");
}
});
test("overrideErrorMap", () => {
// support overrideErrorMap
z.setErrorMap(() => ({ message: "OVERRIDE" }));
const result4 = stringWithCustomError.min(10).safeParse("tooshort");
expect(result4.success).toEqual(false);
if (!result4.success) {
expect(result4.error.issues[0].message).toEqual("OVERRIDE");
}
z.setErrorMap(z.defaultErrorMap);
});
test("invalid and required", () => {
const str = z.string({
invalid_type_error: "Invalid name",
required_error: "Name is required",
});
const result1 = str.safeParse(1234);
expect(result1.success).toEqual(false);
if (!result1.success) {
expect(result1.error.issues[0].message).toEqual("Invalid name");
}
const result2 = str.safeParse(undefined);
expect(result2.success).toEqual(false);
if (!result2.success) {
expect(result2.error.issues[0].message).toEqual("Name is required");
}
});
test("Fallback to default required error", () => {
const str = z.string({
invalid_type_error: "Invalid name",
// required_error: "Name is required",
});
const result2 = str.safeParse(undefined);
expect(result2.success).toEqual(false);
if (!result2.success) {
expect(result2.error.issues[0].message).toEqual("Required");
}
});
test("invalid and required and errorMap", () => {
expect(() => {
return z.string({
invalid_type_error: "Invalid name",
required_error: "Name is required",
errorMap: () => ({ message: "OVERRIDE" }),
});
}).toThrow();
});
test("strict error message", () => {
const errorMsg = "Invalid object";
const obj = z.object({ x: z.string() }).strict(errorMsg);
const result = obj.safeParse({ x: "a", y: "b" });
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual(errorMsg);
}
});
test("enum error message, invalid enum elementstring", () => {
try {
z.enum(["Tuna", "Trout"]).parse("Salmon");
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual("Invalid enum value. Expected 'Tuna' | 'Trout', received 'Salmon'");
}
});
test("enum error message, invalid type", () => {
try {
z.enum(["Tuna", "Trout"]).parse(12);
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual("Expected 'Tuna' | 'Trout', received number");
}
});
test("nativeEnum default error message", () => {
enum Fish {
Tuna = "Tuna",
Trout = "Trout",
}
try {
z.nativeEnum(Fish).parse("Salmon");
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual("Invalid enum value. Expected 'Tuna' | 'Trout', received 'Salmon'");
}
});
test("literal default error message", () => {
try {
z.literal("Tuna").parse("Trout");
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual(`Invalid literal value, expected "Tuna"`);
}
});
test("literal bigint default error message", () => {
try {
z.literal(BigInt(12)).parse(BigInt(13));
} catch (err) {
const zerr: z.ZodError = err as any;
expect(zerr.issues.length).toEqual(1);
expect(zerr.issues[0].message).toEqual(`Invalid literal value, expected "12"`);
}
});
test("enum with message returns the custom error message", () => {
const schema = z.enum(["apple", "banana"], {
message: "the value provided is invalid",
});
const result1 = schema.safeParse("berries");
expect(result1.success).toEqual(false);
if (!result1.success) {
expect(result1.error.issues[0].message).toEqual("the value provided is invalid");
}
const result2 = schema.safeParse(undefined);
expect(result2.success).toEqual(false);
if (!result2.success) {
expect(result2.error.issues[0].message).toEqual("the value provided is invalid");
}
const result3 = schema.safeParse("banana");
expect(result3.success).toEqual(true);
const result4 = schema.safeParse(null);
expect(result4.success).toEqual(false);
if (!result4.success) {
expect(result4.error.issues[0].message).toEqual("the value provided is invalid");
}
});
test("when the message is falsy, it is used as is provided", () => {
const schema = z.string().max(1, { message: "" });
const result = schema.safeParse("asdf");
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].message).toEqual("");
}
});
// test("dont short circuit on continuable errors", () => {
// const user = z
// .object({
// password: z.string().min(6),
// confirm: z.string(),
// })
// .refine((data) => data.password === data.confirm, {
// message: "Passwords don't match",
// path: ["confirm"],
// });
// const result = user.safeParse({ password: "asdf", confirm: "qwer" });
// if (!result.success) {
// expect(result.error.issues.length).toEqual(2);
// }
// });

View file

@ -1,87 +0,0 @@
// @ts-ignore TS6133
import { test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
test("first party switch", () => {
const myType = z.string() as z.ZodFirstPartySchemaTypes;
const def = myType._def;
switch (def.typeName) {
case z.ZodFirstPartyTypeKind.ZodString:
break;
case z.ZodFirstPartyTypeKind.ZodNumber:
break;
case z.ZodFirstPartyTypeKind.ZodNaN:
break;
case z.ZodFirstPartyTypeKind.ZodBigInt:
break;
case z.ZodFirstPartyTypeKind.ZodBoolean:
break;
case z.ZodFirstPartyTypeKind.ZodDate:
break;
case z.ZodFirstPartyTypeKind.ZodUndefined:
break;
case z.ZodFirstPartyTypeKind.ZodNull:
break;
case z.ZodFirstPartyTypeKind.ZodAny:
break;
case z.ZodFirstPartyTypeKind.ZodUnknown:
break;
case z.ZodFirstPartyTypeKind.ZodNever:
break;
case z.ZodFirstPartyTypeKind.ZodVoid:
break;
case z.ZodFirstPartyTypeKind.ZodArray:
break;
case z.ZodFirstPartyTypeKind.ZodObject:
break;
case z.ZodFirstPartyTypeKind.ZodUnion:
break;
case z.ZodFirstPartyTypeKind.ZodDiscriminatedUnion:
break;
case z.ZodFirstPartyTypeKind.ZodIntersection:
break;
case z.ZodFirstPartyTypeKind.ZodTuple:
break;
case z.ZodFirstPartyTypeKind.ZodRecord:
break;
case z.ZodFirstPartyTypeKind.ZodMap:
break;
case z.ZodFirstPartyTypeKind.ZodSet:
break;
case z.ZodFirstPartyTypeKind.ZodFunction:
break;
case z.ZodFirstPartyTypeKind.ZodLazy:
break;
case z.ZodFirstPartyTypeKind.ZodLiteral:
break;
case z.ZodFirstPartyTypeKind.ZodEnum:
break;
case z.ZodFirstPartyTypeKind.ZodEffects:
break;
case z.ZodFirstPartyTypeKind.ZodNativeEnum:
break;
case z.ZodFirstPartyTypeKind.ZodOptional:
break;
case z.ZodFirstPartyTypeKind.ZodNullable:
break;
case z.ZodFirstPartyTypeKind.ZodDefault:
break;
case z.ZodFirstPartyTypeKind.ZodCatch:
break;
case z.ZodFirstPartyTypeKind.ZodPromise:
break;
case z.ZodFirstPartyTypeKind.ZodBranded:
break;
case z.ZodFirstPartyTypeKind.ZodPipeline:
break;
case z.ZodFirstPartyTypeKind.ZodSymbol:
break;
case z.ZodFirstPartyTypeKind.ZodReadonly:
break;
default:
util.assertNever(def);
}
});

View file

@ -1,21 +0,0 @@
// @ts-ignore TS6133
import { test } from "vitest";
import type { ZodFirstPartySchemaTypes, ZodFirstPartyTypeKind } from "zod/v3";
import { util } from "../helpers/util.js";
test("Identify missing [ZodFirstPartySchemaTypes]", () => {
type ZodFirstPartySchemaForType<T extends ZodFirstPartyTypeKind> = ZodFirstPartySchemaTypes extends infer Schema
? Schema extends { _def: { typeName: T } }
? Schema
: never
: never;
type ZodMappedTypes = {
[key in ZodFirstPartyTypeKind]: ZodFirstPartySchemaForType<key>;
};
type ZodFirstPartySchemaTypesMissingFromUnion = keyof {
[key in keyof ZodMappedTypes as ZodMappedTypes[key] extends { _def: never } ? key : never]: unknown;
};
util.assertEqual<ZodFirstPartySchemaTypesMissingFromUnion, never>(true);
});

View file

@ -1,257 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
const args1 = z.tuple([z.string()]);
const returns1 = z.number();
const func1 = z.function(args1, returns1);
test("function parsing", () => {
const parsed = func1.parse((arg: any) => arg.length);
parsed("asdf");
});
test("parsed function fail 1", () => {
const parsed = func1.parse((x: string) => x);
expect(() => parsed("asdf")).toThrow();
});
test("parsed function fail 2", () => {
const parsed = func1.parse((x: string) => x);
expect(() => parsed(13 as any)).toThrow();
});
test("function inference 1", () => {
type func1 = z.TypeOf<typeof func1>;
util.assertEqual<func1, (k: string) => number>(true);
});
test("method parsing", () => {
const methodObject = z.object({
property: z.number(),
method: z.function().args(z.string()).returns(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().args(z.string()).returns(z.promise(z.number())),
});
const methodInstance = {
property: 3,
method: async function (s: string) {
return s.length + this.property;
},
};
const parsed = methodObject.parse(methodInstance);
expect(await parsed.method("length=8")).toBe(11); // 8 length + 3 property
});
test("args method", () => {
const t1 = z.function();
type t1 = z.infer<typeof t1>;
util.assertEqual<t1, (...args_1: unknown[]) => unknown>(true);
const t2 = t1.args(z.string());
type t2 = z.infer<typeof t2>;
util.assertEqual<t2, (arg: string, ...args_1: unknown[]) => unknown>(true);
const t3 = t2.returns(z.boolean());
type t3 = z.infer<typeof t3>;
util.assertEqual<t3, (arg: string, ...args_1: unknown[]) => boolean>(true);
});
const args2 = z.tuple([
z.object({
f1: z.number(),
f2: z.string().nullable(),
f3: z.array(z.boolean().optional()).optional(),
}),
]);
const returns2 = z.union([z.string(), z.number()]);
const func2 = z.function(args2, returns2);
test("function inference 2", () => {
type func2 = z.TypeOf<typeof func2>;
util.assertEqual<
func2,
(arg: {
f1: number;
f2: string | null;
f3?: (boolean | undefined)[] | undefined;
}) => string | number
>(true);
});
test("valid function run", () => {
const validFunc2Instance = func2.validate((_x) => {
return "adf" as any;
});
const checker = () => {
validFunc2Instance({
f1: 21,
f2: "asdf",
f3: [true, false],
});
};
checker();
});
test("input validation error", () => {
const invalidFuncInstance = func2.validate((_x) => {
return "adf" as any;
});
const checker = () => {
invalidFuncInstance("Invalid_input" as any);
};
expect(checker).toThrow();
});
test("output validation error", () => {
const invalidFuncInstance = func2.validate((_x) => {
return ["this", "is", "not", "valid", "output"] as any;
});
const checker = () => {
invalidFuncInstance({
f1: 21,
f2: "asdf",
f3: [true, false],
});
};
expect(checker).toThrow();
});
z.function(z.tuple([z.string()])).args()._def.args;
test("special function error codes", () => {
const checker = z.function(z.tuple([z.string()]), z.boolean()).implement((arg) => {
return arg.length as any;
});
try {
checker("12" as any);
} catch (err) {
const zerr = err as z.ZodError;
const first = zerr.issues[0];
if (first.code !== z.ZodIssueCode.invalid_return_type) throw new Error();
expect(first.returnTypeError).toBeInstanceOf(z.ZodError);
}
try {
checker(12 as any);
} catch (err) {
const zerr = err as z.ZodError;
const first = zerr.issues[0];
if (first.code !== z.ZodIssueCode.invalid_arguments) throw new Error();
expect(first.argumentsError).toBeInstanceOf(z.ZodError);
}
});
test("function with async refinements", async () => {
const func = z
.function()
.args(z.string().refine(async (val) => val.length > 10))
.returns(z.promise(z.number().refine(async (val) => val > 10)))
.implement(async (val) => {
return val.length;
});
const results = [];
try {
await func("asdfasdf");
results.push("success");
} catch (_err) {
results.push("fail");
}
try {
await func("asdflkjasdflkjsf");
results.push("success");
} catch (_err) {
results.push("fail");
}
expect(results).toEqual(["fail", "success"]);
});
test("non async function with async refinements should fail", async () => {
const func = z
.function()
.args(z.string().refine(async (val) => val.length > 10))
.returns(z.number().refine(async (val) => val > 10))
.implement((val) => {
return val.length;
});
const results = [];
try {
await func("asdasdfasdffasdf");
results.push("success");
} catch (_err) {
results.push("fail");
}
expect(results).toEqual(["fail"]);
});
test("allow extra parameters", () => {
const maxLength5 = z
.function()
.args(z.string())
.returns(z.boolean())
.implement((str, _arg, _qewr) => {
return str.length <= 5;
});
const filteredList = ["apple", "orange", "pear", "banana", "strawberry"].filter(maxLength5);
expect(filteredList.length).toEqual(2);
});
test("params and returnType getters", () => {
const func = z.function().args(z.string()).returns(z.string());
func.parameters().items[0].parse("asdf");
func.returnType().parse("asdf");
});
test("inference with transforms", () => {
const funcSchema = z
.function()
.args(z.string().transform((val) => val.length))
.returns(z.object({ val: z.number() }));
const myFunc = funcSchema.implement((val) => {
return { val, extra: "stuff" };
});
myFunc("asdf");
util.assertEqual<typeof myFunc, (arg: string, ...args_1: unknown[]) => { val: number; extra: string }>(true);
});
test("fallback to OuterTypeOfFunction", () => {
const funcSchema = z
.function()
.args(z.string().transform((val) => val.length))
.returns(z.object({ arg: z.number() }).transform((val) => val.arg));
const myFunc = funcSchema.implement((val) => {
return { arg: val, arg2: false };
});
util.assertEqual<typeof myFunc, (arg: string, ...args_1: unknown[]) => number>(true);
});

View file

@ -1,48 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
test("generics", () => {
async function stripOuter<TData extends z.ZodTypeAny>(schema: TData, data: unknown) {
return z
.object({
nested: schema, // as z.ZodTypeAny,
})
.transform((data) => {
return data.nested!;
})
.parse({ nested: data });
}
const result = stripOuter(z.object({ a: z.string() }), { a: "asdf" });
util.assertEqual<typeof result, Promise<{ a: string }>>(true);
});
// test("assignability", () => {
// const createSchemaAndParse = <K extends string, VS extends z.ZodString>(
// key: K,
// valueSchema: VS,
// data: unknown
// ) => {
// const schema = z.object({
// [key]: valueSchema,
// } as { [k in K]: VS });
// return { [key]: valueSchema };
// const parsed = schema.parse(data);
// return parsed;
// // const inferred: z.infer<z.ZodObject<{ [k in K]: VS }>> = parsed;
// // return inferred;
// };
// const parsed = createSchemaAndParse("foo", z.string(), { foo: "" });
// util.assertEqual<typeof parsed, { foo: string }>(true);
// });
test("nested no undefined", () => {
const inner = z.string().or(z.array(z.string()));
const outer = z.object({ inner });
type outerSchema = z.infer<typeof outer>;
z.util.assertEqual<outerSchema, { inner: string | string[] }>(true);
expect(outer.safeParse({ inner: undefined }).success).toEqual(false);
});

View file

@ -1,37 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
test("instanceof", async () => {
class Test {}
class Subtest extends Test {}
abstract class AbstractBar {
constructor(public val: string) {}
}
class Bar extends AbstractBar {}
const TestSchema = z.instanceof(Test);
const SubtestSchema = z.instanceof(Subtest);
const AbstractSchema = z.instanceof(AbstractBar);
const BarSchema = z.instanceof(Bar);
TestSchema.parse(new Test());
TestSchema.parse(new Subtest());
SubtestSchema.parse(new Subtest());
AbstractSchema.parse(new Bar("asdf"));
const bar = BarSchema.parse(new Bar("asdf"));
expect(bar.val).toEqual("asdf");
await expect(() => SubtestSchema.parse(new Test())).toThrow(/Input not instance of Subtest/);
await expect(() => TestSchema.parse(12)).toThrow(/Input not instance of Test/);
util.assertEqual<Test, z.infer<typeof TestSchema>>(true);
});
test("instanceof fatal", () => {
const schema = z.instanceof(Date).refine((d) => d.toString());
const res = schema.safeParse(null);
expect(res.success).toBe(false);
});

View file

@ -1,110 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
test("object intersection", () => {
const BaseTeacher = z.object({
subjects: z.array(z.string()),
});
const HasID = z.object({ id: z.string() });
const Teacher = z.intersection(BaseTeacher.passthrough(), HasID); // BaseTeacher.merge(HasID);
const data = {
subjects: ["math"],
id: "asdfasdf",
};
expect(Teacher.parse(data)).toEqual(data);
expect(() => Teacher.parse({ subject: data.subjects })).toThrow();
expect(Teacher.parse({ ...data, extra: 12 })).toEqual({ ...data, extra: 12 });
expect(() => z.intersection(BaseTeacher.strict(), HasID).parse({ ...data, extra: 12 })).toThrow();
});
test("deep intersection", () => {
const Animal = z.object({
properties: z.object({
is_animal: z.boolean(),
}),
});
const Cat = z
.object({
properties: z.object({
jumped: z.boolean(),
}),
})
.and(Animal);
type _Cat = z.infer<typeof Cat>;
// const cat:Cat = 'asdf' as any;
const cat = Cat.parse({ properties: { is_animal: true, jumped: true } });
expect(cat.properties).toEqual({ is_animal: true, jumped: true });
});
test("deep intersection of arrays", async () => {
const Author = z.object({
posts: z.array(
z.object({
post_id: z.number(),
})
),
});
const Registry = z
.object({
posts: z.array(
z.object({
title: z.string(),
})
),
})
.and(Author);
const posts = [
{ post_id: 1, title: "Novels" },
{ post_id: 2, title: "Fairy tales" },
];
const cat = Registry.parse({ posts });
expect(cat.posts).toEqual(posts);
const asyncCat = await Registry.parseAsync({ posts });
expect(asyncCat.posts).toEqual(posts);
});
test("invalid intersection types", async () => {
const numberIntersection = z.intersection(
z.number(),
z.number().transform((x) => x + 1)
);
const syncResult = numberIntersection.safeParse(1234);
expect(syncResult.success).toEqual(false);
if (!syncResult.success) {
expect(syncResult.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_intersection_types);
}
const asyncResult = await numberIntersection.spa(1234);
expect(asyncResult.success).toEqual(false);
if (!asyncResult.success) {
expect(asyncResult.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_intersection_types);
}
});
test("invalid array merge", async () => {
const stringArrInt = z.intersection(
z.string().array(),
z
.string()
.array()
.transform((val) => [...val, "asdf"])
);
const syncResult = stringArrInt.safeParse(["asdf", "qwer"]);
expect(syncResult.success).toEqual(false);
if (!syncResult.success) {
expect(syncResult.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_intersection_types);
}
const asyncResult = await stringArrInt.spa(["asdf", "qwer"]);
expect(asyncResult.success).toEqual(false);
if (!asyncResult.success) {
expect(asyncResult.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_intersection_types);
}
});

View file

@ -1,76 +0,0 @@
import * as z from "zod/v3";
export const filePath = __filename;
// z.object()
export const Test = z.object({
f1: z.number(),
});
export type Test = z.infer<typeof Test>;
export const instanceOfTest: Test = {
f1: 1,
};
// z.object().merge()
export const TestMerge = z
.object({
f2: z.string().optional(),
})
.merge(Test);
export type TestMerge = z.infer<typeof TestMerge>;
export const instanceOfTestMerge: TestMerge = {
f1: 1,
f2: "string",
};
// z.union()
export const TestUnion = z.union([
z.object({
f2: z.string().optional(),
}),
Test,
]);
export type TestUnion = z.infer<typeof TestUnion>;
export const instanceOfTestUnion: TestUnion = {
f1: 1,
f2: "string",
};
// z.object().partial()
export const TestPartial = Test.partial();
export type TestPartial = z.infer<typeof TestPartial>;
export const instanceOfTestPartial: TestPartial = {
f1: 1,
};
// z.object().pick()
export const TestPick = TestMerge.pick({ f1: true });
export type TestPick = z.infer<typeof TestPick>;
export const instanceOfTestPick: TestPick = {
f1: 1,
};
// z.object().omit()
export const TestOmit = TestMerge.omit({ f2: true });
export type TestOmit = z.infer<typeof TestOmit>;
export const instanceOfTestOmit: TestOmit = {
f1: 1,
};

View file

@ -1,207 +0,0 @@
import { test } from "vitest";
// import path from "path";
// import { Node, Project, SyntaxKind } from "ts-morph";
// import { filePath } from "./language-server.source";
// The following tool is helpful for understanding the TypeScript AST associated with these tests:
// https://ts-ast-viewer.com/ (just copy the contents of language-server.source into the viewer)
test("", () => {});
// describe("Executing Go To Definition (and therefore Find Usages and Rename Refactoring) using an IDE works on inferred object properties", () => {
// // Compile file developmentEnvironment.source
// const project = new Project({
// tsConfigFilePath: path.join(__dirname, "..", "..", "tsconfig.json"),
// skipAddingFilesFromTsConfig: true,
// });
// const sourceFile = project.addSourceFileAtPath(filePath);
// test("works for object properties inferred from z.object()", () => {
// // Find usage of Test.f1 property
// const instanceVariable =
// sourceFile.getVariableDeclarationOrThrow("instanceOfTest");
// const propertyBeingAssigned = getPropertyBeingAssigned(
// instanceVariable,
// "f1"
// );
// // Find definition of Test.f1 property
// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
// SyntaxKind.VariableDeclaration
// );
// // Assert that find definition returned the Zod definition of Test
// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
// expect(parentOfProperty?.getName()).toEqual("Test");
// });
// // test("works for first object properties inferred from z.object().merge()", () => {
// // // Find usage of TestMerge.f1 property
// // const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
// // "instanceOfTestMerge"
// // );
// // const propertyBeingAssigned = getPropertyBeingAssigned(
// // instanceVariable,
// // "f1"
// // );
// // // Find definition of TestMerge.f1 property
// // const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
// // const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
// // SyntaxKind.VariableDeclaration
// // );
// // // Assert that find definition returned the Zod definition of Test
// // expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
// // expect(parentOfProperty?.getName()).toEqual("Test");
// // });
// // test("works for second object properties inferred from z.object().merge()", () => {
// // // Find usage of TestMerge.f2 property
// // const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
// // "instanceOfTestMerge"
// // );
// // const propertyBeingAssigned = getPropertyBeingAssigned(
// // instanceVariable,
// // "f2"
// // );
// // // Find definition of TestMerge.f2 property
// // const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
// // const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
// // SyntaxKind.VariableDeclaration
// // );
// // // Assert that find definition returned the Zod definition of TestMerge
// // expect(definitionOfProperty?.getText()).toEqual(
// // "f2: z.string().optional()"
// // );
// // expect(parentOfProperty?.getName()).toEqual("TestMerge");
// // });
// test("works for first object properties inferred from z.union()", () => {
// // Find usage of TestUnion.f1 property
// const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
// "instanceOfTestUnion"
// );
// const propertyBeingAssigned = getPropertyBeingAssigned(
// instanceVariable,
// "f1"
// );
// // Find definition of TestUnion.f1 property
// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
// SyntaxKind.VariableDeclaration
// );
// // Assert that find definition returned the Zod definition of Test
// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
// expect(parentOfProperty?.getName()).toEqual("Test");
// });
// test("works for second object properties inferred from z.union()", () => {
// // Find usage of TestUnion.f2 property
// const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
// "instanceOfTestUnion"
// );
// const propertyBeingAssigned = getPropertyBeingAssigned(
// instanceVariable,
// "f2"
// );
// // Find definition of TestUnion.f2 property
// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
// SyntaxKind.VariableDeclaration
// );
// // Assert that find definition returned the Zod definition of TestUnion
// expect(definitionOfProperty?.getText()).toEqual(
// "f2: z.string().optional()"
// );
// expect(parentOfProperty?.getName()).toEqual("TestUnion");
// });
// test("works for object properties inferred from z.object().partial()", () => {
// // Find usage of TestPartial.f1 property
// const instanceVariable = sourceFile.getVariableDeclarationOrThrow(
// "instanceOfTestPartial"
// );
// const propertyBeingAssigned = getPropertyBeingAssigned(
// instanceVariable,
// "f1"
// );
// // Find definition of TestPartial.f1 property
// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
// SyntaxKind.VariableDeclaration
// );
// // Assert that find definition returned the Zod definition of Test
// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
// expect(parentOfProperty?.getName()).toEqual("Test");
// });
// test("works for object properties inferred from z.object().pick()", () => {
// // Find usage of TestPick.f1 property
// const instanceVariable =
// sourceFile.getVariableDeclarationOrThrow("instanceOfTestPick");
// const propertyBeingAssigned = getPropertyBeingAssigned(
// instanceVariable,
// "f1"
// );
// // Find definition of TestPick.f1 property
// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
// SyntaxKind.VariableDeclaration
// );
// // Assert that find definition returned the Zod definition of Test
// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
// expect(parentOfProperty?.getName()).toEqual("Test");
// });
// test("works for object properties inferred from z.object().omit()", () => {
// // Find usage of TestOmit.f1 property
// const instanceVariable =
// sourceFile.getVariableDeclarationOrThrow("instanceOfTestOmit");
// const propertyBeingAssigned = getPropertyBeingAssigned(
// instanceVariable,
// "f1"
// );
// // Find definition of TestOmit.f1 property
// const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0];
// const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind(
// SyntaxKind.VariableDeclaration
// );
// // Assert that find definition returned the Zod definition of Test
// expect(definitionOfProperty?.getText()).toEqual("f1: z.number()");
// expect(parentOfProperty?.getName()).toEqual("Test");
// });
// });
// const getPropertyBeingAssigned = (node: Node, name: string) => {
// const propertyAssignment = node.forEachDescendant((descendent) =>
// Node.isPropertyAssignment(descendent) && descendent.getName() == name
// ? descendent
// : undefined
// );
// if (propertyAssignment == null)
// fail(`Could not find property assignment with name ${name}`);
// const propertyLiteral = propertyAssignment.getFirstDescendantByKind(
// SyntaxKind.Identifier
// );
// if (propertyLiteral == null)
// fail(`Could not find property literal with name ${name}`);
// return propertyLiteral;
// };

View file

@ -1,36 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
const literalTuna = z.literal("tuna");
const literalFortyTwo = z.literal(42);
const literalTrue = z.literal(true);
const terrificSymbol = Symbol("terrific");
const literalTerrificSymbol = z.literal(terrificSymbol);
test("passing validations", () => {
literalTuna.parse("tuna");
literalFortyTwo.parse(42);
literalTrue.parse(true);
literalTerrificSymbol.parse(terrificSymbol);
});
test("failing validations", () => {
expect(() => literalTuna.parse("shark")).toThrow();
expect(() => literalFortyTwo.parse(43)).toThrow();
expect(() => literalTrue.parse(false)).toThrow();
expect(() => literalTerrificSymbol.parse(Symbol("terrific"))).toThrow();
});
test("invalid_literal should have `received` field with data", () => {
const data = "shark";
const result = literalTuna.safeParse(data);
if (!result.success) {
const issue = result.error.issues[0];
if (issue.code === "invalid_literal") {
expect(issue.received).toBe(data);
}
}
});

View file

@ -1,110 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { ZodIssueCode } from "zod/v3";
import { util } from "../helpers/util.js";
const stringMap = z.map(z.string(), z.string());
type stringMap = z.infer<typeof stringMap>;
test("type inference", () => {
util.assertEqual<stringMap, Map<string, string>>(true);
});
test("valid parse", () => {
const result = stringMap.safeParse(
new Map([
["first", "foo"],
["second", "bar"],
])
);
expect(result.success).toEqual(true);
if (result.success) {
expect(result.data.has("first")).toEqual(true);
expect(result.data.has("second")).toEqual(true);
expect(result.data.get("first")).toEqual("foo");
expect(result.data.get("second")).toEqual("bar");
}
});
test("valid parse async", async () => {
const result = await stringMap.spa(
new Map([
["first", "foo"],
["second", "bar"],
])
);
expect(result.success).toEqual(true);
if (result.success) {
expect(result.data.has("first")).toEqual(true);
expect(result.data.has("second")).toEqual(true);
expect(result.data.get("first")).toEqual("foo");
expect(result.data.get("second")).toEqual("bar");
}
});
test("throws when a Set is given", () => {
const result = stringMap.safeParse(new Set([]));
expect(result.success).toEqual(false);
if (result.success === false) {
expect(result.error.issues.length).toEqual(1);
expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type);
}
});
test("throws when the given map has invalid key and invalid input", () => {
const result = stringMap.safeParse(new Map([[42, Symbol()]]));
expect(result.success).toEqual(false);
if (result.success === false) {
expect(result.error.issues.length).toEqual(2);
expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type);
expect(result.error.issues[0].path).toEqual([0, "key"]);
expect(result.error.issues[1].code).toEqual(ZodIssueCode.invalid_type);
expect(result.error.issues[1].path).toEqual([0, "value"]);
}
});
test("throws when the given map has multiple invalid entries", () => {
// const result = stringMap.safeParse(new Map([[42, Symbol()]]));
const result = stringMap.safeParse(
new Map([
[1, "foo"],
["bar", 2],
] as [any, any][]) as Map<any, any>
);
// const result = stringMap.safeParse(new Map([[42, Symbol()]]));
expect(result.success).toEqual(false);
if (result.success === false) {
expect(result.error.issues.length).toEqual(2);
expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type);
expect(result.error.issues[0].path).toEqual([0, "key"]);
expect(result.error.issues[1].code).toEqual(ZodIssueCode.invalid_type);
expect(result.error.issues[1].path).toEqual([1, "value"]);
}
});
test("dirty", async () => {
const map = z.map(
z.string().refine((val) => val === val.toUpperCase(), {
message: "Keys must be uppercase",
}),
z.string()
);
const result = await map.spa(
new Map([
["first", "foo"],
["second", "bar"],
])
);
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues.length).toEqual(2);
expect(result.error.issues[0].code).toEqual(z.ZodIssueCode.custom);
expect(result.error.issues[0].message).toEqual("Keys must be uppercase");
expect(result.error.issues[1].code).toEqual(z.ZodIssueCode.custom);
expect(result.error.issues[1].message).toEqual("Keys must be uppercase");
}
});

View file

@ -1,4 +0,0 @@
// @ts-ignore TS6133
import { test } from "vitest";
test("masking test", () => {});

View file

@ -1,19 +0,0 @@
// @ts-ignore TS6133
import { test } from "vitest";
import { Mocker } from "./Mocker.js";
test("mocker", () => {
const mocker = new Mocker();
mocker.string;
mocker.number;
mocker.boolean;
mocker.null;
mocker.undefined;
mocker.stringOptional;
mocker.stringNullable;
mocker.numberOptional;
mocker.numberNullable;
mocker.booleanOptional;
mocker.booleanNullable;
});

View file

@ -1,21 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
const schema = z.nan();
test("passing validations", () => {
schema.parse(Number.NaN);
schema.parse(Number("Not a number"));
});
test("failing validations", () => {
expect(() => schema.parse(5)).toThrow();
expect(() => schema.parse("John")).toThrow();
expect(() => schema.parse(true)).toThrow();
expect(() => schema.parse(null)).toThrow();
expect(() => schema.parse(undefined)).toThrow();
expect(() => schema.parse({})).toThrow();
expect(() => schema.parse([])).toThrow();
});

View file

@ -1,87 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
test("nativeEnum test with consts", () => {
const Fruits: { Apple: "apple"; Banana: "banana" } = {
Apple: "apple",
Banana: "banana",
};
const fruitEnum = z.nativeEnum(Fruits);
type fruitEnum = z.infer<typeof fruitEnum>;
fruitEnum.parse("apple");
fruitEnum.parse("banana");
fruitEnum.parse(Fruits.Apple);
fruitEnum.parse(Fruits.Banana);
util.assertEqual<fruitEnum, "apple" | "banana">(true);
});
test("nativeEnum test with real enum", () => {
enum Fruits {
Apple = "apple",
Banana = "banana",
}
// @ts-ignore
const fruitEnum = z.nativeEnum(Fruits);
type fruitEnum = z.infer<typeof fruitEnum>;
fruitEnum.parse("apple");
fruitEnum.parse("banana");
fruitEnum.parse(Fruits.Apple);
fruitEnum.parse(Fruits.Banana);
util.assertIs<fruitEnum extends Fruits ? true : false>(true);
});
test("nativeEnum test with const with numeric keys", () => {
const FruitValues = {
Apple: 10,
Banana: 20,
// @ts-ignore
} as const;
const fruitEnum = z.nativeEnum(FruitValues);
type fruitEnum = z.infer<typeof fruitEnum>;
fruitEnum.parse(10);
fruitEnum.parse(20);
fruitEnum.parse(FruitValues.Apple);
fruitEnum.parse(FruitValues.Banana);
util.assertEqual<fruitEnum, 10 | 20>(true);
});
test("from enum", () => {
enum Fruits {
Cantaloupe = 0,
Apple = "apple",
Banana = "banana",
}
const FruitEnum = z.nativeEnum(Fruits as any);
type _FruitEnum = z.infer<typeof FruitEnum>;
FruitEnum.parse(Fruits.Cantaloupe);
FruitEnum.parse(Fruits.Apple);
FruitEnum.parse("apple");
FruitEnum.parse(0);
expect(() => FruitEnum.parse(1)).toThrow();
expect(() => FruitEnum.parse("Apple")).toThrow();
expect(() => FruitEnum.parse("Cantaloupe")).toThrow();
});
test("from const", () => {
const Greek = {
Alpha: "a",
Beta: "b",
Gamma: 3,
// @ts-ignore
} as const;
const GreekEnum = z.nativeEnum(Greek);
type _GreekEnum = z.infer<typeof GreekEnum>;
GreekEnum.parse("a");
GreekEnum.parse("b");
GreekEnum.parse(3);
expect(() => GreekEnum.parse("v")).toThrow();
expect(() => GreekEnum.parse("Alpha")).toThrow();
expect(() => GreekEnum.parse(2)).toThrow();
expect(GreekEnum.enum.Alpha).toEqual("a");
});

View file

@ -1,42 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
function checkErrors(a: z.ZodTypeAny, bad: any) {
let expected: any;
try {
a.parse(bad);
} catch (error) {
expected = (error as z.ZodError).formErrors;
}
try {
a.nullable().parse(bad);
} catch (error) {
expect((error as z.ZodError).formErrors).toEqual(expected);
}
}
test("Should have error messages appropriate for the underlying type", () => {
checkErrors(z.string().min(2), 1);
z.string().min(2).nullable().parse(null);
checkErrors(z.number().gte(2), 1);
z.number().gte(2).nullable().parse(null);
checkErrors(z.boolean(), "");
z.boolean().nullable().parse(null);
checkErrors(z.null(), null);
z.null().nullable().parse(null);
checkErrors(z.null(), {});
z.null().nullable().parse(null);
checkErrors(z.object({}), 1);
z.object({}).nullable().parse(null);
checkErrors(z.tuple([]), 1);
z.tuple([]).nullable().parse(null);
checkErrors(z.unknown(), 1);
z.unknown().nullable().parse(null);
});
test("unwrap", () => {
const unwrapped = z.string().nullable().unwrap();
expect(unwrapped).toBeInstanceOf(z.ZodString);
});

View file

@ -1,176 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
const gtFive = z.number().gt(5);
const gteFive = z.number().gte(-5).gte(5);
const minFive = z.number().min(0).min(5);
const ltFive = z.number().lte(10).lt(5);
const lteFive = z.number().lte(5);
const maxFive = z.number().max(10).max(5);
const intNum = z.number().int();
const positive = z.number().positive();
const negative = z.number().negative();
const nonpositive = z.number().nonpositive();
const nonnegative = z.number().nonnegative();
const multipleOfFive = z.number().multipleOf(5);
const multipleOfNegativeFive = z.number().multipleOf(-5);
const finite = z.number().finite();
const safe = z.number().safe();
const stepPointOne = z.number().step(0.1);
const stepPointZeroZeroZeroOne = z.number().step(0.0001);
const stepSixPointFour = z.number().step(6.4);
test("passing validations", () => {
z.number().parse(1);
z.number().parse(1.5);
z.number().parse(0);
z.number().parse(-1.5);
z.number().parse(-1);
z.number().parse(Number.POSITIVE_INFINITY);
z.number().parse(Number.NEGATIVE_INFINITY);
gtFive.parse(6);
gtFive.parse(Number.POSITIVE_INFINITY);
gteFive.parse(5);
gteFive.parse(Number.POSITIVE_INFINITY);
minFive.parse(5);
minFive.parse(Number.POSITIVE_INFINITY);
ltFive.parse(4);
ltFive.parse(Number.NEGATIVE_INFINITY);
lteFive.parse(5);
lteFive.parse(Number.NEGATIVE_INFINITY);
maxFive.parse(5);
maxFive.parse(Number.NEGATIVE_INFINITY);
intNum.parse(4);
positive.parse(1);
positive.parse(Number.POSITIVE_INFINITY);
negative.parse(-1);
negative.parse(Number.NEGATIVE_INFINITY);
nonpositive.parse(0);
nonpositive.parse(-1);
nonpositive.parse(Number.NEGATIVE_INFINITY);
nonnegative.parse(0);
nonnegative.parse(1);
nonnegative.parse(Number.POSITIVE_INFINITY);
multipleOfFive.parse(15);
multipleOfFive.parse(-15);
multipleOfNegativeFive.parse(-15);
multipleOfNegativeFive.parse(15);
finite.parse(123);
safe.parse(Number.MIN_SAFE_INTEGER);
safe.parse(Number.MAX_SAFE_INTEGER);
stepPointOne.parse(6);
stepPointOne.parse(6.1);
stepPointOne.parse(6.1);
stepSixPointFour.parse(12.8);
stepPointZeroZeroZeroOne.parse(3.01);
});
test("failing validations", () => {
expect(() => ltFive.parse(5)).toThrow();
expect(() => lteFive.parse(6)).toThrow();
expect(() => maxFive.parse(6)).toThrow();
expect(() => gtFive.parse(5)).toThrow();
expect(() => gteFive.parse(4)).toThrow();
expect(() => minFive.parse(4)).toThrow();
expect(() => intNum.parse(3.14)).toThrow();
expect(() => positive.parse(0)).toThrow();
expect(() => positive.parse(-1)).toThrow();
expect(() => negative.parse(0)).toThrow();
expect(() => negative.parse(1)).toThrow();
expect(() => nonpositive.parse(1)).toThrow();
expect(() => nonnegative.parse(-1)).toThrow();
expect(() => multipleOfFive.parse(7.5)).toThrow();
expect(() => multipleOfFive.parse(-7.5)).toThrow();
expect(() => multipleOfNegativeFive.parse(-7.5)).toThrow();
expect(() => multipleOfNegativeFive.parse(7.5)).toThrow();
expect(() => finite.parse(Number.POSITIVE_INFINITY)).toThrow();
expect(() => finite.parse(Number.NEGATIVE_INFINITY)).toThrow();
expect(() => safe.parse(Number.MIN_SAFE_INTEGER - 1)).toThrow();
expect(() => safe.parse(Number.MAX_SAFE_INTEGER + 1)).toThrow();
expect(() => stepPointOne.parse(6.11)).toThrow();
expect(() => stepPointOne.parse(6.1000000001)).toThrow();
expect(() => stepSixPointFour.parse(6.41)).toThrow();
});
test("parse NaN", () => {
expect(() => z.number().parse(Number.NaN)).toThrow();
});
test("min max getters", () => {
expect(z.number().minValue).toBeNull;
expect(ltFive.minValue).toBeNull;
expect(lteFive.minValue).toBeNull;
expect(maxFive.minValue).toBeNull;
expect(negative.minValue).toBeNull;
expect(nonpositive.minValue).toBeNull;
expect(intNum.minValue).toBeNull;
expect(multipleOfFive.minValue).toBeNull;
expect(finite.minValue).toBeNull;
expect(gtFive.minValue).toEqual(5);
expect(gteFive.minValue).toEqual(5);
expect(minFive.minValue).toEqual(5);
expect(minFive.min(10).minValue).toEqual(10);
expect(positive.minValue).toEqual(0);
expect(nonnegative.minValue).toEqual(0);
expect(safe.minValue).toEqual(Number.MIN_SAFE_INTEGER);
expect(z.number().maxValue).toBeNull;
expect(gtFive.maxValue).toBeNull;
expect(gteFive.maxValue).toBeNull;
expect(minFive.maxValue).toBeNull;
expect(positive.maxValue).toBeNull;
expect(nonnegative.maxValue).toBeNull;
expect(intNum.minValue).toBeNull;
expect(multipleOfFive.minValue).toBeNull;
expect(finite.minValue).toBeNull;
expect(ltFive.maxValue).toEqual(5);
expect(lteFive.maxValue).toEqual(5);
expect(maxFive.maxValue).toEqual(5);
expect(maxFive.max(1).maxValue).toEqual(1);
expect(negative.maxValue).toEqual(0);
expect(nonpositive.maxValue).toEqual(0);
expect(safe.maxValue).toEqual(Number.MAX_SAFE_INTEGER);
});
test("int getter", () => {
expect(z.number().isInt).toEqual(false);
expect(z.number().multipleOf(1.5).isInt).toEqual(false);
expect(gtFive.isInt).toEqual(false);
expect(gteFive.isInt).toEqual(false);
expect(minFive.isInt).toEqual(false);
expect(positive.isInt).toEqual(false);
expect(nonnegative.isInt).toEqual(false);
expect(finite.isInt).toEqual(false);
expect(ltFive.isInt).toEqual(false);
expect(lteFive.isInt).toEqual(false);
expect(maxFive.isInt).toEqual(false);
expect(negative.isInt).toEqual(false);
expect(nonpositive.isInt).toEqual(false);
expect(safe.isInt).toEqual(false);
expect(intNum.isInt).toEqual(true);
expect(multipleOfFive.isInt).toEqual(true);
});
test("finite getter", () => {
expect(z.number().isFinite).toEqual(false);
expect(gtFive.isFinite).toEqual(false);
expect(gteFive.isFinite).toEqual(false);
expect(minFive.isFinite).toEqual(false);
expect(positive.isFinite).toEqual(false);
expect(nonnegative.isFinite).toEqual(false);
expect(ltFive.isFinite).toEqual(false);
expect(lteFive.isFinite).toEqual(false);
expect(maxFive.isFinite).toEqual(false);
expect(negative.isFinite).toEqual(false);
expect(nonpositive.isFinite).toEqual(false);
expect(finite.isFinite).toEqual(true);
expect(intNum.isFinite).toEqual(true);
expect(multipleOfFive.isFinite).toEqual(true);
expect(z.number().min(5).max(10).isFinite).toEqual(true);
expect(safe.isFinite).toEqual(true);
});

View file

@ -1,29 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
test("object augmentation", () => {
const Animal = z
.object({
species: z.string(),
})
.augment({
population: z.number(),
});
// overwrites `species`
const ModifiedAnimal = Animal.augment({
species: z.array(z.string()),
});
ModifiedAnimal.parse({
species: ["asd"],
population: 1324,
});
const bad = () =>
ModifiedAnimal.parse({
species: "asdf",
population: 1324,
} as any);
expect(bad).toThrow();
});

View file

@ -1,29 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
const RealSet = Set;
const RealMap = Map;
const RealDate = Date;
test("doesnt throw when Date is undefined", () => {
delete (globalThis as any).Date;
const result = z.object({}).safeParse({});
expect(result.success).toEqual(true);
globalThis.Date = RealDate;
});
test("doesnt throw when Set is undefined", () => {
delete (globalThis as any).Set;
const result = z.object({}).safeParse({});
expect(result.success).toEqual(true);
globalThis.Set = RealSet;
});
test("doesnt throw when Map is undefined", () => {
delete (globalThis as any).Map;
const result = z.object({}).safeParse({});
expect(result.success).toEqual(true);
globalThis.Map = RealMap;
});

View file

@ -1,434 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
const Test = z.object({
f1: z.number(),
f2: z.string().optional(),
f3: z.string().nullable(),
f4: z.array(z.object({ t: z.union([z.string(), z.boolean()]) })),
});
test("object type inference", () => {
type TestType = {
f1: number;
f2?: string | undefined;
f3: string | null;
f4: { t: string | boolean }[];
};
util.assertEqual<z.TypeOf<typeof Test>, TestType>(true);
});
test("unknown throw", () => {
const asdf: unknown = 35;
expect(() => Test.parse(asdf)).toThrow();
});
test("shape() should return schema of particular key", () => {
const f1Schema = Test.shape.f1;
const f2Schema = Test.shape.f2;
const f3Schema = Test.shape.f3;
const f4Schema = Test.shape.f4;
expect(f1Schema).toBeInstanceOf(z.ZodNumber);
expect(f2Schema).toBeInstanceOf(z.ZodOptional);
expect(f3Schema).toBeInstanceOf(z.ZodNullable);
expect(f4Schema).toBeInstanceOf(z.ZodArray);
});
test("correct parsing", () => {
Test.parse({
f1: 12,
f2: "string",
f3: "string",
f4: [
{
t: "string",
},
],
});
Test.parse({
f1: 12,
f3: null,
f4: [
{
t: false,
},
],
});
});
test("incorrect #1", () => {
expect(() => Test.parse({} as any)).toThrow();
});
test("nonstrict by default", () => {
z.object({ points: z.number() }).parse({
points: 2314,
unknown: "asdf",
});
});
const data = {
points: 2314,
unknown: "asdf",
};
test("strip by default", () => {
const val = z.object({ points: z.number() }).parse(data);
expect(val).toEqual({ points: 2314 });
});
test("unknownkeys override", () => {
const val = z.object({ points: z.number() }).strict().passthrough().strip().nonstrict().parse(data);
expect(val).toEqual(data);
});
test("passthrough unknown", () => {
const val = z.object({ points: z.number() }).passthrough().parse(data);
expect(val).toEqual(data);
});
test("strip unknown", () => {
const val = z.object({ points: z.number() }).strip().parse(data);
expect(val).toEqual({ points: 2314 });
});
test("strict", () => {
const val = z.object({ points: z.number() }).strict().safeParse(data);
expect(val.success).toEqual(false);
});
test("catchall inference", () => {
const o1 = z
.object({
first: z.string(),
})
.catchall(z.number());
const d1 = o1.parse({ first: "asdf", num: 1243 });
util.assertEqual<number, (typeof d1)["asdf"]>(true);
util.assertEqual<string, (typeof d1)["first"]>(true);
});
test("catchall overrides strict", () => {
const o1 = z.object({ first: z.string().optional() }).strict().catchall(z.number());
// should run fine
// setting a catchall overrides the unknownKeys behavior
o1.parse({
asdf: 1234,
});
// should only run catchall validation
// against unknown keys
o1.parse({
first: "asdf",
asdf: 1234,
});
});
test("catchall overrides strict", () => {
const o1 = z
.object({
first: z.string(),
})
.strict()
.catchall(z.number());
// should run fine
// setting a catchall overrides the unknownKeys behavior
o1.parse({
first: "asdf",
asdf: 1234,
});
});
test("test that optional keys are unset", async () => {
const SNamedEntity = z.object({
id: z.string(),
set: z.string().optional(),
unset: z.string().optional(),
});
const result = await SNamedEntity.parse({
id: "asdf",
set: undefined,
});
// eslint-disable-next-line ban/ban
expect(Object.keys(result)).toEqual(["id", "set"]);
});
test("test catchall parsing", async () => {
const result = z.object({ name: z.string() }).catchall(z.number()).parse({ name: "Foo", validExtraKey: 61 });
expect(result).toEqual({ name: "Foo", validExtraKey: 61 });
const result2 = z
.object({ name: z.string() })
.catchall(z.number())
.safeParse({ name: "Foo", validExtraKey: 61, invalid: "asdf" });
expect(result2.success).toEqual(false);
});
test("test nonexistent keys", async () => {
const Schema = z.union([z.object({ a: z.string() }), z.object({ b: z.number() })]);
const obj = { a: "A" };
const result = await Schema.spa(obj); // Works with 1.11.10, breaks with 2.0.0-beta.21
expect(result.success).toBe(true);
});
test("test async union", async () => {
const Schema2 = z.union([
z.object({
ty: z.string(),
}),
z.object({
ty: z.number(),
}),
]);
const obj = { ty: "A" };
const result = await Schema2.spa(obj); // Works with 1.11.10, breaks with 2.0.0-beta.21
expect(result.success).toEqual(true);
});
test("test inferred merged type", async () => {
const asdf = z.object({ a: z.string() }).merge(z.object({ a: z.number() }));
type asdf = z.infer<typeof asdf>;
util.assertEqual<asdf, { a: number }>(true);
});
test("inferred merged object type with optional properties", async () => {
const Merged = z
.object({ a: z.string(), b: z.string().optional() })
.merge(z.object({ a: z.string().optional(), b: z.string() }));
type Merged = z.infer<typeof Merged>;
util.assertEqual<Merged, { a?: string; b: string }>(true);
// todo
// util.assertEqual<Merged, { a?: string; b: string }>(true);
});
test("inferred unioned object type with optional properties", async () => {
const Unioned = z.union([
z.object({ a: z.string(), b: z.string().optional() }),
z.object({ a: z.string().optional(), b: z.string() }),
]);
type Unioned = z.infer<typeof Unioned>;
util.assertEqual<Unioned, { a: string; b?: string } | { a?: string; b: string }>(true);
});
test("inferred enum type", async () => {
const Enum = z.object({ a: z.string(), b: z.string().optional() }).keyof();
expect(Enum.Values).toEqual({
a: "a",
b: "b",
});
expect(Enum.enum).toEqual({
a: "a",
b: "b",
});
expect(Enum._def.values).toEqual(["a", "b"]);
type Enum = z.infer<typeof Enum>;
util.assertEqual<Enum, "a" | "b">(true);
});
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>;
util.assertEqual<Partial, { a?: string; b?: string }>(true);
});
test("inferred picked object type with optional properties", async () => {
const Picked = z.object({ a: z.string(), b: z.string().optional() }).pick({ b: true });
type Picked = z.infer<typeof Picked>;
util.assertEqual<Picked, { b?: string }>(true);
});
test("inferred type for unknown/any keys", () => {
const myType = z.object({
anyOptional: z.any().optional(),
anyRequired: z.any(),
unknownOptional: z.unknown().optional(),
unknownRequired: z.unknown(),
});
type myType = z.infer<typeof myType>;
util.assertEqual<
myType,
{
anyOptional?: any;
anyRequired?: any;
unknownOptional?: unknown;
unknownRequired?: unknown;
}
>(true);
});
test("setKey", () => {
const base = z.object({ name: z.string() });
const withNewKey = base.setKey("age", z.number());
type withNewKey = z.infer<typeof withNewKey>;
util.assertEqual<withNewKey, { name: string; age: number }>(true);
withNewKey.parse({ name: "asdf", age: 1234 });
});
test("strictcreate", async () => {
const strictObj = z.strictObject({
name: z.string(),
});
const syncResult = strictObj.safeParse({ name: "asdf", unexpected: 13 });
expect(syncResult.success).toEqual(false);
const asyncResult = await strictObj.spa({ name: "asdf", unexpected: 13 });
expect(asyncResult.success).toEqual(false);
});
test("object with refine", async () => {
const schema = z
.object({
a: z.string().default("foo"),
b: z.number(),
})
.refine(() => true);
expect(schema.parse({ b: 5 })).toEqual({ b: 5, a: "foo" });
const result = await schema.parseAsync({ b: 5 });
expect(result).toEqual({ b: 5, a: "foo" });
});
test("intersection of object with date", async () => {
const schema = z.object({
a: z.date(),
});
expect(schema.and(schema).parse({ a: new Date(1637353595983) })).toEqual({
a: new Date(1637353595983),
});
const result = await schema.parseAsync({ a: new Date(1637353595983) });
expect(result).toEqual({ a: new Date(1637353595983) });
});
test("intersection of object with refine with date", async () => {
const schema = z
.object({
a: z.date(),
})
.refine(() => true);
expect(schema.and(schema).parse({ a: new Date(1637353595983) })).toEqual({
a: new Date(1637353595983),
});
const result = await schema.parseAsync({ a: new Date(1637353595983) });
expect(result).toEqual({ a: new Date(1637353595983) });
});
test("constructor key", () => {
const person = z
.object({
name: z.string(),
})
.strict();
expect(() =>
person.parse({
name: "bob dylan",
constructor: 61,
})
).toThrow();
});
test("constructor key", () => {
const Example = z.object({
prop: z.string(),
opt: z.number().optional(),
arr: z.string().array(),
});
type Example = z.infer<typeof Example>;
util.assertEqual<keyof Example, "prop" | "opt" | "arr">(true);
});
test("unknownkeys merging", () => {
// This one is "strict"
const schemaA = z
.object({
a: z.string(),
})
.strict();
// This one is "strip"
const schemaB = z
.object({
b: z.string(),
})
.catchall(z.string());
const mergedSchema = schemaA.merge(schemaB);
type mergedSchema = typeof mergedSchema;
util.assertEqual<mergedSchema["_def"]["unknownKeys"], "strip">(true);
expect(mergedSchema._def.unknownKeys).toEqual("strip");
util.assertEqual<mergedSchema["_def"]["catchall"], z.ZodString>(true);
expect(mergedSchema._def.catchall instanceof z.ZodString).toEqual(true);
});
const personToExtend = z.object({
firstName: z.string(),
lastName: z.string(),
});
test("extend() should return schema with new key", () => {
const PersonWithNickname = personToExtend.extend({ nickName: z.string() });
type PersonWithNickname = z.infer<typeof PersonWithNickname>;
const expected = { firstName: "f", nickName: "n", lastName: "l" };
const actual = PersonWithNickname.parse(expected);
expect(actual).toEqual(expected);
util.assertEqual<keyof PersonWithNickname, "firstName" | "lastName" | "nickName">(true);
util.assertEqual<PersonWithNickname, { firstName: string; lastName: string; nickName: string }>(true);
});
test("extend() should have power to override existing key", () => {
const PersonWithNumberAsLastName = personToExtend.extend({
lastName: z.number(),
});
type PersonWithNumberAsLastName = z.infer<typeof PersonWithNumberAsLastName>;
const expected = { firstName: "f", lastName: 42 };
const actual = PersonWithNumberAsLastName.parse(expected);
expect(actual).toEqual(expected);
util.assertEqual<PersonWithNumberAsLastName, { firstName: string; lastName: number }>(true);
});
test("passthrough index signature", () => {
const a = z.object({ a: z.string() });
type a = z.infer<typeof a>;
util.assertEqual<{ a: string }, a>(true);
const b = a.passthrough();
type b = z.infer<typeof b>;
util.assertEqual<{ a: string } & { [k: string]: unknown }, b>(true);
});
test("xor", () => {
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
type XOR<T, U> = T extends object ? (U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : U) : T;
type A = { name: string; a: number };
type B = { name: string; b: number };
type C = XOR<A, B>;
type Outer = { data: C };
const _Outer: z.ZodType<Outer> = z.object({
data: z.union([z.object({ name: z.string(), a: z.number() }), z.object({ name: z.string(), b: z.number() })]),
});
});

View file

@ -1,42 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
function checkErrors(a: z.ZodTypeAny, bad: any) {
let expected: any;
try {
a.parse(bad);
} catch (error) {
expected = (error as z.ZodError).formErrors;
}
try {
a.optional().parse(bad);
} catch (error) {
expect((error as z.ZodError).formErrors).toEqual(expected);
}
}
test("Should have error messages appropriate for the underlying type", () => {
checkErrors(z.string().min(2), 1);
z.string().min(2).optional().parse(undefined);
checkErrors(z.number().gte(2), 1);
z.number().gte(2).optional().parse(undefined);
checkErrors(z.boolean(), "");
z.boolean().optional().parse(undefined);
checkErrors(z.undefined(), null);
z.undefined().optional().parse(undefined);
checkErrors(z.null(), {});
z.null().optional().parse(undefined);
checkErrors(z.object({}), 1);
z.object({}).optional().parse(undefined);
checkErrors(z.tuple([]), 1);
z.tuple([]).optional().parse(undefined);
checkErrors(z.unknown(), 1);
z.unknown().optional().parse(undefined);
});
test("unwrap", () => {
const unwrapped = z.string().optional().unwrap();
expect(unwrapped).toBeInstanceOf(z.ZodString);
});

View file

@ -1,23 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import { type SyncParseReturnType, isAborted, isDirty, isValid } from "../helpers/parseUtil.js";
test("parseUtil isInvalid should use structural typing", () => {
// Test for issue #556: https://github.com/colinhacks/zod/issues/556
const aborted: SyncParseReturnType = { status: "aborted" };
const dirty: SyncParseReturnType = { status: "dirty", value: "whatever" };
const valid: SyncParseReturnType = { status: "valid", value: "whatever" };
expect(isAborted(aborted)).toBe(true);
expect(isAborted(dirty)).toBe(false);
expect(isAborted(valid)).toBe(false);
expect(isDirty(aborted)).toBe(false);
expect(isDirty(dirty)).toBe(true);
expect(isDirty(valid)).toBe(false);
expect(isValid(aborted)).toBe(false);
expect(isValid(dirty)).toBe(false);
expect(isValid(valid)).toBe(true);
});

View file

@ -1,41 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
test("parse strict object with unknown keys", () => {
expect(() =>
z
.object({ name: z.string() })
.strict()
.parse({ name: "bill", unknownKey: 12 } as any)
).toThrow();
});
test("parse nonstrict object with unknown keys", () => {
z.object({ name: z.string() }).nonstrict().parse({ name: "bill", unknownKey: 12 });
});
test("invalid left side of intersection", () => {
expect(() => z.intersection(z.string(), z.number()).parse(12 as any)).toThrow();
});
test("invalid right side of intersection", () => {
expect(() => z.intersection(z.string(), z.number()).parse("12" as any)).toThrow();
});
test("parsing non-array in tuple schema", () => {
expect(() => z.tuple([]).parse("12" as any)).toThrow();
});
test("incorrect num elements in tuple", () => {
expect(() => z.tuple([]).parse(["asdf"] as any)).toThrow();
});
test("invalid enum value", () => {
expect(() => z.enum(["Blue"]).parse("Red" as any)).toThrow();
});
test("parsing unknown", () => {
z.string().parse("Red" as unknown);
});

View file

@ -1,243 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { ZodNullable, ZodOptional } from "zod/v3";
import { util } from "../helpers/util.js";
const nested = z.object({
name: z.string(),
age: z.number(),
outer: z.object({
inner: z.string(),
}),
array: z.array(z.object({ asdf: z.string() })),
});
test("shallow inference", () => {
const shallow = nested.partial();
type shallow = z.infer<typeof shallow>;
type correct = {
name?: string | undefined;
age?: number | undefined;
outer?: { inner: string } | undefined;
array?: { asdf: string }[];
};
util.assertEqual<shallow, correct>(true);
});
test("shallow partial parse", () => {
const shallow = nested.partial();
shallow.parse({});
shallow.parse({
name: "asdf",
age: 23143,
});
});
test("deep partial inference", () => {
const deep = nested.deepPartial();
const asdf = deep.shape.array.unwrap().element.shape.asdf.unwrap();
asdf.parse("asdf");
type deep = z.infer<typeof deep>;
type correct = {
array?: { asdf?: string }[];
name?: string | undefined;
age?: number | undefined;
outer?: { inner?: string | undefined } | undefined;
};
util.assertEqual<deep, correct>(true);
});
test("deep partial parse", () => {
const deep = nested.deepPartial();
expect(deep.shape.name instanceof z.ZodOptional).toBe(true);
expect(deep.shape.outer instanceof z.ZodOptional).toBe(true);
expect(deep.shape.outer._def.innerType instanceof z.ZodObject).toBe(true);
expect(deep.shape.outer._def.innerType.shape.inner instanceof z.ZodOptional).toBe(true);
expect(deep.shape.outer._def.innerType.shape.inner._def.innerType instanceof z.ZodString).toBe(true);
});
test("deep partial runtime tests", () => {
const deep = nested.deepPartial();
deep.parse({});
deep.parse({
outer: {},
});
deep.parse({
name: "asdf",
age: 23143,
outer: {
inner: "adsf",
},
});
});
test("deep partial optional/nullable", () => {
const schema = z
.object({
name: z.string().optional(),
age: z.number().nullable(),
})
.deepPartial();
expect(schema.shape.name.unwrap()).toBeInstanceOf(ZodOptional);
expect(schema.shape.age.unwrap()).toBeInstanceOf(ZodNullable);
});
test("deep partial tuple", () => {
const schema = z
.object({
tuple: z.tuple([
z.object({
name: z.string().optional(),
age: z.number().nullable(),
}),
]),
})
.deepPartial();
expect(schema.shape.tuple.unwrap().items[0].shape.name).toBeInstanceOf(ZodOptional);
});
test("deep partial inference", () => {
const mySchema = z.object({
name: z.string(),
array: z.array(z.object({ asdf: z.string() })),
tuple: z.tuple([z.object({ value: z.string() })]),
});
const partialed = mySchema.deepPartial();
type partialed = z.infer<typeof partialed>;
type expected = {
name?: string | undefined;
array?:
| {
asdf?: string | undefined;
}[]
| undefined;
tuple?: [{ value?: string }] | undefined;
};
util.assertEqual<expected, partialed>(true);
});
test("required", () => {
const object = z.object({
name: z.string(),
age: z.number().optional(),
field: z.string().optional().default("asdf"),
nullableField: z.number().nullable(),
nullishField: z.string().nullish(),
});
const requiredObject = object.required();
expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString);
expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNumber);
expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault);
expect(requiredObject.shape.nullableField).toBeInstanceOf(z.ZodNullable);
expect(requiredObject.shape.nullishField).toBeInstanceOf(z.ZodNullable);
});
test("required inference", () => {
const object = z.object({
name: z.string(),
age: z.number().optional(),
field: z.string().optional().default("asdf"),
nullableField: z.number().nullable(),
nullishField: z.string().nullish(),
});
const requiredObject = object.required();
type required = z.infer<typeof requiredObject>;
type expected = {
name: string;
age: number;
field: string;
nullableField: number | null;
nullishField: string | null;
};
util.assertEqual<expected, required>(true);
});
test("required with mask", () => {
const object = z.object({
name: z.string(),
age: z.number().optional(),
field: z.string().optional().default("asdf"),
country: z.string().optional(),
});
const requiredObject = object.required({ age: true });
expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString);
expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNumber);
expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault);
expect(requiredObject.shape.country).toBeInstanceOf(z.ZodOptional);
});
test("required with mask -- ignore falsy values", () => {
const object = z.object({
name: z.string(),
age: z.number().optional(),
field: z.string().optional().default("asdf"),
country: z.string().optional(),
});
// @ts-expect-error
const requiredObject = object.required({ age: true, country: false });
expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString);
expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNumber);
expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault);
expect(requiredObject.shape.country).toBeInstanceOf(z.ZodOptional);
});
test("partial with mask", async () => {
const object = z.object({
name: z.string(),
age: z.number().optional(),
field: z.string().optional().default("asdf"),
country: z.string(),
});
const masked = object.partial({ age: true, field: true, name: true }).strict();
expect(masked.shape.name).toBeInstanceOf(z.ZodOptional);
expect(masked.shape.age).toBeInstanceOf(z.ZodOptional);
expect(masked.shape.field).toBeInstanceOf(z.ZodOptional);
expect(masked.shape.country).toBeInstanceOf(z.ZodString);
masked.parse({ country: "US" });
await masked.parseAsync({ country: "US" });
});
test("partial with mask -- ignore falsy values", async () => {
const object = z.object({
name: z.string(),
age: z.number().optional(),
field: z.string().optional().default("asdf"),
country: z.string(),
});
// @ts-expect-error
const masked = object.partial({ name: true, country: false }).strict();
expect(masked.shape.name).toBeInstanceOf(z.ZodOptional);
expect(masked.shape.age).toBeInstanceOf(z.ZodOptional);
expect(masked.shape.field).toBeInstanceOf(z.ZodDefault);
expect(masked.shape.country).toBeInstanceOf(z.ZodString);
masked.parse({ country: "US" });
await masked.parseAsync({ country: "US" });
});
test("deeppartial array", () => {
const schema = z.object({ array: z.string().array().min(42) }).deepPartial();
// works as expected
schema.parse({});
// should be false, but is true
expect(schema.safeParse({ array: [] }).success).toBe(false);
});

View file

@ -1,111 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
const fish = z.object({
name: z.string(),
age: z.number(),
nested: z.object({}),
});
test("pick type inference", () => {
const nameonlyFish = fish.pick({ name: true });
type nameonlyFish = z.infer<typeof nameonlyFish>;
util.assertEqual<nameonlyFish, { name: string }>(true);
});
test("pick parse - success", () => {
const nameonlyFish = fish.pick({ name: true });
nameonlyFish.parse({ name: "bob" });
// @ts-expect-error checking runtime picks `name` only.
const anotherNameonlyFish = fish.pick({ name: true, age: false });
anotherNameonlyFish.parse({ name: "bob" });
});
test("pick parse - fail", () => {
fish.pick({ name: true }).parse({ name: "12" } as any);
fish.pick({ name: true }).parse({ name: "bob", age: 12 } as any);
fish.pick({ age: true }).parse({ age: 12 } as any);
const nameonlyFish = fish.pick({ name: true }).strict();
const bad1 = () => nameonlyFish.parse({ name: 12 } as any);
const bad2 = () => nameonlyFish.parse({ name: "bob", age: 12 } as any);
const bad3 = () => nameonlyFish.parse({ age: 12 } as any);
// @ts-expect-error checking runtime picks `name` only.
const anotherNameonlyFish = fish.pick({ name: true, age: false }).strict();
const bad4 = () => anotherNameonlyFish.parse({ name: "bob", age: 12 } as any);
expect(bad1).toThrow();
expect(bad2).toThrow();
expect(bad3).toThrow();
expect(bad4).toThrow();
});
test("omit type inference", () => {
const nonameFish = fish.omit({ name: true });
type nonameFish = z.infer<typeof nonameFish>;
util.assertEqual<nonameFish, { age: number; nested: {} }>(true);
});
test("omit parse - success", () => {
const nonameFish = fish.omit({ name: true });
nonameFish.parse({ age: 12, nested: {} });
// @ts-expect-error checking runtime omits `name` only.
const anotherNonameFish = fish.omit({ name: true, age: false });
anotherNonameFish.parse({ age: 12, nested: {} });
});
test("omit parse - fail", () => {
const nonameFish = fish.omit({ name: true });
const bad1 = () => nonameFish.parse({ name: 12 } as any);
const bad2 = () => nonameFish.parse({ age: 12 } as any);
const bad3 = () => nonameFish.parse({} as any);
// @ts-expect-error checking runtime omits `name` only.
const anotherNonameFish = fish.omit({ name: true, age: false });
const bad4 = () => anotherNonameFish.parse({ nested: {} } as any);
expect(bad1).toThrow();
expect(bad2).toThrow();
expect(bad3).toThrow();
expect(bad4).toThrow();
});
test("nonstrict inference", () => {
const laxfish = fish.pick({ name: true }).catchall(z.any());
type laxfish = z.infer<typeof laxfish>;
util.assertEqual<laxfish, { name: string } & { [k: string]: any }>(true);
});
test("nonstrict parsing - pass", () => {
const laxfish = fish.passthrough().pick({ name: true });
laxfish.parse({ name: "asdf", whatever: "asdf" });
laxfish.parse({ name: "asdf", age: 12, nested: {} });
});
test("nonstrict parsing - fail", () => {
const laxfish = fish.passthrough().pick({ name: true });
const bad = () => laxfish.parse({ whatever: "asdf" } as any);
expect(bad).toThrow();
});
test("pick/omit/required/partial - do not allow unknown keys", () => {
const schema = z.object({
name: z.string(),
age: z.number(),
});
// @ts-expect-error
schema.pick({ $unknown: true });
// @ts-expect-error
schema.omit({ $unknown: true });
// @ts-expect-error
schema.required({ $unknown: true });
// @ts-expect-error
schema.partial({ $unknown: true });
});

View file

@ -1,29 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
test("string to number pipeline", () => {
const schema = z.string().transform(Number).pipe(z.number());
expect(schema.parse("1234")).toEqual(1234);
});
test("string to number pipeline async", async () => {
const schema = z
.string()
.transform(async (val) => Number(val))
.pipe(z.number());
expect(await schema.parseAsync("1234")).toEqual(1234);
});
test("break if dirty", () => {
const schema = z
.string()
.refine((c) => c === "1234")
.transform(async (val) => Number(val))
.pipe(z.number().refine((v) => v < 100));
const r1: any = schema.safeParse("12345");
expect(r1.error.issues.length).toBe(1);
const r2: any = schema.safeParse("3");
expect(r2.error.issues.length).toBe(1);
});

View file

@ -1,186 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
test("preprocess", () => {
const schema = z.preprocess((data) => [data], z.string().array());
const value = schema.parse("asdf");
expect(value).toEqual(["asdf"]);
util.assertEqual<(typeof schema)["_input"], unknown>(true);
});
test("async preprocess", async () => {
const schema = z.preprocess(async (data) => [data], z.string().array());
const value = await schema.parseAsync("asdf");
expect(value).toEqual(["asdf"]);
});
test("preprocess ctx.addIssue with parse", () => {
expect(() => {
z.preprocess((data, ctx) => {
ctx.addIssue({
code: "custom",
message: `${data} is not one of our allowed strings`,
});
return data;
}, z.string()).parse("asdf");
}).toThrow(
JSON.stringify(
[
{
code: "custom",
message: "asdf is not one of our allowed strings",
path: [],
},
],
null,
2
)
);
});
test("preprocess ctx.addIssue non-fatal by default", () => {
try {
z.preprocess((data, ctx) => {
ctx.addIssue({
code: "custom",
message: `custom error`,
});
return data;
}, z.string()).parse(1234);
} catch (err) {
z.ZodError.assert(err);
expect(err.issues.length).toEqual(2);
}
});
test("preprocess ctx.addIssue fatal true", () => {
try {
z.preprocess((data, ctx) => {
ctx.addIssue({
code: "custom",
message: `custom error`,
fatal: true,
});
return data;
}, z.string()).parse(1234);
} catch (err) {
z.ZodError.assert(err);
expect(err.issues.length).toEqual(1);
}
});
test("async preprocess ctx.addIssue with parse", async () => {
const schema = z.preprocess(async (data, ctx) => {
ctx.addIssue({
code: "custom",
message: `custom error`,
});
return data;
}, z.string());
expect(await schema.safeParseAsync("asdf")).toMatchInlineSnapshot(`
{
"error": [ZodError: [
{
"code": "custom",
"message": "custom error",
"path": []
}
]],
"success": false,
}
`);
});
test("preprocess ctx.addIssue with parseAsync", async () => {
const result = await z
.preprocess(async (data, ctx) => {
ctx.addIssue({
code: "custom",
message: `${data} is not one of our allowed strings`,
});
return data;
}, z.string())
.safeParseAsync("asdf");
expect(JSON.parse(JSON.stringify(result))).toEqual({
success: false,
error: {
issues: [
{
code: "custom",
message: "asdf is not one of our allowed strings",
path: [],
},
],
name: "ZodError",
},
});
});
test("z.NEVER in preprocess", () => {
const foo = z.preprocess((val, ctx) => {
if (!val) {
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "bad" });
return z.NEVER;
}
return val;
}, z.number());
type foo = z.infer<typeof foo>;
util.assertEqual<foo, number>(true);
const arg = foo.safeParse(undefined);
expect(arg.error!.issues).toHaveLength(2);
expect(arg.error!.issues[0].message).toEqual("bad");
});
test("preprocess as the second property of object", () => {
const schema = z.object({
nonEmptyStr: z.string().min(1),
positiveNum: z.preprocess((v) => Number(v), z.number().positive()),
});
const result = schema.safeParse({
nonEmptyStr: "",
positiveNum: "",
});
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues.length).toEqual(2);
expect(result.error.issues[0].code).toEqual(z.ZodIssueCode.too_small);
expect(result.error.issues[1].code).toEqual(z.ZodIssueCode.too_small);
}
});
test("preprocess validates with sibling errors", () => {
expect(() => {
z.object({
// Must be first
missing: z.string().refine(() => false),
preprocess: z.preprocess((data: any) => data?.trim(), z.string().regex(/ asdf/)),
}).parse({ preprocess: " asdf" });
}).toThrow(
JSON.stringify(
[
{
code: "invalid_type",
expected: "string",
received: "undefined",
path: ["missing"],
message: "Required",
},
{
validation: "regex",
code: "invalid_string",
message: "Invalid",
path: ["preprocess"],
},
],
null,
2
)
);
});

View file

@ -1,440 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
import { Mocker } from "./Mocker.js";
const literalStringSchema = z.literal("asdf");
const literalNumberSchema = z.literal(12);
const literalBooleanSchema = z.literal(true);
const literalBigIntSchema = z.literal(BigInt(42));
const MySymbol = Symbol("stuff");
const literalSymbolSchema = z.literal(MySymbol);
const stringSchema = z.string();
const numberSchema = z.number();
const bigintSchema = z.bigint();
const booleanSchema = z.boolean();
const dateSchema = z.date();
const symbolSchema = z.symbol();
const nullSchema = z.null();
const undefinedSchema = z.undefined();
const stringSchemaOptional = z.string().optional();
const stringSchemaNullable = z.string().nullable();
const numberSchemaOptional = z.number().optional();
const numberSchemaNullable = z.number().nullable();
const bigintSchemaOptional = z.bigint().optional();
const bigintSchemaNullable = z.bigint().nullable();
const booleanSchemaOptional = z.boolean().optional();
const booleanSchemaNullable = z.boolean().nullable();
const dateSchemaOptional = z.date().optional();
const dateSchemaNullable = z.date().nullable();
const symbolSchemaOptional = z.symbol().optional();
const symbolSchemaNullable = z.symbol().nullable();
const val = new Mocker();
test("literal string correct", () => {
expect(literalStringSchema.parse("asdf")).toBe("asdf");
});
test("literal string incorrect", () => {
const f = () => literalStringSchema.parse("not_asdf");
expect(f).toThrow();
});
test("literal string number", () => {
const f = () => literalStringSchema.parse(123);
expect(f).toThrow();
});
test("literal string boolean", () => {
const f = () => literalStringSchema.parse(true);
expect(f).toThrow();
});
test("literal string boolean", () => {
const f = () => literalStringSchema.parse(true);
expect(f).toThrow();
});
test("literal string object", () => {
const f = () => literalStringSchema.parse({});
expect(f).toThrow();
});
test("literal number correct", () => {
expect(literalNumberSchema.parse(12)).toBe(12);
});
test("literal number incorrect", () => {
const f = () => literalNumberSchema.parse(13);
expect(f).toThrow();
});
test("literal number number", () => {
const f = () => literalNumberSchema.parse(val.string);
expect(f).toThrow();
});
test("literal number boolean", () => {
const f = () => literalNumberSchema.parse(val.boolean);
expect(f).toThrow();
});
test("literal number object", () => {
const f = () => literalStringSchema.parse({});
expect(f).toThrow();
});
test("literal boolean correct", () => {
expect(literalBooleanSchema.parse(true)).toBe(true);
});
test("literal boolean incorrect", () => {
const f = () => literalBooleanSchema.parse(false);
expect(f).toThrow();
});
test("literal boolean number", () => {
const f = () => literalBooleanSchema.parse("asdf");
expect(f).toThrow();
});
test("literal boolean boolean", () => {
const f = () => literalBooleanSchema.parse(123);
expect(f).toThrow();
});
test("literal boolean object", () => {
const f = () => literalBooleanSchema.parse({});
expect(f).toThrow();
});
test("literal bigint correct", () => {
expect(literalBigIntSchema.parse(BigInt(42))).toBe(BigInt(42));
});
test("literal bigint incorrect", () => {
const f = () => literalBigIntSchema.parse(BigInt(43));
expect(f).toThrow();
});
test("literal bigint number", () => {
const f = () => literalBigIntSchema.parse("asdf");
expect(f).toThrow();
});
test("literal bigint boolean", () => {
const f = () => literalBigIntSchema.parse(123);
expect(f).toThrow();
});
test("literal bigint object", () => {
const f = () => literalBigIntSchema.parse({});
expect(f).toThrow();
});
test("literal symbol", () => {
util.assertEqual<z.infer<typeof literalSymbolSchema>, typeof MySymbol>(true);
literalSymbolSchema.parse(MySymbol);
expect(() => literalSymbolSchema.parse(Symbol("asdf"))).toThrow();
});
test("parse stringSchema string", () => {
stringSchema.parse(val.string);
});
test("parse stringSchema number", () => {
const f = () => stringSchema.parse(val.number);
expect(f).toThrow();
});
test("parse stringSchema boolean", () => {
const f = () => stringSchema.parse(val.boolean);
expect(f).toThrow();
});
test("parse stringSchema undefined", () => {
const f = () => stringSchema.parse(val.undefined);
expect(f).toThrow();
});
test("parse stringSchema null", () => {
const f = () => stringSchema.parse(val.null);
expect(f).toThrow();
});
test("parse numberSchema string", () => {
const f = () => numberSchema.parse(val.string);
expect(f).toThrow();
});
test("parse numberSchema number", () => {
numberSchema.parse(val.number);
});
test("parse numberSchema bigint", () => {
const f = () => numberSchema.parse(val.bigint);
expect(f).toThrow();
});
test("parse numberSchema boolean", () => {
const f = () => numberSchema.parse(val.boolean);
expect(f).toThrow();
});
test("parse numberSchema undefined", () => {
const f = () => numberSchema.parse(val.undefined);
expect(f).toThrow();
});
test("parse numberSchema null", () => {
const f = () => numberSchema.parse(val.null);
expect(f).toThrow();
});
test("parse bigintSchema string", () => {
const f = () => bigintSchema.parse(val.string);
expect(f).toThrow();
});
test("parse bigintSchema number", () => {
const f = () => bigintSchema.parse(val.number);
expect(f).toThrow();
});
test("parse bigintSchema bigint", () => {
bigintSchema.parse(val.bigint);
});
test("parse bigintSchema boolean", () => {
const f = () => bigintSchema.parse(val.boolean);
expect(f).toThrow();
});
test("parse bigintSchema undefined", () => {
const f = () => bigintSchema.parse(val.undefined);
expect(f).toThrow();
});
test("parse bigintSchema null", () => {
const f = () => bigintSchema.parse(val.null);
expect(f).toThrow();
});
test("parse booleanSchema string", () => {
const f = () => booleanSchema.parse(val.string);
expect(f).toThrow();
});
test("parse booleanSchema number", () => {
const f = () => booleanSchema.parse(val.number);
expect(f).toThrow();
});
test("parse booleanSchema boolean", () => {
booleanSchema.parse(val.boolean);
});
test("parse booleanSchema undefined", () => {
const f = () => booleanSchema.parse(val.undefined);
expect(f).toThrow();
});
test("parse booleanSchema null", () => {
const f = () => booleanSchema.parse(val.null);
expect(f).toThrow();
});
// ==============
test("parse dateSchema string", () => {
const f = () => dateSchema.parse(val.string);
expect(f).toThrow();
});
test("parse dateSchema number", () => {
const f = () => dateSchema.parse(val.number);
expect(f).toThrow();
});
test("parse dateSchema boolean", () => {
const f = () => dateSchema.parse(val.boolean);
expect(f).toThrow();
});
test("parse dateSchema date", () => {
dateSchema.parse(val.date);
});
test("parse dateSchema undefined", () => {
const f = () => dateSchema.parse(val.undefined);
expect(f).toThrow();
});
test("parse dateSchema null", () => {
const f = () => dateSchema.parse(val.null);
expect(f).toThrow();
});
test("parse dateSchema invalid date", async () => {
try {
await dateSchema.parseAsync(new Date("invalid"));
} catch (err) {
expect((err as z.ZodError).issues[0].code).toEqual(z.ZodIssueCode.invalid_date);
}
});
// ==============
test("parse symbolSchema string", () => {
const f = () => symbolSchema.parse(val.string);
expect(f).toThrow();
});
test("parse symbolSchema number", () => {
const f = () => symbolSchema.parse(val.number);
expect(f).toThrow();
});
test("parse symbolSchema boolean", () => {
const f = () => symbolSchema.parse(val.boolean);
expect(f).toThrow();
});
test("parse symbolSchema date", () => {
const f = () => symbolSchema.parse(val.date);
expect(f).toThrow();
});
test("parse symbolSchema symbol", () => {
symbolSchema.parse(val.symbol);
});
test("parse symbolSchema undefined", () => {
const f = () => symbolSchema.parse(val.undefined);
expect(f).toThrow();
});
test("parse symbolSchema null", () => {
const f = () => symbolSchema.parse(val.null);
expect(f).toThrow();
});
// ==============
test("parse undefinedSchema string", () => {
const f = () => undefinedSchema.parse(val.string);
expect(f).toThrow();
});
test("parse undefinedSchema number", () => {
const f = () => undefinedSchema.parse(val.number);
expect(f).toThrow();
});
test("parse undefinedSchema boolean", () => {
const f = () => undefinedSchema.parse(val.boolean);
expect(f).toThrow();
});
test("parse undefinedSchema undefined", () => {
undefinedSchema.parse(val.undefined);
});
test("parse undefinedSchema null", () => {
const f = () => undefinedSchema.parse(val.null);
expect(f).toThrow();
});
test("parse nullSchema string", () => {
const f = () => nullSchema.parse(val.string);
expect(f).toThrow();
});
test("parse nullSchema number", () => {
const f = () => nullSchema.parse(val.number);
expect(f).toThrow();
});
test("parse nullSchema boolean", () => {
const f = () => nullSchema.parse(val.boolean);
expect(f).toThrow();
});
test("parse nullSchema undefined", () => {
const f = () => nullSchema.parse(val.undefined);
expect(f).toThrow();
});
test("parse nullSchema null", () => {
nullSchema.parse(val.null);
});
test("primitive inference", () => {
util.assertEqual<z.TypeOf<typeof literalStringSchema>, "asdf">(true);
util.assertEqual<z.TypeOf<typeof literalNumberSchema>, 12>(true);
util.assertEqual<z.TypeOf<typeof literalBooleanSchema>, true>(true);
util.assertEqual<z.TypeOf<typeof literalBigIntSchema>, bigint>(true);
util.assertEqual<z.TypeOf<typeof stringSchema>, string>(true);
util.assertEqual<z.TypeOf<typeof numberSchema>, number>(true);
util.assertEqual<z.TypeOf<typeof bigintSchema>, bigint>(true);
util.assertEqual<z.TypeOf<typeof booleanSchema>, boolean>(true);
util.assertEqual<z.TypeOf<typeof dateSchema>, Date>(true);
util.assertEqual<z.TypeOf<typeof symbolSchema>, symbol>(true);
util.assertEqual<z.TypeOf<typeof nullSchema>, null>(true);
util.assertEqual<z.TypeOf<typeof undefinedSchema>, undefined>(true);
util.assertEqual<z.TypeOf<typeof stringSchemaOptional>, string | undefined>(true);
util.assertEqual<z.TypeOf<typeof stringSchemaNullable>, string | null>(true);
util.assertEqual<z.TypeOf<typeof numberSchemaOptional>, number | undefined>(true);
util.assertEqual<z.TypeOf<typeof numberSchemaNullable>, number | null>(true);
util.assertEqual<z.TypeOf<typeof bigintSchemaOptional>, bigint | undefined>(true);
util.assertEqual<z.TypeOf<typeof bigintSchemaNullable>, bigint | null>(true);
util.assertEqual<z.TypeOf<typeof booleanSchemaOptional>, boolean | undefined>(true);
util.assertEqual<z.TypeOf<typeof booleanSchemaNullable>, boolean | null>(true);
util.assertEqual<z.TypeOf<typeof dateSchemaOptional>, Date | undefined>(true);
util.assertEqual<z.TypeOf<typeof dateSchemaNullable>, Date | null>(true);
util.assertEqual<z.TypeOf<typeof symbolSchemaOptional>, symbol | undefined>(true);
util.assertEqual<z.TypeOf<typeof symbolSchemaNullable>, symbol | null>(true);
// [
// literalStringSchemaTest,
// literalNumberSchemaTest,
// literalBooleanSchemaTest,
// literalBigIntSchemaTest,
// stringSchemaTest,
// numberSchemaTest,
// bigintSchemaTest,
// booleanSchemaTest,
// dateSchemaTest,
// symbolSchemaTest,
// nullSchemaTest,
// undefinedSchemaTest,
// stringSchemaOptionalTest,
// stringSchemaNullableTest,
// numberSchemaOptionalTest,
// numberSchemaNullableTest,
// bigintSchemaOptionalTest,
// bigintSchemaNullableTest,
// booleanSchemaOptionalTest,
// booleanSchemaNullableTest,
// dateSchemaOptionalTest,
// dateSchemaNullableTest,
// symbolSchemaOptionalTest,
// symbolSchemaNullableTest,
// ];
});
test("get literal value", () => {
expect(literalStringSchema.value).toEqual("asdf");
});
test("optional convenience method", () => {
z.ostring().parse(undefined);
z.onumber().parse(undefined);
z.oboolean().parse(undefined);
});

View file

@ -1,90 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
const promSchema = z.promise(
z.object({
name: z.string(),
age: z.number(),
})
);
test("promise inference", () => {
type promSchemaType = z.infer<typeof promSchema>;
util.assertEqual<promSchemaType, Promise<{ name: string; age: number }>>(true);
});
test("promise parsing success", async () => {
const pr = promSchema.parse(Promise.resolve({ name: "Bobby", age: 10 }));
expect(pr).toBeInstanceOf(Promise);
const result = await pr;
expect(typeof result).toBe("object");
expect(typeof result.age).toBe("number");
expect(typeof result.name).toBe("string");
});
test("promise parsing success 2", () => {
const fakePromise = {
then() {
return this;
},
catch() {
return this;
},
};
promSchema.parse(fakePromise);
});
test("promise parsing fail", async () => {
const bad = promSchema.parse(Promise.resolve({ name: "Bobby", age: "10" }));
// return await expect(bad).resolves.toBe({ name: 'Bobby', age: '10' });
return await expect(bad).rejects.toBeInstanceOf(z.ZodError);
// done();
});
test("promise parsing fail 2", async () => {
const failPromise = promSchema.parse(Promise.resolve({ name: "Bobby", age: "10" }));
await expect(failPromise).rejects.toBeInstanceOf(z.ZodError);
// done();/z
});
test("promise parsing fail", () => {
const bad = () => promSchema.parse({ then: () => {}, catch: {} });
expect(bad).toThrow();
});
// test('sync promise parsing', () => {
// expect(() => z.promise(z.string()).parse(Promise.resolve('asfd'))).toThrow();
// });
const asyncFunction = z.function(z.tuple([]), promSchema);
test("async function pass", async () => {
const validatedFunction = asyncFunction.implement(async () => {
return { name: "jimmy", age: 14 };
});
await expect(validatedFunction()).resolves.toEqual({
name: "jimmy",
age: 14,
});
});
test("async function fail", async () => {
const validatedFunction = asyncFunction.implement(() => {
return Promise.resolve("asdf" as any);
});
await expect(validatedFunction()).rejects.toBeInstanceOf(z.ZodError);
});
test("async promise parsing", () => {
const res = z.promise(z.number()).parseAsync(Promise.resolve(12));
expect(res).toBeInstanceOf(Promise);
});
test("resolves", () => {
const foo = z.literal("foo");
const res = z.promise(foo);
expect(res.unwrap()).toEqual(foo);
});

View file

@ -1,194 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
enum testEnum {
A = 0,
B = 1,
}
const schemas = [
z.string().readonly(),
z.number().readonly(),
z.nan().readonly(),
z.bigint().readonly(),
z.boolean().readonly(),
z.date().readonly(),
z.undefined().readonly(),
z.null().readonly(),
z.any().readonly(),
z.unknown().readonly(),
z.void().readonly(),
z.function().args(z.string(), z.number()).readonly(),
z.array(z.string()).readonly(),
z.tuple([z.string(), z.number()]).readonly(),
z.map(z.string(), z.date()).readonly(),
z.set(z.promise(z.string())).readonly(),
z.record(z.string()).readonly(),
z.record(z.string(), z.number()).readonly(),
z.object({ a: z.string(), 1: z.number() }).readonly(),
z.nativeEnum(testEnum).readonly(),
z.promise(z.string()).readonly(),
] as const;
test("flat inference", () => {
util.assertEqual<z.infer<(typeof schemas)[0]>, string>(true);
util.assertEqual<z.infer<(typeof schemas)[1]>, number>(true);
util.assertEqual<z.infer<(typeof schemas)[2]>, number>(true);
util.assertEqual<z.infer<(typeof schemas)[3]>, bigint>(true);
util.assertEqual<z.infer<(typeof schemas)[4]>, boolean>(true);
util.assertEqual<z.infer<(typeof schemas)[5]>, Date>(true);
util.assertEqual<z.infer<(typeof schemas)[6]>, undefined>(true);
util.assertEqual<z.infer<(typeof schemas)[7]>, null>(true);
util.assertEqual<z.infer<(typeof schemas)[8]>, any>(true);
util.assertEqual<z.infer<(typeof schemas)[9]>, Readonly<unknown>>(true);
util.assertEqual<z.infer<(typeof schemas)[10]>, void>(true);
util.assertEqual<z.infer<(typeof schemas)[11]>, (args_0: string, args_1: number, ...args_2: unknown[]) => unknown>(
true
);
util.assertEqual<z.infer<(typeof schemas)[12]>, readonly string[]>(true);
util.assertEqual<z.infer<(typeof schemas)[13]>, readonly [string, number]>(true);
util.assertEqual<z.infer<(typeof schemas)[14]>, ReadonlyMap<string, Date>>(true);
util.assertEqual<z.infer<(typeof schemas)[15]>, ReadonlySet<Promise<string>>>(true);
util.assertEqual<z.infer<(typeof schemas)[16]>, Readonly<Record<string, string>>>(true);
util.assertEqual<z.infer<(typeof schemas)[17]>, Readonly<Record<string, number>>>(true);
util.assertEqual<z.infer<(typeof schemas)[18]>, { readonly a: string; readonly 1: number }>(true);
util.assertEqual<z.infer<(typeof schemas)[19]>, Readonly<testEnum>>(true);
util.assertEqual<z.infer<(typeof schemas)[20]>, Promise<string>>(true);
});
// test("deep inference", () => {
// util.assertEqual<z.infer<(typeof deepReadonlySchemas_0)[0]>, string>(true);
// util.assertEqual<z.infer<(typeof deepReadonlySchemas_0)[1]>, number>(true);
// util.assertEqual<z.infer<(typeof deepReadonlySchemas_0)[2]>, number>(true);
// util.assertEqual<z.infer<(typeof deepReadonlySchemas_0)[3]>, bigint>(true);
// util.assertEqual<z.infer<(typeof deepReadonlySchemas_0)[4]>, boolean>(true);
// util.assertEqual<z.infer<(typeof deepReadonlySchemas_0)[5]>, Date>(true);
// util.assertEqual<z.infer<(typeof deepReadonlySchemas_0)[6]>, undefined>(true);
// util.assertEqual<z.infer<(typeof deepReadonlySchemas_0)[7]>, null>(true);
// util.assertEqual<z.infer<(typeof deepReadonlySchemas_0)[8]>, any>(true);
// util.assertEqual<
// z.infer<(typeof deepReadonlySchemas_0)[9]>,
// Readonly<unknown>
// >(true);
// util.assertEqual<z.infer<(typeof deepReadonlySchemas_0)[10]>, void>(true);
// util.assertEqual<
// z.infer<(typeof deepReadonlySchemas_0)[11]>,
// (args_0: string, args_1: number, ...args_2: unknown[]) => unknown
// >(true);
// util.assertEqual<
// z.infer<(typeof deepReadonlySchemas_0)[12]>,
// readonly string[]
// >(true);
// util.assertEqual<
// z.infer<(typeof deepReadonlySchemas_0)[13]>,
// readonly [string, number]
// >(true);
// util.assertEqual<
// z.infer<(typeof deepReadonlySchemas_0)[14]>,
// ReadonlyMap<string, Date>
// >(true);
// util.assertEqual<
// z.infer<(typeof deepReadonlySchemas_0)[15]>,
// ReadonlySet<Promise<string>>
// >(true);
// util.assertEqual<
// z.infer<(typeof deepReadonlySchemas_0)[16]>,
// Readonly<Record<string, string>>
// >(true);
// util.assertEqual<
// z.infer<(typeof deepReadonlySchemas_0)[17]>,
// Readonly<Record<string, number>>
// >(true);
// util.assertEqual<
// z.infer<(typeof deepReadonlySchemas_0)[18]>,
// { readonly a: string; readonly 1: number }
// >(true);
// util.assertEqual<
// z.infer<(typeof deepReadonlySchemas_0)[19]>,
// Readonly<testEnum>
// >(true);
// util.assertEqual<
// z.infer<(typeof deepReadonlySchemas_0)[20]>,
// Promise<string>
// >(true);
// util.assertEqual<
// z.infer<typeof crazyDeepReadonlySchema>,
// ReadonlyMap<
// ReadonlySet<readonly [string, number]>,
// {
// readonly a: {
// readonly [x: string]: readonly any[];
// };
// readonly b: {
// readonly c: {
// readonly d: {
// readonly e: {
// readonly f: {
// readonly g?: {};
// };
// };
// };
// };
// };
// }
// >
// >(true);
// });
test("object freezing", () => {
expect(Object.isFrozen(z.array(z.string()).readonly().parse(["a"]))).toBe(true);
expect(Object.isFrozen(z.tuple([z.string(), z.number()]).readonly().parse(["a", 1]))).toBe(true);
expect(
Object.isFrozen(
z
.map(z.string(), z.date())
.readonly()
.parse(new Map([["a", new Date()]]))
)
).toBe(true);
expect(
Object.isFrozen(
z
.set(z.promise(z.string()))
.readonly()
.parse(new Set([Promise.resolve("a")]))
)
).toBe(true);
expect(Object.isFrozen(z.record(z.string()).readonly().parse({ a: "b" }))).toBe(true);
expect(Object.isFrozen(z.record(z.string(), z.number()).readonly().parse({ a: 1 }))).toBe(true);
expect(Object.isFrozen(z.object({ a: z.string(), 1: z.number() }).readonly().parse({ a: "b", 1: 2 }))).toBe(true);
expect(Object.isFrozen(z.promise(z.string()).readonly().parse(Promise.resolve("a")))).toBe(true);
});
test("async object freezing", async () => {
expect(Object.isFrozen(await z.array(z.string()).readonly().parseAsync(["a"]))).toBe(true);
expect(Object.isFrozen(await z.tuple([z.string(), z.number()]).readonly().parseAsync(["a", 1]))).toBe(true);
expect(
Object.isFrozen(
await z
.map(z.string(), z.date())
.readonly()
.parseAsync(new Map([["a", new Date()]]))
)
).toBe(true);
expect(
Object.isFrozen(
await z
.set(z.promise(z.string()))
.readonly()
.parseAsync(new Set([Promise.resolve("a")]))
)
).toBe(true);
expect(Object.isFrozen(await z.record(z.string()).readonly().parseAsync({ a: "b" }))).toBe(true);
expect(Object.isFrozen(await z.record(z.string(), z.number()).readonly().parseAsync({ a: 1 }))).toBe(true);
expect(
Object.isFrozen(await z.object({ a: z.string(), 1: z.number() }).readonly().parseAsync({ a: "b", 1: 2 }))
).toBe(true);
expect(Object.isFrozen(await z.promise(z.string()).readonly().parseAsync(Promise.resolve("a")))).toBe(true);
});

View file

@ -1,171 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
const booleanRecord = z.record(z.boolean());
type booleanRecord = z.infer<typeof booleanRecord>;
const recordWithEnumKeys = z.record(z.enum(["Tuna", "Salmon"]), z.string());
type recordWithEnumKeys = z.infer<typeof recordWithEnumKeys>;
const recordWithLiteralKeys = z.record(z.union([z.literal("Tuna"), z.literal("Salmon")]), z.string());
type recordWithLiteralKeys = z.infer<typeof recordWithLiteralKeys>;
test("type inference", () => {
util.assertEqual<booleanRecord, Record<string, boolean>>(true);
util.assertEqual<recordWithEnumKeys, Partial<Record<"Tuna" | "Salmon", string>>>(true);
util.assertEqual<recordWithLiteralKeys, Partial<Record<"Tuna" | "Salmon", string>>>(true);
});
test("methods", () => {
booleanRecord.optional();
booleanRecord.nullable();
});
test("string record parse - pass", () => {
booleanRecord.parse({
k1: true,
k2: false,
1234: false,
});
});
test("string record parse - fail", () => {
const badCheck = () =>
booleanRecord.parse({
asdf: 1234,
} as any);
expect(badCheck).toThrow();
expect(() => booleanRecord.parse("asdf")).toThrow();
});
test("string record parse - fail", () => {
const badCheck = () =>
booleanRecord.parse({
asdf: {},
} as any);
expect(badCheck).toThrow();
});
test("string record parse - fail", () => {
const badCheck = () =>
booleanRecord.parse({
asdf: [],
} as any);
expect(badCheck).toThrow();
});
test("key schema", () => {
const result1 = recordWithEnumKeys.parse({
Tuna: "asdf",
Salmon: "asdf",
});
expect(result1).toEqual({
Tuna: "asdf",
Salmon: "asdf",
});
const result2 = recordWithLiteralKeys.parse({
Tuna: "asdf",
Salmon: "asdf",
});
expect(result2).toEqual({
Tuna: "asdf",
Salmon: "asdf",
});
// shouldn't require us to specify all props in record
const result3 = recordWithEnumKeys.parse({
Tuna: "abcd",
});
expect(result3).toEqual({
Tuna: "abcd",
});
// shouldn't require us to specify all props in record
const result4 = recordWithLiteralKeys.parse({
Salmon: "abcd",
});
expect(result4).toEqual({
Salmon: "abcd",
});
expect(() =>
recordWithEnumKeys.parse({
Tuna: "asdf",
Salmon: "asdf",
Trout: "asdf",
})
).toThrow();
expect(() =>
recordWithLiteralKeys.parse({
Tuna: "asdf",
Salmon: "asdf",
Trout: "asdf",
})
).toThrow();
});
// test("record element", () => {
// expect(booleanRecord.element).toBeInstanceOf(z.ZodBoolean);
// });
test("key and value getters", () => {
const rec = z.record(z.string(), z.number());
rec.keySchema.parse("asdf");
rec.valueSchema.parse(1234);
rec.element.parse(1234);
});
test("is not vulnerable to prototype pollution", async () => {
const rec = z.record(
z.object({
a: z.string(),
})
);
const data = JSON.parse(`
{
"__proto__": {
"a": "evil"
},
"b": {
"a": "good"
}
}
`);
const obj1 = rec.parse(data);
expect(obj1.a).toBeUndefined();
const obj2 = rec.safeParse(data);
expect(obj2.success).toBe(true);
if (obj2.success) {
expect(obj2.data.a).toBeUndefined();
}
const obj3 = await rec.parseAsync(data);
expect(obj3.a).toBeUndefined();
const obj4 = await rec.safeParseAsync(data);
expect(obj4.success).toBe(true);
if (obj4.success) {
expect(obj4.data.a).toBeUndefined();
}
});
test("dont parse undefined values", () => {
const result1 = z.record(z.any()).parse({ foo: undefined });
expect(result1).toEqual({
foo: undefined,
});
});

View file

@ -1,197 +0,0 @@
// @ts-ignore TS6133
import { test } from "vitest";
import { z } from "zod/v3";
interface Category {
name: string;
subcategories: Category[];
}
const testCategory: Category = {
name: "I",
subcategories: [
{
name: "A",
subcategories: [
{
name: "1",
subcategories: [
{
name: "a",
subcategories: [],
},
],
},
],
},
],
};
test("recursion with z.late.object", () => {
const Category: z.ZodType<Category> = z.late.object(() => ({
name: z.string(),
subcategories: z.array(Category),
}));
Category.parse(testCategory);
});
test("recursion with z.lazy", () => {
const Category: z.ZodType<Category> = z.lazy(() =>
z.object({
name: z.string(),
subcategories: z.array(Category),
})
);
Category.parse(testCategory);
});
test("schema getter", () => {
z.lazy(() => z.string()).schema.parse("asdf");
});
type LinkedList = null | { value: number; next: LinkedList };
const linkedListExample = {
value: 1,
next: {
value: 2,
next: {
value: 3,
next: {
value: 4,
next: null,
},
},
},
};
test("recursion involving union type", () => {
const LinkedListSchema: z.ZodType<LinkedList> = z.lazy(() =>
z.union([
z.null(),
z.object({
value: z.number(),
next: LinkedListSchema,
}),
])
);
LinkedListSchema.parse(linkedListExample);
});
// interface A {
// val: number;
// b: B;
// }
// interface B {
// val: number;
// a: A;
// }
// const A: z.ZodType<A> = z.late.object(() => ({
// val: z.number(),
// b: B,
// }));
// const B: z.ZodType<B> = z.late.object(() => ({
// val: z.number(),
// a: A,
// }));
// const Alazy: z.ZodType<A> = z.lazy(() => z.object({
// val: z.number(),
// b: B,
// }));
// const Blazy: z.ZodType<B> = z.lazy(() => z.object({
// val: z.number(),
// a: A,
// }));
// const a: any = { val: 1 };
// const b: any = { val: 2 };
// a.b = b;
// b.a = a;
// test('valid check', () => {
// A.parse(a);
// B.parse(b);
// });
// test("valid check lazy", () => {
// A.parse({val:1, b:});
// B.parse(b);
// });
// test('masking check', () => {
// const FragmentOnA = z
// .object({
// val: z.number(),
// b: z
// .object({
// val: z.number(),
// a: z
// .object({
// val: z.number(),
// })
// .nonstrict(),
// })
// .nonstrict(),
// })
// .nonstrict();
// const fragment = FragmentOnA.parse(a);
// fragment;
// });
// test('invalid check', () => {
// expect(() => A.parse({} as any)).toThrow();
// });
// test('schema getter', () => {
// (A as z.ZodLazy<any>).schema;
// });
// test("self recursion with cyclical data", () => {
// interface Category {
// name: string;
// subcategories: Category[];
// }
// const Category: z.ZodType<Category> = z.late.object(() => ({
// name: z.string(),
// subcategories: z.array(Category),
// }));
// const untypedCategory: any = {
// name: "Category A",
// };
// // creating a cycle
// untypedCategory.subcategories = [untypedCategory];
// Category.parse(untypedCategory);
// });
// test("self recursion with base type", () => {
// const BaseCategory = z.object({
// name: z.string(),
// });
// type BaseCategory = z.infer<typeof BaseCategory>;
// type Category = BaseCategory & { subcategories: Category[] };
// const Category: z.ZodType<Category> = z.late
// .object(() => ({
// subcategories: z.array(Category),
// }))
// .extend({
// name: z.string(),
// });
// const untypedCategory: any = {
// name: "Category A",
// };
// // creating a cycle
// untypedCategory.subcategories = [untypedCategory];
// Category.parse(untypedCategory); // parses successfully
// });

View file

@ -1,313 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { ZodIssueCode } from "../ZodError.js";
import { util } from "../helpers/util.js";
test("refinement", () => {
const obj1 = z.object({
first: z.string(),
second: z.string(),
});
const obj2 = obj1.partial().strict();
const obj3 = obj2.refine((data) => data.first || data.second, "Either first or second should be filled in.");
expect(obj1 === (obj2 as any)).toEqual(false);
expect(obj2 === (obj3 as any)).toEqual(false);
expect(() => obj1.parse({})).toThrow();
expect(() => obj2.parse({ third: "adsf" })).toThrow();
expect(() => obj3.parse({})).toThrow();
obj3.parse({ first: "a" });
obj3.parse({ second: "a" });
obj3.parse({ first: "a", second: "a" });
});
test("refinement 2", () => {
const validationSchema = z
.object({
email: z.string().email(),
password: z.string(),
confirmPassword: z.string(),
})
.refine((data) => data.password === data.confirmPassword, "Both password and confirmation must match");
expect(() =>
validationSchema.parse({
email: "aaaa@gmail.com",
password: "aaaaaaaa",
confirmPassword: "bbbbbbbb",
})
).toThrow();
});
test("refinement type guard", () => {
const validationSchema = z.object({
a: z.string().refine((s): s is "a" => s === "a"),
});
type Input = z.input<typeof validationSchema>;
type Schema = z.infer<typeof validationSchema>;
util.assertEqual<"a", Input["a"]>(false);
util.assertEqual<string, Input["a"]>(true);
util.assertEqual<"a", Schema["a"]>(true);
util.assertEqual<string, Schema["a"]>(false);
});
test("refinement Promise", async () => {
const validationSchema = z
.object({
email: z.string().email(),
password: z.string(),
confirmPassword: z.string(),
})
.refine(
(data) => Promise.resolve().then(() => data.password === data.confirmPassword),
"Both password and confirmation must match"
);
await validationSchema.parseAsync({
email: "aaaa@gmail.com",
password: "password",
confirmPassword: "password",
});
});
test("custom path", async () => {
const result = await z
.object({
password: z.string(),
confirm: z.string(),
})
.refine((data) => data.confirm === data.password, { path: ["confirm"] })
.spa({ password: "asdf", confirm: "qewr" });
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].path).toEqual(["confirm"]);
}
});
test("use path in refinement context", async () => {
const noNested = z.string()._refinement((_val, ctx) => {
if (ctx.path.length > 0) {
ctx.addIssue({
code: ZodIssueCode.custom,
message: `schema cannot be nested. path: ${ctx.path.join(".")}`,
});
return false;
} else {
return true;
}
});
const data = z.object({
foo: noNested,
});
const t1 = await noNested.spa("asdf");
const t2 = await data.spa({ foo: "asdf" });
expect(t1.success).toBe(true);
expect(t2.success).toBe(false);
if (t2.success === false) {
expect(t2.error.issues[0].message).toEqual("schema cannot be nested. path: foo");
}
});
test("superRefine", () => {
const Strings = z.array(z.string()).superRefine((val, ctx) => {
if (val.length > 3) {
ctx.addIssue({
code: z.ZodIssueCode.too_big,
maximum: 3,
type: "array",
inclusive: true,
exact: true,
message: "Too many items 😡",
});
}
if (val.length !== new Set(val).size) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `No duplicates allowed.`,
});
}
});
const result = Strings.safeParse(["asfd", "asfd", "asfd", "asfd"]);
expect(result.success).toEqual(false);
if (!result.success) expect(result.error.issues.length).toEqual(2);
Strings.parse(["asfd", "qwer"]);
});
test("superRefine async", async () => {
const Strings = z.array(z.string()).superRefine(async (val, ctx) => {
if (val.length > 3) {
ctx.addIssue({
code: z.ZodIssueCode.too_big,
maximum: 3,
type: "array",
inclusive: true,
exact: true,
message: "Too many items 😡",
});
}
if (val.length !== new Set(val).size) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `No duplicates allowed.`,
});
}
});
const result = await Strings.safeParseAsync(["asfd", "asfd", "asfd", "asfd"]);
expect(result.success).toEqual(false);
if (!result.success) expect(result.error.issues.length).toEqual(2);
Strings.parseAsync(["asfd", "qwer"]);
});
test("superRefine - type narrowing", () => {
type NarrowType = { type: string; age: number };
const schema = z
.object({
type: z.string(),
age: z.number(),
})
.nullable()
.superRefine((arg, ctx): arg is NarrowType => {
if (!arg) {
// still need to make a call to ctx.addIssue
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "cannot be null",
fatal: true,
});
return false;
}
return true;
});
util.assertEqual<z.infer<typeof schema>, NarrowType>(true);
expect(schema.safeParse({ type: "test", age: 0 }).success).toEqual(true);
expect(schema.safeParse(null).success).toEqual(false);
});
test("chained mixed refining types", () => {
type firstRefinement = { first: string; second: number; third: true };
type secondRefinement = { first: "bob"; second: number; third: true };
type thirdRefinement = { first: "bob"; second: 33; third: true };
const schema = z
.object({
first: z.string(),
second: z.number(),
third: z.boolean(),
})
.nullable()
.refine((arg): arg is firstRefinement => !!arg?.third)
.superRefine((arg, ctx): arg is secondRefinement => {
util.assertEqual<typeof arg, firstRefinement>(true);
if (arg.first !== "bob") {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "`first` property must be `bob`",
});
return false;
}
return true;
})
.refine((arg): arg is thirdRefinement => {
util.assertEqual<typeof arg, secondRefinement>(true);
return arg.second === 33;
});
util.assertEqual<z.infer<typeof schema>, thirdRefinement>(true);
});
test("get inner type", () => {
z.string()
.refine(() => true)
.innerType()
.parse("asdf");
});
test("chained refinements", () => {
const objectSchema = z
.object({
length: z.number(),
size: z.number(),
})
.refine(({ length }) => length > 5, {
path: ["length"],
message: "length greater than 5",
})
.refine(({ size }) => size > 7, {
path: ["size"],
message: "size greater than 7",
});
const r1 = objectSchema.safeParse({
length: 4,
size: 9,
});
expect(r1.success).toEqual(false);
if (!r1.success) expect(r1.error.issues.length).toEqual(1);
const r2 = objectSchema.safeParse({
length: 4,
size: 3,
});
expect(r2.success).toEqual(false);
if (!r2.success) expect(r2.error.issues.length).toEqual(2);
});
test("fatal superRefine", () => {
const Strings = z
.string()
.superRefine((val, ctx) => {
if (val === "") {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "foo",
fatal: true,
});
}
})
.superRefine((val, ctx) => {
if (val !== " ") {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "bar",
});
}
});
const result = Strings.safeParse("");
expect(result.success).toEqual(false);
if (!result.success) expect(result.error.issues.length).toEqual(1);
});
test("superRefine after skipped transform", () => {
const schema = z
.string()
.regex(/^\d+$/)
.transform((val) => Number(val))
.superRefine((val) => {
if (typeof val !== "number") {
throw new Error("Called without transform");
}
});
const result = schema.safeParse("");
expect(result.success).toEqual(false);
});

View file

@ -1,27 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
const stringSchema = z.string();
test("safeparse fail", () => {
const safe = stringSchema.safeParse(12);
expect(safe.success).toEqual(false);
expect(safe.error).toBeInstanceOf(z.ZodError);
});
test("safeparse pass", () => {
const safe = stringSchema.safeParse("12");
expect(safe.success).toEqual(true);
expect(safe.data).toEqual("12");
});
test("safeparse unexpected error", () => {
expect(() =>
stringSchema
.refine((data) => {
throw new Error(data);
})
.safeParse("12")
).toThrow();
});

View file

@ -1,142 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { ZodIssueCode } from "zod/v3";
import { util } from "../helpers/util.js";
const stringSet = z.set(z.string());
type stringSet = z.infer<typeof stringSet>;
const minTwo = z.set(z.string()).min(2);
const maxTwo = z.set(z.string()).max(2);
const justTwo = z.set(z.string()).size(2);
const nonEmpty = z.set(z.string()).nonempty();
const nonEmptyMax = z.set(z.string()).nonempty().max(2);
test("type inference", () => {
util.assertEqual<stringSet, Set<string>>(true);
});
test("valid parse", () => {
const result = stringSet.safeParse(new Set(["first", "second"]));
expect(result.success).toEqual(true);
if (result.success) {
expect(result.data.has("first")).toEqual(true);
expect(result.data.has("second")).toEqual(true);
expect(result.data.has("third")).toEqual(false);
}
expect(() => {
minTwo.parse(new Set(["a", "b"]));
minTwo.parse(new Set(["a", "b", "c"]));
maxTwo.parse(new Set(["a", "b"]));
maxTwo.parse(new Set(["a"]));
justTwo.parse(new Set(["a", "b"]));
nonEmpty.parse(new Set(["a"]));
nonEmptyMax.parse(new Set(["a"]));
}).not.toThrow();
});
test("valid parse async", async () => {
const result = await stringSet.spa(new Set(["first", "second"]));
expect(result.success).toEqual(true);
if (result.success) {
expect(result.data.has("first")).toEqual(true);
expect(result.data.has("second")).toEqual(true);
expect(result.data.has("third")).toEqual(false);
}
const asyncResult = await stringSet.safeParse(new Set(["first", "second"]));
expect(asyncResult.success).toEqual(true);
if (asyncResult.success) {
expect(asyncResult.data.has("first")).toEqual(true);
expect(asyncResult.data.has("second")).toEqual(true);
expect(asyncResult.data.has("third")).toEqual(false);
}
});
test("valid parse: size-related methods", () => {
expect(() => {
minTwo.parse(new Set(["a", "b"]));
minTwo.parse(new Set(["a", "b", "c"]));
maxTwo.parse(new Set(["a", "b"]));
maxTwo.parse(new Set(["a"]));
justTwo.parse(new Set(["a", "b"]));
nonEmpty.parse(new Set(["a"]));
nonEmptyMax.parse(new Set(["a"]));
}).not.toThrow();
const sizeZeroResult = stringSet.parse(new Set());
expect(sizeZeroResult.size).toBe(0);
const sizeTwoResult = minTwo.parse(new Set(["a", "b"]));
expect(sizeTwoResult.size).toBe(2);
});
test("failing when parsing empty set in nonempty ", () => {
const result = nonEmpty.safeParse(new Set());
expect(result.success).toEqual(false);
if (result.success === false) {
expect(result.error.issues.length).toEqual(1);
expect(result.error.issues[0].code).toEqual(ZodIssueCode.too_small);
}
});
test("failing when set is smaller than min() ", () => {
const result = minTwo.safeParse(new Set(["just_one"]));
expect(result.success).toEqual(false);
if (result.success === false) {
expect(result.error.issues.length).toEqual(1);
expect(result.error.issues[0].code).toEqual(ZodIssueCode.too_small);
}
});
test("failing when set is bigger than max() ", () => {
const result = maxTwo.safeParse(new Set(["one", "two", "three"]));
expect(result.success).toEqual(false);
if (result.success === false) {
expect(result.error.issues.length).toEqual(1);
expect(result.error.issues[0].code).toEqual(ZodIssueCode.too_big);
}
});
test("doesnt throw when an empty set is given", () => {
const result = stringSet.safeParse(new Set([]));
expect(result.success).toEqual(true);
});
test("throws when a Map is given", () => {
const result = stringSet.safeParse(new Map([]));
expect(result.success).toEqual(false);
if (result.success === false) {
expect(result.error.issues.length).toEqual(1);
expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type);
}
});
test("throws when the given set has invalid input", () => {
const result = stringSet.safeParse(new Set([Symbol()]));
expect(result.success).toEqual(false);
if (result.success === false) {
expect(result.error.issues.length).toEqual(1);
expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type);
expect(result.error.issues[0].path).toEqual([0]);
}
});
test("throws when the given set has multiple invalid entries", () => {
const result = stringSet.safeParse(new Set([1, 2] as any[]) as Set<any>);
expect(result.success).toEqual(false);
if (result.success === false) {
expect(result.error.issues.length).toEqual(2);
expect(result.error.issues[0].code).toEqual(ZodIssueCode.invalid_type);
expect(result.error.issues[0].path).toEqual([0]);
expect(result.error.issues[1].code).toEqual(ZodIssueCode.invalid_type);
expect(result.error.issues[1].path).toEqual([1]);
}
});

View file

@ -1,83 +0,0 @@
// import type { StandardSchemaV1 } from "@standard-schema/spec";
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
import type { StandardSchemaV1 } from "../standard-schema.js";
test("assignability", () => {
const _s1: StandardSchemaV1 = z.string();
const _s2: StandardSchemaV1<string> = z.string();
const _s3: StandardSchemaV1<string, string> = z.string();
const _s4: StandardSchemaV1<unknown, string> = z.string();
[_s1, _s2, _s3, _s4];
});
test("type inference", () => {
const stringToNumber = z.string().transform((x) => x.length);
type input = StandardSchemaV1.InferInput<typeof stringToNumber>;
util.assertEqual<input, string>(true);
type output = StandardSchemaV1.InferOutput<typeof stringToNumber>;
util.assertEqual<output, number>(true);
});
test("valid parse", () => {
const schema = z.string();
const result = schema["~standard"].validate("hello");
if (result instanceof Promise) {
throw new Error("Expected sync result");
}
expect(result.issues).toEqual(undefined);
if (result.issues) {
throw new Error("Expected no issues");
} else {
expect(result.value).toEqual("hello");
}
});
test("invalid parse", () => {
const schema = z.string();
const result = schema["~standard"].validate(1234);
if (result instanceof Promise) {
throw new Error("Expected sync result");
}
expect(result.issues).toBeDefined();
if (!result.issues) {
throw new Error("Expected issues");
}
expect(result.issues.length).toEqual(1);
expect(result.issues[0].path).toEqual([]);
});
test("valid parse async", async () => {
const schema = z.string().refine(async () => true);
const _result = schema["~standard"].validate("hello");
if (_result instanceof Promise) {
const result = await _result;
expect(result.issues).toEqual(undefined);
if (result.issues) {
throw new Error("Expected no issues");
} else {
expect(result.value).toEqual("hello");
}
} else {
throw new Error("Expected async result");
}
});
test("invalid parse async", async () => {
const schema = z.string().refine(async () => false);
const _result = schema["~standard"].validate("hello");
if (_result instanceof Promise) {
const result = await _result;
expect(result.issues).toBeDefined();
if (!result.issues) {
throw new Error("Expected issues");
}
expect(result.issues.length).toEqual(1);
expect(result.issues[0].path).toEqual([]);
} else {
throw new Error("Expected async result");
}
});

File diff suppressed because one or more lines are too long

View file

@ -1,233 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { util } from "../helpers/util.js";
const stringToNumber = z.string().transform((arg) => Number.parseFloat(arg));
// const numberToString = z
// .transformer(z.number())
// .transform((n) => String(n));
const asyncNumberToString = z.number().transform(async (n) => String(n));
test("transform ctx.addIssue with parse", () => {
const strs = ["foo", "bar"];
expect(() => {
z.string()
.transform((data, ctx) => {
const i = strs.indexOf(data);
if (i === -1) {
ctx.addIssue({
code: "custom",
message: `${data} is not one of our allowed strings`,
});
}
return data.length;
})
.parse("asdf");
}).toThrow(
JSON.stringify(
[
{
code: "custom",
message: "asdf is not one of our allowed strings",
path: [],
},
],
null,
2
)
);
});
test("transform ctx.addIssue with parseAsync", async () => {
const strs = ["foo", "bar"];
const result = await z
.string()
.transform(async (data, ctx) => {
const i = strs.indexOf(data);
if (i === -1) {
ctx.addIssue({
code: "custom",
message: `${data} is not one of our allowed strings`,
});
}
return data.length;
})
.safeParseAsync("asdf");
expect(JSON.parse(JSON.stringify(result))).toEqual({
success: false,
error: {
issues: [
{
code: "custom",
message: "asdf is not one of our allowed strings",
path: [],
},
],
name: "ZodError",
},
});
});
test("z.NEVER in transform", () => {
const foo = z
.number()
.optional()
.transform((val, ctx) => {
if (!val) {
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "bad" });
return z.NEVER;
}
return val;
});
type foo = z.infer<typeof foo>;
util.assertEqual<foo, number>(true);
const arg = foo.safeParse(undefined);
if (!arg.success) {
expect(arg.error.issues[0].message).toEqual("bad");
}
});
test("basic transformations", () => {
const r1 = z
.string()
.transform((data) => data.length)
.parse("asdf");
expect(r1).toEqual(4);
});
test("coercion", () => {
const numToString = z.number().transform((n) => String(n));
const data = z
.object({
id: numToString,
})
.parse({ id: 5 });
expect(data).toEqual({ id: "5" });
});
test("async coercion", async () => {
const numToString = z.number().transform(async (n) => String(n));
const data = await z
.object({
id: numToString,
})
.parseAsync({ id: 5 });
expect(data).toEqual({ id: "5" });
});
test("sync coercion async error", async () => {
expect(() =>
z
.object({
id: asyncNumberToString,
})
.parse({ id: 5 })
).toThrow();
// expect(data).toEqual({ id: '5' });
});
test("default", () => {
const data = z.string().default("asdf").parse(undefined); // => "asdf"
expect(data).toEqual("asdf");
});
test("dynamic default", () => {
const data = z
.string()
.default(() => "string")
.parse(undefined); // => "asdf"
expect(data).toEqual("string");
});
test("default when property is null or undefined", () => {
const data = z
.object({
foo: z.boolean().nullable().default(true),
bar: z.boolean().default(true),
})
.parse({ foo: null });
expect(data).toEqual({ foo: null, bar: true });
});
test("default with falsy values", () => {
const schema = z.object({
emptyStr: z.string().default("def"),
zero: z.number().default(5),
falseBoolean: z.boolean().default(true),
});
const input = { emptyStr: "", zero: 0, falseBoolean: true };
const output = schema.parse(input);
// defaults are not supposed to be used
expect(output).toEqual(input);
});
test("object typing", () => {
const t1 = z.object({
stringToNumber,
});
type t1 = z.input<typeof t1>;
type t2 = z.output<typeof t1>;
util.assertEqual<t1, { stringToNumber: string }>(true);
util.assertEqual<t2, { stringToNumber: number }>(true);
});
test("transform method overloads", () => {
const t1 = z.string().transform((val) => val.toUpperCase());
expect(t1.parse("asdf")).toEqual("ASDF");
const t2 = z.string().transform((val) => val.length);
expect(t2.parse("asdf")).toEqual(4);
});
test("multiple transformers", () => {
const doubler = stringToNumber.transform((val) => {
return val * 2;
});
expect(doubler.parse("5")).toEqual(10);
});
test("short circuit on dirty", () => {
const schema = z
.string()
.refine(() => false)
.transform((val) => val.toUpperCase());
const result = schema.safeParse("asdf");
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].code).toEqual(z.ZodIssueCode.custom);
}
const result2 = schema.safeParse(1234);
expect(result2.success).toEqual(false);
if (!result2.success) {
expect(result2.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_type);
}
});
test("async short circuit on dirty", async () => {
const schema = z
.string()
.refine(() => false)
.transform((val) => val.toUpperCase());
const result = await schema.spa("asdf");
expect(result.success).toEqual(false);
if (!result.success) {
expect(result.error.issues[0].code).toEqual(z.ZodIssueCode.custom);
}
const result2 = await schema.spa(1234);
expect(result2.success).toEqual(false);
if (!result2.success) {
expect(result2.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_type);
}
});

View file

@ -1,90 +0,0 @@
// @ts-ignore TS6133
import { expect, test } from "vitest";
import * as z from "zod/v3";
import { ZodError } from "../ZodError.js";
import { util } from "../helpers/util.js";
const testTuple = z.tuple([z.string(), z.object({ name: z.literal("Rudy") }), z.array(z.literal("blue"))]);
const testData = ["asdf", { name: "Rudy" }, ["blue"]];
const badData = [123, { name: "Rudy2" }, ["blue", "red"]];
test("tuple inference", () => {
const args1 = z.tuple([z.string()]);
const returns1 = z.number();
const func1 = z.function(args1, returns1);
type func1 = z.TypeOf<typeof func1>;
util.assertEqual<func1, (k: string) => number>(true);
});
test("successful validation", () => {
const val = testTuple.parse(testData);
expect(val).toEqual(["asdf", { name: "Rudy" }, ["blue"]]);
});
test("successful async validation", async () => {
const val = await testTuple.parseAsync(testData);
return expect(val).toEqual(testData);
});
test("failed validation", () => {
const checker = () => {
testTuple.parse([123, { name: "Rudy2" }, ["blue", "red"]] as any);
};
try {
checker();
} catch (err) {
if (err instanceof ZodError) {
expect(err.issues.length).toEqual(3);
}
}
});
test("failed async validation", async () => {
const res = await testTuple.safeParse(badData);
expect(res.success).toEqual(false);
if (!res.success) {
expect(res.error.issues.length).toEqual(3);
}
// try {
// checker();
// } catch (err) {
// if (err instanceof ZodError) {
// expect(err.issues.length).toEqual(3);
// }
// }
});
test("tuple with transformers", () => {
const stringToNumber = z.string().transform((val) => val.length);
const val = z.tuple([stringToNumber]);
type t1 = z.input<typeof val>;
util.assertEqual<t1, [string]>(true);
type t2 = z.output<typeof val>;
util.assertEqual<t2, [number]>(true);
expect(val.parse(["1234"])).toEqual([4]);
});
test("tuple with rest schema", () => {
const myTuple = z.tuple([z.string(), z.number()]).rest(z.boolean());
expect(myTuple.parse(["asdf", 1234, true, false, true])).toEqual(["asdf", 1234, true, false, true]);
expect(myTuple.parse(["asdf", 1234])).toEqual(["asdf", 1234]);
expect(() => myTuple.parse(["asdf", 1234, "asdf"])).toThrow();
type t1 = z.output<typeof myTuple>;
util.assertEqual<t1, [string, number, ...boolean[]]>(true);
});
test("parse should fail given sparse array as tuple", () => {
expect(() => testTuple.parse(new Array(3))).toThrow();
});
// test('tuple with optional elements', () => {
// const result = z
// .tuple([z.string(), z.number().optional()])
// .safeParse(['asdf']);
// expect(result).toEqual(['asdf']);
// });

Some files were not shown because too many files have changed in this diff Show more