UNPKG

zod

Version:

TypeScript-first schema declaration and validation library with static type inference

412 lines (411 loc) 12.5 kB
"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; }; Object.defineProperty(exports, "__esModule", { value: true }); const vitest_1 = require("vitest"); const z = __importStar(require("zod/v4")); const Test = z.object({ f1: z.number(), f2: z.string().optional(), f3: z.string().nullable(), f4: z.array(z.object({ t: z.union([z.string(), z.boolean()]) })), }); // type TestFlattenedErrors = core.inferFlattenedErrors<typeof Test, { message: string; code: number }>; // type TestFormErrors = core.inferFlattenedErrors<typeof Test>; const parsed = Test.safeParse({}); (0, vitest_1.test)("regular error", () => { (0, vitest_1.expect)(parsed).toMatchInlineSnapshot(` { "error": [ZodError: [ { "expected": "number", "code": "invalid_type", "path": [ "f1" ], "message": "Invalid input: expected number, received undefined" }, { "expected": "string", "code": "invalid_type", "path": [ "f3" ], "message": "Invalid input: expected string, received undefined" }, { "expected": "array", "code": "invalid_type", "path": [ "f4" ], "message": "Invalid input: expected array, received undefined" } ]], "success": false, } `); }); (0, vitest_1.test)(".flatten()", () => { const flattened = parsed.error.flatten(); // flattened. (0, vitest_1.expectTypeOf)(flattened).toMatchTypeOf(); (0, vitest_1.expect)(flattened).toMatchInlineSnapshot(` { "fieldErrors": { "f1": [ "Invalid input: expected number, received undefined", ], "f3": [ "Invalid input: expected string, received undefined", ], "f4": [ "Invalid input: expected array, received undefined", ], }, "formErrors": [], } `); }); (0, vitest_1.test)("custom .flatten()", () => { const flattened = parsed.error.flatten((iss) => ({ message: iss.message, code: 1234 })); (0, vitest_1.expectTypeOf)(flattened).toMatchTypeOf(); (0, vitest_1.expect)(flattened).toMatchInlineSnapshot(` { "fieldErrors": { "f1": [ { "code": 1234, "message": "Invalid input: expected number, received undefined", }, ], "f3": [ { "code": 1234, "message": "Invalid input: expected string, received undefined", }, ], "f4": [ { "code": 1234, "message": "Invalid input: expected array, received undefined", }, ], }, "formErrors": [], } `); }); (0, vitest_1.test)(".format()", () => { const formatted = parsed.error.format(); (0, vitest_1.expectTypeOf)(formatted).toMatchTypeOf(); (0, vitest_1.expect)(formatted).toMatchInlineSnapshot(` { "_errors": [], "f1": { "_errors": [ "Invalid input: expected number, received undefined", ], }, "f3": { "_errors": [ "Invalid input: expected string, received undefined", ], }, "f4": { "_errors": [ "Invalid input: expected array, received undefined", ], }, } `); }); (0, vitest_1.test)("custom .format()", () => { const formatted = parsed.error.format((iss) => ({ message: iss.message, code: 1234 })); (0, vitest_1.expectTypeOf)(formatted).toMatchTypeOf(); (0, vitest_1.expect)(formatted).toMatchInlineSnapshot(` { "_errors": [], "f1": { "_errors": [ { "code": 1234, "message": "Invalid input: expected number, received undefined", }, ], }, "f3": { "_errors": [ { "code": 1234, "message": "Invalid input: expected string, received undefined", }, ], }, "f4": { "_errors": [ { "code": 1234, "message": "Invalid input: expected array, received undefined", }, ], }, } `); }); (0, vitest_1.test)("all errors", () => { const propertySchema = z.string(); const schema = z .object({ a: propertySchema, b: propertySchema, }) .refine((val) => { return val.a === val.b; }, { message: "Must be equal" }); const r1 = schema.safeParse({ a: "asdf", b: "qwer", }); (0, vitest_1.expect)(z.core.flattenError(r1.error)).toEqual({ formErrors: ["Must be equal"], fieldErrors: {}, }); const r2 = schema.safeParse({ a: null, b: null, }); // const error = _error as z.ZodError; (0, vitest_1.expect)(z.core.flattenError(r2.error)).toMatchInlineSnapshot(` { "fieldErrors": { "a": [ "Invalid input: expected string, received null", ], "b": [ "Invalid input: expected string, received null", ], }, "formErrors": [], } `); (0, vitest_1.expect)(z.core.flattenError(r2.error, (iss) => iss.message.toUpperCase())).toMatchInlineSnapshot(` { "fieldErrors": { "a": [ "INVALID INPUT: EXPECTED STRING, RECEIVED NULL", ], "b": [ "INVALID INPUT: EXPECTED STRING, RECEIVED NULL", ], }, "formErrors": [], } `); // Test identity (0, vitest_1.expect)(z.core.flattenError(r2.error, (i) => i)).toMatchInlineSnapshot(` { "fieldErrors": { "a": [ { "code": "invalid_type", "expected": "string", "message": "Invalid input: expected string, received null", "path": [ "a", ], }, ], "b": [ { "code": "invalid_type", "expected": "string", "message": "Invalid input: expected string, received null", "path": [ "b", ], }, ], }, "formErrors": [], } `); // Test mapping const f1 = z.core.flattenError(r2.error, (i) => i.message.length); (0, vitest_1.expect)(f1).toMatchInlineSnapshot(` { "fieldErrors": { "a": [ 45, ], "b": [ 45, ], }, "formErrors": [], } `); // expect(f1.fieldErrors.a![0]).toEqual("Invalid input: expected string".length); // expect(f1).toMatchObject({ // formErrors: [], // fieldErrors: { // a: ["Invalid input: expected string".length], // b: ["Invalid input: expected string".length], // }, // }); }); const schema = z.strictObject({ username: z.string(), favoriteNumbers: z.array(z.number()), nesting: z.object({ a: z.string(), }), }); const result = schema.safeParse({ username: 1234, favoriteNumbers: [1234, "4567"], nesting: { a: 123, }, extra: 1234, }); (0, vitest_1.test)("z.treeifyError", () => { (0, vitest_1.expect)(z.treeifyError(result.error)).toMatchInlineSnapshot(` { "errors": [ "Unrecognized key: "extra"", ], "properties": { "favoriteNumbers": { "errors": [], "items": [ , { "errors": [ "Invalid input: expected number, received string", ], }, ], }, "nesting": { "errors": [], "properties": { "a": { "errors": [ "Invalid input: expected string, received number", ], }, }, }, "username": { "errors": [ "Invalid input: expected string, received number", ], }, }, } `); }); (0, vitest_1.test)("z.treeifyError 2", () => { const schema = z.strictObject({ name: z.string(), logLevel: z.union([z.string(), z.number()]), env: z.literal(["production", "development"]), }); const data = { name: 1000, logLevel: false, extra: 1000, }; const result = schema.safeParse(data); const err = z.treeifyError(result.error); (0, vitest_1.expect)(err).toMatchInlineSnapshot(` { "errors": [ "Unrecognized key: "extra"", ], "properties": { "env": { "errors": [ "Invalid option: expected one of "production"|"development"", ], }, "logLevel": { "errors": [ "Invalid input: expected string, received boolean", "Invalid input: expected number, received boolean", ], }, "name": { "errors": [ "Invalid input: expected string, received number", ], }, }, } `); }); (0, vitest_1.test)("z.prettifyError", () => { (0, vitest_1.expect)(z.prettifyError(result.error)).toMatchInlineSnapshot(` "✖ Unrecognized key: "extra" ✖ Invalid input: expected string, received number → at username ✖ Invalid input: expected number, received string → at favoriteNumbers[1] ✖ Invalid input: expected string, received number → at nesting.a" `); }); (0, vitest_1.test)("z.toDotPath", () => { (0, vitest_1.expect)(z.core.toDotPath(["a", "b", 0, "c"])).toMatchInlineSnapshot(`"a.b[0].c"`); (0, vitest_1.expect)(z.core.toDotPath(["a", Symbol("b"), 0, "c"])).toMatchInlineSnapshot(`"a["Symbol(b)"][0].c"`); // Test with periods in keys (0, vitest_1.expect)(z.core.toDotPath(["user.name", "first.last"])).toMatchInlineSnapshot(`"["user.name"]["first.last"]"`); // Test with special characters (0, vitest_1.expect)(z.core.toDotPath(["user", "$special", Symbol("#symbol")])).toMatchInlineSnapshot(`"user.$special["Symbol(#symbol)"]"`); // Test with dots and quotes (0, vitest_1.expect)(z.core.toDotPath(["search", `query("foo.bar"="abc")`])).toMatchInlineSnapshot(`"search["query(\\"foo.bar\\"=\\"abc\\")"]"`); // Test with newlines (0, vitest_1.expect)(z.core.toDotPath(["search", `foo\nbar`])).toMatchInlineSnapshot(`"search["foo\\nbar"]"`); // Test with empty strings (0, vitest_1.expect)(z.core.toDotPath(["", "empty"])).toMatchInlineSnapshot(`".empty"`); // Test with array indices (0, vitest_1.expect)(z.core.toDotPath(["items", 0, 1, 2])).toMatchInlineSnapshot(`"items[0][1][2]"`); // Test with mixed path elements (0, vitest_1.expect)(z.core.toDotPath(["users", "user.config", 0, "settings.theme"])).toMatchInlineSnapshot(`"users["user.config"][0]["settings.theme"]"`); // Test with square brackets in keys (0, vitest_1.expect)(z.core.toDotPath(["data[0]", "value"])).toMatchInlineSnapshot(`"["data[0]"].value"`); // Test with empty path (0, vitest_1.expect)(z.core.toDotPath([])).toMatchInlineSnapshot(`""`); }); (0, vitest_1.test)("inheritance", () => { const e1 = new z.ZodError([]); (0, vitest_1.expect)(e1).toBeInstanceOf(z.core.$ZodError); (0, vitest_1.expect)(e1).toBeInstanceOf(z.ZodError); // expect(e1).not.toBeInstanceOf(Error); const e2 = new z.ZodRealError([]); (0, vitest_1.expect)(e2).toBeInstanceOf(z.ZodError); (0, vitest_1.expect)(e2).toBeInstanceOf(z.ZodRealError); (0, vitest_1.expect)(e2).toBeInstanceOf(Error); });