UNPKG

zod

Version:

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

562 lines (560 loc) • 21.7 kB
"use strict"; // import { $ZodType } from "./schemas.js"; 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 }); exports.$ZodCheckOverwrite = exports.$ZodCheckMimeType = exports.$ZodCheckProperties = exports.$ZodCheckProperty = exports.$ZodCheckEndsWith = exports.$ZodCheckStartsWith = exports.$ZodCheckIncludes = exports.$ZodCheckUpperCase = exports.$ZodCheckLowerCase = exports.$ZodCheckRegex = exports.$ZodCheckStringFormat = exports.$ZodCheckLengthEquals = exports.$ZodCheckMinLength = exports.$ZodCheckMaxLength = exports.$ZodCheckSizeEquals = exports.$ZodCheckMinSize = exports.$ZodCheckMaxSize = exports.$ZodCheckBigIntFormat = exports.$ZodCheckNumberFormat = exports.$ZodCheckMultipleOf = exports.$ZodCheckGreaterThan = exports.$ZodCheckLessThan = exports.$ZodCheck = void 0; const core = __importStar(require("./core.cjs")); const regexes = __importStar(require("./regexes.cjs")); const util = __importStar(require("./util.cjs")); exports.$ZodCheck = core.$constructor("$ZodCheck", (inst, def) => { var _a; inst._zod ?? (inst._zod = {}); inst._zod.def = def; (_a = inst._zod).onattach ?? (_a.onattach = []); }); /** Default `when` for size-based checks: run only on non-nullish values with a `size`. */ const _whenHasSize = (payload) => { const val = payload.value; return !util.nullish(val) && val.size !== undefined; }; /** Default `when` for length-based checks: run only on non-nullish values with a `length`. */ const _whenHasLength = (payload) => { const val = payload.value; return !util.nullish(val) && val.length !== undefined; }; const numericOriginMap = { number: "number", bigint: "bigint", object: "date", }; exports.$ZodCheckLessThan = core.$constructor("$ZodCheckLessThan", (inst, def) => { exports.$ZodCheck.init(inst, def); const origin = numericOriginMap[typeof def.value]; inst._zod.check = (payload) => { if (def.inclusive ? payload.value <= def.value : payload.value < def.value) { return; } payload.issues.push({ origin: numericOriginMap[typeof payload.value] ?? origin, code: "too_big", maximum: typeof def.value === "object" ? def.value.getTime() : def.value, input: payload.value, inclusive: def.inclusive, inst, continue: !def.abort, }); }; }); exports.$ZodCheckGreaterThan = core.$constructor("$ZodCheckGreaterThan", (inst, def) => { exports.$ZodCheck.init(inst, def); const origin = numericOriginMap[typeof def.value]; inst._zod.check = (payload) => { if (def.inclusive ? payload.value >= def.value : payload.value > def.value) { return; } payload.issues.push({ origin: numericOriginMap[typeof payload.value] ?? origin, code: "too_small", minimum: typeof def.value === "object" ? def.value.getTime() : def.value, input: payload.value, inclusive: def.inclusive, inst, continue: !def.abort, }); }; }); exports.$ZodCheckMultipleOf = /*@__PURE__*/ core.$constructor("$ZodCheckMultipleOf", (inst, def) => { exports.$ZodCheck.init(inst, def); inst._zod.check = (payload) => { if (typeof payload.value !== typeof def.value) throw new Error("Cannot mix number and bigint in multiple_of check."); const isMultiple = typeof payload.value === "bigint" ? // `value % 0n` throws, and nothing is a multiple of zero — the number branch already fails this way via NaN def.value !== BigInt(0) && payload.value % def.value === BigInt(0) : util.floatSafeRemainder(payload.value, def.value) === 0; if (isMultiple) return; payload.issues.push({ origin: typeof payload.value, code: "not_multiple_of", divisor: def.value, input: payload.value, inst, continue: !def.abort, }); }; }); exports.$ZodCheckNumberFormat = core.$constructor("$ZodCheckNumberFormat", (inst, def) => { exports.$ZodCheck.init(inst, def); // no format checks def.format = def.format || "float64"; const isInt = def.format?.includes("int"); const origin = isInt ? "int" : "number"; const [minimum, maximum] = util.NUMBER_FORMAT_RANGES[def.format]; inst._zod.check = (payload) => { const input = payload.value; if (isInt) { if (!Number.isInteger(input)) { // invalid_format issue // payload.issues.push({ // expected: def.format, // format: def.format, // code: "invalid_format", // input, // inst, // }); // invalid_type issue payload.issues.push({ expected: origin, format: def.format, code: "invalid_type", continue: false, input, inst, }); return; // not_multiple_of issue // payload.issues.push({ // code: "not_multiple_of", // origin: "number", // input, // inst, // divisor: 1, // }); } if (!Number.isSafeInteger(input)) { if (input > 0) { // too_big payload.issues.push({ input, code: "too_big", maximum: Number.MAX_SAFE_INTEGER, note: "Integers must be within the safe integer range.", inst, origin, inclusive: true, continue: !def.abort, }); } else { // too_small payload.issues.push({ input, code: "too_small", minimum: Number.MIN_SAFE_INTEGER, note: "Integers must be within the safe integer range.", inst, origin, inclusive: true, continue: !def.abort, }); } return; } } if (input < minimum) { payload.issues.push({ origin: "number", input, code: "too_small", minimum, inclusive: true, inst, continue: !def.abort, }); } if (input > maximum) { payload.issues.push({ origin: "number", input, code: "too_big", maximum, inclusive: true, inst, continue: !def.abort, }); } }; }); exports.$ZodCheckBigIntFormat = core.$constructor("$ZodCheckBigIntFormat", (inst, def) => { exports.$ZodCheck.init(inst, def); // no format checks const [minimum, maximum] = util.BIGINT_FORMAT_RANGES[def.format]; inst._zod.check = (payload) => { const input = payload.value; if (input < minimum) { payload.issues.push({ origin: "bigint", input, code: "too_small", minimum: minimum, inclusive: true, inst, continue: !def.abort, }); } if (input > maximum) { payload.issues.push({ origin: "bigint", input, code: "too_big", maximum, inclusive: true, inst, continue: !def.abort, }); } }; }); exports.$ZodCheckMaxSize = core.$constructor("$ZodCheckMaxSize", (inst, def) => { var _a; exports.$ZodCheck.init(inst, def); (_a = inst._zod.def).when ?? (_a.when = _whenHasSize); inst._zod.check = (payload) => { const input = payload.value; const size = input.size; if (size <= def.maximum) return; payload.issues.push({ origin: util.getSizableOrigin(input), code: "too_big", maximum: def.maximum, inclusive: true, input, inst, continue: !def.abort, }); }; }); exports.$ZodCheckMinSize = core.$constructor("$ZodCheckMinSize", (inst, def) => { var _a; exports.$ZodCheck.init(inst, def); (_a = inst._zod.def).when ?? (_a.when = _whenHasSize); inst._zod.check = (payload) => { const input = payload.value; const size = input.size; if (size >= def.minimum) return; payload.issues.push({ origin: util.getSizableOrigin(input), code: "too_small", minimum: def.minimum, inclusive: true, input, inst, continue: !def.abort, }); }; }); exports.$ZodCheckSizeEquals = core.$constructor("$ZodCheckSizeEquals", (inst, def) => { var _a; exports.$ZodCheck.init(inst, def); (_a = inst._zod.def).when ?? (_a.when = _whenHasSize); inst._zod.check = (payload) => { const input = payload.value; const size = input.size; if (size === def.size) return; const tooBig = size > def.size; payload.issues.push({ origin: util.getSizableOrigin(input), ...(tooBig ? { code: "too_big", maximum: def.size } : { code: "too_small", minimum: def.size }), inclusive: true, exact: true, input: payload.value, inst, continue: !def.abort, }); }; }); exports.$ZodCheckMaxLength = core.$constructor("$ZodCheckMaxLength", (inst, def) => { var _a; exports.$ZodCheck.init(inst, def); (_a = inst._zod.def).when ?? (_a.when = _whenHasLength); inst._zod.check = (payload) => { const input = payload.value; const units = input.length; // Strings are measured in Unicode code points, not UTF-16 units. A code point is at most two units, so a string that already fits in units fits in code points; only an overflow has to be counted. const length = typeof input === "string" && units > def.maximum ? util.codePointLength(input) : units; if (length <= def.maximum) return; const origin = util.getLengthableOrigin(input); payload.issues.push({ origin, code: "too_big", maximum: def.maximum, inclusive: true, input, inst, continue: !def.abort, }); }; }); exports.$ZodCheckMinLength = core.$constructor("$ZodCheckMinLength", (inst, def) => { var _a; exports.$ZodCheck.init(inst, def); (_a = inst._zod.def).when ?? (_a.when = _whenHasLength); inst._zod.check = (payload) => { const input = payload.value; const units = input.length; // A code point is one or two UTF-16 units, so fewer units than the floor can never reach it and twice the floor always clears it. Only in between is the exact count in doubt. const length = typeof input === "string" && units >= def.minimum && units < def.minimum * 2 ? util.codePointLength(input) : units; if (length >= def.minimum) return; const origin = util.getLengthableOrigin(input); payload.issues.push({ origin, code: "too_small", minimum: def.minimum, inclusive: true, input, inst, continue: !def.abort, }); }; }); exports.$ZodCheckLengthEquals = core.$constructor("$ZodCheckLengthEquals", (inst, def) => { var _a; exports.$ZodCheck.init(inst, def); (_a = inst._zod.def).when ?? (_a.when = _whenHasLength); inst._zod.check = (payload) => { const input = payload.value; const units = input.length; // A code point is one or two UTF-16 units, so outside `[length, length * 2]` units the target is missed either way — and missed in the same direction in both measures. const length = typeof input === "string" && units >= def.length && units <= def.length * 2 ? util.codePointLength(input) : units; if (length === def.length) return; const origin = util.getLengthableOrigin(input); const tooBig = length > def.length; payload.issues.push({ origin, ...(tooBig ? { code: "too_big", maximum: def.length } : { code: "too_small", minimum: def.length }), inclusive: true, exact: true, input: payload.value, inst, continue: !def.abort, }); }; }); exports.$ZodCheckStringFormat = core.$constructor("$ZodCheckStringFormat", (inst, def) => { var _a, _b; exports.$ZodCheck.init(inst, def); if (def.pattern) (_a = inst._zod).check ?? (_a.check = (payload) => { def.pattern.lastIndex = 0; if (def.pattern.test(payload.value)) return; payload.issues.push({ origin: "string", code: "invalid_format", format: def.format, input: payload.value, ...(def.pattern ? { pattern: def.pattern.toString() } : {}), inst, continue: !def.abort, }); }); else (_b = inst._zod).check ?? (_b.check = () => { }); }); exports.$ZodCheckRegex = core.$constructor("$ZodCheckRegex", (inst, def) => { exports.$ZodCheckStringFormat.init(inst, def); inst._zod.check = (payload) => { def.pattern.lastIndex = 0; if (def.pattern.test(payload.value)) return; payload.issues.push({ origin: "string", code: "invalid_format", format: "regex", input: payload.value, pattern: def.pattern.toString(), inst, continue: !def.abort, }); }; }); exports.$ZodCheckLowerCase = core.$constructor("$ZodCheckLowerCase", (inst, def) => { def.pattern ?? (def.pattern = regexes.lowercase); exports.$ZodCheckStringFormat.init(inst, def); }); exports.$ZodCheckUpperCase = core.$constructor("$ZodCheckUpperCase", (inst, def) => { def.pattern ?? (def.pattern = regexes.uppercase); exports.$ZodCheckStringFormat.init(inst, def); }); exports.$ZodCheckIncludes = core.$constructor("$ZodCheckIncludes", (inst, def) => { exports.$ZodCheck.init(inst, def); const escapedRegex = util.escapeRegex(def.includes); // `String.prototype.includes(sub, position)` matches `sub` at `position` // OR LATER, so the pattern must allow at least `position` leading chars // (`{N,}`), not exactly `position` chars (`{N}`). const pattern = new RegExp(typeof def.position === "number" ? `^.{${def.position},}${escapedRegex}` : escapedRegex); def.pattern = pattern; inst._zod.check = (payload) => { if (payload.value.includes(def.includes, def.position)) return; payload.issues.push({ origin: "string", code: "invalid_format", format: "includes", includes: def.includes, input: payload.value, inst, continue: !def.abort, }); }; }); exports.$ZodCheckStartsWith = core.$constructor("$ZodCheckStartsWith", (inst, def) => { exports.$ZodCheck.init(inst, def); const pattern = new RegExp(`^${util.escapeRegex(def.prefix)}.*`); def.pattern ?? (def.pattern = pattern); inst._zod.check = (payload) => { if (payload.value.startsWith(def.prefix)) return; payload.issues.push({ origin: "string", code: "invalid_format", format: "starts_with", prefix: def.prefix, input: payload.value, inst, continue: !def.abort, }); }; }); exports.$ZodCheckEndsWith = core.$constructor("$ZodCheckEndsWith", (inst, def) => { exports.$ZodCheck.init(inst, def); const pattern = new RegExp(`.*${util.escapeRegex(def.suffix)}$`); def.pattern ?? (def.pattern = pattern); inst._zod.check = (payload) => { if (payload.value.endsWith(def.suffix)) return; payload.issues.push({ origin: "string", code: "invalid_format", format: "ends_with", suffix: def.suffix, input: payload.value, inst, continue: !def.abort, }); }; }); /////////////////////////////////// ///// $ZodCheckProperty ///// /////////////////////////////////// function handleCheckPropertyResult(result, payload, property) { if (result.issues.length) { payload.issues.push(...util.prefixIssues(property, result.issues)); } } exports.$ZodCheckProperty = core.$constructor("$ZodCheckProperty", (inst, def) => { exports.$ZodCheck.init(inst, def); inst._zod.check = (payload) => { const result = def.schema._zod.run({ value: payload.value[def.property], issues: [], }, {}); if (result instanceof Promise) { return result.then((result) => handleCheckPropertyResult(result, payload, def.property)); } handleCheckPropertyResult(result, payload, def.property); return; }; }); exports.$ZodCheckProperties = core.$constructor("$ZodCheckProperties", (inst, def) => { exports.$ZodCheck.init(inst, def); util.hide(inst, Symbol.iterator, function* () { yield inst; }); // key and schema snapshotted together: reading one live and the other cached lets a later mutation of the caller's shape object pair a stale key with a missing schema let entries; inst._zod.check = (payload) => { // the base schema already typed the value, so only a nullish one is rejected here: the properties read on a primitive too, matching z.property() on a string's length if (payload.value == null) { payload.issues.push({ expected: "object", code: "invalid_type", input: payload.value, inst }); return undefined; } entries ?? (entries = Reflect.ownKeys(def.shape).map((key) => [key, def.shape[key]])); const input = payload.value; let proms; for (const [key, schema] of entries) { const result = schema._zod.run({ value: input[key], issues: [] }, {}); if (result instanceof Promise) { proms ?? (proms = []); proms.push(result.then((result) => handleCheckPropertyResult(result, payload, key))); } else { handleCheckPropertyResult(result, payload, key); } } if (proms) return Promise.all(proms).then(() => undefined); return undefined; }; }); exports.$ZodCheckMimeType = core.$constructor("$ZodCheckMimeType", (inst, def) => { exports.$ZodCheck.init(inst, def); const mimeSet = new Set(def.mime); inst._zod.check = (payload) => { if (mimeSet.has(payload.value.type)) return; payload.issues.push({ code: "invalid_value", values: def.mime, input: payload.value.type, inst, continue: !def.abort, }); }; }); exports.$ZodCheckOverwrite = core.$constructor("$ZodCheckOverwrite", (inst, def) => { exports.$ZodCheck.init(inst, def); inst._zod.check = (payload) => { payload.value = def.tx(payload.value); }; }); // seal-cjs-exports (function () { var keys = Object.getOwnPropertyNames(exports); for (var i = 0; i < keys.length; i++) { var desc = Object.getOwnPropertyDescriptor(exports, keys[i]); if (!desc || !desc.get || !desc.configurable) continue; var value; try { value = desc.get(); } catch (e) { continue; } // a circular require may not have settled this one yet, so leave it live if (value === undefined) continue; Object.defineProperty(exports, keys[i], { value: value, writable: false, enumerable: desc.enumerable, configurable: false }); } Object.freeze(exports); })();