Update code
This commit is contained in:
32
mcp-server-ssh/node_modules/zod/src/v4/classic/checks.ts
generated
vendored
Normal file
32
mcp-server-ssh/node_modules/zod/src/v4/classic/checks.ts
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
export {
|
||||
_lt as lt,
|
||||
_lte as lte,
|
||||
_gt as gt,
|
||||
_gte as gte,
|
||||
_positive as positive,
|
||||
_negative as negative,
|
||||
_nonpositive as nonpositive,
|
||||
_nonnegative as nonnegative,
|
||||
_multipleOf as multipleOf,
|
||||
_maxSize as maxSize,
|
||||
_minSize as minSize,
|
||||
_size as size,
|
||||
_maxLength as maxLength,
|
||||
_minLength as minLength,
|
||||
_length as length,
|
||||
_regex as regex,
|
||||
_lowercase as lowercase,
|
||||
_uppercase as uppercase,
|
||||
_includes as includes,
|
||||
_startsWith as startsWith,
|
||||
_endsWith as endsWith,
|
||||
_property as property,
|
||||
_mime as mime,
|
||||
_overwrite as overwrite,
|
||||
_normalize as normalize,
|
||||
_trim as trim,
|
||||
_toLowerCase as toLowerCase,
|
||||
_toUpperCase as toUpperCase,
|
||||
_slugify as slugify,
|
||||
type $RefinementCtx as RefinementCtx,
|
||||
} from "../core/index.js";
|
||||
27
mcp-server-ssh/node_modules/zod/src/v4/classic/coerce.ts
generated
vendored
Normal file
27
mcp-server-ssh/node_modules/zod/src/v4/classic/coerce.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import * as core from "../core/index.js";
|
||||
import * as schemas from "./schemas.js";
|
||||
|
||||
export interface ZodCoercedString<T = unknown> extends schemas._ZodString<core.$ZodStringInternals<T>> {}
|
||||
export function string<T = unknown>(params?: string | core.$ZodStringParams): ZodCoercedString<T> {
|
||||
return core._coercedString(schemas.ZodString, params) as any;
|
||||
}
|
||||
|
||||
export interface ZodCoercedNumber<T = unknown> extends schemas._ZodNumber<core.$ZodNumberInternals<T>> {}
|
||||
export function number<T = unknown>(params?: string | core.$ZodNumberParams): ZodCoercedNumber<T> {
|
||||
return core._coercedNumber(schemas.ZodNumber, params) as ZodCoercedNumber<T>;
|
||||
}
|
||||
|
||||
export interface ZodCoercedBoolean<T = unknown> extends schemas._ZodBoolean<core.$ZodBooleanInternals<T>> {}
|
||||
export function boolean<T = unknown>(params?: string | core.$ZodBooleanParams): ZodCoercedBoolean<T> {
|
||||
return core._coercedBoolean(schemas.ZodBoolean, params) as ZodCoercedBoolean<T>;
|
||||
}
|
||||
|
||||
export interface ZodCoercedBigInt<T = unknown> extends schemas._ZodBigInt<core.$ZodBigIntInternals<T>> {}
|
||||
export function bigint<T = unknown>(params?: string | core.$ZodBigIntParams): ZodCoercedBigInt<T> {
|
||||
return core._coercedBigint(schemas.ZodBigInt, params) as ZodCoercedBigInt<T>;
|
||||
}
|
||||
|
||||
export interface ZodCoercedDate<T = unknown> extends schemas._ZodDate<core.$ZodDateInternals<T>> {}
|
||||
export function date<T = unknown>(params?: string | core.$ZodDateParams): ZodCoercedDate<T> {
|
||||
return core._coercedDate(schemas.ZodDate, params) as ZodCoercedDate<T>;
|
||||
}
|
||||
70
mcp-server-ssh/node_modules/zod/src/v4/classic/compat.ts
generated
vendored
Normal file
70
mcp-server-ssh/node_modules/zod/src/v4/classic/compat.ts
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
// Zod 3 compat layer
|
||||
|
||||
import * as core from "../core/index.js";
|
||||
import type { ZodType } from "./schemas.js";
|
||||
|
||||
export type {
|
||||
/** @deprecated Use `z.output<T>` instead. */
|
||||
output as TypeOf,
|
||||
/** @deprecated Use `z.output<T>` instead. */
|
||||
output as Infer,
|
||||
/** @deprecated Use `z.core.$$ZodFirstPartyTypes` instead */
|
||||
$ZodTypes as ZodFirstPartySchemaTypes,
|
||||
} from "../core/index.js";
|
||||
|
||||
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
||||
export const ZodIssueCode = {
|
||||
invalid_type: "invalid_type",
|
||||
too_big: "too_big",
|
||||
too_small: "too_small",
|
||||
invalid_format: "invalid_format",
|
||||
not_multiple_of: "not_multiple_of",
|
||||
unrecognized_keys: "unrecognized_keys",
|
||||
invalid_union: "invalid_union",
|
||||
invalid_key: "invalid_key",
|
||||
invalid_element: "invalid_element",
|
||||
invalid_value: "invalid_value",
|
||||
custom: "custom",
|
||||
} as const;
|
||||
|
||||
/** @deprecated Use `z.$ZodFlattenedError` */
|
||||
export type inferFlattenedErrors<T extends core.$ZodType, U = string> = core.$ZodFlattenedError<core.output<T>, U>;
|
||||
|
||||
/** @deprecated Use `z.$ZodFormattedError` */
|
||||
export type inferFormattedError<T extends core.$ZodType<any, any>, U = string> = core.$ZodFormattedError<
|
||||
core.output<T>,
|
||||
U
|
||||
>;
|
||||
|
||||
/** Use `z.$brand` instead */
|
||||
export type BRAND<T extends string | number | symbol = string | number | symbol> = {
|
||||
[core.$brand]: { [k in T]: true };
|
||||
};
|
||||
export { $brand, config } from "../core/index.js";
|
||||
|
||||
/** @deprecated Use `z.config(params)` instead. */
|
||||
export function setErrorMap(map: core.$ZodErrorMap): void {
|
||||
core.config({
|
||||
customError: map,
|
||||
});
|
||||
}
|
||||
|
||||
/** @deprecated Use `z.config()` instead. */
|
||||
export function getErrorMap(): core.$ZodErrorMap<core.$ZodIssue> | undefined {
|
||||
return core.config().customError;
|
||||
}
|
||||
|
||||
export type {
|
||||
/** @deprecated Use z.ZodType (without generics) instead. */
|
||||
ZodType as ZodTypeAny,
|
||||
/** @deprecated Use `z.ZodType` */
|
||||
ZodType as ZodSchema,
|
||||
/** @deprecated Use `z.ZodType` */
|
||||
ZodType as Schema,
|
||||
};
|
||||
|
||||
/** Included for Zod 3 compatibility */
|
||||
export type ZodRawShape = core.$ZodShape;
|
||||
|
||||
/** @deprecated Do not use. Stub definition, only included for zod-to-json-schema compatibility. */
|
||||
export enum ZodFirstPartyTypeKind {}
|
||||
82
mcp-server-ssh/node_modules/zod/src/v4/classic/errors.ts
generated
vendored
Normal file
82
mcp-server-ssh/node_modules/zod/src/v4/classic/errors.ts
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
import * as core from "../core/index.js";
|
||||
import { $ZodError } from "../core/index.js";
|
||||
import * as util from "../core/util.js";
|
||||
|
||||
/** @deprecated Use `z.core.$ZodIssue` from `@zod/core` instead, especially if you are building a library on top of Zod. */
|
||||
export type ZodIssue = core.$ZodIssue;
|
||||
|
||||
/** An Error-like class used to store Zod validation issues. */
|
||||
export interface ZodError<T = unknown> extends $ZodError<T> {
|
||||
/** @deprecated Use the `z.treeifyError(err)` function instead. */
|
||||
format(): core.$ZodFormattedError<T>;
|
||||
format<U>(mapper: (issue: core.$ZodIssue) => U): core.$ZodFormattedError<T, U>;
|
||||
/** @deprecated Use the `z.treeifyError(err)` function instead. */
|
||||
flatten(): core.$ZodFlattenedError<T>;
|
||||
flatten<U>(mapper: (issue: core.$ZodIssue) => U): core.$ZodFlattenedError<T, U>;
|
||||
/** @deprecated Push directly to `.issues` instead. */
|
||||
addIssue(issue: core.$ZodIssue): void;
|
||||
/** @deprecated Push directly to `.issues` instead. */
|
||||
addIssues(issues: core.$ZodIssue[]): void;
|
||||
|
||||
/** @deprecated Check `err.issues.length === 0` instead. */
|
||||
isEmpty: boolean;
|
||||
}
|
||||
|
||||
const initializer = (inst: ZodError, issues: core.$ZodIssue[]) => {
|
||||
$ZodError.init(inst, issues);
|
||||
inst.name = "ZodError";
|
||||
Object.defineProperties(inst, {
|
||||
format: {
|
||||
value: (mapper: any) => core.formatError(inst, mapper),
|
||||
// enumerable: false,
|
||||
},
|
||||
flatten: {
|
||||
value: (mapper: any) => core.flattenError(inst, mapper),
|
||||
// enumerable: false,
|
||||
},
|
||||
addIssue: {
|
||||
value: (issue: any) => {
|
||||
inst.issues.push(issue);
|
||||
inst.message = JSON.stringify(inst.issues, util.jsonStringifyReplacer, 2);
|
||||
},
|
||||
// enumerable: false,
|
||||
},
|
||||
addIssues: {
|
||||
value: (issues: any) => {
|
||||
inst.issues.push(...issues);
|
||||
inst.message = JSON.stringify(inst.issues, util.jsonStringifyReplacer, 2);
|
||||
},
|
||||
// enumerable: false,
|
||||
},
|
||||
isEmpty: {
|
||||
get() {
|
||||
return inst.issues.length === 0;
|
||||
},
|
||||
// enumerable: false,
|
||||
},
|
||||
});
|
||||
// Object.defineProperty(inst, "isEmpty", {
|
||||
// get() {
|
||||
// return inst.issues.length === 0;
|
||||
// },
|
||||
// });
|
||||
};
|
||||
export const ZodError: core.$constructor<ZodError> = core.$constructor("ZodError", initializer);
|
||||
export const ZodRealError: core.$constructor<ZodError> = core.$constructor("ZodError", initializer, {
|
||||
Parent: Error,
|
||||
});
|
||||
|
||||
export type {
|
||||
/** @deprecated Use `z.core.$ZodFlattenedError` instead. */
|
||||
$ZodFlattenedError as ZodFlattenedError,
|
||||
/** @deprecated Use `z.core.$ZodFormattedError` instead. */
|
||||
$ZodFormattedError as ZodFormattedError,
|
||||
/** @deprecated Use `z.core.$ZodErrorMap` instead. */
|
||||
$ZodErrorMap as ZodErrorMap,
|
||||
} from "../core/index.js";
|
||||
|
||||
/** @deprecated Use `z.core.$ZodRawIssue` instead. */
|
||||
export type IssueData = core.$ZodRawIssue;
|
||||
|
||||
// /** @deprecated Use `z.core.$ZodErrorMapCtx` instead. */
|
||||
// export type ErrorMapCtx = core.$ZodErrorMapCtx;
|
||||
51
mcp-server-ssh/node_modules/zod/src/v4/classic/external.ts
generated
vendored
Normal file
51
mcp-server-ssh/node_modules/zod/src/v4/classic/external.ts
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
export * as core from "../core/index.js";
|
||||
export * from "./schemas.js";
|
||||
export * from "./checks.js";
|
||||
export * from "./errors.js";
|
||||
export * from "./parse.js";
|
||||
export * from "./compat.js";
|
||||
|
||||
// zod-specified
|
||||
import { config } from "../core/index.js";
|
||||
import en from "../locales/en.js";
|
||||
config(en());
|
||||
|
||||
export type { infer, output, input } from "../core/index.js";
|
||||
export {
|
||||
globalRegistry,
|
||||
type GlobalMeta,
|
||||
registry,
|
||||
config,
|
||||
$output,
|
||||
$input,
|
||||
$brand,
|
||||
clone,
|
||||
regexes,
|
||||
treeifyError,
|
||||
prettifyError,
|
||||
formatError,
|
||||
flattenError,
|
||||
TimePrecision,
|
||||
util,
|
||||
NEVER,
|
||||
} from "../core/index.js";
|
||||
export { toJSONSchema } from "../core/json-schema-processors.js";
|
||||
export { fromJSONSchema } from "./from-json-schema.js";
|
||||
|
||||
export * as locales from "../locales/index.js";
|
||||
|
||||
// iso
|
||||
// must be exported from top-level
|
||||
// https://github.com/colinhacks/zod/issues/4491
|
||||
export { ZodISODateTime, ZodISODate, ZodISOTime, ZodISODuration } from "./iso.js";
|
||||
export * as iso from "./iso.js";
|
||||
|
||||
// coerce
|
||||
export type {
|
||||
ZodCoercedString,
|
||||
ZodCoercedNumber,
|
||||
ZodCoercedBigInt,
|
||||
ZodCoercedBoolean,
|
||||
ZodCoercedDate,
|
||||
} from "./coerce.js";
|
||||
export * as coerce from "./coerce.js";
|
||||
643
mcp-server-ssh/node_modules/zod/src/v4/classic/from-json-schema.ts
generated
vendored
Normal file
643
mcp-server-ssh/node_modules/zod/src/v4/classic/from-json-schema.ts
generated
vendored
Normal file
@@ -0,0 +1,643 @@
|
||||
import type * as JSONSchema from "../core/json-schema.js";
|
||||
import { type $ZodRegistry, globalRegistry } from "../core/registries.js";
|
||||
import * as _checks from "./checks.js";
|
||||
import * as _iso from "./iso.js";
|
||||
import * as _schemas from "./schemas.js";
|
||||
import type { ZodNumber, ZodString, ZodType } from "./schemas.js";
|
||||
|
||||
// Local z object to avoid circular dependency with ../index.js
|
||||
const z = {
|
||||
..._schemas,
|
||||
..._checks,
|
||||
iso: _iso,
|
||||
};
|
||||
|
||||
type JSONSchemaVersion = "draft-2020-12" | "draft-7" | "draft-4" | "openapi-3.0";
|
||||
|
||||
interface FromJSONSchemaParams {
|
||||
defaultTarget?: JSONSchemaVersion;
|
||||
registry?: $ZodRegistry<any>;
|
||||
}
|
||||
|
||||
interface ConversionContext {
|
||||
version: JSONSchemaVersion;
|
||||
defs: Record<string, JSONSchema.JSONSchema>;
|
||||
refs: Map<string, ZodType>;
|
||||
processing: Set<string>;
|
||||
rootSchema: JSONSchema.JSONSchema;
|
||||
registry: $ZodRegistry<any>;
|
||||
}
|
||||
|
||||
// Keys that are recognized and handled by the conversion logic
|
||||
const RECOGNIZED_KEYS = new Set([
|
||||
// Schema identification
|
||||
"$schema",
|
||||
"$ref",
|
||||
"$defs",
|
||||
"definitions",
|
||||
// Core schema keywords
|
||||
"$id",
|
||||
"id",
|
||||
"$comment",
|
||||
"$anchor",
|
||||
"$vocabulary",
|
||||
"$dynamicRef",
|
||||
"$dynamicAnchor",
|
||||
// Type
|
||||
"type",
|
||||
"enum",
|
||||
"const",
|
||||
// Composition
|
||||
"anyOf",
|
||||
"oneOf",
|
||||
"allOf",
|
||||
"not",
|
||||
// Object
|
||||
"properties",
|
||||
"required",
|
||||
"additionalProperties",
|
||||
"patternProperties",
|
||||
"propertyNames",
|
||||
"minProperties",
|
||||
"maxProperties",
|
||||
// Array
|
||||
"items",
|
||||
"prefixItems",
|
||||
"additionalItems",
|
||||
"minItems",
|
||||
"maxItems",
|
||||
"uniqueItems",
|
||||
"contains",
|
||||
"minContains",
|
||||
"maxContains",
|
||||
// String
|
||||
"minLength",
|
||||
"maxLength",
|
||||
"pattern",
|
||||
"format",
|
||||
// Number
|
||||
"minimum",
|
||||
"maximum",
|
||||
"exclusiveMinimum",
|
||||
"exclusiveMaximum",
|
||||
"multipleOf",
|
||||
// Already handled metadata
|
||||
"description",
|
||||
"default",
|
||||
// Content
|
||||
"contentEncoding",
|
||||
"contentMediaType",
|
||||
"contentSchema",
|
||||
// Unsupported (error-throwing)
|
||||
"unevaluatedItems",
|
||||
"unevaluatedProperties",
|
||||
"if",
|
||||
"then",
|
||||
"else",
|
||||
"dependentSchemas",
|
||||
"dependentRequired",
|
||||
// OpenAPI
|
||||
"nullable",
|
||||
"readOnly",
|
||||
]);
|
||||
|
||||
function detectVersion(schema: JSONSchema.JSONSchema, defaultTarget?: JSONSchemaVersion): JSONSchemaVersion {
|
||||
const $schema = schema.$schema;
|
||||
|
||||
if ($schema === "https://json-schema.org/draft/2020-12/schema") {
|
||||
return "draft-2020-12";
|
||||
}
|
||||
if ($schema === "http://json-schema.org/draft-07/schema#") {
|
||||
return "draft-7";
|
||||
}
|
||||
if ($schema === "http://json-schema.org/draft-04/schema#") {
|
||||
return "draft-4";
|
||||
}
|
||||
|
||||
// Use defaultTarget if provided, otherwise default to draft-2020-12
|
||||
return defaultTarget ?? "draft-2020-12";
|
||||
}
|
||||
|
||||
function resolveRef(ref: string, ctx: ConversionContext): JSONSchema.JSONSchema {
|
||||
if (!ref.startsWith("#")) {
|
||||
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
||||
}
|
||||
|
||||
const path = ref.slice(1).split("/").filter(Boolean);
|
||||
|
||||
// Handle root reference "#"
|
||||
if (path.length === 0) {
|
||||
return ctx.rootSchema;
|
||||
}
|
||||
|
||||
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
||||
|
||||
if (path[0] === defsKey) {
|
||||
const key = path[1];
|
||||
if (!key || !ctx.defs[key]) {
|
||||
throw new Error(`Reference not found: ${ref}`);
|
||||
}
|
||||
return ctx.defs[key]!;
|
||||
}
|
||||
|
||||
throw new Error(`Reference not found: ${ref}`);
|
||||
}
|
||||
|
||||
function convertBaseSchema(schema: JSONSchema.JSONSchema, ctx: ConversionContext): ZodType {
|
||||
// Handle unsupported features
|
||||
if (schema.not !== undefined) {
|
||||
// Special case: { not: {} } represents never
|
||||
if (typeof schema.not === "object" && Object.keys(schema.not).length === 0) {
|
||||
return z.never();
|
||||
}
|
||||
throw new Error("not is not supported in Zod (except { not: {} } for never)");
|
||||
}
|
||||
if (schema.unevaluatedItems !== undefined) {
|
||||
throw new Error("unevaluatedItems is not supported");
|
||||
}
|
||||
if (schema.unevaluatedProperties !== undefined) {
|
||||
throw new Error("unevaluatedProperties is not supported");
|
||||
}
|
||||
if (schema.if !== undefined || schema.then !== undefined || schema.else !== undefined) {
|
||||
throw new Error("Conditional schemas (if/then/else) are not supported");
|
||||
}
|
||||
if (schema.dependentSchemas !== undefined || schema.dependentRequired !== undefined) {
|
||||
throw new Error("dependentSchemas and dependentRequired are not supported");
|
||||
}
|
||||
|
||||
// Handle $ref
|
||||
if (schema.$ref) {
|
||||
const refPath = schema.$ref;
|
||||
if (ctx.refs.has(refPath)) {
|
||||
return ctx.refs.get(refPath)!;
|
||||
}
|
||||
|
||||
if (ctx.processing.has(refPath)) {
|
||||
// Circular reference - use lazy
|
||||
return z.lazy(() => {
|
||||
if (!ctx.refs.has(refPath)) {
|
||||
throw new Error(`Circular reference not resolved: ${refPath}`);
|
||||
}
|
||||
return ctx.refs.get(refPath)!;
|
||||
});
|
||||
}
|
||||
|
||||
ctx.processing.add(refPath);
|
||||
const resolved = resolveRef(refPath, ctx);
|
||||
const zodSchema = convertSchema(resolved, ctx);
|
||||
ctx.refs.set(refPath, zodSchema);
|
||||
ctx.processing.delete(refPath);
|
||||
return zodSchema;
|
||||
}
|
||||
|
||||
// Handle enum
|
||||
if (schema.enum !== undefined) {
|
||||
const enumValues = schema.enum;
|
||||
|
||||
// Special case: OpenAPI 3.0 null representation { type: "string", nullable: true, enum: [null] }
|
||||
if (
|
||||
ctx.version === "openapi-3.0" &&
|
||||
schema.nullable === true &&
|
||||
enumValues.length === 1 &&
|
||||
enumValues[0] === null
|
||||
) {
|
||||
return z.null();
|
||||
}
|
||||
|
||||
if (enumValues.length === 0) {
|
||||
return z.never();
|
||||
}
|
||||
if (enumValues.length === 1) {
|
||||
return z.literal(enumValues[0]!);
|
||||
}
|
||||
// Check if all values are strings
|
||||
if (enumValues.every((v) => typeof v === "string")) {
|
||||
return z.enum(enumValues as [string, ...string[]]);
|
||||
}
|
||||
// Mixed types - use union of literals
|
||||
const literalSchemas = enumValues.map((v) => z.literal(v));
|
||||
if (literalSchemas.length < 2) {
|
||||
return literalSchemas[0]!;
|
||||
}
|
||||
return z.union([literalSchemas[0]!, literalSchemas[1]!, ...literalSchemas.slice(2)] as [
|
||||
ZodType,
|
||||
ZodType,
|
||||
...ZodType[],
|
||||
]);
|
||||
}
|
||||
|
||||
// Handle const
|
||||
if (schema.const !== undefined) {
|
||||
return z.literal(schema.const);
|
||||
}
|
||||
|
||||
// Handle type
|
||||
const type = schema.type;
|
||||
|
||||
if (Array.isArray(type)) {
|
||||
// Expand type array into anyOf union
|
||||
const typeSchemas = type.map((t) => {
|
||||
const typeSchema: JSONSchema.JSONSchema = { ...schema, type: t };
|
||||
return convertBaseSchema(typeSchema, ctx);
|
||||
});
|
||||
if (typeSchemas.length === 0) {
|
||||
return z.never();
|
||||
}
|
||||
if (typeSchemas.length === 1) {
|
||||
return typeSchemas[0]!;
|
||||
}
|
||||
return z.union(typeSchemas as [ZodType, ZodType, ...ZodType[]]);
|
||||
}
|
||||
|
||||
if (!type) {
|
||||
// No type specified - empty schema (any)
|
||||
return z.any();
|
||||
}
|
||||
|
||||
let zodSchema: ZodType;
|
||||
|
||||
switch (type) {
|
||||
case "string": {
|
||||
let stringSchema: ZodString = z.string();
|
||||
|
||||
// Apply format using .check() with Zod format functions
|
||||
if (schema.format) {
|
||||
const format = schema.format;
|
||||
// Map common formats to Zod check functions
|
||||
if (format === "email") {
|
||||
stringSchema = stringSchema.check(z.email());
|
||||
} else if (format === "uri" || format === "uri-reference") {
|
||||
stringSchema = stringSchema.check(z.url());
|
||||
} else if (format === "uuid" || format === "guid") {
|
||||
stringSchema = stringSchema.check(z.uuid());
|
||||
} else if (format === "date-time") {
|
||||
stringSchema = stringSchema.check(z.iso.datetime());
|
||||
} else if (format === "date") {
|
||||
stringSchema = stringSchema.check(z.iso.date());
|
||||
} else if (format === "time") {
|
||||
stringSchema = stringSchema.check(z.iso.time());
|
||||
} else if (format === "duration") {
|
||||
stringSchema = stringSchema.check(z.iso.duration());
|
||||
} else if (format === "ipv4") {
|
||||
stringSchema = stringSchema.check(z.ipv4());
|
||||
} else if (format === "ipv6") {
|
||||
stringSchema = stringSchema.check(z.ipv6());
|
||||
} else if (format === "mac") {
|
||||
stringSchema = stringSchema.check(z.mac());
|
||||
} else if (format === "cidr") {
|
||||
stringSchema = stringSchema.check(z.cidrv4());
|
||||
} else if (format === "cidr-v6") {
|
||||
stringSchema = stringSchema.check(z.cidrv6());
|
||||
} else if (format === "base64") {
|
||||
stringSchema = stringSchema.check(z.base64());
|
||||
} else if (format === "base64url") {
|
||||
stringSchema = stringSchema.check(z.base64url());
|
||||
} else if (format === "e164") {
|
||||
stringSchema = stringSchema.check(z.e164());
|
||||
} else if (format === "jwt") {
|
||||
stringSchema = stringSchema.check(z.jwt());
|
||||
} else if (format === "emoji") {
|
||||
stringSchema = stringSchema.check(z.emoji());
|
||||
} else if (format === "nanoid") {
|
||||
stringSchema = stringSchema.check(z.nanoid());
|
||||
} else if (format === "cuid") {
|
||||
stringSchema = stringSchema.check(z.cuid());
|
||||
} else if (format === "cuid2") {
|
||||
stringSchema = stringSchema.check(z.cuid2());
|
||||
} else if (format === "ulid") {
|
||||
stringSchema = stringSchema.check(z.ulid());
|
||||
} else if (format === "xid") {
|
||||
stringSchema = stringSchema.check(z.xid());
|
||||
} else if (format === "ksuid") {
|
||||
stringSchema = stringSchema.check(z.ksuid());
|
||||
}
|
||||
// Note: json-string format is not currently supported by Zod
|
||||
// Custom formats are ignored - keep as plain string
|
||||
}
|
||||
|
||||
// Apply constraints
|
||||
if (typeof schema.minLength === "number") {
|
||||
stringSchema = stringSchema.min(schema.minLength);
|
||||
}
|
||||
if (typeof schema.maxLength === "number") {
|
||||
stringSchema = stringSchema.max(schema.maxLength);
|
||||
}
|
||||
if (schema.pattern) {
|
||||
// JSON Schema patterns are not implicitly anchored (match anywhere in string)
|
||||
stringSchema = stringSchema.regex(new RegExp(schema.pattern));
|
||||
}
|
||||
|
||||
zodSchema = stringSchema;
|
||||
break;
|
||||
}
|
||||
|
||||
case "number":
|
||||
case "integer": {
|
||||
let numberSchema: ZodNumber = type === "integer" ? z.number().int() : z.number();
|
||||
|
||||
// Apply constraints
|
||||
if (typeof schema.minimum === "number") {
|
||||
numberSchema = numberSchema.min(schema.minimum);
|
||||
}
|
||||
if (typeof schema.maximum === "number") {
|
||||
numberSchema = numberSchema.max(schema.maximum);
|
||||
}
|
||||
if (typeof schema.exclusiveMinimum === "number") {
|
||||
numberSchema = numberSchema.gt(schema.exclusiveMinimum);
|
||||
} else if (schema.exclusiveMinimum === true && typeof schema.minimum === "number") {
|
||||
numberSchema = numberSchema.gt(schema.minimum);
|
||||
}
|
||||
if (typeof schema.exclusiveMaximum === "number") {
|
||||
numberSchema = numberSchema.lt(schema.exclusiveMaximum);
|
||||
} else if (schema.exclusiveMaximum === true && typeof schema.maximum === "number") {
|
||||
numberSchema = numberSchema.lt(schema.maximum);
|
||||
}
|
||||
if (typeof schema.multipleOf === "number") {
|
||||
numberSchema = numberSchema.multipleOf(schema.multipleOf);
|
||||
}
|
||||
|
||||
zodSchema = numberSchema;
|
||||
break;
|
||||
}
|
||||
|
||||
case "boolean": {
|
||||
zodSchema = z.boolean();
|
||||
break;
|
||||
}
|
||||
|
||||
case "null": {
|
||||
zodSchema = z.null();
|
||||
break;
|
||||
}
|
||||
|
||||
case "object": {
|
||||
const shape: Record<string, ZodType> = {};
|
||||
const properties = schema.properties || {};
|
||||
const requiredSet = new Set(schema.required || []);
|
||||
|
||||
// Convert properties - mark optional ones
|
||||
for (const [key, propSchema] of Object.entries(properties)) {
|
||||
const propZodSchema = convertSchema(propSchema as JSONSchema.JSONSchema, ctx);
|
||||
// If not in required array, make it optional
|
||||
shape[key] = requiredSet.has(key) ? propZodSchema : propZodSchema.optional();
|
||||
}
|
||||
|
||||
// Handle propertyNames
|
||||
if (schema.propertyNames) {
|
||||
const keySchema = convertSchema(schema.propertyNames, ctx) as ZodString;
|
||||
const valueSchema =
|
||||
schema.additionalProperties && typeof schema.additionalProperties === "object"
|
||||
? convertSchema(schema.additionalProperties as JSONSchema.JSONSchema, ctx)
|
||||
: z.any();
|
||||
|
||||
// Case A: No properties (pure record)
|
||||
if (Object.keys(shape).length === 0) {
|
||||
zodSchema = z.record(keySchema, valueSchema);
|
||||
break;
|
||||
}
|
||||
|
||||
// Case B: With properties (intersection of object and looseRecord)
|
||||
const objectSchema = z.object(shape).passthrough();
|
||||
const recordSchema = z.looseRecord(keySchema, valueSchema);
|
||||
zodSchema = z.intersection(objectSchema, recordSchema);
|
||||
break;
|
||||
}
|
||||
|
||||
// Handle patternProperties
|
||||
if (schema.patternProperties) {
|
||||
// patternProperties: keys matching pattern must satisfy corresponding schema
|
||||
// Use loose records so non-matching keys pass through
|
||||
const patternProps = schema.patternProperties;
|
||||
const patternKeys = Object.keys(patternProps);
|
||||
const looseRecords: ZodType[] = [];
|
||||
|
||||
for (const pattern of patternKeys) {
|
||||
const patternValue = convertSchema(patternProps[pattern] as JSONSchema.JSONSchema, ctx);
|
||||
const keySchema = z.string().regex(new RegExp(pattern));
|
||||
looseRecords.push(z.looseRecord(keySchema, patternValue));
|
||||
}
|
||||
|
||||
// Build intersection: object schema + all pattern property records
|
||||
const schemasToIntersect: ZodType[] = [];
|
||||
if (Object.keys(shape).length > 0) {
|
||||
// Use passthrough so patternProperties can validate additional keys
|
||||
schemasToIntersect.push(z.object(shape).passthrough());
|
||||
}
|
||||
schemasToIntersect.push(...looseRecords);
|
||||
|
||||
if (schemasToIntersect.length === 0) {
|
||||
zodSchema = z.object({}).passthrough();
|
||||
} else if (schemasToIntersect.length === 1) {
|
||||
zodSchema = schemasToIntersect[0]!;
|
||||
} else {
|
||||
// Chain intersections: (A & B) & C & D ...
|
||||
let result = z.intersection(schemasToIntersect[0]!, schemasToIntersect[1]!);
|
||||
for (let i = 2; i < schemasToIntersect.length; i++) {
|
||||
result = z.intersection(result, schemasToIntersect[i]!);
|
||||
}
|
||||
zodSchema = result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Handle additionalProperties
|
||||
// In JSON Schema, additionalProperties defaults to true (allow any extra properties)
|
||||
// In Zod, objects strip unknown keys by default, so we need to handle this explicitly
|
||||
const objectSchema = z.object(shape);
|
||||
if (schema.additionalProperties === false) {
|
||||
// Strict mode - no extra properties allowed
|
||||
zodSchema = objectSchema.strict();
|
||||
} else if (typeof schema.additionalProperties === "object") {
|
||||
// Extra properties must match the specified schema
|
||||
zodSchema = objectSchema.catchall(convertSchema(schema.additionalProperties as JSONSchema.JSONSchema, ctx));
|
||||
} else {
|
||||
// additionalProperties is true or undefined - allow any extra properties (passthrough)
|
||||
zodSchema = objectSchema.passthrough();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "array": {
|
||||
// TODO: uniqueItems is not supported
|
||||
// TODO: contains/minContains/maxContains are not supported
|
||||
// Check if this is a tuple (prefixItems or items as array)
|
||||
const prefixItems = schema.prefixItems;
|
||||
const items = schema.items;
|
||||
|
||||
if (prefixItems && Array.isArray(prefixItems)) {
|
||||
// Tuple with prefixItems (draft-2020-12)
|
||||
const tupleItems = prefixItems.map((item) => convertSchema(item as JSONSchema.JSONSchema, ctx));
|
||||
const rest =
|
||||
items && typeof items === "object" && !Array.isArray(items)
|
||||
? convertSchema(items as JSONSchema.JSONSchema, ctx)
|
||||
: undefined;
|
||||
if (rest) {
|
||||
zodSchema = z.tuple(tupleItems as [ZodType, ...ZodType[]]).rest(rest);
|
||||
} else {
|
||||
zodSchema = z.tuple(tupleItems as [ZodType, ...ZodType[]]);
|
||||
}
|
||||
// Apply minItems/maxItems constraints to tuples
|
||||
if (typeof schema.minItems === "number") {
|
||||
zodSchema = (zodSchema as any).check(z.minLength(schema.minItems));
|
||||
}
|
||||
if (typeof schema.maxItems === "number") {
|
||||
zodSchema = (zodSchema as any).check(z.maxLength(schema.maxItems));
|
||||
}
|
||||
} else if (Array.isArray(items)) {
|
||||
// Tuple with items array (draft-7)
|
||||
const tupleItems = items.map((item) => convertSchema(item as JSONSchema.JSONSchema, ctx));
|
||||
const rest =
|
||||
schema.additionalItems && typeof schema.additionalItems === "object"
|
||||
? convertSchema(schema.additionalItems as JSONSchema.JSONSchema, ctx)
|
||||
: undefined; // additionalItems: false means no rest, handled by default tuple behavior
|
||||
if (rest) {
|
||||
zodSchema = z.tuple(tupleItems as [ZodType, ...ZodType[]]).rest(rest);
|
||||
} else {
|
||||
zodSchema = z.tuple(tupleItems as [ZodType, ...ZodType[]]);
|
||||
}
|
||||
// Apply minItems/maxItems constraints to tuples
|
||||
if (typeof schema.minItems === "number") {
|
||||
zodSchema = (zodSchema as any).check(z.minLength(schema.minItems));
|
||||
}
|
||||
if (typeof schema.maxItems === "number") {
|
||||
zodSchema = (zodSchema as any).check(z.maxLength(schema.maxItems));
|
||||
}
|
||||
} else if (items !== undefined) {
|
||||
// Regular array
|
||||
const element = convertSchema(items as JSONSchema.JSONSchema, ctx);
|
||||
let arraySchema = z.array(element);
|
||||
|
||||
// Apply constraints
|
||||
if (typeof schema.minItems === "number") {
|
||||
arraySchema = (arraySchema as any).min(schema.minItems);
|
||||
}
|
||||
if (typeof schema.maxItems === "number") {
|
||||
arraySchema = (arraySchema as any).max(schema.maxItems);
|
||||
}
|
||||
|
||||
zodSchema = arraySchema;
|
||||
} else {
|
||||
// No items specified - array of any
|
||||
zodSchema = z.array(z.any());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
throw new Error(`Unsupported type: ${type}`);
|
||||
}
|
||||
|
||||
// Apply metadata
|
||||
if (schema.description) {
|
||||
zodSchema = zodSchema.describe(schema.description);
|
||||
}
|
||||
if (schema.default !== undefined) {
|
||||
zodSchema = (zodSchema as any).default(schema.default);
|
||||
}
|
||||
|
||||
return zodSchema;
|
||||
}
|
||||
|
||||
function convertSchema(schema: JSONSchema.JSONSchema | boolean, ctx: ConversionContext): ZodType {
|
||||
if (typeof schema === "boolean") {
|
||||
return schema ? z.any() : z.never();
|
||||
}
|
||||
|
||||
// Convert base schema first (ignoring composition keywords)
|
||||
let baseSchema = convertBaseSchema(schema, ctx);
|
||||
const hasExplicitType = schema.type || schema.enum !== undefined || schema.const !== undefined;
|
||||
|
||||
// Process composition keywords LAST (they can appear together)
|
||||
// Handle anyOf - wrap base schema with union
|
||||
if (schema.anyOf && Array.isArray(schema.anyOf)) {
|
||||
const options = schema.anyOf.map((s) => convertSchema(s, ctx));
|
||||
const anyOfUnion = z.union(options as [ZodType, ZodType, ...ZodType[]]);
|
||||
baseSchema = hasExplicitType ? z.intersection(baseSchema, anyOfUnion) : anyOfUnion;
|
||||
}
|
||||
|
||||
// Handle oneOf - exclusive union (exactly one must match)
|
||||
if (schema.oneOf && Array.isArray(schema.oneOf)) {
|
||||
const options = schema.oneOf.map((s) => convertSchema(s, ctx));
|
||||
const oneOfUnion = z.xor(options as [ZodType, ZodType, ...ZodType[]]);
|
||||
baseSchema = hasExplicitType ? z.intersection(baseSchema, oneOfUnion) : oneOfUnion;
|
||||
}
|
||||
|
||||
// Handle allOf - wrap base schema with intersection
|
||||
if (schema.allOf && Array.isArray(schema.allOf)) {
|
||||
if (schema.allOf.length === 0) {
|
||||
baseSchema = hasExplicitType ? baseSchema : z.any();
|
||||
} else {
|
||||
let result = hasExplicitType ? baseSchema : convertSchema(schema.allOf[0]!, ctx);
|
||||
const startIdx = hasExplicitType ? 0 : 1;
|
||||
for (let i = startIdx; i < schema.allOf.length; i++) {
|
||||
result = z.intersection(result, convertSchema(schema.allOf[i]!, ctx));
|
||||
}
|
||||
baseSchema = result;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle nullable (OpenAPI 3.0)
|
||||
if (schema.nullable === true && ctx.version === "openapi-3.0") {
|
||||
baseSchema = z.nullable(baseSchema);
|
||||
}
|
||||
|
||||
// Handle readOnly
|
||||
if (schema.readOnly === true) {
|
||||
baseSchema = z.readonly(baseSchema);
|
||||
}
|
||||
|
||||
// Collect metadata: core schema keywords and unrecognized keys
|
||||
const extraMeta: Record<string, unknown> = {};
|
||||
|
||||
// Core schema keywords that should be captured as metadata
|
||||
const coreMetadataKeys = ["$id", "id", "$comment", "$anchor", "$vocabulary", "$dynamicRef", "$dynamicAnchor"];
|
||||
for (const key of coreMetadataKeys) {
|
||||
if (key in schema) {
|
||||
extraMeta[key] = schema[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Content keywords - store as metadata
|
||||
const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"];
|
||||
for (const key of contentMetadataKeys) {
|
||||
if (key in schema) {
|
||||
extraMeta[key] = schema[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Unrecognized keys (custom metadata)
|
||||
for (const key of Object.keys(schema)) {
|
||||
if (!RECOGNIZED_KEYS.has(key)) {
|
||||
extraMeta[key] = schema[key];
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(extraMeta).length > 0) {
|
||||
ctx.registry.add(baseSchema, extraMeta);
|
||||
}
|
||||
|
||||
return baseSchema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a JSON Schema to a Zod schema. This function should be considered semi-experimental. It's behavior is liable to change. */
|
||||
export function fromJSONSchema(schema: JSONSchema.JSONSchema | boolean, params?: FromJSONSchemaParams): ZodType {
|
||||
// Handle boolean schemas
|
||||
if (typeof schema === "boolean") {
|
||||
return schema ? z.any() : z.never();
|
||||
}
|
||||
|
||||
const version = detectVersion(schema, params?.defaultTarget);
|
||||
const defs = (schema.$defs || schema.definitions || {}) as Record<string, JSONSchema.JSONSchema>;
|
||||
|
||||
const ctx: ConversionContext = {
|
||||
version,
|
||||
defs,
|
||||
refs: new Map(),
|
||||
processing: new Set(),
|
||||
rootSchema: schema,
|
||||
registry: params?.registry ?? globalRegistry,
|
||||
};
|
||||
|
||||
return convertSchema(schema, ctx);
|
||||
}
|
||||
5
mcp-server-ssh/node_modules/zod/src/v4/classic/index.ts
generated
vendored
Normal file
5
mcp-server-ssh/node_modules/zod/src/v4/classic/index.ts
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import * as z from "./external.js";
|
||||
|
||||
export { z };
|
||||
export * from "./external.js";
|
||||
export default z;
|
||||
90
mcp-server-ssh/node_modules/zod/src/v4/classic/iso.ts
generated
vendored
Normal file
90
mcp-server-ssh/node_modules/zod/src/v4/classic/iso.ts
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
import * as core from "../core/index.js";
|
||||
import * as schemas from "./schemas.js";
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//////////////////////////////////////////////
|
||||
////////// //////////
|
||||
////////// ZodISODateTime //////////
|
||||
////////// //////////
|
||||
//////////////////////////////////////////////
|
||||
//////////////////////////////////////////////
|
||||
|
||||
export interface ZodISODateTime extends schemas.ZodStringFormat {
|
||||
_zod: core.$ZodISODateTimeInternals;
|
||||
}
|
||||
export const ZodISODateTime: core.$constructor<ZodISODateTime> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodISODateTime",
|
||||
(inst, def) => {
|
||||
core.$ZodISODateTime.init(inst, def);
|
||||
schemas.ZodStringFormat.init(inst, def);
|
||||
}
|
||||
);
|
||||
|
||||
export function datetime(params?: string | core.$ZodISODateTimeParams): ZodISODateTime {
|
||||
return core._isoDateTime(ZodISODateTime, params);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
//////////////////////////////////////////
|
||||
////////// //////////
|
||||
////////// ZodISODate //////////
|
||||
////////// //////////
|
||||
//////////////////////////////////////////
|
||||
//////////////////////////////////////////
|
||||
|
||||
export interface ZodISODate extends schemas.ZodStringFormat {
|
||||
_zod: core.$ZodISODateInternals;
|
||||
}
|
||||
export const ZodISODate: core.$constructor<ZodISODate> = /*@__PURE__*/ core.$constructor("ZodISODate", (inst, def) => {
|
||||
core.$ZodISODate.init(inst, def);
|
||||
schemas.ZodStringFormat.init(inst, def);
|
||||
});
|
||||
|
||||
export function date(params?: string | core.$ZodISODateParams): ZodISODate {
|
||||
return core._isoDate(ZodISODate, params);
|
||||
}
|
||||
|
||||
// ZodISOTime
|
||||
|
||||
//////////////////////////////////////////
|
||||
//////////////////////////////////////////
|
||||
////////// //////////
|
||||
////////// ZodISOTime //////////
|
||||
////////// //////////
|
||||
//////////////////////////////////////////
|
||||
//////////////////////////////////////////
|
||||
|
||||
export interface ZodISOTime extends schemas.ZodStringFormat {
|
||||
_zod: core.$ZodISOTimeInternals;
|
||||
}
|
||||
export const ZodISOTime: core.$constructor<ZodISOTime> = /*@__PURE__*/ core.$constructor("ZodISOTime", (inst, def) => {
|
||||
core.$ZodISOTime.init(inst, def);
|
||||
schemas.ZodStringFormat.init(inst, def);
|
||||
});
|
||||
|
||||
export function time(params?: string | core.$ZodISOTimeParams): ZodISOTime {
|
||||
return core._isoTime(ZodISOTime, params);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////
|
||||
//////////////////////////////////////////////
|
||||
////////// //////////
|
||||
////////// ZodISODuration //////////
|
||||
////////// //////////
|
||||
//////////////////////////////////////////////
|
||||
//////////////////////////////////////////////
|
||||
|
||||
export interface ZodISODuration extends schemas.ZodStringFormat {
|
||||
_zod: core.$ZodISODurationInternals;
|
||||
}
|
||||
export const ZodISODuration: core.$constructor<ZodISODuration> = /*@__PURE__*/ core.$constructor(
|
||||
"ZodISODuration",
|
||||
(inst, def) => {
|
||||
core.$ZodISODuration.init(inst, def);
|
||||
schemas.ZodStringFormat.init(inst, def);
|
||||
}
|
||||
);
|
||||
|
||||
export function duration(params?: string | core.$ZodISODurationParams): ZodISODuration {
|
||||
return core._isoDuration(ZodISODuration, params);
|
||||
}
|
||||
82
mcp-server-ssh/node_modules/zod/src/v4/classic/parse.ts
generated
vendored
Normal file
82
mcp-server-ssh/node_modules/zod/src/v4/classic/parse.ts
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
import * as core from "../core/index.js";
|
||||
import { type ZodError, ZodRealError } from "./errors.js";
|
||||
|
||||
export type ZodSafeParseResult<T> = ZodSafeParseSuccess<T> | ZodSafeParseError<T>;
|
||||
export type ZodSafeParseSuccess<T> = { success: true; data: T; error?: never };
|
||||
export type ZodSafeParseError<T> = { success: false; data?: never; error: ZodError<T> };
|
||||
|
||||
export const parse: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>,
|
||||
_params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass }
|
||||
) => core.output<T> = /* @__PURE__ */ core._parse(ZodRealError) as any;
|
||||
|
||||
export const parseAsync: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>,
|
||||
_params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass }
|
||||
) => Promise<core.output<T>> = /* @__PURE__ */ core._parseAsync(ZodRealError) as any;
|
||||
|
||||
export const safeParse: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
// _params?: { callee?: core.util.AnyFunc; Err?: core.$ZodErrorClass }
|
||||
) => ZodSafeParseResult<core.output<T>> = /* @__PURE__ */ core._safeParse(ZodRealError) as any;
|
||||
|
||||
export const safeParseAsync: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => Promise<ZodSafeParseResult<core.output<T>>> = /* @__PURE__ */ core._safeParseAsync(ZodRealError) as any;
|
||||
|
||||
// Codec functions
|
||||
export const encode: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => core.input<T> = /* @__PURE__ */ core._encode(ZodRealError) as any;
|
||||
|
||||
export const decode: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => core.output<T> = /* @__PURE__ */ core._decode(ZodRealError) as any;
|
||||
|
||||
export const encodeAsync: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => Promise<core.input<T>> = /* @__PURE__ */ core._encodeAsync(ZodRealError) as any;
|
||||
|
||||
export const decodeAsync: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => Promise<core.output<T>> = /* @__PURE__ */ core._decodeAsync(ZodRealError) as any;
|
||||
|
||||
export const safeEncode: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => ZodSafeParseResult<core.input<T>> = /* @__PURE__ */ core._safeEncode(ZodRealError) as any;
|
||||
|
||||
export const safeDecode: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => ZodSafeParseResult<core.output<T>> = /* @__PURE__ */ core._safeDecode(ZodRealError) as any;
|
||||
|
||||
export const safeEncodeAsync: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => Promise<ZodSafeParseResult<core.input<T>>> = /* @__PURE__ */ core._safeEncodeAsync(ZodRealError) as any;
|
||||
|
||||
export const safeDecodeAsync: <T extends core.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: core.ParseContext<core.$ZodIssue>
|
||||
) => Promise<ZodSafeParseResult<core.output<T>>> = /* @__PURE__ */ core._safeDecodeAsync(ZodRealError) as any;
|
||||
2409
mcp-server-ssh/node_modules/zod/src/v4/classic/schemas.ts
generated
vendored
Normal file
2409
mcp-server-ssh/node_modules/zod/src/v4/classic/schemas.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
26
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/anyunknown.test.ts
generated
vendored
Normal file
26
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/anyunknown.test.ts
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("check any inference", () => {
|
||||
const t1 = z.any();
|
||||
t1.optional();
|
||||
t1.nullable();
|
||||
type t1 = z.infer<typeof t1>;
|
||||
expectTypeOf<t1>().toEqualTypeOf<any>();
|
||||
});
|
||||
|
||||
test("check unknown inference", () => {
|
||||
const t1 = z.unknown();
|
||||
t1.optional();
|
||||
t1.nullable();
|
||||
type t1 = z.infer<typeof t1>;
|
||||
expectTypeOf<t1>().toEqualTypeOf<unknown>();
|
||||
});
|
||||
|
||||
test("check never inference", () => {
|
||||
const t1 = z.never();
|
||||
expect(() => t1.parse(undefined)).toThrow();
|
||||
expect(() => t1.parse("asdf")).toThrow();
|
||||
expect(() => t1.parse(null)).toThrow();
|
||||
});
|
||||
59
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/apply.test.ts
generated
vendored
Normal file
59
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/apply.test.ts
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("basic apply (object)", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.number(),
|
||||
b: z.string(),
|
||||
})
|
||||
.apply((s) => s.omit({ b: true }))
|
||||
.apply((s) => s.extend({ c: z.boolean() }));
|
||||
|
||||
expect(z.toJSONSchema(schema)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"a": {
|
||||
"type": "number",
|
||||
},
|
||||
"c": {
|
||||
"type": "boolean",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"a",
|
||||
"c",
|
||||
],
|
||||
"type": "object",
|
||||
}
|
||||
`);
|
||||
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<{
|
||||
a: number;
|
||||
c: boolean;
|
||||
}>();
|
||||
});
|
||||
|
||||
test("basic apply (number)", () => {
|
||||
const setCommonNumberChecks = <T extends z.ZodNumber>(schema: T) => {
|
||||
return schema.min(0).max(100);
|
||||
};
|
||||
|
||||
const schema = z.number().apply(setCommonNumberChecks).nullable();
|
||||
|
||||
expect(() => schema.parse(-1)).toThrowError();
|
||||
expect(() => schema.parse(101)).toThrowError();
|
||||
expect(schema.parse(0)).toBe(0);
|
||||
expect(schema.parse(null)).toBe(null);
|
||||
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<number | null>();
|
||||
});
|
||||
|
||||
test("The callback's return value becomes the apply's return value.", () => {
|
||||
const symbol = Symbol();
|
||||
const result = z.number().apply(() => symbol);
|
||||
|
||||
expect(result).toBe(symbol);
|
||||
expectTypeOf<typeof result>().toEqualTypeOf<symbol>();
|
||||
});
|
||||
264
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/array.test.ts
generated
vendored
Normal file
264
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/array.test.ts
generated
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("type inference", () => {
|
||||
const schema = z.string().array();
|
||||
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<string[]>();
|
||||
});
|
||||
|
||||
test("array min/max", () => {
|
||||
const schema = z.array(z.string()).min(2).max(2);
|
||||
const r1 = schema.safeParse(["asdf"]);
|
||||
expect(r1.success).toEqual(false);
|
||||
expect(r1.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected array to have >=2 items",
|
||||
"minimum": 2,
|
||||
"origin": "array",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
||||
const r2 = schema.safeParse(["asdf", "asdf", "asdf"]);
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 2,
|
||||
"message": "Too big: expected array to have <=2 items",
|
||||
"origin": "array",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test("array length", () => {
|
||||
const schema = z.array(z.string()).length(2);
|
||||
schema.parse(["asdf", "asdf"]);
|
||||
|
||||
const r1 = schema.safeParse(["asdf"]);
|
||||
expect(r1.success).toEqual(false);
|
||||
expect(r1.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"exact": true,
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected array to have >=2 items",
|
||||
"minimum": 2,
|
||||
"origin": "array",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
||||
const r2 = schema.safeParse(["asdf", "asdf", "asdf"]);
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"exact": true,
|
||||
"inclusive": true,
|
||||
"maximum": 2,
|
||||
"message": "Too big: expected array to have <=2 items",
|
||||
"origin": "array",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test("array.nonempty()", () => {
|
||||
const schema = z.string().array().nonempty();
|
||||
schema.parse(["a"]);
|
||||
expect(() => schema.parse([])).toThrow();
|
||||
});
|
||||
|
||||
test("array.nonempty().max()", () => {
|
||||
const schema = z.string().array().nonempty().max(2);
|
||||
schema.parse(["a"]);
|
||||
expect(() => schema.parse([])).toThrow();
|
||||
expect(() => schema.parse(["a", "a", "a"])).toThrow();
|
||||
});
|
||||
|
||||
test("parse empty array in nonempty", () => {
|
||||
expect(() =>
|
||||
z
|
||||
.array(z.string())
|
||||
.nonempty()
|
||||
.parse([] as any)
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
test("get element", () => {
|
||||
const schema = z.string().array();
|
||||
schema.element.parse("asdf");
|
||||
expect(() => schema.element.parse(12)).toThrow();
|
||||
});
|
||||
|
||||
test("continue parsing despite array size error", () => {
|
||||
const schema = z.object({
|
||||
people: z.string().array().min(2),
|
||||
});
|
||||
|
||||
const result = schema.safeParse({
|
||||
people: [123],
|
||||
});
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"people",
|
||||
0
|
||||
],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
},
|
||||
{
|
||||
"origin": "array",
|
||||
"code": "too_small",
|
||||
"minimum": 2,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"people"
|
||||
],
|
||||
"message": "Too small: expected array to have >=2 items"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("parse should fail given sparse array", () => {
|
||||
const schema = z.array(z.string()).nonempty().min(1).max(3);
|
||||
const result = schema.safeParse(new Array(3));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
0
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
1
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
2
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
// const unique = z.string().array().unique();
|
||||
// const uniqueArrayOfObjects = z.array(z.object({ name: z.string() })).unique({ identifier: (item) => item.name });
|
||||
|
||||
// test("passing unique validation", () => {
|
||||
// unique.parse(["a", "b", "c"]);
|
||||
// uniqueArrayOfObjects.parse([{ name: "Leo" }, { name: "Joe" }]);
|
||||
// });
|
||||
|
||||
// test("failing unique validation", () => {
|
||||
// expect(() => unique.parse(["a", "a", "b"])).toThrow();
|
||||
// expect(() => uniqueArrayOfObjects.parse([{ name: "Leo" }, { name: "Leo" }])).toThrow();
|
||||
// });
|
||||
|
||||
// test("continue parsing despite array of primitives uniqueness error", () => {
|
||||
// const schema = z.number().array().unique();
|
||||
|
||||
// const result = schema.safeParse([1, 1, 2, 2, 3]);
|
||||
|
||||
// expect(result.success).toEqual(false);
|
||||
// if (!result.success) {
|
||||
// const issue = result.error.issues.find(({ code }) => code === "not_unique");
|
||||
// expect(issue?.message).toEqual("Values must be unique");
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("continue parsing despite array of objects not_unique error", () => {
|
||||
// const schema = z.array(z.object({ name: z.string() })).unique({
|
||||
// identifier: (item) => item.name,
|
||||
// showDuplicates: true,
|
||||
// });
|
||||
|
||||
// const result = schema.safeParse([
|
||||
// { name: "Leo" },
|
||||
// { name: "Joe" },
|
||||
// { name: "Leo" },
|
||||
// ]);
|
||||
|
||||
// expect(result.success).toEqual(false);
|
||||
// if (!result.success) {
|
||||
// const issue = result.error.issues.find(({ code }) => code === "not_unique");
|
||||
// expect(issue?.message).toEqual("Element(s): 'Leo' not unique");
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("returns custom error message without duplicate elements", () => {
|
||||
// const schema = z.number().array().unique({ message: "Custom message" });
|
||||
|
||||
// const result = schema.safeParse([1, 1, 2, 2, 3]);
|
||||
|
||||
// expect(result.success).toEqual(false);
|
||||
// if (!result.success) {
|
||||
// const issue = result.error.issues.find(({ code }) => code === "not_unique");
|
||||
// expect(issue?.message).toEqual("Custom message");
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("returns error message with duplicate elements", () => {
|
||||
// const schema = z.number().array().unique({ showDuplicates: true });
|
||||
|
||||
// const result = schema.safeParse([1, 1, 2, 2, 3]);
|
||||
|
||||
// expect(result.success).toEqual(false);
|
||||
// if (!result.success) {
|
||||
// const issue = result.error.issues.find(({ code }) => code === "not_unique");
|
||||
// expect(issue?.message).toEqual("Element(s): '1,2' not unique");
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("returns custom error message with duplicate elements", () => {
|
||||
// const schema = z
|
||||
// .number()
|
||||
// .array()
|
||||
// .unique({
|
||||
// message: (item) => `Custom message: '${item}' are not unique`,
|
||||
// showDuplicates: true,
|
||||
// });
|
||||
|
||||
// const result = schema.safeParse([1, 1, 2, 2, 3]);
|
||||
|
||||
// expect(result.success).toEqual(false);
|
||||
// if (!result.success) {
|
||||
// const issue = result.error.issues.find(({ code }) => code === "not_unique");
|
||||
// expect(issue?.message).toEqual("Custom message: '1,2' are not unique");
|
||||
// }
|
||||
// });
|
||||
210
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/assignability.test.ts
generated
vendored
Normal file
210
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/assignability.test.ts
generated
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
import { expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("assignability", () => {
|
||||
// $ZodString
|
||||
z.string() satisfies z.core.$ZodString;
|
||||
z.string() satisfies z.ZodString;
|
||||
|
||||
// $ZodNumber
|
||||
z.number() satisfies z.core.$ZodNumber;
|
||||
z.number() satisfies z.ZodNumber;
|
||||
|
||||
// $ZodBigInt
|
||||
z.bigint() satisfies z.core.$ZodBigInt;
|
||||
z.bigint() satisfies z.ZodBigInt;
|
||||
|
||||
// $ZodBoolean
|
||||
z.boolean() satisfies z.core.$ZodBoolean;
|
||||
z.boolean() satisfies z.ZodBoolean;
|
||||
|
||||
// $ZodDate
|
||||
z.date() satisfies z.core.$ZodDate;
|
||||
z.date() satisfies z.ZodDate;
|
||||
|
||||
// $ZodSymbol
|
||||
z.symbol() satisfies z.core.$ZodSymbol;
|
||||
z.symbol() satisfies z.ZodSymbol;
|
||||
|
||||
// $ZodUndefined
|
||||
z.undefined() satisfies z.core.$ZodUndefined;
|
||||
z.undefined() satisfies z.ZodUndefined;
|
||||
|
||||
// $ZodNullable
|
||||
z.string().nullable() satisfies z.core.$ZodNullable;
|
||||
z.string().nullable() satisfies z.ZodNullable;
|
||||
|
||||
// $ZodNull
|
||||
z.null() satisfies z.core.$ZodNull;
|
||||
z.null() satisfies z.ZodNull;
|
||||
|
||||
// $ZodAny
|
||||
z.any() satisfies z.core.$ZodAny;
|
||||
z.any() satisfies z.ZodAny;
|
||||
|
||||
// $ZodUnknown
|
||||
z.unknown() satisfies z.core.$ZodUnknown;
|
||||
z.unknown() satisfies z.ZodUnknown;
|
||||
|
||||
// $ZodNever
|
||||
z.never() satisfies z.core.$ZodNever;
|
||||
z.never() satisfies z.ZodNever;
|
||||
|
||||
// $ZodVoid
|
||||
z.void() satisfies z.core.$ZodVoid;
|
||||
z.void() satisfies z.ZodVoid;
|
||||
|
||||
// $ZodArray
|
||||
z.array(z.string()) satisfies z.core.$ZodArray;
|
||||
z.array(z.string()) satisfies z.ZodArray;
|
||||
z.array(z.string()) satisfies z.ZodType<Array<unknown>>;
|
||||
|
||||
// $ZodObject
|
||||
z.object({ key: z.string() }) satisfies z.core.$ZodObject;
|
||||
z.object({ key: z.string() }) satisfies z.ZodObject<{ key: z.ZodType }>;
|
||||
z.object({ key: z.string() }) satisfies z.ZodType<{ key: string }>;
|
||||
|
||||
// $ZodUnion
|
||||
z.union([z.string(), z.number()]) satisfies z.core.$ZodUnion;
|
||||
z.union([z.string(), z.number()]) satisfies z.ZodUnion;
|
||||
z.union([z.string(), z.number()]) satisfies z.ZodType<string | number>;
|
||||
|
||||
// $ZodIntersection
|
||||
z.intersection(z.string(), z.number()) satisfies z.core.$ZodIntersection;
|
||||
z.intersection(z.string(), z.number()) satisfies z.ZodIntersection;
|
||||
|
||||
// $ZodTuple
|
||||
z.tuple([z.string(), z.number()]) satisfies z.core.$ZodTuple;
|
||||
z.tuple([z.string(), z.number()]) satisfies z.ZodTuple;
|
||||
|
||||
// $ZodRecord
|
||||
z.record(z.string(), z.number()) satisfies z.core.$ZodRecord;
|
||||
z.record(z.string(), z.number()) satisfies z.ZodRecord;
|
||||
|
||||
// $ZodMap
|
||||
z.map(z.string(), z.number()) satisfies z.core.$ZodMap;
|
||||
z.map(z.string(), z.number()) satisfies z.ZodMap;
|
||||
|
||||
// $ZodSet
|
||||
z.set(z.string()) satisfies z.core.$ZodSet;
|
||||
z.set(z.string()) satisfies z.ZodSet;
|
||||
|
||||
// $ZodLiteral
|
||||
z.literal("example") satisfies z.core.$ZodLiteral;
|
||||
z.literal("example") satisfies z.ZodLiteral;
|
||||
|
||||
// $ZodEnum
|
||||
z.enum(["a", "b", "c"]) satisfies z.core.$ZodEnum;
|
||||
z.enum(["a", "b", "c"]) satisfies z.ZodEnum;
|
||||
|
||||
// $ZodPromise
|
||||
z.promise(z.string()) satisfies z.core.$ZodPromise;
|
||||
z.promise(z.string()) satisfies z.ZodPromise;
|
||||
|
||||
// $ZodLazy
|
||||
const lazySchema = z.lazy(() => z.string());
|
||||
lazySchema satisfies z.core.$ZodLazy;
|
||||
lazySchema satisfies z.ZodLazy;
|
||||
|
||||
// $ZodOptional
|
||||
z.string().optional() satisfies z.core.$ZodOptional;
|
||||
z.string().optional() satisfies z.ZodOptional;
|
||||
|
||||
// $ZodDefault
|
||||
z.string().default("default") satisfies z.core.$ZodDefault;
|
||||
z.string().default("default") satisfies z.ZodDefault;
|
||||
|
||||
// $ZodTemplateLiteral
|
||||
z.templateLiteral([z.literal("a"), z.literal("b")]) satisfies z.core.$ZodTemplateLiteral;
|
||||
z.templateLiteral([z.literal("a"), z.literal("b")]) satisfies z.ZodTemplateLiteral;
|
||||
|
||||
// $ZodCustom
|
||||
z.custom<string>((val) => typeof val === "string") satisfies z.core.$ZodCustom;
|
||||
z.custom<string>((val) => typeof val === "string") satisfies z.ZodCustom;
|
||||
|
||||
// $ZodTransform
|
||||
z.transform((val) => val as string) satisfies z.core.$ZodTransform;
|
||||
z.transform((val) => val as string) satisfies z.ZodTransform;
|
||||
|
||||
// $ZodNonOptional
|
||||
z.string().optional().nonoptional() satisfies z.core.$ZodNonOptional;
|
||||
z.string().optional().nonoptional() satisfies z.ZodNonOptional;
|
||||
|
||||
// $ZodReadonly
|
||||
z.object({ key: z.string() }).readonly() satisfies z.core.$ZodReadonly;
|
||||
z.object({ key: z.string() }).readonly() satisfies z.ZodReadonly;
|
||||
|
||||
// $ZodNaN
|
||||
z.nan() satisfies z.core.$ZodNaN;
|
||||
z.nan() satisfies z.ZodNaN;
|
||||
|
||||
// $ZodPipe
|
||||
z.unknown().pipe(z.number()) satisfies z.core.$ZodPipe;
|
||||
z.unknown().pipe(z.number()) satisfies z.ZodPipe;
|
||||
|
||||
// $ZodSuccess
|
||||
z.success(z.string()) satisfies z.core.$ZodSuccess;
|
||||
z.success(z.string()) satisfies z.ZodSuccess;
|
||||
|
||||
// $ZodCatch
|
||||
z.string().catch("fallback") satisfies z.core.$ZodCatch;
|
||||
z.string().catch("fallback") satisfies z.ZodCatch;
|
||||
|
||||
// $ZodFile
|
||||
z.file() satisfies z.core.$ZodFile;
|
||||
z.file() satisfies z.ZodFile;
|
||||
});
|
||||
|
||||
test("checks", () => {
|
||||
const _a: z.core.$ZodCheck = {} as any as z.core.$ZodChecks;
|
||||
const _b: z.core.$ZodCheck = {} as any as z.core.$ZodStringFormatChecks;
|
||||
const _c: z.core.$ZodType = {} as any as z.core.$ZodTypes;
|
||||
const _d: z.core.$ZodType = {} as any as z.core.$ZodStringFormatTypes;
|
||||
});
|
||||
|
||||
test("assignability to $ZodType", () => {
|
||||
z.string() satisfies z.ZodType;
|
||||
z.number() satisfies z.ZodType;
|
||||
z.boolean() satisfies z.ZodType;
|
||||
z.object({ key: z.string() }) satisfies z.ZodType;
|
||||
z.object({ key: z.string() }) satisfies z.ZodType<{ key: string }>;
|
||||
z.array(z.string()) satisfies z.ZodType;
|
||||
z.union([z.string(), z.number()]) satisfies z.ZodType;
|
||||
z.intersection(z.string(), z.number()) satisfies z.ZodType;
|
||||
z.tuple([z.string(), z.number()]) satisfies z.ZodType;
|
||||
z.record(z.string(), z.number()) satisfies z.ZodType;
|
||||
z.map(z.string(), z.number()) satisfies z.ZodType;
|
||||
z.set(z.string()) satisfies z.ZodType;
|
||||
z.literal("example") satisfies z.ZodType;
|
||||
|
||||
expectTypeOf<z.ZodType extends z.core.$ZodType ? true : false>().toEqualTypeOf<true>();
|
||||
});
|
||||
|
||||
test("assignability with narrowing", () => {
|
||||
type _RefinedSchema<T extends z.ZodType<object> | z.ZodUnion> = T extends z.ZodUnion
|
||||
? RefinedUnionSchema<T> // <-- Type instantiation is excessively deep and possibly infinite.
|
||||
: T extends z.ZodType<object>
|
||||
? RefinedTypeSchema<z.output<T>> // <-- Type instantiation is excessively deep and possibly infinite.
|
||||
: never;
|
||||
|
||||
type RefinedTypeSchema<T extends object> = T;
|
||||
|
||||
type RefinedUnionSchema<T extends z.ZodUnion> = T;
|
||||
});
|
||||
|
||||
test("generic assignability in objects", () => {
|
||||
interface SortItem<T extends string> {
|
||||
key: T;
|
||||
order: string;
|
||||
}
|
||||
|
||||
const createSortItemSchema = <T extends z.ZodType<string>>(sortKeySchema: T) =>
|
||||
z.object({
|
||||
key: sortKeySchema,
|
||||
order: z.string(),
|
||||
});
|
||||
|
||||
<T extends z.ZodType<string>>(sortKeySchema: T, defaultSortBy: SortItem<z.output<T>>[] = []) =>
|
||||
createSortItemSchema(sortKeySchema).array().default(defaultSortBy);
|
||||
});
|
||||
381
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/async-parsing.test.ts
generated
vendored
Normal file
381
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/async-parsing.test.ts
generated
vendored
Normal file
@@ -0,0 +1,381 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
/// string
|
||||
const stringSchema = z.string();
|
||||
|
||||
test("string async parse", async () => {
|
||||
const goodData = "XXX";
|
||||
const badData = 12;
|
||||
|
||||
const goodResult = await stringSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await stringSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// number
|
||||
const numberSchema = z.number();
|
||||
test("number async parse", async () => {
|
||||
const goodData = 1234.2353;
|
||||
const badData = "1234";
|
||||
|
||||
const goodResult = await numberSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await numberSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// bigInt
|
||||
const bigIntSchema = z.bigint();
|
||||
test("bigInt async parse", async () => {
|
||||
const goodData = BigInt(145);
|
||||
const badData = 134;
|
||||
|
||||
const goodResult = await bigIntSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await bigIntSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// boolean
|
||||
const booleanSchema = z.boolean();
|
||||
test("boolean async parse", async () => {
|
||||
const goodData = true;
|
||||
const badData = 1;
|
||||
|
||||
const goodResult = await booleanSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await booleanSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// date
|
||||
const dateSchema = z.date();
|
||||
test("date async parse", async () => {
|
||||
const goodData = new Date();
|
||||
const badData = new Date().toISOString();
|
||||
|
||||
const goodResult = await dateSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await dateSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// undefined
|
||||
const undefinedSchema = z.undefined();
|
||||
test("undefined async parse", async () => {
|
||||
const goodData = undefined;
|
||||
const badData = "XXX";
|
||||
|
||||
const goodResult = await undefinedSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(undefined);
|
||||
|
||||
const badResult = await undefinedSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// null
|
||||
const nullSchema = z.null();
|
||||
test("null async parse", async () => {
|
||||
const goodData = null;
|
||||
const badData = undefined;
|
||||
|
||||
const goodResult = await nullSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await nullSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// any
|
||||
const anySchema = z.any();
|
||||
test("any async parse", async () => {
|
||||
const goodData = [{}];
|
||||
// const badData = 'XXX';
|
||||
|
||||
const goodResult = await anySchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
// const badResult = await anySchema.safeParseAsync(badData);
|
||||
// expect(badResult.success).toBe(false);
|
||||
// if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// unknown
|
||||
const unknownSchema = z.unknown();
|
||||
test("unknown async parse", async () => {
|
||||
const goodData = ["asdf", 124, () => {}];
|
||||
// const badData = 'XXX';
|
||||
|
||||
const goodResult = await unknownSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
// const badResult = await unknownSchema.safeParseAsync(badData);
|
||||
// expect(badResult.success).toBe(false);
|
||||
// if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// void
|
||||
const voidSchema = z.void();
|
||||
test("void async parse", async () => {
|
||||
const goodData = undefined;
|
||||
const badData = 0;
|
||||
|
||||
const goodResult = await voidSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await voidSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// array
|
||||
const arraySchema = z.array(z.string());
|
||||
test("array async parse", async () => {
|
||||
const goodData = ["XXX"];
|
||||
const badData = "XXX";
|
||||
|
||||
const goodResult = await arraySchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await arraySchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// object
|
||||
const objectSchema = z.object({ string: z.string() });
|
||||
test("object async parse", async () => {
|
||||
const goodData = { string: "XXX" };
|
||||
const badData = { string: 12 };
|
||||
|
||||
const goodResult = await objectSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await objectSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// union
|
||||
const unionSchema = z.union([z.string(), z.undefined()]);
|
||||
test("union async parse", async () => {
|
||||
const goodData = undefined;
|
||||
const badData = null;
|
||||
|
||||
const goodResult = await unionSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await unionSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// record
|
||||
const recordSchema = z.record(z.string(), z.object({}));
|
||||
test("record async parse", async () => {
|
||||
const goodData = { adsf: {}, asdf: {} };
|
||||
const badData = [{}];
|
||||
|
||||
const goodResult = await recordSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await recordSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// function
|
||||
// const functionSchema = z.function();
|
||||
// test("function async parse", async () => {
|
||||
// const goodData = () => {};
|
||||
// const badData = "XXX";
|
||||
|
||||
// const goodResult = await functionSchema.safeParseAsync(goodData);
|
||||
// expect(goodResult.success).toBe(true);
|
||||
// if (goodResult.success) expect(typeof goodResult.data).toEqual("function");
|
||||
|
||||
// const badResult = await functionSchema.safeParseAsync(badData);
|
||||
// expect(badResult.success).toBe(false);
|
||||
// if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
// });
|
||||
|
||||
/// literal
|
||||
const literalSchema = z.literal("asdf");
|
||||
test("literal async parse", async () => {
|
||||
const goodData = "asdf";
|
||||
const badData = "asdff";
|
||||
|
||||
const goodResult = await literalSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await literalSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// enum
|
||||
const enumSchema = z.enum(["fish", "whale"]);
|
||||
test("enum async parse", async () => {
|
||||
const goodData = "whale";
|
||||
const badData = "leopard";
|
||||
|
||||
const goodResult = await enumSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await enumSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// nativeEnum
|
||||
enum nativeEnumTest {
|
||||
asdf = "qwer",
|
||||
}
|
||||
// @ts-ignore
|
||||
const nativeEnumSchema = z.nativeEnum(nativeEnumTest);
|
||||
test("nativeEnum async parse", async () => {
|
||||
const goodData = nativeEnumTest.asdf;
|
||||
const badData = "asdf";
|
||||
|
||||
const goodResult = await nativeEnumSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
if (goodResult.success) expect(goodResult.data).toEqual(goodData);
|
||||
|
||||
const badResult = await nativeEnumSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
if (!badResult.success) expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
/// promise
|
||||
const promiseSchema = z.promise(z.number());
|
||||
test("promise async parse good", async () => {
|
||||
const goodData = Promise.resolve(123);
|
||||
|
||||
const goodResult = await promiseSchema.safeParseAsync(goodData);
|
||||
expect(goodResult.success).toBe(true);
|
||||
expect(typeof goodResult.data).toEqual("number");
|
||||
expect(goodResult.data).toEqual(123);
|
||||
});
|
||||
|
||||
test("promise async parse bad", async () => {
|
||||
const badData = Promise.resolve("XXX");
|
||||
const badResult = await promiseSchema.safeParseAsync(badData);
|
||||
expect(badResult.success).toBe(false);
|
||||
expect(badResult.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
test("async validation non-empty strings", async () => {
|
||||
const base = z.object({
|
||||
hello: z.string().refine((x) => x && x.length > 0),
|
||||
foo: z.string().refine((x) => x && x.length > 0),
|
||||
});
|
||||
|
||||
const testval = { hello: "", foo: "" };
|
||||
const result1 = base.safeParse(testval);
|
||||
const result2 = base.safeParseAsync(testval);
|
||||
|
||||
const r1 = result1;
|
||||
await result2.then((r2) => {
|
||||
expect(r1.error!.issues.length).toBe(r2.error!.issues.length);
|
||||
});
|
||||
});
|
||||
|
||||
test("async validation multiple errors 1", async () => {
|
||||
const base = z.object({
|
||||
hello: z.string(),
|
||||
foo: z.number(),
|
||||
});
|
||||
|
||||
const testval = { hello: 3, foo: "hello" };
|
||||
const result1 = base.safeParse(testval);
|
||||
const result2 = base.safeParseAsync(testval);
|
||||
|
||||
await result2.then((result2) => {
|
||||
expect(result2.error!.issues.length).toBe(result1.error!.issues.length);
|
||||
});
|
||||
});
|
||||
|
||||
test("async validation multiple errors 2", async () => {
|
||||
const base = (is_async?: boolean) =>
|
||||
z.object({
|
||||
hello: z.string(),
|
||||
foo: z.object({
|
||||
bar: z.number().refine(
|
||||
is_async
|
||||
? async () =>
|
||||
new Promise((resolve) => {
|
||||
setTimeout(() => resolve(false), 500);
|
||||
})
|
||||
: () => false
|
||||
),
|
||||
}),
|
||||
});
|
||||
|
||||
const testval = { hello: 3, foo: { bar: 4 } };
|
||||
const result1 = base().safeParse(testval);
|
||||
const result2 = base(true).safeParseAsync(testval);
|
||||
|
||||
await result2.then((result2) => {
|
||||
expect(result1.error!.issues.length).toBe(result2.error!.issues.length);
|
||||
});
|
||||
});
|
||||
|
||||
test("ensure early async failure prevents follow-up refinement checks", async () => {
|
||||
let count = 0;
|
||||
const base = z.object({
|
||||
hello: z.string(),
|
||||
foo: z
|
||||
.number()
|
||||
.refine(async () => {
|
||||
count++;
|
||||
return true;
|
||||
})
|
||||
.refine(async () => {
|
||||
count++;
|
||||
return true;
|
||||
}, "Good"),
|
||||
});
|
||||
|
||||
const testval = { hello: "bye", foo: 3 };
|
||||
const result = await base.safeParseAsync(testval);
|
||||
if (result.success === false) {
|
||||
expect(result.error.issues.length).toBe(1);
|
||||
expect(count).toBe(1);
|
||||
}
|
||||
|
||||
// await result.then((r) => {
|
||||
// if (r.success === false) expect(r.error.issues.length).toBe(1);
|
||||
// expect(count).toBe(2);
|
||||
// });
|
||||
});
|
||||
68
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/async-refinements.test.ts
generated
vendored
Normal file
68
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/async-refinements.test.ts
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("async refine .parse()", async () => {
|
||||
// throws ZodAsyncError
|
||||
const s1 = z.string().refine(async (_val) => true);
|
||||
expect(() => s1.safeParse("asdf")).toThrow();
|
||||
});
|
||||
|
||||
test("async refine", async () => {
|
||||
const s1 = z.string().refine(async (_val) => true);
|
||||
const r1 = await s1.parseAsync("asdf");
|
||||
expect(r1).toEqual("asdf");
|
||||
|
||||
const s2 = z.string().refine(async (_val) => false);
|
||||
const r2 = await s2.safeParseAsync("asdf");
|
||||
expect(r2.success).toBe(false);
|
||||
expect(r2).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("async refine with Promises", async () => {
|
||||
// expect.assertions(2);
|
||||
|
||||
const schema1 = z.string().refine((_val) => Promise.resolve(true));
|
||||
const v1 = await schema1.parseAsync("asdf");
|
||||
expect(v1).toEqual("asdf");
|
||||
|
||||
const schema2 = z.string().refine((_val) => Promise.resolve(false));
|
||||
await expect(schema2.parseAsync("asdf")).rejects.toBeDefined();
|
||||
|
||||
const schema3 = z.string().refine((_val) => Promise.resolve(true));
|
||||
await expect(schema3.parseAsync("asdf")).resolves.toEqual("asdf");
|
||||
return await expect(schema3.parseAsync("qwer")).resolves.toEqual("qwer");
|
||||
});
|
||||
|
||||
test("async refine that uses value", async () => {
|
||||
const schema1 = z.string().refine(async (val) => {
|
||||
return val.length > 5;
|
||||
});
|
||||
|
||||
const r1 = await schema1.safeParseAsync("asdf");
|
||||
expect(r1.success).toBe(false);
|
||||
expect(r1.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const r2 = await schema1.safeParseAsync("asdf123");
|
||||
expect(r2.success).toBe(true);
|
||||
expect(r2.data).toEqual("asdf123");
|
||||
});
|
||||
7
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/base.test.ts
generated
vendored
Normal file
7
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/base.test.ts
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("test this binding", () => {
|
||||
const parse = z.string().parse;
|
||||
expect(parse("asdf")).toBe("asdf");
|
||||
});
|
||||
54
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/bigint.test.ts
generated
vendored
Normal file
54
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/bigint.test.ts
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const gtFive = z.bigint().gt(BigInt(5));
|
||||
const gteFive = z.bigint().gte(BigInt(5));
|
||||
const ltFive = z.bigint().lt(BigInt(5));
|
||||
const lteFive = z.bigint().lte(BigInt(5));
|
||||
const positive = z.bigint().positive();
|
||||
const negative = z.bigint().negative();
|
||||
const nonnegative = z.bigint().nonnegative();
|
||||
const nonpositive = z.bigint().nonpositive();
|
||||
const multipleOfFive = z.bigint().multipleOf(BigInt(5));
|
||||
|
||||
test("passing validations", () => {
|
||||
z.bigint().parse(BigInt(1));
|
||||
z.bigint().parse(BigInt(0));
|
||||
z.bigint().parse(BigInt(-1));
|
||||
gtFive.parse(BigInt(6));
|
||||
gteFive.parse(BigInt(5));
|
||||
gteFive.parse(BigInt(6));
|
||||
ltFive.parse(BigInt(4));
|
||||
lteFive.parse(BigInt(5));
|
||||
lteFive.parse(BigInt(4));
|
||||
positive.parse(BigInt(3));
|
||||
negative.parse(BigInt(-2));
|
||||
nonnegative.parse(BigInt(0));
|
||||
nonnegative.parse(BigInt(7));
|
||||
nonpositive.parse(BigInt(0));
|
||||
nonpositive.parse(BigInt(-12));
|
||||
multipleOfFive.parse(BigInt(15));
|
||||
});
|
||||
|
||||
test("failing validations", () => {
|
||||
expect(() => gtFive.parse(BigInt(5))).toThrow();
|
||||
expect(() => gteFive.parse(BigInt(4))).toThrow();
|
||||
expect(() => ltFive.parse(BigInt(5))).toThrow();
|
||||
expect(() => lteFive.parse(BigInt(6))).toThrow();
|
||||
expect(() => positive.parse(BigInt(0))).toThrow();
|
||||
expect(() => positive.parse(BigInt(-2))).toThrow();
|
||||
expect(() => negative.parse(BigInt(0))).toThrow();
|
||||
expect(() => negative.parse(BigInt(3))).toThrow();
|
||||
expect(() => nonnegative.parse(BigInt(-1))).toThrow();
|
||||
expect(() => nonpositive.parse(BigInt(1))).toThrow();
|
||||
expect(() => multipleOfFive.parse(BigInt(13))).toThrow();
|
||||
});
|
||||
|
||||
test("min max getters", () => {
|
||||
expect(z.bigint().min(BigInt(5)).minValue).toEqual(BigInt(5));
|
||||
expect(z.bigint().min(BigInt(5)).min(BigInt(10)).minValue).toEqual(BigInt(10));
|
||||
|
||||
expect(z.bigint().max(BigInt(5)).maxValue).toEqual(BigInt(5));
|
||||
expect(z.bigint().max(BigInt(5)).max(BigInt(1)).maxValue).toEqual(BigInt(1));
|
||||
});
|
||||
106
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/brand.test.ts
generated
vendored
Normal file
106
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/brand.test.ts
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
import { expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("branded types", () => {
|
||||
const mySchema = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
})
|
||||
.brand<"superschema">();
|
||||
|
||||
// simple branding
|
||||
type MySchema = z.infer<typeof mySchema>;
|
||||
|
||||
expectTypeOf<MySchema>().toEqualTypeOf<{ name: string } & z.$brand<"superschema">>();
|
||||
|
||||
const doStuff = (arg: MySchema) => arg;
|
||||
doStuff(mySchema.parse({ name: "hello there" }));
|
||||
|
||||
// inheritance
|
||||
const extendedSchema = mySchema.brand<"subschema">();
|
||||
type ExtendedSchema = z.infer<typeof extendedSchema>;
|
||||
expectTypeOf<ExtendedSchema>().toEqualTypeOf<{ name: string } & z.BRAND<"superschema"> & z.BRAND<"subschema">>();
|
||||
|
||||
doStuff(extendedSchema.parse({ name: "hello again" }));
|
||||
|
||||
// number branding
|
||||
const numberSchema = z.number().brand<42>();
|
||||
type NumberSchema = z.infer<typeof numberSchema>;
|
||||
expectTypeOf<NumberSchema>().toEqualTypeOf<number & { [z.$brand]: { 42: true } }>();
|
||||
|
||||
// symbol branding
|
||||
const MyBrand: unique symbol = Symbol("hello");
|
||||
type MyBrand = typeof MyBrand;
|
||||
const symbolBrand = z.number().brand<"sup">().brand<typeof MyBrand>();
|
||||
type SymbolBrand = z.infer<typeof symbolBrand>;
|
||||
// number & { [z.BRAND]: { sup: true, [MyBrand]: true } }
|
||||
expectTypeOf<SymbolBrand>().toEqualTypeOf<number & z.BRAND<"sup"> & z.BRAND<MyBrand>>();
|
||||
|
||||
// keeping brands out of input types
|
||||
const age = z.number().brand<"age">();
|
||||
|
||||
type Age = z.infer<typeof age>;
|
||||
type AgeInput = z.input<typeof age>;
|
||||
|
||||
expectTypeOf<AgeInput>().not.toEqualTypeOf<Age>();
|
||||
expectTypeOf<number>().toEqualTypeOf<AgeInput>();
|
||||
expectTypeOf<number & z.BRAND<"age">>().toEqualTypeOf<Age>();
|
||||
|
||||
// @ts-expect-error
|
||||
doStuff({ name: "hello there!" });
|
||||
});
|
||||
|
||||
test("$branded", () => {
|
||||
const a = z.string().brand<"a">();
|
||||
|
||||
expectTypeOf<typeof a>().toEqualTypeOf<z.core.$ZodBranded<z.ZodString, "a">>();
|
||||
});
|
||||
|
||||
test("branded record", () => {
|
||||
const recordWithBrandedNumberKeys = z.record(z.string().brand("SomeBrand"), z.number());
|
||||
type recordWithBrandedNumberKeys = z.infer<typeof recordWithBrandedNumberKeys>;
|
||||
expectTypeOf<recordWithBrandedNumberKeys>().toEqualTypeOf<Record<string & z.core.$brand<"SomeBrand">, number>>();
|
||||
});
|
||||
|
||||
test("brand direction: out (default)", () => {
|
||||
const schema = z.string().brand<"A">();
|
||||
type Input = z.input<typeof schema>;
|
||||
type Output = z.output<typeof schema>;
|
||||
|
||||
// output is branded
|
||||
expectTypeOf<Output>().toEqualTypeOf<string & z.$brand<"A">>();
|
||||
// input is NOT branded (default behavior)
|
||||
expectTypeOf<Input>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("brand direction: out (explicit)", () => {
|
||||
const schema = z.string().brand<"A", "out">();
|
||||
type Input = z.input<typeof schema>;
|
||||
type Output = z.output<typeof schema>;
|
||||
|
||||
// output is branded
|
||||
expectTypeOf<Output>().toEqualTypeOf<string & z.$brand<"A">>();
|
||||
// input is NOT branded
|
||||
expectTypeOf<Input>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("brand direction: in", () => {
|
||||
const schema = z.string().brand<"A", "in">();
|
||||
type Input = z.input<typeof schema>;
|
||||
type Output = z.output<typeof schema>;
|
||||
|
||||
// input is branded
|
||||
expectTypeOf<Input>().toEqualTypeOf<string & z.$brand<"A">>();
|
||||
// output is NOT branded
|
||||
expectTypeOf<Output>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("brand direction: inout", () => {
|
||||
const schema = z.string().brand<"A", "inout">();
|
||||
type Input = z.input<typeof schema>;
|
||||
type Output = z.output<typeof schema>;
|
||||
|
||||
// both are branded
|
||||
expectTypeOf<Input>().toEqualTypeOf<string & z.$brand<"A">>();
|
||||
expectTypeOf<Output>().toEqualTypeOf<string & z.$brand<"A">>();
|
||||
});
|
||||
276
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/catch.test.ts
generated
vendored
Normal file
276
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/catch.test.ts
generated
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
test("basic catch", () => {
|
||||
expect(z.string().catch("default").parse(undefined)).toBe("default");
|
||||
});
|
||||
|
||||
test("catch fn does not run when parsing succeeds", () => {
|
||||
let isCalled = false;
|
||||
const cb = () => {
|
||||
isCalled = true;
|
||||
return "asdf";
|
||||
};
|
||||
expect(z.string().catch(cb).parse("test")).toBe("test");
|
||||
expect(isCalled).toEqual(false);
|
||||
});
|
||||
|
||||
test("basic catch async", async () => {
|
||||
const result = await z.string().catch("default").parseAsync(1243);
|
||||
expect(result).toBe("default");
|
||||
});
|
||||
|
||||
test("catch replace wrong types", () => {
|
||||
expect(z.string().catch("default").parse(true)).toBe("default");
|
||||
expect(z.string().catch("default").parse(true)).toBe("default");
|
||||
expect(z.string().catch("default").parse(15)).toBe("default");
|
||||
expect(z.string().catch("default").parse([])).toBe("default");
|
||||
expect(z.string().catch("default").parse(new Map())).toBe("default");
|
||||
expect(z.string().catch("default").parse(new Set())).toBe("default");
|
||||
expect(z.string().catch("default").parse({})).toBe("default");
|
||||
});
|
||||
|
||||
test("catch with transform", () => {
|
||||
const stringWithDefault = z
|
||||
.string()
|
||||
.transform((val) => val.toUpperCase())
|
||||
.catch("default");
|
||||
|
||||
expect(stringWithDefault.parse(undefined)).toBe("default");
|
||||
expect(stringWithDefault.parse(15)).toBe("default");
|
||||
expect(stringWithDefault).toBeInstanceOf(z.ZodCatch);
|
||||
expect(stringWithDefault.unwrap()).toBeInstanceOf(z.ZodPipe);
|
||||
expect(stringWithDefault.unwrap().in).toBeInstanceOf(z.ZodString);
|
||||
expect(stringWithDefault.unwrap().out).toBeInstanceOf(z.ZodTransform);
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("catch on existing optional", () => {
|
||||
const stringWithDefault = z.string().optional().catch("asdf");
|
||||
expect(stringWithDefault.parse(undefined)).toBe(undefined);
|
||||
expect(stringWithDefault.parse(15)).toBe("asdf");
|
||||
expect(stringWithDefault).toBeInstanceOf(z.ZodCatch);
|
||||
expect(stringWithDefault.unwrap()).toBeInstanceOf(z.ZodOptional);
|
||||
expect(stringWithDefault.unwrap().unwrap()).toBeInstanceOf(z.ZodString);
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string | undefined>();
|
||||
});
|
||||
|
||||
test("optional on catch", () => {
|
||||
const stringWithDefault = z.string().catch("asdf").optional();
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string | undefined>();
|
||||
});
|
||||
|
||||
test("complex chain example", () => {
|
||||
const complex = z
|
||||
.string()
|
||||
.catch("asdf")
|
||||
.transform((val) => `${val}!`)
|
||||
.transform((val) => val.toUpperCase())
|
||||
.catch("qwer")
|
||||
.unwrap()
|
||||
.optional()
|
||||
.catch("asdfasdf");
|
||||
|
||||
expect(complex.parse("qwer")).toBe("QWER!");
|
||||
expect(complex.parse(15)).toBe("ASDF!");
|
||||
expect(complex.parse(true)).toBe("ASDF!");
|
||||
});
|
||||
|
||||
test("removeCatch", () => {
|
||||
const stringWithRemovedDefault = z.string().catch("asdf").unwrap();
|
||||
|
||||
type out = z.output<typeof stringWithRemovedDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("nested", () => {
|
||||
const inner = z.string().catch("asdf");
|
||||
const outer = z.object({ inner }).catch({
|
||||
inner: "asdf",
|
||||
});
|
||||
type input = z.input<typeof outer>;
|
||||
expectTypeOf<input>().toEqualTypeOf<{ inner: string }>();
|
||||
type out = z.output<typeof outer>;
|
||||
|
||||
expectTypeOf<out>().toEqualTypeOf<{ inner: string }>();
|
||||
expect(outer.parse(undefined)).toEqual({ inner: "asdf" });
|
||||
expect(outer.parse({})).toEqual({ inner: "asdf" });
|
||||
expect(outer.parse({ inner: undefined })).toEqual({ inner: "asdf" });
|
||||
});
|
||||
|
||||
test("chained catch", () => {
|
||||
const stringWithDefault = z.string().catch("inner").catch("outer");
|
||||
const result = stringWithDefault.parse(undefined);
|
||||
expect(result).toEqual("inner");
|
||||
const resultDiff = stringWithDefault.parse(5);
|
||||
expect(resultDiff).toEqual("inner");
|
||||
});
|
||||
|
||||
test("native enum", () => {
|
||||
enum Fruits {
|
||||
apple = "apple",
|
||||
orange = "orange",
|
||||
}
|
||||
|
||||
const schema = z.object({
|
||||
fruit: z.nativeEnum(Fruits).catch(Fruits.apple),
|
||||
});
|
||||
|
||||
expect(schema.parse({})).toEqual({ fruit: Fruits.apple });
|
||||
expect(schema.parse({ fruit: 15 })).toEqual({ fruit: Fruits.apple });
|
||||
});
|
||||
|
||||
test("enum", () => {
|
||||
const schema = z.object({
|
||||
fruit: z.enum(["apple", "orange"]).catch("apple"),
|
||||
});
|
||||
|
||||
expect(schema.parse({})).toEqual({ fruit: "apple" });
|
||||
expect(schema.parse({ fruit: true })).toEqual({ fruit: "apple" });
|
||||
expect(schema.parse({ fruit: 15 })).toEqual({ fruit: "apple" });
|
||||
});
|
||||
|
||||
test("reported issues with nested usage", () => {
|
||||
const schema = z.object({
|
||||
string: z.string(),
|
||||
obj: z.object({
|
||||
sub: z.object({
|
||||
lit: z.literal("a"),
|
||||
subCatch: z.number().catch(23),
|
||||
}),
|
||||
midCatch: z.number().catch(42),
|
||||
}),
|
||||
number: z.number().catch(0),
|
||||
bool: z.boolean(),
|
||||
});
|
||||
|
||||
try {
|
||||
schema.parse({
|
||||
string: {},
|
||||
obj: {
|
||||
sub: {
|
||||
lit: "b",
|
||||
subCatch: "24",
|
||||
},
|
||||
midCatch: 444,
|
||||
},
|
||||
number: "",
|
||||
bool: "yes",
|
||||
});
|
||||
} catch (error) {
|
||||
const issues = (error as z.ZodError).issues;
|
||||
|
||||
expect(issues.length).toEqual(3);
|
||||
expect(issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received object",
|
||||
"path": [
|
||||
"string",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"message": "Invalid input: expected "a"",
|
||||
"path": [
|
||||
"obj",
|
||||
"sub",
|
||||
"lit",
|
||||
],
|
||||
"values": [
|
||||
"a",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "boolean",
|
||||
"message": "Invalid input: expected boolean, received string",
|
||||
"path": [
|
||||
"bool",
|
||||
],
|
||||
},
|
||||
]
|
||||
`);
|
||||
// expect(issues[0].message).toMatch("string");
|
||||
// expect(issues[1].message).toMatch("literal");
|
||||
// expect(issues[2].message).toMatch("boolean");
|
||||
}
|
||||
});
|
||||
|
||||
test("catch error", () => {
|
||||
const schema = z.object({
|
||||
age: z.number(),
|
||||
name: z.string().catch((ctx) => {
|
||||
ctx.issues;
|
||||
// issues = ctx.issues;
|
||||
|
||||
return "John Doe";
|
||||
}),
|
||||
});
|
||||
|
||||
const result = schema.safeParse({
|
||||
age: null,
|
||||
name: null,
|
||||
});
|
||||
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"age"
|
||||
],
|
||||
"message": "Invalid input: expected number, received null"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("ctx.input", () => {
|
||||
const schema = z.string().catch((ctx) => {
|
||||
return String(ctx.input);
|
||||
});
|
||||
|
||||
expect(schema.parse(123)).toEqual("123");
|
||||
});
|
||||
|
||||
test("direction-aware catch", () => {
|
||||
const schema = z.string().catch("fallback");
|
||||
|
||||
// Forward direction (regular parse): catch should be applied
|
||||
expect(schema.parse(123)).toBe("fallback");
|
||||
|
||||
// Reverse direction (encode): catch should NOT be applied, invalid value should fail validation
|
||||
expect(z.safeEncode(schema, 123 as any)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
// But valid values should still work in reverse
|
||||
expect(z.encode(schema, "world")).toBe("world");
|
||||
});
|
||||
20
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/coalesce.test.ts
generated
vendored
Normal file
20
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/coalesce.test.ts
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
test("coalesce", () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
// test("nonoptional with default", () => {
|
||||
// const schema = z.string().optional().coalesce("hi");
|
||||
// expectTypeOf<typeof schema._input>().toEqualTypeOf<string | undefined>();
|
||||
// expectTypeOf<typeof schema._output>().toEqualTypeOf<string>();
|
||||
// expect(schema.parse(undefined)).toBe("hi");
|
||||
// });
|
||||
|
||||
// test("nonoptional in object", () => {
|
||||
// const schema = z.object({ hi: z.string().optional().nonoptional("hi") });
|
||||
|
||||
// expectTypeOf<typeof schema._input>().toEqualTypeOf<{ hi: string | undefined }>();
|
||||
// expectTypeOf<typeof schema._output>().toEqualTypeOf<{ hi: string }>();
|
||||
// expect(schema.parse(undefined)).toBe("hi");
|
||||
// });
|
||||
573
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/codec-examples.test.ts
generated
vendored
Normal file
573
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/codec-examples.test.ts
generated
vendored
Normal file
@@ -0,0 +1,573 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
// ============================================================================
|
||||
// stringToNumber
|
||||
// ============================================================================
|
||||
|
||||
const stringToNumber = () =>
|
||||
z.codec(z.string(), z.number(), {
|
||||
decode: (str) => Number.parseFloat(str),
|
||||
encode: (num) => num.toString(),
|
||||
});
|
||||
|
||||
test("stringToNumber codec", () => {
|
||||
const codec = stringToNumber();
|
||||
|
||||
// Test decode
|
||||
expect(z.decode(codec, "42.5")).toBe(42.5);
|
||||
expect(z.decode(codec, "0")).toBe(0);
|
||||
expect(z.decode(codec, "-123.456")).toBe(-123.456);
|
||||
|
||||
// Test encode
|
||||
expect(z.encode(codec, 42.5)).toBe("42.5");
|
||||
expect(z.encode(codec, 0)).toBe("0");
|
||||
expect(z.encode(codec, -123.456)).toBe("-123.456");
|
||||
|
||||
// Test round trip
|
||||
const original = "3.14159";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe("3.14159");
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// stringToInt
|
||||
// ============================================================================
|
||||
|
||||
const stringToInt = () =>
|
||||
z.codec(z.string(), z.int(), {
|
||||
decode: (str) => Number.parseInt(str, 10),
|
||||
encode: (num) => num.toString(),
|
||||
});
|
||||
|
||||
test("stringToInt codec", () => {
|
||||
const codec = stringToInt();
|
||||
|
||||
// Test decode
|
||||
expect(z.decode(codec, "42")).toBe(42);
|
||||
expect(z.decode(codec, "0")).toBe(0);
|
||||
expect(z.decode(codec, "-123")).toBe(-123);
|
||||
|
||||
// Test encode
|
||||
expect(z.encode(codec, 42)).toBe("42");
|
||||
expect(z.encode(codec, 0)).toBe("0");
|
||||
expect(z.encode(codec, -123)).toBe("-123");
|
||||
|
||||
// Test round trip
|
||||
const original = "999";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe("999");
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// stringToBigInt
|
||||
// ============================================================================
|
||||
|
||||
const stringToBigInt = () =>
|
||||
z.codec(z.string(), z.bigint(), {
|
||||
decode: (str) => BigInt(str),
|
||||
encode: (bigint) => bigint.toString(),
|
||||
});
|
||||
|
||||
test("stringToBigInt codec", () => {
|
||||
const codec = stringToBigInt();
|
||||
|
||||
// Test decode
|
||||
expect(z.decode(codec, "123456789012345678901234567890")).toBe(123456789012345678901234567890n);
|
||||
expect(z.decode(codec, "0")).toBe(0n);
|
||||
expect(z.decode(codec, "-999")).toBe(-999n);
|
||||
|
||||
// Test encode
|
||||
expect(z.encode(codec, 123456789012345678901234567890n)).toBe("123456789012345678901234567890");
|
||||
expect(z.encode(codec, 0n)).toBe("0");
|
||||
expect(z.encode(codec, -999n)).toBe("-999");
|
||||
|
||||
// Test round trip
|
||||
const original = "987654321098765432109876543210";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe("987654321098765432109876543210");
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// numberToBigInt
|
||||
// ============================================================================
|
||||
|
||||
const numberToBigInt = () =>
|
||||
z.codec(z.int(), z.bigint(), {
|
||||
decode: (num) => BigInt(num),
|
||||
encode: (bigint) => Number(bigint),
|
||||
});
|
||||
|
||||
test("numberToBigInt codec", () => {
|
||||
const codec = numberToBigInt();
|
||||
|
||||
// Test decode
|
||||
expect(z.decode(codec, 42)).toBe(42n);
|
||||
expect(z.decode(codec, 0)).toBe(0n);
|
||||
expect(z.decode(codec, -123)).toBe(-123n);
|
||||
|
||||
// Test encode
|
||||
expect(z.encode(codec, 42n)).toBe(42);
|
||||
expect(z.encode(codec, 0n)).toBe(0);
|
||||
expect(z.encode(codec, -123n)).toBe(-123);
|
||||
|
||||
// Test round trip
|
||||
const original = 999;
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(999);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// isoDatetimeToDate
|
||||
// ============================================================================
|
||||
|
||||
const isoDatetimeToDate = () =>
|
||||
z.codec(z.iso.datetime(), z.date(), {
|
||||
decode: (isoString) => new Date(isoString),
|
||||
encode: (date) => date.toISOString(),
|
||||
});
|
||||
|
||||
test("isoDatetimeToDate codec", () => {
|
||||
const codec = isoDatetimeToDate();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "2024-01-15T10:30:00.000Z");
|
||||
expect(decoded).toBeInstanceOf(Date);
|
||||
expect(decoded.getTime()).toBe(1705314600000);
|
||||
|
||||
// Test encode
|
||||
const date = new Date("2024-01-15T10:30:00.000Z");
|
||||
expect(z.encode(codec, date)).toBe("2024-01-15T10:30:00.000Z");
|
||||
|
||||
// Test round trip
|
||||
const original = "2024-12-25T15:45:30.123Z";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe("2024-12-25T15:45:30.123Z");
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// epochSecondsToDate
|
||||
// ============================================================================
|
||||
|
||||
const epochSecondsToDate = () =>
|
||||
z.codec(z.int().min(0), z.date(), {
|
||||
decode: (seconds) => new Date(seconds * 1000),
|
||||
encode: (date) => Math.floor(date.getTime() / 1000),
|
||||
});
|
||||
|
||||
test("epochSecondsToDate codec", () => {
|
||||
const codec = epochSecondsToDate();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, 1705314600);
|
||||
expect(decoded).toBeInstanceOf(Date);
|
||||
expect(decoded.getTime()).toBe(1705314600000);
|
||||
|
||||
// Test encode
|
||||
const date = new Date(1705314600000);
|
||||
expect(z.encode(codec, date)).toBe(1705314600);
|
||||
|
||||
// Test round trip
|
||||
const original = 1640995200; // 2022-01-01 00:00:00 UTC
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(1640995200);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// epochMillisToDate
|
||||
// ============================================================================
|
||||
|
||||
const epochMillisToDate = () =>
|
||||
z.codec(z.int().min(0), z.date(), {
|
||||
decode: (millis) => new Date(millis),
|
||||
encode: (date) => date.getTime(),
|
||||
});
|
||||
|
||||
test("epochMillisToDate codec", () => {
|
||||
const codec = epochMillisToDate();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, 1705314600000);
|
||||
expect(decoded).toBeInstanceOf(Date);
|
||||
expect(decoded.getTime()).toBe(1705314600000);
|
||||
|
||||
// Test encode
|
||||
const date = new Date(1705314600000);
|
||||
expect(z.encode(codec, date)).toBe(1705314600000);
|
||||
|
||||
// Test round trip
|
||||
const original = 1640995200123; // 2022-01-01 00:00:00.123 UTC
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(1640995200123);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// json
|
||||
// ============================================================================
|
||||
|
||||
const jsonCodec = <T extends z.core.$ZodType>(schema: T) =>
|
||||
z.codec(z.string(), schema, {
|
||||
decode: (jsonString, ctx) => {
|
||||
try {
|
||||
return JSON.parse(jsonString);
|
||||
} catch (err: any) {
|
||||
ctx.issues.push({
|
||||
code: "invalid_format",
|
||||
format: "json",
|
||||
input: jsonString,
|
||||
message: err.message,
|
||||
});
|
||||
return z.NEVER;
|
||||
}
|
||||
},
|
||||
encode: (value) => JSON.stringify(value),
|
||||
});
|
||||
|
||||
test("json codec", () => {
|
||||
const codec = jsonCodec(z.object({ name: z.string(), age: z.number() }));
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, '{"name":"Alice","age":30}');
|
||||
expect(decoded).toEqual({ name: "Alice", age: 30 });
|
||||
|
||||
// Test encode
|
||||
const encoded = z.encode(codec, { name: "Bob", age: 25 });
|
||||
expect(encoded).toBe('{"name":"Bob","age":25}');
|
||||
|
||||
// Test round trip
|
||||
const original = '{"name":"Charlie","age":35}';
|
||||
const parsed = z.decode(codec, original);
|
||||
const roundTrip = z.encode(codec, parsed);
|
||||
expect(JSON.parse(roundTrip)).toEqual(JSON.parse(original));
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// utf8ToBytes
|
||||
// ============================================================================
|
||||
|
||||
const utf8ToBytes = () =>
|
||||
z.codec(z.string(), z.instanceof(Uint8Array), {
|
||||
decode: (str) => new TextEncoder().encode(str),
|
||||
encode: (bytes) => new TextDecoder().decode(bytes),
|
||||
});
|
||||
|
||||
test("utf8ToBytes codec", () => {
|
||||
const codec = utf8ToBytes();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "Hello, 世界!");
|
||||
expect(decoded).toBeInstanceOf(Uint8Array);
|
||||
expect(Array.from(decoded)).toEqual([72, 101, 108, 108, 111, 44, 32, 228, 184, 150, 231, 149, 140, 33]);
|
||||
|
||||
// Test encode
|
||||
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
|
||||
expect(z.encode(codec, bytes)).toBe("Hello");
|
||||
|
||||
// Test round trip
|
||||
const original = "Hello, 世界! 🚀";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(original);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// bytesToUtf8
|
||||
// ============================================================================
|
||||
|
||||
const bytesToUtf8 = () =>
|
||||
z.codec(z.instanceof(Uint8Array), z.string(), {
|
||||
decode: (bytes) => new TextDecoder().decode(bytes),
|
||||
encode: (str) => new TextEncoder().encode(str),
|
||||
});
|
||||
|
||||
test("bytesToUtf8 codec", () => {
|
||||
const codec = bytesToUtf8();
|
||||
|
||||
// Test decode
|
||||
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
|
||||
const decoded = z.decode(codec, bytes);
|
||||
expect(decoded).toBe("Hello");
|
||||
|
||||
// Test encode
|
||||
const encoded = z.encode(codec, "Hello, 世界!");
|
||||
expect(encoded).toBeInstanceOf(Uint8Array);
|
||||
expect(Array.from(encoded)).toEqual([72, 101, 108, 108, 111, 44, 32, 228, 184, 150, 231, 149, 140, 33]);
|
||||
|
||||
// Test round trip
|
||||
const original = new Uint8Array([72, 101, 108, 108, 111, 44, 32, 228, 184, 150, 231, 149, 140, 33]);
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toEqual(original);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// base64
|
||||
// ============================================================================
|
||||
|
||||
const base64 = () =>
|
||||
z.codec(z.base64(), z.instanceof(Uint8Array), {
|
||||
decode: (base64String) => z.util.base64ToUint8Array(base64String),
|
||||
encode: (bytes) => z.util.uint8ArrayToBase64(bytes),
|
||||
});
|
||||
|
||||
test("base64 codec", () => {
|
||||
const codec = base64();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "SGVsbG8=");
|
||||
expect(decoded).toBeInstanceOf(Uint8Array);
|
||||
expect(Array.from(decoded)).toEqual([72, 101, 108, 108, 111]);
|
||||
|
||||
// Test encode
|
||||
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
|
||||
expect(z.encode(codec, bytes)).toBe("SGVsbG8=");
|
||||
|
||||
// Test round trip
|
||||
const original = "SGVsbG8gV29ybGQh";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(original);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// base64urlToBytes
|
||||
// ============================================================================
|
||||
|
||||
const base64urlToBytes = () =>
|
||||
z.codec(z.base64url(), z.instanceof(Uint8Array), {
|
||||
decode: (base64urlString) => z.util.base64urlToUint8Array(base64urlString),
|
||||
encode: (bytes) => z.util.uint8ArrayToBase64url(bytes),
|
||||
});
|
||||
|
||||
test("base64urlToBytes codec", () => {
|
||||
const codec = base64urlToBytes();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "SGVsbG8");
|
||||
expect(decoded).toBeInstanceOf(Uint8Array);
|
||||
expect(Array.from(decoded)).toEqual([72, 101, 108, 108, 111]);
|
||||
|
||||
// Test encode
|
||||
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
|
||||
expect(z.encode(codec, bytes)).toBe("SGVsbG8");
|
||||
|
||||
// Test round trip with padding case
|
||||
const original = "SGVsbG9Xb3JsZA";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(original);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// hexToBytes
|
||||
// ============================================================================
|
||||
|
||||
const hexToBytes = () =>
|
||||
z.codec(z.hex(), z.instanceof(Uint8Array), {
|
||||
decode: (hexString) => z.util.hexToUint8Array(hexString),
|
||||
encode: (bytes) => z.util.uint8ArrayToHex(bytes),
|
||||
});
|
||||
|
||||
test("hexToBytes codec", () => {
|
||||
const codec = hexToBytes();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "48656c6c6f");
|
||||
expect(decoded).toBeInstanceOf(Uint8Array);
|
||||
expect(Array.from(decoded)).toEqual([72, 101, 108, 108, 111]);
|
||||
|
||||
// Note: z.hex() doesn't accept 0x prefix, but our utility function can handle it
|
||||
// const decodedWithPrefix = z.decode(codec, "0x48656c6c6f");
|
||||
// expect(Array.from(decodedWithPrefix)).toEqual([72, 101, 108, 108, 111]);
|
||||
|
||||
// Test encode
|
||||
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
|
||||
expect(z.encode(codec, bytes)).toBe("48656c6c6f");
|
||||
|
||||
// Test round trip
|
||||
const original = "deadbeef";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe("deadbeef");
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// stringToURL
|
||||
// ============================================================================
|
||||
|
||||
const stringToURL = () =>
|
||||
z.codec(z.url(), z.instanceof(URL), {
|
||||
decode: (urlString) => new URL(urlString),
|
||||
encode: (url) => url.href,
|
||||
});
|
||||
|
||||
test("stringToURL codec", () => {
|
||||
const codec = stringToURL();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "https://example.com/path?query=value");
|
||||
expect(decoded).toBeInstanceOf(URL);
|
||||
expect(decoded.hostname).toBe("example.com");
|
||||
expect(decoded.pathname).toBe("/path");
|
||||
expect(decoded.search).toBe("?query=value");
|
||||
|
||||
// Test encode
|
||||
const url = new URL("https://example.com/path?query=value");
|
||||
expect(z.encode(codec, url)).toBe("https://example.com/path?query=value");
|
||||
|
||||
// Test round trip
|
||||
const original = "https://test.com/api/v1?foo=bar&baz=qux";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(original);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// stringToHttpURL
|
||||
// ============================================================================
|
||||
|
||||
const stringToHttpURL = () =>
|
||||
z.codec(z.httpUrl(), z.instanceof(URL), {
|
||||
decode: (urlString) => new URL(urlString),
|
||||
encode: (url) => url.href,
|
||||
});
|
||||
|
||||
test("stringToHttpURL codec", () => {
|
||||
const codec = stringToHttpURL();
|
||||
|
||||
// Test decode HTTPS
|
||||
const decodedHttps = z.decode(codec, "https://example.com/path");
|
||||
expect(decodedHttps).toBeInstanceOf(URL);
|
||||
expect(decodedHttps.protocol).toBe("https:");
|
||||
|
||||
// Test decode HTTP
|
||||
const decodedHttp = z.decode(codec, "http://example.com/path");
|
||||
expect(decodedHttp).toBeInstanceOf(URL);
|
||||
expect(decodedHttp.protocol).toBe("http:");
|
||||
|
||||
// Test encode
|
||||
const url = new URL("https://example.com/path");
|
||||
expect(z.encode(codec, url)).toBe("https://example.com/path");
|
||||
|
||||
// Test round trip
|
||||
const original = "http://api.example.com/v1/users";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe(original);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// uriComponent
|
||||
// ============================================================================
|
||||
|
||||
const uriComponent = () =>
|
||||
z.codec(z.string(), z.string(), {
|
||||
decode: (encodedString) => decodeURIComponent(encodedString),
|
||||
encode: (decodedString) => encodeURIComponent(decodedString),
|
||||
});
|
||||
|
||||
test("uriComponent codec", () => {
|
||||
const codec = uriComponent();
|
||||
|
||||
// Test decode
|
||||
const decoded = z.decode(codec, "Hello%20World%21");
|
||||
expect(decoded).toBe("Hello World!");
|
||||
|
||||
// Test encode
|
||||
const encoded = z.encode(codec, "Hello World!");
|
||||
expect(encoded).toBe("Hello%20World!");
|
||||
|
||||
// Test round trip
|
||||
const original = "Hello%20World%21%20%26%20More";
|
||||
const roundTrip = z.encode(codec, z.decode(codec, original));
|
||||
expect(roundTrip).toBe("Hello%20World!%20%26%20More");
|
||||
|
||||
// Test complex characters
|
||||
const complex = "café & résumé";
|
||||
const encodedComplex = z.encode(codec, complex);
|
||||
const decodedComplex = z.decode(codec, encodedComplex);
|
||||
expect(decodedComplex).toBe(complex);
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// stringToBoolean
|
||||
// ============================================================================
|
||||
|
||||
const stringToBoolean = (options?: { truthy?: string[]; falsy?: string[] }) => z.stringbool(options);
|
||||
|
||||
test("stringToBoolean codec", () => {
|
||||
const codec = stringToBoolean();
|
||||
|
||||
// Test decode - default truthy values
|
||||
expect(z.decode(codec, "true")).toBe(true);
|
||||
expect(z.decode(codec, "yes")).toBe(true);
|
||||
expect(z.decode(codec, "1")).toBe(true);
|
||||
|
||||
// Test decode - default falsy values
|
||||
expect(z.decode(codec, "false")).toBe(false);
|
||||
expect(z.decode(codec, "no")).toBe(false);
|
||||
expect(z.decode(codec, "0")).toBe(false);
|
||||
|
||||
// Test encode - default behavior
|
||||
expect(z.encode(codec, true)).toBe("true");
|
||||
expect(z.encode(codec, false)).toBe("false");
|
||||
|
||||
// Test custom options
|
||||
const customCodec = stringToBoolean({ truthy: ["yes", "y"], falsy: ["no", "n"] });
|
||||
expect(z.decode(customCodec, "yes")).toBe(true);
|
||||
expect(z.decode(customCodec, "y")).toBe(true);
|
||||
expect(z.decode(customCodec, "no")).toBe(false);
|
||||
expect(z.decode(customCodec, "n")).toBe(false);
|
||||
expect(z.encode(customCodec, true)).toBe("yes");
|
||||
expect(z.encode(customCodec, false)).toBe("no");
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// Error Handling Tests
|
||||
// ============================================================================
|
||||
|
||||
// Test error cases - these test input validation, not transform errors
|
||||
test("codec input validation", () => {
|
||||
// Test invalid base64 format
|
||||
const base64Codec = base64();
|
||||
const invalidBase64Result = z.safeDecode(base64Codec, "invalid!@#");
|
||||
expect(invalidBase64Result.success).toBe(false);
|
||||
|
||||
// Test invalid hex format
|
||||
const hexCodec = hexToBytes();
|
||||
const invalidHexResult = z.safeDecode(hexCodec, "gg");
|
||||
expect(invalidHexResult.success).toBe(false);
|
||||
|
||||
// Test invalid URL format
|
||||
const urlCodec = stringToURL();
|
||||
const invalidUrlResult = z.safeDecode(urlCodec, "not a url");
|
||||
expect(invalidUrlResult.success).toBe(false);
|
||||
|
||||
// Test invalid HTTP URL format
|
||||
const httpUrlCodec = stringToHttpURL();
|
||||
const invalidHttpResult = z.safeDecode(httpUrlCodec, "ftp://example.com");
|
||||
expect(invalidHttpResult.success).toBe(false);
|
||||
});
|
||||
|
||||
// Test transform errors - these test errors added by transform functions
|
||||
test("codec transform error handling", () => {
|
||||
// JSON codec that can fail during transform
|
||||
const anyJSON = jsonCodec(z.json());
|
||||
|
||||
// Test successful JSON parsing
|
||||
const validResult = z.safeDecode(anyJSON, '{"valid": "json"}');
|
||||
expect(validResult.success).toBe(true);
|
||||
if (validResult.success) {
|
||||
expect(validResult.data).toEqual({ valid: "json" });
|
||||
}
|
||||
|
||||
// Test invalid JSON that should create a single "invalid_format" issue
|
||||
// Verifies that the transform error aborts before reaching the output schema
|
||||
const invalidResult = z.safeDecode(anyJSON, '{"invalid":,}');
|
||||
expect(invalidResult.success).toBe(false);
|
||||
if (!invalidResult.success) {
|
||||
expect(invalidResult.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "json",
|
||||
"message": "Unexpected token ',', "{"invalid":,}" is not valid JSON",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
562
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/codec.test.ts
generated
vendored
Normal file
562
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/codec.test.ts
generated
vendored
Normal file
@@ -0,0 +1,562 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const isoDateCodec = z.codec(
|
||||
z.iso.datetime(), // Input: ISO string (validates to string)
|
||||
z.date(), // Output: Date object
|
||||
{
|
||||
decode: (isoString) => new Date(isoString), // Forward: ISO string → Date
|
||||
encode: (date) => date.toISOString(), // Backward: Date → ISO string
|
||||
}
|
||||
);
|
||||
|
||||
test("instanceof", () => {
|
||||
expect(isoDateCodec instanceof z.ZodCodec).toBe(true);
|
||||
expect(isoDateCodec instanceof z.ZodPipe).toBe(true);
|
||||
expect(isoDateCodec instanceof z.ZodType).toBe(true);
|
||||
expect(isoDateCodec instanceof z.core.$ZodCodec).toBe(true);
|
||||
expect(isoDateCodec instanceof z.core.$ZodPipe).toBe(true);
|
||||
expect(isoDateCodec instanceof z.core.$ZodType).toBe(true);
|
||||
|
||||
expectTypeOf(isoDateCodec.def).toEqualTypeOf<z.core.$ZodCodecDef<z.ZodISODateTime, z.ZodDate>>();
|
||||
});
|
||||
|
||||
test("codec basic functionality", () => {
|
||||
// ISO string -> Date codec using z.iso.datetime() for input validation
|
||||
|
||||
const testIsoString = "2024-01-15T10:30:00.000Z";
|
||||
const testDate = new Date("2024-01-15T10:30:00.000Z");
|
||||
|
||||
// Forward decoding (ISO string -> Date)
|
||||
const decodedResult = z.decode(isoDateCodec, testIsoString);
|
||||
expect(decodedResult).toBeInstanceOf(Date);
|
||||
expect(decodedResult.toISOString()).toMatchInlineSnapshot(`"2024-01-15T10:30:00.000Z"`);
|
||||
|
||||
// Backward encoding (Date -> ISO string)
|
||||
const encodedResult = z.encode(isoDateCodec, testDate);
|
||||
expect(typeof encodedResult).toBe("string");
|
||||
expect(encodedResult).toMatchInlineSnapshot(`"2024-01-15T10:30:00.000Z"`);
|
||||
});
|
||||
|
||||
test("codec round trip", () => {
|
||||
const isoDateCodec = z.codec(z.iso.datetime(), z.date(), {
|
||||
decode: (isoString) => new Date(isoString),
|
||||
encode: (date) => date.toISOString(),
|
||||
});
|
||||
|
||||
const original = "2024-12-25T15:45:30.123Z";
|
||||
const toDate = z.decode(isoDateCodec, original);
|
||||
const backToString = z.encode(isoDateCodec, toDate);
|
||||
|
||||
expect(backToString).toMatchInlineSnapshot(`"2024-12-25T15:45:30.123Z"`);
|
||||
expect(toDate).toBeInstanceOf(Date);
|
||||
expect(toDate.getTime()).toMatchInlineSnapshot(`1735141530123`);
|
||||
});
|
||||
|
||||
test("codec with refinement", () => {
|
||||
const isoDateCodec = z
|
||||
.codec(z.iso.datetime(), z.date(), {
|
||||
decode: (isoString) => new Date(isoString),
|
||||
encode: (date) => date.toISOString(),
|
||||
})
|
||||
.refine((val) => val.getFullYear() === 2024, { error: "Year must be 2024" });
|
||||
|
||||
// Valid 2024 date
|
||||
const validDate = z.decode(isoDateCodec, "2024-01-15T10:30:00.000Z");
|
||||
expect(validDate.getFullYear()).toMatchInlineSnapshot(`2024`);
|
||||
expect(validDate.getTime()).toMatchInlineSnapshot(`1705314600000`);
|
||||
|
||||
// Invalid year should fail safely
|
||||
const invalidYearResult = z.safeDecode(isoDateCodec, "2023-01-15T10:30:00.000Z");
|
||||
expect(invalidYearResult.success).toBe(false);
|
||||
if (!invalidYearResult.success) {
|
||||
expect(invalidYearResult.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Year must be 2024",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("safe codec operations", () => {
|
||||
const isoDateCodec = z.codec(z.iso.datetime(), z.date(), {
|
||||
decode: (isoString) => new Date(isoString),
|
||||
encode: (date) => date.toISOString(),
|
||||
});
|
||||
|
||||
// Safe decode with invalid input
|
||||
const safeDecodeResult = z.safeDecode(isoDateCodec, "invalid-date");
|
||||
expect(safeDecodeResult.success).toBe(false);
|
||||
if (!safeDecodeResult.success) {
|
||||
expect(safeDecodeResult.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "datetime",
|
||||
"message": "Invalid ISO datetime",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$/",
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
|
||||
// Safe decode with valid input
|
||||
const safeDecodeValid = z.safeDecode(isoDateCodec, "2024-01-15T10:30:00.000Z");
|
||||
expect(safeDecodeValid.success).toBe(true);
|
||||
if (safeDecodeValid.success) {
|
||||
expect(safeDecodeValid.data).toBeInstanceOf(Date);
|
||||
expect(safeDecodeValid.data.getTime()).toMatchInlineSnapshot(`1705314600000`);
|
||||
}
|
||||
|
||||
// Safe encode with valid input
|
||||
const safeEncodeResult = z.safeEncode(isoDateCodec, new Date("2024-01-01"));
|
||||
expect(safeEncodeResult.success).toBe(true);
|
||||
if (safeEncodeResult.success) {
|
||||
expect(safeEncodeResult.data).toMatchInlineSnapshot(`"2024-01-01T00:00:00.000Z"`);
|
||||
}
|
||||
});
|
||||
|
||||
test("codec with different types", () => {
|
||||
// String -> Number codec
|
||||
const stringNumberCodec = z.codec(z.string(), z.number(), {
|
||||
decode: (str) => Number.parseFloat(str),
|
||||
encode: (num) => num.toString(),
|
||||
});
|
||||
|
||||
const decodedNumber = z.decode(stringNumberCodec, "42.5");
|
||||
expect(decodedNumber).toMatchInlineSnapshot(`42.5`);
|
||||
expect(typeof decodedNumber).toBe("number");
|
||||
|
||||
const encodedString = z.encode(stringNumberCodec, 42.5);
|
||||
expect(encodedString).toMatchInlineSnapshot(`"42.5"`);
|
||||
expect(typeof encodedString).toBe("string");
|
||||
});
|
||||
|
||||
test("async codec operations", async () => {
|
||||
const isoDateCodec = z.codec(z.iso.datetime(), z.date(), {
|
||||
decode: (isoString) => new Date(isoString),
|
||||
encode: (date) => date.toISOString(),
|
||||
});
|
||||
|
||||
// Async decode
|
||||
const decodedResult = await z.decodeAsync(isoDateCodec, "2024-01-15T10:30:00.000Z");
|
||||
expect(decodedResult).toBeInstanceOf(Date);
|
||||
expect(decodedResult.getTime()).toMatchInlineSnapshot(`1705314600000`);
|
||||
|
||||
// Async encode
|
||||
const encodedResult = await z.encodeAsync(isoDateCodec, new Date("2024-01-15T10:30:00.000Z"));
|
||||
expect(typeof encodedResult).toBe("string");
|
||||
expect(encodedResult).toMatchInlineSnapshot(`"2024-01-15T10:30:00.000Z"`);
|
||||
|
||||
// Safe async operations
|
||||
const safeDecodeResult = await z.safeDecodeAsync(isoDateCodec, "2024-01-15T10:30:00.000Z");
|
||||
expect(safeDecodeResult.success).toBe(true);
|
||||
if (safeDecodeResult.success) {
|
||||
expect(safeDecodeResult.data.getTime()).toMatchInlineSnapshot(`1705314600000`);
|
||||
}
|
||||
|
||||
const safeEncodeResult = await z.safeEncodeAsync(isoDateCodec, new Date("2024-01-15T10:30:00.000Z"));
|
||||
expect(safeEncodeResult.success).toBe(true);
|
||||
if (safeEncodeResult.success) {
|
||||
expect(safeEncodeResult.data).toMatchInlineSnapshot(`"2024-01-15T10:30:00.000Z"`);
|
||||
}
|
||||
});
|
||||
|
||||
test("codec type inference", () => {
|
||||
const codec = z.codec(z.string(), z.number(), {
|
||||
decode: (str) => Number.parseInt(str),
|
||||
encode: (num) => num.toString(),
|
||||
});
|
||||
|
||||
// These should compile without type errors
|
||||
const decoded: number = z.decode(codec, "123");
|
||||
const encoded: string = z.encode(codec, 123);
|
||||
|
||||
expect(decoded).toMatchInlineSnapshot(`123`);
|
||||
expect(encoded).toMatchInlineSnapshot(`"123"`);
|
||||
});
|
||||
|
||||
test("nested codec with object containing codec property", () => {
|
||||
// Nested schema: object containing a codec as one of its properties, with refinements at all levels
|
||||
const waypointSchema = z
|
||||
.object({
|
||||
name: z.string().min(1, "Waypoint name required"),
|
||||
difficulty: z.enum(["easy", "medium", "hard"]),
|
||||
coordinate: z
|
||||
.codec(
|
||||
z
|
||||
.string()
|
||||
.regex(/^-?\d+,-?\d+$/, "Must be 'x,y' format"), // Input: coordinate string
|
||||
z
|
||||
.object({ x: z.number(), y: z.number() })
|
||||
.refine((coord) => coord.x >= 0 && coord.y >= 0, { error: "Coordinates must be non-negative" }), // Output: coordinate object
|
||||
{
|
||||
decode: (coordString: string) => {
|
||||
const [x, y] = coordString.split(",").map(Number);
|
||||
return { x, y };
|
||||
},
|
||||
encode: (coord: { x: number; y: number }) => `${coord.x},${coord.y}`,
|
||||
}
|
||||
)
|
||||
.refine((coord) => coord.x <= 1000 && coord.y <= 1000, { error: "Coordinates must be within bounds" }),
|
||||
})
|
||||
.refine((waypoint) => waypoint.difficulty !== "hard" || waypoint.coordinate.x >= 100, {
|
||||
error: "Hard waypoints must be at least 100 units from origin",
|
||||
});
|
||||
|
||||
// Test data
|
||||
const inputWaypoint = {
|
||||
name: "Summit Point",
|
||||
difficulty: "medium" as const,
|
||||
coordinate: "150,200",
|
||||
};
|
||||
|
||||
// Forward decoding (object with string coordinate -> object with coordinate object)
|
||||
const decodedWaypoint = z.decode(waypointSchema, inputWaypoint);
|
||||
expect(decodedWaypoint).toMatchInlineSnapshot(`
|
||||
{
|
||||
"coordinate": {
|
||||
"x": 150,
|
||||
"y": 200,
|
||||
},
|
||||
"difficulty": "medium",
|
||||
"name": "Summit Point",
|
||||
}
|
||||
`);
|
||||
|
||||
// Backward encoding (object with coordinate object -> object with string coordinate)
|
||||
const encodedWaypoint = z.encode(waypointSchema, decodedWaypoint);
|
||||
expect(encodedWaypoint).toMatchInlineSnapshot(`
|
||||
{
|
||||
"coordinate": "150,200",
|
||||
"difficulty": "medium",
|
||||
"name": "Summit Point",
|
||||
}
|
||||
`);
|
||||
|
||||
// Test refinements at all levels
|
||||
// String validation (empty waypoint name)
|
||||
const emptyNameResult = z.safeDecode(waypointSchema, {
|
||||
name: "",
|
||||
difficulty: "easy",
|
||||
coordinate: "10,20",
|
||||
});
|
||||
expect(emptyNameResult.success).toBe(false);
|
||||
if (!emptyNameResult.success) {
|
||||
expect(emptyNameResult.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Waypoint name required",
|
||||
"minimum": 1,
|
||||
"origin": "string",
|
||||
"path": [
|
||||
"name",
|
||||
],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
|
||||
// Enum validation (invalid difficulty)
|
||||
const invalidDifficultyResult = z.safeDecode(waypointSchema, {
|
||||
name: "Test Point",
|
||||
difficulty: "impossible" as any,
|
||||
coordinate: "10,20",
|
||||
});
|
||||
expect(invalidDifficultyResult.success).toBe(false);
|
||||
if (!invalidDifficultyResult.success) {
|
||||
expect(invalidDifficultyResult.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"message": "Invalid option: expected one of "easy"|"medium"|"hard"",
|
||||
"path": [
|
||||
"difficulty",
|
||||
],
|
||||
"values": [
|
||||
"easy",
|
||||
"medium",
|
||||
"hard",
|
||||
],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
|
||||
// Codec string format validation (invalid coordinate format)
|
||||
const invalidFormatResult = z.safeDecode(waypointSchema, {
|
||||
name: "Test Point",
|
||||
difficulty: "easy",
|
||||
coordinate: "invalid",
|
||||
});
|
||||
expect(invalidFormatResult.success).toBe(false);
|
||||
if (!invalidFormatResult.success) {
|
||||
expect(invalidFormatResult.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "regex",
|
||||
"message": "Must be 'x,y' format",
|
||||
"origin": "string",
|
||||
"path": [
|
||||
"coordinate",
|
||||
],
|
||||
"pattern": "/^-?\\d+,-?\\d+$/",
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
|
||||
// Codec object refinement (negative coordinates)
|
||||
const negativeCoordResult = z.safeDecode(waypointSchema, {
|
||||
name: "Test Point",
|
||||
difficulty: "easy",
|
||||
coordinate: "-5,10",
|
||||
});
|
||||
expect(negativeCoordResult.success).toBe(false);
|
||||
if (!negativeCoordResult.success) {
|
||||
expect(negativeCoordResult.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Coordinates must be non-negative",
|
||||
"path": [
|
||||
"coordinate",
|
||||
],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
|
||||
// Codec-level refinement (coordinates out of bounds)
|
||||
const outOfBoundsResult = z.safeDecode(waypointSchema, {
|
||||
name: "Test Point",
|
||||
difficulty: "easy",
|
||||
coordinate: "1500,2000",
|
||||
});
|
||||
expect(outOfBoundsResult.success).toBe(false);
|
||||
if (!outOfBoundsResult.success) {
|
||||
expect(outOfBoundsResult.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Coordinates must be within bounds",
|
||||
"path": [
|
||||
"coordinate",
|
||||
],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
|
||||
// Object-level refinement (hard waypoint too close to origin)
|
||||
const hardWaypointResult = z.safeDecode(waypointSchema, {
|
||||
name: "Expert Point",
|
||||
difficulty: "hard",
|
||||
coordinate: "50,60", // x < 100, but hard waypoints need x >= 100
|
||||
});
|
||||
expect(hardWaypointResult.success).toBe(false);
|
||||
if (!hardWaypointResult.success) {
|
||||
expect(hardWaypointResult.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Hard waypoints must be at least 100 units from origin",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
|
||||
// Round trip test
|
||||
const roundTripResult = z.encode(waypointSchema, z.decode(waypointSchema, inputWaypoint));
|
||||
expect(roundTripResult).toMatchInlineSnapshot(`
|
||||
{
|
||||
"coordinate": "150,200",
|
||||
"difficulty": "medium",
|
||||
"name": "Summit Point",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("mutating refinements", () => {
|
||||
const A = z.codec(z.string(), z.string().trim(), {
|
||||
decode: (val) => val,
|
||||
encode: (val) => val,
|
||||
});
|
||||
|
||||
expect(z.decode(A, " asdf ")).toMatchInlineSnapshot(`"asdf"`);
|
||||
expect(z.encode(A, " asdf ")).toMatchInlineSnapshot(`"asdf"`);
|
||||
|
||||
const B = z
|
||||
.codec(z.string(), z.string(), {
|
||||
decode: (val) => val,
|
||||
encode: (val) => val,
|
||||
})
|
||||
.check(z.trim(), z.maxLength(4));
|
||||
|
||||
expect(z.decode(B, " asdf ")).toMatchInlineSnapshot(`"asdf"`);
|
||||
expect(z.encode(B, " asdf ")).toMatchInlineSnapshot(`"asdf"`);
|
||||
});
|
||||
|
||||
test("codec type enforcement - correct encode/decode signatures", () => {
|
||||
// Test that codec functions have correct type signatures
|
||||
const stringToNumberCodec = z.codec(z.string(), z.number(), {
|
||||
decode: (value: string) => Number(value), // core.output<A> -> core.input<B>
|
||||
encode: (value: number) => String(value), // core.input<B> -> core.output<A>
|
||||
});
|
||||
|
||||
// These should compile without errors - correct types (async support)
|
||||
expectTypeOf<(value: string, payload: z.core.ParsePayload<string>) => z.core.util.MaybeAsync<number>>(
|
||||
stringToNumberCodec.def.transform
|
||||
).toBeFunction();
|
||||
expectTypeOf<(value: number, payload: z.core.ParsePayload<number>) => z.core.util.MaybeAsync<string>>(
|
||||
stringToNumberCodec.def.reverseTransform
|
||||
).toBeFunction();
|
||||
|
||||
// Test that decode parameter type is core.output<A> (string)
|
||||
const validDecode = (value: string) => Number(value);
|
||||
expectTypeOf(validDecode).toMatchTypeOf<(value: string) => number>();
|
||||
|
||||
// Test that encode parameter type is core.input<B> (number)
|
||||
const validEncode = (value: number) => String(value);
|
||||
expectTypeOf(validEncode).toMatchTypeOf<(value: number) => string>();
|
||||
|
||||
z.codec(z.string(), z.number(), {
|
||||
// @ts-expect-error - decode should NOT accept core.input<A> as parameter
|
||||
decode: (value: never, _payload) => Number(value), // Wrong: should be string, not unknown
|
||||
encode: (value: number, _payload) => String(value),
|
||||
});
|
||||
|
||||
z.codec(z.string(), z.number(), {
|
||||
decode: (value: string) => Number(value),
|
||||
// @ts-expect-error - encode should NOT accept core.output<B> as parameter
|
||||
encode: (value: never) => String(value), // Wrong: should be number, not unknown
|
||||
});
|
||||
|
||||
z.codec(z.string(), z.number(), {
|
||||
// @ts-expect-error - decode return type should be core.input<B>
|
||||
decode: (value: string) => String(value), // Wrong: should return number, not string
|
||||
encode: (value: number) => String(value),
|
||||
});
|
||||
|
||||
z.codec(z.string(), z.number(), {
|
||||
decode: (value: string) => Number(value),
|
||||
// @ts-expect-error - encode return type should be core.output<A>
|
||||
encode: (value: number) => Number(value), // Wrong: should return string, not number
|
||||
});
|
||||
});
|
||||
|
||||
test("codec type enforcement - complex types", () => {
|
||||
type User = { id: number; name: string };
|
||||
type UserInput = { id: string; name: string };
|
||||
|
||||
const userCodec = z.codec(
|
||||
z.object({ id: z.string(), name: z.string() }),
|
||||
z.object({ id: z.number(), name: z.string() }),
|
||||
{
|
||||
decode: (input: UserInput) => ({ id: Number(input.id), name: input.name }),
|
||||
encode: (user: User) => ({ id: String(user.id), name: user.name }),
|
||||
}
|
||||
);
|
||||
|
||||
// Verify correct types are inferred (async support)
|
||||
expectTypeOf<(input: UserInput, payload: z.core.ParsePayload<UserInput>) => z.core.util.MaybeAsync<User>>(
|
||||
userCodec.def.transform
|
||||
).toBeFunction();
|
||||
expectTypeOf<(user: User, payload: z.core.ParsePayload<User>) => z.core.util.MaybeAsync<UserInput>>(
|
||||
userCodec.def.reverseTransform
|
||||
).toBeFunction();
|
||||
|
||||
z.codec(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
}),
|
||||
z.object({ id: z.number(), name: z.string() }),
|
||||
{
|
||||
// @ts-expect-error - decode parameter should be UserInput, not User
|
||||
decode: (input: User) => ({ id: Number(input.id), name: input.name }), // Wrong type
|
||||
encode: (user: User) => ({ id: String(user.id), name: user.name }),
|
||||
}
|
||||
);
|
||||
|
||||
z.codec(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
}),
|
||||
z.object({ id: z.number(), name: z.string() }),
|
||||
{
|
||||
decode: (input: UserInput) => ({ id: Number(input.id), name: input.name }),
|
||||
// @ts-expect-error - encode parameter should be User, not UserInput
|
||||
encode: (user: UserInput) => ({ id: String(user.id), name: user.name }), // Wrong type
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("codec with overwrites", () => {
|
||||
const stringPlusA = z.string().overwrite((val) => val + "a");
|
||||
const A = z
|
||||
.codec(stringPlusA, stringPlusA, {
|
||||
decode: (val) => val,
|
||||
encode: (val) => val,
|
||||
})
|
||||
.overwrite((val) => val + "a");
|
||||
|
||||
expect(z.decode(A, "")).toEqual("aaa");
|
||||
expect(z.encode(A, "")).toEqual("aaa");
|
||||
|
||||
// @ts-expect-error
|
||||
expect(z.safeEncode(A, Symbol("a"))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received symbol"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("async codec functionality", async () => {
|
||||
// Test that async encode/decode functions work properly
|
||||
const asyncCodec = z.codec(z.string(), z.number(), {
|
||||
decode: async (str) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1)); // Simulate async work
|
||||
return Number.parseFloat(str);
|
||||
},
|
||||
encode: async (num) => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1)); // Simulate async work
|
||||
return num.toString();
|
||||
},
|
||||
});
|
||||
|
||||
// Test async decode/encode
|
||||
const decoded = await z.decodeAsync(asyncCodec, "42.5");
|
||||
expect(decoded).toBe(42.5);
|
||||
|
||||
const encoded = await z.encodeAsync(asyncCodec, 42.5);
|
||||
expect(encoded).toBe("42.5");
|
||||
|
||||
// Test that both sync and async work
|
||||
const mixedCodec = z.codec(z.string(), z.number(), {
|
||||
decode: async (str) => Number.parseFloat(str),
|
||||
encode: (num) => num.toString(), // sync encode
|
||||
});
|
||||
|
||||
const mixedResult = await z.decodeAsync(mixedCodec, "123");
|
||||
expect(mixedResult).toBe(123);
|
||||
});
|
||||
160
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/coerce.test.ts
generated
vendored
Normal file
160
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/coerce.test.ts
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("string coercion", () => {
|
||||
const schema = z.coerce.string();
|
||||
expect(schema.parse("sup")).toEqual("sup");
|
||||
expect(schema.parse("")).toEqual("");
|
||||
expect(schema.parse(12)).toEqual("12");
|
||||
expect(schema.parse(0)).toEqual("0");
|
||||
expect(schema.parse(-12)).toEqual("-12");
|
||||
expect(schema.parse(3.14)).toEqual("3.14");
|
||||
expect(schema.parse(BigInt(15))).toEqual("15");
|
||||
expect(schema.parse(Number.NaN)).toEqual("NaN");
|
||||
expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual("Infinity");
|
||||
expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual("-Infinity");
|
||||
expect(schema.parse(true)).toEqual("true");
|
||||
expect(schema.parse(false)).toEqual("false");
|
||||
expect(schema.parse(null)).toEqual("null");
|
||||
expect(schema.parse(undefined)).toEqual("undefined");
|
||||
expect(schema.parse({ hello: "world!" })).toEqual("[object Object]");
|
||||
expect(schema.parse(["item", "another_item"])).toEqual("item,another_item");
|
||||
expect(schema.parse([])).toEqual("");
|
||||
expect(schema.parse(new Date("2022-01-01T00:00:00.000Z"))).toEqual(new Date("2022-01-01T00:00:00.000Z").toString());
|
||||
});
|
||||
|
||||
test("number coercion", () => {
|
||||
const schema = z.coerce.number();
|
||||
expect(schema.parse("12")).toEqual(12);
|
||||
expect(schema.parse("0")).toEqual(0);
|
||||
expect(schema.parse("-12")).toEqual(-12);
|
||||
expect(schema.parse("3.14")).toEqual(3.14);
|
||||
expect(schema.parse("")).toEqual(0);
|
||||
expect(() => schema.parse("NOT_A_NUMBER")).toThrow(); // z.ZodError
|
||||
expect(schema.parse(12)).toEqual(12);
|
||||
expect(schema.parse(0)).toEqual(0);
|
||||
expect(schema.parse(-12)).toEqual(-12);
|
||||
expect(schema.parse(3.14)).toEqual(3.14);
|
||||
expect(schema.parse(BigInt(15))).toEqual(15);
|
||||
expect(() => schema.parse(Number.NaN)).toThrow(); // z.ZodError
|
||||
// expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual(Number.POSITIVE_INFINITY);
|
||||
// expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual(Number.NEGATIVE_INFINITY);
|
||||
expect(schema.parse(true)).toEqual(1);
|
||||
expect(schema.parse(false)).toEqual(0);
|
||||
expect(schema.parse(null)).toEqual(0);
|
||||
expect(() => schema.parse(undefined)).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse({ hello: "world!" })).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse(["item", "another_item"])).toThrow(); // z.ZodError
|
||||
expect(schema.parse([])).toEqual(0);
|
||||
expect(schema.parse(new Date(1670139203496))).toEqual(1670139203496);
|
||||
});
|
||||
|
||||
test("boolean coercion", () => {
|
||||
const schema = z.coerce.boolean();
|
||||
expect(schema.parse("true")).toEqual(true);
|
||||
expect(schema.parse("false")).toEqual(true);
|
||||
expect(schema.parse("0")).toEqual(true);
|
||||
expect(schema.parse("1")).toEqual(true);
|
||||
expect(schema.parse("")).toEqual(false);
|
||||
expect(schema.parse(1)).toEqual(true);
|
||||
expect(schema.parse(0)).toEqual(false);
|
||||
expect(schema.parse(-1)).toEqual(true);
|
||||
expect(schema.parse(3.14)).toEqual(true);
|
||||
expect(schema.parse(BigInt(15))).toEqual(true);
|
||||
expect(schema.parse(Number.NaN)).toEqual(false);
|
||||
expect(schema.parse(Number.POSITIVE_INFINITY)).toEqual(true);
|
||||
expect(schema.parse(Number.NEGATIVE_INFINITY)).toEqual(true);
|
||||
expect(schema.parse(true)).toEqual(true);
|
||||
expect(schema.parse(false)).toEqual(false);
|
||||
expect(schema.parse(null)).toEqual(false);
|
||||
expect(schema.parse(undefined)).toEqual(false);
|
||||
expect(schema.parse({ hello: "world!" })).toEqual(true);
|
||||
expect(schema.parse(["item", "another_item"])).toEqual(true);
|
||||
expect(schema.parse([])).toEqual(true);
|
||||
expect(schema.parse(new Date(1670139203496))).toEqual(true);
|
||||
});
|
||||
|
||||
test("bigint coercion", () => {
|
||||
const schema = z.coerce.bigint();
|
||||
expect(schema.parse("5")).toEqual(BigInt(5));
|
||||
expect(schema.parse("0")).toEqual(BigInt(0));
|
||||
expect(schema.parse("-5")).toEqual(BigInt(-5));
|
||||
expect(() => schema.parse("3.14")).toThrow(); // not a z.ZodError!
|
||||
expect(schema.parse("")).toEqual(BigInt(0));
|
||||
expect(() => schema.parse("NOT_A_NUMBER")).toThrow(); // not a z.ZodError!
|
||||
expect(schema.parse(5)).toEqual(BigInt(5));
|
||||
expect(schema.parse(0)).toEqual(BigInt(0));
|
||||
expect(schema.parse(-5)).toEqual(BigInt(-5));
|
||||
expect(() => schema.parse(3.14)).toThrow(); // not a z.ZodError!
|
||||
expect(schema.parse(BigInt(5))).toEqual(BigInt(5));
|
||||
expect(() => schema.parse(Number.NaN)).toThrow(); // not a z.ZodError!
|
||||
expect(() => schema.parse(Number.POSITIVE_INFINITY)).toThrow(); // not a z.ZodError!
|
||||
expect(() => schema.parse(Number.NEGATIVE_INFINITY)).toThrow(); // not a z.ZodError!
|
||||
expect(schema.parse(true)).toEqual(BigInt(1));
|
||||
expect(schema.parse(false)).toEqual(BigInt(0));
|
||||
expect(() => schema.parse(null)).toThrow(); // not a z.ZodError!
|
||||
expect(() => schema.parse(undefined)).toThrow(); // not a z.ZodError!
|
||||
expect(() => schema.parse({ hello: "world!" })).toThrow(); // not a z.ZodError!
|
||||
expect(() => schema.parse(["item", "another_item"])).toThrow(); // not a z.ZodError!
|
||||
expect(schema.parse([])).toEqual(BigInt(0));
|
||||
expect(schema.parse(new Date(1670139203496))).toEqual(BigInt(1670139203496));
|
||||
});
|
||||
|
||||
test("date coercion", () => {
|
||||
const schema = z.coerce.date();
|
||||
expect(schema.parse(new Date().toDateString())).toBeInstanceOf(Date);
|
||||
expect(schema.parse(new Date().toISOString())).toBeInstanceOf(Date);
|
||||
expect(schema.parse(new Date().toUTCString())).toBeInstanceOf(Date);
|
||||
expect(schema.parse("5")).toBeInstanceOf(Date);
|
||||
expect(schema.parse("2000-01-01")).toBeInstanceOf(Date);
|
||||
// expect(schema.parse("0")).toBeInstanceOf(Date);
|
||||
// expect(schema.parse("-5")).toBeInstanceOf(Date);
|
||||
// expect(schema.parse("3.14")).toBeInstanceOf(Date);
|
||||
expect(() => schema.parse("")).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse("NOT_A_DATE")).toThrow(); // z.ZodError
|
||||
expect(schema.parse(5)).toBeInstanceOf(Date);
|
||||
expect(schema.parse(0)).toBeInstanceOf(Date);
|
||||
expect(schema.parse(-5)).toBeInstanceOf(Date);
|
||||
expect(schema.parse(3.14)).toBeInstanceOf(Date);
|
||||
expect(() => schema.parse(BigInt(5))).toThrow(); // not a z.ZodError!
|
||||
expect(() => schema.parse(Number.NaN)).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse(Number.POSITIVE_INFINITY)).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse(Number.NEGATIVE_INFINITY)).toThrow(); // z.ZodError
|
||||
expect(schema.parse(true)).toBeInstanceOf(Date);
|
||||
expect(schema.parse(false)).toBeInstanceOf(Date);
|
||||
expect(schema.parse(null)).toBeInstanceOf(Date);
|
||||
expect(() => schema.parse(undefined)).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse({ hello: "world!" })).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse(["item", "another_item"])).toThrow(); // z.ZodError
|
||||
expect(() => schema.parse([])).toThrow(); // z.ZodError
|
||||
expect(schema.parse(new Date())).toBeInstanceOf(Date);
|
||||
});
|
||||
|
||||
// test("template literal coercion", () => {
|
||||
// const schema = z.coerce
|
||||
// .templateLiteral()
|
||||
// .interpolated(z.number().finite())
|
||||
// .interpolated(
|
||||
// z.enum(["px", "em", "rem", "vh", "vw", "vmin", "vmax"]).optional()
|
||||
// );
|
||||
// expect(schema.parse(300)).toEqual("300");
|
||||
// expect(schema.parse(BigInt(300))).toEqual("300");
|
||||
// expect(schema.parse("300")).toEqual("300");
|
||||
// expect(schema.parse("300px")).toEqual("300px");
|
||||
// expect(schema.parse("300em")).toEqual("300em");
|
||||
// expect(schema.parse("300rem")).toEqual("300rem");
|
||||
// expect(schema.parse("300vh")).toEqual("300vh");
|
||||
// expect(schema.parse("300vw")).toEqual("300vw");
|
||||
// expect(schema.parse("300vmin")).toEqual("300vmin");
|
||||
// expect(schema.parse("300vmax")).toEqual("300vmax");
|
||||
// expect(schema.parse(["300px"])).toEqual("300px");
|
||||
// });
|
||||
|
||||
test("override input type", () => {
|
||||
const a = z.coerce.string<any>();
|
||||
type input = z.input<typeof a>;
|
||||
expectTypeOf<input>().toEqualTypeOf<any>();
|
||||
type output = z.infer<typeof a>;
|
||||
expectTypeOf<output>().toEqualTypeOf<string>();
|
||||
});
|
||||
374
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/continuability.test.ts
generated
vendored
Normal file
374
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/continuability.test.ts
generated
vendored
Normal file
@@ -0,0 +1,374 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("continuability", () => {
|
||||
/**
|
||||
* | $ZodGUID
|
||||
| $ZodUUID
|
||||
| $ZodEmail
|
||||
| $ZodURL
|
||||
| $ZodEmoji
|
||||
| $ZodNanoID
|
||||
| $ZodCUID
|
||||
| $ZodCUID2
|
||||
| $ZodULID
|
||||
| $ZodXID
|
||||
| $ZodKSUID
|
||||
| $ZodISODateTime
|
||||
| $ZodISODate
|
||||
| $ZodISOTime
|
||||
| $ZodISODuration
|
||||
| $ZodIPv4
|
||||
| $ZodIPv6
|
||||
| $ZodCIDRv4
|
||||
| $ZodCIDRv6
|
||||
| $ZodBase64
|
||||
| $ZodBase64URL
|
||||
| $ZodE164
|
||||
| $ZodJWT;
|
||||
*/
|
||||
expect(
|
||||
z
|
||||
.email()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "email",
|
||||
"message": "Invalid email address",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.uuid()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "uuid",
|
||||
"message": "Invalid UUID",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.url()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "url",
|
||||
"message": "Invalid URL",
|
||||
"path": [],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.jwt()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "jwt",
|
||||
"message": "Invalid JWT",
|
||||
"path": [],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.cidrv4()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "cidrv4",
|
||||
"message": "Invalid IPv4 range",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\/([0-9]|[1-2][0-9]|3[0-2])$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.cidrv6()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "cidrv6",
|
||||
"message": "Invalid IPv6 range",
|
||||
"path": [],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.ipv4()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "ipv4",
|
||||
"message": "Invalid IPv4 address",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.ipv6()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "ipv6",
|
||||
"message": "Invalid IPv6 address",
|
||||
"path": [],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.mac()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "mac",
|
||||
"message": "Invalid MAC address",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^(?:[0-9A-F]{2}:){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}:){5}[0-9a-f]{2}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.emoji()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "emoji",
|
||||
"message": "Invalid emoji",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$/u",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.nanoid()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "nanoid",
|
||||
"message": "Invalid nanoid",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^[a-zA-Z0-9_-]{21}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.cuid()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "cuid",
|
||||
"message": "Invalid cuid",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^[cC][^\\s-]{8,}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.cuid2()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "cuid2",
|
||||
"message": "Invalid cuid2",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^[0-9a-z]+$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.ulid()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "ulid",
|
||||
"message": "Invalid ULID",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.xid()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "xid",
|
||||
"message": "Invalid XID",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^[0-9a-vA-V]{20}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(
|
||||
z
|
||||
.ksuid()
|
||||
.refine(() => false)
|
||||
.safeParse("invalid_value").error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "ksuid",
|
||||
"message": "Invalid KSUID",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
"pattern": "/^[A-Za-z0-9]{27}$/",
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
40
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/custom.test.ts
generated
vendored
Normal file
40
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/custom.test.ts
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("passing validations", () => {
|
||||
const example1 = z.custom<number>((x) => typeof x === "number");
|
||||
example1.parse(1234);
|
||||
expect(() => example1.parse({})).toThrow();
|
||||
});
|
||||
|
||||
test("string params", () => {
|
||||
const example1 = z.custom<number>((x) => typeof x !== "number", "customerr");
|
||||
const result = example1.safeParse(1234);
|
||||
expect(result.success).toEqual(false);
|
||||
expect(JSON.stringify(result.error).includes("customerr")).toEqual(true);
|
||||
});
|
||||
|
||||
test("instanceof", () => {
|
||||
const fn = (value: string) => Uint8Array.from(Buffer.from(value, "base64"));
|
||||
|
||||
// Argument of type 'ZodCustom<Uint8Array<ArrayBuffer>, unknown>' is not assignable to parameter of type '$ZodType<any, Uint8Array<ArrayBuffer>>'.
|
||||
z.string().transform(fn).pipe(z.instanceof(Uint8Array));
|
||||
});
|
||||
|
||||
test("non-continuable by default", () => {
|
||||
const A = z
|
||||
.custom<string>((val) => typeof val === "string")
|
||||
.transform((_) => {
|
||||
throw new Error("Invalid input");
|
||||
});
|
||||
expect(A.safeParse(123).error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
62
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/date.test.ts
generated
vendored
Normal file
62
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/date.test.ts
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const beforeBenchmarkDate = new Date(Date.UTC(2022, 10, 4));
|
||||
const benchmarkDate = new Date(Date.UTC(2022, 10, 5));
|
||||
const afterBenchmarkDate = new Date(Date.UTC(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("date min", () => {
|
||||
const result = minCheck.safeParse(beforeBenchmarkDate);
|
||||
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected date to be >=1667606400000",
|
||||
"minimum": 1667606400000,
|
||||
"origin": "date",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test("date max", () => {
|
||||
const result = maxCheck.safeParse(afterBenchmarkDate);
|
||||
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 1667606400000,
|
||||
"message": "Too big: expected date to be <=1667606400000",
|
||||
"origin": "date",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
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);
|
||||
});
|
||||
302
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/datetime.test.ts
generated
vendored
Normal file
302
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/datetime.test.ts
generated
vendored
Normal file
@@ -0,0 +1,302 @@
|
||||
import { checkSync } from "recheck";
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("basic datetime parsing", () => {
|
||||
const datetime = z.string().datetime();
|
||||
datetime.parse("1970-01-01T00:00:00.000Z");
|
||||
datetime.parse("2022-10-13T09:52:31.816Z");
|
||||
datetime.parse("2022-10-13T09:52:31.8162314Z");
|
||||
datetime.parse("1970-01-01T00:00:00Z");
|
||||
datetime.parse("2022-10-13T09:52:31Z");
|
||||
expect(() => datetime.parse("")).toThrow();
|
||||
expect(() => datetime.parse("foo")).toThrow();
|
||||
expect(() => datetime.parse("2020-10-14")).toThrow();
|
||||
expect(() => datetime.parse("T18:45:12.123")).toThrow();
|
||||
expect(() => datetime.parse("2020-10-14T17:42:29+00:00")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime parsing with precision -1", () => {
|
||||
const datetimeNoMs = z.string().datetime({ precision: -1, offset: true, local: true });
|
||||
datetimeNoMs.parse("1970-01-01T00:00Z");
|
||||
datetimeNoMs.parse("2022-10-13T09:52Z");
|
||||
datetimeNoMs.parse("2022-10-13T09:52+02:00");
|
||||
|
||||
datetimeNoMs.parse("2022-10-13T09:52");
|
||||
expect(() => datetimeNoMs.parse("tuna")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("2022-10-13T09:52+02")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.000Z")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.Z")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("2022-10-13T09:52:31.816Z")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime parsing with precision 0", () => {
|
||||
const datetimeNoMs = z.string().datetime({ precision: 0 });
|
||||
datetimeNoMs.parse("1970-01-01T00:00:00Z");
|
||||
datetimeNoMs.parse("2022-10-13T09:52:31Z");
|
||||
expect(() => datetimeNoMs.parse("tuna")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.000Z")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("1970-01-01T00:00:00.Z")).toThrow();
|
||||
expect(() => datetimeNoMs.parse("2022-10-13T09:52:31.816Z")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime parsing with precision 3", () => {
|
||||
const datetime3Ms = z.string().datetime({ precision: 3 });
|
||||
datetime3Ms.parse("1970-01-01T00:00:00.000Z");
|
||||
datetime3Ms.parse("2022-10-13T09:52:31.123Z");
|
||||
expect(() => datetime3Ms.parse("tuna")).toThrow();
|
||||
expect(() => datetime3Ms.parse("1970-01-01T00:00:00.1Z")).toThrow();
|
||||
expect(() => datetime3Ms.parse("1970-01-01T00:00:00.12Z")).toThrow();
|
||||
expect(() => datetime3Ms.parse("2022-10-13T09:52:31Z")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime parsing with offset", () => {
|
||||
const datetimeOffset = z.string().datetime({ offset: true });
|
||||
datetimeOffset.parse("1970-01-01T00:00:00.000Z");
|
||||
datetimeOffset.parse("2022-10-13T09:52:31.816234134Z");
|
||||
datetimeOffset.parse("1970-01-01T00:00:00Z");
|
||||
datetimeOffset.parse("2022-10-13T09:52:31.4Z");
|
||||
datetimeOffset.parse("2020-10-14T17:42:29+00:00");
|
||||
datetimeOffset.parse("2020-10-14T17:42:29+03:15");
|
||||
expect(() => datetimeOffset.parse("2020-10-14T17:42:29+0315")).toThrow();
|
||||
expect(() => datetimeOffset.parse("2020-10-14T17:42:29+03")).toThrow();
|
||||
expect(() => datetimeOffset.parse("tuna")).toThrow();
|
||||
expect(() => datetimeOffset.parse("2022-10-13T09:52:31.Z")).toThrow();
|
||||
|
||||
// Invalid offset tests
|
||||
expect(() => datetimeOffset.parse("2020-10-14T17:42:29+24:00")).toThrow(); // out of range hours
|
||||
expect(() => datetimeOffset.parse("2020-10-14T17:42:29+00:60")).toThrow(); // out of range minutes
|
||||
expect(() => datetimeOffset.parse("2020-10-14T17:42:29+1:30")).toThrow(); // single digit hours
|
||||
expect(() => datetimeOffset.parse("2020-10-14T17:42:29+00:")).toThrow(); // incomplete offset
|
||||
});
|
||||
|
||||
test("datetime parsing with offset and precision 0", () => {
|
||||
const datetimeOffsetNoMs = z.string().datetime({ offset: true, precision: 0 });
|
||||
datetimeOffsetNoMs.parse("1970-01-01T00:00:00Z");
|
||||
datetimeOffsetNoMs.parse("2022-10-13T09:52:31Z");
|
||||
datetimeOffsetNoMs.parse("2020-10-14T17:42:29+00:00");
|
||||
expect(() => datetimeOffsetNoMs.parse("2020-10-14T17:42:29+0000")).toThrow();
|
||||
expect(() => datetimeOffsetNoMs.parse("2020-10-14T17:42:29+00")).toThrow();
|
||||
expect(() => datetimeOffsetNoMs.parse("tuna")).toThrow();
|
||||
expect(() => datetimeOffsetNoMs.parse("1970-01-01T00:00:00.000Z")).toThrow();
|
||||
expect(() => datetimeOffsetNoMs.parse("1970-01-01T00:00:00.Z")).toThrow();
|
||||
expect(() => datetimeOffsetNoMs.parse("2022-10-13T09:52:31.816Z")).toThrow();
|
||||
expect(() => datetimeOffsetNoMs.parse("2020-10-14T17:42:29.124+00:00")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime parsing with offset and precision 4", () => {
|
||||
const datetimeOffset4Ms = z.string().datetime({ offset: true, precision: 4 });
|
||||
datetimeOffset4Ms.parse("1970-01-01T00:00:00.1234Z");
|
||||
datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+00:00");
|
||||
expect(() => datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+0000")).toThrow();
|
||||
expect(() => datetimeOffset4Ms.parse("2020-10-14T17:42:29.1234+00")).toThrow();
|
||||
expect(() => datetimeOffset4Ms.parse("tuna")).toThrow();
|
||||
expect(() => datetimeOffset4Ms.parse("1970-01-01T00:00:00.123Z")).toThrow();
|
||||
expect(() => datetimeOffset4Ms.parse("2020-10-14T17:42:29.124+00:00")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime offset normalization", () => {
|
||||
const a = z.iso.datetime({ offset: true });
|
||||
|
||||
expect(a.safeParse("2020-10-14T17:42:29+02")).toMatchObject({ success: false });
|
||||
expect(a.safeParse("2020-10-14T17:42:29+0200")).toMatchObject({ success: false });
|
||||
a.safeParse("2020-10-14T17:42:29+02:00");
|
||||
});
|
||||
|
||||
test("datetime parsing with local option", () => {
|
||||
const a = z.string().datetime({ local: true });
|
||||
|
||||
expect(a.safeParse("1970-01-01T00:00")).toMatchObject({ success: true });
|
||||
expect(a.safeParse("1970-01-01T00:00:00")).toMatchObject({ success: true });
|
||||
expect(a.safeParse("2022-10-13T09:52:31.816")).toMatchObject({ success: true });
|
||||
expect(a.safeParse("1970-01-01T00:00:00.000")).toMatchObject({ success: true });
|
||||
expect(a.safeParse("1970-01-01T00")).toMatchObject({ success: false });
|
||||
|
||||
// Should reject timezone indicators and invalid formats
|
||||
|
||||
expect(() => a.parse("2022-10-13T09:52:31+00:00")).toThrow();
|
||||
expect(() => a.parse("2022-10-13 09:52:31")).toThrow();
|
||||
expect(() => a.parse("2022-10-13T24:52:31")).toThrow();
|
||||
expect(() => a.parse("2022-10-13T24:52")).toThrow();
|
||||
expect(() => a.parse("2022-10-13T24:52Z")).toThrow();
|
||||
});
|
||||
|
||||
test("datetime parsing with local and offset", () => {
|
||||
const a = z.string().datetime({ local: true, offset: true });
|
||||
|
||||
// expect(a.parse("2022-10-13T12:52")).toEqual("2022-10-13T12:52:00");
|
||||
a.parse("2022-10-13T12:52:00");
|
||||
a.parse("2022-10-13T12:52:00Z");
|
||||
a.parse("2022-10-13T12:52Z");
|
||||
a.parse("2022-10-13T12:52");
|
||||
a.parse("2022-10-13T12:52+02:00");
|
||||
expect(() => a.parse("2022-10-13T12:52:00+02")).toThrow();
|
||||
// expect(() => a.parse("2022-10-13T12:52Z")).toThrow();
|
||||
// expect(() => a.parse("2022-10-13T12:52+02:00")).toThrow();
|
||||
});
|
||||
|
||||
test("date parsing", () => {
|
||||
const date = z.string().date();
|
||||
date.parse("1970-01-01");
|
||||
date.parse("2022-01-31");
|
||||
date.parse("2022-03-31");
|
||||
date.parse("2022-04-30");
|
||||
date.parse("2022-05-31");
|
||||
date.parse("2022-06-30");
|
||||
date.parse("2022-07-31");
|
||||
date.parse("2022-08-31");
|
||||
date.parse("2022-09-30");
|
||||
date.parse("2022-10-31");
|
||||
date.parse("2022-11-30");
|
||||
date.parse("2022-12-31");
|
||||
|
||||
date.parse("2000-02-29");
|
||||
date.parse("2400-02-29");
|
||||
expect(() => date.parse("2022-02-29")).toThrow();
|
||||
expect(() => date.parse("2100-02-29")).toThrow();
|
||||
expect(() => date.parse("2200-02-29")).toThrow();
|
||||
expect(() => date.parse("2300-02-29")).toThrow();
|
||||
expect(() => date.parse("2500-02-29")).toThrow();
|
||||
|
||||
expect(() => date.parse("")).toThrow();
|
||||
expect(() => date.parse("foo")).toThrow();
|
||||
expect(() => date.parse("200-01-01")).toThrow();
|
||||
expect(() => date.parse("20000-01-01")).toThrow();
|
||||
expect(() => date.parse("2000-0-01")).toThrow();
|
||||
expect(() => date.parse("2000-011-01")).toThrow();
|
||||
expect(() => date.parse("2000-01-0")).toThrow();
|
||||
expect(() => date.parse("2000-01-011")).toThrow();
|
||||
expect(() => date.parse("2000/01/01")).toThrow();
|
||||
expect(() => date.parse("01-01-2022")).toThrow();
|
||||
expect(() => date.parse("01/01/2022")).toThrow();
|
||||
expect(() => date.parse("2000-01-01 00:00:00Z")).toThrow();
|
||||
expect(() => date.parse("2020-10-14T17:42:29+00:00")).toThrow();
|
||||
expect(() => date.parse("2020-10-14T17:42:29Z")).toThrow();
|
||||
expect(() => date.parse("2020-10-14T17:42:29")).toThrow();
|
||||
expect(() => date.parse("2020-10-14T17:42:29.123Z")).toThrow();
|
||||
|
||||
expect(() => date.parse("2000-00-12")).toThrow();
|
||||
expect(() => date.parse("2000-12-00")).toThrow();
|
||||
expect(() => date.parse("2000-01-32")).toThrow();
|
||||
expect(() => date.parse("2000-13-01")).toThrow();
|
||||
expect(() => date.parse("2000-21-01")).toThrow();
|
||||
|
||||
expect(() => date.parse("2000-02-30")).toThrow();
|
||||
expect(() => date.parse("2000-02-31")).toThrow();
|
||||
expect(() => date.parse("2000-04-31")).toThrow();
|
||||
expect(() => date.parse("2000-06-31")).toThrow();
|
||||
expect(() => date.parse("2000-09-31")).toThrow();
|
||||
expect(() => date.parse("2000-11-31")).toThrow();
|
||||
});
|
||||
|
||||
test("time parsing", () => {
|
||||
const time = z.string().time();
|
||||
time.parse("00:00:00");
|
||||
time.parse("23:00:00");
|
||||
time.parse("00:59:00");
|
||||
time.parse("00:00:59");
|
||||
time.parse("23:59:59");
|
||||
time.parse("09:52:31");
|
||||
time.parse("23:59:59.9999999");
|
||||
time.parse("00:00");
|
||||
expect(() => time.parse("")).toThrow();
|
||||
expect(() => time.parse("foo")).toThrow();
|
||||
expect(() => time.parse("00:00:00Z")).toThrow();
|
||||
expect(() => time.parse("0:00:00")).toThrow();
|
||||
expect(() => time.parse("00:0:00")).toThrow();
|
||||
expect(() => time.parse("00:00:0")).toThrow();
|
||||
expect(() => time.parse("00:00:00.000+00:00")).toThrow();
|
||||
expect(() => time.parse("24:00:00")).toThrow();
|
||||
expect(() => time.parse("00:60:00")).toThrow();
|
||||
expect(() => time.parse("00:00:60")).toThrow();
|
||||
expect(() => time.parse("24:60:60")).toThrow();
|
||||
|
||||
const time2 = z.string().time({ precision: 2 });
|
||||
time2.parse("00:00:00.00");
|
||||
time2.parse("09:52:31.12");
|
||||
time2.parse("23:59:59.99");
|
||||
expect(() => time2.parse("")).toThrow();
|
||||
expect(() => time2.parse("foo")).toThrow();
|
||||
expect(() => time2.parse("00:00:00")).toThrow();
|
||||
expect(() => time2.parse("00:00:00.00Z")).toThrow();
|
||||
expect(() => time2.parse("00:00:00.0")).toThrow();
|
||||
expect(() => time2.parse("00:00:00.000")).toThrow();
|
||||
expect(() => time2.parse("00:00:00.00+00:00")).toThrow();
|
||||
|
||||
const time3 = z.string().time({ precision: z.TimePrecision.Minute });
|
||||
time3.parse("00:00");
|
||||
expect(() => time3.parse("00:00:00")).toThrow();
|
||||
});
|
||||
|
||||
test("duration", () => {
|
||||
const duration = z.string().duration();
|
||||
|
||||
const validDurations = [
|
||||
"P3Y6M4DT12H30M5S",
|
||||
"P2Y9M3DT12H31M8.001S",
|
||||
// "+P3Y6M4DT12H30M5S",
|
||||
// "-PT0.001S",
|
||||
// "+PT0.001S",
|
||||
"PT0,001S",
|
||||
"PT12H30M5S",
|
||||
// "-P2M1D",
|
||||
// "P-2M-1D",
|
||||
// "-P5DT10H",
|
||||
// "P-5DT-10H",
|
||||
"P1Y",
|
||||
"P2MT30M",
|
||||
"PT6H",
|
||||
"P5W",
|
||||
// "P0.5Y",
|
||||
// "P0,5Y",
|
||||
// "P42YT7.004M",
|
||||
];
|
||||
|
||||
const invalidDurations = [
|
||||
"foo bar",
|
||||
"",
|
||||
" ",
|
||||
"P",
|
||||
"PT",
|
||||
"P1Y2MT",
|
||||
"T1H",
|
||||
"P0.5Y1D",
|
||||
"P0,5Y6M",
|
||||
"P1YT",
|
||||
"P-2M-1D",
|
||||
"P-5DT-10H",
|
||||
"P1W2D",
|
||||
"-P1D",
|
||||
];
|
||||
|
||||
for (const val of validDurations) {
|
||||
const result = duration.safeParse(val);
|
||||
if (!result.success) {
|
||||
throw Error(`Valid duration could not be parsed: ${val}`);
|
||||
}
|
||||
}
|
||||
|
||||
for (const val of invalidDurations) {
|
||||
const result = duration.safeParse(val);
|
||||
|
||||
if (result.success) {
|
||||
throw Error(`Invalid duration was successful parsed: ${val}`);
|
||||
}
|
||||
|
||||
expect(result.error.issues[0].message).toEqual("Invalid ISO duration");
|
||||
}
|
||||
});
|
||||
|
||||
test("redos checker", () => {
|
||||
const a = z.iso.datetime();
|
||||
const b = z.string().datetime({ offset: true });
|
||||
const c = z.string().datetime({ local: true });
|
||||
const d = z.string().datetime({ local: true, offset: true, precision: 3 });
|
||||
const e = z.string().date();
|
||||
const f = z.string().time();
|
||||
const g = z.string().duration();
|
||||
for (const schema of [a, b, c, d, e, f, g]) {
|
||||
const result = checkSync(schema._zod.pattern.source, "");
|
||||
if (result.status !== "safe") throw Error("ReDoS issue");
|
||||
}
|
||||
});
|
||||
365
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/default.test.ts
generated
vendored
Normal file
365
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/default.test.ts
generated
vendored
Normal file
@@ -0,0 +1,365 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
test("basic defaults", () => {
|
||||
expect(z.string().default("default").parse(undefined)).toBe("default");
|
||||
});
|
||||
|
||||
test("default with optional", () => {
|
||||
const schema = z.string().optional().default("default");
|
||||
expect(schema.parse(undefined)).toBe("default");
|
||||
expect(schema.unwrap().parse(undefined)).toBe(undefined);
|
||||
});
|
||||
|
||||
test("default with transform", () => {
|
||||
const stringWithDefault = z
|
||||
.string()
|
||||
.transform((val) => val.toUpperCase())
|
||||
.default("default");
|
||||
expect(stringWithDefault.parse(undefined)).toBe("default");
|
||||
expect(stringWithDefault).toBeInstanceOf(z.ZodDefault);
|
||||
expect(stringWithDefault.unwrap()).toBeInstanceOf(z.ZodPipe);
|
||||
expect(stringWithDefault.unwrap().in).toBeInstanceOf(z.ZodString);
|
||||
expect(stringWithDefault.unwrap().out).toBeInstanceOf(z.ZodTransform);
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("default on existing optional", () => {
|
||||
const stringWithDefault = z.string().optional().default("asdf");
|
||||
expect(stringWithDefault.parse(undefined)).toBe("asdf");
|
||||
expect(stringWithDefault).toBeInstanceOf(z.ZodDefault);
|
||||
expect(stringWithDefault.unwrap()).toBeInstanceOf(z.ZodOptional);
|
||||
expect(stringWithDefault.unwrap().unwrap()).toBeInstanceOf(z.ZodString);
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("optional on default", () => {
|
||||
const stringWithDefault = z.string().default("asdf").optional();
|
||||
|
||||
type inp = z.input<typeof stringWithDefault>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined>();
|
||||
type out = z.output<typeof stringWithDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string | undefined>();
|
||||
|
||||
expect(stringWithDefault.parse(undefined)).toBe("asdf");
|
||||
});
|
||||
|
||||
// test("complex chain example", () => {
|
||||
// const complex = z
|
||||
// .string()
|
||||
// .default("asdf")
|
||||
// .transform((val) => val.toUpperCase())
|
||||
// .default("qwer")
|
||||
// .unwrap()
|
||||
// .optional()
|
||||
// .default("asdfasdf");
|
||||
|
||||
// expect(complex.parse(undefined)).toBe("asdfasdf");
|
||||
// });
|
||||
|
||||
test("removeDefault", () => {
|
||||
const stringWithRemovedDefault = z.string().default("asdf").removeDefault();
|
||||
|
||||
type out = z.output<typeof stringWithRemovedDefault>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("apply default at output", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.transform((_) => (Math.random() > 0 ? undefined : _))
|
||||
.default("asdf");
|
||||
expect(schema.parse("")).toEqual("asdf");
|
||||
});
|
||||
|
||||
test("nested", () => {
|
||||
const inner = z.string().default("asdf");
|
||||
const outer = z.object({ inner }).default({
|
||||
inner: "qwer",
|
||||
});
|
||||
type input = z.input<typeof outer>;
|
||||
expectTypeOf<input>().toEqualTypeOf<{ inner?: string | undefined } | undefined>();
|
||||
type out = z.output<typeof outer>;
|
||||
expectTypeOf<out>().toEqualTypeOf<{ inner: string }>();
|
||||
expect(outer.parse(undefined)).toEqual({ inner: "qwer" });
|
||||
expect(outer.parse({})).toEqual({ inner: "asdf" });
|
||||
expect(outer.parse({ inner: undefined })).toEqual({ inner: "asdf" });
|
||||
});
|
||||
|
||||
test("chained defaults", () => {
|
||||
const stringWithDefault = z.string().default("inner").default("outer");
|
||||
const result = stringWithDefault.parse(undefined);
|
||||
expect(result).toEqual("outer");
|
||||
});
|
||||
|
||||
test("object optionality", () => {
|
||||
const schema = z.object({
|
||||
hi: z.string().default("hi"),
|
||||
});
|
||||
type schemaInput = z.input<typeof schema>;
|
||||
type schemaOutput = z.output<typeof schema>;
|
||||
expectTypeOf<schemaInput>().toEqualTypeOf<{ hi?: string | undefined }>();
|
||||
expectTypeOf<schemaOutput>().toEqualTypeOf<{ hi: string }>();
|
||||
expect(schema.parse({})).toEqual({
|
||||
hi: "hi",
|
||||
});
|
||||
});
|
||||
|
||||
test("nested prefault/default", () => {
|
||||
const a = z
|
||||
.string()
|
||||
.default("a")
|
||||
.refine((val) => val.startsWith("a"));
|
||||
const b = z
|
||||
.string()
|
||||
.refine((val) => val.startsWith("b"))
|
||||
.default("b");
|
||||
const c = z
|
||||
.string()
|
||||
.prefault("c")
|
||||
.refine((val) => val.startsWith("c"));
|
||||
const d = z
|
||||
.string()
|
||||
.refine((val) => val.startsWith("d"))
|
||||
.prefault("d");
|
||||
|
||||
const obj = z.object({
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
});
|
||||
|
||||
expect(obj.safeParse({ a: "a1", b: "b1", c: "c1", d: "d1" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": {
|
||||
"a": "a1",
|
||||
"b": "b1",
|
||||
"c": "c1",
|
||||
"d": "d1",
|
||||
},
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(obj.safeParse({ a: "f", b: "f", c: "f", d: "f" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"a"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"b"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"c"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"d"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(obj.safeParse({})).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": {
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
"c": "c",
|
||||
"d": "d",
|
||||
},
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(obj.safeParse({ a: undefined, b: undefined, c: undefined, d: undefined })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": {
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
"c": "c",
|
||||
"d": "d",
|
||||
},
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
|
||||
const obj2 = z.object({
|
||||
a: a.optional(),
|
||||
b: b.optional(),
|
||||
c: c.optional(),
|
||||
d: d.optional(),
|
||||
});
|
||||
expect(obj2.safeParse({ a: undefined, b: undefined, c: undefined, d: undefined })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": {
|
||||
"a": "a",
|
||||
"b": "b",
|
||||
"c": "c",
|
||||
"d": "d",
|
||||
},
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(a.parse(undefined)).toBe("a");
|
||||
expect(b.parse(undefined)).toBe("b");
|
||||
expect(c.parse(undefined)).toBe("c");
|
||||
expect(d.parse(undefined)).toBe("d");
|
||||
});
|
||||
|
||||
test("failing default", () => {
|
||||
const a = z
|
||||
.string()
|
||||
.default("z")
|
||||
.refine((val) => val.startsWith("a"));
|
||||
const b = z
|
||||
.string()
|
||||
.refine((val) => val.startsWith("b"))
|
||||
.default("z");
|
||||
const c = z
|
||||
.string()
|
||||
.prefault("z")
|
||||
.refine((val) => val.startsWith("c"));
|
||||
const d = z
|
||||
.string()
|
||||
.refine((val) => val.startsWith("d"))
|
||||
.prefault("z");
|
||||
|
||||
const obj = z.object({
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
d,
|
||||
});
|
||||
|
||||
expect(
|
||||
obj.safeParse({
|
||||
a: undefined,
|
||||
b: undefined,
|
||||
c: undefined,
|
||||
d: undefined,
|
||||
}).error!.issues
|
||||
).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [
|
||||
"a",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [
|
||||
"c",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Invalid input",
|
||||
"path": [
|
||||
"d",
|
||||
],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test("partial should not clobber defaults", () => {
|
||||
const objWithDefaults = z.object({
|
||||
a: z.string().default("defaultA"),
|
||||
b: z.string().default("defaultB"),
|
||||
c: z.string().default("defaultC"),
|
||||
});
|
||||
|
||||
const objPartialWithOneRequired = objWithDefaults.partial(); //.required({ a: true });
|
||||
|
||||
const test = objPartialWithOneRequired.parse({});
|
||||
expect(test).toMatchInlineSnapshot(`
|
||||
{
|
||||
"a": "defaultA",
|
||||
"b": "defaultB",
|
||||
"c": "defaultC",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("defaulted object schema returns shallow clone", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.string(),
|
||||
})
|
||||
.default({ a: "x" });
|
||||
const result1 = schema.parse(undefined);
|
||||
const result2 = schema.parse(undefined);
|
||||
expect(result1).not.toBe(result2);
|
||||
expect(result1).toEqual(result2);
|
||||
});
|
||||
|
||||
test("defaulted array schema returns shallow clone", () => {
|
||||
const schema = z.array(z.string()).default(["x"]);
|
||||
const result1 = schema.parse(undefined);
|
||||
const result2 = schema.parse(undefined);
|
||||
expect(result1).not.toBe(result2);
|
||||
expect(result1).toEqual(result2);
|
||||
});
|
||||
|
||||
test("direction-aware defaults", () => {
|
||||
const schema = z.string().default("hello");
|
||||
|
||||
// Forward direction (regular parse): defaults should be applied
|
||||
expect(schema.parse(undefined)).toBe("hello");
|
||||
expect(schema.parse("hello")).toBe("hello");
|
||||
|
||||
// Reverse direction (encode): defaults should NOT be applied, undefined should fail validation
|
||||
expect(() => z.encode(schema, undefined as any)).toThrow();
|
||||
|
||||
// But valid values should still work in reverse
|
||||
expect(z.safeEncode(schema, "world")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": "world",
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
expect(z.safeEncode(schema, undefined as any)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
27
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/describe-meta-checks.test.ts
generated
vendored
Normal file
27
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/describe-meta-checks.test.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import * as z from "../index.js";
|
||||
|
||||
describe("z.describe() check", () => {
|
||||
it("registers description in globalRegistry", () => {
|
||||
const schema = z.string().check(z.describe("A string"));
|
||||
expect(z.globalRegistry.get(schema)?.description).toBe("A string");
|
||||
});
|
||||
});
|
||||
|
||||
describe("z.meta() check", () => {
|
||||
it("registers metadata in globalRegistry", () => {
|
||||
const schema = z.number().check(z.meta({ title: "Age", description: "User's age" }));
|
||||
const meta = z.globalRegistry.get(schema);
|
||||
expect(meta?.title).toBe("Age");
|
||||
expect(meta?.description).toBe("User's age");
|
||||
});
|
||||
});
|
||||
|
||||
describe("combined usage", () => {
|
||||
it("works with multiple checks", () => {
|
||||
const schema = z.string().check(z.describe("Email address"), z.meta({ title: "Email" }));
|
||||
const meta = z.globalRegistry.get(schema);
|
||||
expect(meta?.description).toBe("Email address");
|
||||
expect(meta?.title).toBe("Email");
|
||||
});
|
||||
});
|
||||
32
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/description.test.ts
generated
vendored
Normal file
32
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/description.test.ts
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const description = "a description";
|
||||
|
||||
// test("passing `description` to schema should add a description", () => {
|
||||
// expect(z.string({ description }).description).toEqual(description);
|
||||
// expect(z.number({ description }).description).toEqual(description);
|
||||
// expect(z.boolean({ description }).description).toEqual(description);
|
||||
// });
|
||||
|
||||
test(".describe", () => {
|
||||
expect(z.string().describe(description).description).toEqual(description);
|
||||
expect(z.number().describe(description).description).toEqual(description);
|
||||
expect(z.boolean().describe(description).description).toEqual(description);
|
||||
});
|
||||
|
||||
test("adding description with z.globalRegistry", () => {
|
||||
const schema = z.string();
|
||||
z.core.globalRegistry.add(schema, { description });
|
||||
z.core.globalRegistry.get(schema);
|
||||
expect(schema.description).toEqual(description);
|
||||
});
|
||||
|
||||
// in Zod 4 descriptions are not inherited
|
||||
// test("description should carry over to chained schemas", () => {
|
||||
// const schema = z.string().describe(description);
|
||||
// expect(schema.description).toEqual(description);
|
||||
// expect(schema.optional().description).toEqual(description);
|
||||
// expect(schema.optional().nullable().default("default").description).toEqual(description);
|
||||
// });
|
||||
661
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts
generated
vendored
Normal file
661
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/discriminated-unions.test.ts
generated
vendored
Normal file
@@ -0,0 +1,661 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("_values", () => {
|
||||
expect(z.string()._zod.values).toEqual(undefined);
|
||||
expect(z.enum(["a", "b"])._zod.values).toEqual(new Set(["a", "b"]));
|
||||
expect(z.nativeEnum({ a: "A", b: "B" })._zod.values).toEqual(new Set(["A", "B"]));
|
||||
expect(z.literal("test")._zod.values).toEqual(new Set(["test"]));
|
||||
expect(z.literal(123)._zod.values).toEqual(new Set([123]));
|
||||
expect(z.literal(true)._zod.values).toEqual(new Set([true]));
|
||||
expect(z.literal(BigInt(123))._zod.values).toEqual(new Set([BigInt(123)]));
|
||||
expect(z.undefined()._zod.values).toEqual(new Set([undefined]));
|
||||
expect(z.null()._zod.values).toEqual(new Set([null]));
|
||||
|
||||
const t = z.literal("test");
|
||||
expect(t.optional()._zod.values).toEqual(new Set(["test", undefined]));
|
||||
expect(t.nullable()._zod.values).toEqual(new Set(["test", null]));
|
||||
expect(t.default("test")._zod.values).toEqual(new Set(["test"]));
|
||||
expect(t.catch("test")._zod.values).toEqual(new Set(["test"]));
|
||||
|
||||
const pre = z.preprocess((val) => String(val), z.string()).pipe(z.literal("test"));
|
||||
expect(pre._zod.values).toEqual(undefined);
|
||||
|
||||
const post = z.literal("test").transform((_) => Math.random());
|
||||
expect(post._zod.values).toEqual(new Set(["test"]));
|
||||
|
||||
// Test that readonly literals pass through their values property
|
||||
expect(z.literal("test").readonly()._zod.values).toEqual(new Set(["test"]));
|
||||
});
|
||||
|
||||
test("valid parse - object", () => {
|
||||
expect(
|
||||
z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
])
|
||||
.parse({ type: "a", a: "abc" })
|
||||
).toEqual({ type: "a", a: "abc" });
|
||||
});
|
||||
|
||||
test("valid - include discriminator key (deprecated)", () => {
|
||||
expect(
|
||||
z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
])
|
||||
.parse({ type: "a", a: "abc" })
|
||||
).toEqual({ type: "a", a: "abc" });
|
||||
});
|
||||
|
||||
test("valid - optional discriminator (object)", () => {
|
||||
const schema = z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a").optional(), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
]);
|
||||
expect(schema.parse({ type: "a", a: "abc" })).toEqual({ type: "a", a: "abc" });
|
||||
expect(schema.parse({ a: "abc" })).toEqual({ a: "abc" });
|
||||
});
|
||||
|
||||
test("valid - discriminator value of various primitive types", () => {
|
||||
const schema = z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("1"), val: z.string() }),
|
||||
z.object({ type: z.literal(1), val: z.string() }),
|
||||
z.object({ type: z.literal(BigInt(1)), val: z.string() }),
|
||||
z.object({ type: z.literal("true"), val: z.string() }),
|
||||
z.object({ type: z.literal(true), val: z.string() }),
|
||||
z.object({ type: z.literal("null"), val: z.string() }),
|
||||
z.object({ type: z.null(), val: z.string() }),
|
||||
z.object({ type: z.literal("undefined"), val: z.string() }),
|
||||
z.object({ type: z.undefined(), val: z.string() }),
|
||||
]);
|
||||
|
||||
expect(schema.parse({ type: "1", val: "val" })).toEqual({ type: "1", val: "val" });
|
||||
expect(schema.parse({ type: 1, val: "val" })).toEqual({ type: 1, val: "val" });
|
||||
expect(schema.parse({ type: BigInt(1), val: "val" })).toEqual({
|
||||
type: BigInt(1),
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: "true", val: "val" })).toEqual({
|
||||
type: "true",
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: true, val: "val" })).toEqual({
|
||||
type: true,
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: "null", val: "val" })).toEqual({
|
||||
type: "null",
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: null, val: "val" })).toEqual({
|
||||
type: null,
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: "undefined", val: "val" })).toEqual({
|
||||
type: "undefined",
|
||||
val: "val",
|
||||
});
|
||||
expect(schema.parse({ type: undefined, val: "val" })).toEqual({
|
||||
type: undefined,
|
||||
val: "val",
|
||||
});
|
||||
|
||||
const fail = schema.safeParse({
|
||||
type: "not_a_key",
|
||||
val: "val",
|
||||
});
|
||||
expect(fail.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
test("invalid - null", () => {
|
||||
try {
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
]).parse(null);
|
||||
throw new Error();
|
||||
} catch (e: any) {
|
||||
// [
|
||||
// {
|
||||
// code: z.ZodIssueCode.invalid_type,
|
||||
// expected: z.ZodParsedType.object,
|
||||
// input: null,
|
||||
// message: "Expected object, received null",
|
||||
// received: z.ZodParsedType.null,
|
||||
// path: [],
|
||||
// },
|
||||
// ];
|
||||
expect(e.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "object",
|
||||
"message": "Invalid input: expected object, received null",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("invalid discriminator value", () => {
|
||||
const result = z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
])
|
||||
.safeParse({ type: "x", a: "abc" });
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_union",
|
||||
"errors": [],
|
||||
"note": "No matching discriminator",
|
||||
"discriminator": "type",
|
||||
"path": [
|
||||
"type"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("invalid discriminator value - unionFallback", () => {
|
||||
const result = z
|
||||
.discriminatedUnion(
|
||||
"type",
|
||||
[z.object({ type: z.literal("a"), a: z.string() }), z.object({ type: z.literal("b"), b: z.string() })],
|
||||
{ unionFallback: true }
|
||||
)
|
||||
.safeParse({ type: "x", a: "abc" });
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_union",
|
||||
"errors": [
|
||||
[
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"a"
|
||||
],
|
||||
"path": [
|
||||
"type"
|
||||
],
|
||||
"message": "Invalid input: expected \\"a\\""
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"b"
|
||||
],
|
||||
"path": [
|
||||
"type"
|
||||
],
|
||||
"message": "Invalid input: expected \\"b\\""
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"b"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("valid discriminator value, invalid data", () => {
|
||||
const result = z
|
||||
.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.string() }),
|
||||
])
|
||||
.safeParse({ type: "a", b: "abc" });
|
||||
|
||||
// [
|
||||
// {
|
||||
// code: z.ZodIssueCode.invalid_type,
|
||||
// expected: z.ZodParsedType.string,
|
||||
// message: "Required",
|
||||
// path: ["a"],
|
||||
// received: z.ZodParsedType.undefined,
|
||||
// },
|
||||
// ];
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"a"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("wrong schema - missing discriminator", () => {
|
||||
try {
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), a: z.string() }),
|
||||
z.object({ b: z.string() }) as any,
|
||||
])._zod.propValues;
|
||||
throw new Error();
|
||||
} catch (e: any) {
|
||||
expect(e.message.includes("Invalid discriminated union option")).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
// removed to account for unions of unions
|
||||
// test("wrong schema - duplicate discriminator values", () => {
|
||||
// try {
|
||||
// z.discriminatedUnion("type",[
|
||||
// z.object({ type: z.literal("a"), a: z.string() }),
|
||||
// z.object({ type: z.literal("a"), b: z.string() }),
|
||||
// ]);
|
||||
// throw new Error();
|
||||
// } catch (e: any) {
|
||||
// expect(e.message.includes("Duplicate discriminator value")).toEqual(true);
|
||||
// }
|
||||
// });
|
||||
|
||||
test("async - valid", async () => {
|
||||
const schema = await z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal("a"),
|
||||
a: z
|
||||
.string()
|
||||
.refine(async () => true)
|
||||
.transform(async (val) => Number(val)),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("b"),
|
||||
b: z.string(),
|
||||
}),
|
||||
]);
|
||||
const data = { type: "a", a: "1" };
|
||||
const result = await schema.safeParseAsync(data);
|
||||
expect(result.data).toEqual({ type: "a", a: 1 });
|
||||
});
|
||||
|
||||
test("async - invalid", async () => {
|
||||
// try {
|
||||
const a = z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal("a"),
|
||||
a: z
|
||||
.string()
|
||||
.refine(async () => true)
|
||||
.transform(async (val) => val),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("b"),
|
||||
b: z.string(),
|
||||
}),
|
||||
]);
|
||||
const result = await a.safeParseAsync({ type: "a", a: 1 });
|
||||
|
||||
// expect(JSON.parse(e.message)).toEqual([
|
||||
// {
|
||||
// code: "invalid_type",
|
||||
// expected: "string",
|
||||
// input: 1,
|
||||
// received: "number",
|
||||
// path: ["a"],
|
||||
// message: "Expected string, received number",
|
||||
// },
|
||||
// ]);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"a"
|
||||
],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("valid - literals with .default or .pipe", () => {
|
||||
const schema = z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal("foo").default("foo"),
|
||||
a: z.string(),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("custom"),
|
||||
method: z.string(),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("bar").transform((val) => val),
|
||||
c: z.string(),
|
||||
}),
|
||||
]);
|
||||
expect(schema.parse({ type: "foo", a: "foo" })).toEqual({
|
||||
type: "foo",
|
||||
a: "foo",
|
||||
});
|
||||
});
|
||||
|
||||
test("enum and nativeEnum", () => {
|
||||
enum MyEnum {
|
||||
d = 0,
|
||||
e = "e",
|
||||
}
|
||||
|
||||
const schema = z.discriminatedUnion("key", [
|
||||
z.object({
|
||||
key: z.literal("a"),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
z.object({
|
||||
key: z.enum(["b", "c"]),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
z.object({
|
||||
key: z.nativeEnum(MyEnum),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
]);
|
||||
|
||||
type schema = z.infer<typeof schema>;
|
||||
expectTypeOf<schema>().toEqualTypeOf<{ key: "a" } | { key: "b" | "c" } | { key: MyEnum.d | MyEnum.e }>();
|
||||
|
||||
schema.parse({ key: "a" });
|
||||
schema.parse({ key: "b" });
|
||||
schema.parse({ key: "c" });
|
||||
schema.parse({ key: MyEnum.d });
|
||||
schema.parse({ key: MyEnum.e });
|
||||
schema.parse({ key: "e" });
|
||||
});
|
||||
|
||||
test("branded", () => {
|
||||
const schema = z.discriminatedUnion("key", [
|
||||
z.object({
|
||||
key: z.literal("a"),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
z.object({
|
||||
key: z.literal("b").brand<"asdfasdf">(),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
]);
|
||||
|
||||
type schema = z.infer<typeof schema>;
|
||||
expectTypeOf<schema>().toEqualTypeOf<{ key: "a" } | { key: "b" & z.core.$brand<"asdfasdf"> }>();
|
||||
|
||||
schema.parse({ key: "a" });
|
||||
schema.parse({ key: "b" });
|
||||
expect(() => {
|
||||
schema.parse({ key: "c" });
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test("optional and nullable", () => {
|
||||
const schema = z.discriminatedUnion("key", [
|
||||
z.object({
|
||||
key: z.literal("a").optional(),
|
||||
a: z.literal(true),
|
||||
}),
|
||||
z.object({
|
||||
key: z.literal("b").nullable(),
|
||||
b: z.literal(true),
|
||||
// Add other properties specific to this option
|
||||
}),
|
||||
]);
|
||||
|
||||
type schema = z.infer<typeof schema>;
|
||||
expectTypeOf<schema>().toEqualTypeOf<{ key?: "a" | undefined; a: true } | { key: "b" | null; b: true }>();
|
||||
|
||||
schema.parse({ key: "a", a: true });
|
||||
schema.parse({ key: undefined, a: true });
|
||||
schema.parse({ key: "b", b: true });
|
||||
schema.parse({ key: null, b: true });
|
||||
expect(() => {
|
||||
schema.parse({ key: null, a: true });
|
||||
}).toThrow();
|
||||
expect(() => {
|
||||
schema.parse({ key: "b", a: true });
|
||||
}).toThrow();
|
||||
|
||||
const value = schema.parse({ key: null, b: true });
|
||||
|
||||
if (!("key" in value)) value.a;
|
||||
if (value.key === undefined) value.a;
|
||||
if (value.key === "a") value.a;
|
||||
if (value.key === "b") value.b;
|
||||
if (value.key === null) value.b;
|
||||
});
|
||||
|
||||
test("multiple discriminators", () => {
|
||||
const FreeConfig = z.object({
|
||||
type: z.literal("free"),
|
||||
min_cents: z.null(),
|
||||
});
|
||||
|
||||
// console.log(FreeConfig.shape.type);
|
||||
const PricedConfig = z.object({
|
||||
type: z.literal("fiat-price"),
|
||||
// min_cents: z.int().nullable(),
|
||||
min_cents: z.null(),
|
||||
});
|
||||
|
||||
const Config = z.discriminatedUnion("type", [FreeConfig, PricedConfig]);
|
||||
|
||||
Config.parse({
|
||||
min_cents: null,
|
||||
type: "fiat-price",
|
||||
name: "Standard",
|
||||
});
|
||||
|
||||
expect(() => {
|
||||
Config.parse({
|
||||
min_cents: null,
|
||||
type: "not real",
|
||||
name: "Standard",
|
||||
});
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test("single element union", () => {
|
||||
const schema = z.object({
|
||||
a: z.literal("discKey"),
|
||||
b: z.enum(["apple", "banana"]),
|
||||
c: z.object({ id: z.string() }),
|
||||
});
|
||||
|
||||
const input = {
|
||||
a: "discKey",
|
||||
b: "apple",
|
||||
c: {}, // Invalid, as schema requires `id` property
|
||||
};
|
||||
|
||||
// Validation must fail here, but it doesn't
|
||||
|
||||
const u = z.discriminatedUnion("a", [schema]);
|
||||
const result = u.safeParse(input);
|
||||
expect(result).toMatchObject({ success: false });
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"c",
|
||||
"id"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(u.options.length).toEqual(1);
|
||||
});
|
||||
|
||||
test("nested discriminated unions", () => {
|
||||
const BaseError = z.object({ status: z.literal("failed"), message: z.string() });
|
||||
const MyErrors = z.discriminatedUnion("code", [
|
||||
BaseError.extend({ code: z.literal(400) }),
|
||||
BaseError.extend({ code: z.literal(401) }),
|
||||
BaseError.extend({ code: z.literal(500) }),
|
||||
]);
|
||||
|
||||
const MyResult = z.discriminatedUnion("status", [
|
||||
z.object({ status: z.literal("success"), data: z.string() }),
|
||||
MyErrors,
|
||||
]);
|
||||
|
||||
expect(MyErrors._zod.propValues).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": Set {
|
||||
400,
|
||||
401,
|
||||
500,
|
||||
},
|
||||
"status": Set {
|
||||
"failed",
|
||||
},
|
||||
}
|
||||
`);
|
||||
expect(MyResult._zod.propValues).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": Set {
|
||||
400,
|
||||
401,
|
||||
500,
|
||||
},
|
||||
"status": Set {
|
||||
"success",
|
||||
"failed",
|
||||
},
|
||||
}
|
||||
`);
|
||||
|
||||
const result = MyResult.parse({ status: "success", data: "hello" });
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": "hello",
|
||||
"status": "success",
|
||||
}
|
||||
`);
|
||||
const result2 = MyResult.parse({ status: "failed", code: 400, message: "bad request" });
|
||||
expect(result2).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": 400,
|
||||
"message": "bad request",
|
||||
"status": "failed",
|
||||
}
|
||||
`);
|
||||
const result3 = MyResult.parse({ status: "failed", code: 401, message: "unauthorized" });
|
||||
expect(result3).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": 401,
|
||||
"message": "unauthorized",
|
||||
"status": "failed",
|
||||
}
|
||||
`);
|
||||
const result4 = MyResult.parse({ status: "failed", code: 500, message: "internal server error" });
|
||||
expect(result4).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": 500,
|
||||
"message": "internal server error",
|
||||
"status": "failed",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("readonly literal discriminator", () => {
|
||||
const discUnion = z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a").readonly(), a: z.string() }),
|
||||
z.object({ type: z.literal("b"), b: z.number() }),
|
||||
]);
|
||||
|
||||
// Test that both discriminator values are correctly included in propValues
|
||||
const propValues = discUnion._zod.propValues;
|
||||
expect(propValues?.type?.has("a")).toBe(true);
|
||||
expect(propValues?.type?.has("b")).toBe(true);
|
||||
|
||||
// Test that the discriminated union works correctly
|
||||
const result1 = discUnion.parse({ type: "a", a: "hello" });
|
||||
expect(result1).toEqual({ type: "a", a: "hello" });
|
||||
|
||||
const result2 = discUnion.parse({ type: "b", b: 42 });
|
||||
expect(result2).toEqual({ type: "b", b: 42 });
|
||||
|
||||
// Test that invalid discriminator values are rejected
|
||||
expect(() => {
|
||||
discUnion.parse({ type: "c", a: "hello" });
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
test("pipes", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
type: z.literal("foo"),
|
||||
})
|
||||
.transform((s) => ({ ...s, v: 2 }));
|
||||
|
||||
expect(schema._zod.propValues).toMatchInlineSnapshot(`
|
||||
{
|
||||
"type": Set {
|
||||
"foo",
|
||||
},
|
||||
}
|
||||
`);
|
||||
|
||||
const schema2 = z.object({
|
||||
type: z.literal("bar"),
|
||||
});
|
||||
|
||||
const combinedSchema = z.discriminatedUnion("type", [schema, schema2], {
|
||||
unionFallback: false,
|
||||
});
|
||||
|
||||
combinedSchema.parse({
|
||||
type: "foo",
|
||||
v: 2,
|
||||
});
|
||||
});
|
||||
|
||||
test("def", () => {
|
||||
const schema = z.discriminatedUnion(
|
||||
"type",
|
||||
[z.object({ type: z.literal("play") }), z.object({ type: z.literal("pause") })],
|
||||
{ unionFallback: true }
|
||||
);
|
||||
|
||||
expect(schema.def).toBeDefined();
|
||||
expect(schema.def.discriminator).toEqual("type");
|
||||
expect(schema.def.unionFallback).toEqual(true);
|
||||
});
|
||||
285
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/enum.test.ts
generated
vendored
Normal file
285
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/enum.test.ts
generated
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("enum from string array", () => {
|
||||
const MyEnum = z.enum(["Red", "Green", "Blue"]);
|
||||
expect(MyEnum.enum.Red).toEqual("Red");
|
||||
|
||||
type MyEnum = z.infer<typeof MyEnum>;
|
||||
expectTypeOf<MyEnum>().toEqualTypeOf<"Red" | "Green" | "Blue">();
|
||||
});
|
||||
|
||||
test("enum from const object", () => {
|
||||
const Fruits: { Apple: "apple"; Banana: "banana" } = {
|
||||
Apple: "apple",
|
||||
Banana: "banana",
|
||||
};
|
||||
const fruitEnum = z.nativeEnum(Fruits);
|
||||
type fruitEnum = z.infer<typeof fruitEnum>;
|
||||
fruitEnum.parse("apple");
|
||||
fruitEnum.parse("banana");
|
||||
fruitEnum.parse(Fruits.Apple);
|
||||
fruitEnum.parse(Fruits.Banana);
|
||||
expectTypeOf<fruitEnum>().toEqualTypeOf<"apple" | "banana">();
|
||||
});
|
||||
|
||||
test("enum from native enum", () => {
|
||||
enum Fruits {
|
||||
Apple = "apple",
|
||||
Banana = "banana",
|
||||
Orange = 3,
|
||||
}
|
||||
// @ts-ignore
|
||||
const fruitEnum = z.nativeEnum(Fruits);
|
||||
type fruitEnum = z.infer<typeof fruitEnum>;
|
||||
fruitEnum.parse("apple");
|
||||
fruitEnum.parse("banana");
|
||||
fruitEnum.parse(Fruits.Apple);
|
||||
fruitEnum.parse(Fruits.Banana);
|
||||
|
||||
expect(fruitEnum.safeParse("Apple").success).toEqual(false);
|
||||
expect(fruitEnum.safeParse("Cantaloupe").success).toEqual(false);
|
||||
|
||||
expectTypeOf<fruitEnum>().toMatchTypeOf<Fruits>();
|
||||
expectTypeOf<Fruits>().toMatchTypeOf<fruitEnum>();
|
||||
});
|
||||
|
||||
test("enum from native enum with numeric keys", () => {
|
||||
const FruitValues = {
|
||||
Apple: 10,
|
||||
Banana: 20,
|
||||
// @ts-ignore
|
||||
} as const;
|
||||
const fruitEnum = z.nativeEnum(FruitValues);
|
||||
type fruitEnum = z.infer<typeof fruitEnum>;
|
||||
fruitEnum.parse(10);
|
||||
fruitEnum.parse(20);
|
||||
fruitEnum.parse(FruitValues.Apple);
|
||||
fruitEnum.parse(FruitValues.Banana);
|
||||
expectTypeOf<fruitEnum>().toEqualTypeOf<10 | 20>();
|
||||
});
|
||||
|
||||
test("issue metadata", () => {
|
||||
const schema = z.enum(["Red", "Green", "Blue"]);
|
||||
const result = schema.safeParse("Yellow");
|
||||
expect(result.error!.issues[0]).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"message": "Invalid option: expected one of "Red"|"Green"|"Blue"",
|
||||
"path": [],
|
||||
"values": [
|
||||
"Red",
|
||||
"Green",
|
||||
"Blue",
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("enum from non-const inputs", () => {
|
||||
const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"];
|
||||
const FoodEnum = z.enum(foods);
|
||||
|
||||
expectTypeOf<z.infer<typeof FoodEnum>>().toEqualTypeOf<string>();
|
||||
expect(FoodEnum.safeParse("Pasta").success).toEqual(true);
|
||||
expect(FoodEnum.safeParse("Cucumbers").success).toEqual(false);
|
||||
});
|
||||
|
||||
test("get options", () => {
|
||||
expect(z.enum(["tuna", "trout"]).options).toEqual(["tuna", "trout"]);
|
||||
});
|
||||
|
||||
test("readonly enum", () => {
|
||||
const HTTP_SUCCESS = ["200", "201"] as const;
|
||||
const arg = z.enum(HTTP_SUCCESS);
|
||||
type arg = z.infer<typeof arg>;
|
||||
expectTypeOf<arg>().toEqualTypeOf<"200" | "201">();
|
||||
|
||||
arg.parse("201");
|
||||
expect(() => arg.parse("202")).toThrow();
|
||||
});
|
||||
|
||||
test("error map", () => {
|
||||
const result = z
|
||||
.enum(["test"], { error: (iss) => (iss.input === undefined ? "REQUIRED" : undefined) })
|
||||
.safeParse(undefined);
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues[0].message).toEqual("REQUIRED");
|
||||
}
|
||||
});
|
||||
|
||||
test("type signatures", () => {
|
||||
const a = z.enum(["a", "b", "c"]);
|
||||
const b = z.enum(a.options);
|
||||
expectTypeOf(a).toEqualTypeOf(b);
|
||||
|
||||
const c = z.enum({ a: 1, b: 2 } as const);
|
||||
expectTypeOf(c.enum).toEqualTypeOf<{
|
||||
readonly a: 1;
|
||||
readonly b: 2;
|
||||
}>();
|
||||
|
||||
enum Fruit {
|
||||
Apple = "apple",
|
||||
Banana = "banana",
|
||||
Orange = "orange",
|
||||
}
|
||||
const d = z.enum(Fruit);
|
||||
expectTypeOf(d.enum).toEqualTypeOf(Fruit);
|
||||
|
||||
const e = z.enum({ a: 1, b: 2 });
|
||||
expectTypeOf(e.enum).toEqualTypeOf<{
|
||||
readonly a: 1;
|
||||
readonly b: 2;
|
||||
}>();
|
||||
});
|
||||
|
||||
test("extract", () => {
|
||||
const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"] as const;
|
||||
const FoodEnum = z.enum(foods);
|
||||
const ItalianEnum = FoodEnum.extract(["Pasta", "Pizza"]);
|
||||
|
||||
expect(ItalianEnum.safeParse("Pasta").success).toEqual(true);
|
||||
expect(ItalianEnum.safeParse("Tacos").success).toEqual(false);
|
||||
|
||||
expectTypeOf<z.infer<typeof ItalianEnum>>().toEqualTypeOf<"Pasta" | "Pizza">();
|
||||
});
|
||||
|
||||
test("exclude", () => {
|
||||
const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"] as const;
|
||||
const FoodEnum = z.enum(foods);
|
||||
const UnhealthyEnum = FoodEnum.exclude(["Salad"]);
|
||||
|
||||
expect(UnhealthyEnum.safeParse("Pasta").success).toEqual(true);
|
||||
expect(UnhealthyEnum.safeParse("Salad").success).toEqual(false);
|
||||
expectTypeOf<z.infer<typeof UnhealthyEnum>>().toEqualTypeOf<"Pasta" | "Pizza" | "Tacos" | "Burgers">();
|
||||
|
||||
const EmptyFoodEnum = FoodEnum.exclude(foods);
|
||||
expectTypeOf<typeof EmptyFoodEnum>().toEqualTypeOf<z.ZodEnum<{}>>();
|
||||
expectTypeOf<z.infer<typeof EmptyFoodEnum>>().toEqualTypeOf<never>();
|
||||
});
|
||||
|
||||
test("error map inheritance", () => {
|
||||
const foods = ["Pasta", "Pizza", "Tacos", "Burgers", "Salad"] as const;
|
||||
const FoodEnum = z.enum(foods, { error: () => "This is not food!" });
|
||||
const ItalianEnum = FoodEnum.extract(["Pasta", "Pizza"]);
|
||||
|
||||
const foodsError = FoodEnum.safeParse("Cucumbers");
|
||||
const italianError = ItalianEnum.safeParse("Tacos");
|
||||
|
||||
expect(foodsError.error!.issues[0].message).toEqual(italianError.error!.issues[0].message);
|
||||
|
||||
const UnhealthyEnum = FoodEnum.exclude(["Salad"], {
|
||||
error: () => ({ message: "This is not healthy food!" }),
|
||||
});
|
||||
const unhealthyError = UnhealthyEnum.safeParse("Salad");
|
||||
if (!unhealthyError.success) {
|
||||
expect(unhealthyError.error.issues[0].message).toEqual("This is not healthy food!");
|
||||
}
|
||||
});
|
||||
|
||||
test("readonly in ZodEnumDef", () => {
|
||||
type _a = z.ZodEnum<{ readonly a: "a"; readonly b: "b" }>;
|
||||
type _b = z.ZodEnum<{ a: "a"; b: "b" }>;
|
||||
});
|
||||
|
||||
test("enum error message, invalid enum elementstring", () => {
|
||||
const result = z.enum(["Tuna", "Trout"]).safeParse("Salmon");
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"Tuna",
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid option: expected one of \\"Tuna\\"|\\"Trout\\""
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("enum error message, invalid type", () => {
|
||||
const result = z.enum(["Tuna", "Trout"]).safeParse(12);
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
// expect(result.error!.issues[0].message).toEqual('Invalid input: expected one of "Tuna"|"Trout"');
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"Tuna",
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid option: expected one of \\"Tuna\\"|\\"Trout\\""
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("nativeEnum default error message", () => {
|
||||
enum Fish {
|
||||
Tuna = "Tuna",
|
||||
Trout = "Trout",
|
||||
}
|
||||
const result = z.nativeEnum(Fish).safeParse("Salmon");
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
// expect(result.error!.issues[0].message).toEqual('Invalid input: expected one of "Tuna"|"Trout"');
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"Tuna",
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid option: expected one of \\"Tuna\\"|\\"Trout\\""
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("enum with message returns the custom error message", () => {
|
||||
const schema = z.enum(["apple", "banana"], {
|
||||
message: "the value provided is invalid",
|
||||
});
|
||||
|
||||
const result1 = schema.safeParse("berries");
|
||||
expect(result1.success).toEqual(false);
|
||||
if (!result1.success) {
|
||||
expect(result1.error.issues[0].message).toEqual("the value provided is invalid");
|
||||
}
|
||||
|
||||
const result2 = schema.safeParse(undefined);
|
||||
expect(result2.success).toEqual(false);
|
||||
if (!result2.success) {
|
||||
expect(result2.error.issues[0].message).toEqual("the value provided is invalid");
|
||||
}
|
||||
|
||||
const result3 = schema.safeParse("banana");
|
||||
expect(result3.success).toEqual(true);
|
||||
|
||||
const result4 = schema.safeParse(null);
|
||||
expect(result4.success).toEqual(false);
|
||||
if (!result4.success) {
|
||||
expect(result4.error.issues[0].message).toEqual("the value provided is invalid");
|
||||
}
|
||||
});
|
||||
|
||||
test("enum with diagonal keys", () => {
|
||||
const schema_02 = z.enum({
|
||||
A: 1,
|
||||
B: "A",
|
||||
});
|
||||
|
||||
expect(schema_02.safeParse("A")).toMatchObject({ success: true });
|
||||
});
|
||||
595
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/error-utils.test.ts
generated
vendored
Normal file
595
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/error-utils.test.ts
generated
vendored
Normal file
@@ -0,0 +1,595 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
declare const iss: z.core.$ZodIssueCode;
|
||||
|
||||
const Test = z.object({
|
||||
f1: z.number(),
|
||||
f2: z.string().optional(),
|
||||
f3: z.string().nullable(),
|
||||
f4: z.array(z.object({ t: z.union([z.string(), z.boolean()]) })),
|
||||
});
|
||||
// type TestFlattenedErrors = core.inferFlattenedErrors<typeof Test, { message: string; code: number }>;
|
||||
// type TestFormErrors = core.inferFlattenedErrors<typeof Test>;
|
||||
const parsed = Test.safeParse({});
|
||||
|
||||
test("regular error", () => {
|
||||
expect(parsed).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"f1"
|
||||
],
|
||||
"message": "Invalid input: expected number, received undefined"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"f3"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
},
|
||||
{
|
||||
"expected": "array",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"f4"
|
||||
],
|
||||
"message": "Invalid input: expected array, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test(".flatten()", () => {
|
||||
const flattened = parsed.error!.flatten();
|
||||
// flattened.
|
||||
expectTypeOf(flattened).toMatchTypeOf<{
|
||||
formErrors: string[];
|
||||
fieldErrors: {
|
||||
f2?: string[];
|
||||
f1?: string[];
|
||||
f3?: string[];
|
||||
f4?: string[];
|
||||
};
|
||||
}>();
|
||||
|
||||
expect(flattened).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"f1": [
|
||||
"Invalid input: expected number, received undefined",
|
||||
],
|
||||
"f3": [
|
||||
"Invalid input: expected string, received undefined",
|
||||
],
|
||||
"f4": [
|
||||
"Invalid input: expected array, received undefined",
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("custom .flatten()", () => {
|
||||
type ErrorType = { message: string; code: number };
|
||||
const flattened = parsed.error!.flatten((iss) => ({ message: iss.message, code: 1234 }));
|
||||
expectTypeOf(flattened).toMatchTypeOf<{
|
||||
formErrors: ErrorType[];
|
||||
fieldErrors: {
|
||||
f2?: ErrorType[];
|
||||
f1?: ErrorType[];
|
||||
f3?: ErrorType[];
|
||||
f4?: ErrorType[];
|
||||
};
|
||||
}>();
|
||||
|
||||
expect(flattened).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"f1": [
|
||||
{
|
||||
"code": 1234,
|
||||
"message": "Invalid input: expected number, received undefined",
|
||||
},
|
||||
],
|
||||
"f3": [
|
||||
{
|
||||
"code": 1234,
|
||||
"message": "Invalid input: expected string, received undefined",
|
||||
},
|
||||
],
|
||||
"f4": [
|
||||
{
|
||||
"code": 1234,
|
||||
"message": "Invalid input: expected array, received undefined",
|
||||
},
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test(".format()", () => {
|
||||
const formatted = parsed.error!.format();
|
||||
expectTypeOf(formatted).toMatchTypeOf<{
|
||||
_errors: string[];
|
||||
f2?: { _errors: string[] };
|
||||
f1?: { _errors: string[] };
|
||||
f3?: { _errors: string[] };
|
||||
f4?: {
|
||||
[x: number]: {
|
||||
_errors: string[];
|
||||
t?: {
|
||||
_errors: string[];
|
||||
};
|
||||
};
|
||||
_errors: string[];
|
||||
};
|
||||
}>();
|
||||
|
||||
expect(formatted).toMatchInlineSnapshot(`
|
||||
{
|
||||
"_errors": [],
|
||||
"f1": {
|
||||
"_errors": [
|
||||
"Invalid input: expected number, received undefined",
|
||||
],
|
||||
},
|
||||
"f3": {
|
||||
"_errors": [
|
||||
"Invalid input: expected string, received undefined",
|
||||
],
|
||||
},
|
||||
"f4": {
|
||||
"_errors": [
|
||||
"Invalid input: expected array, received undefined",
|
||||
],
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("custom .format()", () => {
|
||||
type ErrorType = { message: string; code: number };
|
||||
const formatted = parsed.error!.format((iss) => ({ message: iss.message, code: 1234 }));
|
||||
expectTypeOf(formatted).toMatchTypeOf<{
|
||||
_errors: ErrorType[];
|
||||
f2?: { _errors: ErrorType[] };
|
||||
f1?: { _errors: ErrorType[] };
|
||||
f3?: { _errors: ErrorType[] };
|
||||
f4?: {
|
||||
[x: number]: {
|
||||
_errors: ErrorType[];
|
||||
t?: {
|
||||
_errors: ErrorType[];
|
||||
};
|
||||
};
|
||||
_errors: ErrorType[];
|
||||
};
|
||||
}>();
|
||||
|
||||
expect(formatted).toMatchInlineSnapshot(`
|
||||
{
|
||||
"_errors": [],
|
||||
"f1": {
|
||||
"_errors": [
|
||||
{
|
||||
"code": 1234,
|
||||
"message": "Invalid input: expected number, received undefined",
|
||||
},
|
||||
],
|
||||
},
|
||||
"f3": {
|
||||
"_errors": [
|
||||
{
|
||||
"code": 1234,
|
||||
"message": "Invalid input: expected string, received undefined",
|
||||
},
|
||||
],
|
||||
},
|
||||
"f4": {
|
||||
"_errors": [
|
||||
{
|
||||
"code": 1234,
|
||||
"message": "Invalid input: expected array, received undefined",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("all errors", () => {
|
||||
const propertySchema = z.string();
|
||||
const schema = z
|
||||
.object({
|
||||
a: propertySchema,
|
||||
b: propertySchema,
|
||||
})
|
||||
.refine(
|
||||
(val) => {
|
||||
return val.a === val.b;
|
||||
},
|
||||
{ message: "Must be equal" }
|
||||
);
|
||||
|
||||
const r1 = schema.safeParse({
|
||||
a: "asdf",
|
||||
b: "qwer",
|
||||
});
|
||||
|
||||
expect(z.core.flattenError(r1.error!)).toEqual({
|
||||
formErrors: ["Must be equal"],
|
||||
fieldErrors: {},
|
||||
});
|
||||
|
||||
const r2 = schema.safeParse({
|
||||
a: null,
|
||||
b: null,
|
||||
});
|
||||
|
||||
// const error = _error as z.ZodError;
|
||||
expect(z.core.flattenError(r2.error!)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"a": [
|
||||
"Invalid input: expected string, received null",
|
||||
],
|
||||
"b": [
|
||||
"Invalid input: expected string, received null",
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
|
||||
expect(z.core.flattenError(r2.error!, (iss) => iss.message.toUpperCase())).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"a": [
|
||||
"INVALID INPUT: EXPECTED STRING, RECEIVED NULL",
|
||||
],
|
||||
"b": [
|
||||
"INVALID INPUT: EXPECTED STRING, RECEIVED NULL",
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
// Test identity
|
||||
|
||||
expect(z.core.flattenError(r2.error!, (i: z.ZodIssue) => i)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"a": [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received null",
|
||||
"path": [
|
||||
"a",
|
||||
],
|
||||
},
|
||||
],
|
||||
"b": [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received null",
|
||||
"path": [
|
||||
"b",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
|
||||
// Test mapping
|
||||
const f1 = z.core.flattenError(r2.error!, (i: z.ZodIssue) => i.message.length);
|
||||
expect(f1).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"a": [
|
||||
45,
|
||||
],
|
||||
"b": [
|
||||
45,
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
// expect(f1.fieldErrors.a![0]).toEqual("Invalid input: expected string".length);
|
||||
// expect(f1).toMatchObject({
|
||||
// formErrors: [],
|
||||
// fieldErrors: {
|
||||
// a: ["Invalid input: expected string".length],
|
||||
// b: ["Invalid input: expected string".length],
|
||||
// },
|
||||
// });
|
||||
});
|
||||
|
||||
const schema = z.strictObject({
|
||||
username: z.string().brand<"username">(),
|
||||
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,
|
||||
});
|
||||
|
||||
const tree = z.treeifyError(result.error!);
|
||||
|
||||
expectTypeOf(tree).toEqualTypeOf<{
|
||||
errors: string[];
|
||||
properties?: {
|
||||
username?: {
|
||||
errors: string[];
|
||||
};
|
||||
favoriteNumbers?: {
|
||||
errors: string[];
|
||||
items?: {
|
||||
errors: string[];
|
||||
}[];
|
||||
};
|
||||
nesting?: {
|
||||
errors: string[];
|
||||
properties?: {
|
||||
a?: {
|
||||
errors: string[];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}>();
|
||||
|
||||
test("z.treeifyError", () => {
|
||||
expect(tree).toMatchInlineSnapshot(`
|
||||
{
|
||||
"errors": [
|
||||
"Unrecognized key: "extra"",
|
||||
],
|
||||
"properties": {
|
||||
"favoriteNumbers": {
|
||||
"errors": [],
|
||||
"items": [
|
||||
,
|
||||
{
|
||||
"errors": [
|
||||
"Invalid input: expected number, received string",
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
"nesting": {
|
||||
"errors": [],
|
||||
"properties": {
|
||||
"a": {
|
||||
"errors": [
|
||||
"Invalid input: expected string, received number",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
"username": {
|
||||
"errors": [
|
||||
"Invalid input: expected string, received number",
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("z.treeifyError 2", () => {
|
||||
const schema = z.strictObject({
|
||||
name: z.string(),
|
||||
logLevel: z.union([z.string(), z.number()]),
|
||||
env: z.literal(["production", "development"]),
|
||||
});
|
||||
|
||||
const data = {
|
||||
name: 1000,
|
||||
logLevel: false,
|
||||
extra: 1000,
|
||||
};
|
||||
|
||||
const result = schema.safeParse(data);
|
||||
const err = z.treeifyError(result.error!);
|
||||
expect(err).toMatchInlineSnapshot(`
|
||||
{
|
||||
"errors": [
|
||||
"Unrecognized key: "extra"",
|
||||
],
|
||||
"properties": {
|
||||
"env": {
|
||||
"errors": [
|
||||
"Invalid option: expected one of "production"|"development"",
|
||||
],
|
||||
},
|
||||
"logLevel": {
|
||||
"errors": [
|
||||
"Invalid input: expected string, received boolean",
|
||||
"Invalid input: expected number, received boolean",
|
||||
],
|
||||
},
|
||||
"name": {
|
||||
"errors": [
|
||||
"Invalid input: expected string, received number",
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("z.prettifyError", () => {
|
||||
expect(z.prettifyError(result.error!)).toMatchInlineSnapshot(`
|
||||
"✖ Unrecognized key: "extra"
|
||||
✖ Invalid input: expected string, received number
|
||||
→ at username
|
||||
✖ Invalid input: expected number, received string
|
||||
→ at favoriteNumbers[1]
|
||||
✖ Invalid input: expected string, received number
|
||||
→ at nesting.a"
|
||||
`);
|
||||
});
|
||||
|
||||
test("z.toDotPath", () => {
|
||||
expect(z.core.toDotPath(["a", "b", 0, "c"])).toMatchInlineSnapshot(`"a.b[0].c"`);
|
||||
|
||||
expect(z.core.toDotPath(["a", Symbol("b"), 0, "c"])).toMatchInlineSnapshot(`"a["Symbol(b)"][0].c"`);
|
||||
|
||||
// Test with periods in keys
|
||||
expect(z.core.toDotPath(["user.name", "first.last"])).toMatchInlineSnapshot(`"["user.name"]["first.last"]"`);
|
||||
|
||||
// Test with special characters
|
||||
expect(z.core.toDotPath(["user", "$special", Symbol("#symbol")])).toMatchInlineSnapshot(
|
||||
`"user.$special["Symbol(#symbol)"]"`
|
||||
);
|
||||
|
||||
// Test with dots and quotes
|
||||
expect(z.core.toDotPath(["search", `query("foo.bar"="abc")`])).toMatchInlineSnapshot(
|
||||
`"search["query(\\"foo.bar\\"=\\"abc\\")"]"`
|
||||
);
|
||||
|
||||
// Test with newlines
|
||||
expect(z.core.toDotPath(["search", `foo\nbar`])).toMatchInlineSnapshot(`"search["foo\\nbar"]"`);
|
||||
|
||||
// Test with empty strings
|
||||
expect(z.core.toDotPath(["", "empty"])).toMatchInlineSnapshot(`".empty"`);
|
||||
|
||||
// Test with array indices
|
||||
expect(z.core.toDotPath(["items", 0, 1, 2])).toMatchInlineSnapshot(`"items[0][1][2]"`);
|
||||
|
||||
// Test with mixed path elements
|
||||
expect(z.core.toDotPath(["users", "user.config", 0, "settings.theme"])).toMatchInlineSnapshot(
|
||||
`"users["user.config"][0]["settings.theme"]"`
|
||||
);
|
||||
|
||||
// Test with square brackets in keys
|
||||
expect(z.core.toDotPath(["data[0]", "value"])).toMatchInlineSnapshot(`"["data[0]"].value"`);
|
||||
|
||||
// Test with empty path
|
||||
expect(z.core.toDotPath([])).toMatchInlineSnapshot(`""`);
|
||||
});
|
||||
|
||||
test("inheritance", () => {
|
||||
const e1 = new z.ZodError([]);
|
||||
expect(e1).toBeInstanceOf(z.core.$ZodError);
|
||||
expect(e1).toBeInstanceOf(z.ZodError);
|
||||
// expect(e1).not.toBeInstanceOf(Error);
|
||||
|
||||
const e2 = new z.ZodRealError([]);
|
||||
expect(e2).toBeInstanceOf(z.ZodError);
|
||||
expect(e2).toBeInstanceOf(z.ZodRealError);
|
||||
expect(e2).toBeInstanceOf(Error);
|
||||
});
|
||||
|
||||
test("disc union treeify/format", () => {
|
||||
const schema = z.discriminatedUnion(
|
||||
"foo",
|
||||
[
|
||||
z.object({
|
||||
foo: z.literal("x"),
|
||||
x: z.string(),
|
||||
}),
|
||||
z.object({
|
||||
foo: z.literal("y"),
|
||||
y: z.string(),
|
||||
}),
|
||||
],
|
||||
{
|
||||
error: "Invalid discriminator",
|
||||
}
|
||||
);
|
||||
|
||||
const error = schema.safeParse({ foo: "invalid" }).error;
|
||||
expect(z.treeifyError(error!)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"errors": [],
|
||||
"properties": {
|
||||
"foo": {
|
||||
"errors": [
|
||||
"Invalid discriminator",
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
`);
|
||||
expect(z.prettifyError(error!)).toMatchInlineSnapshot(`
|
||||
"✖ Invalid discriminator
|
||||
→ at foo"
|
||||
`);
|
||||
expect(z.formatError(error!)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"_errors": [],
|
||||
"foo": {
|
||||
"_errors": [
|
||||
"Invalid discriminator",
|
||||
],
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("update message after adding issues", () => {
|
||||
const e = new z.ZodError([]);
|
||||
e.addIssue({
|
||||
code: "custom",
|
||||
message: "message",
|
||||
input: "asdf",
|
||||
path: [],
|
||||
});
|
||||
expect(e.message).toMatchInlineSnapshot(`
|
||||
"[
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "message",
|
||||
"input": "asdf",
|
||||
"path": []
|
||||
}
|
||||
]"
|
||||
`);
|
||||
|
||||
e.addIssue({
|
||||
code: "custom",
|
||||
message: "message",
|
||||
input: "asdf",
|
||||
path: [],
|
||||
});
|
||||
expect(e.message).toMatchInlineSnapshot(`
|
||||
"[
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "message",
|
||||
"input": "asdf",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "message",
|
||||
"input": "asdf",
|
||||
"path": []
|
||||
}
|
||||
]"
|
||||
`);
|
||||
});
|
||||
711
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/error.test.ts
generated
vendored
Normal file
711
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/error.test.ts
generated
vendored
Normal file
@@ -0,0 +1,711 @@
|
||||
import { inspect } from "node:util";
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("error creation", () => {
|
||||
const err1 = new z.ZodError([]);
|
||||
|
||||
err1.issues.push({
|
||||
code: "invalid_type",
|
||||
expected: "object",
|
||||
path: [],
|
||||
message: "",
|
||||
input: "adf",
|
||||
});
|
||||
err1.isEmpty;
|
||||
|
||||
const err2 = new z.ZodError(err1.issues);
|
||||
const err3 = new z.ZodError([]);
|
||||
err3.addIssues(err1.issues);
|
||||
err3.addIssue(err1.issues[0]);
|
||||
err1.message;
|
||||
err2.message;
|
||||
err3.message;
|
||||
});
|
||||
|
||||
test("do not allow error and message together", () => {
|
||||
expect(() =>
|
||||
z.string().refine((_) => true, {
|
||||
message: "override",
|
||||
error: (iss) => (iss.input === undefined ? "asdf" : null),
|
||||
})
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
const errorMap: z.ZodErrorMap = (issue) => {
|
||||
if (issue.code === "invalid_type") {
|
||||
if (issue.expected === "string") {
|
||||
return { message: "bad type!" };
|
||||
}
|
||||
}
|
||||
if (issue.code === "custom") {
|
||||
return { message: `less-than-${issue.params?.minimum}` };
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
test("type error with custom error map", () => {
|
||||
const result = z.string().safeParse(234, { error: errorMap });
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "bad type!"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("refinement fail with params", () => {
|
||||
const result = z
|
||||
.number()
|
||||
.refine((val) => val >= 3, {
|
||||
params: { minimum: 3 },
|
||||
})
|
||||
.safeParse(2, { error: errorMap });
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"params": {
|
||||
"minimum": 3
|
||||
},
|
||||
"message": "less-than-3"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("hard coded error with custom errormap", () => {
|
||||
const result = z
|
||||
.string()
|
||||
.refine((val) => val.length > 12, {
|
||||
params: { minimum: 13 },
|
||||
message: "override",
|
||||
})
|
||||
.safeParse("asdf", { error: () => "contextual" });
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"params": {
|
||||
"minimum": 13
|
||||
},
|
||||
"message": "override"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("default error message", () => {
|
||||
const result = z
|
||||
.number()
|
||||
.refine((x) => x > 3)
|
||||
.safeParse(2);
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("override error in refine", () => {
|
||||
const result = z
|
||||
.number()
|
||||
.refine((x) => x > 3, "override")
|
||||
.safeParse(2);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "override"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("override error in refinement", () => {
|
||||
const result = z
|
||||
.number()
|
||||
.refine((x) => x > 3, {
|
||||
message: "override",
|
||||
})
|
||||
.safeParse(2);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "override"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("array minimum", () => {
|
||||
let result = z.array(z.string()).min(3, "tooshort").safeParse(["asdf", "qwer"]);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues[0].code).toEqual("too_small");
|
||||
expect(result.error!.issues[0].message).toEqual("tooshort");
|
||||
|
||||
result = z.array(z.string()).min(3).safeParse(["asdf", "qwer"]);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues[0].code).toEqual("too_small");
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"origin": "array",
|
||||
"code": "too_small",
|
||||
"minimum": 3,
|
||||
"inclusive": true,
|
||||
"path": [],
|
||||
"message": "Too small: expected array to have >=3 items"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("literal bigint default error message", () => {
|
||||
const result = z.literal(BigInt(12)).safeParse(BigInt(13));
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"12"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid input: expected 12n"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("custom path in custom error map", () => {
|
||||
const schema = z.object({
|
||||
items: z.array(z.string()).refine((data) => data.length > 3, {
|
||||
path: ["items-too-few"],
|
||||
}),
|
||||
});
|
||||
|
||||
const errorMap: z.ZodErrorMap = (issue) => {
|
||||
expect((issue.path ?? []).length).toBe(2);
|
||||
return { message: "doesnt matter" };
|
||||
};
|
||||
const result = schema.safeParse({ items: ["first"] }, { error: errorMap });
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"items",
|
||||
"items-too-few"
|
||||
],
|
||||
"message": "doesnt matter"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
// test("error metadata from value", () => {
|
||||
// const dynamicRefine = z.string().refine(
|
||||
// (val) => val === val.toUpperCase(),
|
||||
// (val) => ({ params: { val } })
|
||||
// );
|
||||
|
||||
// const result = dynamicRefine.safeParse("asdf");
|
||||
// expect(result.success).toEqual(false);
|
||||
// if (!result.success) {
|
||||
// const sub = result.error.issues[0];
|
||||
// expect(result.error.issues[0].code).toEqual("custom");
|
||||
// if (sub.code === "custom") {
|
||||
// expect(sub.params?.val).toEqual("asdf");
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("don't call refine after validation failed", () => {
|
||||
// const asdf = z
|
||||
// .union([
|
||||
// z.number(),
|
||||
// z.string().transform(z.number(), (val) => {
|
||||
// return parseFloat(val);
|
||||
// }),
|
||||
// ])
|
||||
// .refine((v) => v >= 1);
|
||||
|
||||
// expect(() => asdf.safeParse("foo")).not.toThrow();
|
||||
// });
|
||||
|
||||
test("root level formatting", () => {
|
||||
const schema = z.string().email();
|
||||
const result = schema.safeParse("asdfsdf");
|
||||
expect(result.success).toBe(false);
|
||||
|
||||
expect(result.error!.format()).toMatchInlineSnapshot(`
|
||||
{
|
||||
"_errors": [
|
||||
"Invalid email address",
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("custom path", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
password: z.string(),
|
||||
confirm: z.string(),
|
||||
})
|
||||
.refine((val) => val.confirm === val.password, { path: ["confirm"] });
|
||||
|
||||
const result = schema.safeParse({
|
||||
password: "peanuts",
|
||||
confirm: "qeanuts",
|
||||
});
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
const error = result.error!.format();
|
||||
expect(error._errors).toEqual([]);
|
||||
expect(error.password?._errors).toEqual(undefined);
|
||||
expect(error.confirm?._errors).toEqual(["Invalid input"]);
|
||||
});
|
||||
|
||||
test("custom path", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
password: z.string().min(6),
|
||||
confirm: z.string().min(6),
|
||||
})
|
||||
.refine((val) => val.confirm === val.password);
|
||||
|
||||
const result = schema.safeParse({
|
||||
password: "qwer",
|
||||
confirm: "asdf",
|
||||
});
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues.length).toEqual(3);
|
||||
});
|
||||
|
||||
const schema = z.object({
|
||||
inner: z.object({
|
||||
name: z
|
||||
.string()
|
||||
.refine((val) => val.length > 5)
|
||||
.array()
|
||||
.refine((val) => val.length <= 1),
|
||||
}),
|
||||
});
|
||||
|
||||
test("no abort early on refinements", () => {
|
||||
const invalidItem = {
|
||||
inner: { name: ["aasd", "asdfasdfasfd"] },
|
||||
};
|
||||
|
||||
const result1 = schema.safeParse(invalidItem);
|
||||
expect(result1.success).toBe(false);
|
||||
expect(result1.error!.issues.length).toEqual(2);
|
||||
});
|
||||
|
||||
test("detect issue with input fallback", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.transform((val) => val.length)
|
||||
.refine(() => false, { message: "always fails" })
|
||||
.refine(
|
||||
(val) => {
|
||||
if (typeof val !== "number") throw new Error();
|
||||
return (val ^ 2) > 10;
|
||||
} // should be number but it's a string
|
||||
);
|
||||
expect(() => schema.parse("hello")).toThrow(z.ZodError);
|
||||
});
|
||||
|
||||
test("formatting", () => {
|
||||
const invalidItem = {
|
||||
inner: { name: ["aasd", "asdfasdfasfd"] },
|
||||
};
|
||||
const invalidArray = {
|
||||
inner: { name: ["asdfasdf", "asdfasdfasfd"] },
|
||||
};
|
||||
const result1 = schema.safeParse(invalidItem);
|
||||
const result2 = schema.safeParse(invalidArray);
|
||||
|
||||
expect(result1.success).toBe(false);
|
||||
expect(result2.success).toBe(false);
|
||||
const error1 = result1.error!.format();
|
||||
expect(error1._errors).toEqual([]);
|
||||
expect(error1.inner?._errors).toEqual([]);
|
||||
expect(error1.inner?.name?.[1]).toEqual(undefined);
|
||||
|
||||
type FormattedError = z.inferFormattedError<typeof schema>;
|
||||
const error2: FormattedError = result2.error!.format();
|
||||
expect(error2._errors).toEqual([]);
|
||||
expect(error2.inner?._errors).toEqual([]);
|
||||
expect(error2.inner?.name?._errors).toEqual(["Invalid input"]);
|
||||
expect(error2.inner?.name?.[0]).toEqual(undefined);
|
||||
expect(error2.inner?.name?.[1]).toEqual(undefined);
|
||||
expect(error2.inner?.name?.[2]).toEqual(undefined);
|
||||
|
||||
// test custom mapper
|
||||
type FormattedErrorWithNumber = z.inferFormattedError<typeof schema, number>;
|
||||
const errorWithNumber: FormattedErrorWithNumber = result2.error!.format(() => 5);
|
||||
expect(errorWithNumber._errors).toEqual([]);
|
||||
expect(errorWithNumber.inner?._errors).toEqual([]);
|
||||
expect(errorWithNumber.inner?.name?._errors).toEqual([5]);
|
||||
});
|
||||
|
||||
test("formatting with nullable and optional fields", () => {
|
||||
const nameSchema = z.string().refine((val) => val.length > 5);
|
||||
const schema = z.object({
|
||||
nullableObject: z.object({ name: nameSchema }).nullable(),
|
||||
nullableArray: z.array(nameSchema).nullable(),
|
||||
nullableTuple: z.tuple([nameSchema, nameSchema, z.number()]).nullable(),
|
||||
optionalObject: z.object({ name: nameSchema }).optional(),
|
||||
optionalArray: z.array(nameSchema).optional(),
|
||||
optionalTuple: z.tuple([nameSchema, nameSchema, z.number()]).optional(),
|
||||
});
|
||||
const invalidItem = {
|
||||
nullableObject: { name: "abcd" },
|
||||
nullableArray: ["abcd"],
|
||||
nullableTuple: ["abcd", "abcd", 1],
|
||||
optionalObject: { name: "abcd" },
|
||||
optionalArray: ["abcd"],
|
||||
optionalTuple: ["abcd", "abcd", 1],
|
||||
};
|
||||
const result = schema.safeParse(invalidItem);
|
||||
expect(result.success).toBe(false);
|
||||
const error: z.inferFormattedError<typeof schema> = result.error!.format();
|
||||
expect(error._errors).toEqual([]);
|
||||
expect(error.nullableObject?._errors).toEqual([]);
|
||||
expect(error.nullableObject?.name?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.nullableArray?._errors).toEqual([]);
|
||||
expect(error.nullableArray?.[0]?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.nullableTuple?._errors).toEqual([]);
|
||||
expect(error.nullableTuple?.[0]?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.nullableTuple?.[1]?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.optionalObject?._errors).toEqual([]);
|
||||
expect(error.optionalObject?.name?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.optionalArray?._errors).toEqual([]);
|
||||
expect(error.optionalArray?.[0]?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.optionalTuple?._errors).toEqual([]);
|
||||
expect(error.optionalTuple?.[0]?._errors).toEqual(["Invalid input"]);
|
||||
expect(error.optionalTuple?.[1]?._errors).toEqual(["Invalid input"]);
|
||||
|
||||
expect(error).toMatchInlineSnapshot(`
|
||||
{
|
||||
"_errors": [],
|
||||
"nullableArray": {
|
||||
"0": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
"_errors": [],
|
||||
},
|
||||
"nullableObject": {
|
||||
"_errors": [],
|
||||
"name": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
},
|
||||
"nullableTuple": {
|
||||
"0": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
"1": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
"_errors": [],
|
||||
},
|
||||
"optionalArray": {
|
||||
"0": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
"_errors": [],
|
||||
},
|
||||
"optionalObject": {
|
||||
"_errors": [],
|
||||
"name": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
},
|
||||
"optionalTuple": {
|
||||
"0": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
"1": {
|
||||
"_errors": [
|
||||
"Invalid input",
|
||||
],
|
||||
},
|
||||
"_errors": [],
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("inferFlattenedErrors", () => {
|
||||
const schemaWithTransform = z.object({ foo: z.string() }).transform((o) => ({ bar: o.foo }));
|
||||
|
||||
const result = schemaWithTransform.safeParse({});
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
type ValidationErrors = z.inferFlattenedErrors<typeof schemaWithTransform>;
|
||||
const error: ValidationErrors = result.error!.flatten();
|
||||
expect(error).toMatchInlineSnapshot(`
|
||||
{
|
||||
"fieldErrors": {
|
||||
"foo": [
|
||||
"Invalid input: expected string, received undefined",
|
||||
],
|
||||
},
|
||||
"formErrors": [],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
const stringWithCustomError = z.string({
|
||||
error: () => "bound",
|
||||
});
|
||||
|
||||
test("schema-bound error map", () => {
|
||||
const result = stringWithCustomError.safeParse(1234);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues[0].message).toEqual("bound");
|
||||
});
|
||||
|
||||
test("bound error map overrides contextual", () => {
|
||||
// support contextual override
|
||||
const result = stringWithCustomError.safeParse(undefined, {
|
||||
error: () => ({ message: "override" }),
|
||||
});
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues[0].message).toEqual("bound");
|
||||
});
|
||||
|
||||
test("z.config customError ", () => {
|
||||
// support overrideErrorMap
|
||||
|
||||
z.config({ customError: () => ({ message: "override" }) });
|
||||
const result = stringWithCustomError.min(10).safeParse("tooshort");
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 10,
|
||||
"inclusive": true,
|
||||
"path": [],
|
||||
"message": "override"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
expect(result.error!.issues[0].message).toEqual("override");
|
||||
z.config({ customError: undefined });
|
||||
});
|
||||
|
||||
// test("invalid and required", () => {
|
||||
// const str = z.string({
|
||||
// invalid_type_error: "Invalid name",
|
||||
// required_error: "Name is required",
|
||||
// });
|
||||
// const result1 = str.safeParse(1234);
|
||||
// expect(result1.success).toBe(false);
|
||||
// if (!result1.success) {
|
||||
// expect(result1.error.issues[0].message).toEqual("Invalid name");
|
||||
// }
|
||||
// const result2 = str.safeParse(undefined);
|
||||
// expect(result2.success).toBe(false);
|
||||
// if (!result2.success) {
|
||||
// expect(result2.error.issues[0].message).toEqual("Name is required");
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("Fallback to default required error", () => {
|
||||
// const str = z.string({
|
||||
// invalid_type_error: "Invalid name",
|
||||
// // required_error: "Name is required",
|
||||
// });
|
||||
|
||||
// const result2 = str.safeParse(undefined);
|
||||
// expect(result2.success).toBe(false);
|
||||
// if (!result2.success) {
|
||||
// expect(result2.error.issues[0].message).toEqual("Required");
|
||||
// }
|
||||
// });
|
||||
|
||||
// test("invalid and required and errorMap", () => {
|
||||
// expect(() => {
|
||||
// return z.string({
|
||||
// invalid_type_error: "Invalid name",
|
||||
// required_error: "Name is required",
|
||||
// errorMap: () => ({ message: "override" }),
|
||||
// });
|
||||
// }).toThrow();
|
||||
// });
|
||||
|
||||
// test("strict error message", () => {
|
||||
// const errorMsg = "Invalid object";
|
||||
// const obj = z.object({ x: z.string() }).strict(errorMsg);
|
||||
// const result = obj.safeParse({ x: "a", y: "b" });
|
||||
// expect(result.success).toBe(false);
|
||||
// if (!result.success) {
|
||||
// expect(result.error.issues[0].message).toEqual(errorMsg);
|
||||
// }
|
||||
// });
|
||||
|
||||
test("empty string error message", () => {
|
||||
const schema = z.string().max(1, { message: "" });
|
||||
const result = schema.safeParse("asdf");
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error!.issues[0].message).toEqual("");
|
||||
});
|
||||
|
||||
test("dont short circuit on continuable errors", () => {
|
||||
const user = z
|
||||
.object({
|
||||
password: z.string().min(6),
|
||||
confirm: z.string(),
|
||||
})
|
||||
.refine((data) => data.password === data.confirm, {
|
||||
message: "Passwords don't match",
|
||||
path: ["confirm"],
|
||||
});
|
||||
const result = user.safeParse({ password: "asdf", confirm: "qwer" });
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 6,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"password"
|
||||
],
|
||||
"message": "Too small: expected string to have >=6 characters"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"confirm"
|
||||
],
|
||||
"message": "Passwords don't match"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
// expect(result.error!.issues.length).toEqual(2);
|
||||
});
|
||||
|
||||
test("string error params", () => {
|
||||
const a = z.string("Bad!");
|
||||
expect(a.safeParse(123).error!.issues[0].message).toBe("Bad!");
|
||||
|
||||
const b = z.string().min(5, "Too short!");
|
||||
expect(b.safeParse("abc").error!.issues[0].message).toBe("Too short!");
|
||||
|
||||
const c = z.uuid("Bad UUID!");
|
||||
expect(c.safeParse("not-a-uuid").error!.issues[0].message).toBe("Bad UUID!");
|
||||
|
||||
const d = z.string().datetime({ message: "Bad date!" });
|
||||
expect(d.safeParse("not-a-date").error!.issues[0].message).toBe("Bad date!");
|
||||
|
||||
const e = z.array(z.string(), "Bad array!");
|
||||
expect(e.safeParse("not-an-array").error!.issues[0].message).toBe("Bad array!");
|
||||
|
||||
const f = z.array(z.string()).min(5, "Too few items!");
|
||||
expect(f.safeParse(["a", "b"]).error!.issues[0].message).toBe("Too few items!");
|
||||
|
||||
const g = z.set(z.string(), "Bad set!");
|
||||
expect(g.safeParse("not-a-set").error!.issues[0].message).toBe("Bad set!");
|
||||
|
||||
const h = z.array(z.string(), "Bad array!");
|
||||
expect(h.safeParse(123).error!.issues[0].message).toBe("Bad array!");
|
||||
|
||||
const i = z.set(z.string(), "Bad set!");
|
||||
expect(i.safeParse(123).error!.issues[0].message).toBe("Bad set!");
|
||||
|
||||
const j = z.array(z.string(), "Bad array!");
|
||||
expect(j.safeParse(null).error!.issues[0].message).toBe("Bad array!");
|
||||
});
|
||||
|
||||
test("error inheritance", () => {
|
||||
const e1 = z.string().safeParse(123).error!;
|
||||
expect(e1).toBeInstanceOf(z.core.$ZodError);
|
||||
expect(e1).toBeInstanceOf(z.ZodError);
|
||||
expect(e1).toBeInstanceOf(z.ZodRealError);
|
||||
// expect(e1).not.toBeInstanceOf(Error);
|
||||
|
||||
try {
|
||||
z.string().parse(123);
|
||||
} catch (e2) {
|
||||
expect(e1).toBeInstanceOf(z.core.$ZodError);
|
||||
expect(e2).toBeInstanceOf(z.ZodError);
|
||||
expect(e2).toBeInstanceOf(z.ZodRealError);
|
||||
// expect(e2).toBeInstanceOf(Error);
|
||||
}
|
||||
});
|
||||
|
||||
test("error serialization", () => {
|
||||
try {
|
||||
z.string().parse(123);
|
||||
} catch (e) {
|
||||
expect(e).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
expect(inspect(e).split("\n").slice(0, 8).join("\n")).toMatchInlineSnapshot(`
|
||||
"ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]"
|
||||
`);
|
||||
}
|
||||
});
|
||||
96
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/file.test.ts
generated
vendored
Normal file
96
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/file.test.ts
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
import { File as WebFile } from "@web-std/file";
|
||||
|
||||
import { afterEach, beforeEach, expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const minCheck = z.file().min(5);
|
||||
const maxCheck = z.file().max(8);
|
||||
const mimeCheck = z.file().mime(["text/plain", "application/json"]);
|
||||
|
||||
const originalFile = global.File;
|
||||
beforeEach(async () => {
|
||||
if (!globalThis.File) globalThis.File = WebFile;
|
||||
});
|
||||
afterEach(() => {
|
||||
if (globalThis.File !== originalFile) {
|
||||
globalThis.File = originalFile;
|
||||
}
|
||||
});
|
||||
|
||||
test("passing validations", () => {
|
||||
minCheck.safeParse(new File(["12345"], "test.txt"));
|
||||
maxCheck.safeParse(new File(["12345678"], "test.txt"));
|
||||
mimeCheck.safeParse(new File([""], "test.csv", { type: "text/plain" }));
|
||||
expect(() => mimeCheck.parse(new File([""], "test.txt"))).toThrow();
|
||||
expect(() => mimeCheck.parse(new File([""], "test.txt", { type: "text/csv" }))).toThrow();
|
||||
});
|
||||
|
||||
test("types", () => {
|
||||
expectTypeOf(z.file().parse(new File([], "test.txt"))).toEqualTypeOf(new File([], "test.txt"));
|
||||
});
|
||||
|
||||
test("failing validations", () => {
|
||||
expect(minCheck.safeParse(new File(["1234"], "test.txt"))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "file",
|
||||
"code": "too_small",
|
||||
"minimum": 5,
|
||||
"inclusive": true,
|
||||
"path": [],
|
||||
"message": "Too small: expected file to have >=5 bytes"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(maxCheck.safeParse(new File(["123456789"], "test.txt"))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "file",
|
||||
"code": "too_big",
|
||||
"maximum": 8,
|
||||
"inclusive": true,
|
||||
"path": [],
|
||||
"message": "Too big: expected file to have <=8 bytes"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(mimeCheck.safeParse(new File([""], "test.csv"))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"text/plain",
|
||||
"application/json"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid option: expected one of \\"text/plain\\"|\\"application/json\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(mimeCheck.safeParse(new File([""], "test.csv", { type: "text/csv" }))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"text/plain",
|
||||
"application/json"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid option: expected one of \\"text/plain\\"|\\"application/json\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
179
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/firstparty.test.ts
generated
vendored
Normal file
179
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/firstparty.test.ts
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
import { expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
import type * as core from "zod/v4/core";
|
||||
|
||||
test("first party switch", () => {
|
||||
const myType = z.string() as core.$ZodTypes;
|
||||
const def = myType._zod.def;
|
||||
switch (def.type) {
|
||||
case "string":
|
||||
break;
|
||||
case "number":
|
||||
break;
|
||||
case "bigint":
|
||||
break;
|
||||
case "boolean":
|
||||
break;
|
||||
case "date":
|
||||
break;
|
||||
case "symbol":
|
||||
break;
|
||||
case "undefined":
|
||||
break;
|
||||
case "null":
|
||||
break;
|
||||
case "any":
|
||||
break;
|
||||
case "unknown":
|
||||
break;
|
||||
case "never":
|
||||
break;
|
||||
case "void":
|
||||
break;
|
||||
case "array":
|
||||
break;
|
||||
case "object":
|
||||
break;
|
||||
case "union":
|
||||
break;
|
||||
case "intersection":
|
||||
break;
|
||||
case "tuple":
|
||||
break;
|
||||
case "record":
|
||||
break;
|
||||
case "map":
|
||||
break;
|
||||
case "set":
|
||||
break;
|
||||
case "literal":
|
||||
break;
|
||||
case "enum":
|
||||
break;
|
||||
case "promise":
|
||||
break;
|
||||
case "optional":
|
||||
break;
|
||||
case "nonoptional":
|
||||
break;
|
||||
case "nullable":
|
||||
break;
|
||||
case "default":
|
||||
break;
|
||||
case "prefault":
|
||||
break;
|
||||
case "template_literal":
|
||||
break;
|
||||
case "custom":
|
||||
break;
|
||||
case "transform":
|
||||
break;
|
||||
case "readonly":
|
||||
break;
|
||||
case "nan":
|
||||
break;
|
||||
case "pipe":
|
||||
break;
|
||||
case "success":
|
||||
break;
|
||||
case "catch":
|
||||
break;
|
||||
case "file":
|
||||
break;
|
||||
case "lazy":
|
||||
break;
|
||||
case "function":
|
||||
break;
|
||||
default:
|
||||
expectTypeOf(def).toEqualTypeOf<never>();
|
||||
}
|
||||
});
|
||||
|
||||
test("$ZodSchemaTypes", () => {
|
||||
const type = "string" as core.$ZodTypeDef["type"];
|
||||
switch (type) {
|
||||
case "string":
|
||||
break;
|
||||
case "number":
|
||||
break;
|
||||
case "int":
|
||||
break;
|
||||
case "bigint":
|
||||
break;
|
||||
case "boolean":
|
||||
break;
|
||||
case "date":
|
||||
break;
|
||||
case "symbol":
|
||||
break;
|
||||
case "undefined":
|
||||
break;
|
||||
case "null":
|
||||
break;
|
||||
case "any":
|
||||
break;
|
||||
case "unknown":
|
||||
break;
|
||||
case "never":
|
||||
break;
|
||||
case "void":
|
||||
break;
|
||||
case "array":
|
||||
break;
|
||||
case "object":
|
||||
break;
|
||||
case "union":
|
||||
break;
|
||||
case "intersection":
|
||||
break;
|
||||
case "tuple":
|
||||
break;
|
||||
case "record":
|
||||
break;
|
||||
case "map":
|
||||
break;
|
||||
case "set":
|
||||
break;
|
||||
case "literal":
|
||||
break;
|
||||
case "enum":
|
||||
break;
|
||||
case "promise":
|
||||
break;
|
||||
case "optional":
|
||||
break;
|
||||
case "nonoptional":
|
||||
break;
|
||||
case "nullable":
|
||||
break;
|
||||
case "default":
|
||||
break;
|
||||
case "prefault":
|
||||
break;
|
||||
case "template_literal":
|
||||
break;
|
||||
case "custom":
|
||||
break;
|
||||
case "transform":
|
||||
break;
|
||||
case "readonly":
|
||||
break;
|
||||
case "nan":
|
||||
break;
|
||||
case "pipe":
|
||||
break;
|
||||
case "success":
|
||||
break;
|
||||
case "catch":
|
||||
break;
|
||||
case "file":
|
||||
break;
|
||||
case "lazy":
|
||||
break;
|
||||
case "function":
|
||||
break;
|
||||
|
||||
default:
|
||||
expectTypeOf(type).toEqualTypeOf<never>();
|
||||
}
|
||||
});
|
||||
26
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/fix-json-issue.test.ts
generated
vendored
Normal file
26
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/fix-json-issue.test.ts
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import { expect, test } from "vitest";
|
||||
import { type infer as _infer, json, nullable, object, pipe, transform } from "../../mini/index.js";
|
||||
// biome-ignore lint/correctness/noUnusedImports: This import verifies the type is exported
|
||||
import type { _ZodMiniJSONSchema } from "../../mini/schemas.js";
|
||||
|
||||
const DataType = object({
|
||||
data: json(),
|
||||
});
|
||||
type DataType = _infer<typeof DataType>;
|
||||
|
||||
// biome-ignore lint/suspicious/noExportsInTest: This export is required to reproduce TS4023
|
||||
export const Container = object({
|
||||
contained: pipe(
|
||||
nullable(DataType),
|
||||
transform<DataType | null>(
|
||||
(v) =>
|
||||
v ?? {
|
||||
data: "",
|
||||
}
|
||||
)
|
||||
),
|
||||
});
|
||||
|
||||
test("issue reproduction should compile without type errors", () => {
|
||||
expect(Container).toBeDefined();
|
||||
});
|
||||
734
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/from-json-schema.test.ts
generated
vendored
Normal file
734
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/from-json-schema.test.ts
generated
vendored
Normal file
@@ -0,0 +1,734 @@
|
||||
import { expect, test } from "vitest";
|
||||
import { fromJSONSchema } from "../from-json-schema.js";
|
||||
import * as z from "../index.js";
|
||||
|
||||
test("basic string schema", () => {
|
||||
const schema = fromJSONSchema({ type: "string" });
|
||||
expect(schema.parse("hello")).toBe("hello");
|
||||
expect(() => schema.parse(123)).toThrow();
|
||||
});
|
||||
|
||||
test("string with constraints", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "string",
|
||||
minLength: 3,
|
||||
maxLength: 10,
|
||||
pattern: "^[a-z]+$",
|
||||
});
|
||||
expect(schema.parse("hello")).toBe("hello");
|
||||
expect(schema.parse("helloworld")).toBe("helloworld"); // exactly 10 chars - valid
|
||||
expect(() => schema.parse("hi")).toThrow(); // too short
|
||||
expect(() => schema.parse("helloworld1")).toThrow(); // too long (11 chars)
|
||||
expect(() => schema.parse("Hello")).toThrow(); // pattern mismatch
|
||||
});
|
||||
|
||||
test("pattern is not implicitly anchored", () => {
|
||||
// JSON Schema patterns match anywhere in the string, not just the full string
|
||||
const schema = fromJSONSchema({
|
||||
type: "string",
|
||||
pattern: "foo",
|
||||
});
|
||||
expect(schema.parse("foo")).toBe("foo");
|
||||
expect(schema.parse("foobar")).toBe("foobar"); // matches at start
|
||||
expect(schema.parse("barfoo")).toBe("barfoo"); // matches at end
|
||||
expect(schema.parse("barfoobar")).toBe("barfoobar"); // matches in middle
|
||||
expect(() => schema.parse("bar")).toThrow(); // no match
|
||||
});
|
||||
|
||||
test("number schema", () => {
|
||||
const schema = fromJSONSchema({ type: "number" });
|
||||
expect(schema.parse(42)).toBe(42);
|
||||
expect(() => schema.parse("42")).toThrow();
|
||||
});
|
||||
|
||||
test("number with constraints", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "number",
|
||||
minimum: 0,
|
||||
maximum: 100,
|
||||
multipleOf: 5,
|
||||
});
|
||||
expect(schema.parse(50)).toBe(50);
|
||||
expect(() => schema.parse(-1)).toThrow();
|
||||
expect(() => schema.parse(101)).toThrow();
|
||||
expect(() => schema.parse(47)).toThrow(); // not multiple of 5
|
||||
});
|
||||
|
||||
test("integer schema", () => {
|
||||
const schema = fromJSONSchema({ type: "integer" });
|
||||
expect(schema.parse(42)).toBe(42);
|
||||
expect(() => schema.parse(42.5)).toThrow();
|
||||
});
|
||||
|
||||
test("boolean schema", () => {
|
||||
const schema = fromJSONSchema({ type: "boolean" });
|
||||
expect(schema.parse(true)).toBe(true);
|
||||
expect(schema.parse(false)).toBe(false);
|
||||
expect(() => schema.parse("true")).toThrow();
|
||||
});
|
||||
|
||||
test("null schema", () => {
|
||||
const schema = fromJSONSchema({ type: "null" });
|
||||
expect(schema.parse(null)).toBe(null);
|
||||
expect(() => schema.parse(undefined)).toThrow();
|
||||
});
|
||||
|
||||
test("object schema", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "object",
|
||||
properties: {
|
||||
name: { type: "string" },
|
||||
age: { type: "number" },
|
||||
},
|
||||
required: ["name"],
|
||||
});
|
||||
expect(schema.parse({ name: "John", age: 30 })).toEqual({ name: "John", age: 30 });
|
||||
expect(schema.parse({ name: "John" })).toEqual({ name: "John" });
|
||||
expect(() => schema.parse({ age: 30 })).toThrow(); // missing required
|
||||
});
|
||||
|
||||
test("object with additionalProperties false", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "object",
|
||||
properties: {
|
||||
name: { type: "string" },
|
||||
},
|
||||
additionalProperties: false,
|
||||
});
|
||||
expect(schema.parse({ name: "John" })).toEqual({ name: "John" });
|
||||
expect(() => schema.parse({ name: "John", extra: "field" })).toThrow();
|
||||
});
|
||||
|
||||
test("array schema", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "array",
|
||||
items: { type: "string" },
|
||||
});
|
||||
expect(schema.parse(["a", "b", "c"])).toEqual(["a", "b", "c"]);
|
||||
expect(() => schema.parse([1, 2, 3])).toThrow();
|
||||
});
|
||||
|
||||
test("array with constraints", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "array",
|
||||
items: { type: "number" },
|
||||
minItems: 2,
|
||||
maxItems: 4,
|
||||
});
|
||||
expect(schema.parse([1, 2])).toEqual([1, 2]);
|
||||
expect(schema.parse([1, 2, 3, 4])).toEqual([1, 2, 3, 4]);
|
||||
expect(() => schema.parse([1])).toThrow();
|
||||
expect(() => schema.parse([1, 2, 3, 4, 5])).toThrow();
|
||||
});
|
||||
|
||||
test("tuple with prefixItems (draft-2020-12)", () => {
|
||||
const schema = fromJSONSchema({
|
||||
$schema: "https://json-schema.org/draft/2020-12/schema",
|
||||
type: "array",
|
||||
prefixItems: [{ type: "string" }, { type: "number" }],
|
||||
});
|
||||
expect(schema.parse(["hello", 42])).toEqual(["hello", 42]);
|
||||
expect(() => schema.parse(["hello"])).toThrow();
|
||||
expect(() => schema.parse(["hello", "world"])).toThrow();
|
||||
});
|
||||
|
||||
test("tuple with items array (draft-7)", () => {
|
||||
const schema = fromJSONSchema({
|
||||
$schema: "http://json-schema.org/draft-07/schema#",
|
||||
type: "array",
|
||||
items: [{ type: "string" }, { type: "number" }],
|
||||
additionalItems: false,
|
||||
});
|
||||
expect(schema.parse(["hello", 42])).toEqual(["hello", 42]);
|
||||
expect(() => schema.parse(["hello", 42, "extra"])).toThrow();
|
||||
});
|
||||
|
||||
test("enum schema", () => {
|
||||
const schema = fromJSONSchema({
|
||||
enum: ["red", "green", "blue"],
|
||||
});
|
||||
expect(schema.parse("red")).toBe("red");
|
||||
expect(() => schema.parse("yellow")).toThrow();
|
||||
});
|
||||
|
||||
test("const schema", () => {
|
||||
const schema = fromJSONSchema({
|
||||
const: "hello",
|
||||
});
|
||||
expect(schema.parse("hello")).toBe("hello");
|
||||
expect(() => schema.parse("world")).toThrow();
|
||||
});
|
||||
|
||||
test("anyOf schema", () => {
|
||||
const schema = fromJSONSchema({
|
||||
anyOf: [{ type: "string" }, { type: "number" }],
|
||||
});
|
||||
expect(schema.parse("hello")).toBe("hello");
|
||||
expect(schema.parse(42)).toBe(42);
|
||||
expect(() => schema.parse(true)).toThrow();
|
||||
});
|
||||
|
||||
test("allOf schema", () => {
|
||||
const schema = fromJSONSchema({
|
||||
allOf: [
|
||||
{ type: "object", properties: { name: { type: "string" } }, required: ["name"] },
|
||||
{ type: "object", properties: { age: { type: "number" } }, required: ["age"] },
|
||||
],
|
||||
});
|
||||
const result = schema.parse({ name: "John", age: 30 }) as { name: string; age: number };
|
||||
expect(result.name).toBe("John");
|
||||
expect(result.age).toBe(30);
|
||||
});
|
||||
|
||||
test("allOf with empty array", () => {
|
||||
// Empty allOf without explicit type returns any
|
||||
const schema1 = fromJSONSchema({
|
||||
allOf: [],
|
||||
});
|
||||
expect(schema1.parse("hello")).toBe("hello");
|
||||
expect(schema1.parse(123)).toBe(123);
|
||||
expect(schema1.parse({})).toEqual({});
|
||||
|
||||
// Empty allOf with explicit type returns base schema
|
||||
const schema2 = fromJSONSchema({
|
||||
type: "string",
|
||||
allOf: [],
|
||||
});
|
||||
expect(schema2.parse("hello")).toBe("hello");
|
||||
expect(() => schema2.parse(123)).toThrow();
|
||||
});
|
||||
|
||||
test("oneOf schema (exclusive union)", () => {
|
||||
const schema = fromJSONSchema({
|
||||
oneOf: [{ type: "string" }, { type: "number" }],
|
||||
});
|
||||
expect(schema.parse("hello")).toBe("hello");
|
||||
expect(schema.parse(42)).toBe(42);
|
||||
expect(() => schema.parse(true)).toThrow();
|
||||
});
|
||||
|
||||
test("type with anyOf creates intersection", () => {
|
||||
// type: string AND (type:string,minLength:5 OR type:string,pattern:^a)
|
||||
const schema = fromJSONSchema({
|
||||
type: "string",
|
||||
anyOf: [
|
||||
{ type: "string", minLength: 5 },
|
||||
{ type: "string", pattern: "^a" },
|
||||
],
|
||||
});
|
||||
// Should pass: string AND (minLength:5 OR pattern:^a) - matches minLength
|
||||
expect(schema.parse("hello")).toBe("hello");
|
||||
// Should pass: string AND (minLength:5 OR pattern:^a) - matches pattern
|
||||
expect(schema.parse("abc")).toBe("abc");
|
||||
// Should fail: string but neither minLength nor pattern match
|
||||
expect(() => schema.parse("hi")).toThrow();
|
||||
// Should fail: not a string
|
||||
expect(() => schema.parse(123)).toThrow();
|
||||
});
|
||||
|
||||
test("type with oneOf creates intersection", () => {
|
||||
// type: string AND (exactly one of: type:string,minLength:5 OR type:string,pattern:^a)
|
||||
const schema = fromJSONSchema({
|
||||
type: "string",
|
||||
oneOf: [
|
||||
{ type: "string", minLength: 5 },
|
||||
{ type: "string", pattern: "^a" },
|
||||
],
|
||||
});
|
||||
// Should pass: string AND minLength:5 (exactly one match - "hello" length 5 >= 5, doesn't start with 'a')
|
||||
expect(schema.parse("hello")).toBe("hello");
|
||||
// Should pass: string AND pattern:^a (exactly one match - "abc" starts with 'a', length 3 < 5)
|
||||
expect(schema.parse("abc")).toBe("abc");
|
||||
// Should fail: string but neither match
|
||||
expect(() => schema.parse("hi")).toThrow();
|
||||
// Should fail: not a string
|
||||
expect(() => schema.parse(123)).toThrow();
|
||||
// Should fail: matches both (length >= 5 AND starts with 'a') - exclusive union fails
|
||||
expect(() => schema.parse("apple")).toThrow();
|
||||
});
|
||||
|
||||
test("unevaluatedItems throws error", () => {
|
||||
expect(() => {
|
||||
fromJSONSchema({
|
||||
type: "array",
|
||||
unevaluatedItems: false,
|
||||
});
|
||||
}).toThrow("unevaluatedItems is not supported");
|
||||
});
|
||||
|
||||
test("unevaluatedProperties throws error", () => {
|
||||
expect(() => {
|
||||
fromJSONSchema({
|
||||
type: "object",
|
||||
unevaluatedProperties: false,
|
||||
});
|
||||
}).toThrow("unevaluatedProperties is not supported");
|
||||
});
|
||||
|
||||
test("if/then/else throws error", () => {
|
||||
expect(() => {
|
||||
fromJSONSchema({
|
||||
if: { type: "string" },
|
||||
then: { type: "number" },
|
||||
});
|
||||
}).toThrow("Conditional schemas");
|
||||
});
|
||||
|
||||
test("external $ref throws error", () => {
|
||||
expect(() => {
|
||||
fromJSONSchema({
|
||||
$ref: "https://example.com/schema#/definitions/User",
|
||||
});
|
||||
}).toThrow("External $ref is not supported");
|
||||
});
|
||||
|
||||
test("local $ref resolution", () => {
|
||||
const schema = fromJSONSchema({
|
||||
$defs: {
|
||||
User: {
|
||||
type: "object",
|
||||
properties: {
|
||||
name: { type: "string" },
|
||||
},
|
||||
required: ["name"],
|
||||
},
|
||||
},
|
||||
$ref: "#/$defs/User",
|
||||
});
|
||||
expect(schema.parse({ name: "John" })).toEqual({ name: "John" });
|
||||
expect(() => schema.parse({})).toThrow();
|
||||
});
|
||||
|
||||
test("circular $ref with lazy", () => {
|
||||
const schema = fromJSONSchema({
|
||||
$defs: {
|
||||
Node: {
|
||||
type: "object",
|
||||
properties: {
|
||||
value: { type: "string" },
|
||||
children: {
|
||||
type: "array",
|
||||
items: { $ref: "#/$defs/Node" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
$ref: "#/$defs/Node",
|
||||
});
|
||||
type Node = { value: string; children: Node[] };
|
||||
const result = schema.parse({
|
||||
value: "root",
|
||||
children: [{ value: "child", children: [] }],
|
||||
}) as Node;
|
||||
expect(result.value).toBe("root");
|
||||
expect(result.children[0]?.value).toBe("child");
|
||||
});
|
||||
|
||||
test("patternProperties", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "object",
|
||||
patternProperties: {
|
||||
"^S_": { type: "string" },
|
||||
},
|
||||
});
|
||||
const result = schema.parse({ S_name: "John", S_age: "30" }) as Record<string, string>;
|
||||
expect(result.S_name).toBe("John");
|
||||
expect(result.S_age).toBe("30");
|
||||
});
|
||||
|
||||
test("patternProperties with regular properties", () => {
|
||||
// Note: When patternProperties is combined with properties, the intersection
|
||||
// validates all keys against the pattern. This test uses a pattern that
|
||||
// matches the regular property name as well.
|
||||
const schema = fromJSONSchema({
|
||||
type: "object",
|
||||
properties: {
|
||||
S_name: { type: "string" },
|
||||
},
|
||||
patternProperties: {
|
||||
"^S_": { type: "string" },
|
||||
},
|
||||
required: ["S_name"],
|
||||
});
|
||||
const result = schema.parse({ S_name: "John", S_extra: "value" }) as Record<string, string>;
|
||||
expect(result.S_name).toBe("John");
|
||||
expect(result.S_extra).toBe("value");
|
||||
});
|
||||
|
||||
test("multiple patternProperties", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "object",
|
||||
patternProperties: {
|
||||
"^S_": { type: "string" },
|
||||
"^N_": { type: "number" },
|
||||
},
|
||||
});
|
||||
const result = schema.parse({ S_name: "John", N_count: 123 }) as Record<string, string | number>;
|
||||
expect(result.S_name).toBe("John");
|
||||
expect(result.N_count).toBe(123);
|
||||
// Keys not matching any pattern should pass through
|
||||
const result2 = schema.parse({ S_name: "John", N_count: 123, other: "value" }) as Record<string, string | number>;
|
||||
expect(result2.other).toBe("value");
|
||||
});
|
||||
|
||||
test("multiple overlapping patternProperties", () => {
|
||||
// If a key matches multiple patterns, value must satisfy all schemas
|
||||
const schema = fromJSONSchema({
|
||||
type: "object",
|
||||
patternProperties: {
|
||||
"^S_": { type: "string" },
|
||||
"^S_N": { type: "string", minLength: 3 },
|
||||
},
|
||||
});
|
||||
// S_name matches ^S_ but not ^S_N
|
||||
expect(schema.parse({ S_name: "John" })).toEqual({ S_name: "John" });
|
||||
// S_N matches both patterns - must satisfy both (string with minLength 3)
|
||||
expect(schema.parse({ S_N: "abc" })).toEqual({ S_N: "abc" });
|
||||
expect(() => schema.parse({ S_N: "ab" })).toThrow(); // too short for ^S_N pattern
|
||||
});
|
||||
|
||||
test("default value", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "string",
|
||||
default: "hello",
|
||||
});
|
||||
// Default is applied during parsing if value is missing/undefined
|
||||
// This depends on Zod's default behavior
|
||||
expect(schema.parse("world")).toBe("world");
|
||||
});
|
||||
|
||||
test("description metadata", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "string",
|
||||
description: "A string value",
|
||||
});
|
||||
expect(schema.parse("hello")).toBe("hello");
|
||||
});
|
||||
|
||||
test("version detection - draft-2020-12", () => {
|
||||
const schema = fromJSONSchema({
|
||||
$schema: "https://json-schema.org/draft/2020-12/schema",
|
||||
type: "array",
|
||||
prefixItems: [{ type: "string" }],
|
||||
});
|
||||
expect(schema.parse(["hello"])).toEqual(["hello"]);
|
||||
});
|
||||
|
||||
test("version detection - draft-7", () => {
|
||||
const schema = fromJSONSchema({
|
||||
$schema: "http://json-schema.org/draft-07/schema#",
|
||||
type: "array",
|
||||
items: [{ type: "string" }],
|
||||
});
|
||||
expect(schema.parse(["hello"])).toEqual(["hello"]);
|
||||
});
|
||||
|
||||
test("version detection - draft-4", () => {
|
||||
const schema = fromJSONSchema({
|
||||
$schema: "http://json-schema.org/draft-04/schema#",
|
||||
type: "array",
|
||||
items: [{ type: "string" }],
|
||||
});
|
||||
expect(schema.parse(["hello"])).toEqual(["hello"]);
|
||||
});
|
||||
|
||||
test("default version (draft-2020-12)", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "array",
|
||||
prefixItems: [{ type: "string" }],
|
||||
});
|
||||
expect(schema.parse(["hello"])).toEqual(["hello"]);
|
||||
});
|
||||
|
||||
test("string format - email", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "string",
|
||||
format: "email",
|
||||
});
|
||||
expect(schema.parse("test@example.com")).toBe("test@example.com");
|
||||
});
|
||||
|
||||
test("string format - uuid", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "string",
|
||||
format: "uuid",
|
||||
});
|
||||
const uuid = "550e8400-e29b-41d4-a716-446655440000";
|
||||
expect(schema.parse(uuid)).toBe(uuid);
|
||||
});
|
||||
|
||||
test("exclusiveMinimum and exclusiveMaximum", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "number",
|
||||
exclusiveMinimum: 0,
|
||||
exclusiveMaximum: 100,
|
||||
});
|
||||
expect(schema.parse(50)).toBe(50);
|
||||
expect(() => schema.parse(0)).toThrow();
|
||||
expect(() => schema.parse(100)).toThrow();
|
||||
});
|
||||
|
||||
test("boolean schema (true/false)", () => {
|
||||
const trueSchema = fromJSONSchema(true);
|
||||
expect(trueSchema.parse("anything")).toBe("anything");
|
||||
|
||||
const falseSchema = fromJSONSchema(false);
|
||||
expect(() => falseSchema.parse("anything")).toThrow();
|
||||
});
|
||||
|
||||
test("empty object schema", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "object",
|
||||
});
|
||||
expect(schema.parse({})).toEqual({});
|
||||
expect(schema.parse({ extra: "field" })).toEqual({ extra: "field" });
|
||||
});
|
||||
|
||||
test("array without items", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "array",
|
||||
});
|
||||
expect(schema.parse([1, "string", true])).toEqual([1, "string", true]);
|
||||
});
|
||||
|
||||
test("mixed enum types", () => {
|
||||
const schema = fromJSONSchema({
|
||||
enum: ["string", 42, true, null],
|
||||
});
|
||||
expect(schema.parse("string")).toBe("string");
|
||||
expect(schema.parse(42)).toBe(42);
|
||||
expect(schema.parse(true)).toBe(true);
|
||||
expect(schema.parse(null)).toBe(null);
|
||||
});
|
||||
|
||||
test("nullable in OpenAPI 3.0", () => {
|
||||
// General nullable case (not just enum: [null])
|
||||
const stringSchema = fromJSONSchema(
|
||||
{
|
||||
type: "string",
|
||||
nullable: true,
|
||||
},
|
||||
{ defaultTarget: "openapi-3.0" }
|
||||
);
|
||||
expect(stringSchema.parse("hello")).toBe("hello");
|
||||
expect(stringSchema.parse(null)).toBe(null);
|
||||
expect(() => stringSchema.parse(123)).toThrow();
|
||||
|
||||
const numberSchema = fromJSONSchema(
|
||||
{
|
||||
type: "number",
|
||||
nullable: true,
|
||||
},
|
||||
{ defaultTarget: "openapi-3.0" }
|
||||
);
|
||||
expect(numberSchema.parse(42)).toBe(42);
|
||||
expect(numberSchema.parse(null)).toBe(null);
|
||||
expect(() => numberSchema.parse("string")).toThrow();
|
||||
|
||||
const objectSchema = fromJSONSchema(
|
||||
{
|
||||
type: "object",
|
||||
properties: { name: { type: "string" } },
|
||||
nullable: true,
|
||||
},
|
||||
{ defaultTarget: "openapi-3.0" }
|
||||
);
|
||||
expect(objectSchema.parse({ name: "John" })).toEqual({ name: "John" });
|
||||
expect(objectSchema.parse(null)).toBe(null);
|
||||
});
|
||||
|
||||
// Metadata extraction tests
|
||||
|
||||
test("unrecognized keys stored in globalRegistry by default", () => {
|
||||
const schema = fromJSONSchema({
|
||||
type: "string",
|
||||
title: "My String",
|
||||
deprecated: true,
|
||||
examples: ["hello", "world"],
|
||||
"x-custom": "custom value",
|
||||
});
|
||||
|
||||
const meta = z.globalRegistry.get(schema);
|
||||
expect(meta).toBeDefined();
|
||||
expect(meta?.title).toBe("My String");
|
||||
expect(meta?.deprecated).toBe(true);
|
||||
expect(meta?.examples).toEqual(["hello", "world"]);
|
||||
expect((meta as any)?.["x-custom"]).toBe("custom value");
|
||||
|
||||
// Clean up
|
||||
z.globalRegistry.remove(schema);
|
||||
});
|
||||
|
||||
test("unrecognized keys stored in custom registry", () => {
|
||||
const customRegistry = z.registry<{ title?: string; deprecated?: boolean }>();
|
||||
|
||||
const schema = fromJSONSchema(
|
||||
{
|
||||
type: "number",
|
||||
title: "Age",
|
||||
deprecated: true,
|
||||
},
|
||||
{ registry: customRegistry }
|
||||
);
|
||||
|
||||
// Should be in custom registry
|
||||
const meta = customRegistry.get(schema);
|
||||
expect(meta).toBeDefined();
|
||||
expect(meta?.title).toBe("Age");
|
||||
expect(meta?.deprecated).toBe(true);
|
||||
|
||||
// Should NOT be in globalRegistry
|
||||
expect(z.globalRegistry.get(schema)).toBeUndefined();
|
||||
});
|
||||
|
||||
test("$id and id are captured as metadata", () => {
|
||||
const customRegistry = z.registry<{ $id?: string; id?: string }>();
|
||||
|
||||
const schema1 = fromJSONSchema(
|
||||
{
|
||||
$id: "https://example.com/schemas/user",
|
||||
type: "object",
|
||||
},
|
||||
{ registry: customRegistry }
|
||||
);
|
||||
expect(customRegistry.get(schema1)?.$id).toBe("https://example.com/schemas/user");
|
||||
|
||||
const schema2 = fromJSONSchema(
|
||||
{
|
||||
id: "legacy-id",
|
||||
type: "string",
|
||||
},
|
||||
{ registry: customRegistry }
|
||||
);
|
||||
expect(customRegistry.get(schema2)?.id).toBe("legacy-id");
|
||||
});
|
||||
|
||||
test("x-* extension keys are captured as metadata", () => {
|
||||
const customRegistry = z.registry<Record<string, unknown>>();
|
||||
|
||||
const schema = fromJSONSchema(
|
||||
{
|
||||
type: "string",
|
||||
"x-openapi-example": "example value",
|
||||
"x-internal": true,
|
||||
"x-tags": ["api", "public"],
|
||||
},
|
||||
{ registry: customRegistry }
|
||||
);
|
||||
|
||||
const meta = customRegistry.get(schema);
|
||||
expect(meta?.["x-openapi-example"]).toBe("example value");
|
||||
expect(meta?.["x-internal"]).toBe(true);
|
||||
expect(meta?.["x-tags"]).toEqual(["api", "public"]);
|
||||
});
|
||||
|
||||
test("metadata on nested schemas", () => {
|
||||
const customRegistry = z.registry<Record<string, unknown>>();
|
||||
|
||||
const parentSchema = fromJSONSchema(
|
||||
{
|
||||
type: "object",
|
||||
title: "User",
|
||||
properties: {
|
||||
name: {
|
||||
type: "string",
|
||||
title: "Name",
|
||||
"x-field-order": 1,
|
||||
},
|
||||
age: {
|
||||
type: "number",
|
||||
title: "Age",
|
||||
deprecated: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{ registry: customRegistry }
|
||||
);
|
||||
|
||||
// Verify parent schema has its metadata
|
||||
expect(customRegistry.get(parentSchema)?.title).toBe("User");
|
||||
|
||||
// We can't easily access nested schemas directly, but we can verify
|
||||
// the registry is being used correctly by checking a separate schema
|
||||
const simpleSchema = fromJSONSchema(
|
||||
{
|
||||
type: "string",
|
||||
title: "Simple",
|
||||
},
|
||||
{ registry: customRegistry }
|
||||
);
|
||||
expect(customRegistry.get(simpleSchema)?.title).toBe("Simple");
|
||||
});
|
||||
|
||||
test("no metadata added when no unrecognized keys", () => {
|
||||
const customRegistry = z.registry<Record<string, unknown>>();
|
||||
|
||||
const schema = fromJSONSchema(
|
||||
{
|
||||
type: "string",
|
||||
minLength: 1,
|
||||
maxLength: 100,
|
||||
description: "A regular string",
|
||||
},
|
||||
{ registry: customRegistry }
|
||||
);
|
||||
|
||||
// description is handled via .describe(), so it shouldn't be in metadata
|
||||
// All other keys are recognized, so no metadata should be added
|
||||
expect(customRegistry.get(schema)).toBeUndefined();
|
||||
});
|
||||
|
||||
test("writeOnly and examples are captured as metadata", () => {
|
||||
const customRegistry = z.registry<{ writeOnly?: boolean; examples?: unknown[] }>();
|
||||
|
||||
const schema = fromJSONSchema(
|
||||
{
|
||||
type: "string",
|
||||
writeOnly: true,
|
||||
examples: ["password123", "secret"],
|
||||
},
|
||||
{ registry: customRegistry }
|
||||
);
|
||||
|
||||
const meta = customRegistry.get(schema);
|
||||
expect(meta?.writeOnly).toBe(true);
|
||||
expect(meta?.examples).toEqual(["password123", "secret"]);
|
||||
});
|
||||
|
||||
test("$comment and $anchor are captured as metadata", () => {
|
||||
const customRegistry = z.registry<{ $comment?: string; $anchor?: string }>();
|
||||
|
||||
const schema = fromJSONSchema(
|
||||
{
|
||||
type: "string",
|
||||
$comment: "This is a developer note",
|
||||
$anchor: "my-anchor",
|
||||
},
|
||||
{ registry: customRegistry }
|
||||
);
|
||||
|
||||
const meta = customRegistry.get(schema);
|
||||
expect(meta?.$comment).toBe("This is a developer note");
|
||||
expect(meta?.$anchor).toBe("my-anchor");
|
||||
});
|
||||
|
||||
test("contentEncoding and contentMediaType are stored as metadata", () => {
|
||||
const customRegistry = z.registry<{ contentEncoding?: string; contentMediaType?: string }>();
|
||||
|
||||
const schema = fromJSONSchema(
|
||||
{
|
||||
type: "string",
|
||||
contentEncoding: "base64",
|
||||
contentMediaType: "image/png",
|
||||
},
|
||||
{ registry: customRegistry }
|
||||
);
|
||||
|
||||
// Should just be a string schema
|
||||
expect(schema.parse("aGVsbG8gd29ybGQ=")).toBe("aGVsbG8gd29ybGQ=");
|
||||
|
||||
// Content keywords should be in metadata
|
||||
const meta = customRegistry.get(schema);
|
||||
expect(meta?.contentEncoding).toBe("base64");
|
||||
expect(meta?.contentMediaType).toBe("image/png");
|
||||
});
|
||||
360
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/function.test.ts
generated
vendored
Normal file
360
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/function.test.ts
generated
vendored
Normal file
@@ -0,0 +1,360 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const args1 = z.tuple([z.string()]);
|
||||
const returns1 = z.number();
|
||||
const func1 = z.function({
|
||||
input: args1,
|
||||
|
||||
output: returns1,
|
||||
});
|
||||
|
||||
test("function parsing", () => {
|
||||
const parsed = func1.implement((arg: any) => arg.length);
|
||||
const result = parsed("asdf");
|
||||
expect(result).toBe(4);
|
||||
});
|
||||
|
||||
test("parsed function fail 1", () => {
|
||||
// @ts-expect-error
|
||||
const parsed = func1.implement((x: string) => x);
|
||||
expect(() => parsed("asdf")).toThrow();
|
||||
});
|
||||
|
||||
test("parsed function fail 2", () => {
|
||||
// @ts-expect-error
|
||||
const parsed = func1.implement((x: string) => x);
|
||||
expect(() => parsed(13 as any)).toThrow();
|
||||
});
|
||||
|
||||
test("function inference 1", () => {
|
||||
type func1 = (typeof func1)["_input"];
|
||||
expectTypeOf<func1>().toEqualTypeOf<(k: string) => number>();
|
||||
});
|
||||
|
||||
test("method parsing", () => {
|
||||
const methodObject = z.object({
|
||||
property: z.number(),
|
||||
method: z
|
||||
.function()
|
||||
.input(z.tuple([z.string()]))
|
||||
.output(z.number()),
|
||||
});
|
||||
const methodInstance = {
|
||||
property: 3,
|
||||
method: function (s: string) {
|
||||
return s.length + this.property;
|
||||
},
|
||||
};
|
||||
const parsed = methodObject.parse(methodInstance);
|
||||
expect(parsed.method("length=8")).toBe(11); // 8 length + 3 property
|
||||
});
|
||||
|
||||
test("async method parsing", async () => {
|
||||
const methodObject = z.object({
|
||||
property: z.number(),
|
||||
method: z.function().input([z.string()]).output(z.promise(z.number())),
|
||||
});
|
||||
const methodInstance = {
|
||||
property: 3,
|
||||
method: async function (s: string) {
|
||||
return s.length + this.property;
|
||||
},
|
||||
};
|
||||
const parsed = methodObject.parse(methodInstance);
|
||||
expect(await parsed.method("length=8")).toBe(11); // 8 length + 3 property
|
||||
});
|
||||
|
||||
test("args method", () => {
|
||||
const t1 = z.function();
|
||||
type t1 = (typeof t1)["_input"];
|
||||
expectTypeOf<t1>().toEqualTypeOf<(...args_1: never[]) => unknown>();
|
||||
t1._input;
|
||||
|
||||
const t2args = z.tuple([z.string()], z.unknown());
|
||||
|
||||
const t2 = t1.input(t2args);
|
||||
type t2 = (typeof t2)["_input"];
|
||||
expectTypeOf<t2>().toEqualTypeOf<(arg: string, ...args_1: unknown[]) => unknown>();
|
||||
|
||||
const t3 = t2.output(z.boolean());
|
||||
type t3 = (typeof t3)["_input"];
|
||||
expectTypeOf<t3>().toEqualTypeOf<(arg: string, ...args_1: unknown[]) => boolean>();
|
||||
});
|
||||
|
||||
// test("custom args", () => {
|
||||
// const fn = z.function().implement((_a: string, _b: number) => {
|
||||
// return new Date();
|
||||
// });
|
||||
|
||||
// expectTypeOf(fn).toEqualTypeOf<(a: string, b: number) => Date>();
|
||||
// });
|
||||
|
||||
const args2 = z.tuple([
|
||||
z.object({
|
||||
f1: z.number(),
|
||||
f2: z.string().nullable(),
|
||||
f3: z.array(z.boolean().optional()).optional(),
|
||||
}),
|
||||
]);
|
||||
const returns2 = z.union([z.string(), z.number()]);
|
||||
|
||||
const func2 = z.function({
|
||||
input: args2,
|
||||
output: returns2,
|
||||
});
|
||||
|
||||
test("function inference 2", () => {
|
||||
type func2 = (typeof func2)["_input"];
|
||||
|
||||
expectTypeOf<func2>().toEqualTypeOf<
|
||||
(arg: {
|
||||
f3?: (boolean | undefined)[] | undefined;
|
||||
f1: number;
|
||||
f2: string | null;
|
||||
}) => string | number
|
||||
>();
|
||||
});
|
||||
|
||||
test("valid function run", () => {
|
||||
const validFunc2Instance = func2.implement((_x) => {
|
||||
_x.f2;
|
||||
_x.f3![0];
|
||||
return "adf" as any;
|
||||
});
|
||||
|
||||
validFunc2Instance({
|
||||
f1: 21,
|
||||
f2: "asdf",
|
||||
f3: [true, false],
|
||||
});
|
||||
});
|
||||
|
||||
const args3 = [
|
||||
z.object({
|
||||
f1: z.number(),
|
||||
f2: z.string().nullable(),
|
||||
f3: z.array(z.boolean().optional()).optional(),
|
||||
}),
|
||||
] as const;
|
||||
const returns3 = z.union([z.string(), z.number()]);
|
||||
|
||||
const func3 = z.function({
|
||||
input: args3,
|
||||
output: returns3,
|
||||
});
|
||||
|
||||
test("function inference 3", () => {
|
||||
type func3 = (typeof func3)["_input"];
|
||||
|
||||
expectTypeOf<func3>().toEqualTypeOf<
|
||||
(arg: {
|
||||
f3?: (boolean | undefined)[] | undefined;
|
||||
f1: number;
|
||||
f2: string | null;
|
||||
}) => string | number
|
||||
>();
|
||||
});
|
||||
|
||||
test("valid function run", () => {
|
||||
const validFunc3Instance = func3.implement((_x) => {
|
||||
_x.f2;
|
||||
_x.f3![0];
|
||||
return "adf" as any;
|
||||
});
|
||||
|
||||
validFunc3Instance({
|
||||
f1: 21,
|
||||
f2: "asdf",
|
||||
f3: [true, false],
|
||||
});
|
||||
});
|
||||
|
||||
test("input validation error", () => {
|
||||
const schema = z.function({
|
||||
input: z.tuple([z.string()]),
|
||||
output: z.void(),
|
||||
});
|
||||
const fn = schema.implement(() => 1234 as any);
|
||||
|
||||
// @ts-expect-error
|
||||
const checker = () => fn();
|
||||
|
||||
try {
|
||||
checker();
|
||||
} catch (e: any) {
|
||||
expect(e.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received undefined",
|
||||
"path": [
|
||||
0,
|
||||
],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("array inputs", () => {
|
||||
const a = z.function({
|
||||
input: [
|
||||
z.object({
|
||||
name: z.string(),
|
||||
age: z.number().int(),
|
||||
}),
|
||||
],
|
||||
output: z.string(),
|
||||
});
|
||||
|
||||
a.implement((args) => {
|
||||
return `${args.age}`;
|
||||
});
|
||||
|
||||
const b = z.function({
|
||||
input: [
|
||||
z.object({
|
||||
name: z.string(),
|
||||
age: z.number().int(),
|
||||
}),
|
||||
],
|
||||
});
|
||||
b.implement((args) => {
|
||||
return `${args.age}`;
|
||||
});
|
||||
});
|
||||
|
||||
test("output validation error", () => {
|
||||
const schema = z.function({
|
||||
input: z.tuple([]),
|
||||
output: z.string(),
|
||||
});
|
||||
const fn = schema.implement(() => 1234 as any);
|
||||
try {
|
||||
fn();
|
||||
} catch (e: any) {
|
||||
expect(e.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("function with async refinements", async () => {
|
||||
const schema = z
|
||||
.function()
|
||||
.input([z.string().refine(async (val) => val.length > 10)])
|
||||
.output(z.promise(z.number().refine(async (val) => val > 10)));
|
||||
|
||||
const func = schema.implementAsync(async (val) => {
|
||||
return val.length;
|
||||
});
|
||||
const results = [];
|
||||
try {
|
||||
await func("asdfasdf");
|
||||
results.push("success");
|
||||
} catch (_) {
|
||||
results.push("fail");
|
||||
}
|
||||
try {
|
||||
await func("asdflkjasdflkjsf");
|
||||
results.push("success");
|
||||
} catch (_) {
|
||||
results.push("fail");
|
||||
}
|
||||
|
||||
expect(results).toEqual(["fail", "success"]);
|
||||
});
|
||||
|
||||
test("implement async with transforms", async () => {
|
||||
const typeGuard = (data: string): data is "1234" => data === "1234";
|
||||
const codeSchema = z.string().transform((data, ctx) => {
|
||||
if (typeGuard(data)) {
|
||||
return data;
|
||||
} else {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "Invalid code",
|
||||
});
|
||||
return z.NEVER;
|
||||
}
|
||||
});
|
||||
const inputSchema = z.object({
|
||||
code: codeSchema,
|
||||
});
|
||||
const outputSchema = z.object({
|
||||
data: z.array(z.string()).default([]),
|
||||
});
|
||||
const fnImplementation = async (data: z.infer<typeof inputSchema>): Promise<z.infer<typeof outputSchema>> => {
|
||||
return {
|
||||
data: [data.code],
|
||||
};
|
||||
};
|
||||
const schema = z.function().input([inputSchema]).output(outputSchema);
|
||||
|
||||
const func = schema.implementAsync(fnImplementation);
|
||||
type TheInterface = {
|
||||
myFunction: (data: z.infer<typeof inputSchema>) => Promise<z.infer<typeof outputSchema>>;
|
||||
};
|
||||
const theImplementation: TheInterface = {
|
||||
myFunction: func,
|
||||
};
|
||||
const results = [];
|
||||
try {
|
||||
await theImplementation.myFunction({
|
||||
code: "1234",
|
||||
});
|
||||
results.push("success");
|
||||
} catch (_) {
|
||||
results.push("fail");
|
||||
}
|
||||
try {
|
||||
await func({ data: "asdflkjasdflkjsf" } as any);
|
||||
results.push("success");
|
||||
} catch (_) {
|
||||
results.push("fail");
|
||||
}
|
||||
|
||||
expect(results).toEqual(["success", "fail"]);
|
||||
});
|
||||
|
||||
test("non async function with async refinements should fail", async () => {
|
||||
const func = z
|
||||
.function()
|
||||
.input([z.string().refine(async (val) => val.length > 10)])
|
||||
.output(z.number().refine(async (val) => val > 10))
|
||||
.implement((val) => {
|
||||
return val.length;
|
||||
});
|
||||
|
||||
const results = [];
|
||||
try {
|
||||
await func("asdasdfasdffasdf");
|
||||
results.push("success");
|
||||
} catch (_) {
|
||||
results.push("fail");
|
||||
}
|
||||
|
||||
expect(results).toEqual(["fail"]);
|
||||
});
|
||||
|
||||
test("extra parameters with rest", () => {
|
||||
const maxLength5 = z
|
||||
.function()
|
||||
.input([z.string()], z.unknown())
|
||||
.output(z.boolean())
|
||||
.implement((str, _arg, _qewr) => {
|
||||
return str.length <= 5;
|
||||
});
|
||||
|
||||
const filteredList = ["apple", "orange", "pear", "banana", "strawberry"].filter(maxLength5);
|
||||
expect(filteredList.length).toEqual(2);
|
||||
});
|
||||
72
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/generics.test.ts
generated
vendored
Normal file
72
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/generics.test.ts
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
function nest<TData extends z.ZodType>(schema: TData) {
|
||||
return z.object({
|
||||
nested: schema,
|
||||
});
|
||||
}
|
||||
|
||||
test("generics", () => {
|
||||
const a = nest(z.object({ a: z.string() }));
|
||||
type a = z.infer<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<{ nested: { a: string } }>();
|
||||
|
||||
const b = nest(z.object({ a: z.string().optional() }));
|
||||
type b = z.infer<typeof b>;
|
||||
expectTypeOf<b>().toEqualTypeOf<{ nested: { a?: string | undefined } }>();
|
||||
});
|
||||
|
||||
test("generics with optional", () => {
|
||||
async function stripOuter<TData extends z.ZodType>(schema: TData, data: unknown) {
|
||||
return z
|
||||
.object({
|
||||
nested: schema.optional(),
|
||||
})
|
||||
.transform((data) => {
|
||||
return data.nested;
|
||||
})
|
||||
.parse({ nested: data });
|
||||
}
|
||||
|
||||
const result = stripOuter(z.object({ a: z.string() }), { a: "asdf" });
|
||||
expectTypeOf<typeof result>().toEqualTypeOf<Promise<{ a: string } | undefined>>();
|
||||
});
|
||||
|
||||
// test("assignability", () => {
|
||||
// const createSchemaAndParse = <K extends string, VS extends z.ZodString>(key: K, valueSchema: VS, data: unknown) => {
|
||||
// const schema = z.object({
|
||||
// [key]: valueSchema,
|
||||
// });
|
||||
// // return { [key]: valueSchema };
|
||||
// const parsed = schema.parse(data);
|
||||
// return parsed;
|
||||
// // const inferred: z.infer<z.ZodObject<{ [k in K]: VS }>> = parsed;
|
||||
// // return inferred;
|
||||
// };
|
||||
// const parsed = createSchemaAndParse("foo", z.string(), { foo: "" });
|
||||
// expectTypeOf<typeof parsed>().toEqualTypeOf<{ foo: string }>();
|
||||
// });
|
||||
|
||||
test("nested no undefined", () => {
|
||||
const inner = z.string().or(z.array(z.string()));
|
||||
const outer = z.object({ inner });
|
||||
type outerSchema = z.infer<typeof outer>;
|
||||
expectTypeOf<outerSchema>().toEqualTypeOf<{ inner: string | string[] }>();
|
||||
|
||||
expect(outer.safeParse({ inner: undefined }).success).toEqual(false);
|
||||
});
|
||||
|
||||
test("generic on output type", () => {
|
||||
const createV4Schema = <Output>(opts: {
|
||||
schema: z.ZodType<Output>;
|
||||
}) => {
|
||||
return opts.schema;
|
||||
};
|
||||
|
||||
createV4Schema({
|
||||
schema: z.object({
|
||||
name: z.string(),
|
||||
}),
|
||||
})?._zod?.output?.name;
|
||||
});
|
||||
68
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/hash.test.ts
generated
vendored
Normal file
68
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/hash.test.ts
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { type ZodCustomStringFormat, hash } from "zod"; // adjust path as needed
|
||||
|
||||
test("hash() API — types and runtime across all alg/enc combinations", async () => {
|
||||
const { createHash } = await import("node:crypto");
|
||||
|
||||
type Alg = "md5" | "sha1" | "sha256" | "sha384" | "sha512";
|
||||
// type Enc = "hex" | "base64" | "base64url";
|
||||
|
||||
const toB64Url = (b64: string) => b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
||||
|
||||
const makeDigests = (alg: Alg, input: string) => {
|
||||
const buf = createHash(alg).update(input).digest();
|
||||
const hex = buf.toString("hex");
|
||||
const base64 = buf.toString("base64");
|
||||
const base64url = toB64Url(base64);
|
||||
return { hex, base64, base64url };
|
||||
};
|
||||
|
||||
const algs: ReadonlyArray<Alg> = ["md5", "sha1", "sha256", "sha384", "sha512"];
|
||||
const input = "zodasklfjaasdf";
|
||||
|
||||
// --- Type-level checks (ensure the literal format string is encoded in the return type)
|
||||
expectTypeOf(hash("md5")).toEqualTypeOf<ZodCustomStringFormat<"md5_hex">>();
|
||||
expectTypeOf(hash("sha1")).toEqualTypeOf<ZodCustomStringFormat<"sha1_hex">>();
|
||||
expectTypeOf(hash("sha256", { enc: "base64" as const })).toEqualTypeOf<ZodCustomStringFormat<"sha256_base64">>();
|
||||
expectTypeOf(hash("sha384", { enc: "base64url" as const })).toEqualTypeOf<
|
||||
ZodCustomStringFormat<"sha384_base64url">
|
||||
>();
|
||||
|
||||
// Test generic format types are correctly inferred and Enc defaults to "hex"
|
||||
expectTypeOf(hash("sha256")).toEqualTypeOf<ZodCustomStringFormat<"sha256_hex">>();
|
||||
|
||||
// --- Runtime matrix (success + a few sharp-edged failures per combo)
|
||||
for (const alg of algs) {
|
||||
const { hex, base64, base64url } = makeDigests(alg, input);
|
||||
|
||||
// Success cases
|
||||
expect(hash(alg).parse(hex)).toBe(hex); // default enc=hex
|
||||
expect(hash(alg, { enc: "hex" }).parse(hex)).toBe(hex);
|
||||
expect(hash(alg, { enc: "base64" }).parse(base64)).toBe(base64);
|
||||
expect(hash(alg, { enc: "base64url" }).parse(base64url)).toBe(base64url);
|
||||
|
||||
// Failure cases (wrong encoding to schema)
|
||||
expect(() => hash(alg, { enc: "hex" }).parse(base64)).toThrow();
|
||||
expect(() => hash(alg, { enc: "base64" }).parse(hex)).toThrow();
|
||||
expect(() => hash(alg, { enc: "base64url" }).parse(base64)).toThrow();
|
||||
|
||||
// Encoding-specific failures
|
||||
// hex: uppercase allowed, wrong length should fail
|
||||
hash(alg, { enc: "hex" }).parse(hex.toUpperCase());
|
||||
expect(() => hash(alg, { enc: "hex" }).parse(hex.slice(0, -1))).toThrow();
|
||||
|
||||
// base64: missing required padding should fail (only for algorithms that require padding)
|
||||
if (base64.includes("=")) {
|
||||
const base64NoPad = base64.replace(/=+$/g, "");
|
||||
expect(() => hash(alg, { enc: "base64" }).parse(base64NoPad)).toThrow();
|
||||
}
|
||||
|
||||
// base64url: adding padding or using invalid characters should fail
|
||||
expect(() => hash(alg, { enc: "base64url" }).parse(base64url + "=")).toThrow();
|
||||
expect(() => hash(alg, { enc: "base64url" }).parse(base64url + "!")).toThrow();
|
||||
|
||||
// Param object present but enc omitted should still default to hex at runtime
|
||||
const schemaWithEmptyParams = hash(alg, {} as any);
|
||||
expect(schemaWithEmptyParams.parse(hex)).toBe(hex);
|
||||
}
|
||||
});
|
||||
939
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/index.test.ts
generated
vendored
Normal file
939
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/index.test.ts
generated
vendored
Normal file
@@ -0,0 +1,939 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
import type { util } from "zod/v4/core";
|
||||
|
||||
test("z.boolean", () => {
|
||||
const a = z.boolean();
|
||||
expect(z.parse(a, true)).toEqual(true);
|
||||
expect(z.parse(a, false)).toEqual(false);
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
expect(() => z.parse(a, "true")).toThrow();
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<boolean>();
|
||||
});
|
||||
|
||||
test("z.bigint", () => {
|
||||
const a = z.bigint();
|
||||
expect(z.parse(a, BigInt(123))).toEqual(BigInt(123));
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
expect(() => z.parse(a, "123")).toThrow();
|
||||
});
|
||||
|
||||
test("z.symbol", () => {
|
||||
const a = z.symbol();
|
||||
const sym = Symbol();
|
||||
expect(z.parse(a, sym)).toEqual(sym);
|
||||
expect(() => z.parse(a, "symbol")).toThrow();
|
||||
});
|
||||
|
||||
test("z.date", () => {
|
||||
const a = z.date();
|
||||
const date = new Date();
|
||||
expect(z.parse(a, date)).toEqual(date);
|
||||
expect(() => z.parse(a, "date")).toThrow();
|
||||
});
|
||||
|
||||
test("z.coerce.string", () => {
|
||||
const a = z.coerce.string();
|
||||
expect(z.parse(a, 123)).toEqual("123");
|
||||
expect(z.parse(a, true)).toEqual("true");
|
||||
expect(z.parse(a, null)).toEqual("null");
|
||||
expect(z.parse(a, undefined)).toEqual("undefined");
|
||||
});
|
||||
|
||||
test("z.coerce.number", () => {
|
||||
const a = z.coerce.number();
|
||||
expect(z.parse(a, "123")).toEqual(123);
|
||||
expect(z.parse(a, "123.45")).toEqual(123.45);
|
||||
expect(z.parse(a, true)).toEqual(1);
|
||||
expect(z.parse(a, false)).toEqual(0);
|
||||
expect(() => z.parse(a, "abc")).toThrow();
|
||||
});
|
||||
|
||||
test("z.coerce.boolean", () => {
|
||||
const a = z.coerce.boolean();
|
||||
// test booleans
|
||||
expect(z.parse(a, true)).toEqual(true);
|
||||
expect(z.parse(a, false)).toEqual(false);
|
||||
expect(z.parse(a, "true")).toEqual(true);
|
||||
expect(z.parse(a, "false")).toEqual(true);
|
||||
expect(z.parse(a, 1)).toEqual(true);
|
||||
expect(z.parse(a, 0)).toEqual(false);
|
||||
expect(z.parse(a, {})).toEqual(true);
|
||||
expect(z.parse(a, [])).toEqual(true);
|
||||
expect(z.parse(a, undefined)).toEqual(false);
|
||||
expect(z.parse(a, null)).toEqual(false);
|
||||
expect(z.parse(a, "")).toEqual(false);
|
||||
});
|
||||
|
||||
test("z.coerce.bigint", () => {
|
||||
const a = z.coerce.bigint();
|
||||
expect(z.parse(a, "123")).toEqual(BigInt(123));
|
||||
expect(z.parse(a, 123)).toEqual(BigInt(123));
|
||||
expect(() => z.parse(a, "abc")).toThrow();
|
||||
});
|
||||
|
||||
test("z.coerce.date", () => {
|
||||
const a = z.coerce.date();
|
||||
const date = new Date();
|
||||
expect(z.parse(a, date.toISOString())).toEqual(date);
|
||||
expect(z.parse(a, date.getTime())).toEqual(date);
|
||||
expect(() => z.parse(a, "invalid date")).toThrow();
|
||||
});
|
||||
|
||||
test("z.iso.datetime", () => {
|
||||
const d1 = "2021-01-01T00:00:00Z";
|
||||
const d2 = "2021-01-01T00:00:00.123Z";
|
||||
const d3 = "2021-01-01T00:00:00";
|
||||
const d4 = "2021-01-01T00:00:00+07:00";
|
||||
const d5 = "bad data";
|
||||
|
||||
// local: false, offset: false, precision: null
|
||||
const a = z.iso.datetime();
|
||||
expect(z.safeParse(a, d1).success).toEqual(true);
|
||||
expect(z.safeParse(a, d2).success).toEqual(true);
|
||||
expect(z.safeParse(a, d3).success).toEqual(false);
|
||||
expect(z.safeParse(a, d4).success).toEqual(false);
|
||||
expect(z.safeParse(a, d5).success).toEqual(false);
|
||||
|
||||
const b = z.iso.datetime({ local: true });
|
||||
expect(z.safeParse(b, d1).success).toEqual(true);
|
||||
expect(z.safeParse(b, d2).success).toEqual(true);
|
||||
expect(z.safeParse(b, d3).success).toEqual(true);
|
||||
expect(z.safeParse(b, d4).success).toEqual(false);
|
||||
expect(z.safeParse(b, d5).success).toEqual(false);
|
||||
|
||||
const c = z.iso.datetime({ offset: true });
|
||||
expect(z.safeParse(c, d1).success).toEqual(true);
|
||||
expect(z.safeParse(c, d2).success).toEqual(true);
|
||||
expect(z.safeParse(c, d3).success).toEqual(false);
|
||||
expect(z.safeParse(c, d4).success).toEqual(true);
|
||||
expect(z.safeParse(c, d5).success).toEqual(false);
|
||||
|
||||
const d = z.iso.datetime({ precision: 3 });
|
||||
expect(z.safeParse(d, d1).success).toEqual(false);
|
||||
expect(z.safeParse(d, d2).success).toEqual(true);
|
||||
expect(z.safeParse(d, d3).success).toEqual(false);
|
||||
expect(z.safeParse(d, d4).success).toEqual(false);
|
||||
expect(z.safeParse(d, d5).success).toEqual(false);
|
||||
});
|
||||
|
||||
test("z.iso.date", () => {
|
||||
const d1 = "2021-01-01";
|
||||
const d2 = "bad data";
|
||||
|
||||
const a = z.iso.date();
|
||||
expect(z.safeParse(a, d1).success).toEqual(true);
|
||||
expect(z.safeParse(a, d2).success).toEqual(false);
|
||||
|
||||
const b = z.string().check(z.iso.date());
|
||||
expect(z.safeParse(b, d1).success).toEqual(true);
|
||||
expect(z.safeParse(b, d2).success).toEqual(false);
|
||||
});
|
||||
|
||||
test("z.iso.time", () => {
|
||||
const d1 = "00:00:00";
|
||||
const d2 = "00:00:00.123";
|
||||
const d3 = "bad data";
|
||||
|
||||
const a = z.iso.time();
|
||||
expect(z.safeParse(a, d1).success).toEqual(true);
|
||||
expect(z.safeParse(a, d2).success).toEqual(true);
|
||||
expect(z.safeParse(a, d3).success).toEqual(false);
|
||||
|
||||
const b = z.iso.time({ precision: 3 });
|
||||
expect(z.safeParse(b, d1).success).toEqual(false);
|
||||
expect(z.safeParse(b, d2).success).toEqual(true);
|
||||
expect(z.safeParse(b, d3).success).toEqual(false);
|
||||
|
||||
const c = z.string().check(z.iso.time());
|
||||
expect(z.safeParse(c, d1).success).toEqual(true);
|
||||
expect(z.safeParse(c, d2).success).toEqual(true);
|
||||
expect(z.safeParse(c, d3).success).toEqual(false);
|
||||
});
|
||||
|
||||
test("z.iso.duration", () => {
|
||||
const d1 = "P3Y6M4DT12H30M5S";
|
||||
const d2 = "bad data";
|
||||
|
||||
const a = z.iso.duration();
|
||||
expect(z.safeParse(a, d1).success).toEqual(true);
|
||||
expect(z.safeParse(a, d2).success).toEqual(false);
|
||||
|
||||
const b = z.string().check(z.iso.duration());
|
||||
expect(z.safeParse(b, d1).success).toEqual(true);
|
||||
expect(z.safeParse(b, d2).success).toEqual(false);
|
||||
});
|
||||
|
||||
test("z.undefined", () => {
|
||||
const a = z.undefined();
|
||||
expect(z.parse(a, undefined)).toEqual(undefined);
|
||||
expect(() => z.parse(a, "undefined")).toThrow();
|
||||
});
|
||||
|
||||
test("z.null", () => {
|
||||
const a = z.null();
|
||||
expect(z.parse(a, null)).toEqual(null);
|
||||
expect(() => z.parse(a, "null")).toThrow();
|
||||
});
|
||||
|
||||
test("z.any", () => {
|
||||
const a = z.any();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, 123)).toEqual(123);
|
||||
expect(z.parse(a, true)).toEqual(true);
|
||||
expect(z.parse(a, null)).toEqual(null);
|
||||
expect(z.parse(a, undefined)).toEqual(undefined);
|
||||
z.parse(a, {});
|
||||
z.parse(a, []);
|
||||
z.parse(a, Symbol());
|
||||
z.parse(a, new Date());
|
||||
});
|
||||
|
||||
test("z.unknown", () => {
|
||||
const a = z.unknown();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, 123)).toEqual(123);
|
||||
expect(z.parse(a, true)).toEqual(true);
|
||||
expect(z.parse(a, null)).toEqual(null);
|
||||
expect(z.parse(a, undefined)).toEqual(undefined);
|
||||
z.parse(a, {});
|
||||
z.parse(a, []);
|
||||
z.parse(a, Symbol());
|
||||
z.parse(a, new Date());
|
||||
});
|
||||
|
||||
test("z.never", () => {
|
||||
const a = z.never();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
});
|
||||
|
||||
test("z.void", () => {
|
||||
const a = z.void();
|
||||
expect(z.parse(a, undefined)).toEqual(undefined);
|
||||
expect(() => z.parse(a, null)).toThrow();
|
||||
});
|
||||
|
||||
test("z.array", () => {
|
||||
const a = z.array(z.string());
|
||||
expect(z.parse(a, ["hello", "world"])).toEqual(["hello", "world"]);
|
||||
expect(() => z.parse(a, [123])).toThrow();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
});
|
||||
|
||||
test("z.union", () => {
|
||||
const a = z.union([z.string(), z.number()]);
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, 123)).toEqual(123);
|
||||
expect(() => z.parse(a, true)).toThrow();
|
||||
});
|
||||
|
||||
test("z.intersection", () => {
|
||||
const a = z.intersection(z.object({ a: z.string() }), z.object({ b: z.number() }));
|
||||
expect(z.parse(a, { a: "hello", b: 123 })).toEqual({ a: "hello", b: 123 });
|
||||
expect(() => z.parse(a, { a: "hello" })).toThrow();
|
||||
expect(() => z.parse(a, { b: 123 })).toThrow();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
});
|
||||
|
||||
test("z.tuple", () => {
|
||||
const a = z.tuple([z.string(), z.number()]);
|
||||
expect(z.parse(a, ["hello", 123])).toEqual(["hello", 123]);
|
||||
expect(() => z.parse(a, ["hello", "world"])).toThrow();
|
||||
expect(() => z.parse(a, [123, 456])).toThrow();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
|
||||
// tuple with rest
|
||||
const b = z.tuple([z.string(), z.number(), z.optional(z.string())], z.boolean());
|
||||
type b = z.output<typeof b>;
|
||||
|
||||
expectTypeOf<b>().toEqualTypeOf<[string, number, string?, ...boolean[]]>();
|
||||
const datas = [
|
||||
["hello", 123],
|
||||
["hello", 123, "world"],
|
||||
["hello", 123, "world", true],
|
||||
["hello", 123, "world", true, false, true],
|
||||
];
|
||||
for (const data of datas) {
|
||||
expect(z.parse(b, data)).toEqual(data);
|
||||
}
|
||||
|
||||
expect(() => z.parse(b, ["hello", 123, 123])).toThrow();
|
||||
expect(() => z.parse(b, ["hello", 123, "world", 123])).toThrow();
|
||||
|
||||
// tuple with readonly args
|
||||
const cArgs = [z.string(), z.number(), z.optional(z.string())] as const;
|
||||
const c = z.tuple(cArgs, z.boolean());
|
||||
type c = z.output<typeof c>;
|
||||
expectTypeOf<c>().toEqualTypeOf<[string, number, string?, ...boolean[]]>();
|
||||
// type c = z.output<typeof c>;
|
||||
});
|
||||
|
||||
test("z.record", () => {
|
||||
// record schema with enum keys
|
||||
const a = z.record(z.string(), z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<Record<string, string>>();
|
||||
|
||||
const b = z.record(z.union([z.string(), z.number(), z.symbol()]), z.string());
|
||||
type b = z.output<typeof b>;
|
||||
expectTypeOf<b>().toEqualTypeOf<Record<string | number | symbol, string>>();
|
||||
expect(z.parse(b, { a: "hello", 1: "world", [Symbol.for("asdf")]: "symbol" })).toEqual({
|
||||
a: "hello",
|
||||
1: "world",
|
||||
[Symbol.for("asdf")]: "symbol",
|
||||
});
|
||||
|
||||
// enum keys
|
||||
const c = z.record(z.enum(["a", "b", "c"]), z.string());
|
||||
type c = z.output<typeof c>;
|
||||
expectTypeOf<c>().toEqualTypeOf<Record<"a" | "b" | "c", string>>();
|
||||
expect(z.parse(c, { a: "hello", b: "world", c: "world" })).toEqual({
|
||||
a: "hello",
|
||||
b: "world",
|
||||
c: "world",
|
||||
});
|
||||
// missing keys
|
||||
expect(() => z.parse(c, { a: "hello", b: "world" })).toThrow();
|
||||
// extra keys
|
||||
expect(() => z.parse(c, { a: "hello", b: "world", c: "world", d: "world" })).toThrow();
|
||||
|
||||
// partial enum
|
||||
const d = z.record(z.enum(["a", "b"]).or(z.never()), z.string());
|
||||
type d = z.output<typeof d>;
|
||||
expectTypeOf<d>().toEqualTypeOf<Record<"a" | "b", string>>();
|
||||
|
||||
// literal union keys
|
||||
const e = z.record(z.union([z.literal("a"), z.literal(0)]), z.string());
|
||||
type e = z.output<typeof e>;
|
||||
expectTypeOf<e>().toEqualTypeOf<Record<"a" | 0, string>>();
|
||||
expect(z.parse(e, { a: "hello", 0: "world" })).toEqual({
|
||||
a: "hello",
|
||||
0: "world",
|
||||
});
|
||||
|
||||
// TypeScript enum keys
|
||||
enum Enum {
|
||||
A = 0,
|
||||
B = "hi",
|
||||
}
|
||||
|
||||
const f = z.record(z.enum(Enum), z.string());
|
||||
type f = z.output<typeof f>;
|
||||
expectTypeOf<f>().toEqualTypeOf<Record<Enum, string>>();
|
||||
expect(z.parse(f, { [Enum.A]: "hello", [Enum.B]: "world" })).toEqual({
|
||||
[Enum.A]: "hello",
|
||||
[Enum.B]: "world",
|
||||
});
|
||||
});
|
||||
|
||||
test("z.map", () => {
|
||||
const a = z.map(z.string(), z.number());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<Map<string, number>>();
|
||||
expect(z.parse(a, new Map([["hello", 123]]))).toEqual(new Map([["hello", 123]]));
|
||||
expect(() => z.parse(a, new Map([["hello", "world"]]))).toThrow();
|
||||
expect(() => z.parse(a, new Map([[1243, "world"]]))).toThrow();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
|
||||
const r1 = z.safeParse(a, new Map([[123, 123]]));
|
||||
expect(r1.error?.issues[0].code).toEqual("invalid_type");
|
||||
expect(r1.error?.issues[0].path).toEqual([123]);
|
||||
|
||||
const r2: any = z.safeParse(a, new Map([[BigInt(123), 123]]));
|
||||
expect(r2.error!.issues[0].code).toEqual("invalid_key");
|
||||
expect(r2.error!.issues[0].path).toEqual([]);
|
||||
|
||||
const r3: any = z.safeParse(a, new Map([["hello", "world"]]));
|
||||
expect(r3.error!.issues[0].code).toEqual("invalid_type");
|
||||
expect(r3.error!.issues[0].path).toEqual(["hello"]);
|
||||
});
|
||||
|
||||
test("z.map invalid_element", () => {
|
||||
const a = z.map(z.bigint(), z.number());
|
||||
const r1 = z.safeParse(a, new Map([[BigInt(123), BigInt(123)]]));
|
||||
|
||||
expect(r1.error!.issues[0].code).toEqual("invalid_element");
|
||||
expect(r1.error!.issues[0].path).toEqual([]);
|
||||
});
|
||||
|
||||
test("z.map async", async () => {
|
||||
const a = z.map(z.string().check(z.refine(async () => true)), z.number().check(z.refine(async () => true)));
|
||||
const d1 = new Map([["hello", 123]]);
|
||||
expect(await z.parseAsync(a, d1)).toEqual(d1);
|
||||
|
||||
await expect(z.parseAsync(a, new Map([[123, 123]]))).rejects.toThrow();
|
||||
await expect(z.parseAsync(a, new Map([["hi", "world"]]))).rejects.toThrow();
|
||||
await expect(z.parseAsync(a, new Map([[1243, "world"]]))).rejects.toThrow();
|
||||
await expect(z.parseAsync(a, "hello")).rejects.toThrow();
|
||||
|
||||
const r = await z.safeParseAsync(a, new Map([[123, 123]]));
|
||||
expect(r.success).toEqual(false);
|
||||
expect(r.error!.issues[0].code).toEqual("invalid_type");
|
||||
expect(r.error!.issues[0].path).toEqual([123]);
|
||||
});
|
||||
|
||||
test("z.set", () => {
|
||||
const a = z.set(z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<Set<string>>();
|
||||
expect(z.parse(a, new Set(["hello", "world"]))).toEqual(new Set(["hello", "world"]));
|
||||
expect(() => z.parse(a, new Set([123]))).toThrow();
|
||||
expect(() => z.parse(a, ["hello", "world"])).toThrow();
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
|
||||
const b = z.set(z.number());
|
||||
expect(z.parse(b, new Set([1, 2, 3]))).toEqual(new Set([1, 2, 3]));
|
||||
expect(() => z.parse(b, new Set(["hello"]))).toThrow();
|
||||
expect(() => z.parse(b, [1, 2, 3])).toThrow();
|
||||
expect(() => z.parse(b, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.enum", () => {
|
||||
const a = z.enum(["A", "B", "C"]);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<"A" | "B" | "C">();
|
||||
expect(z.parse(a, "A")).toEqual("A");
|
||||
expect(z.parse(a, "B")).toEqual("B");
|
||||
expect(z.parse(a, "C")).toEqual("C");
|
||||
expect(() => z.parse(a, "D")).toThrow();
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
|
||||
expect(a.enum.A).toEqual("A");
|
||||
expect(a.enum.B).toEqual("B");
|
||||
expect(a.enum.C).toEqual("C");
|
||||
expect((a.enum as any).D).toEqual(undefined);
|
||||
});
|
||||
|
||||
test("z.enum - native", () => {
|
||||
enum NativeEnum {
|
||||
A = "A",
|
||||
B = "B",
|
||||
C = "C",
|
||||
}
|
||||
const a = z.enum(NativeEnum);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<NativeEnum>();
|
||||
expect(z.parse(a, NativeEnum.A)).toEqual(NativeEnum.A);
|
||||
expect(z.parse(a, NativeEnum.B)).toEqual(NativeEnum.B);
|
||||
expect(z.parse(a, NativeEnum.C)).toEqual(NativeEnum.C);
|
||||
expect(() => z.parse(a, "D")).toThrow();
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
|
||||
// test a.enum
|
||||
a;
|
||||
expect(a.enum.A).toEqual(NativeEnum.A);
|
||||
expect(a.enum.B).toEqual(NativeEnum.B);
|
||||
expect(a.enum.C).toEqual(NativeEnum.C);
|
||||
});
|
||||
|
||||
test("z.nativeEnum", () => {
|
||||
enum NativeEnum {
|
||||
A = "A",
|
||||
B = "B",
|
||||
C = "C",
|
||||
}
|
||||
const a = z.nativeEnum(NativeEnum);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<NativeEnum>();
|
||||
expect(z.parse(a, NativeEnum.A)).toEqual(NativeEnum.A);
|
||||
expect(z.parse(a, NativeEnum.B)).toEqual(NativeEnum.B);
|
||||
expect(z.parse(a, NativeEnum.C)).toEqual(NativeEnum.C);
|
||||
expect(() => z.parse(a, "D")).toThrow();
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
|
||||
// test a.enum
|
||||
a;
|
||||
expect(a.enum.A).toEqual(NativeEnum.A);
|
||||
expect(a.enum.B).toEqual(NativeEnum.B);
|
||||
expect(a.enum.C).toEqual(NativeEnum.C);
|
||||
});
|
||||
|
||||
test("z.literal", () => {
|
||||
const a = z.literal("hello");
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<"hello">();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(() => z.parse(a, "world")).toThrow();
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.file", () => {
|
||||
const a = z.file();
|
||||
const file = new File(["content"], "filename.txt", { type: "text/plain" });
|
||||
expect(z.parse(a, file)).toEqual(file);
|
||||
expect(() => z.parse(a, "file")).toThrow();
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.transform", () => {
|
||||
const a = z.pipe(
|
||||
z.string(),
|
||||
z.transform((val) => val.toUpperCase())
|
||||
);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
expect(z.parse(a, "hello")).toEqual("HELLO");
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.transform async", async () => {
|
||||
const a = z.pipe(
|
||||
z.string(),
|
||||
z.transform(async (val) => val.toUpperCase())
|
||||
);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
expect(await z.parseAsync(a, "hello")).toEqual("HELLO");
|
||||
await expect(() => z.parseAsync(a, 123)).rejects.toThrow();
|
||||
});
|
||||
|
||||
test("z.preprocess", () => {
|
||||
const a = z.pipe(
|
||||
z.transform((val) => String(val).toUpperCase()),
|
||||
z.string()
|
||||
);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
expect(z.parse(a, 123)).toEqual("123");
|
||||
expect(z.parse(a, true)).toEqual("TRUE");
|
||||
expect(z.parse(a, BigInt(1234))).toEqual("1234");
|
||||
// expect(() => z.parse(a, Symbol("asdf"))).toThrow();
|
||||
});
|
||||
|
||||
// test("z.preprocess async", () => {
|
||||
// const a = z.preprocess(async (val) => String(val), z.string());
|
||||
// type a = z.output<typeof a>;
|
||||
// expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
// expect(z.parse(a, 123)).toEqual("123");
|
||||
// expect(z.parse(a, true)).toEqual("true");
|
||||
// expect(() => z.parse(a, {})).toThrow();
|
||||
// });
|
||||
|
||||
test("z.optional", () => {
|
||||
const a = z.optional(z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string | undefined>();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, undefined)).toEqual(undefined);
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.nullable", () => {
|
||||
const a = z.nullable(z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string | null>();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, null)).toEqual(null);
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.default", () => {
|
||||
const a = z._default(z.string(), "default");
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
expect(z.parse(a, undefined)).toEqual("default");
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
|
||||
const b = z._default(z.string(), () => "default");
|
||||
expect(z.parse(b, undefined)).toEqual("default");
|
||||
expect(z.parse(b, "hello")).toEqual("hello");
|
||||
expect(() => z.parse(b, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.catch", () => {
|
||||
const a = z.catch(z.string(), "default");
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, 123)).toEqual("default");
|
||||
|
||||
const b = z.catch(z.string(), () => "default");
|
||||
expect(z.parse(b, "hello")).toEqual("hello");
|
||||
expect(z.parse(b, 123)).toEqual("default");
|
||||
|
||||
const c = z.catch(z.string(), (ctx) => {
|
||||
return `${ctx.error.issues.length}issues`;
|
||||
});
|
||||
expect(z.parse(c, 1234)).toEqual("1issues");
|
||||
});
|
||||
|
||||
test("z.nan", () => {
|
||||
const a = z.nan();
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<number>();
|
||||
expect(z.parse(a, Number.NaN)).toEqual(Number.NaN);
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
expect(() => z.parse(a, "NaN")).toThrow();
|
||||
});
|
||||
|
||||
test("z.pipe", () => {
|
||||
const a = z.pipe(
|
||||
z.pipe(
|
||||
z.string(),
|
||||
z.transform((val) => val.length)
|
||||
),
|
||||
z.number()
|
||||
);
|
||||
type a_in = z.input<typeof a>;
|
||||
expectTypeOf<a_in>().toEqualTypeOf<string>();
|
||||
type a_out = z.output<typeof a>;
|
||||
expectTypeOf<a_out>().toEqualTypeOf<number>();
|
||||
|
||||
expect(z.parse(a, "123")).toEqual(3);
|
||||
expect(z.parse(a, "hello")).toEqual(5);
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.readonly", () => {
|
||||
const a = z.readonly(z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<Readonly<string>>();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.templateLiteral", () => {
|
||||
const a = z.templateLiteral([z.string(), z.number()]);
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<`${string}${number}`>();
|
||||
expect(z.parse(a, "hello123")).toEqual("hello123");
|
||||
expect(() => z.parse(a, "hello")).toThrow();
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
|
||||
// multipart
|
||||
const b = z.templateLiteral([z.string(), z.number(), z.string()]);
|
||||
type b = z.output<typeof b>;
|
||||
expectTypeOf<b>().toEqualTypeOf<`${string}${number}${string}`>();
|
||||
expect(z.parse(b, "hello123world")).toEqual("hello123world");
|
||||
expect(z.parse(b, "123")).toEqual("123");
|
||||
expect(() => z.parse(b, "hello")).toThrow();
|
||||
expect(() => z.parse(b, 123)).toThrow();
|
||||
|
||||
// include boolean
|
||||
const c = z.templateLiteral([z.string(), z.boolean()]);
|
||||
type c = z.output<typeof c>;
|
||||
expectTypeOf<c>().toEqualTypeOf<`${string}${boolean}`>();
|
||||
expect(z.parse(c, "hellotrue")).toEqual("hellotrue");
|
||||
expect(z.parse(c, "hellofalse")).toEqual("hellofalse");
|
||||
expect(() => z.parse(c, "hello")).toThrow();
|
||||
expect(() => z.parse(c, 123)).toThrow();
|
||||
|
||||
// include literal prefix
|
||||
const d = z.templateLiteral([z.literal("hello"), z.number()]);
|
||||
type d = z.output<typeof d>;
|
||||
expectTypeOf<d>().toEqualTypeOf<`hello${number}`>();
|
||||
expect(z.parse(d, "hello123")).toEqual("hello123");
|
||||
expect(() => z.parse(d, 123)).toThrow();
|
||||
expect(() => z.parse(d, "world123")).toThrow();
|
||||
|
||||
// include literal union
|
||||
const e = z.templateLiteral([z.literal(["aa", "bb"]), z.number()]);
|
||||
type e = z.output<typeof e>;
|
||||
expectTypeOf<e>().toEqualTypeOf<`aa${number}` | `bb${number}`>();
|
||||
expect(z.parse(e, "aa123")).toEqual("aa123");
|
||||
expect(z.parse(e, "bb123")).toEqual("bb123");
|
||||
expect(() => z.parse(e, "cc123")).toThrow();
|
||||
expect(() => z.parse(e, 123)).toThrow();
|
||||
});
|
||||
|
||||
// this returns both a schema and a check
|
||||
test("z.custom schema", () => {
|
||||
const a = z.custom((val) => {
|
||||
return typeof val === "string";
|
||||
});
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
test("z.custom check", () => {
|
||||
// @ts-expect-error Inference not possible, use z.refine()
|
||||
z.date().check(z.custom((val) => val.getTime() > 0));
|
||||
});
|
||||
|
||||
test("z.check", () => {
|
||||
// this is a more flexible version of z.custom that accepts an arbitrary _parse logic
|
||||
// the function should return base.$ZodResult
|
||||
const a = z.any().check(
|
||||
z.check<string>((ctx) => {
|
||||
if (typeof ctx.value === "string") return;
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
origin: "custom",
|
||||
message: "Expected a string",
|
||||
input: ctx.value,
|
||||
});
|
||||
})
|
||||
);
|
||||
expect(z.safeParse(a, "hello")).toMatchObject({
|
||||
success: true,
|
||||
data: "hello",
|
||||
});
|
||||
expect(z.safeParse(a, 123)).toMatchObject({
|
||||
success: false,
|
||||
error: { issues: [{ code: "custom", message: "Expected a string" }] },
|
||||
});
|
||||
});
|
||||
|
||||
test("z.with (alias for z.check)", () => {
|
||||
// .with() should work exactly the same as .check()
|
||||
const a = z.any().with(
|
||||
z.check<string>((ctx) => {
|
||||
if (typeof ctx.value === "string") return;
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
origin: "custom",
|
||||
message: "Expected a string",
|
||||
input: ctx.value,
|
||||
});
|
||||
})
|
||||
);
|
||||
expect(z.safeParse(a, "hello")).toMatchObject({
|
||||
success: true,
|
||||
data: "hello",
|
||||
});
|
||||
expect(z.safeParse(a, 123)).toMatchObject({
|
||||
success: false,
|
||||
error: { issues: [{ code: "custom", message: "Expected a string" }] },
|
||||
});
|
||||
|
||||
// Test with refine
|
||||
const b = z.string().with(z.refine((val) => val.length > 3, "Must be longer than 3"));
|
||||
expect(z.safeParse(b, "hello").success).toBe(true);
|
||||
expect(z.safeParse(b, "hi").success).toBe(false);
|
||||
|
||||
// Test with function
|
||||
const c = z.string().with(({ value, issues }) => {
|
||||
if (value.length <= 3) {
|
||||
issues.push({
|
||||
code: "custom",
|
||||
input: value,
|
||||
message: "Must be longer than 3",
|
||||
});
|
||||
}
|
||||
});
|
||||
expect(z.safeParse(c, "hello").success).toBe(true);
|
||||
expect(z.safeParse(c, "hi").success).toBe(false);
|
||||
});
|
||||
|
||||
test("z.instanceof", () => {
|
||||
class A {}
|
||||
|
||||
const a = z.instanceof(A);
|
||||
expect(z.parse(a, new A())).toBeInstanceOf(A);
|
||||
expect(() => z.parse(a, {})).toThrow();
|
||||
});
|
||||
|
||||
test("z.refine", () => {
|
||||
const a = z.number().check(
|
||||
z.refine((val) => val > 3),
|
||||
z.refine((val) => val < 10)
|
||||
);
|
||||
expect(z.parse(a, 5)).toEqual(5);
|
||||
expect(() => z.parse(a, 2)).toThrow();
|
||||
expect(() => z.parse(a, 11)).toThrow();
|
||||
expect(() => z.parse(a, "hi")).toThrow();
|
||||
});
|
||||
|
||||
// test("z.superRefine", () => {
|
||||
// const a = z.number([
|
||||
// z.superRefine((val, ctx) => {
|
||||
// if (val < 3) {
|
||||
// return ctx.addIssue({
|
||||
// code: "custom",
|
||||
// origin: "custom",
|
||||
// message: "Too small",
|
||||
// input: val,
|
||||
// });
|
||||
// }
|
||||
// if (val > 10) {
|
||||
// return ctx.addIssue("Too big");
|
||||
// }
|
||||
// }),
|
||||
// ]);
|
||||
|
||||
// expect(z.parse(a, 5)).toEqual(5);
|
||||
// expect(() => z.parse(a, 2)).toThrow();
|
||||
// expect(() => z.parse(a, 11)).toThrow();
|
||||
// expect(() => z.parse(a, "hi")).toThrow();
|
||||
// });
|
||||
|
||||
test("z.transform", () => {
|
||||
const a = z.transform((val: number) => {
|
||||
return `${val}`;
|
||||
});
|
||||
type a_in = z.input<typeof a>;
|
||||
expectTypeOf<a_in>().toEqualTypeOf<number>();
|
||||
type a_out = z.output<typeof a>;
|
||||
expectTypeOf<a_out>().toEqualTypeOf<string>();
|
||||
expect(z.parse(a, 123)).toEqual("123");
|
||||
});
|
||||
|
||||
test("z.$brand()", () => {
|
||||
const a = z.string().brand<"my-brand">();
|
||||
type a = z.output<typeof a>;
|
||||
const branded = (_: a) => {};
|
||||
// @ts-expect-error
|
||||
branded("asdf");
|
||||
});
|
||||
|
||||
test("z.lazy", () => {
|
||||
const a = z.lazy(() => z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<string>();
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(() => z.parse(a, 123)).toThrow();
|
||||
});
|
||||
|
||||
// schema that validates JSON-like data
|
||||
test("z.json", () => {
|
||||
const a = z.json();
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<util.JSONType>();
|
||||
|
||||
expect(z.parse(a, "hello")).toEqual("hello");
|
||||
expect(z.parse(a, 123)).toEqual(123);
|
||||
expect(z.parse(a, true)).toEqual(true);
|
||||
expect(z.parse(a, null)).toEqual(null);
|
||||
expect(z.parse(a, {})).toEqual({});
|
||||
expect(z.parse(a, { a: "hello" })).toEqual({ a: "hello" });
|
||||
expect(z.parse(a, [1, 2, 3])).toEqual([1, 2, 3]);
|
||||
expect(z.parse(a, [{ a: "hello" }])).toEqual([{ a: "hello" }]);
|
||||
|
||||
// fail cases
|
||||
expect(() => z.parse(a, new Date())).toThrow();
|
||||
expect(() => z.parse(a, Symbol())).toThrow();
|
||||
expect(() => z.parse(a, { a: new Date() })).toThrow();
|
||||
expect(() => z.parse(a, undefined)).toThrow();
|
||||
expect(() => z.parse(a, { a: undefined })).toThrow();
|
||||
});
|
||||
|
||||
// promise
|
||||
test("z.promise", async () => {
|
||||
const a = z.promise(z.string());
|
||||
type a = z.output<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<Promise<string>>();
|
||||
|
||||
expect(await z.safeParseAsync(a, Promise.resolve("hello"))).toMatchObject({
|
||||
success: true,
|
||||
data: "hello",
|
||||
});
|
||||
expect(await z.safeParseAsync(a, Promise.resolve(123))).toMatchObject({
|
||||
success: false,
|
||||
});
|
||||
|
||||
const b = z.string();
|
||||
expect(() => z.parse(b, Promise.resolve("hello"))).toThrow();
|
||||
});
|
||||
// test("type assertions", () => {
|
||||
// const schema = z.pipe(
|
||||
// z.string(),
|
||||
// z.transform((val) => val.length)
|
||||
// );
|
||||
// schema.assertInput<string>();
|
||||
// // @ts-expect-error
|
||||
// schema.assertInput<number>();
|
||||
|
||||
// schema.assertOutput<number>();
|
||||
// // @ts-expect-error
|
||||
// schema.assertOutput<string>();
|
||||
// });
|
||||
|
||||
test("isPlainObject", () => {
|
||||
expect(z.core.util.isPlainObject({})).toEqual(true);
|
||||
expect(z.core.util.isPlainObject(Object.create(null))).toEqual(true);
|
||||
expect(z.core.util.isPlainObject([])).toEqual(false);
|
||||
expect(z.core.util.isPlainObject(new Date())).toEqual(false);
|
||||
expect(z.core.util.isPlainObject(null)).toEqual(false);
|
||||
expect(z.core.util.isPlainObject(undefined)).toEqual(false);
|
||||
expect(z.core.util.isPlainObject("string")).toEqual(false);
|
||||
expect(z.core.util.isPlainObject(123)).toEqual(false);
|
||||
expect(z.core.util.isPlainObject(Symbol())).toEqual(false);
|
||||
expect(z.core.util.isPlainObject({ constructor: "string" })).toEqual(true);
|
||||
expect(z.core.util.isPlainObject({ constructor: 123 })).toEqual(true);
|
||||
expect(z.core.util.isPlainObject({ constructor: null })).toEqual(true);
|
||||
expect(z.core.util.isPlainObject({ constructor: undefined })).toEqual(true);
|
||||
expect(z.core.util.isPlainObject({ constructor: true })).toEqual(true);
|
||||
expect(z.core.util.isPlainObject({ constructor: {} })).toEqual(true);
|
||||
expect(z.core.util.isPlainObject({ constructor: [] })).toEqual(true);
|
||||
});
|
||||
|
||||
test("shallowClone with constructor field", () => {
|
||||
const objWithConstructor = { constructor: "string", key: "value" };
|
||||
const cloned = z.core.util.shallowClone(objWithConstructor);
|
||||
|
||||
expect(cloned).toEqual(objWithConstructor);
|
||||
expect(cloned).not.toBe(objWithConstructor);
|
||||
expect(cloned.constructor).toBe("string");
|
||||
expect(cloned.key).toBe("value");
|
||||
|
||||
const testCases = [
|
||||
{ constructor: 123, data: "test" },
|
||||
{ constructor: null, data: "test" },
|
||||
{ constructor: true, data: "test" },
|
||||
{ constructor: {}, data: "test" },
|
||||
{ constructor: [], data: "test" },
|
||||
];
|
||||
|
||||
for (const testCase of testCases) {
|
||||
const clonedCase = z.core.util.shallowClone(testCase);
|
||||
expect(clonedCase).toEqual(testCase);
|
||||
expect(clonedCase).not.toBe(testCase);
|
||||
}
|
||||
});
|
||||
|
||||
test("def typing", () => {
|
||||
z.string().def.type satisfies "string";
|
||||
z.number().def.type satisfies "number";
|
||||
z.bigint().def.type satisfies "bigint";
|
||||
z.boolean().def.type satisfies "boolean";
|
||||
z.date().def.type satisfies "date";
|
||||
z.symbol().def.type satisfies "symbol";
|
||||
z.undefined().def.type satisfies "undefined";
|
||||
z.string().nullable().def.type satisfies "nullable";
|
||||
z.null().def.type satisfies "null";
|
||||
z.any().def.type satisfies "any";
|
||||
z.unknown().def.type satisfies "unknown";
|
||||
z.never().def.type satisfies "never";
|
||||
z.void().def.type satisfies "void";
|
||||
z.array(z.string()).def.type satisfies "array";
|
||||
z.object({ key: z.string() }).def.type satisfies "object";
|
||||
z.union([z.string(), z.number()]).def.type satisfies "union";
|
||||
z.intersection(z.string(), z.number()).def.type satisfies "intersection";
|
||||
z.tuple([z.string(), z.number()]).def.type satisfies "tuple";
|
||||
z.record(z.string(), z.number()).def.type satisfies "record";
|
||||
z.map(z.string(), z.number()).def.type satisfies "map";
|
||||
z.set(z.string()).def.type satisfies "set";
|
||||
z.literal("example").def.type satisfies "literal";
|
||||
z.enum(["a", "b", "c"]).def.type satisfies "enum";
|
||||
z.promise(z.string()).def.type satisfies "promise";
|
||||
z.lazy(() => z.string()).def.type satisfies "lazy";
|
||||
z.string().optional().def.type satisfies "optional";
|
||||
z.string().default("default").def.type satisfies "default";
|
||||
z.templateLiteral([z.literal("a"), z.literal("b")]).def.type satisfies "template_literal";
|
||||
z.custom<string>((val) => typeof val === "string").def.type satisfies "custom";
|
||||
z.transform((val) => val as string).def.type satisfies "transform";
|
||||
z.string().optional().nonoptional().def.type satisfies "nonoptional";
|
||||
z.object({ key: z.string() }).readonly().def.type satisfies "readonly";
|
||||
z.nan().def.type satisfies "nan";
|
||||
z.unknown().pipe(z.number()).def.type satisfies "pipe";
|
||||
z.success(z.string()).def.type satisfies "success";
|
||||
z.string().catch("fallback").def.type satisfies "catch";
|
||||
z.file().def.type satisfies "file";
|
||||
});
|
||||
|
||||
test("runtime type property exists and returns correct values", () => {
|
||||
const stringSchema = z.string();
|
||||
expect(stringSchema.type).toBe("string");
|
||||
});
|
||||
|
||||
test("type narrowing works with type property", () => {
|
||||
type ArrayOrRecord = z.ZodArray<z.ZodString> | z.ZodRecord<z.ZodString, z.ZodAny>;
|
||||
const arraySchema = z.array(z.string()) as ArrayOrRecord;
|
||||
|
||||
if (arraySchema.type === "array") {
|
||||
expectTypeOf(arraySchema).toEqualTypeOf<z.ZodArray<z.ZodString>>();
|
||||
expect(arraySchema.element).toBeDefined();
|
||||
}
|
||||
});
|
||||
60
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/instanceof.test.ts
generated
vendored
Normal file
60
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/instanceof.test.ts
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("instanceof", async () => {
|
||||
class Test {}
|
||||
class Subtest extends Test {}
|
||||
abstract class AbstractBar {
|
||||
constructor(public val: string) {}
|
||||
}
|
||||
class Bar extends AbstractBar {}
|
||||
|
||||
const TestSchema = z.instanceof(Test);
|
||||
const SubtestSchema = z.instanceof(Subtest);
|
||||
const AbstractSchema = z.instanceof(AbstractBar);
|
||||
const BarSchema = z.instanceof(Bar);
|
||||
|
||||
TestSchema.parse(new Test());
|
||||
TestSchema.parse(new Subtest());
|
||||
SubtestSchema.parse(new Subtest());
|
||||
AbstractSchema.parse(new Bar("asdf"));
|
||||
const bar = BarSchema.parse(new Bar("asdf"));
|
||||
expect(bar.val).toEqual("asdf");
|
||||
|
||||
await expect(() => SubtestSchema.parse(new Test())).toThrow();
|
||||
await expect(() => TestSchema.parse(12)).toThrow();
|
||||
|
||||
expectTypeOf<Test>().toEqualTypeOf<z.infer<typeof TestSchema>>();
|
||||
});
|
||||
|
||||
test("instanceof fatal", () => {
|
||||
const schema = z.instanceof(Date).refine((d) => d.toString());
|
||||
const res = schema.safeParse(null);
|
||||
expect(res.success).toBe(false);
|
||||
});
|
||||
|
||||
test("instanceof respects customError", () => {
|
||||
class Test {
|
||||
name!: string;
|
||||
}
|
||||
|
||||
z.config({
|
||||
customError: () => {
|
||||
return "This is invalid!";
|
||||
},
|
||||
});
|
||||
|
||||
const TestSchema = z.instanceof(Test);
|
||||
const result = TestSchema.safeParse("whatever");
|
||||
expect(result.success).toBe(false);
|
||||
if (!result.success) {
|
||||
const issue = result.error.issues[0];
|
||||
expect(issue.code).toBe("invalid_type");
|
||||
if (issue.code === "invalid_type") {
|
||||
expect(issue.expected).toBe("Test");
|
||||
}
|
||||
expect(issue.message).toBe("This is invalid!");
|
||||
}
|
||||
|
||||
z.config({ customError: undefined });
|
||||
});
|
||||
198
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/intersection.test.ts
generated
vendored
Normal file
198
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/intersection.test.ts
generated
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import type { util } from "zod/v4/core";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("object intersection", () => {
|
||||
const A = z.object({ a: z.string() });
|
||||
const B = z.object({ b: z.string() });
|
||||
|
||||
const C = z.intersection(A, B); // BaseC.merge(HasID);
|
||||
type C = z.infer<typeof C>;
|
||||
expectTypeOf<C>().toEqualTypeOf<{ a: string } & { b: string }>();
|
||||
const data = { a: "foo", b: "foo" };
|
||||
expect(C.parse(data)).toEqual(data);
|
||||
expect(() => C.parse({ a: "foo" })).toThrow();
|
||||
});
|
||||
|
||||
test("object intersection: loose", () => {
|
||||
const A = z.looseObject({ a: z.string() });
|
||||
const B = z.object({ b: z.string() });
|
||||
|
||||
const C = z.intersection(A, B); // BaseC.merge(HasID);
|
||||
type C = z.infer<typeof C>;
|
||||
expectTypeOf<C>().toEqualTypeOf<{ a: string; [x: string]: unknown } & { b: string }>();
|
||||
const data = { a: "foo", b: "foo", c: "extra" };
|
||||
expect(C.parse(data)).toEqual(data);
|
||||
expect(() => C.parse({ a: "foo" })).toThrow();
|
||||
});
|
||||
|
||||
test("object intersection: strict + strip", () => {
|
||||
const A = z.strictObject({ a: z.string() });
|
||||
const B = z.object({ b: z.string() });
|
||||
|
||||
const C = z.intersection(A, B);
|
||||
type C = z.infer<typeof C>;
|
||||
expectTypeOf<C>().toEqualTypeOf<{ a: string } & { b: string }>();
|
||||
|
||||
// Keys recognized by either side should work
|
||||
expect(C.parse({ a: "foo", b: "bar" })).toEqual({ a: "foo", b: "bar" });
|
||||
|
||||
// Extra keys are stripped (follows strip behavior from B)
|
||||
expect(C.parse({ a: "foo", b: "bar", c: "extra" })).toEqual({ a: "foo", b: "bar" });
|
||||
});
|
||||
|
||||
test("object intersection: strict + strict", () => {
|
||||
const A = z.strictObject({ a: z.string() });
|
||||
const B = z.strictObject({ b: z.string() });
|
||||
|
||||
const C = z.intersection(A, B);
|
||||
|
||||
// Keys recognized by either side should work
|
||||
expect(C.parse({ a: "foo", b: "bar" })).toEqual({ a: "foo", b: "bar" });
|
||||
|
||||
// Keys unrecognized by BOTH sides should error
|
||||
const result = C.safeParse({ a: "foo", b: "bar", c: "extra" });
|
||||
expect(result.error?.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": [
|
||||
"c",
|
||||
],
|
||||
"message": "Unrecognized key: "c"",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test("deep intersection", () => {
|
||||
const Animal = z.object({
|
||||
properties: z.object({
|
||||
is_animal: z.boolean(),
|
||||
}),
|
||||
});
|
||||
const Cat = z.intersection(
|
||||
z.object({
|
||||
properties: z.object({
|
||||
jumped: z.boolean(),
|
||||
}),
|
||||
}),
|
||||
Animal
|
||||
);
|
||||
|
||||
type Cat = util.Flatten<z.infer<typeof Cat>>;
|
||||
expectTypeOf<Cat>().toEqualTypeOf<{ properties: { is_animal: boolean } & { jumped: boolean } }>();
|
||||
const a = Cat.safeParse({ properties: { is_animal: true, jumped: true } });
|
||||
expect(a.data!.properties).toEqual({ is_animal: true, jumped: true });
|
||||
});
|
||||
|
||||
test("deep intersection of arrays", async () => {
|
||||
const Author = z.object({
|
||||
posts: z.array(
|
||||
z.object({
|
||||
post_id: z.number(),
|
||||
})
|
||||
),
|
||||
});
|
||||
const Registry = z.intersection(
|
||||
Author,
|
||||
z.object({
|
||||
posts: z.array(
|
||||
z.object({
|
||||
title: z.string(),
|
||||
})
|
||||
),
|
||||
})
|
||||
);
|
||||
|
||||
const posts = [
|
||||
{ post_id: 1, title: "Novels" },
|
||||
{ post_id: 2, title: "Fairy tales" },
|
||||
];
|
||||
const cat = Registry.parse({ posts });
|
||||
expect(cat.posts).toEqual(posts);
|
||||
const asyncCat = await Registry.parseAsync({ posts });
|
||||
expect(asyncCat.posts).toEqual(posts);
|
||||
});
|
||||
|
||||
test("invalid intersection types", async () => {
|
||||
const numberIntersection = z.intersection(
|
||||
z.number(),
|
||||
z.number().transform((x) => x + 1)
|
||||
);
|
||||
|
||||
expect(() => {
|
||||
numberIntersection.parse(1234);
|
||||
}).toThrowErrorMatchingInlineSnapshot(`[Error: Unmergable intersection. Error path: []]`);
|
||||
});
|
||||
|
||||
test("invalid array merge (incompatible lengths)", async () => {
|
||||
const stringArrInt = z.intersection(
|
||||
z.string().array(),
|
||||
z
|
||||
.string()
|
||||
.array()
|
||||
.transform((val) => [...val, "asdf"])
|
||||
);
|
||||
|
||||
expect(() => stringArrInt.safeParse(["asdf", "qwer"])).toThrowErrorMatchingInlineSnapshot(
|
||||
`[Error: Unmergable intersection. Error path: []]`
|
||||
);
|
||||
});
|
||||
|
||||
test("invalid array merge (incompatible elements)", async () => {
|
||||
const stringArrInt = z.intersection(
|
||||
z.string().array(),
|
||||
z
|
||||
.string()
|
||||
.array()
|
||||
.transform((val) => [...val.slice(0, -1), "asdf"])
|
||||
);
|
||||
|
||||
expect(() => stringArrInt.safeParse(["asdf", "qwer"])).toThrowErrorMatchingInlineSnapshot(
|
||||
`[Error: Unmergable intersection. Error path: [1]]`
|
||||
);
|
||||
});
|
||||
|
||||
test("invalid object merge", async () => {
|
||||
const Cat = z.object({
|
||||
phrase: z.string().transform((val) => `${val} Meow`),
|
||||
});
|
||||
const Dog = z.object({
|
||||
phrase: z.string().transform((val) => `${val} Woof`),
|
||||
});
|
||||
const CatDog = z.intersection(Cat, Dog);
|
||||
|
||||
expect(() => CatDog.parse({ phrase: "Hello, my name is CatDog." })).toThrowErrorMatchingInlineSnapshot(
|
||||
`[Error: Unmergable intersection. Error path: ["phrase"]]`
|
||||
);
|
||||
});
|
||||
|
||||
test("invalid deep merge of object and array combination", async () => {
|
||||
const University = z.object({
|
||||
students: z.array(
|
||||
z.object({
|
||||
name: z.string().transform((val) => `Student name: ${val}`),
|
||||
})
|
||||
),
|
||||
});
|
||||
const Registry = z.intersection(
|
||||
University,
|
||||
z.object({
|
||||
students: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
surname: z.string(),
|
||||
})
|
||||
),
|
||||
})
|
||||
);
|
||||
|
||||
const students = [{ name: "John", surname: "Doe" }];
|
||||
|
||||
expect(() => Registry.parse({ students })).toThrowErrorMatchingInlineSnapshot(
|
||||
`[Error: Unmergable intersection. Error path: ["students",0,"name"]]`
|
||||
);
|
||||
});
|
||||
109
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/json.test.ts
generated
vendored
Normal file
109
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/json.test.ts
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
test("placeholder test", () => {
|
||||
expect(2).toBe(2);
|
||||
});
|
||||
// test("overload types", () => {
|
||||
// const schema = z.string().json();
|
||||
// util.assertEqual<typeof schema, z.ZodString>(true);
|
||||
// const schema2 = z.string().json(z.number());
|
||||
// util.assertEqual<typeof schema2, z.ZodPipe<z.ZodTransform<any, string>, z.ZodNumber>>(true);
|
||||
// const r2 = schema2.parse("12");
|
||||
// util.assertEqual<number, typeof r2>(true);
|
||||
// });
|
||||
// test("parse string to json", async () => {
|
||||
// const Env = z.object({
|
||||
// myJsonConfig: z.string().jsonString(z.object({ foo: z.number() })),
|
||||
// someOtherValue: z.string(),
|
||||
// });
|
||||
|
||||
// expect(
|
||||
// Env.parse({
|
||||
// myJsonConfig: '{ "foo": 123 }',
|
||||
// someOtherValue: "abc",
|
||||
// })
|
||||
// ).toEqual({
|
||||
// myJsonConfig: { foo: 123 },
|
||||
// someOtherValue: "abc",
|
||||
// });
|
||||
|
||||
// const invalidValues = Env.safeParse({
|
||||
// myJsonConfig: '{"foo": "not a number!"}',
|
||||
// someOtherValue: null,
|
||||
// });
|
||||
// expect(JSON.parse(JSON.stringify(invalidValues))).toEqual({
|
||||
// success: false,
|
||||
// error: {
|
||||
// name: "ZodError",
|
||||
// issues: [
|
||||
// {
|
||||
// code: "invalid_type",
|
||||
// expected: "number",
|
||||
// input: "not a number!",
|
||||
// received: "string",
|
||||
// path: ["myJsonConfig", "foo"],
|
||||
// message: "Expected number, received string",
|
||||
// },
|
||||
// {
|
||||
// code: "invalid_type",
|
||||
// expected: "string",
|
||||
// input: null,
|
||||
// received: "null",
|
||||
// path: ["someOtherValue"],
|
||||
// message: "Expected string, received null",
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// });
|
||||
|
||||
// const invalidJsonSyntax = Env.safeParse({
|
||||
// myJsonConfig: "This is not valid json",
|
||||
// someOtherValue: null,
|
||||
// });
|
||||
// expect(JSON.parse(JSON.stringify(invalidJsonSyntax))).toMatchObject({
|
||||
// success: false,
|
||||
// error: {
|
||||
// name: "ZodError",
|
||||
// issues: [
|
||||
// {
|
||||
// code: "invalid_string",
|
||||
// input: {
|
||||
// _def: {
|
||||
// catchall: {
|
||||
// _def: {
|
||||
// typeName: "ZodNever",
|
||||
// },
|
||||
// },
|
||||
// typeName: "ZodObject",
|
||||
// unknownKeys: "strip",
|
||||
// },
|
||||
// },
|
||||
// validation: "json",
|
||||
// message: "Invalid json",
|
||||
// path: ["myJsonConfig"],
|
||||
// },
|
||||
// {
|
||||
// code: "invalid_type",
|
||||
// expected: "string",
|
||||
// input: null,
|
||||
// received: "null",
|
||||
// path: ["someOtherValue"],
|
||||
// message: "Expected string, received null",
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// });
|
||||
// });
|
||||
|
||||
// test("no argument", () => {
|
||||
// const schema = z.string().json();
|
||||
// util.assertEqual<typeof schema, z.ZodString>(true);
|
||||
// z.string().json().parse(`{}`);
|
||||
// z.string().json().parse(`null`);
|
||||
// z.string().json().parse(`12`);
|
||||
// z.string().json().parse(`{ "test": "test"}`);
|
||||
// expect(() => z.string().json().parse(`asdf`)).toThrow();
|
||||
// expect(() => z.string().json().parse(`{ "test": undefined }`)).toThrow();
|
||||
// expect(() => z.string().json().parse(`{ "test": 12n }`)).toThrow();
|
||||
// expect(() => z.string().json().parse(`{ test: "test" }`)).toThrow();
|
||||
// });
|
||||
227
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/lazy.test.ts
generated
vendored
Normal file
227
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/lazy.test.ts
generated
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("opt passthrough", () => {
|
||||
const object = z.object({
|
||||
a: z.lazy(() => z.string()),
|
||||
b: z.lazy(() => z.string().optional()),
|
||||
c: z.lazy(() => z.string().default("default")),
|
||||
});
|
||||
|
||||
type ObjectTypeIn = z.input<typeof object>;
|
||||
expectTypeOf<ObjectTypeIn>().toEqualTypeOf<{
|
||||
a: string;
|
||||
b?: string | undefined;
|
||||
c?: string | undefined;
|
||||
}>();
|
||||
|
||||
type ObjectTypeOut = z.output<typeof object>;
|
||||
expectTypeOf<ObjectTypeOut>().toEqualTypeOf<{
|
||||
a: string;
|
||||
b?: string | undefined;
|
||||
c: string;
|
||||
}>();
|
||||
|
||||
const result = object.parse(
|
||||
{
|
||||
a: "hello",
|
||||
b: undefined,
|
||||
},
|
||||
{ jitless: true }
|
||||
);
|
||||
expect(result).toEqual({
|
||||
a: "hello",
|
||||
// b: undefined,
|
||||
c: "default",
|
||||
});
|
||||
|
||||
expect(z.lazy(() => z.string())._zod.optin).toEqual(undefined);
|
||||
expect(z.lazy(() => z.string())._zod.optout).toEqual(undefined);
|
||||
|
||||
expect(z.lazy(() => z.string().optional())._zod.optin).toEqual("optional");
|
||||
expect(z.lazy(() => z.string().optional())._zod.optout).toEqual("optional");
|
||||
|
||||
expect(z.lazy(() => z.string().default("asdf"))._zod.optin).toEqual("optional");
|
||||
expect(z.lazy(() => z.string().default("asdf"))._zod.optout).toEqual(undefined);
|
||||
});
|
||||
|
||||
////////////// LAZY //////////////
|
||||
|
||||
test("schema getter", () => {
|
||||
z.lazy(() => z.string()).parse("asdf");
|
||||
});
|
||||
|
||||
test("lazy proxy", () => {
|
||||
const schema = z.lazy(() => z.string())._zod.innerType.min(6);
|
||||
schema.parse("123456");
|
||||
expect(schema.safeParse("12345").success).toBe(false);
|
||||
});
|
||||
|
||||
interface Category {
|
||||
name: string;
|
||||
subcategories: Category[];
|
||||
}
|
||||
|
||||
const testCategory: Category = {
|
||||
name: "I",
|
||||
subcategories: [
|
||||
{
|
||||
name: "A",
|
||||
subcategories: [
|
||||
{
|
||||
name: "1",
|
||||
subcategories: [
|
||||
{
|
||||
name: "a",
|
||||
subcategories: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
test("recursion with z.lazy", () => {
|
||||
const Category: z.ZodType<Category> = z.lazy(() =>
|
||||
z.object({
|
||||
name: z.string(),
|
||||
subcategories: z.array(Category),
|
||||
})
|
||||
);
|
||||
Category.parse(testCategory);
|
||||
});
|
||||
|
||||
type LinkedList = null | { value: number; next: LinkedList };
|
||||
|
||||
const linkedListExample = {
|
||||
value: 1,
|
||||
next: {
|
||||
value: 2,
|
||||
next: {
|
||||
value: 3,
|
||||
next: {
|
||||
value: 4,
|
||||
next: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
test("recursive union wit z.lazy", () => {
|
||||
const LinkedListSchema: z.ZodType<LinkedList> = z.lazy(() =>
|
||||
z.union([
|
||||
z.null(),
|
||||
z.object({
|
||||
value: z.number(),
|
||||
next: LinkedListSchema,
|
||||
}),
|
||||
])
|
||||
);
|
||||
LinkedListSchema.parse(linkedListExample);
|
||||
});
|
||||
|
||||
interface A {
|
||||
val: number;
|
||||
b: B;
|
||||
}
|
||||
|
||||
interface B {
|
||||
val: number;
|
||||
a?: A | undefined;
|
||||
}
|
||||
|
||||
test("mutual recursion with lazy", () => {
|
||||
const Alazy: z.ZodType<A> = z.lazy(() =>
|
||||
z.object({
|
||||
val: z.number(),
|
||||
b: Blazy,
|
||||
})
|
||||
);
|
||||
|
||||
const Blazy: z.ZodType<B> = z.lazy(() =>
|
||||
z.object({
|
||||
val: z.number(),
|
||||
a: Alazy.optional(),
|
||||
})
|
||||
);
|
||||
|
||||
const testData = {
|
||||
val: 1,
|
||||
b: {
|
||||
val: 5,
|
||||
a: {
|
||||
val: 3,
|
||||
b: {
|
||||
val: 4,
|
||||
a: {
|
||||
val: 2,
|
||||
b: {
|
||||
val: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Alazy.parse(testData);
|
||||
Blazy.parse(testData.b);
|
||||
|
||||
expect(() => Alazy.parse({ val: "asdf" })).toThrow();
|
||||
});
|
||||
|
||||
// TODO
|
||||
test("mutual recursion with cyclical data", () => {
|
||||
const a: any = { val: 1 };
|
||||
const b: any = { val: 2 };
|
||||
a.b = b;
|
||||
b.a = a;
|
||||
});
|
||||
|
||||
test("complicated self-recursion", () => {
|
||||
const Category = z.object({
|
||||
name: z.string(),
|
||||
age: z.optional(z.number()),
|
||||
get nullself() {
|
||||
return Category.nullable();
|
||||
},
|
||||
get optself() {
|
||||
return Category.optional();
|
||||
},
|
||||
get self() {
|
||||
return Category;
|
||||
},
|
||||
get subcategories() {
|
||||
return z.array(Category);
|
||||
},
|
||||
nested: z.object({
|
||||
get sub() {
|
||||
return Category;
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
type _Category = z.output<typeof Category>;
|
||||
});
|
||||
|
||||
test("lazy initialization", () => {
|
||||
const a: any = z.lazy(() => a).optional();
|
||||
const b: any = z.lazy(() => b).nullable();
|
||||
const c: any = z.lazy(() => c).default({} as any);
|
||||
const d: any = z.lazy(() => d).prefault({} as any);
|
||||
const e: any = z.lazy(() => e).nonoptional();
|
||||
const f: any = z.lazy(() => f).catch({} as any);
|
||||
const g: any = z.lazy(() => z.object({ g })).readonly();
|
||||
|
||||
const baseCategorySchema = z.object({
|
||||
name: z.string(),
|
||||
});
|
||||
type Category = z.infer<typeof baseCategorySchema> & {
|
||||
subcategories: Category[];
|
||||
};
|
||||
const categorySchema: z.ZodType<Category> = baseCategorySchema.extend({
|
||||
subcategories: z.lazy(() => categorySchema.array()),
|
||||
});
|
||||
});
|
||||
117
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/literal.test.ts
generated
vendored
Normal file
117
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/literal.test.ts
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const literalTuna = z.literal("tuna");
|
||||
const literalTunaCustomMessage = z.literal("tuna", {
|
||||
message: "That's not a tuna",
|
||||
});
|
||||
const literalFortyTwo = z.literal(42);
|
||||
const literalTrue = z.literal(true);
|
||||
|
||||
test("passing validations", () => {
|
||||
literalTuna.parse("tuna");
|
||||
literalFortyTwo.parse(42);
|
||||
literalTrue.parse(true);
|
||||
});
|
||||
|
||||
test("failing validations", () => {
|
||||
expect(() => literalTuna.parse("shark")).toThrow();
|
||||
expect(() => literalFortyTwo.parse(43)).toThrow();
|
||||
expect(() => literalTrue.parse(false)).toThrow();
|
||||
});
|
||||
|
||||
test("invalid_literal should have `input` field with data", () => {
|
||||
const data = "shark";
|
||||
const result = literalTuna.safeParse(data);
|
||||
|
||||
const issue = result.error!.issues[0];
|
||||
expect(issue.code).toBe("invalid_value");
|
||||
expect(issue).toMatchInlineSnapshot(`
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"message": "Invalid input: expected "tuna"",
|
||||
"path": [],
|
||||
"values": [
|
||||
"tuna",
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("invalid_literal should return default message", () => {
|
||||
const data = "shark";
|
||||
const result = literalTuna.safeParse(data);
|
||||
|
||||
const issue = result.error!.issues[0];
|
||||
expect(issue.message).toEqual(`Invalid input: expected \"tuna\"`);
|
||||
});
|
||||
|
||||
test("invalid_literal should return custom message", () => {
|
||||
const data = "shark";
|
||||
const result = literalTunaCustomMessage.safeParse(data);
|
||||
|
||||
const issue = result.error!.issues[0];
|
||||
expect(issue.message).toEqual(`That's not a tuna`);
|
||||
});
|
||||
|
||||
test("literal default error message", () => {
|
||||
const result = z.literal("Tuna").safeParse("Trout");
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"Tuna"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid input: expected \\"Tuna\\""
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("literal bigint default error message", () => {
|
||||
const result = z.literal(BigInt(12)).safeParse(BigInt(13));
|
||||
expect(result.success).toBe(false);
|
||||
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error!.issues[0].message).toEqual(`Invalid input: expected 12n`);
|
||||
});
|
||||
|
||||
test(".value getter", () => {
|
||||
expect(z.literal("tuna").value).toEqual("tuna");
|
||||
expect(() => z.literal([1, 2, 3]).value).toThrow();
|
||||
});
|
||||
|
||||
test("readonly", () => {
|
||||
const a = ["asdf"] as const;
|
||||
z.literal(a);
|
||||
});
|
||||
|
||||
test("literal pattern", () => {
|
||||
expect(z.literal(1.1)._zod.pattern).toMatchInlineSnapshot(`/\\^\\(1\\\\\\.1\\)\\$/`);
|
||||
|
||||
expect(z.templateLiteral([z.literal(1.1)]).safeParse("1.1")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": "1.1",
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
expect(z.templateLiteral([z.literal(1.1)]).safeParse("1n1")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^(1\\\\.1)$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
330
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/map.test.ts
generated
vendored
Normal file
330
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/map.test.ts
generated
vendored
Normal file
@@ -0,0 +1,330 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const stringMap = z.map(z.string(), z.string());
|
||||
type stringMap = z.infer<typeof stringMap>;
|
||||
|
||||
const minTwo = stringMap.min(2);
|
||||
const maxTwo = stringMap.max(2);
|
||||
const justTwo = stringMap.size(2);
|
||||
const nonEmpty = stringMap.nonempty();
|
||||
const nonEmptyMax = stringMap.nonempty().max(2);
|
||||
|
||||
test("type inference", () => {
|
||||
expectTypeOf<stringMap>().toEqualTypeOf<Map<string, string>>();
|
||||
});
|
||||
|
||||
test("valid parse", () => {
|
||||
const result = stringMap.safeParse(
|
||||
new Map([
|
||||
["first", "foo"],
|
||||
["second", "bar"],
|
||||
])
|
||||
);
|
||||
expect(result.success).toEqual(true);
|
||||
expect(result.data).toMatchInlineSnapshot(`
|
||||
Map {
|
||||
"first" => "foo",
|
||||
"second" => "bar",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("valid parse: size-related methods", () => {
|
||||
expect(() => {
|
||||
minTwo.parse(
|
||||
new Map([
|
||||
["a", "b"],
|
||||
["c", "d"],
|
||||
])
|
||||
);
|
||||
minTwo.parse(
|
||||
new Map([
|
||||
["a", "b"],
|
||||
["c", "d"],
|
||||
["e", "f"],
|
||||
])
|
||||
);
|
||||
maxTwo.parse(
|
||||
new Map([
|
||||
["a", "b"],
|
||||
["c", "d"],
|
||||
])
|
||||
);
|
||||
maxTwo.parse(new Map([["a", "b"]]));
|
||||
justTwo.parse(
|
||||
new Map([
|
||||
["a", "b"],
|
||||
["c", "d"],
|
||||
])
|
||||
);
|
||||
nonEmpty.parse(new Map([["a", "b"]]));
|
||||
nonEmptyMax.parse(
|
||||
new Map([
|
||||
["a", "b"],
|
||||
["c", "d"],
|
||||
])
|
||||
);
|
||||
}).not.toThrow();
|
||||
|
||||
const sizeZeroResult = stringMap.parse(new Map());
|
||||
expect(sizeZeroResult.size).toBe(0);
|
||||
|
||||
const sizeTwoResult = minTwo.parse(
|
||||
new Map([
|
||||
["a", "b"],
|
||||
["c", "d"],
|
||||
])
|
||||
);
|
||||
expect(sizeTwoResult.size).toBe(2);
|
||||
});
|
||||
|
||||
test("failing when parsing empty map in nonempty ", () => {
|
||||
const result = nonEmpty.safeParse(new Map());
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error!.issues[0].code).toEqual("too_small");
|
||||
});
|
||||
|
||||
test("failing when map is bigger than max() ", () => {
|
||||
const result = maxTwo.safeParse(
|
||||
new Map([
|
||||
["a", "b"],
|
||||
["c", "d"],
|
||||
["e", "f"],
|
||||
])
|
||||
);
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error!.issues[0].code).toEqual("too_big");
|
||||
});
|
||||
|
||||
test("valid parse async", async () => {
|
||||
const asyncMap = z.map(
|
||||
z.string().refine(async () => false, "bad key"),
|
||||
z.string().refine(async () => false, "bad value")
|
||||
);
|
||||
const result = await asyncMap.safeParseAsync(new Map([["first", "foo"]]));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"first"
|
||||
],
|
||||
"message": "bad key"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"first"
|
||||
],
|
||||
"message": "bad value"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("throws when a Set is given", () => {
|
||||
const result = stringMap.safeParse(new Set([]));
|
||||
expect(result.success).toEqual(false);
|
||||
if (result.success === false) {
|
||||
expect(result.error.issues.length).toEqual(1);
|
||||
expect(result.error.issues[0].code).toEqual("invalid_type");
|
||||
}
|
||||
});
|
||||
|
||||
test("throws when the given map has invalid key and invalid input", () => {
|
||||
const result = stringMap.safeParse(new Map([[42, Symbol()]]));
|
||||
expect(result.success).toEqual(false);
|
||||
if (result.success === false) {
|
||||
expect(result.error.issues.length).toEqual(2);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
42
|
||||
],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
42
|
||||
],
|
||||
"message": "Invalid input: expected string, received symbol"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("throws when the given map has multiple invalid entries", () => {
|
||||
// const result = stringMap.safeParse(new Map([[42, Symbol()]]));
|
||||
|
||||
const result = stringMap.safeParse(
|
||||
new Map([
|
||||
[1, "foo"],
|
||||
["bar", 2],
|
||||
] as [any, any][]) as Map<any, any>
|
||||
);
|
||||
|
||||
// const result = stringMap.safeParse(new Map([[42, Symbol()]]));
|
||||
expect(result.success).toEqual(false);
|
||||
if (result.success === false) {
|
||||
expect(result.error.issues.length).toEqual(2);
|
||||
expect(result.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received number",
|
||||
"path": [
|
||||
1,
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received number",
|
||||
"path": [
|
||||
"bar",
|
||||
],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("dirty", async () => {
|
||||
const map = z.map(
|
||||
z.string().refine((val) => val === val.toUpperCase(), {
|
||||
message: "Keys must be uppercase",
|
||||
}),
|
||||
z.string()
|
||||
);
|
||||
const result = await map.spa(
|
||||
new Map([
|
||||
["first", "foo"],
|
||||
["second", "bar"],
|
||||
])
|
||||
);
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(2);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"first"
|
||||
],
|
||||
"message": "Keys must be uppercase"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"second"
|
||||
],
|
||||
"message": "Keys must be uppercase"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("map with object keys", () => {
|
||||
const map = z.map(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
}),
|
||||
z.string()
|
||||
);
|
||||
const data = new Map([
|
||||
[{ name: "John", age: 30 }, "foo"],
|
||||
[{ name: "Jane", age: 25 }, "bar"],
|
||||
]);
|
||||
const result = map.safeParse(data);
|
||||
expect(result.success).toEqual(true);
|
||||
expect(result.data!).toEqual(data);
|
||||
|
||||
const badData = new Map([["bad", "foo"]]);
|
||||
const badResult = map.safeParse(badData);
|
||||
expect(badResult.success).toEqual(false);
|
||||
expect(badResult.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "object",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"bad"
|
||||
],
|
||||
"message": "Invalid input: expected object, received string"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("min/max", async () => {
|
||||
const schema = stringMap.min(4).max(5);
|
||||
|
||||
const r1 = schema.safeParse(
|
||||
new Map([
|
||||
["a", "a"],
|
||||
["b", "b"],
|
||||
["c", "c"],
|
||||
["d", "d"],
|
||||
])
|
||||
);
|
||||
expect(r1.success).toEqual(true);
|
||||
|
||||
const r2 = schema.safeParse(
|
||||
new Map([
|
||||
["a", "a"],
|
||||
["b", "b"],
|
||||
["c", "c"],
|
||||
])
|
||||
);
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected map to have >=4 entries",
|
||||
"minimum": 4,
|
||||
"origin": "map",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
||||
const r3 = schema.safeParse(
|
||||
new Map([
|
||||
["a", "a"],
|
||||
["b", "b"],
|
||||
["c", "c"],
|
||||
["d", "d"],
|
||||
["e", "e"],
|
||||
["f", "f"],
|
||||
])
|
||||
);
|
||||
expect(r3.success).toEqual(false);
|
||||
expect(r3.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 5,
|
||||
"message": "Too big: expected map to have <=5 entries",
|
||||
"origin": "map",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
21
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/nan.test.ts
generated
vendored
Normal file
21
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/nan.test.ts
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const schema = z.nan();
|
||||
|
||||
test("passing validations", () => {
|
||||
schema.parse(Number.NaN);
|
||||
schema.parse(Number("Not a number"));
|
||||
expectTypeOf<typeof schema._output>().toEqualTypeOf<number>();
|
||||
});
|
||||
|
||||
test("failing validations", () => {
|
||||
expect(() => schema.parse(5)).toThrow();
|
||||
expect(() => schema.parse("John")).toThrow();
|
||||
expect(() => schema.parse(true)).toThrow();
|
||||
expect(() => schema.parse(null)).toThrow();
|
||||
expect(() => schema.parse(undefined)).toThrow();
|
||||
expect(() => schema.parse({})).toThrow();
|
||||
expect(() => schema.parse([])).toThrow();
|
||||
});
|
||||
168
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/nested-refine.test.ts
generated
vendored
Normal file
168
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/nested-refine.test.ts
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("nested refinements", () => {
|
||||
const zodSchema = z
|
||||
.object({
|
||||
password: z.string().min(1),
|
||||
nested: z
|
||||
.object({
|
||||
confirm: z
|
||||
.string()
|
||||
.min(1)
|
||||
.refine((value) => value.length > 2, {
|
||||
message: "Confirm length should be > 2",
|
||||
}),
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
return data.confirm === "bar";
|
||||
},
|
||||
{
|
||||
path: ["confirm"],
|
||||
error: 'Value must be "bar"',
|
||||
}
|
||||
),
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
return data.nested.confirm === data.password;
|
||||
},
|
||||
{
|
||||
path: ["nested", "confirm"],
|
||||
error: "Password and confirm must match",
|
||||
}
|
||||
);
|
||||
|
||||
const DATA = {
|
||||
password: "bar",
|
||||
nested: { confirm: "" },
|
||||
};
|
||||
expect(zodSchema.safeParse(DATA)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 1,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Too small: expected string to have >=1 characters"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Confirm length should be > 2"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Value must be \\"bar\\""
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Password and confirm must match"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(zodSchema.safeParse(DATA, { jitless: true })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 1,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Too small: expected string to have >=1 characters"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Confirm length should be > 2"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Value must be \\"bar\\""
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm"
|
||||
],
|
||||
"message": "Password and confirm must match"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(zodSchema["~standard"].validate(DATA)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"issues": [
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected string to have >=1 characters",
|
||||
"minimum": 1,
|
||||
"origin": "string",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Confirm length should be > 2",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Value must be "bar"",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm",
|
||||
],
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Password and confirm must match",
|
||||
"path": [
|
||||
"nested",
|
||||
"confirm",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
101
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/nonoptional.test.ts
generated
vendored
Normal file
101
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/nonoptional.test.ts
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
test("nonoptional", () => {
|
||||
const schema = z.string().nonoptional();
|
||||
expectTypeOf<typeof schema._input>().toEqualTypeOf<string>();
|
||||
expectTypeOf<typeof schema._output>().toEqualTypeOf<string>();
|
||||
|
||||
const result = schema.safeParse(undefined);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("nonoptional with default", () => {
|
||||
const schema = z.string().optional().nonoptional();
|
||||
expectTypeOf<typeof schema._input>().toEqualTypeOf<string>();
|
||||
expectTypeOf<typeof schema._output>().toEqualTypeOf<string>();
|
||||
|
||||
const result = schema.safeParse(undefined);
|
||||
expect(result.success).toBe(false);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "nonoptional",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected nonoptional, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("nonoptional in object", () => {
|
||||
const schema = z.object({ hi: z.string().optional().nonoptional() });
|
||||
|
||||
expectTypeOf<typeof schema._input>().toEqualTypeOf<{ hi: string }>();
|
||||
expectTypeOf<typeof schema._output>().toEqualTypeOf<{ hi: string }>();
|
||||
const r1 = schema.safeParse({ hi: "asdf" });
|
||||
expect(r1.success).toEqual(true);
|
||||
|
||||
const r2 = schema.safeParse({ hi: undefined });
|
||||
// expect(schema.safeParse({ hi: undefined }).success).toEqual(false);
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "nonoptional",
|
||||
"path": [
|
||||
"hi"
|
||||
],
|
||||
"message": "Invalid input: expected nonoptional, received undefined"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const r3 = schema.safeParse({});
|
||||
expect(r3.success).toEqual(false);
|
||||
expect(r3.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "nonoptional",
|
||||
"path": [
|
||||
"hi"
|
||||
],
|
||||
"message": "Invalid input: expected nonoptional, received undefined"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("encoding", () => {
|
||||
const schema = z.string().optional().nonoptional();
|
||||
expect(z.encode(schema, "hello")).toEqual("hello");
|
||||
expect(() => z.encode(schema, undefined as any)).toThrowErrorMatchingInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "nonoptional",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected nonoptional, received undefined"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
22
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/nullable.test.ts
generated
vendored
Normal file
22
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/nullable.test.ts
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test(".nullable()", () => {
|
||||
const nullable = z.string().nullable();
|
||||
expect(nullable.parse(null)).toBe(null);
|
||||
expect(nullable.parse("asdf")).toBe("asdf");
|
||||
expect(() => nullable.parse(123)).toThrow();
|
||||
});
|
||||
|
||||
test(".nullable unwrap", () => {
|
||||
const schema = z.string().nullable();
|
||||
expect(schema).toBeInstanceOf(z.ZodNullable);
|
||||
expect(schema.unwrap()).toBeInstanceOf(z.ZodString);
|
||||
});
|
||||
|
||||
test("z.null", () => {
|
||||
const n = z.null();
|
||||
expect(n.parse(null)).toBe(null);
|
||||
expect(() => n.parse("asdf")).toThrow();
|
||||
});
|
||||
270
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/number.test.ts
generated
vendored
Normal file
270
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/number.test.ts
generated
vendored
Normal file
@@ -0,0 +1,270 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("z.number() basic validation", () => {
|
||||
const schema = z.number();
|
||||
expect(schema.parse(1234)).toEqual(1234);
|
||||
});
|
||||
|
||||
test("NaN validation", () => {
|
||||
const schema = z.number();
|
||||
expect(() => schema.parse(Number.NaN)).toThrow();
|
||||
});
|
||||
|
||||
test("Infinity validation", () => {
|
||||
const schema = z.number();
|
||||
expect(schema.safeParse(Number.POSITIVE_INFINITY)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"received": "Infinity",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected number, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse(Number.NEGATIVE_INFINITY)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"received": "Infinity",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected number, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test(".gt() validation", () => {
|
||||
const schema = z.number().gt(0).gt(5);
|
||||
expect(schema.parse(6)).toEqual(6);
|
||||
expect(() => schema.parse(5)).toThrow();
|
||||
});
|
||||
|
||||
test(".gte() validation", () => {
|
||||
const schema = z.number().gt(0).gte(1).gte(5);
|
||||
expect(schema.parse(5)).toEqual(5);
|
||||
expect(() => schema.parse(4)).toThrow();
|
||||
});
|
||||
|
||||
test(".min() validation", () => {
|
||||
const schema = z.number().min(0).min(5);
|
||||
expect(schema.parse(5)).toEqual(5);
|
||||
expect(() => schema.parse(4)).toThrow();
|
||||
});
|
||||
|
||||
test(".lt() validation", () => {
|
||||
const schema = z.number().lte(10).lt(5);
|
||||
expect(schema.parse(4)).toEqual(4);
|
||||
expect(() => schema.parse(5)).toThrow();
|
||||
});
|
||||
|
||||
test(".lte() validation", () => {
|
||||
const schema = z.number().lte(10).lte(5);
|
||||
expect(schema.parse(5)).toEqual(5);
|
||||
expect(() => schema.parse(6)).toThrow();
|
||||
});
|
||||
|
||||
test(".max() validation", () => {
|
||||
const schema = z.number().max(10).max(5);
|
||||
expect(schema.parse(5)).toEqual(5);
|
||||
expect(() => schema.parse(6)).toThrow();
|
||||
});
|
||||
|
||||
test(".int() validation", () => {
|
||||
const schema = z.number().int();
|
||||
expect(schema.parse(4)).toEqual(4);
|
||||
expect(() => schema.parse(3.14)).toThrow();
|
||||
});
|
||||
|
||||
test(".positive() validation", () => {
|
||||
const schema = z.number().positive();
|
||||
expect(schema.parse(1)).toEqual(1);
|
||||
expect(() => schema.parse(0)).toThrow();
|
||||
expect(() => schema.parse(-1)).toThrow();
|
||||
});
|
||||
|
||||
test(".negative() validation", () => {
|
||||
const schema = z.number().negative();
|
||||
expect(schema.parse(-1)).toEqual(-1);
|
||||
expect(() => schema.parse(0)).toThrow();
|
||||
expect(() => schema.parse(1)).toThrow();
|
||||
});
|
||||
|
||||
test(".nonpositive() validation", () => {
|
||||
const schema = z.number().nonpositive();
|
||||
expect(schema.parse(0)).toEqual(0);
|
||||
expect(schema.parse(-1)).toEqual(-1);
|
||||
expect(() => schema.parse(1)).toThrow();
|
||||
});
|
||||
|
||||
test(".nonnegative() validation", () => {
|
||||
const schema = z.number().nonnegative();
|
||||
expect(schema.parse(0)).toEqual(0);
|
||||
expect(schema.parse(1)).toEqual(1);
|
||||
expect(() => schema.parse(-1)).toThrow();
|
||||
});
|
||||
|
||||
test("multipleOf", () => {
|
||||
const numbers = {
|
||||
number3: 5.123,
|
||||
number6: 5.123456,
|
||||
number7: 5.1234567,
|
||||
number8: 5.12345678,
|
||||
};
|
||||
|
||||
const schemas = {
|
||||
schema6: z.number().multipleOf(0.000001),
|
||||
schema7: z.number().multipleOf(0.0000001),
|
||||
};
|
||||
|
||||
expect(() => schemas.schema6.parse(numbers.number3)).not.toThrow();
|
||||
expect(() => schemas.schema6.parse(numbers.number6)).not.toThrow();
|
||||
expect(() => schemas.schema6.parse(numbers.number7)).toThrow();
|
||||
expect(() => schemas.schema6.parse(numbers.number8)).toThrow();
|
||||
expect(() => schemas.schema7.parse(numbers.number3)).not.toThrow();
|
||||
expect(() => schemas.schema7.parse(numbers.number6)).not.toThrow();
|
||||
expect(() => schemas.schema7.parse(numbers.number7)).not.toThrow();
|
||||
expect(() => schemas.schema7.parse(numbers.number8)).toThrow();
|
||||
});
|
||||
|
||||
test(".multipleOf() with positive divisor", () => {
|
||||
const schema = z.number().multipleOf(5);
|
||||
expect(schema.parse(15)).toEqual(15);
|
||||
expect(schema.parse(-15)).toEqual(-15);
|
||||
expect(() => schema.parse(7.5)).toThrow();
|
||||
expect(() => schema.parse(-7.5)).toThrow();
|
||||
});
|
||||
|
||||
test(".multipleOf() with negative divisor", () => {
|
||||
const schema = z.number().multipleOf(-5);
|
||||
expect(schema.parse(-15)).toEqual(-15);
|
||||
expect(schema.parse(15)).toEqual(15);
|
||||
expect(() => schema.parse(-7.5)).toThrow();
|
||||
expect(() => schema.parse(7.5)).toThrow();
|
||||
});
|
||||
|
||||
test(".step() validation", () => {
|
||||
const schemaPointOne = z.number().step(0.1);
|
||||
const schemaPointZeroZeroZeroOne = z.number().step(0.0001);
|
||||
const schemaSixPointFour = z.number().step(6.4);
|
||||
|
||||
expect(schemaPointOne.parse(6)).toEqual(6);
|
||||
expect(schemaPointOne.parse(6.1)).toEqual(6.1);
|
||||
expect(schemaSixPointFour.parse(12.8)).toEqual(12.8);
|
||||
expect(schemaPointZeroZeroZeroOne.parse(3.01)).toEqual(3.01);
|
||||
expect(() => schemaPointOne.parse(6.11)).toThrow();
|
||||
expect(() => schemaPointOne.parse(6.1000000001)).toThrow();
|
||||
expect(() => schemaSixPointFour.parse(6.41)).toThrow();
|
||||
});
|
||||
|
||||
test(".finite() validation", () => {
|
||||
const schema = z.number().finite();
|
||||
expect(schema.parse(123)).toEqual(123);
|
||||
expect(schema.safeParse(Number.POSITIVE_INFINITY)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"received": "Infinity",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected number, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse(Number.NEGATIVE_INFINITY)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"received": "Infinity",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected number, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test(".safe() validation", () => {
|
||||
const schema = z.number().safe();
|
||||
expect(schema.parse(Number.MIN_SAFE_INTEGER)).toEqual(Number.MIN_SAFE_INTEGER);
|
||||
expect(schema.parse(Number.MAX_SAFE_INTEGER)).toEqual(Number.MAX_SAFE_INTEGER);
|
||||
expect(() => schema.parse(Number.MIN_SAFE_INTEGER - 1)).toThrow();
|
||||
expect(() => schema.parse(Number.MAX_SAFE_INTEGER + 1)).toThrow();
|
||||
});
|
||||
|
||||
test("min value getters", () => {
|
||||
expect(z.number().minValue).toBeNull;
|
||||
expect(z.number().lt(5).minValue).toBeNull;
|
||||
expect(z.number().lte(5).minValue).toBeNull;
|
||||
expect(z.number().max(5).minValue).toBeNull;
|
||||
expect(z.number().negative().minValue).toBeNull;
|
||||
expect(z.number().nonpositive().minValue).toBeNull;
|
||||
expect(z.number().int().minValue).toBeNull;
|
||||
expect(z.number().multipleOf(5).minValue).toBeNull;
|
||||
expect(z.number().finite().minValue).toBeNull;
|
||||
expect(z.number().gt(5).minValue).toEqual(5);
|
||||
expect(z.number().gte(5).minValue).toEqual(5);
|
||||
expect(z.number().min(5).minValue).toEqual(5);
|
||||
expect(z.number().min(5).min(10).minValue).toEqual(10);
|
||||
expect(z.number().positive().minValue).toEqual(0);
|
||||
expect(z.number().nonnegative().minValue).toEqual(0);
|
||||
expect(z.number().safe().minValue).toEqual(Number.MIN_SAFE_INTEGER);
|
||||
});
|
||||
|
||||
test("max value getters", () => {
|
||||
expect(z.number().maxValue).toBeNull;
|
||||
expect(z.number().gt(5).maxValue).toBeNull;
|
||||
expect(z.number().gte(5).maxValue).toBeNull;
|
||||
expect(z.number().min(5).maxValue).toBeNull;
|
||||
expect(z.number().positive().maxValue).toBeNull;
|
||||
expect(z.number().nonnegative().maxValue).toBeNull;
|
||||
expect(z.number().int().minValue).toBeNull;
|
||||
expect(z.number().multipleOf(5).minValue).toBeNull;
|
||||
expect(z.number().finite().minValue).toBeNull;
|
||||
expect(z.number().lt(5).maxValue).toEqual(5);
|
||||
expect(z.number().lte(5).maxValue).toEqual(5);
|
||||
expect(z.number().max(5).maxValue).toEqual(5);
|
||||
expect(z.number().max(5).max(1).maxValue).toEqual(1);
|
||||
expect(z.number().negative().maxValue).toEqual(0);
|
||||
expect(z.number().nonpositive().maxValue).toEqual(0);
|
||||
expect(z.number().safe().maxValue).toEqual(Number.MAX_SAFE_INTEGER);
|
||||
});
|
||||
|
||||
test("int getter", () => {
|
||||
expect(z.number().isInt).toEqual(false);
|
||||
expect(z.number().int().isInt).toEqual(true);
|
||||
expect(z.number().safe().isInt).toEqual(true);
|
||||
expect(z.number().multipleOf(5).isInt).toEqual(true);
|
||||
});
|
||||
|
||||
/** In Zod 4, number schemas don't accept infinite values. */
|
||||
test("finite getter", () => {
|
||||
expect(z.number().isFinite).toEqual(true);
|
||||
});
|
||||
|
||||
test("string format methods", () => {
|
||||
const a = z.int32().min(5);
|
||||
expect(a.parse(6)).toEqual(6);
|
||||
expect(() => a.parse(1)).toThrow();
|
||||
});
|
||||
|
||||
test("error customization", () => {
|
||||
z.number().gte(5, { error: (iss) => "Min: " + iss.minimum.valueOf() });
|
||||
z.number().lte(5, { error: (iss) => "Max: " + iss.maximum.valueOf() });
|
||||
});
|
||||
640
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/object.test.ts
generated
vendored
Normal file
640
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/object.test.ts
generated
vendored
Normal file
@@ -0,0 +1,640 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
import * as core from "zod/v4/core";
|
||||
|
||||
const Test = z.object({
|
||||
f1: z.number(),
|
||||
f2: z.string().optional(),
|
||||
f3: z.string().nullable(),
|
||||
f4: z.array(z.object({ t: z.union([z.string(), z.boolean()]) })),
|
||||
});
|
||||
|
||||
test("object type inference", () => {
|
||||
type TestType = {
|
||||
f1: number;
|
||||
f2?: string | undefined;
|
||||
f3: string | null;
|
||||
f4: { t: string | boolean }[];
|
||||
};
|
||||
|
||||
expectTypeOf<z.TypeOf<typeof Test>>().toEqualTypeOf<TestType>();
|
||||
});
|
||||
|
||||
test("unknown throw", () => {
|
||||
const asdf: unknown = 35;
|
||||
expect(() => Test.parse(asdf)).toThrow();
|
||||
});
|
||||
|
||||
test("shape() should return schema of particular key", () => {
|
||||
const f1Schema = Test.shape.f1;
|
||||
const f2Schema = Test.shape.f2;
|
||||
const f3Schema = Test.shape.f3;
|
||||
const f4Schema = Test.shape.f4;
|
||||
|
||||
expect(f1Schema).toBeInstanceOf(z.ZodNumber);
|
||||
expect(f2Schema).toBeInstanceOf(z.ZodOptional);
|
||||
expect(f3Schema).toBeInstanceOf(z.ZodNullable);
|
||||
expect(f4Schema).toBeInstanceOf(z.ZodArray);
|
||||
});
|
||||
|
||||
test("correct parsing", () => {
|
||||
Test.parse({
|
||||
f1: 12,
|
||||
f2: "string",
|
||||
f3: "string",
|
||||
f4: [
|
||||
{
|
||||
t: "string",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
Test.parse({
|
||||
f1: 12,
|
||||
f3: null,
|
||||
f4: [
|
||||
{
|
||||
t: false,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
test("nonstrict by default", () => {
|
||||
z.object({ points: z.number() }).parse({
|
||||
points: 2314,
|
||||
unknown: "asdf",
|
||||
});
|
||||
});
|
||||
|
||||
test("parse optional keys ", () => {
|
||||
const schema = z.object({
|
||||
a: z.string().optional(),
|
||||
});
|
||||
expect(schema.parse({ a: "asdf" })).toEqual({ a: "asdf" });
|
||||
});
|
||||
|
||||
test("empty object", () => {
|
||||
const schema = z.object({});
|
||||
expect(schema.parse({})).toEqual({});
|
||||
expect(schema.parse({ name: "asdf" })).toEqual({});
|
||||
expect(schema.safeParse(null).success).toEqual(false);
|
||||
expect(schema.safeParse("asdf").success).toEqual(false);
|
||||
expectTypeOf<z.output<typeof schema>>().toEqualTypeOf<Record<string, never>>();
|
||||
});
|
||||
|
||||
const data = {
|
||||
points: 2314,
|
||||
unknown: "asdf",
|
||||
};
|
||||
|
||||
test("strip by default", () => {
|
||||
const val = z.object({ points: z.number() }).parse(data);
|
||||
expect(val).toEqual({ points: 2314 });
|
||||
});
|
||||
|
||||
test("unknownkeys override", () => {
|
||||
const val = z.object({ points: z.number() }).strict().passthrough().strip().passthrough().parse(data);
|
||||
|
||||
expect(val).toEqual(data);
|
||||
});
|
||||
|
||||
test("passthrough unknown", () => {
|
||||
const val = z.object({ points: z.number() }).passthrough().parse(data);
|
||||
|
||||
expect(val).toEqual(data);
|
||||
});
|
||||
|
||||
test("strip unknown", () => {
|
||||
const val = z.object({ points: z.number() }).strip().parse(data);
|
||||
|
||||
expect(val).toEqual({ points: 2314 });
|
||||
});
|
||||
|
||||
test("strict", () => {
|
||||
const val = z.object({ points: z.number() }).strict().safeParse(data);
|
||||
|
||||
expect(val.success).toEqual(false);
|
||||
});
|
||||
|
||||
test("catchall inference", () => {
|
||||
const o1 = z
|
||||
.object({
|
||||
first: z.string(),
|
||||
})
|
||||
.catchall(z.number());
|
||||
|
||||
const d1 = o1.parse({ first: "asdf", num: 1243 });
|
||||
// expectTypeOf<(typeof d1)["asdf"]>().toEqualTypeOf<number>();
|
||||
expectTypeOf<(typeof d1)["first"]>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("catchall overrides strict", () => {
|
||||
const o1 = z.object({ first: z.string().optional() }).strict().catchall(z.number());
|
||||
|
||||
// should run fine
|
||||
// setting a catchall overrides the unknownKeys behavior
|
||||
o1.parse({
|
||||
asdf: 1234,
|
||||
});
|
||||
|
||||
// should only run catchall validation
|
||||
// against unknown keys
|
||||
o1.parse({
|
||||
first: "asdf",
|
||||
asdf: 1234,
|
||||
});
|
||||
});
|
||||
|
||||
test("catchall overrides strict", () => {
|
||||
const o1 = z
|
||||
.object({
|
||||
first: z.string(),
|
||||
})
|
||||
.strict()
|
||||
.catchall(z.number());
|
||||
|
||||
// should run fine
|
||||
// setting a catchall overrides the unknownKeys behavior
|
||||
o1.parse({
|
||||
first: "asdf",
|
||||
asdf: 1234,
|
||||
});
|
||||
});
|
||||
|
||||
test("optional keys are unset", () => {
|
||||
const SNamedEntity = z.object({
|
||||
id: z.string(),
|
||||
set: z.string().optional(),
|
||||
unset: z.string().optional(),
|
||||
});
|
||||
const result = SNamedEntity.parse({
|
||||
id: "asdf",
|
||||
set: undefined,
|
||||
});
|
||||
expect(Object.keys(result)).toEqual(["id", "set"]);
|
||||
});
|
||||
|
||||
test("catchall parsing", async () => {
|
||||
const result = z.object({ name: z.string() }).catchall(z.number()).parse({ name: "Foo", validExtraKey: 61 });
|
||||
|
||||
expect(result).toEqual({ name: "Foo", validExtraKey: 61 });
|
||||
|
||||
const result2 = z
|
||||
.object({ name: z.string() })
|
||||
.catchall(z.number())
|
||||
.safeParse({ name: "Foo", validExtraKey: 61, invalid: "asdf" });
|
||||
|
||||
expect(result2.success).toEqual(false);
|
||||
});
|
||||
|
||||
test("nonexistent keys", async () => {
|
||||
const Schema = z.union([z.object({ a: z.string() }), z.object({ b: z.number() })]);
|
||||
const obj = { a: "A" };
|
||||
const result = await Schema.spa(obj); // Works with 1.11.10, breaks with 2.0.0-beta.21
|
||||
expect(result.success).toBe(true);
|
||||
});
|
||||
|
||||
test("test async union", async () => {
|
||||
const Schema2 = z.union([
|
||||
z.object({
|
||||
ty: z.string(),
|
||||
}),
|
||||
z.object({
|
||||
ty: z.number(),
|
||||
}),
|
||||
]);
|
||||
|
||||
const obj = { ty: "A" };
|
||||
const result = await Schema2.spa(obj); // Works with 1.11.10, breaks with 2.0.0-beta.21
|
||||
expect(result.success).toEqual(true);
|
||||
});
|
||||
|
||||
test("test inferred merged type", async () => {
|
||||
const asdf = z.object({ a: z.string() }).merge(z.object({ a: z.number() }));
|
||||
type asdf = z.infer<typeof asdf>;
|
||||
|
||||
expectTypeOf<asdf>().toEqualTypeOf<{ a: number }>();
|
||||
});
|
||||
|
||||
test("inferred type with Record shape", () => {
|
||||
type A = z.ZodObject<Record<string, z.ZodType<string, number>>>;
|
||||
expectTypeOf<z.infer<A>>().toEqualTypeOf<Record<string, string>>();
|
||||
expectTypeOf<z.input<A>>().toEqualTypeOf<Record<string, number>>();
|
||||
|
||||
type B = z.ZodObject;
|
||||
expectTypeOf<z.infer<B>>().toEqualTypeOf<Record<string, unknown>>();
|
||||
expectTypeOf<z.input<B>>().toEqualTypeOf<Record<string, unknown>>();
|
||||
});
|
||||
|
||||
test("inferred merged object type with optional properties", async () => {
|
||||
const Merged = z
|
||||
.object({ a: z.string(), b: z.string().optional() })
|
||||
.merge(z.object({ a: z.string().optional(), b: z.string() }));
|
||||
type Merged = z.infer<typeof Merged>;
|
||||
expectTypeOf<Merged>().toEqualTypeOf<{ a?: string; b: string }>();
|
||||
expectTypeOf<Merged>().toEqualTypeOf<{ a?: string; b: string }>();
|
||||
});
|
||||
|
||||
test("inferred unioned object type with optional properties", async () => {
|
||||
const Unioned = z.union([
|
||||
z.object({ a: z.string(), b: z.string().optional() }),
|
||||
z.object({ a: z.string().optional(), b: z.string() }),
|
||||
]);
|
||||
type Unioned = z.infer<typeof Unioned>;
|
||||
expectTypeOf<Unioned>().toEqualTypeOf<{ a: string; b?: string } | { a?: string; b: string }>();
|
||||
});
|
||||
|
||||
test("inferred enum type", async () => {
|
||||
const Enum = z.object({ a: z.string(), b: z.string().optional() }).keyof();
|
||||
|
||||
expect(Enum.enum).toEqual({
|
||||
a: "a",
|
||||
b: "b",
|
||||
});
|
||||
|
||||
expect(Enum._zod.def.entries).toEqual({
|
||||
a: "a",
|
||||
b: "b",
|
||||
});
|
||||
type Enum = z.infer<typeof Enum>;
|
||||
expectTypeOf<Enum>().toEqualTypeOf<"a" | "b">();
|
||||
});
|
||||
|
||||
test("z.keyof returns enum", () => {
|
||||
const User = z.object({ name: z.string(), age: z.number() });
|
||||
const keysSchema = z.keyof(User);
|
||||
expect(keysSchema.enum).toEqual({
|
||||
name: "name",
|
||||
age: "age",
|
||||
});
|
||||
expect(keysSchema._zod.def.entries).toEqual({
|
||||
name: "name",
|
||||
age: "age",
|
||||
});
|
||||
type Keys = z.infer<typeof keysSchema>;
|
||||
expectTypeOf<Keys>().toEqualTypeOf<"name" | "age">();
|
||||
});
|
||||
|
||||
test("inferred partial object type with optional properties", async () => {
|
||||
const Partial = z.object({ a: z.string(), b: z.string().optional() }).partial();
|
||||
type Partial = z.infer<typeof Partial>;
|
||||
expectTypeOf<Partial>().toEqualTypeOf<{ a?: string; b?: string }>();
|
||||
});
|
||||
|
||||
test("inferred picked object type with optional properties", async () => {
|
||||
const Picked = z.object({ a: z.string(), b: z.string().optional() }).pick({ b: true });
|
||||
type Picked = z.infer<typeof Picked>;
|
||||
expectTypeOf<Picked>().toEqualTypeOf<{ b?: string }>();
|
||||
});
|
||||
|
||||
test("inferred type for unknown/any keys", () => {
|
||||
const myType = z.object({
|
||||
anyOptional: z.any().optional(),
|
||||
anyRequired: z.any(),
|
||||
unknownOptional: z.unknown().optional(),
|
||||
unknownRequired: z.unknown(),
|
||||
});
|
||||
type myType = z.infer<typeof myType>;
|
||||
expectTypeOf<myType>().toEqualTypeOf<{
|
||||
anyOptional?: any;
|
||||
anyRequired: any;
|
||||
unknownOptional?: unknown;
|
||||
unknownRequired: unknown;
|
||||
}>();
|
||||
});
|
||||
|
||||
test("strictObject", async () => {
|
||||
const strictObj = z.strictObject({
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const syncResult = strictObj.safeParse({ name: "asdf", unexpected: 13 });
|
||||
expect(syncResult.success).toEqual(false);
|
||||
|
||||
const asyncResult = await strictObj.spa({ name: "asdf", unexpected: 13 });
|
||||
expect(asyncResult.success).toEqual(false);
|
||||
});
|
||||
|
||||
test("object with refine", async () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.string().default("foo"),
|
||||
b: z.number(),
|
||||
})
|
||||
.refine(() => true);
|
||||
expect(schema.parse({ b: 5 })).toEqual({ b: 5, a: "foo" });
|
||||
const result = await schema.parseAsync({ b: 5 });
|
||||
expect(result).toEqual({ b: 5, a: "foo" });
|
||||
});
|
||||
|
||||
test("intersection of object with date", async () => {
|
||||
const schema = z.object({
|
||||
a: z.date(),
|
||||
});
|
||||
expect(z.intersection(schema, schema).parse({ a: new Date(1637353595983) })).toEqual({
|
||||
a: new Date(1637353595983),
|
||||
});
|
||||
const result = await schema.parseAsync({ a: new Date(1637353595983) });
|
||||
expect(result).toEqual({ a: new Date(1637353595983) });
|
||||
});
|
||||
|
||||
test("intersection of object with refine with date", async () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.date(),
|
||||
})
|
||||
.refine(() => true);
|
||||
expect(z.intersection(schema, schema).parse({ a: new Date(1637353595983) })).toEqual({
|
||||
a: new Date(1637353595983),
|
||||
});
|
||||
const result = await schema.parseAsync({ a: new Date(1637353595983) });
|
||||
expect(result).toEqual({ a: new Date(1637353595983) });
|
||||
});
|
||||
|
||||
test("constructor key", () => {
|
||||
const person = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
expect(() =>
|
||||
person.parse({
|
||||
name: "bob dylan",
|
||||
constructor: 61,
|
||||
})
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
test("constructor key", () => {
|
||||
const Example = z.object({
|
||||
prop: z.string(),
|
||||
opt: z.number().optional(),
|
||||
arr: z.string().array(),
|
||||
});
|
||||
|
||||
type Example = z.infer<typeof Example>;
|
||||
expectTypeOf<keyof Example>().toEqualTypeOf<"prop" | "opt" | "arr">();
|
||||
});
|
||||
|
||||
test("catchall", () => {
|
||||
const a = z.object({});
|
||||
expect(a._zod.def.catchall).toBeUndefined();
|
||||
|
||||
const b = z.strictObject({});
|
||||
expect(b._zod.def.catchall).toBeInstanceOf(core.$ZodNever);
|
||||
|
||||
const c = z.looseObject({});
|
||||
expect(c._zod.def.catchall).toBeInstanceOf(core.$ZodUnknown);
|
||||
|
||||
const d = z.object({}).catchall(z.number());
|
||||
expect(d._zod.def.catchall).toBeInstanceOf(core.$ZodNumber);
|
||||
});
|
||||
|
||||
test("unknownkeys merging", () => {
|
||||
// This one is "strict"
|
||||
const a = z.looseObject({
|
||||
a: z.string(),
|
||||
});
|
||||
|
||||
const b = z.strictObject({ b: z.string() });
|
||||
|
||||
// incoming object overrides
|
||||
const c = a.merge(b);
|
||||
expect(c._zod.def.catchall).toBeInstanceOf(core.$ZodNever);
|
||||
});
|
||||
|
||||
const personToExtend = z.object({
|
||||
firstName: z.string(),
|
||||
lastName: z.string(),
|
||||
});
|
||||
|
||||
test("extend() should return schema with new key", () => {
|
||||
const PersonWithNickname = personToExtend.extend({ nickName: z.string() });
|
||||
type PersonWithNickname = z.infer<typeof PersonWithNickname>;
|
||||
|
||||
const expected = { firstName: "f", nickName: "n", lastName: "l" };
|
||||
const actual = PersonWithNickname.parse(expected);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
expectTypeOf<keyof PersonWithNickname>().toEqualTypeOf<"firstName" | "lastName" | "nickName">();
|
||||
expectTypeOf<PersonWithNickname>().toEqualTypeOf<{ firstName: string; lastName: string; nickName: string }>();
|
||||
});
|
||||
|
||||
test("extend() should have power to override existing key", () => {
|
||||
const PersonWithNumberAsLastName = personToExtend.extend({
|
||||
lastName: z.number(),
|
||||
});
|
||||
type PersonWithNumberAsLastName = z.infer<typeof PersonWithNumberAsLastName>;
|
||||
|
||||
const expected = { firstName: "f", lastName: 42 };
|
||||
const actual = PersonWithNumberAsLastName.parse(expected);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
expectTypeOf<PersonWithNumberAsLastName>().toEqualTypeOf<{ firstName: string; lastName: number }>();
|
||||
});
|
||||
|
||||
test("safeExtend() should have power to override existing key", () => {
|
||||
const PersonWithMinLastName = personToExtend.safeExtend({
|
||||
lastName: z.string().min(3),
|
||||
});
|
||||
type PersonWithMinLastName = z.infer<typeof PersonWithMinLastName>;
|
||||
|
||||
const expected = { firstName: "f", lastName: "abc" };
|
||||
const actual = PersonWithMinLastName.parse(expected);
|
||||
|
||||
expect(actual).toEqual(expected);
|
||||
expect(() => PersonWithMinLastName.parse({ firstName: "f", lastName: "ab" })).toThrow();
|
||||
expectTypeOf<PersonWithMinLastName>().toEqualTypeOf<{ firstName: string; lastName: string }>();
|
||||
});
|
||||
|
||||
test("safeExtend() maintains refinements", () => {
|
||||
const schema = z.object({ name: z.string().min(1) });
|
||||
const extended = schema.safeExtend({ name: z.string().min(2) });
|
||||
expect(() => extended.parse({ name: "" })).toThrow();
|
||||
expect(extended.parse({ name: "ab" })).toEqual({ name: "ab" });
|
||||
type Extended = z.infer<typeof extended>;
|
||||
expectTypeOf<Extended>().toEqualTypeOf<{ name: string }>();
|
||||
// @ts-expect-error
|
||||
schema.safeExtend({ name: z.number() });
|
||||
});
|
||||
|
||||
test("passthrough index signature", () => {
|
||||
const a = z.object({ a: z.string() });
|
||||
type a = z.infer<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<{ a: string }>();
|
||||
const b = a.passthrough();
|
||||
type b = z.infer<typeof b>;
|
||||
expectTypeOf<b>().toEqualTypeOf<{ a: string; [k: string]: unknown }>();
|
||||
});
|
||||
|
||||
// test("xor", () => {
|
||||
// type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
|
||||
// type XOR<T, U> = T extends object ? (U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : U) : T;
|
||||
|
||||
// type A = { name: string; a: number };
|
||||
// type B = { name: string; b: number };
|
||||
// type C = XOR<A, B>;
|
||||
// type Outer = { data: C };
|
||||
// const Outer = z.object({
|
||||
// data: z.union([z.object({ name: z.string(), a: z.number() }), z.object({ name: z.string(), b: z.number() })]),
|
||||
// }) satisfies z.ZodType<Outer, any>;
|
||||
// });
|
||||
|
||||
test("assignability", () => {
|
||||
z.object({ a: z.string() }) satisfies z.ZodObject<{ a: z.ZodString }>;
|
||||
z.object({ a: z.string() }).catchall(z.number()) satisfies z.ZodObject<{ a: z.ZodString }>;
|
||||
z.object({ a: z.string() }).strict() satisfies z.ZodObject;
|
||||
z.object({}) satisfies z.ZodObject;
|
||||
|
||||
z.looseObject({ name: z.string() }) satisfies z.ZodObject<
|
||||
{
|
||||
name: z.ZodString;
|
||||
},
|
||||
z.core.$loose
|
||||
>;
|
||||
z.looseObject({ name: z.string() }) satisfies z.ZodObject<{
|
||||
name: z.ZodString;
|
||||
}>;
|
||||
z.strictObject({ name: z.string() }) satisfies z.ZodObject<
|
||||
{
|
||||
name: z.ZodString;
|
||||
},
|
||||
z.core.$loose
|
||||
>;
|
||||
z.strictObject({ name: z.string() }) satisfies z.ZodObject<
|
||||
{
|
||||
name: z.ZodString;
|
||||
},
|
||||
z.core.$strict
|
||||
>;
|
||||
z.object({ name: z.string() }) satisfies z.ZodObject<{
|
||||
name: z.ZodString;
|
||||
}>;
|
||||
z.object({
|
||||
a: z.string(),
|
||||
b: z.number(),
|
||||
c: z.boolean(),
|
||||
}) satisfies z.core.$ZodObject;
|
||||
});
|
||||
|
||||
test("null prototype", () => {
|
||||
const schema = z.object({ a: z.string() });
|
||||
const obj = Object.create(null);
|
||||
obj.a = "foo";
|
||||
expect(schema.parse(obj)).toEqual({ a: "foo" });
|
||||
});
|
||||
|
||||
test("empty objects", () => {
|
||||
const A = z.looseObject({});
|
||||
type Ain = z.input<typeof A>;
|
||||
expectTypeOf<Ain>().toEqualTypeOf<Record<string, unknown>>();
|
||||
type Aout = z.output<typeof A>;
|
||||
expectTypeOf<Aout>().toEqualTypeOf<Record<string, unknown>>();
|
||||
|
||||
const B = z.object({});
|
||||
type Bout = z.output<typeof B>;
|
||||
expectTypeOf<Bout>().toEqualTypeOf<Record<string, never>>();
|
||||
type Bin = z.input<typeof B>;
|
||||
expectTypeOf<Bin>().toEqualTypeOf<Record<string, never>>();
|
||||
|
||||
const C = z.strictObject({});
|
||||
type Cout = z.output<typeof C>;
|
||||
expectTypeOf<Cout>().toEqualTypeOf<Record<string, never>>();
|
||||
type Cin = z.input<typeof C>;
|
||||
expectTypeOf<Cin>().toEqualTypeOf<Record<string, never>>();
|
||||
});
|
||||
|
||||
test("preserve key order", () => {
|
||||
const schema = z.object({
|
||||
a: z.string().optional(),
|
||||
b: z.string(),
|
||||
});
|
||||
const r1 = schema.safeParse({ a: "asdf", b: "qwer" });
|
||||
const r2 = schema.safeParse({ a: "asdf", b: "qwer" }, { jitless: true });
|
||||
|
||||
expect(Object.keys(r1.data!)).toMatchInlineSnapshot(`
|
||||
[
|
||||
"a",
|
||||
"b",
|
||||
]
|
||||
`);
|
||||
expect(Object.keys(r1.data!)).toEqual(Object.keys(r2.data!));
|
||||
});
|
||||
|
||||
test("empty shape", () => {
|
||||
const a = z.object({});
|
||||
|
||||
a.parse({});
|
||||
a.parse({}, { jitless: true });
|
||||
a.parse(Object.create(null));
|
||||
a.parse(Object.create(null), { jitless: true });
|
||||
|
||||
expect(() => a.parse([])).toThrow();
|
||||
expect(() => a.parse([], { jitless: true })).toThrow();
|
||||
});
|
||||
|
||||
test("zodtype assignability", () => {
|
||||
// Does not error
|
||||
z.object({ hello: z.string().optional() }) satisfies z.ZodType<{ hello?: string | undefined }>;
|
||||
z.object({ hello: z.string() }) satisfies z.ZodType<{ hello?: string | undefined }>;
|
||||
// @ts-expect-error
|
||||
z.object({}) satisfies z.ZodType<{ hello: string | undefined }>;
|
||||
// @ts-expect-error
|
||||
z.object({ hello: z.string().optional() }) satisfies z.ZodType<{ hello: string | undefined }>;
|
||||
// @ts-expect-error
|
||||
z.object({ hello: z.string().optional() }) satisfies z.ZodType<{ hello: string }>;
|
||||
// @ts-expect-error
|
||||
z.object({ hello: z.number() }) satisfies z.ZodType<{ hello?: string | undefined }>;
|
||||
});
|
||||
|
||||
test("index signature in shape", () => {
|
||||
function makeZodObj<const T extends string>(key: T) {
|
||||
return z.looseObject({
|
||||
[key]: z.string(),
|
||||
});
|
||||
}
|
||||
|
||||
const schema = makeZodObj("foo");
|
||||
type schema = z.infer<typeof schema>;
|
||||
|
||||
expectTypeOf<schema>().toEqualTypeOf<Record<string, string>>();
|
||||
});
|
||||
|
||||
test("extend() on object with refinements should throw when overwriting properties", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.string(),
|
||||
})
|
||||
.refine(() => true);
|
||||
|
||||
expect(() => schema.extend({ a: z.number() })).toThrow();
|
||||
});
|
||||
|
||||
test("extend() on object with refinements should not throw when adding new properties", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.string(),
|
||||
})
|
||||
.refine((data) => data.a.length > 0);
|
||||
|
||||
// Should not throw since 'b' doesn't overlap with 'a'
|
||||
const extended = schema.extend({ b: z.number() });
|
||||
|
||||
// Verify the extended schema works correctly
|
||||
expect(extended.parse({ a: "hello", b: 42 })).toEqual({ a: "hello", b: 42 });
|
||||
|
||||
// Verify the original refinement still applies
|
||||
expect(() => extended.parse({ a: "", b: 42 })).toThrow();
|
||||
});
|
||||
|
||||
test("safeExtend() on object with refinements should not throw", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.string(),
|
||||
})
|
||||
.refine(() => true);
|
||||
|
||||
expect(() => schema.safeExtend({ b: z.string() })).not.toThrow();
|
||||
});
|
||||
223
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/optional.test.ts
generated
vendored
Normal file
223
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/optional.test.ts
generated
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
// @ts-ignore TS6133
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test(".optional()", () => {
|
||||
const schema = z.string().optional();
|
||||
expect(schema.parse("adsf")).toEqual("adsf");
|
||||
expect(schema.parse(undefined)).toEqual(undefined);
|
||||
expect(schema.safeParse(null).success).toEqual(false);
|
||||
|
||||
expectTypeOf<typeof schema._output>().toEqualTypeOf<string | undefined>();
|
||||
});
|
||||
|
||||
test("unwrap", () => {
|
||||
const unwrapped = z.string().optional().unwrap();
|
||||
expect(unwrapped).toBeInstanceOf(z.ZodString);
|
||||
});
|
||||
|
||||
test("optionality", () => {
|
||||
const a = z.string();
|
||||
expect(a._zod.optin).toEqual(undefined);
|
||||
expect(a._zod.optout).toEqual(undefined);
|
||||
|
||||
const b = z.string().optional();
|
||||
expect(b._zod.optin).toEqual("optional");
|
||||
expect(b._zod.optout).toEqual("optional");
|
||||
|
||||
const c = z.string().default("asdf");
|
||||
expect(c._zod.optin).toEqual("optional");
|
||||
expect(c._zod.optout).toEqual(undefined);
|
||||
|
||||
const d = z.string().optional().nullable();
|
||||
expect(d._zod.optin).toEqual("optional");
|
||||
expect(d._zod.optout).toEqual("optional");
|
||||
|
||||
const e = z.string().default("asdf").nullable();
|
||||
expect(e._zod.optin).toEqual("optional");
|
||||
expect(e._zod.optout).toEqual(undefined);
|
||||
|
||||
// z.undefined should NOT be optional
|
||||
const f = z.undefined();
|
||||
expect(f._zod.optin).toEqual("optional");
|
||||
expect(f._zod.optout).toEqual("optional");
|
||||
expectTypeOf<typeof f._zod.optin>().toEqualTypeOf<"optional" | undefined>();
|
||||
expectTypeOf<typeof f._zod.optout>().toEqualTypeOf<"optional" | undefined>();
|
||||
|
||||
// z.union should be optional if any of the types are optional
|
||||
const g = z.union([z.string(), z.undefined()]);
|
||||
expect(g._zod.optin).toEqual("optional");
|
||||
expect(g._zod.optout).toEqual("optional");
|
||||
expectTypeOf<typeof g._zod.optin>().toEqualTypeOf<"optional" | undefined>();
|
||||
expectTypeOf<typeof g._zod.optout>().toEqualTypeOf<"optional" | undefined>();
|
||||
|
||||
const h = z.union([z.string(), z.optional(z.string())]);
|
||||
expect(h._zod.optin).toEqual("optional");
|
||||
expect(h._zod.optout).toEqual("optional");
|
||||
expectTypeOf<typeof h._zod.optin>().toEqualTypeOf<"optional">();
|
||||
expectTypeOf<typeof h._zod.optout>().toEqualTypeOf<"optional">();
|
||||
});
|
||||
|
||||
test("pipe optionality", () => {
|
||||
z.string().optional()._zod.optin;
|
||||
const a = z.string().optional().pipe(z.string());
|
||||
expect(a._zod.optin).toEqual("optional");
|
||||
expect(a._zod.optout).toEqual(undefined);
|
||||
expectTypeOf<typeof a._zod.optin>().toEqualTypeOf<"optional">();
|
||||
expectTypeOf<typeof a._zod.optout>().toEqualTypeOf<"optional" | undefined>();
|
||||
|
||||
const b = z
|
||||
.string()
|
||||
.transform((val) => (Math.random() ? val : undefined))
|
||||
.pipe(z.string().optional());
|
||||
expect(b._zod.optin).toEqual(undefined);
|
||||
expect(b._zod.optout).toEqual("optional");
|
||||
expectTypeOf<typeof b._zod.optin>().toEqualTypeOf<"optional" | undefined>();
|
||||
expectTypeOf<typeof b._zod.optout>().toEqualTypeOf<"optional">();
|
||||
|
||||
const c = z.string().default("asdf").pipe(z.string());
|
||||
expect(c._zod.optin).toEqual("optional");
|
||||
expect(c._zod.optout).toEqual(undefined);
|
||||
|
||||
const d = z
|
||||
.string()
|
||||
.transform((val) => (Math.random() ? val : undefined))
|
||||
.pipe(z.string().default("asdf"));
|
||||
expect(d._zod.optin).toEqual(undefined);
|
||||
expect(d._zod.optout).toEqual(undefined);
|
||||
});
|
||||
|
||||
test("pipe optionality inside objects", () => {
|
||||
const schema = z.object({
|
||||
a: z.string().optional(),
|
||||
b: z.string().optional().pipe(z.string()),
|
||||
c: z.string().default("asdf").pipe(z.string()),
|
||||
d: z
|
||||
.string()
|
||||
.transform((val) => (Math.random() ? val : undefined))
|
||||
.pipe(z.string().optional()),
|
||||
e: z
|
||||
.string()
|
||||
.transform((val) => (Math.random() ? val : undefined))
|
||||
.pipe(z.string().default("asdf")),
|
||||
});
|
||||
|
||||
type SchemaIn = z.input<typeof schema>;
|
||||
expectTypeOf<SchemaIn>().toEqualTypeOf<{
|
||||
a?: string | undefined;
|
||||
b?: string | undefined;
|
||||
c?: string | undefined;
|
||||
d: string;
|
||||
e: string;
|
||||
}>();
|
||||
|
||||
type SchemaOut = z.output<typeof schema>;
|
||||
expectTypeOf<SchemaOut>().toEqualTypeOf<{
|
||||
a?: string | undefined;
|
||||
b: string;
|
||||
c: string;
|
||||
d?: string | undefined;
|
||||
e: string;
|
||||
}>();
|
||||
});
|
||||
|
||||
test("optional prop with pipe", () => {
|
||||
const schema = z.object({
|
||||
id: z
|
||||
.union([z.number(), z.string().nullish()])
|
||||
.transform((val) => (val === null || val === undefined ? val : Number(val)))
|
||||
.pipe(z.number())
|
||||
.optional(),
|
||||
});
|
||||
|
||||
schema.parse({});
|
||||
schema.parse({}, { jitless: true });
|
||||
});
|
||||
|
||||
// exactOptional tests
|
||||
test(".exactOptional()", () => {
|
||||
const schema = z.string().exactOptional();
|
||||
expect(schema.parse("asdf")).toEqual("asdf");
|
||||
expect(schema.safeParse(undefined).success).toEqual(false);
|
||||
expect(schema.safeParse(null).success).toEqual(false);
|
||||
|
||||
// Type should NOT include undefined
|
||||
expectTypeOf<typeof schema._output>().toEqualTypeOf<string>();
|
||||
expectTypeOf<typeof schema._input>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("exactOptional unwrap", () => {
|
||||
const unwrapped = z.string().exactOptional().unwrap();
|
||||
expect(unwrapped).toBeInstanceOf(z.ZodString);
|
||||
});
|
||||
|
||||
test("exactOptional optionality", () => {
|
||||
const a = z.string().exactOptional();
|
||||
expect(a._zod.optin).toEqual("optional");
|
||||
expect(a._zod.optout).toEqual("optional");
|
||||
expectTypeOf<typeof a._zod.optin>().toEqualTypeOf<"optional">();
|
||||
expectTypeOf<typeof a._zod.optout>().toEqualTypeOf<"optional">();
|
||||
});
|
||||
|
||||
test("exactOptional in objects - absent keys", () => {
|
||||
const schema = z.object({
|
||||
a: z.string().exactOptional(),
|
||||
});
|
||||
|
||||
// Absent key should pass
|
||||
expect(schema.parse({})).toEqual({});
|
||||
expect(schema.parse({}, { jitless: true })).toEqual({});
|
||||
|
||||
// Present key with valid value should pass
|
||||
expect(schema.parse({ a: "hello" })).toEqual({ a: "hello" });
|
||||
expect(schema.parse({ a: "hello" }, { jitless: true })).toEqual({ a: "hello" });
|
||||
});
|
||||
|
||||
test("exactOptional in objects - explicit undefined rejected", () => {
|
||||
const schema = z.object({
|
||||
a: z.string().exactOptional(),
|
||||
});
|
||||
|
||||
// Explicit undefined should fail
|
||||
expect(schema.safeParse({ a: undefined }).success).toEqual(false);
|
||||
expect(schema.safeParse({ a: undefined }, { jitless: true }).success).toEqual(false);
|
||||
});
|
||||
|
||||
test("exactOptional type inference in objects", () => {
|
||||
const schema = z.object({
|
||||
a: z.string().exactOptional(),
|
||||
b: z.string().optional(),
|
||||
});
|
||||
|
||||
type SchemaIn = z.input<typeof schema>;
|
||||
expectTypeOf<SchemaIn>().toEqualTypeOf<{
|
||||
a?: string;
|
||||
b?: string | undefined;
|
||||
}>();
|
||||
|
||||
type SchemaOut = z.output<typeof schema>;
|
||||
expectTypeOf<SchemaOut>().toEqualTypeOf<{
|
||||
a?: string;
|
||||
b?: string | undefined;
|
||||
}>();
|
||||
});
|
||||
|
||||
test("exactOptional vs optional comparison", () => {
|
||||
const optionalSchema = z.object({ a: z.string().optional() });
|
||||
const exactOptionalSchema = z.object({ a: z.string().exactOptional() });
|
||||
|
||||
// Both accept absent keys
|
||||
expect(optionalSchema.parse({})).toEqual({});
|
||||
expect(exactOptionalSchema.parse({})).toEqual({});
|
||||
|
||||
// Both accept valid values
|
||||
expect(optionalSchema.parse({ a: "hi" })).toEqual({ a: "hi" });
|
||||
expect(exactOptionalSchema.parse({ a: "hi" })).toEqual({ a: "hi" });
|
||||
|
||||
// optional() accepts explicit undefined
|
||||
expect(optionalSchema.parse({ a: undefined })).toEqual({ a: undefined });
|
||||
|
||||
// exactOptional() rejects explicit undefined
|
||||
expect(exactOptionalSchema.safeParse({ a: undefined }).success).toEqual(false);
|
||||
});
|
||||
427
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/partial.test.ts
generated
vendored
Normal file
427
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/partial.test.ts
generated
vendored
Normal file
@@ -0,0 +1,427 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const nested = z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
outer: z.object({
|
||||
inner: z.string(),
|
||||
}),
|
||||
array: z.array(z.object({ asdf: z.string() })),
|
||||
});
|
||||
|
||||
test("shallow inference", () => {
|
||||
const shallow = nested.partial();
|
||||
type shallow = z.infer<typeof shallow>;
|
||||
|
||||
expectTypeOf<shallow>().toEqualTypeOf<{
|
||||
name?: string | undefined;
|
||||
age?: number | undefined;
|
||||
outer?: { inner: string } | undefined;
|
||||
array?: { asdf: string }[] | undefined;
|
||||
}>();
|
||||
});
|
||||
|
||||
test("shallow partial parse", () => {
|
||||
const shallow = nested.partial();
|
||||
shallow.parse({});
|
||||
shallow.parse({
|
||||
name: "asdf",
|
||||
age: 23143,
|
||||
});
|
||||
});
|
||||
|
||||
test("required", () => {
|
||||
const object = z.object({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
field: z.string().optional().default("asdf"),
|
||||
nullableField: z.number().nullable(),
|
||||
nullishField: z.string().nullish(),
|
||||
});
|
||||
|
||||
const requiredObject = object.required();
|
||||
expect(requiredObject.shape.name).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.name.unwrap()).toBeInstanceOf(z.ZodString);
|
||||
expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.age.unwrap()).toBeInstanceOf(z.ZodOptional);
|
||||
expect(requiredObject.shape.field).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.field.unwrap()).toBeInstanceOf(z.ZodDefault);
|
||||
expect(requiredObject.shape.nullableField).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.nullableField.unwrap()).toBeInstanceOf(z.ZodNullable);
|
||||
expect(requiredObject.shape.nullishField).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.nullishField.unwrap()).toBeInstanceOf(z.ZodOptional);
|
||||
expect(requiredObject.shape.nullishField.unwrap().unwrap()).toBeInstanceOf(z.ZodNullable);
|
||||
});
|
||||
|
||||
test("required inference", () => {
|
||||
const object = z.object({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
field: z.string().optional().default("asdf"),
|
||||
nullableField: z.number().nullable(),
|
||||
nullishField: z.string().nullish(),
|
||||
});
|
||||
|
||||
const requiredObject = object.required();
|
||||
|
||||
type required = z.infer<typeof requiredObject>;
|
||||
type expected = {
|
||||
name: string;
|
||||
age: number;
|
||||
field: string;
|
||||
nullableField: number | null;
|
||||
nullishField: string | null;
|
||||
};
|
||||
expectTypeOf<expected>().toEqualTypeOf<required>();
|
||||
});
|
||||
|
||||
test("required with mask", () => {
|
||||
const object = z.object({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
field: z.string().optional().default("asdf"),
|
||||
country: z.string().optional(),
|
||||
});
|
||||
|
||||
const requiredObject = object.required({ age: true });
|
||||
expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString);
|
||||
expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault);
|
||||
expect(requiredObject.shape.country).toBeInstanceOf(z.ZodOptional);
|
||||
});
|
||||
|
||||
test("required with mask -- ignore falsy values", () => {
|
||||
const object = z.object({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
field: z.string().optional().default("asdf"),
|
||||
country: z.string().optional(),
|
||||
});
|
||||
|
||||
// @ts-expect-error
|
||||
const requiredObject = object.required({ age: true, country: false });
|
||||
expect(requiredObject.shape.name).toBeInstanceOf(z.ZodString);
|
||||
expect(requiredObject.shape.age).toBeInstanceOf(z.ZodNonOptional);
|
||||
expect(requiredObject.shape.field).toBeInstanceOf(z.ZodDefault);
|
||||
expect(requiredObject.shape.country).toBeInstanceOf(z.ZodOptional);
|
||||
});
|
||||
|
||||
test("partial with mask", async () => {
|
||||
const object = z.object({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
field: z.string().optional().default("asdf"),
|
||||
country: z.string(),
|
||||
});
|
||||
|
||||
const masked = object.partial({ age: true, field: true, name: true }).strict();
|
||||
|
||||
expect(masked.shape.name).toBeInstanceOf(z.ZodOptional);
|
||||
expect(masked.shape.age).toBeInstanceOf(z.ZodOptional);
|
||||
expect(masked.shape.field).toBeInstanceOf(z.ZodOptional);
|
||||
expect(masked.shape.country).toBeInstanceOf(z.ZodString);
|
||||
|
||||
masked.parse({ country: "US" });
|
||||
await masked.parseAsync({ country: "US" });
|
||||
});
|
||||
|
||||
test("partial with mask -- ignore falsy values", async () => {
|
||||
const object = z.object({
|
||||
name: z.string(),
|
||||
age: z.number().optional(),
|
||||
field: z.string().optional().default("asdf"),
|
||||
country: z.string(),
|
||||
});
|
||||
|
||||
// @ts-expect-error
|
||||
const masked = object.partial({ name: true, country: false }).strict();
|
||||
|
||||
expect(masked.shape.name).toBeInstanceOf(z.ZodOptional);
|
||||
expect(masked.shape.age).toBeInstanceOf(z.ZodOptional);
|
||||
expect(masked.shape.field).toBeInstanceOf(z.ZodDefault);
|
||||
expect(masked.shape.country).toBeInstanceOf(z.ZodString);
|
||||
|
||||
masked.parse({ country: "US" });
|
||||
await masked.parseAsync({ country: "US" });
|
||||
});
|
||||
|
||||
test("catch/prefault/default", () => {
|
||||
const mySchema = z.object({
|
||||
a: z.string().catch("catch value").optional(),
|
||||
b: z.string().default("default value").optional(),
|
||||
c: z.string().prefault("prefault value").optional(),
|
||||
d: z.string().catch("catch value"),
|
||||
e: z.string().default("default value"),
|
||||
f: z.string().prefault("prefault value"),
|
||||
});
|
||||
|
||||
expect(mySchema.parse({})).toMatchInlineSnapshot(`
|
||||
{
|
||||
"b": "default value",
|
||||
"c": "prefault value",
|
||||
"d": "catch value",
|
||||
"e": "default value",
|
||||
"f": "prefault value",
|
||||
}
|
||||
`);
|
||||
|
||||
expect(mySchema.parse({}, { jitless: true })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"b": "default value",
|
||||
"c": "prefault value",
|
||||
"d": "catch value",
|
||||
"e": "default value",
|
||||
"f": "prefault value",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("handleOptionalObjectResult branches", () => {
|
||||
const mySchema = z.object({
|
||||
// Branch: input[key] === undefined, key not in input, caught error
|
||||
caughtMissing: z.string().catch("caught").optional(),
|
||||
// Branch: input[key] === undefined, key in input, caught error
|
||||
caughtUndefined: z.string().catch("caught").optional(),
|
||||
// Branch: input[key] === undefined, key not in input, validation issues
|
||||
issueMissing: z.string().min(5).optional(),
|
||||
// Branch: input[key] === undefined, key in input, validation issues
|
||||
issueUndefined: z.string().min(5).optional(),
|
||||
// Branch: input[key] === undefined, validation returns undefined
|
||||
validUndefined: z.string().optional(),
|
||||
// Branch: input[key] === undefined, non-undefined result (default/transform)
|
||||
defaultValue: z.string().default("default").optional(),
|
||||
// Branch: input[key] defined, caught error
|
||||
caughtDefined: z.string().catch("caught").optional(),
|
||||
// Branch: input[key] defined, validation issues
|
||||
issueDefined: z.string().min(5).optional(),
|
||||
// Branch: input[key] defined, validation returns undefined
|
||||
validDefinedUndefined: z
|
||||
.string()
|
||||
.transform(() => undefined)
|
||||
.optional(),
|
||||
// Branch: input[key] defined, non-undefined value
|
||||
validDefined: z.string().optional(),
|
||||
});
|
||||
|
||||
// Test input[key] === undefined cases
|
||||
const result1 = mySchema.parse(
|
||||
{
|
||||
// caughtMissing: not present (key not in input)
|
||||
caughtUndefined: undefined, // key in input
|
||||
// issueMissing: not present (key not in input)
|
||||
issueUndefined: undefined, // key in input
|
||||
validUndefined: undefined,
|
||||
// defaultValue: not present, will get default
|
||||
},
|
||||
{ jitless: true }
|
||||
);
|
||||
|
||||
expect(result1).toEqual({
|
||||
caughtUndefined: undefined,
|
||||
issueUndefined: undefined,
|
||||
validUndefined: undefined,
|
||||
defaultValue: "default",
|
||||
});
|
||||
|
||||
// Test input[key] defined cases (successful)
|
||||
const result2 = mySchema.parse(
|
||||
{
|
||||
caughtDefined: 123, // invalid type, should catch
|
||||
validDefinedUndefined: "test", // transforms to undefined
|
||||
validDefined: "valid", // valid value
|
||||
},
|
||||
{ jitless: true }
|
||||
);
|
||||
|
||||
expect(result2).toEqual({
|
||||
caughtDefined: "caught",
|
||||
validDefinedUndefined: undefined,
|
||||
validDefined: "valid",
|
||||
defaultValue: "default",
|
||||
});
|
||||
|
||||
// Test validation issues are properly reported (input[key] defined, validation fails)
|
||||
expect(() =>
|
||||
mySchema.parse(
|
||||
{
|
||||
issueDefined: "abc", // too short
|
||||
},
|
||||
{ jitless: true }
|
||||
)
|
||||
).toThrow();
|
||||
});
|
||||
|
||||
test("fastpass vs non-fastpass consistency", () => {
|
||||
const mySchema = z.object({
|
||||
caughtMissing: z.string().catch("caught").optional(),
|
||||
caughtUndefined: z.string().catch("caught").optional(),
|
||||
issueMissing: z.string().min(5).optional(),
|
||||
issueUndefined: z.string().min(5).optional(),
|
||||
validUndefined: z.string().optional(),
|
||||
defaultValue: z.string().default("default").optional(),
|
||||
caughtDefined: z.string().catch("caught").optional(),
|
||||
validDefinedUndefined: z
|
||||
.string()
|
||||
.transform(() => undefined)
|
||||
.optional(),
|
||||
validDefined: z.string().optional(),
|
||||
});
|
||||
|
||||
const input = {
|
||||
caughtUndefined: undefined,
|
||||
issueUndefined: undefined,
|
||||
validUndefined: undefined,
|
||||
caughtDefined: 123,
|
||||
validDefinedUndefined: "test",
|
||||
validDefined: "valid",
|
||||
};
|
||||
|
||||
// Test both paths produce identical results
|
||||
const jitlessResult = mySchema.parse(input, { jitless: true });
|
||||
const fastpassResult = mySchema.parse(input);
|
||||
|
||||
expect(jitlessResult).toEqual(fastpassResult);
|
||||
expect(jitlessResult).toEqual({
|
||||
caughtUndefined: undefined,
|
||||
issueUndefined: undefined,
|
||||
validUndefined: undefined,
|
||||
defaultValue: "default",
|
||||
caughtDefined: "caught",
|
||||
validDefinedUndefined: undefined,
|
||||
validDefined: "valid",
|
||||
});
|
||||
});
|
||||
|
||||
test("optional with check", () => {
|
||||
const baseSchema = z
|
||||
.string()
|
||||
.optional()
|
||||
.check(({ value, ...ctx }) => {
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
input: value,
|
||||
message: "message",
|
||||
});
|
||||
});
|
||||
|
||||
// this correctly fails
|
||||
expect(baseSchema.safeParse(undefined)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "message",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
const schemaObject = z.object({
|
||||
date: baseSchema,
|
||||
});
|
||||
|
||||
expect(schemaObject.safeParse({ date: undefined })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "message",
|
||||
"path": [
|
||||
"date"
|
||||
]
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("partial - throws error on schema with refinements", () => {
|
||||
const baseSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
items: z.string().array(),
|
||||
});
|
||||
|
||||
const refinedSchema = baseSchema.superRefine((val, ctx) => {
|
||||
if (val.items.length === 0) {
|
||||
ctx.addIssue({
|
||||
message: "Must have at least one item",
|
||||
code: "custom",
|
||||
path: ["items"],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
expect(() => refinedSchema.partial()).toThrow(".partial() cannot be used on object schemas containing refinements");
|
||||
});
|
||||
|
||||
test("partial - throws error on schema with refine", () => {
|
||||
const baseSchema = z.object({
|
||||
password: z.string(),
|
||||
confirmPassword: z.string(),
|
||||
});
|
||||
|
||||
const refinedSchema = baseSchema.refine((data) => data.password === data.confirmPassword, {
|
||||
message: "Passwords must match",
|
||||
});
|
||||
|
||||
expect(() => refinedSchema.partial()).toThrow(".partial() cannot be used on object schemas containing refinements");
|
||||
});
|
||||
|
||||
test("required - preserves refinements", () => {
|
||||
const baseSchema = z.object({
|
||||
name: z.string().optional(),
|
||||
age: z.number().optional(),
|
||||
});
|
||||
|
||||
const refinedSchema = baseSchema.superRefine((val, ctx) => {
|
||||
if (val.name === "admin") {
|
||||
ctx.addIssue({
|
||||
message: "Name cannot be admin",
|
||||
code: "custom",
|
||||
path: ["name"],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const requiredSchema = refinedSchema.required();
|
||||
|
||||
// The refinement should still be applied
|
||||
const result = requiredSchema.safeParse({ name: "admin", age: 25 });
|
||||
expect(result.success).toBe(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues[0].message).toBe("Name cannot be admin");
|
||||
}
|
||||
|
||||
// Valid data should pass
|
||||
const validResult = requiredSchema.safeParse({ name: "user", age: 25 });
|
||||
expect(validResult.success).toBe(true);
|
||||
});
|
||||
|
||||
test("required - refinement is executed on required schema", () => {
|
||||
const baseSchema = z.object({
|
||||
password: z.string().optional(),
|
||||
confirmPassword: z.string().optional(),
|
||||
});
|
||||
|
||||
const refinedSchema = baseSchema.refine((data) => data.password === data.confirmPassword, {
|
||||
message: "Passwords must match",
|
||||
});
|
||||
|
||||
const requiredSchema = refinedSchema.required();
|
||||
|
||||
// Mismatched passwords should fail refinement
|
||||
const result = requiredSchema.safeParse({ password: "abc", confirmPassword: "xyz" });
|
||||
expect(result.success).toBe(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues[0].message).toBe("Passwords must match");
|
||||
}
|
||||
|
||||
// Matching passwords should pass
|
||||
const validResult = requiredSchema.safeParse({ password: "abc", confirmPassword: "abc" });
|
||||
expect(validResult.success).toBe(true);
|
||||
});
|
||||
211
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/pickomit.test.ts
generated
vendored
Normal file
211
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/pickomit.test.ts
generated
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const fish = z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
nested: z.object({}),
|
||||
});
|
||||
|
||||
test("pick type inference", () => {
|
||||
const nameonlyFish = fish.pick({ name: true });
|
||||
type nameonlyFish = z.infer<typeof nameonlyFish>;
|
||||
expectTypeOf<nameonlyFish>().toEqualTypeOf<{ name: string }>();
|
||||
});
|
||||
|
||||
test("pick parse - success", () => {
|
||||
const nameonlyFish = fish.pick({ name: true });
|
||||
nameonlyFish.parse({ name: "bob" });
|
||||
|
||||
// @ts-expect-error checking runtime picks `name` only.
|
||||
const anotherNameonlyFish = fish.pick({ name: true, age: false });
|
||||
anotherNameonlyFish.parse({ name: "bob" });
|
||||
});
|
||||
|
||||
test("pick parse - fail", () => {
|
||||
fish.pick({ name: true }).parse({ name: "12" } as any);
|
||||
fish.pick({ name: true }).parse({ name: "bob", age: 12 } as any);
|
||||
fish.pick({ age: true }).parse({ age: 12 } as any);
|
||||
|
||||
const nameonlyFish = fish.pick({ name: true }).strict();
|
||||
const bad1 = () => nameonlyFish.parse({ name: 12 } as any);
|
||||
const bad2 = () => nameonlyFish.parse({ name: "bob", age: 12 } as any);
|
||||
const bad3 = () => nameonlyFish.parse({ age: 12 } as any);
|
||||
|
||||
// @ts-expect-error checking runtime picks `name` only.
|
||||
const anotherNameonlyFish = fish.pick({ name: true, age: false }).strict();
|
||||
const bad4 = () => anotherNameonlyFish.parse({ name: "bob", age: 12 } as any);
|
||||
|
||||
expect(bad1).toThrow();
|
||||
expect(bad2).toThrow();
|
||||
expect(bad3).toThrow();
|
||||
expect(bad4).toThrow();
|
||||
});
|
||||
|
||||
test("pick - remove optional", () => {
|
||||
const schema = z.object({ a: z.string(), b: z.string().optional() });
|
||||
expect("a" in schema._zod.def.shape).toEqual(true);
|
||||
expect("b" in schema._zod.def.shape!).toEqual(true);
|
||||
const picked = schema.pick({ a: true });
|
||||
expect("a" in picked._zod.def.shape).toEqual(true);
|
||||
expect("b" in picked._zod.def.shape!).toEqual(false);
|
||||
});
|
||||
|
||||
test("omit type inference", () => {
|
||||
const nonameFish = fish.omit({ name: true });
|
||||
type nonameFish = z.infer<typeof nonameFish>;
|
||||
|
||||
expectTypeOf<nonameFish>().toEqualTypeOf<{ age: number; nested: Record<string, never> }>();
|
||||
});
|
||||
|
||||
test("omit parse - success", () => {
|
||||
const nonameFish = fish.omit({ name: true });
|
||||
nonameFish.parse({ age: 12, nested: {} });
|
||||
|
||||
// @ts-expect-error checking runtime omits `name` only.
|
||||
const anotherNonameFish = fish.omit({ name: true, age: false });
|
||||
anotherNonameFish.parse({ age: 12, nested: {} });
|
||||
});
|
||||
|
||||
test("omit parse - fail", () => {
|
||||
const nonameFish = fish.omit({ name: true });
|
||||
const bad1 = () => nonameFish.parse({ name: 12 } as any);
|
||||
const bad2 = () => nonameFish.parse({ age: 12 } as any);
|
||||
const bad3 = () => nonameFish.parse({} as any);
|
||||
|
||||
// @ts-expect-error checking runtime omits `name` only.
|
||||
const anotherNonameFish = fish.omit({ name: true, age: false });
|
||||
const bad4 = () => anotherNonameFish.parse({ nested: {} } as any);
|
||||
|
||||
expect(bad1).toThrow();
|
||||
expect(bad2).toThrow();
|
||||
expect(bad3).toThrow();
|
||||
expect(bad4).toThrow();
|
||||
});
|
||||
|
||||
test("omit - remove optional", () => {
|
||||
const schema = z.object({ a: z.string(), b: z.string().optional() });
|
||||
expect("a" in schema._zod.def.shape).toEqual(true);
|
||||
const omitted = schema.omit({ a: true });
|
||||
expect("a" in omitted._zod.def.shape).toEqual(false);
|
||||
});
|
||||
|
||||
test("nonstrict inference", () => {
|
||||
const laxfish = fish.pick({ name: true }).catchall(z.any());
|
||||
type laxfish = z.infer<typeof laxfish>;
|
||||
expectTypeOf<laxfish>().toEqualTypeOf<{ name: string; [k: string]: any }>();
|
||||
});
|
||||
|
||||
test("nonstrict parsing - pass", () => {
|
||||
const laxfish = fish.passthrough().pick({ name: true });
|
||||
laxfish.parse({ name: "asdf", whatever: "asdf" });
|
||||
laxfish.parse({ name: "asdf", age: 12, nested: {} });
|
||||
});
|
||||
|
||||
test("nonstrict parsing - fail", () => {
|
||||
const laxfish = fish.passthrough().pick({ name: true });
|
||||
const bad = () => laxfish.parse({ whatever: "asdf" } as any);
|
||||
expect(bad).toThrow();
|
||||
});
|
||||
|
||||
test("pick/omit/required/partial - do not allow unknown keys", () => {
|
||||
const schema = z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
});
|
||||
|
||||
// Mixed valid + invalid keys
|
||||
// @ts-expect-error
|
||||
expect(() => schema.pick({ name: true, asdf: true }).safeParse({})).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => schema.omit({ name: true, asdf: true }).safeParse({})).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => schema.partial({ name: true, asdf: true }).safeParse({})).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => schema.required({ name: true, asdf: true }).safeParse({})).toThrow();
|
||||
|
||||
// Only invalid keys
|
||||
// @ts-expect-error
|
||||
expect(() => schema.pick({ $unknown: true }).safeParse({})).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => schema.omit({ $unknown: true }).safeParse({})).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => schema.required({ $unknown: true }).safeParse({})).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => schema.partial({ $unknown: true }).safeParse({})).toThrow();
|
||||
});
|
||||
|
||||
test("pick - throws error on schema with refinements", () => {
|
||||
const baseSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
items: z.string().array(),
|
||||
});
|
||||
|
||||
const refinedSchema = baseSchema.superRefine((val, ctx) => {
|
||||
if (val.items.length === 0) {
|
||||
ctx.addIssue({
|
||||
message: "Must have at least one item",
|
||||
code: "custom",
|
||||
path: ["items"],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
expect(() => refinedSchema.pick({ name: true })).toThrow(
|
||||
".pick() cannot be used on object schemas containing refinements"
|
||||
);
|
||||
});
|
||||
|
||||
test("omit - throws error on schema with refinements", () => {
|
||||
const baseSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
items: z.string().array(),
|
||||
});
|
||||
|
||||
const refinedSchema = baseSchema.superRefine((val, ctx) => {
|
||||
if (val.items.length === 0) {
|
||||
ctx.addIssue({
|
||||
message: "Must have at least one item",
|
||||
code: "custom",
|
||||
path: ["items"],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
expect(() => refinedSchema.omit({ id: true })).toThrow(
|
||||
".omit() cannot be used on object schemas containing refinements"
|
||||
);
|
||||
});
|
||||
|
||||
test("pick - throws error on schema with refine", () => {
|
||||
const baseSchema = z.object({
|
||||
password: z.string(),
|
||||
confirmPassword: z.string(),
|
||||
});
|
||||
|
||||
const refinedSchema = baseSchema.refine((data) => data.password === data.confirmPassword, {
|
||||
message: "Passwords must match",
|
||||
});
|
||||
|
||||
expect(() => refinedSchema.pick({ password: true })).toThrow(
|
||||
".pick() cannot be used on object schemas containing refinements"
|
||||
);
|
||||
});
|
||||
|
||||
test("omit - throws error on schema with refine", () => {
|
||||
const baseSchema = z.object({
|
||||
password: z.string(),
|
||||
confirmPassword: z.string(),
|
||||
email: z.string(),
|
||||
});
|
||||
|
||||
const refinedSchema = baseSchema.refine((data) => data.password === data.confirmPassword, {
|
||||
message: "Passwords must match",
|
||||
});
|
||||
|
||||
expect(() => refinedSchema.omit({ email: true })).toThrow(
|
||||
".omit() cannot be used on object schemas containing refinements"
|
||||
);
|
||||
});
|
||||
101
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/pipe.test.ts
generated
vendored
Normal file
101
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/pipe.test.ts
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("string to number pipe", () => {
|
||||
const schema = z.string().transform(Number).pipe(z.number());
|
||||
expect(schema.parse("1234")).toEqual(1234);
|
||||
});
|
||||
|
||||
test("string to number pipe async", async () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.transform(async (val) => Number(val))
|
||||
.pipe(z.number());
|
||||
expect(await schema.parseAsync("1234")).toEqual(1234);
|
||||
});
|
||||
|
||||
test("string with default fallback", () => {
|
||||
const stringWithDefault = z
|
||||
.pipe(
|
||||
z.transform((v) => (v === "none" ? undefined : v)),
|
||||
z.string()
|
||||
)
|
||||
.catch("default");
|
||||
|
||||
expect(stringWithDefault.parse("ok")).toBe("ok");
|
||||
expect(stringWithDefault.parse(undefined)).toBe("default");
|
||||
expect(stringWithDefault.parse("none")).toBe("default");
|
||||
expect(stringWithDefault.parse(15)).toBe("default");
|
||||
});
|
||||
|
||||
test("continue on non-fatal errors", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.refine((c) => c === "1234", "A")
|
||||
.transform((val) => Number(val))
|
||||
.refine((c) => c === 1234, "B");
|
||||
|
||||
schema.parse("1234");
|
||||
|
||||
expect(schema.safeParse("4321")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "A"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("break on fatal errors", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.refine((c) => c === "1234", { message: "A", abort: true })
|
||||
.transform((val) => Number(val))
|
||||
.refine((c) => c === 1234, "B");
|
||||
|
||||
schema.parse("1234");
|
||||
|
||||
expect(schema.safeParse("4321")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "A"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("reverse parsing with pipe", () => {
|
||||
const schema = z.string().pipe(z.string());
|
||||
|
||||
// Reverse direction: default should NOT be applied
|
||||
expect(z.safeDecode(schema, "asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": "asdf",
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
expect(z.safeEncode(schema, "asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": "asdf",
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("reverse parsing with pipe", () => {
|
||||
const schema = z.string().transform((val) => val.length);
|
||||
|
||||
// should throw
|
||||
expect(() => z.encode(schema, 1234)).toThrow();
|
||||
});
|
||||
74
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/prefault.test.ts
generated
vendored
Normal file
74
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/prefault.test.ts
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
test("basic prefault", () => {
|
||||
const a = z.prefault(z.string().trim(), " default ");
|
||||
expect(a).toBeInstanceOf(z.ZodPrefault);
|
||||
expect(a.parse(" asdf ")).toEqual("asdf");
|
||||
expect(a.parse(undefined)).toEqual("default");
|
||||
|
||||
type inp = z.input<typeof a>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<string | undefined>();
|
||||
type out = z.output<typeof a>;
|
||||
expectTypeOf<out>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
test("prefault inside object", () => {
|
||||
// test optinality
|
||||
const a = z.object({
|
||||
name: z.string().optional(),
|
||||
age: z.number().default(1234),
|
||||
email: z.string().prefault("1234"),
|
||||
});
|
||||
|
||||
type inp = z.input<typeof a>;
|
||||
expectTypeOf<inp>().toEqualTypeOf<{
|
||||
name?: string | undefined;
|
||||
age?: number | undefined;
|
||||
email?: string | undefined;
|
||||
}>();
|
||||
|
||||
type out = z.output<typeof a>;
|
||||
expectTypeOf<out>().toEqualTypeOf<{
|
||||
name?: string | undefined;
|
||||
age: number;
|
||||
email: string;
|
||||
}>();
|
||||
});
|
||||
|
||||
test("object schema with prefault should return shallow clone", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
a: z.string(),
|
||||
})
|
||||
.default({ a: "x" });
|
||||
const result1 = schema.parse(undefined);
|
||||
const result2 = schema.parse(undefined);
|
||||
expect(result1).not.toBe(result2);
|
||||
expect(result1).toEqual(result2);
|
||||
});
|
||||
|
||||
test("direction-aware prefault", () => {
|
||||
const schema = z.string().prefault("hello");
|
||||
|
||||
// Forward direction (regular parse): prefault should be applied
|
||||
expect(schema.parse(undefined)).toBe("hello");
|
||||
|
||||
// Reverse direction (encode): prefault should NOT be applied, undefined should fail validation
|
||||
expect(z.safeEncode(schema, undefined as any)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
// But valid values should still work in reverse
|
||||
expect(z.encode(schema, "world")).toBe("world");
|
||||
});
|
||||
282
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/preprocess.test.ts
generated
vendored
Normal file
282
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/preprocess.test.ts
generated
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("preprocess", () => {
|
||||
const schema = z.preprocess((data) => [data], z.string().array());
|
||||
const value = schema.parse("asdf");
|
||||
expect(value).toEqual(["asdf"]);
|
||||
expectTypeOf<(typeof schema)["_input"]>().toEqualTypeOf<unknown>();
|
||||
});
|
||||
|
||||
test("async preprocess", async () => {
|
||||
const schema = z.preprocess(async (data) => {
|
||||
return [data];
|
||||
}, z.string().array());
|
||||
const value = await schema.safeParseAsync("asdf");
|
||||
expect(value.data).toEqual(["asdf"]);
|
||||
expect(value).toMatchInlineSnapshot(`
|
||||
{
|
||||
"data": [
|
||||
"asdf",
|
||||
],
|
||||
"success": true,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("ctx.addIssue accepts string", () => {
|
||||
const schema = z.preprocess((_, ctx) => {
|
||||
ctx.addIssue("bad stuff");
|
||||
}, z.string());
|
||||
const result = schema.safeParse("asdf");
|
||||
expect(result.error!.issues).toHaveLength(1);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"message": "bad stuff",
|
||||
"code": "custom",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("preprocess ctx.addIssue with parse", () => {
|
||||
const a = z.preprocess((data, ctx) => {
|
||||
ctx.addIssue({
|
||||
input: data,
|
||||
code: "custom",
|
||||
message: `${data} is not one of our allowed strings`,
|
||||
});
|
||||
return data;
|
||||
}, z.string());
|
||||
|
||||
const result = a.safeParse("asdf");
|
||||
|
||||
// expect(result.error!.toJSON()).toContain("not one of our allowed strings");
|
||||
|
||||
expect(result.error!.issues).toHaveLength(1);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "asdf is not one of our allowed strings",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("preprocess ctx.addIssue fatal by default", () => {
|
||||
const schema = z.preprocess((data, ctx) => {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
});
|
||||
|
||||
return data;
|
||||
}, z.string());
|
||||
const result = schema.safeParse(1234);
|
||||
|
||||
expect(result.error!.issues).toHaveLength(1);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("preprocess ctx.addIssue fatal true", () => {
|
||||
const schema = z.preprocess((data, ctx) => {
|
||||
ctx.addIssue({
|
||||
input: data,
|
||||
code: "custom",
|
||||
origin: "custom",
|
||||
message: `custom error`,
|
||||
fatal: true,
|
||||
});
|
||||
return data;
|
||||
}, z.string());
|
||||
|
||||
const result = schema.safeParse(1234);
|
||||
|
||||
expect(result.error!.issues).toHaveLength(1);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"origin": "custom",
|
||||
"message": "custom error",
|
||||
"fatal": true,
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("async preprocess ctx.addIssue with parseAsync", async () => {
|
||||
const schema = z.preprocess(async (data, ctx) => {
|
||||
ctx.addIssue({
|
||||
input: data,
|
||||
code: "custom",
|
||||
message: `${data} is not one of our allowed strings`,
|
||||
});
|
||||
return data;
|
||||
}, z.string());
|
||||
|
||||
const result = await schema.safeParseAsync("asdf");
|
||||
|
||||
expect(result.error!.issues).toHaveLength(1);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "asdf is not one of our allowed strings",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("z.NEVER in preprocess", () => {
|
||||
const foo = z.preprocess((val, ctx) => {
|
||||
if (!val) {
|
||||
ctx.addIssue({ input: val, code: "custom", message: "bad" });
|
||||
return z.NEVER;
|
||||
}
|
||||
return val;
|
||||
}, z.number());
|
||||
|
||||
type foo = z.infer<typeof foo>;
|
||||
expectTypeOf<foo>().toEqualTypeOf<number>();
|
||||
const result = foo.safeParse(undefined);
|
||||
|
||||
expect(result.error!.issues).toHaveLength(1);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "bad",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("preprocess as the second property of object", () => {
|
||||
const schema = z.object({
|
||||
nonEmptyStr: z.string().min(1),
|
||||
positiveNum: z.preprocess((v) => Number(v), z.number().positive()),
|
||||
});
|
||||
const result = schema.safeParse({
|
||||
nonEmptyStr: "",
|
||||
positiveNum: "",
|
||||
});
|
||||
|
||||
expect(result.error!.issues).toHaveLength(2);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 1,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"nonEmptyStr"
|
||||
],
|
||||
"message": "Too small: expected string to have >=1 characters"
|
||||
},
|
||||
{
|
||||
"origin": "number",
|
||||
"code": "too_small",
|
||||
"minimum": 0,
|
||||
"inclusive": false,
|
||||
"path": [
|
||||
"positiveNum"
|
||||
],
|
||||
"message": "Too small: expected number to be >0"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("preprocess validates with sibling errors", () => {
|
||||
const schema = z.object({
|
||||
missing: z.string().refine(() => false),
|
||||
preprocess: z.preprocess((data: any) => data?.trim(), z.string().regex(/ asdf/)),
|
||||
});
|
||||
|
||||
const result = schema.safeParse({ preprocess: " asdf" });
|
||||
|
||||
expect(result.error!.issues).toHaveLength(2);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"missing"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
},
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "invalid_format",
|
||||
"format": "regex",
|
||||
"pattern": "/ asdf/",
|
||||
"path": [
|
||||
"preprocess"
|
||||
],
|
||||
"message": "Invalid string: must match pattern / asdf/"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("perform transform with non-fatal issues", () => {
|
||||
const A = z
|
||||
.string()
|
||||
.refine((_) => false)
|
||||
.min(4)
|
||||
.transform((val) => val.length)
|
||||
.pipe(z.number())
|
||||
.refine((_) => false);
|
||||
expect(A.safeParse("asdfasdf").error!.issues).toHaveLength(1);
|
||||
expect(A.safeParse("asdfasdf").error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
175
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/primitive.test.ts
generated
vendored
Normal file
175
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/primitive.test.ts
generated
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const literalStringSchema = z.literal("asdf");
|
||||
const literalNumberSchema = z.literal(12);
|
||||
const literalBooleanSchema = z.literal(true);
|
||||
const literalBigIntSchema = z.literal(BigInt(42));
|
||||
|
||||
const stringSchema = z.string();
|
||||
const numberSchema = z.number();
|
||||
const bigintSchema = z.bigint();
|
||||
const booleanSchema = z.boolean();
|
||||
const dateSchema = z.date();
|
||||
const symbolSchema = z.symbol();
|
||||
const nullSchema = z.null();
|
||||
const undefinedSchema = z.undefined();
|
||||
const stringSchemaOptional = z.string().optional();
|
||||
const stringSchemaNullable = z.string().nullable();
|
||||
const numberSchemaOptional = z.number().optional();
|
||||
const numberSchemaNullable = z.number().nullable();
|
||||
const bigintSchemaOptional = z.bigint().optional();
|
||||
const bigintSchemaNullable = z.bigint().nullable();
|
||||
const booleanSchemaOptional = z.boolean().optional();
|
||||
const booleanSchemaNullable = z.boolean().nullable();
|
||||
const dateSchemaOptional = z.date().optional();
|
||||
const dateSchemaNullable = z.date().nullable();
|
||||
const symbolSchemaOptional = z.symbol().optional();
|
||||
const symbolSchemaNullable = z.symbol().nullable();
|
||||
|
||||
test("literal string schema", () => {
|
||||
expect(literalStringSchema.parse("asdf")).toBe("asdf");
|
||||
expect(() => literalStringSchema.parse("not_asdf")).toThrow();
|
||||
expect(() => literalStringSchema.parse(123)).toThrow();
|
||||
expect(() => literalStringSchema.parse(true)).toThrow();
|
||||
expect(() => literalStringSchema.parse({})).toThrow();
|
||||
});
|
||||
|
||||
test("literal number schema", () => {
|
||||
expect(literalNumberSchema.parse(12)).toBe(12);
|
||||
expect(() => literalNumberSchema.parse(13)).toThrow();
|
||||
expect(() => literalNumberSchema.parse("foo")).toThrow();
|
||||
expect(() => literalNumberSchema.parse(true)).toThrow();
|
||||
expect(() => literalNumberSchema.parse({})).toThrow();
|
||||
});
|
||||
|
||||
test("literal boolean schema", () => {
|
||||
expect(literalBooleanSchema.parse(true)).toBe(true);
|
||||
expect(() => literalBooleanSchema.parse(false)).toThrow();
|
||||
expect(() => literalBooleanSchema.parse("asdf")).toThrow();
|
||||
expect(() => literalBooleanSchema.parse(123)).toThrow();
|
||||
expect(() => literalBooleanSchema.parse({})).toThrow();
|
||||
});
|
||||
|
||||
test("literal bigint schema", () => {
|
||||
expect(literalBigIntSchema.parse(BigInt(42))).toBe(BigInt(42));
|
||||
expect(() => literalBigIntSchema.parse(BigInt(43))).toThrow();
|
||||
expect(() => literalBigIntSchema.parse("asdf")).toThrow();
|
||||
expect(() => literalBigIntSchema.parse(123)).toThrow();
|
||||
expect(() => literalBigIntSchema.parse({})).toThrow();
|
||||
});
|
||||
|
||||
test("string schema", () => {
|
||||
stringSchema.parse("foo");
|
||||
expect(() => stringSchema.parse(Math.random())).toThrow();
|
||||
expect(() => stringSchema.parse(true)).toThrow();
|
||||
expect(() => stringSchema.parse(undefined)).toThrow();
|
||||
expect(() => stringSchema.parse(null)).toThrow();
|
||||
});
|
||||
|
||||
test("number schema", () => {
|
||||
numberSchema.parse(Math.random());
|
||||
expect(() => numberSchema.parse("foo")).toThrow();
|
||||
expect(() => numberSchema.parse(BigInt(17))).toThrow();
|
||||
expect(() => numberSchema.parse(true)).toThrow();
|
||||
expect(() => numberSchema.parse(undefined)).toThrow();
|
||||
expect(() => numberSchema.parse(null)).toThrow();
|
||||
});
|
||||
|
||||
test("bigint schema", () => {
|
||||
bigintSchema.parse(BigInt(17));
|
||||
expect(() => bigintSchema.parse("foo")).toThrow();
|
||||
expect(() => bigintSchema.parse(Math.random())).toThrow();
|
||||
expect(() => bigintSchema.parse(true)).toThrow();
|
||||
expect(() => bigintSchema.parse(undefined)).toThrow();
|
||||
expect(() => bigintSchema.parse(null)).toThrow();
|
||||
});
|
||||
|
||||
test("boolean schema", () => {
|
||||
booleanSchema.parse(true);
|
||||
expect(() => booleanSchema.parse("foo")).toThrow();
|
||||
expect(() => booleanSchema.parse(Math.random())).toThrow();
|
||||
expect(() => booleanSchema.parse(undefined)).toThrow();
|
||||
expect(() => booleanSchema.parse(null)).toThrow();
|
||||
});
|
||||
|
||||
test("date schema", async () => {
|
||||
dateSchema.parse(new Date());
|
||||
expect(() => dateSchema.parse("foo")).toThrow();
|
||||
expect(() => dateSchema.parse(Math.random())).toThrow();
|
||||
expect(() => dateSchema.parse(true)).toThrow();
|
||||
expect(() => dateSchema.parse(undefined)).toThrow();
|
||||
expect(() => dateSchema.parse(null)).toThrow();
|
||||
expect(await dateSchema.safeParseAsync(new Date("invalid"))).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "date",
|
||||
"code": "invalid_type",
|
||||
"received": "Invalid Date",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected date, received Date"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("symbol schema", () => {
|
||||
symbolSchema.parse(Symbol("foo"));
|
||||
expect(() => symbolSchema.parse("foo")).toThrow();
|
||||
expect(() => symbolSchema.parse(Math.random())).toThrow();
|
||||
expect(() => symbolSchema.parse(true)).toThrow();
|
||||
expect(() => symbolSchema.parse(new Date())).toThrow();
|
||||
expect(() => symbolSchema.parse(undefined)).toThrow();
|
||||
expect(() => symbolSchema.parse(null)).toThrow();
|
||||
});
|
||||
|
||||
test("undefined schema", () => {
|
||||
undefinedSchema.parse(undefined);
|
||||
expect(() => undefinedSchema.parse("foo")).toThrow();
|
||||
expect(() => undefinedSchema.parse(Math.random())).toThrow();
|
||||
expect(() => undefinedSchema.parse(true)).toThrow();
|
||||
expect(() => undefinedSchema.parse(null)).toThrow();
|
||||
});
|
||||
|
||||
test("null schema", () => {
|
||||
nullSchema.parse(null);
|
||||
expect(() => nullSchema.parse("foo")).toThrow();
|
||||
expect(() => nullSchema.parse(Math.random())).toThrow();
|
||||
expect(() => nullSchema.parse(true)).toThrow();
|
||||
expect(() => nullSchema.parse(undefined)).toThrow();
|
||||
});
|
||||
|
||||
test("primitive inference", () => {
|
||||
expectTypeOf<z.TypeOf<typeof literalStringSchema>>().toEqualTypeOf<"asdf">();
|
||||
expectTypeOf<z.TypeOf<typeof literalNumberSchema>>().toEqualTypeOf<12>();
|
||||
expectTypeOf<z.TypeOf<typeof literalBooleanSchema>>().toEqualTypeOf<true>();
|
||||
expectTypeOf<z.TypeOf<typeof literalBigIntSchema>>().toEqualTypeOf<bigint>();
|
||||
expectTypeOf<z.TypeOf<typeof stringSchema>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.TypeOf<typeof numberSchema>>().toEqualTypeOf<number>();
|
||||
expectTypeOf<z.TypeOf<typeof bigintSchema>>().toEqualTypeOf<bigint>();
|
||||
expectTypeOf<z.TypeOf<typeof booleanSchema>>().toEqualTypeOf<boolean>();
|
||||
expectTypeOf<z.TypeOf<typeof dateSchema>>().toEqualTypeOf<Date>();
|
||||
expectTypeOf<z.TypeOf<typeof symbolSchema>>().toEqualTypeOf<symbol>();
|
||||
expectTypeOf<z.TypeOf<typeof nullSchema>>().toEqualTypeOf<null>();
|
||||
expectTypeOf<z.TypeOf<typeof undefinedSchema>>().toEqualTypeOf<undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof stringSchemaOptional>>().toEqualTypeOf<string | undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof stringSchemaNullable>>().toEqualTypeOf<string | null>();
|
||||
expectTypeOf<z.TypeOf<typeof numberSchemaOptional>>().toEqualTypeOf<number | undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof numberSchemaNullable>>().toEqualTypeOf<number | null>();
|
||||
expectTypeOf<z.TypeOf<typeof bigintSchemaOptional>>().toEqualTypeOf<bigint | undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof bigintSchemaNullable>>().toEqualTypeOf<bigint | null>();
|
||||
expectTypeOf<z.TypeOf<typeof booleanSchemaOptional>>().toEqualTypeOf<boolean | undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof booleanSchemaNullable>>().toEqualTypeOf<boolean | null>();
|
||||
expectTypeOf<z.TypeOf<typeof dateSchemaOptional>>().toEqualTypeOf<Date | undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof dateSchemaNullable>>().toEqualTypeOf<Date | null>();
|
||||
expectTypeOf<z.TypeOf<typeof symbolSchemaOptional>>().toEqualTypeOf<symbol | undefined>();
|
||||
expectTypeOf<z.TypeOf<typeof symbolSchemaNullable>>().toEqualTypeOf<symbol | null>();
|
||||
});
|
||||
|
||||
test("get literal values", () => {
|
||||
expect(literalStringSchema.values).toEqual(new Set(["asdf"]));
|
||||
expect(literalStringSchema._zod.def.values).toEqual(["asdf"]);
|
||||
});
|
||||
81
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/promise.test.ts
generated
vendored
Normal file
81
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/promise.test.ts
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const promSchema = z.promise(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
age: z.number(),
|
||||
})
|
||||
);
|
||||
|
||||
test("promise inference", () => {
|
||||
type promSchemaType = z.infer<typeof promSchema>;
|
||||
expectTypeOf<promSchemaType>().toEqualTypeOf<Promise<{ name: string; age: number }>>();
|
||||
});
|
||||
|
||||
test("promise parsing success", async () => {
|
||||
// expect(() => promSchema.parse(Promise.resolve({ name: "Bobby", age: 10 }))).toThrow();
|
||||
const pr = promSchema.parseAsync(Promise.resolve({ name: "Bobby", age: 10 }));
|
||||
expect(pr).toBeInstanceOf(Promise);
|
||||
const result = await pr;
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"age": 10,
|
||||
"name": "Bobby",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("promise parsing fail", async () => {
|
||||
const bad = await promSchema.safeParseAsync(Promise.resolve({ name: "Bobby", age: "10" }));
|
||||
expect(bad.success).toBe(false);
|
||||
expect(bad.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
test("promise parsing fail 2", async () => {
|
||||
const result = await promSchema.safeParseAsync(Promise.resolve({ name: "Bobby", age: "10" }));
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toBeInstanceOf(z.ZodError);
|
||||
});
|
||||
|
||||
test("promise parsing fail", () => {
|
||||
const bad = () => promSchema.parse({ then: () => {}, catch: {} });
|
||||
expect(bad).toThrow();
|
||||
});
|
||||
|
||||
test("sync promise parsing", () => {
|
||||
expect(() => z.promise(z.string()).parse(Promise.resolve("asfd"))).toThrow();
|
||||
});
|
||||
|
||||
const asyncFunction = z.function({
|
||||
input: z.tuple([]),
|
||||
output: promSchema,
|
||||
});
|
||||
|
||||
test("async function pass", async () => {
|
||||
const validatedFunction = asyncFunction.implementAsync(async () => {
|
||||
return { name: "jimmy", age: 14 };
|
||||
});
|
||||
await expect(validatedFunction()).resolves.toEqual({
|
||||
name: "jimmy",
|
||||
age: 14,
|
||||
});
|
||||
});
|
||||
|
||||
test("async function fail", async () => {
|
||||
const validatedFunction = asyncFunction.implementAsync(() => {
|
||||
return Promise.resolve("asdf" as any);
|
||||
});
|
||||
await expect(validatedFunction()).rejects.toBeInstanceOf(z.core.$ZodError);
|
||||
});
|
||||
|
||||
test("async promise parsing", () => {
|
||||
const res = z.promise(z.number()).parseAsync(Promise.resolve(12));
|
||||
expect(res).toBeInstanceOf(Promise);
|
||||
});
|
||||
|
||||
test("resolves", () => {
|
||||
const foo = z.literal("foo");
|
||||
const res = z.promise(foo);
|
||||
expect(res.unwrap()).toEqual(foo);
|
||||
});
|
||||
23
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/prototypes.test.ts
generated
vendored
Normal file
23
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/prototypes.test.ts
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
declare module "zod/v4" {
|
||||
interface ZodType {
|
||||
/** @deprecated */
|
||||
_classic(): string;
|
||||
}
|
||||
}
|
||||
|
||||
test("prototype extension", () => {
|
||||
z.ZodType.prototype._classic = function () {
|
||||
return "_classic";
|
||||
};
|
||||
|
||||
// should pass
|
||||
const result = z.string()._classic();
|
||||
expect(result).toBe("_classic");
|
||||
// expectTypeOf<typeof result>().toEqualTypeOf<string>();
|
||||
|
||||
// clean up
|
||||
z.ZodType.prototype._classic = undefined;
|
||||
});
|
||||
252
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/readonly.test.ts
generated
vendored
Normal file
252
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/readonly.test.ts
generated
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
enum testEnum {
|
||||
A = 0,
|
||||
B = 1,
|
||||
}
|
||||
|
||||
test("flat inference", () => {
|
||||
const readonlyString = z.string().readonly();
|
||||
const readonlyNumber = z.number().readonly();
|
||||
const readonlyNaN = z.nan().readonly();
|
||||
const readonlyBigInt = z.bigint().readonly();
|
||||
const readonlyBoolean = z.boolean().readonly();
|
||||
const readonlyDate = z.date().readonly();
|
||||
const readonlyUndefined = z.undefined().readonly();
|
||||
const readonlyNull = z.null().readonly();
|
||||
const readonlyAny = z.any().readonly();
|
||||
const readonlyUnknown = z.unknown().readonly();
|
||||
const readonlyVoid = z.void().readonly();
|
||||
const readonlyStringArray = z.array(z.string()).readonly();
|
||||
const readonlyTuple = z.tuple([z.string(), z.number()]).readonly();
|
||||
const readonlyMap = z.map(z.string(), z.date()).readonly();
|
||||
const readonlySet = z.set(z.string()).readonly();
|
||||
const readonlyStringRecord = z.record(z.string(), z.string()).readonly();
|
||||
const readonlyNumberRecord = z.record(z.string(), z.number()).readonly();
|
||||
const readonlyObject = z.object({ a: z.string(), 1: z.number() }).readonly();
|
||||
const readonlyEnum = z.nativeEnum(testEnum).readonly();
|
||||
const readonlyPromise = z.promise(z.string()).readonly();
|
||||
|
||||
expectTypeOf<typeof readonlyString._output>().toEqualTypeOf<string>();
|
||||
expectTypeOf<typeof readonlyNumber._output>().toEqualTypeOf<number>();
|
||||
expectTypeOf<typeof readonlyNaN._output>().toEqualTypeOf<number>();
|
||||
expectTypeOf<typeof readonlyBigInt._output>().toEqualTypeOf<bigint>();
|
||||
expectTypeOf<typeof readonlyBoolean._output>().toEqualTypeOf<boolean>();
|
||||
expectTypeOf<typeof readonlyDate._output>().toEqualTypeOf<Date>();
|
||||
expectTypeOf<typeof readonlyUndefined._output>().toEqualTypeOf<undefined>();
|
||||
expectTypeOf<typeof readonlyNull._output>().toEqualTypeOf<null>();
|
||||
expectTypeOf<typeof readonlyAny._output>().toEqualTypeOf<any>();
|
||||
expectTypeOf<typeof readonlyUnknown._output>().toEqualTypeOf<Readonly<unknown>>();
|
||||
expectTypeOf<typeof readonlyVoid._output>().toEqualTypeOf<void>();
|
||||
expectTypeOf<typeof readonlyStringArray._output>().toEqualTypeOf<readonly string[]>();
|
||||
expectTypeOf<typeof readonlyTuple._output>().toEqualTypeOf<readonly [string, number]>();
|
||||
expectTypeOf<typeof readonlyMap._output>().toEqualTypeOf<ReadonlyMap<string, Date>>();
|
||||
expectTypeOf<typeof readonlySet._output>().toEqualTypeOf<ReadonlySet<string>>();
|
||||
expectTypeOf<typeof readonlyStringRecord._output>().toEqualTypeOf<Readonly<Record<string, string>>>();
|
||||
expectTypeOf<typeof readonlyNumberRecord._output>().toEqualTypeOf<Readonly<Record<string, number>>>();
|
||||
expectTypeOf<typeof readonlyObject._output>().toEqualTypeOf<{ readonly a: string; readonly 1: number }>();
|
||||
expectTypeOf<typeof readonlyEnum._output>().toEqualTypeOf<Readonly<testEnum>>();
|
||||
expectTypeOf<typeof readonlyPromise._output>().toEqualTypeOf<Promise<string>>();
|
||||
});
|
||||
|
||||
// test("deep inference", () => {
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[0]>>().toEqualTypeOf<string>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[1]>>().toEqualTypeOf<number>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[2]>>().toEqualTypeOf<number>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[3]>>().toEqualTypeOf<bigint>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[4]>>().toEqualTypeOf<boolean>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[5]>>().toEqualTypeOf<Date>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[6]>>().toEqualTypeOf<undefined>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[7]>>().toEqualTypeOf<null>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[8]>>().toEqualTypeOf<any>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[9]>
|
||||
// >().toEqualTypeOf<Readonly<unknown>>();
|
||||
// expectTypeOf<z.infer<(typeof deepReadonlySchemas_0)[10]>>().toEqualTypeOf<void>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[11]>
|
||||
// >().toEqualTypeOf<(args_0: string, args_1: number, ...args_2: unknown[]) => unknown>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[12]>
|
||||
// >().toEqualTypeOf<readonly string[]>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[13]>
|
||||
// >().toEqualTypeOf<readonly [string, number]>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[14]>
|
||||
// >().toEqualTypeOf<ReadonlyMap<string, Date>>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[15]>
|
||||
// >().toEqualTypeOf<ReadonlySet<Promise<string>>>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[16]>
|
||||
// >().toEqualTypeOf<Readonly<Record<string, string>>>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[17]>
|
||||
// >().toEqualTypeOf<Readonly<Record<string, number>>>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[18]>
|
||||
// >().toEqualTypeOf<{ readonly a: string; readonly 1: number }>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[19]>
|
||||
// >().toEqualTypeOf<Readonly<testEnum>>();
|
||||
// expectTypeOf<
|
||||
// z.infer<(typeof deepReadonlySchemas_0)[20]>
|
||||
// >().toEqualTypeOf<Promise<string>>();
|
||||
|
||||
// expectTypeOf<
|
||||
// z.infer<typeof crazyDeepReadonlySchema>
|
||||
// >().toEqualTypeOf<ReadonlyMap<
|
||||
// ReadonlySet<readonly [string, number]>,
|
||||
// {
|
||||
// readonly a: {
|
||||
// readonly [x: string]: readonly any[];
|
||||
// };
|
||||
// readonly b: {
|
||||
// readonly c: {
|
||||
// readonly d: {
|
||||
// readonly e: {
|
||||
// readonly f: {
|
||||
// readonly g?: {};
|
||||
// };
|
||||
// };
|
||||
// };
|
||||
// };
|
||||
// };
|
||||
// }
|
||||
// >>();
|
||||
// });
|
||||
|
||||
test("object freezing", async () => {
|
||||
expect(Object.isFrozen(z.array(z.string()).readonly().parse(["a"]))).toBe(true);
|
||||
expect(Object.isFrozen(z.tuple([z.string(), z.number()]).readonly().parse(["a", 1]))).toBe(true);
|
||||
expect(
|
||||
Object.isFrozen(
|
||||
z
|
||||
.map(z.string(), z.date())
|
||||
.readonly()
|
||||
.parse(new Map([["a", new Date()]]))
|
||||
)
|
||||
).toBe(true);
|
||||
|
||||
expect(Object.isFrozen(z.record(z.string(), z.string()).readonly().parse({ a: "b" }))).toBe(true);
|
||||
expect(Object.isFrozen(z.record(z.string(), z.number()).readonly().parse({ a: 1 }))).toBe(true);
|
||||
expect(Object.isFrozen(z.object({ a: z.string(), 1: z.number() }).readonly().parse({ a: "b", 1: 2 }))).toBe(true);
|
||||
expect(
|
||||
Object.isFrozen(
|
||||
await z
|
||||
.set(z.promise(z.string()))
|
||||
.readonly()
|
||||
.parseAsync(new Set([Promise.resolve("a")]))
|
||||
)
|
||||
).toBe(true);
|
||||
expect(Object.isFrozen(await z.promise(z.string()).readonly().parseAsync(Promise.resolve("a")))).toBe(true);
|
||||
});
|
||||
|
||||
test("async object freezing", async () => {
|
||||
expect(Object.isFrozen(await z.array(z.string()).readonly().parseAsync(["a"]))).toBe(true);
|
||||
expect(Object.isFrozen(await z.tuple([z.string(), z.number()]).readonly().parseAsync(["a", 1]))).toBe(true);
|
||||
expect(
|
||||
Object.isFrozen(
|
||||
await z
|
||||
.map(z.string(), z.date())
|
||||
.readonly()
|
||||
.parseAsync(new Map([["a", new Date()]]))
|
||||
)
|
||||
).toBe(true);
|
||||
expect(
|
||||
Object.isFrozen(
|
||||
await z
|
||||
.set(z.promise(z.string()))
|
||||
.readonly()
|
||||
.parseAsync(new Set([Promise.resolve("a")]))
|
||||
)
|
||||
).toBe(true);
|
||||
expect(Object.isFrozen(await z.record(z.string(), z.string()).readonly().parseAsync({ a: "b" }))).toBe(true);
|
||||
expect(Object.isFrozen(await z.record(z.string(), z.number()).readonly().parseAsync({ a: 1 }))).toBe(true);
|
||||
expect(
|
||||
Object.isFrozen(await z.object({ a: z.string(), 1: z.number() }).readonly().parseAsync({ a: "b", 1: 2 }))
|
||||
).toBe(true);
|
||||
expect(Object.isFrozen(await z.promise(z.string()).readonly().parseAsync(Promise.resolve("a")))).toBe(true);
|
||||
});
|
||||
|
||||
test("readonly inference", () => {
|
||||
const readonlyStringArray = z.string().array().readonly();
|
||||
const readonlyStringTuple = z.tuple([z.string()]).readonly();
|
||||
const deepReadonly = z.object({ a: z.string() }).readonly();
|
||||
|
||||
type readonlyStringArray = z.infer<typeof readonlyStringArray>;
|
||||
type readonlyStringTuple = z.infer<typeof readonlyStringTuple>;
|
||||
type deepReadonly = z.infer<typeof deepReadonly>;
|
||||
|
||||
expectTypeOf<readonlyStringArray>().toEqualTypeOf<readonly string[]>();
|
||||
expectTypeOf<readonlyStringTuple>().toEqualTypeOf<readonly [string]>();
|
||||
expectTypeOf<deepReadonly>().toEqualTypeOf<{ readonly a: string }>();
|
||||
});
|
||||
|
||||
test("readonly parse", () => {
|
||||
const schema = z.array(z.string()).readonly();
|
||||
const readonlyArray = ["a", "b", "c"] as const;
|
||||
const mutableArray = ["a", "b", "c"];
|
||||
const result1 = schema.parse(readonlyArray);
|
||||
const result2 = schema.parse(mutableArray);
|
||||
expect(result1).toEqual(readonlyArray);
|
||||
expect(result2).toEqual(mutableArray);
|
||||
});
|
||||
|
||||
test("readonly parse with tuples", () => {
|
||||
const schema = z.tuple([z.string(), z.number()]).readonly();
|
||||
schema.parse(["a", 1]);
|
||||
});
|
||||
|
||||
test("readonly and the get method", () => {
|
||||
const readonlyString = z.string().readonly();
|
||||
const readonlyNumber1 = z.number().readonly();
|
||||
const readonlyNumber2 = z.number().readonly();
|
||||
const readonlyBigInt = z.bigint().readonly();
|
||||
const readonlyBoolean = z.boolean().readonly();
|
||||
const readonlyDate = z.date().readonly();
|
||||
const readonlyUndefined = z.undefined().readonly();
|
||||
const readonlyNull = z.null().readonly();
|
||||
const readonlyAny = z.any().readonly();
|
||||
const readonlyUnknown = z.unknown().readonly();
|
||||
const readonlyVoid = z.void().readonly();
|
||||
// const readonlyFunction = z.function(z.tuple([z.string(), z.number()]), z.unknown()).readonly();
|
||||
const readonlyStringArray = z.string().array().readonly();
|
||||
const readonlyTuple = z.tuple([z.string(), z.number()]).readonly();
|
||||
|
||||
expectTypeOf<z.infer<typeof readonlyString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof readonlyNumber1>>().toEqualTypeOf<number>();
|
||||
expectTypeOf<z.infer<typeof readonlyNumber2>>().toEqualTypeOf<number>();
|
||||
expectTypeOf<z.infer<typeof readonlyBigInt>>().toEqualTypeOf<bigint>();
|
||||
expectTypeOf<z.infer<typeof readonlyBoolean>>().toEqualTypeOf<boolean>();
|
||||
expectTypeOf<z.infer<typeof readonlyDate>>().toEqualTypeOf<Date>();
|
||||
expectTypeOf<z.infer<typeof readonlyUndefined>>().toEqualTypeOf<undefined>();
|
||||
expectTypeOf<z.infer<typeof readonlyNull>>().toEqualTypeOf<null>();
|
||||
expectTypeOf<z.infer<typeof readonlyAny>>().toEqualTypeOf<any>();
|
||||
expectTypeOf<z.infer<typeof readonlyUnknown>>().toEqualTypeOf<Readonly<unknown>>();
|
||||
expectTypeOf<z.infer<typeof readonlyVoid>>().toEqualTypeOf<void>();
|
||||
// expectTypeOf<z.infer<typeof readonlyFunction>>().toEqualTypeOf<
|
||||
// (args_0: string, args_1: number, ...args_2: unknown[]) => unknown
|
||||
// >();
|
||||
expectTypeOf<z.infer<typeof readonlyStringArray>>().toEqualTypeOf<readonly string[]>();
|
||||
expectTypeOf<z.infer<typeof readonlyTuple>>().toEqualTypeOf<readonly [string, number]>();
|
||||
|
||||
expect(readonlyString.parse("asdf")).toEqual("asdf");
|
||||
expect(readonlyNumber1.parse(1234)).toEqual(1234);
|
||||
expect(readonlyNumber2.parse(1234)).toEqual(1234);
|
||||
const bigIntVal = BigInt(1);
|
||||
expect(readonlyBigInt.parse(bigIntVal)).toEqual(bigIntVal);
|
||||
expect(readonlyBoolean.parse(true)).toEqual(true);
|
||||
const dateVal = new Date();
|
||||
expect(readonlyDate.parse(dateVal)).toEqual(dateVal);
|
||||
expect(readonlyUndefined.parse(undefined)).toEqual(undefined);
|
||||
expect(readonlyNull.parse(null)).toEqual(null);
|
||||
expect(readonlyAny.parse("whatever")).toEqual("whatever");
|
||||
expect(readonlyUnknown.parse("whatever")).toEqual("whatever");
|
||||
expect(readonlyVoid.parse(undefined)).toEqual(undefined);
|
||||
// expect(readonlyFunction.parse(() => void 0)).toEqual(() => void 0);
|
||||
expect(readonlyStringArray.parse(["asdf"])).toEqual(["asdf"]);
|
||||
expect(readonlyTuple.parse(["asdf", 1234])).toEqual(["asdf", 1234]);
|
||||
});
|
||||
632
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/record.test.ts
generated
vendored
Normal file
632
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/record.test.ts
generated
vendored
Normal file
@@ -0,0 +1,632 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("type inference", () => {
|
||||
const booleanRecord = z.record(z.string(), z.boolean());
|
||||
type booleanRecord = typeof booleanRecord._output;
|
||||
|
||||
const recordWithEnumKeys = z.record(z.enum(["Tuna", "Salmon"]), z.string());
|
||||
type recordWithEnumKeys = z.infer<typeof recordWithEnumKeys>;
|
||||
|
||||
const recordWithLiteralKey = z.record(z.literal(["Tuna", "Salmon", 21]), z.string());
|
||||
type recordWithLiteralKey = z.infer<typeof recordWithLiteralKey>;
|
||||
|
||||
const recordWithLiteralUnionKeys = z.record(
|
||||
z.union([z.literal("Tuna"), z.literal("Salmon"), z.literal(21)]),
|
||||
z.string()
|
||||
);
|
||||
type recordWithLiteralUnionKeys = z.infer<typeof recordWithLiteralUnionKeys>;
|
||||
|
||||
enum Enum {
|
||||
Tuna = 0,
|
||||
Salmon = "Shark",
|
||||
}
|
||||
|
||||
const recordWithTypescriptEnum = z.record(z.enum(Enum), z.string());
|
||||
type recordWithTypescriptEnum = z.infer<typeof recordWithTypescriptEnum>;
|
||||
|
||||
expectTypeOf<booleanRecord>().toEqualTypeOf<Record<string, boolean>>();
|
||||
expectTypeOf<recordWithEnumKeys>().toEqualTypeOf<Record<"Tuna" | "Salmon", string>>();
|
||||
expectTypeOf<recordWithLiteralKey>().toEqualTypeOf<Record<"Tuna" | "Salmon" | 21, string>>();
|
||||
expectTypeOf<recordWithLiteralUnionKeys>().toEqualTypeOf<Record<"Tuna" | "Salmon" | 21, string>>();
|
||||
expectTypeOf<recordWithTypescriptEnum>().toEqualTypeOf<Record<Enum, string>>();
|
||||
});
|
||||
|
||||
test("enum exhaustiveness", () => {
|
||||
const schema = z.record(z.enum(["Tuna", "Salmon"]), z.string());
|
||||
expect(
|
||||
schema.parse({
|
||||
Tuna: "asdf",
|
||||
Salmon: "asdf",
|
||||
})
|
||||
).toEqual({
|
||||
Tuna: "asdf",
|
||||
Salmon: "asdf",
|
||||
});
|
||||
|
||||
expect(schema.safeParse({ Tuna: "asdf", Salmon: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": [
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Unrecognized key: \\"Trout\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse({ Tuna: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"Salmon"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("typescript enum exhaustiveness", () => {
|
||||
enum BigFish {
|
||||
Tuna = 0,
|
||||
Salmon = "Shark",
|
||||
}
|
||||
|
||||
const schema = z.record(z.enum(BigFish), z.string());
|
||||
const value = {
|
||||
[BigFish.Tuna]: "asdf",
|
||||
[BigFish.Salmon]: "asdf",
|
||||
};
|
||||
|
||||
expect(schema.parse(value)).toEqual(value);
|
||||
|
||||
expect(schema.safeParse({ [BigFish.Tuna]: "asdf", [BigFish.Salmon]: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": [
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Unrecognized key: \\"Trout\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse({ [BigFish.Tuna]: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"Shark"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse({ [BigFish.Salmon]: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
0
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("literal exhaustiveness", () => {
|
||||
const schema = z.record(z.literal(["Tuna", "Salmon", 21]), z.string());
|
||||
schema.parse({
|
||||
Tuna: "asdf",
|
||||
Salmon: "asdf",
|
||||
21: "asdf",
|
||||
});
|
||||
|
||||
expect(schema.safeParse({ Tuna: "asdf", Salmon: "asdf", 21: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": [
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Unrecognized key: \\"Trout\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse({ Tuna: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"Salmon"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
21
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("pipe exhaustiveness", () => {
|
||||
const schema = z.record(z.enum(["Tuna", "Salmon"]).pipe(z.any()), z.string());
|
||||
expect(schema.parse({ Tuna: "asdf", Salmon: "asdf" })).toEqual({
|
||||
Tuna: "asdf",
|
||||
Salmon: "asdf",
|
||||
});
|
||||
|
||||
expect(schema.safeParse({ Tuna: "asdf", Salmon: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": [
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Unrecognized key: \\"Trout\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse({ Tuna: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"Salmon"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("union exhaustiveness", () => {
|
||||
const schema = z.record(z.union([z.literal("Tuna"), z.literal("Salmon"), z.literal(21)]), z.string());
|
||||
expect(schema.parse({ Tuna: "asdf", Salmon: "asdf", 21: "asdf" })).toEqual({
|
||||
Tuna: "asdf",
|
||||
Salmon: "asdf",
|
||||
21: "asdf",
|
||||
});
|
||||
|
||||
expect(schema.safeParse({ Tuna: "asdf", Salmon: "asdf", 21: "asdf", Trout: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "unrecognized_keys",
|
||||
"keys": [
|
||||
"Trout"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Unrecognized key: \\"Trout\\""
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse({ Tuna: "asdf" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"Salmon"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
21
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("string record parse - pass", () => {
|
||||
const schema = z.record(z.string(), z.boolean());
|
||||
schema.parse({
|
||||
k1: true,
|
||||
k2: false,
|
||||
1234: false,
|
||||
});
|
||||
|
||||
expect(schema.safeParse({ asdf: 1234 }).success).toEqual(false);
|
||||
expect(schema.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "record",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected record, received string"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("key and value getters", () => {
|
||||
const rec = z.record(z.string(), z.number());
|
||||
|
||||
rec.keyType.parse("asdf");
|
||||
rec.valueType.parse(1234);
|
||||
});
|
||||
|
||||
test("is not vulnerable to prototype pollution", async () => {
|
||||
const rec = z.record(
|
||||
z.string(),
|
||||
z.object({
|
||||
a: z.string(),
|
||||
})
|
||||
);
|
||||
|
||||
const data = JSON.parse(`
|
||||
{
|
||||
"__proto__": {
|
||||
"a": "evil"
|
||||
},
|
||||
"b": {
|
||||
"a": "good"
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
const obj1 = rec.parse(data);
|
||||
expect(obj1.a).toBeUndefined();
|
||||
|
||||
const obj2 = rec.safeParse(data);
|
||||
expect(obj2.success).toBe(true);
|
||||
if (obj2.success) {
|
||||
expect(obj2.data.a).toBeUndefined();
|
||||
}
|
||||
|
||||
const obj3 = await rec.parseAsync(data);
|
||||
expect(obj3.a).toBeUndefined();
|
||||
|
||||
const obj4 = await rec.safeParseAsync(data);
|
||||
expect(obj4.success).toBe(true);
|
||||
if (obj4.success) {
|
||||
expect(obj4.data.a).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
||||
test("dont remove undefined values", () => {
|
||||
const result1 = z.record(z.string(), z.any()).parse({ foo: undefined });
|
||||
|
||||
expect(result1).toEqual({
|
||||
foo: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
test("allow undefined values", () => {
|
||||
const schema = z.record(z.string(), z.undefined());
|
||||
|
||||
expect(
|
||||
Object.keys(
|
||||
schema.parse({
|
||||
_test: undefined,
|
||||
})
|
||||
)
|
||||
).toEqual(["_test"]);
|
||||
});
|
||||
|
||||
test("async parsing", async () => {
|
||||
const schema = z
|
||||
.record(
|
||||
z.string(),
|
||||
z
|
||||
.string()
|
||||
.optional()
|
||||
.refine(async () => true)
|
||||
)
|
||||
.refine(async () => true);
|
||||
|
||||
const data = {
|
||||
foo: "bar",
|
||||
baz: "qux",
|
||||
};
|
||||
const result = await schema.safeParseAsync(data);
|
||||
expect(result.data).toEqual(data);
|
||||
});
|
||||
|
||||
test("async parsing", async () => {
|
||||
const schema = z
|
||||
.record(
|
||||
z.string(),
|
||||
z
|
||||
.string()
|
||||
.optional()
|
||||
.refine(async () => false)
|
||||
)
|
||||
.refine(async () => false);
|
||||
|
||||
const data = {
|
||||
foo: "bar",
|
||||
baz: "qux",
|
||||
};
|
||||
const result = await schema.safeParseAsync(data);
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"foo"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"baz"
|
||||
],
|
||||
"message": "Invalid input"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("partial record", () => {
|
||||
const schema = z.partialRecord(z.string(), z.string());
|
||||
type schema = z.infer<typeof schema>;
|
||||
expectTypeOf<schema>().toEqualTypeOf<Partial<Record<string, string>>>();
|
||||
|
||||
const Keys = z.enum(["id", "name", "email"]); //.or(z.never());
|
||||
const Person = z.partialRecord(Keys, z.string());
|
||||
expectTypeOf<z.infer<typeof Person>>().toEqualTypeOf<Partial<Record<"id" | "name" | "email", string>>>();
|
||||
|
||||
Person.parse({
|
||||
id: "123",
|
||||
// name: "John",
|
||||
// email: "john@example.com",
|
||||
});
|
||||
|
||||
Person.parse({
|
||||
// id: "123",
|
||||
// name: "John",
|
||||
email: "john@example.com",
|
||||
});
|
||||
|
||||
expect(Person.def.keyType._zod.def.type).toEqual("enum");
|
||||
});
|
||||
|
||||
test("partialRecord with z.literal([key, ...])", () => {
|
||||
const Keys = z.literal(["id", "name", "email"]);
|
||||
const schema = z.partialRecord(Keys, z.string());
|
||||
type Schema = z.infer<typeof schema>;
|
||||
expectTypeOf<Schema>().toEqualTypeOf<Partial<Record<"id" | "name" | "email", string>>>();
|
||||
|
||||
// Should parse valid partials
|
||||
expect(schema.parse({})).toEqual({});
|
||||
expect(schema.parse({ id: "1" })).toEqual({ id: "1" });
|
||||
expect(schema.parse({ name: "n", email: "e@example.com" })).toEqual({ name: "n", email: "e@example.com" });
|
||||
|
||||
// Should fail with unrecognized key, error checked via inline snapshot
|
||||
expect(schema.safeParse({ foo: "bar" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_key",
|
||||
"origin": "record",
|
||||
"issues": [
|
||||
{
|
||||
"code": "invalid_value",
|
||||
"values": [
|
||||
"id",
|
||||
"name",
|
||||
"email"
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid option: expected one of \\"id\\"|\\"name\\"|\\"email\\""
|
||||
}
|
||||
],
|
||||
"path": [
|
||||
"foo"
|
||||
],
|
||||
"message": "Invalid key in record"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("partialRecord with numeric literal keys", () => {
|
||||
const Keys = z.literal([1, 2, 3]);
|
||||
const schema = z.partialRecord(Keys, z.string());
|
||||
type Schema = z.infer<typeof schema>;
|
||||
expectTypeOf<Schema>().toEqualTypeOf<Partial<Record<1 | 2 | 3, string>>>();
|
||||
|
||||
// Should parse valid partials with numeric keys (as strings in JS objects)
|
||||
expect(schema.parse({})).toEqual({});
|
||||
expect(schema.parse({ 1: "one" })).toEqual({ 1: "one" });
|
||||
expect(schema.parse({ 2: "two", 3: "three" })).toEqual({ 2: "two", 3: "three" });
|
||||
|
||||
// Should fail with unrecognized key
|
||||
expect(schema.safeParse({ 4: "four" }).success).toBe(false);
|
||||
});
|
||||
|
||||
test("partialRecord with union of string and numeric literal keys", () => {
|
||||
const StringKeys = z.literal(["a", "b", "c"]);
|
||||
const NumericKeys = z.literal([1, 2, 3]);
|
||||
const schema = z.partialRecord(z.union([StringKeys, NumericKeys]), z.string());
|
||||
type Schema = z.infer<typeof schema>;
|
||||
expectTypeOf<Schema>().toEqualTypeOf<Partial<Record<"a" | "b" | "c" | 1 | 2 | 3, string>>>();
|
||||
|
||||
// Should parse valid partials with mixed keys
|
||||
expect(schema.parse({})).toEqual({});
|
||||
expect(schema.parse({ a: "1", 2: "4" })).toEqual({ a: "1", 2: "4" });
|
||||
expect(schema.parse({ a: "a", b: "b", 1: "1", 2: "2" })).toEqual({ a: "a", b: "b", 1: "1", 2: "2" });
|
||||
|
||||
// Should fail with unrecognized key
|
||||
expect(schema.safeParse({ d: "d" }).success).toBe(false);
|
||||
expect(schema.safeParse({ 4: "4" }).success).toBe(false);
|
||||
});
|
||||
|
||||
test("looseRecord passes through non-matching keys", () => {
|
||||
const schema = z.looseRecord(z.string().regex(/^S_/), z.string());
|
||||
|
||||
// Keys matching pattern are validated
|
||||
expect(schema.parse({ S_name: "John" })).toEqual({ S_name: "John" });
|
||||
expect(() => schema.parse({ S_name: 123 })).toThrow(); // wrong value type
|
||||
|
||||
// Keys not matching pattern pass through unchanged
|
||||
expect(schema.parse({ S_name: "John", other: "value" })).toEqual({ S_name: "John", other: "value" });
|
||||
expect(schema.parse({ S_name: "John", count: 123 })).toEqual({ S_name: "John", count: 123 });
|
||||
expect(schema.parse({ other: "value" })).toEqual({ other: "value" });
|
||||
});
|
||||
|
||||
test("intersection of loose records", () => {
|
||||
const schema = z.intersection(
|
||||
z.object({ name: z.string() }).passthrough(),
|
||||
z.intersection(
|
||||
z.looseRecord(z.string().regex(/^S_/), z.string()),
|
||||
z.looseRecord(z.string().regex(/^N_/), z.number())
|
||||
)
|
||||
);
|
||||
|
||||
// Each pattern validates its matching keys
|
||||
const result = schema.parse({ name: "John", S_foo: "bar", N_count: 123 });
|
||||
expect(result.name).toBe("John");
|
||||
expect(result.S_foo).toBe("bar");
|
||||
expect(result.N_count).toBe(123);
|
||||
|
||||
// Keys not matching any pattern pass through
|
||||
const result2 = schema.parse({ name: "John", S_foo: "bar", N_count: 123, other: "value" });
|
||||
expect(result2.other).toBe("value");
|
||||
|
||||
// Validation errors still occur for matching keys
|
||||
expect(() => schema.parse({ name: "John", S_foo: 123 })).toThrow(); // S_foo should be string
|
||||
expect(() => schema.parse({ name: "John", N_count: "abc" })).toThrow(); // N_count should be number
|
||||
});
|
||||
|
||||
test("object with looseRecord index signature", () => {
|
||||
// Simulates TypeScript index signature: { label: string; [key: `label:${string}`]: string }
|
||||
const schema = z.object({ label: z.string() }).and(z.looseRecord(z.string().regex(/^label:[a-z]{2}$/), z.string()));
|
||||
|
||||
type Schema = z.infer<typeof schema>;
|
||||
expectTypeOf<Schema>().toEqualTypeOf<{ label: string } & Record<string, string>>();
|
||||
|
||||
// Valid: has required property and matching pattern keys
|
||||
expect(schema.parse({ label: "Purple", "label:en": "Purple", "label:ru": "Пурпурный" })).toEqual({
|
||||
label: "Purple",
|
||||
"label:en": "Purple",
|
||||
"label:ru": "Пурпурный",
|
||||
});
|
||||
|
||||
// Valid: just required property
|
||||
expect(schema.parse({ label: "Purple" })).toEqual({ label: "Purple" });
|
||||
|
||||
// Invalid: missing required property
|
||||
expect(schema.safeParse({ "label:en": "Purple" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"label"
|
||||
],
|
||||
"message": "Invalid input: expected string, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
// Invalid: pattern key with wrong value type
|
||||
expect(schema.safeParse({ label: "Purple", "label:en": 123 })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"label:en"
|
||||
],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("numeric string keys", () => {
|
||||
const schema = z.record(z.number(), z.number());
|
||||
|
||||
// Numeric string keys work
|
||||
expect(schema.parse({ 1: 100, 2: 200 })).toEqual({ 1: 100, 2: 200 });
|
||||
expect(schema.parse({ "1.5": 100, "-3": 200 })).toEqual({ "1.5": 100, "-3": 200 });
|
||||
|
||||
// Non-numeric keys fail
|
||||
expect(schema.safeParse({ abc: 100 }).success).toBe(false);
|
||||
|
||||
// Integer constraint is respected
|
||||
const intSchema = z.record(z.number().int(), z.number());
|
||||
expect(intSchema.parse({ 1: 100 })).toEqual({ 1: 100 });
|
||||
expect(intSchema.safeParse({ "1.5": 100 }).success).toBe(false);
|
||||
|
||||
// Transforms on numeric keys work
|
||||
const transformedSchema = z.record(
|
||||
z.number().overwrite((n) => n * 2),
|
||||
z.string()
|
||||
);
|
||||
expect(transformedSchema.parse({ 5: "five", 10: "ten" })).toEqual({ 10: "five", 20: "ten" });
|
||||
});
|
||||
582
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts
generated
vendored
Normal file
582
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/recursive-types.test.ts
generated
vendored
Normal file
@@ -0,0 +1,582 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
test("recursion with z.lazy", () => {
|
||||
const data = {
|
||||
name: "I",
|
||||
subcategories: [
|
||||
{
|
||||
name: "A",
|
||||
subcategories: [
|
||||
{
|
||||
name: "1",
|
||||
subcategories: [
|
||||
{
|
||||
name: "a",
|
||||
subcategories: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const Category = z.object({
|
||||
name: z.string(),
|
||||
get subcategories() {
|
||||
return z.array(Category).optional().nullable();
|
||||
},
|
||||
});
|
||||
type Category = z.infer<typeof Category>;
|
||||
interface _Category {
|
||||
name: string;
|
||||
subcategories?: _Category[] | undefined | null;
|
||||
}
|
||||
expectTypeOf<Category>().toEqualTypeOf<_Category>();
|
||||
Category.parse(data);
|
||||
});
|
||||
|
||||
test("recursion involving union type", () => {
|
||||
const data = {
|
||||
value: 1,
|
||||
next: {
|
||||
value: 2,
|
||||
next: {
|
||||
value: 3,
|
||||
next: {
|
||||
value: 4,
|
||||
next: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const LL = z.object({
|
||||
value: z.number(),
|
||||
get next() {
|
||||
return LL.nullable();
|
||||
},
|
||||
});
|
||||
type LL = z.infer<typeof LL>;
|
||||
type _LL = {
|
||||
value: number;
|
||||
next: _LL | null;
|
||||
};
|
||||
expectTypeOf<LL>().toEqualTypeOf<_LL>();
|
||||
|
||||
LL.parse(data);
|
||||
});
|
||||
|
||||
test("mutual recursion - native", () => {
|
||||
const Alazy = z.object({
|
||||
val: z.number(),
|
||||
get b() {
|
||||
return Blazy;
|
||||
},
|
||||
});
|
||||
|
||||
const Blazy = z.object({
|
||||
val: z.number(),
|
||||
get a() {
|
||||
return Alazy.optional();
|
||||
},
|
||||
});
|
||||
const testData = {
|
||||
val: 1,
|
||||
b: {
|
||||
val: 5,
|
||||
a: {
|
||||
val: 3,
|
||||
b: {
|
||||
val: 4,
|
||||
a: {
|
||||
val: 2,
|
||||
b: {
|
||||
val: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
type Alazy = z.infer<typeof Alazy>;
|
||||
type Blazy = z.infer<typeof Blazy>;
|
||||
interface _Alazy {
|
||||
val: number;
|
||||
b: _Blazy;
|
||||
}
|
||||
interface _Blazy {
|
||||
val: number;
|
||||
a?: _Alazy | undefined;
|
||||
}
|
||||
expectTypeOf<Alazy>().toEqualTypeOf<_Alazy>();
|
||||
expectTypeOf<Blazy>().toEqualTypeOf<_Blazy>();
|
||||
Alazy.parse(testData);
|
||||
Blazy.parse(testData.b);
|
||||
|
||||
expect(() => Alazy.parse({ val: "asdf" })).toThrow();
|
||||
});
|
||||
|
||||
test("pick and omit with getter", () => {
|
||||
const Category = z.strictObject({
|
||||
name: z.string(),
|
||||
get subcategories() {
|
||||
return z.array(Category);
|
||||
},
|
||||
});
|
||||
|
||||
type Category = z.infer<typeof Category>;
|
||||
|
||||
interface _Category {
|
||||
name: string;
|
||||
subcategories: _Category[];
|
||||
}
|
||||
expectTypeOf<Category>().toEqualTypeOf<_Category>();
|
||||
|
||||
const PickedCategory = Category.pick({ name: true });
|
||||
const OmittedCategory = Category.omit({ subcategories: true });
|
||||
|
||||
const picked = { name: "test" };
|
||||
const omitted = { name: "test" };
|
||||
|
||||
PickedCategory.parse(picked);
|
||||
OmittedCategory.parse(omitted);
|
||||
|
||||
expect(() => PickedCategory.parse({ name: "test", subcategories: [] })).toThrow();
|
||||
expect(() => OmittedCategory.parse({ name: "test", subcategories: [] })).toThrow();
|
||||
});
|
||||
|
||||
test("deferred self-recursion", () => {
|
||||
const Feature = z.object({
|
||||
title: z.string(),
|
||||
get features(): z.ZodOptional<z.ZodArray<typeof Feature>> {
|
||||
return z.optional(z.array(Feature)); //.optional();
|
||||
},
|
||||
});
|
||||
// type Feature = z.infer<typeof Feature>;
|
||||
|
||||
const Output = z.object({
|
||||
id: z.int(), //.nonnegative(),
|
||||
name: z.string(),
|
||||
get features(): z.ZodArray<typeof Feature> {
|
||||
return Feature.array();
|
||||
},
|
||||
});
|
||||
type Output = z.output<typeof Output>;
|
||||
|
||||
type _Feature = {
|
||||
title: string;
|
||||
features?: _Feature[] | undefined;
|
||||
};
|
||||
|
||||
type _Output = {
|
||||
id: number;
|
||||
name: string;
|
||||
features: _Feature[];
|
||||
};
|
||||
|
||||
// expectTypeOf<Feature>().toEqualTypeOf<_Feature>();
|
||||
expectTypeOf<Output>().toEqualTypeOf<_Output>();
|
||||
});
|
||||
|
||||
test("deferred mutual recursion", () => {
|
||||
const Slot = z.object({
|
||||
slotCode: z.string(),
|
||||
|
||||
get blocks() {
|
||||
return z.array(Block);
|
||||
},
|
||||
});
|
||||
type Slot = z.infer<typeof Slot>;
|
||||
|
||||
const Block = z.object({
|
||||
blockCode: z.string(),
|
||||
get slots() {
|
||||
return z.array(Slot).optional();
|
||||
},
|
||||
});
|
||||
type Block = z.infer<typeof Block>;
|
||||
|
||||
const Page = z.object({
|
||||
slots: z.array(Slot),
|
||||
});
|
||||
type Page = z.infer<typeof Page>;
|
||||
|
||||
type _Slot = {
|
||||
slotCode: string;
|
||||
blocks: _Block[];
|
||||
};
|
||||
type _Block = {
|
||||
blockCode: string;
|
||||
slots?: _Slot[] | undefined;
|
||||
};
|
||||
type _Page = {
|
||||
slots: _Slot[];
|
||||
};
|
||||
expectTypeOf<Slot>().toEqualTypeOf<_Slot>();
|
||||
expectTypeOf<Block>().toEqualTypeOf<_Block>();
|
||||
expectTypeOf<Page>().toEqualTypeOf<_Page>();
|
||||
});
|
||||
|
||||
test("mutual recursion with meta", () => {
|
||||
const A = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
get b() {
|
||||
return B;
|
||||
},
|
||||
})
|
||||
.readonly()
|
||||
.meta({ id: "A" })
|
||||
.optional();
|
||||
|
||||
const B = z
|
||||
.object({
|
||||
name: z.string(),
|
||||
get a() {
|
||||
return A;
|
||||
},
|
||||
})
|
||||
.readonly()
|
||||
.meta({ id: "B" });
|
||||
|
||||
type A = z.infer<typeof A>;
|
||||
type B = z.infer<typeof B>;
|
||||
|
||||
type _A =
|
||||
| Readonly<{
|
||||
name: string;
|
||||
b: _B;
|
||||
}>
|
||||
| undefined;
|
||||
// | undefined;
|
||||
type _B = Readonly<{
|
||||
name: string;
|
||||
a?: _A;
|
||||
}>;
|
||||
expectTypeOf<A>().toEqualTypeOf<_A>();
|
||||
expectTypeOf<B>().toEqualTypeOf<_B>();
|
||||
});
|
||||
|
||||
test("intersection with recursive types", () => {
|
||||
const A = z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal("CONTAINER"),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("SCREEN"),
|
||||
config: z.object({ x: z.number(), y: z.number() }),
|
||||
}),
|
||||
]);
|
||||
// type A = z.infer<typeof A>;
|
||||
|
||||
const B = z.object({
|
||||
get children() {
|
||||
return z.array(C).optional();
|
||||
},
|
||||
});
|
||||
// type B = z.infer<typeof B>;
|
||||
|
||||
const C = z.intersection(A, B);
|
||||
type C = z.infer<typeof C>;
|
||||
|
||||
type _C = (
|
||||
| {
|
||||
type: "CONTAINER";
|
||||
}
|
||||
| {
|
||||
type: "SCREEN";
|
||||
config: {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
}
|
||||
) & {
|
||||
children?: _C[] | undefined;
|
||||
};
|
||||
expectTypeOf<C>().toEqualTypeOf<_C>();
|
||||
});
|
||||
|
||||
test("object utilities with recursive types", () => {
|
||||
const NodeBase = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
get children() {
|
||||
return z.array(Node).optional();
|
||||
},
|
||||
});
|
||||
|
||||
// Test extend with new keys (extend throws when overwriting existing keys)
|
||||
const NodeOne = NodeBase.extend({
|
||||
name: z.literal("nodeOne"),
|
||||
get children() {
|
||||
return z.array(Node);
|
||||
},
|
||||
});
|
||||
|
||||
const NodeTwo = NodeBase.extend({
|
||||
name: z.literal("nodeTwo"),
|
||||
get children() {
|
||||
return z.array(Node);
|
||||
},
|
||||
});
|
||||
|
||||
// Test pick
|
||||
const PickedNode = NodeBase.pick({ id: true, name: true });
|
||||
|
||||
// Test omit
|
||||
const OmittedNode = NodeBase.omit({ children: true });
|
||||
|
||||
// Test merge
|
||||
const ExtraProps = {
|
||||
metadata: z.string(),
|
||||
get parent() {
|
||||
return Node.optional();
|
||||
},
|
||||
};
|
||||
const MergedNode = NodeBase.extend(ExtraProps);
|
||||
|
||||
// Test partial
|
||||
const PartialNode = NodeBase.partial();
|
||||
const PartialMaskedNode = NodeBase.partial({ name: true });
|
||||
|
||||
// Test required (assuming NodeBase has optional fields)
|
||||
const OptionalNodeBase = z.object({
|
||||
id: z.string().optional(),
|
||||
name: z.string().optional(),
|
||||
get children() {
|
||||
return z.array(Node).optional();
|
||||
},
|
||||
});
|
||||
const RequiredNode = OptionalNodeBase.required();
|
||||
const RequiredMaskedNode = OptionalNodeBase.required({ id: true });
|
||||
|
||||
const Node = z.union([
|
||||
NodeOne,
|
||||
NodeTwo,
|
||||
PickedNode,
|
||||
OmittedNode,
|
||||
MergedNode,
|
||||
PartialNode,
|
||||
PartialMaskedNode,
|
||||
RequiredNode,
|
||||
RequiredMaskedNode,
|
||||
]);
|
||||
});
|
||||
|
||||
test("tuple with recursive types", () => {
|
||||
const TaskListNodeSchema = z.strictObject({
|
||||
type: z.literal("taskList"),
|
||||
get content() {
|
||||
return z.array(z.tuple([TaskListNodeSchema, z.union([TaskListNodeSchema])])).min(1);
|
||||
},
|
||||
});
|
||||
type TaskListNodeSchema = z.infer<typeof TaskListNodeSchema>;
|
||||
type _TaskListNodeSchema = {
|
||||
type: "taskList";
|
||||
content: [_TaskListNodeSchema, _TaskListNodeSchema][];
|
||||
};
|
||||
expectTypeOf<TaskListNodeSchema>().toEqualTypeOf<_TaskListNodeSchema>();
|
||||
});
|
||||
|
||||
test("recursion compatibility", () => {
|
||||
// array
|
||||
const A = z.object({
|
||||
get array() {
|
||||
return A.array();
|
||||
},
|
||||
get optional() {
|
||||
return A.optional();
|
||||
},
|
||||
get nullable() {
|
||||
return A.nullable();
|
||||
},
|
||||
get nonoptional() {
|
||||
return A.nonoptional();
|
||||
},
|
||||
get readonly() {
|
||||
return A.readonly();
|
||||
},
|
||||
get describe() {
|
||||
return A.describe("A recursive type");
|
||||
},
|
||||
get meta() {
|
||||
return A.meta({ description: "A recursive type" });
|
||||
},
|
||||
get pipe() {
|
||||
return A.pipe(z.any());
|
||||
},
|
||||
get strict() {
|
||||
return A.strict();
|
||||
},
|
||||
get tuple() {
|
||||
return z.tuple([A, A]);
|
||||
},
|
||||
get object() {
|
||||
return z
|
||||
.object({
|
||||
subcategories: A,
|
||||
})
|
||||
.strict()
|
||||
.loose();
|
||||
},
|
||||
get union() {
|
||||
return z.union([A, A]);
|
||||
},
|
||||
get intersection() {
|
||||
return z.intersection(A, A);
|
||||
},
|
||||
get record() {
|
||||
return z.record(z.string(), A);
|
||||
},
|
||||
get map() {
|
||||
return z.map(z.string(), A);
|
||||
},
|
||||
get set() {
|
||||
return z.set(A);
|
||||
},
|
||||
get lazy() {
|
||||
return z.lazy(() => A);
|
||||
},
|
||||
get promise() {
|
||||
return z.promise(A);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("recursive object with .check()", () => {
|
||||
const Category = z
|
||||
.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
get subcategories() {
|
||||
return z.array(Category).optional();
|
||||
},
|
||||
})
|
||||
.check((ctx) => {
|
||||
// Check for duplicate IDs among direct subcategories
|
||||
if (ctx.value.subcategories) {
|
||||
const siblingIds = new Set<string>();
|
||||
ctx.value.subcategories.forEach((sub, index) => {
|
||||
if (siblingIds.has(sub.id)) {
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
message: `Duplicate sibling ID found: ${sub.id}`,
|
||||
path: ["subcategories", index, "id"],
|
||||
input: ctx.value,
|
||||
});
|
||||
}
|
||||
siblingIds.add(sub.id);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Valid - siblings have unique IDs
|
||||
const validData = {
|
||||
id: "electronics",
|
||||
name: "Electronics",
|
||||
subcategories: [
|
||||
{
|
||||
id: "computers",
|
||||
name: "Computers",
|
||||
subcategories: [
|
||||
{ id: "laptops", name: "Laptops" },
|
||||
{ id: "desktops", name: "Desktops" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "phones",
|
||||
name: "Phones",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Invalid - duplicate sibling IDs
|
||||
const invalidData = {
|
||||
id: "electronics",
|
||||
name: "Electronics",
|
||||
subcategories: [
|
||||
{ id: "computers", name: "Computers" },
|
||||
{ id: "phones", name: "Phones" },
|
||||
{ id: "computers", name: "Computers Again" }, // Duplicate at index 2
|
||||
],
|
||||
};
|
||||
|
||||
expect(() => Category.parse(validData)).not.toThrow();
|
||||
expect(() => Category.parse(invalidData)).toThrow();
|
||||
});
|
||||
|
||||
// biome-ignore lint: sadf
|
||||
export type RecursiveA = z.ZodUnion<
|
||||
[
|
||||
z.ZodObject<{
|
||||
a: z.ZodDefault<RecursiveA>;
|
||||
b: z.ZodPrefault<RecursiveA>;
|
||||
c: z.ZodNonOptional<RecursiveA>;
|
||||
d: z.ZodOptional<RecursiveA>;
|
||||
e: z.ZodNullable<RecursiveA>;
|
||||
g: z.ZodReadonly<RecursiveA>;
|
||||
h: z.ZodPipe<RecursiveA, z.ZodString>;
|
||||
i: z.ZodArray<RecursiveA>;
|
||||
j: z.ZodSet<RecursiveA>;
|
||||
k: z.ZodMap<RecursiveA, RecursiveA>;
|
||||
l: z.ZodRecord<z.ZodString, RecursiveA>;
|
||||
m: z.ZodUnion<[RecursiveA, RecursiveA]>;
|
||||
n: z.ZodIntersection<RecursiveA, RecursiveA>;
|
||||
o: z.ZodLazy<RecursiveA>;
|
||||
p: z.ZodPromise<RecursiveA>;
|
||||
q: z.ZodCatch<RecursiveA>;
|
||||
r: z.ZodSuccess<RecursiveA>;
|
||||
s: z.ZodTransform<RecursiveA, string>;
|
||||
t: z.ZodTuple<[RecursiveA, RecursiveA]>;
|
||||
u: z.ZodObject<{
|
||||
a: RecursiveA;
|
||||
}>;
|
||||
}>,
|
||||
]
|
||||
>;
|
||||
|
||||
test("recursive type with `id` meta", () => {
|
||||
const AType = z.object({
|
||||
type: z.literal("a"),
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const BType = z.object({
|
||||
type: z.literal("b"),
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const CType = z.object({
|
||||
type: z.literal("c"),
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const Schema = z.object({
|
||||
type: z.literal("special").meta({ description: "Type" }),
|
||||
config: z.object({
|
||||
title: z.string().meta({ description: "Title" }),
|
||||
get elements() {
|
||||
return z.array(z.discriminatedUnion("type", [AType, BType, CType])).meta({
|
||||
id: "SpecialElements",
|
||||
title: "SpecialElements",
|
||||
description: "Array of elements",
|
||||
});
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
Schema.parse({
|
||||
type: "special",
|
||||
config: {
|
||||
title: "Special",
|
||||
elements: [
|
||||
{ type: "a", name: "John" },
|
||||
{ type: "b", name: "Jane" },
|
||||
{ type: "c", name: "Jim" },
|
||||
],
|
||||
},
|
||||
});
|
||||
});
|
||||
570
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/refine.test.ts
generated
vendored
Normal file
570
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/refine.test.ts
generated
vendored
Normal file
@@ -0,0 +1,570 @@
|
||||
import { describe, expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
describe("basic refinement functionality", () => {
|
||||
test("should create a new schema instance when refining", () => {
|
||||
const obj1 = z.object({
|
||||
first: z.string(),
|
||||
second: z.string(),
|
||||
});
|
||||
const obj2 = obj1.partial().strict();
|
||||
const obj3 = obj2.refine((data) => data.first || data.second, "Either first or second should be filled in.");
|
||||
|
||||
expect(obj1 === (obj2 as any)).toEqual(false);
|
||||
expect(obj2 === (obj3 as any)).toEqual(false);
|
||||
});
|
||||
|
||||
test("should validate according to refinement logic", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
first: z.string(),
|
||||
second: z.string(),
|
||||
})
|
||||
.partial()
|
||||
.strict()
|
||||
.refine((data) => data.first || data.second, "Either first or second should be filled in.");
|
||||
|
||||
// Should fail on empty object
|
||||
expect(() => schema.parse({})).toThrow();
|
||||
|
||||
// Should pass with first property
|
||||
expect(schema.parse({ first: "a" })).toEqual({ first: "a" });
|
||||
|
||||
// Should pass with second property
|
||||
expect(schema.parse({ second: "a" })).toEqual({ second: "a" });
|
||||
|
||||
// Should pass with both properties
|
||||
expect(schema.parse({ first: "a", second: "a" })).toEqual({ first: "a", second: "a" });
|
||||
});
|
||||
|
||||
test("should validate strict mode correctly", () => {
|
||||
const schema = z
|
||||
.object({
|
||||
first: z.string(),
|
||||
second: z.string(),
|
||||
})
|
||||
.partial()
|
||||
.strict();
|
||||
|
||||
// Should throw on extra properties
|
||||
expect(() => schema.parse({ third: "adsf" })).toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("refinement with custom error messages", () => {
|
||||
test("should use custom error message when validation fails", () => {
|
||||
const validationSchema = z
|
||||
.object({
|
||||
email: z.string().email(),
|
||||
password: z.string(),
|
||||
confirmPassword: z.string(),
|
||||
})
|
||||
.refine((data) => data.password === data.confirmPassword, "Both password and confirmation must match");
|
||||
|
||||
const result = validationSchema.safeParse({
|
||||
email: "aaaa@gmail.com",
|
||||
password: "aaaaaaaa",
|
||||
confirmPassword: "bbbbbbbb",
|
||||
});
|
||||
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues[0].message).toEqual("Both password and confirmation must match");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("async refinements", () => {
|
||||
test("should support async refinement functions", async () => {
|
||||
const validationSchema = z
|
||||
.object({
|
||||
email: z.string().email(),
|
||||
password: z.string(),
|
||||
confirmPassword: z.string(),
|
||||
})
|
||||
.refine(
|
||||
(data) => Promise.resolve().then(() => data.password === data.confirmPassword),
|
||||
"Both password and confirmation must match"
|
||||
);
|
||||
|
||||
// Should pass with matching passwords
|
||||
const validData = {
|
||||
email: "aaaa@gmail.com",
|
||||
password: "password",
|
||||
confirmPassword: "password",
|
||||
};
|
||||
|
||||
await expect(validationSchema.parseAsync(validData)).resolves.toEqual(validData);
|
||||
|
||||
// Should fail with non-matching passwords
|
||||
await expect(
|
||||
validationSchema.parseAsync({
|
||||
email: "aaaa@gmail.com",
|
||||
password: "password",
|
||||
confirmPassword: "different",
|
||||
})
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("early termination options", () => {
|
||||
test("should abort early with continue: false", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.superRefine((val, ctx) => {
|
||||
if (val.length < 2) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: "BAD",
|
||||
continue: false,
|
||||
});
|
||||
}
|
||||
})
|
||||
.refine((_) => false);
|
||||
|
||||
const result = schema.safeParse("");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(1);
|
||||
expect(result.error.issues[0].message).toEqual("BAD");
|
||||
}
|
||||
});
|
||||
|
||||
test("should abort early with fatal: true", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.superRefine((val, ctx) => {
|
||||
if (val.length < 2) {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
fatal: true,
|
||||
message: "BAD",
|
||||
});
|
||||
}
|
||||
})
|
||||
.refine((_) => false);
|
||||
|
||||
const result = schema.safeParse("");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(1);
|
||||
expect(result.error.issues[0].message).toEqual("BAD");
|
||||
}
|
||||
});
|
||||
|
||||
test("should abort early with abort flag", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.refine((_) => false, { abort: true })
|
||||
.refine((_) => false);
|
||||
|
||||
const result = schema.safeParse("");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("custom error paths", () => {
|
||||
test("should use custom path in error message", () => {
|
||||
const result = z
|
||||
.object({ password: z.string(), confirm: z.string() })
|
||||
.refine((data) => data.confirm === data.password, { path: ["confirm"] })
|
||||
.safeParse({ password: "asdf", confirm: "qewr" });
|
||||
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues[0].path).toEqual(["confirm"]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("superRefine functionality", () => {
|
||||
test("should support multiple validation rules", () => {
|
||||
const Strings = z.array(z.string()).superRefine((val, ctx) => {
|
||||
if (val.length > 3) {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: "too_big",
|
||||
origin: "array",
|
||||
maximum: 3,
|
||||
inclusive: true,
|
||||
exact: true,
|
||||
message: "Too many items 😡",
|
||||
});
|
||||
}
|
||||
|
||||
if (val.length !== new Set(val).size) {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: "custom",
|
||||
message: `No duplicates allowed.`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Should fail with too many items and duplicates
|
||||
const result = Strings.safeParse(["asfd", "asfd", "asfd", "asfd"]);
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(2);
|
||||
expect(result.error.issues[0].message).toEqual("Too many items 😡");
|
||||
expect(result.error.issues[1].message).toEqual("No duplicates allowed.");
|
||||
}
|
||||
|
||||
// Should pass with valid input
|
||||
const validArray = ["asfd", "qwer"];
|
||||
expect(Strings.parse(validArray)).toEqual(validArray);
|
||||
});
|
||||
|
||||
test("should support async superRefine", async () => {
|
||||
const Strings = z.array(z.string()).superRefine(async (val, ctx) => {
|
||||
if (val.length > 3) {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: "too_big",
|
||||
origin: "array",
|
||||
maximum: 3,
|
||||
inclusive: true,
|
||||
message: "Too many items 😡",
|
||||
});
|
||||
}
|
||||
|
||||
if (val.length !== new Set(val).size) {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: "custom",
|
||||
message: `No duplicates allowed.`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Should fail with too many items and duplicates
|
||||
const result = await Strings.safeParseAsync(["asfd", "asfd", "asfd", "asfd"]);
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(2);
|
||||
}
|
||||
|
||||
// Should pass with valid input
|
||||
const validArray = ["asfd", "qwer"];
|
||||
await expect(Strings.parseAsync(validArray)).resolves.toEqual(validArray);
|
||||
});
|
||||
|
||||
test("should test continuability of custom issues", () => {
|
||||
// Default continue behavior - allows subsequent refinements
|
||||
const defaultContinue = z
|
||||
.string()
|
||||
.superRefine((_, ctx) => {
|
||||
ctx.addIssue({ code: "custom", message: "First issue" });
|
||||
})
|
||||
.refine(() => false, "Second issue");
|
||||
|
||||
expect(defaultContinue.safeParse("test")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "First issue",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Second issue"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
// Explicit continue: false - prevents subsequent refinements
|
||||
const explicitContinueFalse = z
|
||||
.string()
|
||||
.superRefine((_, ctx) => {
|
||||
ctx.addIssue({ code: "custom", message: "First issue", continue: false });
|
||||
})
|
||||
.refine(() => false, "Second issue");
|
||||
|
||||
expect(explicitContinueFalse.safeParse("test")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "First issue",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
// Multiple issues in same refinement - both always added regardless of continue
|
||||
const multipleInSame = z.string().superRefine((_, ctx) => {
|
||||
ctx.addIssue({ code: "custom", message: "First", continue: false });
|
||||
ctx.addIssue({ code: "custom", message: "Second" });
|
||||
});
|
||||
|
||||
expect(multipleInSame.safeParse("test")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "First",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "Second",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("should accept string as shorthand for custom error message", () => {
|
||||
const schema = z.string().superRefine((_, ctx) => {
|
||||
ctx.addIssue("bad stuff");
|
||||
});
|
||||
|
||||
const result = schema.safeParse("asdf");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues).toHaveLength(1);
|
||||
expect(result.error.issues[0].message).toEqual("bad stuff");
|
||||
}
|
||||
});
|
||||
|
||||
test("should respect fatal flag in superRefine", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.superRefine((val, ctx) => {
|
||||
if (val === "") {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: "custom",
|
||||
message: "foo",
|
||||
fatal: true,
|
||||
});
|
||||
}
|
||||
})
|
||||
.superRefine((val, ctx) => {
|
||||
if (val !== " ") {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: "custom",
|
||||
message: "bar",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const result = schema.safeParse("");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues.length).toEqual(1);
|
||||
expect(result.error.issues[0].message).toEqual("foo");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("chained refinements", () => {
|
||||
test("should collect all validation errors when appropriate", () => {
|
||||
const objectSchema = z
|
||||
.object({
|
||||
length: z.number(),
|
||||
size: z.number(),
|
||||
})
|
||||
.refine(({ length }) => length > 5, {
|
||||
path: ["length"],
|
||||
message: "length greater than 5",
|
||||
})
|
||||
.refine(({ size }) => size > 7, {
|
||||
path: ["size"],
|
||||
message: "size greater than 7",
|
||||
});
|
||||
|
||||
// Should fail with one error
|
||||
const r1 = objectSchema.safeParse({
|
||||
length: 4,
|
||||
size: 9,
|
||||
});
|
||||
expect(r1.success).toEqual(false);
|
||||
if (!r1.success) {
|
||||
expect(r1.error.issues.length).toEqual(1);
|
||||
expect(r1.error.issues[0].path).toEqual(["length"]);
|
||||
}
|
||||
|
||||
// Should fail with two errors
|
||||
const r2 = objectSchema.safeParse({
|
||||
length: 4,
|
||||
size: 3,
|
||||
});
|
||||
expect(r2.success).toEqual(false);
|
||||
if (!r2.success) {
|
||||
expect(r2.error.issues.length).toEqual(2);
|
||||
}
|
||||
|
||||
// Should pass with valid input
|
||||
const validData = {
|
||||
length: 6,
|
||||
size: 8,
|
||||
};
|
||||
expect(objectSchema.parse(validData)).toEqual(validData);
|
||||
});
|
||||
});
|
||||
|
||||
describe("type refinement with type guards", () => {
|
||||
test("type guard narrows output type", () => {
|
||||
const schema = z.string().refine((s): s is "a" => s === "a");
|
||||
|
||||
expectTypeOf<z.input<typeof schema>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.output<typeof schema>>().toEqualTypeOf<"a">();
|
||||
});
|
||||
|
||||
test("non-type-guard refine does not narrow", () => {
|
||||
const schema = z.string().refine((s) => s.length > 0);
|
||||
|
||||
expectTypeOf<z.input<typeof schema>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.output<typeof schema>>().toEqualTypeOf<string>();
|
||||
});
|
||||
|
||||
// TODO: Implement type narrowing for superRefine
|
||||
// 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) {
|
||||
// ctx.addIssue({
|
||||
// input: arg,
|
||||
// code: "custom",
|
||||
// message: "cannot be null",
|
||||
// fatal: true,
|
||||
// });
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
// });
|
||||
//
|
||||
// expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<NarrowType>();
|
||||
//
|
||||
// expect(schema.safeParse({ type: "test", age: 0 }).success).toEqual(true);
|
||||
// expect(schema.safeParse(null).success).toEqual(false);
|
||||
// });
|
||||
});
|
||||
|
||||
test("when", () => {
|
||||
const schema = z
|
||||
.strictObject({
|
||||
password: z.string().min(8),
|
||||
confirmPassword: z.string(),
|
||||
other: z.string(),
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
// console.log("running check...");
|
||||
// console.log(data);
|
||||
// console.log(data.password);
|
||||
return data.password === data.confirmPassword;
|
||||
},
|
||||
{
|
||||
message: "Passwords do not match",
|
||||
path: ["confirmPassword"],
|
||||
when(payload) {
|
||||
if (payload.value === undefined) return false;
|
||||
if (payload.value === null) return false;
|
||||
// no issues with confirmPassword or password
|
||||
return payload.issues.every((iss) => iss.path?.[0] !== "confirmPassword" && iss.path?.[0] !== "password");
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
expect(schema.safeParse(undefined)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "object",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected object, received undefined"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(schema.safeParse(null)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"expected": "object",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected object, received null"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(
|
||||
schema.safeParse({
|
||||
password: "asdf",
|
||||
confirmPassword: "asdfg",
|
||||
other: "qwer",
|
||||
})
|
||||
).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 8,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"password"
|
||||
],
|
||||
"message": "Too small: expected string to have >=8 characters"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(
|
||||
schema.safeParse({
|
||||
password: "asdf",
|
||||
confirmPassword: "asdfg",
|
||||
other: 1234,
|
||||
})
|
||||
).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "too_small",
|
||||
"minimum": 8,
|
||||
"inclusive": true,
|
||||
"path": [
|
||||
"password"
|
||||
],
|
||||
"message": "Too small: expected string to have >=8 characters"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
"other"
|
||||
],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
243
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/registries.test.ts
generated
vendored
Normal file
243
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/registries.test.ts
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("globalRegistry", () => {
|
||||
const reg = z.registry();
|
||||
|
||||
const a = z.string();
|
||||
reg.add(a);
|
||||
expect(reg.has(a)).toEqual(true);
|
||||
|
||||
reg.remove(a);
|
||||
expect(reg.has(a)).toEqual(false);
|
||||
|
||||
a.register(z.globalRegistry, { field: "sup" });
|
||||
expect(z.globalRegistry.has(a)).toEqual(true);
|
||||
expect(z.globalRegistry.get(a)).toEqual({ field: "sup" });
|
||||
|
||||
z.globalRegistry.remove(a);
|
||||
expect(z.globalRegistry.has(a)).toEqual(false);
|
||||
});
|
||||
|
||||
test("globalRegistry is singleton and attached to globalThis", () => {
|
||||
expect(z.globalRegistry).toBe((globalThis as any).__zod_globalRegistry);
|
||||
});
|
||||
|
||||
test("z.registry", () => {
|
||||
const fieldRegistry = z.registry<{ name: string; description: string }>();
|
||||
|
||||
const a = z.string();
|
||||
fieldRegistry.add(a, { name: "hello", description: "world" });
|
||||
const a_meta = fieldRegistry.get(a);
|
||||
expect(a_meta).toEqual({ name: "hello", description: "world" });
|
||||
|
||||
fieldRegistry.remove(a);
|
||||
expect(fieldRegistry.has(a)).toEqual(false);
|
||||
expect(fieldRegistry.get(a)).toEqual(undefined);
|
||||
});
|
||||
|
||||
test("z.registry no metadata", () => {
|
||||
const fieldRegistry = z.registry();
|
||||
|
||||
const a = z.string();
|
||||
fieldRegistry.add(a);
|
||||
fieldRegistry.add(z.number());
|
||||
expect(fieldRegistry.get(a)).toEqual(undefined);
|
||||
expect(fieldRegistry.has(a)).toEqual(true);
|
||||
});
|
||||
|
||||
test("z.registry with schema constraints", () => {
|
||||
const fieldRegistry = z.registry<{ name: string; description: string }, z.ZodString>();
|
||||
|
||||
const a = z.string();
|
||||
fieldRegistry.add(a, { name: "hello", description: "world" });
|
||||
// @ts-expect-error
|
||||
fieldRegistry.add(z.number(), { name: "test" });
|
||||
// @ts-expect-error
|
||||
z.number().register(fieldRegistry, { name: "test", description: "test" });
|
||||
});
|
||||
|
||||
// test("z.namedRegistry", () => {
|
||||
// const namedReg = z
|
||||
// .namedRegistry<{ name: string; description: string }>()
|
||||
// .add(z.string(), { name: "hello", description: "world" })
|
||||
// .add(z.number(), { name: "number", description: "number" });
|
||||
|
||||
// expect(namedReg.get("hello")).toEqual({
|
||||
// name: "hello",
|
||||
// description: "world",
|
||||
// });
|
||||
// expect(namedReg.has("hello")).toEqual(true);
|
||||
// expect(namedReg.get("number")).toEqual({
|
||||
// name: "number",
|
||||
// description: "number",
|
||||
// });
|
||||
|
||||
// // @ts-expect-error
|
||||
// namedReg.get("world");
|
||||
// // @ts-expect-error
|
||||
// expect(namedReg.get("world")).toEqual(undefined);
|
||||
|
||||
// const hello = namedReg.get("hello");
|
||||
// expect(hello).toEqual({ name: "hello", description: "world" });
|
||||
// expectTypeOf<typeof hello>().toEqualTypeOf<{
|
||||
// name: "hello";
|
||||
// description: "world";
|
||||
// }>();
|
||||
// expectTypeOf<typeof namedReg.items>().toEqualTypeOf<{
|
||||
// hello: { name: "hello"; description: "world" };
|
||||
// number: { name: "number"; description: "number" };
|
||||
// }>();
|
||||
// });
|
||||
|
||||
test("output type in registry meta", () => {
|
||||
const reg = z.registry<{ out: z.$output }>();
|
||||
const a = z.string();
|
||||
reg.add(a, { out: "asdf" });
|
||||
// @ts-expect-error
|
||||
reg.add(a, 1234);
|
||||
expectTypeOf(reg.get(a)).toEqualTypeOf<{ out: string } | undefined>();
|
||||
});
|
||||
|
||||
test("output type in registry meta - objects and arrays", () => {
|
||||
const reg = z.registry<{ name: string; examples: z.$output[] }>();
|
||||
const a = z.string();
|
||||
reg.add(a, { name: "hello", examples: ["world"] });
|
||||
|
||||
// @ts-expect-error
|
||||
reg.add(a, { name: "hello", examples: "world" });
|
||||
expectTypeOf(reg.get(a)).toEqualTypeOf<{ name: string; examples: string[] } | undefined>();
|
||||
});
|
||||
|
||||
test("input type in registry meta", () => {
|
||||
const reg = z.registry<{ in: z.$input }>();
|
||||
const a = z.pipe(z.number(), z.transform(String));
|
||||
reg.add(a, { in: 1234 });
|
||||
// @ts-expect-error
|
||||
reg.add(a, "1234");
|
||||
expectTypeOf(reg.get(a)).toEqualTypeOf<{ in: number } | undefined>();
|
||||
});
|
||||
|
||||
test("input type in registry meta - objects and arrays", () => {
|
||||
const reg = z.registry<{ name: string; examples: z.$input[] }>();
|
||||
const a = z.pipe(z.number(), z.transform(String));
|
||||
reg.add(a, { name: "hello", examples: [1234] });
|
||||
|
||||
// @ts-expect-error
|
||||
reg.add(a, { name: "hello", examples: "world" });
|
||||
expectTypeOf(reg.get(a)).toEqualTypeOf<{ name: string; examples: number[] } | undefined>();
|
||||
});
|
||||
|
||||
test(".meta method", () => {
|
||||
const a1 = z.string();
|
||||
const a2 = a1.meta({ name: "hello" });
|
||||
|
||||
expect(a1.meta()).toEqual(undefined);
|
||||
expect(a2.meta()).toEqual({ name: "hello" });
|
||||
expect(a1 === a2).toEqual(false);
|
||||
});
|
||||
|
||||
test(".meta metadata does not bubble up", () => {
|
||||
const a1 = z.string().meta({ name: "hello" });
|
||||
const a2 = a1.optional();
|
||||
|
||||
expect(a1.meta()).toEqual({ name: "hello" });
|
||||
expect(a2.meta()).toEqual(undefined);
|
||||
});
|
||||
|
||||
test(".describe", () => {
|
||||
const a1 = z.string();
|
||||
const a2 = a1.describe("Hello");
|
||||
|
||||
expect(a1.description).toEqual(undefined);
|
||||
expect(a2.description).toEqual("Hello");
|
||||
});
|
||||
|
||||
test("inherit across clone", () => {
|
||||
const A = z.string().meta({ a: true });
|
||||
expect(A.meta()).toEqual({ a: true });
|
||||
const B = A.meta({ b: true });
|
||||
expect(B.meta()).toEqual({ a: true, b: true });
|
||||
const C = B.describe("hello");
|
||||
expect(C.meta()).toEqual({ a: true, b: true, description: "hello" });
|
||||
});
|
||||
|
||||
test("loose examples", () => {
|
||||
z.string().register(z.globalRegistry, {
|
||||
examples: ["example"],
|
||||
});
|
||||
});
|
||||
|
||||
test("function meta without replacement", () => {
|
||||
const myReg = z.registry<{
|
||||
defaulter: (arg: string, test: boolean) => number;
|
||||
}>();
|
||||
|
||||
const mySchema = z.date();
|
||||
myReg.add(mySchema, {
|
||||
defaulter: (arg, _test) => {
|
||||
return arg.length;
|
||||
},
|
||||
});
|
||||
|
||||
expect(myReg.get(mySchema)!.defaulter("hello", true)).toEqual(5);
|
||||
});
|
||||
|
||||
test("function meta with replacement", () => {
|
||||
const myReg = z.registry<{
|
||||
defaulter: (arg: z.$input, test: boolean) => z.$output;
|
||||
}>();
|
||||
|
||||
const mySchema = z.string().transform((val) => val.length);
|
||||
myReg.add(mySchema, {
|
||||
defaulter: (arg, _test) => {
|
||||
return arg.length;
|
||||
},
|
||||
});
|
||||
|
||||
expect(myReg.get(mySchema)!.defaulter("hello", true)).toEqual(5);
|
||||
});
|
||||
|
||||
test("test .clear()", () => {
|
||||
const reg = z.registry();
|
||||
const a = z.string();
|
||||
reg.add(a);
|
||||
expect(reg.has(a)).toEqual(true);
|
||||
reg.clear();
|
||||
expect(reg.has(a)).toEqual(false);
|
||||
});
|
||||
|
||||
test("re-registering same id silently overwrites", () => {
|
||||
const reg = z.registry<z.core.GlobalMeta>();
|
||||
const a = z.string();
|
||||
const b = z.number();
|
||||
|
||||
reg.add(a, { id: "shared-id" });
|
||||
reg.add(b, { id: "shared-id" });
|
||||
|
||||
// No error thrown, b now owns the id
|
||||
expect(reg._idmap.get("shared-id")).toBe(b);
|
||||
});
|
||||
|
||||
test("toJSONSchema throws on duplicate id across different schemas", () => {
|
||||
const reg = z.registry<z.core.GlobalMeta>();
|
||||
const a = z.string().register(reg, { id: "duplicate-id" });
|
||||
const b = z.number().register(reg, { id: "duplicate-id" });
|
||||
|
||||
const wrapper = z.object({ a, b });
|
||||
|
||||
expect(() => z.toJSONSchema(wrapper, { metadata: reg })).toThrow(
|
||||
'Duplicate schema id "duplicate-id" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.'
|
||||
);
|
||||
});
|
||||
|
||||
test("toJSONSchema allows same schema with same id", () => {
|
||||
const reg = z.registry<z.core.GlobalMeta>();
|
||||
const shared = z.string().register(reg, { id: "shared-id" });
|
||||
|
||||
const wrapper = z.object({ a: shared, b: shared });
|
||||
|
||||
// Should not throw - same schema instance used twice
|
||||
const result = z.toJSONSchema(wrapper, { metadata: reg });
|
||||
expect(result.$defs?.["shared-id"]).toBeDefined();
|
||||
});
|
||||
181
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/set.test.ts
generated
vendored
Normal file
181
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/set.test.ts
generated
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const stringSet = z.set(z.string());
|
||||
type stringSet = z.infer<typeof stringSet>;
|
||||
|
||||
const minTwo = z.set(z.string()).min(2);
|
||||
const maxTwo = z.set(z.string()).max(2);
|
||||
const justTwo = z.set(z.string()).size(2);
|
||||
const nonEmpty = z.set(z.string()).nonempty();
|
||||
const nonEmptyMax = z.set(z.string()).nonempty().max(2);
|
||||
|
||||
test("type inference", () => {
|
||||
expectTypeOf<stringSet>().toEqualTypeOf<Set<string>>();
|
||||
});
|
||||
|
||||
test("valid parse", () => {
|
||||
const result = stringSet.safeParse(new Set(["first", "second"]));
|
||||
expect(result.success).toEqual(true);
|
||||
expect(result.data!.has("first")).toEqual(true);
|
||||
expect(result.data!.has("second")).toEqual(true);
|
||||
expect(result.data!.has("third")).toEqual(false);
|
||||
|
||||
expect(() => {
|
||||
minTwo.parse(new Set(["a", "b"]));
|
||||
minTwo.parse(new Set(["a", "b", "c"]));
|
||||
maxTwo.parse(new Set(["a", "b"]));
|
||||
maxTwo.parse(new Set(["a"]));
|
||||
justTwo.parse(new Set(["a", "b"]));
|
||||
nonEmpty.parse(new Set(["a"]));
|
||||
nonEmptyMax.parse(new Set(["a"]));
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
test("valid parse async", async () => {
|
||||
const result = await stringSet.spa(new Set(["first", "second"]));
|
||||
expect(result.success).toEqual(true);
|
||||
expect(result.data!.has("first")).toEqual(true);
|
||||
expect(result.data!.has("second")).toEqual(true);
|
||||
expect(result.data!.has("third")).toEqual(false);
|
||||
|
||||
const asyncResult = stringSet.safeParse(new Set(["first", "second"]));
|
||||
expect(asyncResult.success).toEqual(true);
|
||||
expect(asyncResult.data!.has("first")).toEqual(true);
|
||||
expect(asyncResult.data!.has("second")).toEqual(true);
|
||||
expect(asyncResult.data!.has("third")).toEqual(false);
|
||||
});
|
||||
|
||||
test("valid parse: size-related methods", () => {
|
||||
expect(() => {
|
||||
minTwo.parse(new Set(["a", "b"]));
|
||||
minTwo.parse(new Set(["a", "b", "c"]));
|
||||
maxTwo.parse(new Set(["a", "b"]));
|
||||
maxTwo.parse(new Set(["a"]));
|
||||
justTwo.parse(new Set(["a", "b"]));
|
||||
nonEmpty.parse(new Set(["a"]));
|
||||
nonEmptyMax.parse(new Set(["a"]));
|
||||
}).not.toThrow();
|
||||
|
||||
const sizeZeroResult = stringSet.parse(new Set());
|
||||
expect(sizeZeroResult.size).toBe(0);
|
||||
|
||||
const sizeTwoResult = minTwo.parse(new Set(["a", "b"]));
|
||||
expect(sizeTwoResult.size).toBe(2);
|
||||
});
|
||||
|
||||
test("failing when parsing empty set in nonempty ", () => {
|
||||
const result = nonEmpty.safeParse(new Set());
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error!.issues[0].code).toEqual("too_small");
|
||||
});
|
||||
|
||||
test("failing when set is smaller than min() ", () => {
|
||||
const result = minTwo.safeParse(new Set(["just_one"]));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error!.issues[0].code).toEqual("too_small");
|
||||
});
|
||||
|
||||
test("failing when set is bigger than max() ", () => {
|
||||
const result = maxTwo.safeParse(new Set(["one", "two", "three"]));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error!.issues[0].code).toEqual("too_big");
|
||||
});
|
||||
|
||||
test("doesn’t throw when an empty set is given", () => {
|
||||
const result = stringSet.safeParse(new Set([]));
|
||||
expect(result.success).toEqual(true);
|
||||
});
|
||||
|
||||
test("throws when a Map is given", () => {
|
||||
const result = stringSet.safeParse(new Map([]));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "set",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected set, received Map"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("throws when the given set has invalid input", () => {
|
||||
const result = stringSet.safeParse(new Set([Symbol()]));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(1);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received symbol"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("throws when the given set has multiple invalid entries", () => {
|
||||
const result = stringSet.safeParse(new Set([1, 2] as any[]));
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!.issues.length).toEqual(2);
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
},
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("min/max", async () => {
|
||||
const schema = z.set(z.string()).min(4).max(5);
|
||||
|
||||
const r1 = schema.safeParse(new Set(["a", "b", "c", "d"]));
|
||||
expect(r1.success).toEqual(true);
|
||||
|
||||
const r2 = schema.safeParse(new Set(["a", "b", "c"]));
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected set to have >=4 items",
|
||||
"minimum": 4,
|
||||
"origin": "set",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
||||
const r3 = schema.safeParse(new Set(["a", "b", "c", "d", "e", "f"]));
|
||||
expect(r3.success).toEqual(false);
|
||||
expect(r3.error!.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 5,
|
||||
"message": "Too big: expected set to have <=5 items",
|
||||
"origin": "set",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
134
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/standard-schema.test.ts
generated
vendored
Normal file
134
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/standard-schema.test.ts
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("length checks", async () => {
|
||||
const schema = z.string();
|
||||
const result = await schema["~standard"].validate(12);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"issues": [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received number",
|
||||
"path": [],
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("length checks", async () => {
|
||||
const schema = z.string();
|
||||
const result = await schema["~standard"].validate("asdf");
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"value": "asdf",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("length checks", async () => {
|
||||
const schema = z.string().refine(async (val) => val.length > 5);
|
||||
const result = await schema["~standard"].validate(12);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"issues": [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"message": "Invalid input: expected string, received number",
|
||||
"path": [],
|
||||
},
|
||||
],
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("length checks", async () => {
|
||||
const schema = z.string().refine(async (val) => val.length > 5);
|
||||
const result = await schema["~standard"].validate("234134134");
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"value": "234134134",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("schemas conform to StandardJSONSchemaV1", async () => {
|
||||
const schema = z.codec(z.string(), z.number(), {
|
||||
decode: (str) => Number.parseFloat(str),
|
||||
encode: (num) => num.toString(),
|
||||
});
|
||||
expect(schema["~standard"].validate).toBeTypeOf("function");
|
||||
expect(await schema["~standard"].validate("42")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"value": 42,
|
||||
}
|
||||
`);
|
||||
expect(schema["~standard"].jsonSchema.input({ target: "draft-2020-12" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
expect(schema["~standard"].jsonSchema.output({ target: "draft-2020-12" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "number",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test(".toJSONSchema() returns StandardJSONSchemaV1", async () => {
|
||||
const codec = z.codec(z.string(), z.number(), {
|
||||
decode: (str) => Number.parseFloat(str),
|
||||
encode: (num) => num.toString(),
|
||||
});
|
||||
const result = codec.toJSONSchema();
|
||||
expect(result["~standard"].validate).toBeTypeOf("function");
|
||||
expect(await result["~standard"].validate("42")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"value": 42,
|
||||
}
|
||||
`);
|
||||
expect(result["~standard"].jsonSchema.input({ target: "draft-2020-12" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
expect(result["~standard"].jsonSchema.output({ target: "draft-2020-12" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "number",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("z.toJSONSchema() returns StandardJSONSchemaV1", async () => {
|
||||
const codec = z.codec(z.string(), z.number(), {
|
||||
decode: (str) => Number.parseFloat(str),
|
||||
encode: (num) => num.toString(),
|
||||
});
|
||||
const result = z.toJSONSchema(codec);
|
||||
expect(result["~standard"].validate).toBeTypeOf("function");
|
||||
expect(await result["~standard"].validate("42")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"value": 42,
|
||||
}
|
||||
`);
|
||||
expect(result["~standard"].jsonSchema.input({ target: "draft-2020-12" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "string",
|
||||
}
|
||||
`);
|
||||
expect(result["~standard"].jsonSchema.output({ target: "draft-2020-12" })).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"type": "number",
|
||||
}
|
||||
`);
|
||||
});
|
||||
125
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/string-formats.test.ts
generated
vendored
Normal file
125
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/string-formats.test.ts
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("string format methods", () => {
|
||||
const a = z.email().min(10);
|
||||
const b = z.email().max(10);
|
||||
const c = z.email().length(10);
|
||||
const d = z.email().uppercase();
|
||||
const e = z.email().lowercase();
|
||||
|
||||
// Positive and negative cases for `a`
|
||||
expect(a.safeParse("longemail@example.com").success).toBe(true); // Positive
|
||||
expect(a.safeParse("ort@e.co").success).toBe(false); // Negative
|
||||
|
||||
// Positive and negative cases for `b`
|
||||
expect(b.safeParse("sho@e.co").success).toBe(true); // Positive
|
||||
expect(b.safeParse("longemail@example.com").success).toBe(false); // Negative
|
||||
|
||||
// Positive and negative cases for `c`
|
||||
expect(c.safeParse("56780@e.co").success).toBe(true); // Positive
|
||||
expect(c.safeParse("shoasdfasdfrt@e.co").success).toBe(false); // Negative
|
||||
|
||||
// Positive and negative cases for `d`
|
||||
expect(d.safeParse("EMAIL@EXAMPLE.COM").success).toBe(true); // Positive
|
||||
expect(d.safeParse("email@example.com").success).toBe(false); // Negative
|
||||
|
||||
// Positive and negative cases for `e`
|
||||
expect(e.safeParse("email@example.com").success).toBe(true); // Positive
|
||||
expect(e.safeParse("EMAIL@EXAMPLE.COM").success).toBe(false); // Negative
|
||||
});
|
||||
|
||||
test("z.stringFormat", () => {
|
||||
const ccRegex = /^(?:\d{14,19}|\d{4}(?: \d{3,6}){2,4}|\d{4}(?:-\d{3,6}){2,4})$/u;
|
||||
|
||||
const a = z
|
||||
.stringFormat("creditCard", (val) => ccRegex.test(val), {
|
||||
error: `Invalid credit card number`,
|
||||
})
|
||||
.refine((_) => false, "Also bad");
|
||||
|
||||
expect(a.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "creditCard",
|
||||
"path": [],
|
||||
"message": "Invalid credit card number"
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Also bad"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(a.safeParse("1234-5678-9012-3456")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Also bad"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(a.def.pattern).toMatchInlineSnapshot(`undefined`);
|
||||
|
||||
const b = z
|
||||
.stringFormat("creditCard", ccRegex, {
|
||||
abort: true,
|
||||
error: `Invalid credit card number`,
|
||||
})
|
||||
.refine((_) => false, "Also bad");
|
||||
|
||||
expect(b.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "creditCard",
|
||||
"path": [],
|
||||
"message": "Invalid credit card number"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(b.safeParse("1234-5678-9012-3456")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Also bad"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(b.def.pattern).toMatchInlineSnapshot(
|
||||
`/\\^\\(\\?:\\\\d\\{14,19\\}\\|\\\\d\\{4\\}\\(\\?: \\\\d\\{3,6\\}\\)\\{2,4\\}\\|\\\\d\\{4\\}\\(\\?:-\\\\d\\{3,6\\}\\)\\{2,4\\}\\)\\$/u`
|
||||
);
|
||||
});
|
||||
|
||||
test("z.hex", () => {
|
||||
const hexSchema = z.hex();
|
||||
|
||||
// Valid hex strings
|
||||
expect(hexSchema.safeParse("").success).toBe(true); // Empty string is valid hex
|
||||
expect(hexSchema.safeParse("123abc").success).toBe(true);
|
||||
expect(hexSchema.safeParse("DEADBEEF").success).toBe(true);
|
||||
expect(hexSchema.safeParse("0123456789abcdefABCDEF").success).toBe(true);
|
||||
|
||||
// Invalid hex strings
|
||||
expect(hexSchema.safeParse("xyz").success).toBe(false);
|
||||
expect(hexSchema.safeParse("123g").success).toBe(false);
|
||||
expect(hexSchema.safeParse("hello world").success).toBe(false);
|
||||
expect(hexSchema.safeParse("123-abc").success).toBe(false);
|
||||
});
|
||||
1175
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/string.test.ts
generated
vendored
Normal file
1175
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/string.test.ts
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
106
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/stringbool.test.ts
generated
vendored
Normal file
106
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/stringbool.test.ts
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("z.stringbool", () => {
|
||||
const a = z.stringbool();
|
||||
type a = z.infer<typeof a>;
|
||||
expectTypeOf<a>().toEqualTypeOf<boolean>();
|
||||
type a_in = z.input<typeof a>;
|
||||
expectTypeOf<a_in>().toEqualTypeOf<string>();
|
||||
|
||||
expect(z.parse(a, "true")).toEqual(true);
|
||||
expect(z.parse(a, "yes")).toEqual(true);
|
||||
expect(z.parse(a, "1")).toEqual(true);
|
||||
expect(z.parse(a, "on")).toEqual(true);
|
||||
expect(z.parse(a, "y")).toEqual(true);
|
||||
expect(z.parse(a, "enabled")).toEqual(true);
|
||||
expect(z.parse(a, "TRUE")).toEqual(true);
|
||||
|
||||
expect(z.parse(a, "false")).toEqual(false);
|
||||
expect(z.parse(a, "no")).toEqual(false);
|
||||
expect(z.parse(a, "0")).toEqual(false);
|
||||
expect(z.parse(a, "off")).toEqual(false);
|
||||
expect(z.parse(a, "n")).toEqual(false);
|
||||
expect(z.parse(a, "disabled")).toEqual(false);
|
||||
expect(z.parse(a, "FALSE")).toEqual(false);
|
||||
|
||||
expect(z.safeParse(a, "other")).toMatchObject({ success: false });
|
||||
expect(z.safeParse(a, "")).toMatchObject({ success: false });
|
||||
expect(z.safeParse(a, undefined)).toMatchObject({ success: false });
|
||||
expect(z.safeParse(a, {})).toMatchObject({ success: false });
|
||||
expect(z.safeParse(a, true)).toMatchObject({ success: false });
|
||||
expect(z.safeParse(a, false)).toMatchObject({ success: false });
|
||||
});
|
||||
|
||||
test("custom values", () => {
|
||||
const b = z.stringbool({
|
||||
truthy: ["y"],
|
||||
falsy: ["N"],
|
||||
});
|
||||
expect(z.parse(b, "y")).toEqual(true);
|
||||
expect(z.parse(b, "Y")).toEqual(true);
|
||||
expect(z.parse(b, "n")).toEqual(false);
|
||||
expect(z.parse(b, "N")).toEqual(false);
|
||||
expect(z.safeParse(b, "true")).toMatchObject({ success: false });
|
||||
expect(z.safeParse(b, "false")).toMatchObject({ success: false });
|
||||
});
|
||||
|
||||
test("custom values - case sensitive", () => {
|
||||
const c = z.stringbool({
|
||||
truthy: ["y"],
|
||||
falsy: ["N"],
|
||||
case: "sensitive",
|
||||
});
|
||||
expect(z.parse(c, "y")).toEqual(true);
|
||||
expect(z.safeParse(c, "Y")).toMatchObject({ success: false });
|
||||
expect(z.parse(c, "N")).toEqual(false);
|
||||
expect(z.safeParse(c, "n")).toMatchObject({ success: false });
|
||||
expect(z.safeParse(c, "TRUE")).toMatchObject({ success: false });
|
||||
});
|
||||
|
||||
// test custom error messages
|
||||
test("z.stringbool with custom error messages", () => {
|
||||
const a = z.stringbool("wrong!");
|
||||
|
||||
expect(() => a.parse("")).toThrowError("wrong!");
|
||||
});
|
||||
|
||||
test("z.stringbool codec encoding", () => {
|
||||
const schema = z.stringbool();
|
||||
|
||||
// Test encoding with default values
|
||||
expect(z.encode(schema, true)).toEqual("true");
|
||||
expect(z.encode(schema, false)).toEqual("false");
|
||||
});
|
||||
|
||||
test("z.stringbool codec encoding with custom values", () => {
|
||||
const schema = z.stringbool({
|
||||
truthy: ["yes", "on", "1"],
|
||||
falsy: ["no", "off", "0"],
|
||||
});
|
||||
|
||||
// Should return first element of custom arrays
|
||||
expect(z.encode(schema, true)).toEqual("yes");
|
||||
expect(z.encode(schema, false)).toEqual("no");
|
||||
});
|
||||
|
||||
test("z.stringbool codec round trip", () => {
|
||||
const schema = z.stringbool({
|
||||
truthy: ["enabled", "active"],
|
||||
falsy: ["disabled", "inactive"],
|
||||
});
|
||||
|
||||
// Test round trip: string -> boolean -> string
|
||||
const decoded = z.decode(schema, "enabled");
|
||||
expect(decoded).toEqual(true);
|
||||
|
||||
const encoded = z.encode(schema, decoded);
|
||||
expect(encoded).toEqual("enabled"); // First element of truthy array
|
||||
|
||||
// Test with falsy value
|
||||
const decodedFalse = z.decode(schema, "inactive");
|
||||
expect(decodedFalse).toEqual(false);
|
||||
|
||||
const encodedFalse = z.encode(schema, decodedFalse);
|
||||
expect(encodedFalse).toEqual("disabled"); // First element of falsy array
|
||||
});
|
||||
771
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/template-literal.test.ts
generated
vendored
Normal file
771
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/template-literal.test.ts
generated
vendored
Normal file
@@ -0,0 +1,771 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
const empty = z.templateLiteral([]);
|
||||
const hello = z.templateLiteral(["hello"]);
|
||||
const world = z.templateLiteral(["", z.literal("world")]);
|
||||
const one = z.templateLiteral([1]);
|
||||
const two = z.templateLiteral(["", z.literal(2)]);
|
||||
const onePointOne = z.templateLiteral([z.literal(1.1)]);
|
||||
const truee = z.templateLiteral([true]);
|
||||
const anotherTrue = z.templateLiteral(["", z.literal(true)]);
|
||||
const falsee = z.templateLiteral([false]);
|
||||
const anotherFalse = z.templateLiteral(["", z.literal(false)]);
|
||||
const nulll = z.templateLiteral([null]);
|
||||
const anotherNull = z.templateLiteral(["", z.null()]);
|
||||
const undefinedd = z.templateLiteral([undefined]);
|
||||
const anotherUndefined = z.templateLiteral(["", z.undefined()]);
|
||||
const anyString = z.templateLiteral(["", z.string()]);
|
||||
const lazyString = z.templateLiteral(["", z.lazy(() => z.string())]);
|
||||
const anyNumber = z.templateLiteral(["", z.number()]);
|
||||
const anyInt = z.templateLiteral(["", z.number().int()]);
|
||||
// const anyFiniteNumber = z.templateLiteral(["", z.number().finite()]);
|
||||
// const anyNegativeNumber = z.templateLiteral(["", z.number().negative()]);
|
||||
// const anyPositiveNumber = z.templateLiteral(["", z.number().positive()]);
|
||||
// const zeroButInADumbWay = z.templateLiteral(["", z.number().nonnegative().nonpositive()]);
|
||||
// const finiteButInADumbWay = z.templateLiteral(["", z.number().min(5).max(10)]);
|
||||
const bool = z.templateLiteral(["", z.boolean()]);
|
||||
const bigone = z.templateLiteral(["", z.literal(BigInt(1))]);
|
||||
const anyBigint = z.templateLiteral(["", z.bigint()]);
|
||||
const nullableYo = z.templateLiteral(["", z.nullable(z.literal("yo"))]);
|
||||
const nullableString = z.templateLiteral(["", z.nullable(z.string())]);
|
||||
const optionalYeah = z.templateLiteral(["", z.literal("yeah").optional()]);
|
||||
|
||||
const optionalString = z.templateLiteral(["", z.string().optional()]);
|
||||
const optionalNumber = z.templateLiteral(["", z.number().optional()]);
|
||||
const nullishBruh = z.templateLiteral(["", z.literal("bruh").nullish()]);
|
||||
const nullishString = z.templateLiteral(["", z.string().nullish()]);
|
||||
const cuid = z.templateLiteral(["", z.string().cuid()]);
|
||||
const cuidZZZ = z.templateLiteral(["", z.string().cuid(), "ZZZ"]);
|
||||
const cuid2 = z.templateLiteral(["", z.string().cuid2()]);
|
||||
const datetime = z.templateLiteral(["", z.string().datetime()]);
|
||||
const email = z.templateLiteral(["", z.string().email()]);
|
||||
// const ip = z.templateLiteral(["", z.string().ip()]);
|
||||
const ipv4 = z.templateLiteral(["", z.string().ipv4()]);
|
||||
const ipv6 = z.templateLiteral(["", z.string().ipv6()]);
|
||||
const mac = z.templateLiteral(["", z.mac()]);
|
||||
const ulid = z.templateLiteral(["", z.string().ulid()]);
|
||||
const uuid = z.templateLiteral(["", z.string().uuid()]);
|
||||
const stringAToZ = z.templateLiteral(["", z.string().regex(/^[a-z]+$/)]);
|
||||
const stringStartsWith = z.templateLiteral(["", z.string().startsWith("hello")]);
|
||||
const stringEndsWith = z.templateLiteral(["", z.string().endsWith("world")]);
|
||||
const stringMax5 = z.templateLiteral(["", z.string().max(5)]);
|
||||
const stringMin5 = z.templateLiteral(["", z.string().min(5)]);
|
||||
const stringLen5 = z.templateLiteral(["", z.string().length(5)]);
|
||||
const stringMin5Max10 = z.templateLiteral(["", z.string().min(5).max(10)]);
|
||||
const stringStartsWithMax5 = z.templateLiteral(["", z.string().startsWith("hello").max(5)]);
|
||||
const brandedString = z.templateLiteral(["", z.string().min(1).brand("myBrand")]);
|
||||
// const anything = z.templateLiteral(["", z.any()]);
|
||||
|
||||
const url = z.templateLiteral(["https://", z.string().regex(/\w+/), ".", z.enum(["com", "net"])]);
|
||||
|
||||
const measurement = z.templateLiteral([
|
||||
"",
|
||||
z.number().finite(),
|
||||
z.enum(["px", "em", "rem", "vh", "vw", "vmin", "vmax"]).optional(),
|
||||
]);
|
||||
|
||||
const connectionString = z.templateLiteral([
|
||||
"mongodb://",
|
||||
z
|
||||
.templateLiteral([
|
||||
"",
|
||||
z.string().regex(/\w+/).describe("username"),
|
||||
":",
|
||||
z.string().regex(/\w+/).describe("password"),
|
||||
"@",
|
||||
])
|
||||
.optional(),
|
||||
z.string().regex(/\w+/).describe("host"),
|
||||
":",
|
||||
z.number().finite().int().positive().describe("port"),
|
||||
z
|
||||
.templateLiteral([
|
||||
"/",
|
||||
z.string().regex(/\w+/).optional().describe("defaultauthdb"),
|
||||
z
|
||||
.templateLiteral([
|
||||
"?",
|
||||
z
|
||||
.string()
|
||||
.regex(/^\w+=\w+(&\w+=\w+)*$/)
|
||||
.optional()
|
||||
.describe("options"),
|
||||
])
|
||||
.optional(),
|
||||
])
|
||||
.optional(),
|
||||
]);
|
||||
|
||||
test("template literal type inference", () => {
|
||||
expectTypeOf<z.infer<typeof empty>>().toEqualTypeOf<``>();
|
||||
expectTypeOf<z.infer<typeof hello>>().toEqualTypeOf<`hello`>();
|
||||
expectTypeOf<z.infer<typeof world>>().toEqualTypeOf<`world`>();
|
||||
expectTypeOf<z.infer<typeof one>>().toEqualTypeOf<`1`>();
|
||||
expectTypeOf<z.infer<typeof two>>().toEqualTypeOf<`2`>();
|
||||
expectTypeOf<z.infer<typeof truee>>().toEqualTypeOf<`true`>();
|
||||
expectTypeOf<z.infer<typeof anotherTrue>>().toEqualTypeOf<`true`>();
|
||||
expectTypeOf<z.infer<typeof falsee>>().toEqualTypeOf<`false`>();
|
||||
expectTypeOf<z.infer<typeof anotherFalse>>().toEqualTypeOf<`false`>();
|
||||
expectTypeOf<z.infer<typeof nulll>>().toEqualTypeOf<`null`>();
|
||||
expectTypeOf<z.infer<typeof anotherNull>>().toEqualTypeOf<`null`>();
|
||||
expectTypeOf<z.infer<typeof undefinedd>>().toEqualTypeOf<``>();
|
||||
expectTypeOf<z.infer<typeof anotherUndefined>>().toEqualTypeOf<``>();
|
||||
expectTypeOf<z.infer<typeof anyString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof lazyString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof anyNumber>>().toEqualTypeOf<`${number}`>();
|
||||
expectTypeOf<z.infer<typeof anyInt>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof anyFiniteNumber>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof anyNegativeNumber>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof anyPositiveNumber>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof zeroButInADumbWay>>().toEqualTypeOf<`${number}`>();
|
||||
// expectTypeOf<z.infer<typeof finiteButInADumbWay>>().toEqualTypeOf<`${number}`>();
|
||||
expectTypeOf<z.infer<typeof bool>>().toEqualTypeOf<`true` | `false`>();
|
||||
expectTypeOf<z.infer<typeof bigone>>().toEqualTypeOf<`${bigint}`>();
|
||||
expectTypeOf<z.infer<typeof anyBigint>>().toEqualTypeOf<`${bigint}`>();
|
||||
expectTypeOf<z.infer<typeof nullableYo>>().toEqualTypeOf<`yo` | `null`>();
|
||||
expectTypeOf<z.infer<typeof nullableString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof optionalYeah>>().toEqualTypeOf<`yeah` | ``>();
|
||||
expectTypeOf<z.infer<typeof optionalString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof optionalNumber>>().toEqualTypeOf<`${number}` | ``>();
|
||||
expectTypeOf<z.infer<typeof nullishBruh>>().toEqualTypeOf<`bruh` | `null` | ``>();
|
||||
expectTypeOf<z.infer<typeof nullishString>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof cuid>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof cuidZZZ>>().toEqualTypeOf<`${string}ZZZ`>();
|
||||
expectTypeOf<z.infer<typeof cuid2>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof datetime>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof email>>().toEqualTypeOf<string>();
|
||||
// expectTypeOf<z.infer<typeof ip>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof ipv4>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof ipv6>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof mac>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof ulid>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof uuid>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringAToZ>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringStartsWith>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringEndsWith>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringMax5>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringMin5>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringLen5>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringMin5Max10>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof stringStartsWithMax5>>().toEqualTypeOf<string>();
|
||||
expectTypeOf<z.infer<typeof brandedString>>().toEqualTypeOf<`${string & z.core.$brand<"myBrand">}`>();
|
||||
|
||||
// expectTypeOf<z.infer<typeof anything>>().toEqualTypeOf<`${any}`>();
|
||||
|
||||
expectTypeOf<z.infer<typeof url>>().toEqualTypeOf<`https://${string}.com` | `https://${string}.net`>();
|
||||
|
||||
expectTypeOf<z.infer<typeof measurement>>().toEqualTypeOf<
|
||||
| `${number}`
|
||||
| `${number}px`
|
||||
| `${number}em`
|
||||
| `${number}rem`
|
||||
| `${number}vh`
|
||||
| `${number}vw`
|
||||
| `${number}vmin`
|
||||
| `${number}vmax`
|
||||
>();
|
||||
|
||||
expectTypeOf<z.infer<typeof connectionString>>().toEqualTypeOf<
|
||||
| `mongodb://${string}:${number}`
|
||||
| `mongodb://${string}:${number}/${string}`
|
||||
| `mongodb://${string}:${number}/${string}?${string}`
|
||||
| `mongodb://${string}:${string}@${string}:${number}`
|
||||
| `mongodb://${string}:${string}@${string}:${number}/${string}`
|
||||
| `mongodb://${string}:${string}@${string}:${number}/${string}?${string}`
|
||||
>();
|
||||
});
|
||||
|
||||
test("template literal unsupported args", () => {
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.object({})])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.array(z.object({}))])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.union([z.object({}), z.string()])])
|
||||
).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => z.templateLiteral([z.date()])).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.custom<object>((_) => true)])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
z.templateLiteral([
|
||||
// @ts-expect-error
|
||||
z.discriminatedUnion("discriminator", [z.object({}), z.object({})]),
|
||||
])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.function()])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.instanceof(class MyClass {})])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.intersection(z.object({}), z.object({}))])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.map(z.string(), z.string())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.nullable(z.object({}))])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.optional(z.object({}))])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.promise()])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.record(z.unknown())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.set(z.string())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.symbol()])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.tuple([z.string()])])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.unknown()])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.void()])
|
||||
).toThrow();
|
||||
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.never()])
|
||||
).toThrow();
|
||||
// @ts-expect-error
|
||||
expect(() => z.templateLiteral([z.nan()])).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.pipe(z.string(), z.string())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.preprocess(() => true, z.boolean())])
|
||||
).toThrow();
|
||||
expect(() =>
|
||||
// @ts-expect-error
|
||||
z.templateLiteral([z.object({}).brand("brand")])
|
||||
).toThrow();
|
||||
|
||||
// these constraints aren't enforced but they shouldn't throw
|
||||
z.templateLiteral([z.number().multipleOf(2)]);
|
||||
z.templateLiteral([z.string().emoji()]);
|
||||
z.templateLiteral([z.string().url()]);
|
||||
z.templateLiteral([z.string().url()]);
|
||||
z.templateLiteral([z.string().trim()]);
|
||||
z.templateLiteral([z.string().includes("train")]);
|
||||
z.templateLiteral([z.string().toLowerCase()]);
|
||||
z.templateLiteral([z.string().toUpperCase()]);
|
||||
});
|
||||
|
||||
test("template literal parsing - success - basic cases", () => {
|
||||
expect(() => z.templateLiteral([]).parse(7)).toThrow();
|
||||
|
||||
empty.parse("");
|
||||
hello.parse("hello");
|
||||
world.parse("world");
|
||||
one.parse("1");
|
||||
two.parse("2");
|
||||
onePointOne.parse("1.1");
|
||||
truee.parse("true");
|
||||
anotherTrue.parse("true");
|
||||
falsee.parse("false");
|
||||
anotherFalse.parse("false");
|
||||
nulll.parse("null");
|
||||
anotherNull.parse("null");
|
||||
undefinedd.parse("undefined");
|
||||
anotherUndefined.parse("undefined");
|
||||
anyString.parse("blahblahblah");
|
||||
anyString.parse("");
|
||||
lazyString.parse("blahblahblah");
|
||||
lazyString.parse("");
|
||||
anyNumber.parse("123");
|
||||
anyNumber.parse("1.23");
|
||||
anyNumber.parse("0");
|
||||
anyNumber.parse("-1.23");
|
||||
anyNumber.parse("-123");
|
||||
// anyNumber.parse("Infinity");
|
||||
// anyNumber.parse("-Infinity");
|
||||
anyInt.parse("123");
|
||||
// anyInt.parse("-123");
|
||||
// anyFiniteNumber.parse("123");
|
||||
// anyFiniteNumber.parse("1.23");
|
||||
// anyFiniteNumber.parse("0");
|
||||
// anyFiniteNumber.parse("-1.23");
|
||||
// anyFiniteNumber.parse("-123");
|
||||
// anyNegativeNumber.parse("-123");
|
||||
// anyNegativeNumber.parse("-1.23");
|
||||
// anyNegativeNumber.parse("-Infinity");
|
||||
// anyPositiveNumber.parse("123");
|
||||
// anyPositiveNumber.parse("1.23");
|
||||
// anyPositiveNumber.parse("Infinity");
|
||||
// zeroButInADumbWay.parse("0");
|
||||
// zeroButInADumbWay.parse("00000");
|
||||
// finiteButInADumbWay.parse("5");
|
||||
// finiteButInADumbWay.parse("10");
|
||||
// finiteButInADumbWay.parse("6.66");
|
||||
bool.parse("true");
|
||||
bool.parse("false");
|
||||
bigone.parse("1");
|
||||
anyBigint.parse("123456");
|
||||
anyBigint.parse("0");
|
||||
// anyBigint.parse("-123456");
|
||||
nullableYo.parse("yo");
|
||||
nullableYo.parse("null");
|
||||
nullableString.parse("abc");
|
||||
nullableString.parse("null");
|
||||
optionalYeah.parse("yeah");
|
||||
optionalYeah.parse("");
|
||||
optionalString.parse("abc");
|
||||
optionalString.parse("");
|
||||
optionalNumber.parse("123");
|
||||
optionalNumber.parse("1.23");
|
||||
optionalNumber.parse("0");
|
||||
optionalNumber.parse("-1.23");
|
||||
optionalNumber.parse("-123");
|
||||
// optionalNumber.parse("Infinity");
|
||||
// optionalNumber.parse("-Infinity");
|
||||
nullishBruh.parse("bruh");
|
||||
nullishBruh.parse("null");
|
||||
nullishBruh.parse("");
|
||||
cuid.parse("cjld2cyuq0000t3rmniod1foy");
|
||||
cuidZZZ.parse("cjld2cyuq0000t3rmniod1foyZZZ");
|
||||
cuid2.parse("tz4a98xxat96iws9zmbrgj3a");
|
||||
datetime.parse(new Date().toISOString());
|
||||
email.parse("info@example.com");
|
||||
// ip.parse("213.174.246.205");
|
||||
// ip.parse("c359:f57c:21e5:39eb:1187:e501:f936:b452");
|
||||
ipv4.parse("213.174.246.205");
|
||||
ipv6.parse("c359:f57c:21e5:39eb:1187:e501:f936:b452");
|
||||
mac.parse("00:1A:2B:3C:4D:5E");
|
||||
ulid.parse("01GW3D2QZJBYB6P1Z1AE997VPW");
|
||||
uuid.parse("808989fd-3a6e-4af2-b607-737323a176f6");
|
||||
stringAToZ.parse("asudgaskhdgashd");
|
||||
stringStartsWith.parse("hello world");
|
||||
stringEndsWith.parse("hello world");
|
||||
stringMax5.parse("hello");
|
||||
stringMin5.parse("hello");
|
||||
stringLen5.parse("hello");
|
||||
stringMin5Max10.parse("hello worl");
|
||||
stringStartsWithMax5.parse("hello");
|
||||
brandedString.parse("branded string");
|
||||
});
|
||||
|
||||
test("template literal parsing - failure - basic cases", () => {
|
||||
expect(() => empty.parse("a")).toThrow();
|
||||
expect(() => hello.parse("hello!")).toThrow();
|
||||
expect(() => hello.parse("!hello")).toThrow();
|
||||
expect(() => world.parse("world!")).toThrow();
|
||||
expect(() => world.parse("!world")).toThrow();
|
||||
expect(() => one.parse("2")).toThrow();
|
||||
expect(() => one.parse("12")).toThrow();
|
||||
expect(() => one.parse("21")).toThrow();
|
||||
expect(() => onePointOne.parse("1s1")).toThrow();
|
||||
expect(() => two.parse("1")).toThrow();
|
||||
expect(() => two.parse("21")).toThrow();
|
||||
expect(() => two.parse("12")).toThrow();
|
||||
expect(() => truee.parse("false")).toThrow();
|
||||
expect(() => truee.parse("1true")).toThrow();
|
||||
expect(() => truee.parse("true1")).toThrow();
|
||||
expect(() => anotherTrue.parse("false")).toThrow();
|
||||
expect(() => anotherTrue.parse("1true")).toThrow();
|
||||
expect(() => anotherTrue.parse("true1")).toThrow();
|
||||
expect(() => falsee.parse("true")).toThrow();
|
||||
expect(() => falsee.parse("1false")).toThrow();
|
||||
expect(() => falsee.parse("false1")).toThrow();
|
||||
expect(() => anotherFalse.parse("true")).toThrow();
|
||||
expect(() => anotherFalse.parse("1false")).toThrow();
|
||||
expect(() => anotherFalse.parse("false1")).toThrow();
|
||||
expect(() => nulll.parse("123")).toThrow();
|
||||
expect(() => nulll.parse("null1")).toThrow();
|
||||
expect(() => nulll.parse("1null")).toThrow();
|
||||
expect(() => anotherNull.parse("123")).toThrow();
|
||||
expect(() => anotherNull.parse("null1")).toThrow();
|
||||
expect(() => anotherNull.parse("1null")).toThrow();
|
||||
expect(() => undefinedd.parse("123")).toThrow();
|
||||
expect(() => undefinedd.parse("undefined1")).toThrow();
|
||||
expect(() => undefinedd.parse("1undefined")).toThrow();
|
||||
expect(() => anotherUndefined.parse("123")).toThrow();
|
||||
expect(() => anotherUndefined.parse("undefined1")).toThrow();
|
||||
expect(() => anotherUndefined.parse("1undefined")).toThrow();
|
||||
expect(() => anyNumber.parse("2a")).toThrow();
|
||||
expect(() => anyNumber.parse("a2")).toThrow();
|
||||
expect(() => anyNumber.parse("-2a")).toThrow();
|
||||
expect(() => anyNumber.parse("a-2")).toThrow();
|
||||
expect(() => anyNumber.parse("2.5a")).toThrow();
|
||||
expect(() => anyNumber.parse("a2.5")).toThrow();
|
||||
expect(() => anyNumber.parse("Infinitya")).toThrow();
|
||||
expect(() => anyNumber.parse("aInfinity")).toThrow();
|
||||
expect(() => anyNumber.parse("-Infinitya")).toThrow();
|
||||
expect(() => anyNumber.parse("a-Infinity")).toThrow();
|
||||
expect(() => anyNumber.parse("2e5")).toThrow();
|
||||
expect(() => anyNumber.parse("2e-5")).toThrow();
|
||||
expect(() => anyNumber.parse("2e+5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2e5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2e-5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2e+5")).toThrow();
|
||||
expect(() => anyNumber.parse("2.1e5")).toThrow();
|
||||
expect(() => anyNumber.parse("2.1e-5")).toThrow();
|
||||
expect(() => anyNumber.parse("2.1e+5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2.1e5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2.1e-5")).toThrow();
|
||||
expect(() => anyNumber.parse("-2.1e+5")).toThrow();
|
||||
expect(() => anyNumber.parse("-Infinity")).toThrow();
|
||||
expect(() => anyNumber.parse("Infinity")).toThrow();
|
||||
expect(() => anyInt.parse("1.23")).toThrow();
|
||||
expect(() => anyInt.parse("-1.23")).toThrow();
|
||||
expect(() => anyInt.parse("d1")).toThrow();
|
||||
expect(() => anyInt.parse("1d")).toThrow();
|
||||
// expect(() => anyFiniteNumber.parse("Infinity")).toThrow();
|
||||
// expect(() => anyFiniteNumber.parse("-Infinity")).toThrow();
|
||||
// expect(() => anyFiniteNumber.parse("123a")).toThrow();
|
||||
// expect(() => anyFiniteNumber.parse("a123")).toThrow();
|
||||
// expect(() => anyNegativeNumber.parse("0")).toThrow();
|
||||
// expect(() => anyNegativeNumber.parse("1")).toThrow();
|
||||
// expect(() => anyNegativeNumber.parse("Infinity")).toThrow();
|
||||
// expect(() => anyPositiveNumber.parse("0")).toThrow();
|
||||
// expect(() => anyPositiveNumber.parse("-1")).toThrow();
|
||||
// expect(() => anyPositiveNumber.parse("-Infinity")).toThrow();
|
||||
// expect(() => zeroButInADumbWay.parse("1")).toThrow();
|
||||
// expect(() => zeroButInADumbWay.parse("-1")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("Infinity")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("-Infinity")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("-5")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("10a")).toThrow();
|
||||
// expect(() => finiteButInADumbWay.parse("a10")).toThrow();
|
||||
expect(() => bool.parse("123")).toThrow();
|
||||
expect(() => bigone.parse("2")).toThrow();
|
||||
expect(() => bigone.parse("c1")).toThrow();
|
||||
expect(() => anyBigint.parse("1.23")).toThrow();
|
||||
expect(() => anyBigint.parse("-1.23")).toThrow();
|
||||
expect(() => anyBigint.parse("c123")).toThrow();
|
||||
expect(() => nullableYo.parse("yo1")).toThrow();
|
||||
expect(() => nullableYo.parse("1yo")).toThrow();
|
||||
expect(() => nullableYo.parse("null1")).toThrow();
|
||||
expect(() => nullableYo.parse("1null")).toThrow();
|
||||
expect(() => optionalYeah.parse("yeah1")).toThrow();
|
||||
expect(() => optionalYeah.parse("1yeah")).toThrow();
|
||||
expect(() => optionalYeah.parse("undefined")).toThrow();
|
||||
expect(() => optionalNumber.parse("123a")).toThrow();
|
||||
expect(() => optionalNumber.parse("a123")).toThrow();
|
||||
// expect(() => optionalNumber.parse("Infinitya")).toThrow();
|
||||
// expect(() => optionalNumber.parse("aInfinity")).toThrow();
|
||||
expect(() => nullishBruh.parse("bruh1")).toThrow();
|
||||
expect(() => nullishBruh.parse("1bruh")).toThrow();
|
||||
expect(() => nullishBruh.parse("null1")).toThrow();
|
||||
expect(() => nullishBruh.parse("1null")).toThrow();
|
||||
expect(() => nullishBruh.parse("undefined")).toThrow();
|
||||
expect(() => cuid.parse("bjld2cyuq0000t3rmniod1foy")).toThrow();
|
||||
expect(() => cuid.parse("cjld2cyu")).toThrow();
|
||||
expect(() => cuid.parse("cjld2 cyu")).toThrow();
|
||||
expect(() => cuid.parse("cjld2cyuq0000t3rmniod1foy ")).toThrow();
|
||||
expect(() => cuid.parse("1cjld2cyuq0000t3rmniod1foy")).toThrow();
|
||||
expect(() => cuidZZZ.parse("cjld2cyuq0000t3rmniod1foy")).toThrow();
|
||||
expect(() => cuidZZZ.parse("cjld2cyuq0000t3rmniod1foyZZY")).toThrow();
|
||||
expect(() => cuidZZZ.parse("cjld2cyuq0000t3rmniod1foyZZZ1")).toThrow();
|
||||
expect(() => cuidZZZ.parse("1cjld2cyuq0000t3rmniod1foyZZZ")).toThrow();
|
||||
expect(() => cuid2.parse("A9z4a98xxat96iws9zmbrgj3a")).toThrow();
|
||||
expect(() => cuid2.parse("tz4a98xxat96iws9zmbrgj3!")).toThrow();
|
||||
expect(() => datetime.parse("2022-01-01 00:00:00")).toThrow();
|
||||
expect(() => email.parse("info@example.com@")).toThrow();
|
||||
// expect(() => ip.parse("213.174.246:205")).toThrow();
|
||||
// expect(() => ip.parse("c359.f57c:21e5:39eb:1187:e501:f936:b452")).toThrow();
|
||||
expect(() => ipv4.parse("1213.174.246.205")).toThrow();
|
||||
expect(() => ipv4.parse("c359:f57c:21e5:39eb:1187:e501:f936:b452")).toThrow();
|
||||
expect(() => ipv6.parse("c359:f57c:21e5:39eb:1187:e501:f936:b4521")).toThrow();
|
||||
expect(() => ipv6.parse("213.174.246.205")).toThrow();
|
||||
expect(() => mac.parse("00:1A:2B:3C:4D:5E:6A:7B")).toThrow();
|
||||
expect(() => mac.parse("00:1A:2B:3C")).toThrow();
|
||||
expect(() => ulid.parse("01GW3D2QZJBYB6P1Z1AE997VPW!")).toThrow();
|
||||
expect(() => uuid.parse("808989fd-3a6e-4af2-b607-737323a176f6Z")).toThrow();
|
||||
expect(() => uuid.parse("Z808989fd-3a6e-4af2-b607-737323a176f6")).toThrow();
|
||||
expect(() => stringAToZ.parse("asdasdasd1")).toThrow();
|
||||
expect(() => stringAToZ.parse("1asdasdasd")).toThrow();
|
||||
expect(() => stringStartsWith.parse("ahello")).toThrow();
|
||||
expect(() => stringEndsWith.parse("worlda")).toThrow();
|
||||
expect(() => stringMax5.parse("123456")).toThrow();
|
||||
expect(() => stringMin5.parse("1234")).toThrow();
|
||||
expect(() => stringLen5.parse("123456")).toThrow();
|
||||
expect(() => stringLen5.parse("1234")).toThrow();
|
||||
expect(() => stringMin5Max10.parse("1234")).toThrow();
|
||||
expect(() => stringMin5Max10.parse("12345678901")).toThrow();
|
||||
|
||||
// the "startswith" overrides the max length
|
||||
// expect(() => stringStartsWithMax5.parse("hello1")).toThrow();
|
||||
expect(() => stringStartsWithMax5.parse("1hell")).toThrow();
|
||||
expect(() => brandedString.parse("")).toThrow();
|
||||
});
|
||||
|
||||
test("regexes", () => {
|
||||
expect(empty._zod.pattern.source).toMatchInlineSnapshot(`"^$"`);
|
||||
expect(hello._zod.pattern.source).toMatchInlineSnapshot(`"^hello$"`);
|
||||
expect(world._zod.pattern.source).toMatchInlineSnapshot(`"^(world)$"`);
|
||||
expect(one._zod.pattern.source).toMatchInlineSnapshot(`"^1$"`);
|
||||
expect(two._zod.pattern.source).toMatchInlineSnapshot(`"^(2)$"`);
|
||||
expect(truee._zod.pattern.source).toMatchInlineSnapshot(`"^true$"`);
|
||||
expect(anotherTrue._zod.pattern.source).toMatchInlineSnapshot(`"^(true)$"`);
|
||||
expect(falsee._zod.pattern.source).toMatchInlineSnapshot(`"^false$"`);
|
||||
expect(anotherFalse._zod.pattern.source).toMatchInlineSnapshot(`"^(false)$"`);
|
||||
expect(nulll._zod.pattern.source).toMatchInlineSnapshot(`"^null$"`);
|
||||
expect(anotherNull._zod.pattern.source).toMatchInlineSnapshot(`"^null$"`);
|
||||
expect(undefinedd._zod.pattern.source).toMatchInlineSnapshot(`"^undefined$"`);
|
||||
expect(anotherUndefined._zod.pattern.source).toMatchInlineSnapshot(`"^undefined$"`);
|
||||
expect(anyString._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{0,}$"`);
|
||||
expect(lazyString._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{0,}$"`);
|
||||
expect(anyNumber._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
expect(anyInt._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+$"`);
|
||||
// expect(anyFiniteNumber._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
// expect(anyNegativeNumber._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
// expect(anyPositiveNumber._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
// expect(zeroButInADumbWay._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
// expect(finiteButInADumbWay._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?$"`);
|
||||
expect(bool._zod.pattern.source).toMatchInlineSnapshot(`"^(?:true|false)$"`);
|
||||
expect(bigone._zod.pattern.source).toMatchInlineSnapshot(`"^(1)$"`);
|
||||
expect(anyBigint._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+n?$"`);
|
||||
expect(nullableYo._zod.pattern.source).toMatchInlineSnapshot(`"^((yo)|null)$"`);
|
||||
expect(nullableString._zod.pattern.source).toMatchInlineSnapshot(`"^([\\s\\S]{0,}|null)$"`);
|
||||
expect(optionalYeah._zod.pattern.source).toMatchInlineSnapshot(`"^((yeah))?$"`);
|
||||
expect(optionalString._zod.pattern.source).toMatchInlineSnapshot(`"^([\\s\\S]{0,})?$"`);
|
||||
expect(optionalNumber._zod.pattern.source).toMatchInlineSnapshot(`"^(-?\\d+(?:\\.\\d+)?)?$"`);
|
||||
expect(nullishBruh._zod.pattern.source).toMatchInlineSnapshot(`"^(((bruh)|null))?$"`);
|
||||
expect(nullishString._zod.pattern.source).toMatchInlineSnapshot(`"^(([\\s\\S]{0,}|null))?$"`);
|
||||
expect(cuid._zod.pattern.source).toMatchInlineSnapshot(`"^[cC][^\\s-]{8,}$"`);
|
||||
expect(cuidZZZ._zod.pattern.source).toMatchInlineSnapshot(`"^[cC][^\\s-]{8,}ZZZ$"`);
|
||||
expect(cuid2._zod.pattern.source).toMatchInlineSnapshot(`"^[0-9a-z]+$"`);
|
||||
expect(datetime._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"`
|
||||
);
|
||||
expect(email._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"`
|
||||
);
|
||||
// expect(ip._zod.pattern.source).toMatchInlineSnapshot(
|
||||
// `"^(^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$)|(^(([a-fA-F0-9]{1,4}:){7}|::([a-fA-F0-9]{1,4}:){0,6}|([a-fA-F0-9]{1,4}:){1}:([a-fA-F0-9]{1,4}:){0,5}|([a-fA-F0-9]{1,4}:){2}:([a-fA-F0-9]{1,4}:){0,4}|([a-fA-F0-9]{1,4}:){3}:([a-fA-F0-9]{1,4}:){0,3}|([a-fA-F0-9]{1,4}:){4}:([a-fA-F0-9]{1,4}:){0,2}|([a-fA-F0-9]{1,4}:){5}:([a-fA-F0-9]{1,4}:){0,1})([a-fA-F0-9]{1,4}|(((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2}))\\.){3}((25[0-5])|(2[0-4][0-9])|(1[0-9]{2})|([0-9]{1,2})))$)$"`
|
||||
// );
|
||||
expect(ipv4._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$"`
|
||||
);
|
||||
expect(ipv6._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$"`
|
||||
);
|
||||
expect(mac._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^(?:[0-9A-F]{2}:){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}:){5}[0-9a-f]{2}$"`
|
||||
);
|
||||
expect(ulid._zod.pattern.source).toMatchInlineSnapshot(`"^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$"`);
|
||||
expect(uuid._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"`
|
||||
);
|
||||
expect(stringAToZ._zod.pattern.source).toMatchInlineSnapshot(`"^[a-z]+$"`);
|
||||
expect(stringStartsWith._zod.pattern.source).toMatchInlineSnapshot(`"^hello.*$"`);
|
||||
expect(stringEndsWith._zod.pattern.source).toMatchInlineSnapshot(`"^.*world$"`);
|
||||
expect(stringMax5._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{0,5}$"`);
|
||||
expect(stringMin5._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{5,}$"`);
|
||||
expect(stringLen5._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{5,5}$"`);
|
||||
expect(stringMin5Max10._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{5,10}$"`);
|
||||
expect(brandedString._zod.pattern.source).toMatchInlineSnapshot(`"^[\\s\\S]{1,}$"`);
|
||||
expect(url._zod.pattern.source).toMatchInlineSnapshot(`"^https:\\/\\/\\w+\\.(com|net)$"`);
|
||||
expect(measurement._zod.pattern.source).toMatchInlineSnapshot(`"^-?\\d+(?:\\.\\d+)?((px|em|rem|vh|vw|vmin|vmax))?$"`);
|
||||
expect(connectionString._zod.pattern.source).toMatchInlineSnapshot(
|
||||
`"^mongodb:\\/\\/(\\w+:\\w+@)?\\w+:-?\\d+(\\/(\\w+)?(\\?(\\w+=\\w+(&\\w+=\\w+)*)?)?)?$"`
|
||||
);
|
||||
});
|
||||
|
||||
test("template literal parsing - success - complex cases", () => {
|
||||
url.parse("https://example.com");
|
||||
url.parse("https://speedtest.net");
|
||||
|
||||
// measurement.parse(1);
|
||||
// measurement.parse(1.1);
|
||||
// measurement.parse(0);
|
||||
// measurement.parse(-1.1);
|
||||
// measurement.parse(-1);
|
||||
measurement.parse("1");
|
||||
measurement.parse("1.1");
|
||||
measurement.parse("0");
|
||||
measurement.parse("-1");
|
||||
measurement.parse("-1.1");
|
||||
measurement.parse("1px");
|
||||
measurement.parse("1.1px");
|
||||
measurement.parse("0px");
|
||||
measurement.parse("-1px");
|
||||
measurement.parse("-1.1px");
|
||||
measurement.parse("1em");
|
||||
measurement.parse("1.1em");
|
||||
measurement.parse("0em");
|
||||
measurement.parse("-1em");
|
||||
measurement.parse("-1.1em");
|
||||
measurement.parse("1rem");
|
||||
measurement.parse("1.1rem");
|
||||
measurement.parse("0rem");
|
||||
measurement.parse("-1rem");
|
||||
measurement.parse("-1.1rem");
|
||||
measurement.parse("1vh");
|
||||
measurement.parse("1.1vh");
|
||||
measurement.parse("0vh");
|
||||
measurement.parse("-1vh");
|
||||
measurement.parse("-1.1vh");
|
||||
measurement.parse("1vw");
|
||||
measurement.parse("1.1vw");
|
||||
measurement.parse("0vw");
|
||||
measurement.parse("-1vw");
|
||||
measurement.parse("-1.1vw");
|
||||
measurement.parse("1vmin");
|
||||
measurement.parse("1.1vmin");
|
||||
measurement.parse("0vmin");
|
||||
measurement.parse("-1vmin");
|
||||
measurement.parse("-1.1vmin");
|
||||
measurement.parse("1vmax");
|
||||
measurement.parse("1.1vmax");
|
||||
measurement.parse("0vmax");
|
||||
measurement.parse("-1vmax");
|
||||
measurement.parse("-1.1vmax");
|
||||
|
||||
connectionString.parse("mongodb://host:1234");
|
||||
connectionString.parse("mongodb://host:1234/");
|
||||
connectionString.parse("mongodb://host:1234/defaultauthdb");
|
||||
connectionString.parse("mongodb://host:1234/defaultauthdb?authSource=admin");
|
||||
connectionString.parse("mongodb://host:1234/defaultauthdb?authSource=admin&connectTimeoutMS=300000");
|
||||
connectionString.parse("mongodb://host:1234/?authSource=admin");
|
||||
connectionString.parse("mongodb://host:1234/?authSource=admin&connectTimeoutMS=300000");
|
||||
connectionString.parse("mongodb://username:password@host:1234");
|
||||
connectionString.parse("mongodb://username:password@host:1234/");
|
||||
connectionString.parse("mongodb://username:password@host:1234/defaultauthdb");
|
||||
connectionString.parse("mongodb://username:password@host:1234/defaultauthdb?authSource=admin");
|
||||
connectionString.parse(
|
||||
"mongodb://username:password@host:1234/defaultauthdb?authSource=admin&connectTimeoutMS=300000"
|
||||
);
|
||||
connectionString.parse("mongodb://username:password@host:1234/?authSource=admin");
|
||||
connectionString.parse("mongodb://username:password@host:1234/?authSource=admin&connectTimeoutMS=300000");
|
||||
});
|
||||
|
||||
test("template literal parsing - failure - complex cases", () => {
|
||||
expect(() => url.parse("http://example.com")).toThrow();
|
||||
expect(() => url.parse("https://.com")).toThrow();
|
||||
expect(() => url.parse("https://examplecom")).toThrow();
|
||||
expect(() => url.parse("https://example.org")).toThrow();
|
||||
expect(() => url.parse("https://example.net.il")).toThrow();
|
||||
|
||||
expect(() => measurement.parse("1.1.1")).toThrow();
|
||||
expect(() => measurement.parse("Infinity")).toThrow();
|
||||
expect(() => measurement.parse("-Infinity")).toThrow();
|
||||
expect(() => measurement.parse("NaN")).toThrow();
|
||||
expect(() => measurement.parse("1%")).toThrow();
|
||||
|
||||
expect(() => connectionString.parse("mongod://host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:d234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:12.34")).toThrow();
|
||||
// Note: template literal regex currently allows negative numbers despite .positive() constraint
|
||||
// This is a known limitation where template literals use regex patterns directly
|
||||
// expect(() => connectionString.parse("mongodb://host:-1234")).toThrow();
|
||||
// expect(() => connectionString.parse("mongodb://host:-12.34")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://:password@host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://usernamepassword@host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://username:@host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://@host:1234")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:1234/defaultauthdb?authSourceadmin")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:1234/?authSourceadmin")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:1234/defaultauthdb?&authSource=admin")).toThrow();
|
||||
expect(() => connectionString.parse("mongodb://host:1234/?&authSource=admin")).toThrow();
|
||||
});
|
||||
|
||||
test("template literal parsing - failure - issue format", () => {
|
||||
expect(anotherNull.safeParse("1null")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^null$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(cuidZZZ.safeParse("1cjld2cyuq0000t3rmniod1foyZZZ")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^[cC][^\\\\s-]{8,}ZZZ$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(stringMin5Max10.safeParse("1234")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^[\\\\s\\\\S]{5,10}$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
expect(connectionString.safeParse("mongodb://host:1234/defaultauthdb?authSourceadmin")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^mongodb:\\\\/\\\\/(\\\\w+:\\\\w+@)?\\\\w+:-?\\\\d+(\\\\/(\\\\w+)?(\\\\?(\\\\w+=\\\\w+(&\\\\w+=\\\\w+)*)?)?)?$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
expect(stringStartsWithMax5.safeParse("1hell")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "template_literal",
|
||||
"pattern": "^hello.*$",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
438
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/to-json-schema-methods.test.ts
generated
vendored
Normal file
438
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/to-json-schema-methods.test.ts
generated
vendored
Normal file
@@ -0,0 +1,438 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
// Utility functions
|
||||
function expectMethodMatch(schema: z.ZodType, params?: z.core.ToJSONSchemaParams): void {
|
||||
const staticResult = z.toJSONSchema(schema, params);
|
||||
const methodResult = schema.toJSONSchema(params);
|
||||
expect(methodResult).toEqual(staticResult);
|
||||
}
|
||||
|
||||
describe("toJSONSchema method", () => {
|
||||
describe("primitive types", () => {
|
||||
test("string", () => {
|
||||
expectMethodMatch(z.string());
|
||||
});
|
||||
|
||||
test("number", () => {
|
||||
expectMethodMatch(z.number());
|
||||
});
|
||||
|
||||
test("boolean", () => {
|
||||
expectMethodMatch(z.boolean());
|
||||
});
|
||||
|
||||
test("bigint", () => {
|
||||
expectMethodMatch(z.bigint(), { unrepresentable: "any" });
|
||||
});
|
||||
|
||||
test("symbol", () => {
|
||||
expectMethodMatch(z.symbol(), { unrepresentable: "any" });
|
||||
});
|
||||
|
||||
test("null", () => {
|
||||
expectMethodMatch(z.null());
|
||||
});
|
||||
|
||||
test("undefined", () => {
|
||||
expectMethodMatch(z.undefined(), { unrepresentable: "any" });
|
||||
});
|
||||
|
||||
test("void", () => {
|
||||
expectMethodMatch(z.void(), { unrepresentable: "any" });
|
||||
});
|
||||
|
||||
test("never", () => {
|
||||
expectMethodMatch(z.never());
|
||||
});
|
||||
|
||||
test("any", () => {
|
||||
expectMethodMatch(z.any());
|
||||
});
|
||||
|
||||
test("unknown", () => {
|
||||
expectMethodMatch(z.unknown());
|
||||
});
|
||||
|
||||
test("date", () => {
|
||||
expectMethodMatch(z.date(), { unrepresentable: "any" });
|
||||
});
|
||||
|
||||
test("nan", () => {
|
||||
expectMethodMatch(z.nan(), { unrepresentable: "any" });
|
||||
});
|
||||
});
|
||||
|
||||
describe("string formats", () => {
|
||||
test("email", () => {
|
||||
expectMethodMatch(z.email());
|
||||
});
|
||||
|
||||
test("url", () => {
|
||||
expectMethodMatch(z.url());
|
||||
});
|
||||
|
||||
test("uuid", () => {
|
||||
expectMethodMatch(z.uuid());
|
||||
});
|
||||
|
||||
test("datetime", () => {
|
||||
expectMethodMatch(z.iso.datetime());
|
||||
});
|
||||
|
||||
test("date", () => {
|
||||
expectMethodMatch(z.iso.date());
|
||||
});
|
||||
|
||||
test("guid", () => {
|
||||
expectMethodMatch(z.guid());
|
||||
});
|
||||
|
||||
test("cuid", () => {
|
||||
expectMethodMatch(z.cuid());
|
||||
});
|
||||
|
||||
test("cuid2", () => {
|
||||
expectMethodMatch(z.cuid2());
|
||||
});
|
||||
|
||||
test("ulid", () => {
|
||||
expectMethodMatch(z.ulid());
|
||||
});
|
||||
|
||||
test("base64", () => {
|
||||
expectMethodMatch(z.base64());
|
||||
});
|
||||
|
||||
test("ipv4", () => {
|
||||
expectMethodMatch(z.ipv4());
|
||||
});
|
||||
|
||||
test("ipv6", () => {
|
||||
expectMethodMatch(z.ipv6());
|
||||
});
|
||||
});
|
||||
|
||||
describe("string validations", () => {
|
||||
test("min length", () => {
|
||||
expectMethodMatch(z.string().min(5));
|
||||
});
|
||||
|
||||
test("max length", () => {
|
||||
expectMethodMatch(z.string().max(10));
|
||||
});
|
||||
|
||||
test("length", () => {
|
||||
expectMethodMatch(z.string().length(5));
|
||||
});
|
||||
|
||||
test("regex", () => {
|
||||
expectMethodMatch(z.string().regex(/^[A-Z]+$/));
|
||||
});
|
||||
|
||||
test("multiple patterns", () => {
|
||||
expectMethodMatch(
|
||||
z
|
||||
.string()
|
||||
.regex(/^[A-Z]+$/)
|
||||
.regex(/^[0-9]+$/)
|
||||
);
|
||||
});
|
||||
|
||||
test("startsWith", () => {
|
||||
expectMethodMatch(z.string().startsWith("hello"));
|
||||
});
|
||||
|
||||
test("endsWith", () => {
|
||||
expectMethodMatch(z.string().endsWith("world"));
|
||||
});
|
||||
|
||||
test("includes", () => {
|
||||
expectMethodMatch(z.string().includes("test"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("number validations", () => {
|
||||
test("min", () => {
|
||||
expectMethodMatch(z.number().min(5));
|
||||
});
|
||||
|
||||
test("max", () => {
|
||||
expectMethodMatch(z.number().max(10));
|
||||
});
|
||||
|
||||
test("int", () => {
|
||||
expectMethodMatch(z.int());
|
||||
});
|
||||
|
||||
test("positive", () => {
|
||||
expectMethodMatch(z.number().positive());
|
||||
});
|
||||
|
||||
test("negative", () => {
|
||||
expectMethodMatch(z.number().negative());
|
||||
});
|
||||
|
||||
test("multipleOf", () => {
|
||||
expectMethodMatch(z.number().multipleOf(2));
|
||||
});
|
||||
|
||||
test("gte", () => {
|
||||
expectMethodMatch(z.number().gte(5));
|
||||
});
|
||||
|
||||
test("lte", () => {
|
||||
expectMethodMatch(z.number().lte(10));
|
||||
});
|
||||
|
||||
test("gt", () => {
|
||||
expectMethodMatch(z.number().gt(5));
|
||||
});
|
||||
|
||||
test("lt", () => {
|
||||
expectMethodMatch(z.number().lt(10));
|
||||
});
|
||||
});
|
||||
|
||||
describe("literals and enums", () => {
|
||||
test("literal string", () => {
|
||||
expectMethodMatch(z.literal("hello"));
|
||||
});
|
||||
|
||||
test("literal number", () => {
|
||||
expectMethodMatch(z.literal(42));
|
||||
});
|
||||
|
||||
test("literal boolean", () => {
|
||||
expectMethodMatch(z.literal(true));
|
||||
});
|
||||
|
||||
test("literal null", () => {
|
||||
expectMethodMatch(z.literal(null));
|
||||
});
|
||||
|
||||
test("multiple literals", () => {
|
||||
expectMethodMatch(z.literal(["a", "b", "c"]));
|
||||
});
|
||||
|
||||
test("enum", () => {
|
||||
expectMethodMatch(z.enum(["red", "green", "blue"]));
|
||||
});
|
||||
|
||||
test("nativeEnum", () => {
|
||||
enum Colors {
|
||||
Red = "red",
|
||||
Green = "green",
|
||||
Blue = "blue",
|
||||
}
|
||||
expectMethodMatch(z.nativeEnum(Colors));
|
||||
});
|
||||
});
|
||||
|
||||
describe("composite types", () => {
|
||||
test("array", () => {
|
||||
expectMethodMatch(z.array(z.string()));
|
||||
});
|
||||
|
||||
test("array with min", () => {
|
||||
expectMethodMatch(z.array(z.string()).min(2));
|
||||
});
|
||||
|
||||
test("array with max", () => {
|
||||
expectMethodMatch(z.array(z.string()).max(10));
|
||||
});
|
||||
|
||||
test("object", () => {
|
||||
expectMethodMatch(z.object({ name: z.string(), age: z.number() }));
|
||||
});
|
||||
|
||||
test("object with optional", () => {
|
||||
expectMethodMatch(z.object({ name: z.string(), age: z.number().optional() }));
|
||||
});
|
||||
|
||||
test("strict object", () => {
|
||||
expectMethodMatch(z.strictObject({ name: z.string() }));
|
||||
});
|
||||
|
||||
test("loose object", () => {
|
||||
expectMethodMatch(z.looseObject({ name: z.string() }));
|
||||
});
|
||||
|
||||
test("object with catchall", () => {
|
||||
expectMethodMatch(z.object({ name: z.string() }).catchall(z.string()));
|
||||
});
|
||||
|
||||
test("tuple", () => {
|
||||
expectMethodMatch(z.tuple([z.string(), z.number()]));
|
||||
});
|
||||
|
||||
test("tuple with rest", () => {
|
||||
expectMethodMatch(z.tuple([z.string()], z.number()));
|
||||
});
|
||||
|
||||
test("record", () => {
|
||||
expectMethodMatch(z.record(z.string(), z.number()));
|
||||
});
|
||||
|
||||
test("union", () => {
|
||||
expectMethodMatch(z.union([z.string(), z.number()]));
|
||||
});
|
||||
|
||||
test("discriminated union", () => {
|
||||
expectMethodMatch(
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({ type: z.literal("a"), value: z.string() }),
|
||||
z.object({ type: z.literal("b"), value: z.number() }),
|
||||
])
|
||||
);
|
||||
});
|
||||
|
||||
test("intersection", () => {
|
||||
expectMethodMatch(z.intersection(z.object({ a: z.string() }), z.object({ b: z.number() })));
|
||||
});
|
||||
});
|
||||
|
||||
describe("wrapper types", () => {
|
||||
test("optional", () => {
|
||||
expectMethodMatch(z.string().optional());
|
||||
});
|
||||
|
||||
test("nullable", () => {
|
||||
expectMethodMatch(z.string().nullable());
|
||||
});
|
||||
|
||||
test("nullish", () => {
|
||||
expectMethodMatch(z.string().nullish());
|
||||
});
|
||||
|
||||
test("default", () => {
|
||||
expectMethodMatch(z.string().default("hello"));
|
||||
});
|
||||
|
||||
test("default function", () => {
|
||||
expectMethodMatch(z.string().default(() => "hello"));
|
||||
});
|
||||
|
||||
test("prefault", () => {
|
||||
expectMethodMatch(z.string().prefault("hello"));
|
||||
});
|
||||
|
||||
test("prefault function", () => {
|
||||
expectMethodMatch(z.string().prefault(() => "hello"));
|
||||
});
|
||||
|
||||
test("catch", () => {
|
||||
expectMethodMatch(z.string().catch("hello"));
|
||||
});
|
||||
|
||||
test("readonly", () => {
|
||||
expectMethodMatch(z.string().readonly());
|
||||
});
|
||||
|
||||
test("nonoptional", () => {
|
||||
expectMethodMatch(z.string().optional().nonoptional());
|
||||
});
|
||||
});
|
||||
|
||||
describe("special types", () => {
|
||||
test("lazy", () => {
|
||||
type Node = {
|
||||
value: string;
|
||||
children?: Node[] | undefined;
|
||||
};
|
||||
const Node: z.ZodType<Node> = z.lazy(() =>
|
||||
z.object({
|
||||
value: z.string(),
|
||||
children: z.array(Node).optional(),
|
||||
})
|
||||
) as z.ZodType<Node>;
|
||||
expectMethodMatch(Node);
|
||||
});
|
||||
|
||||
test("promise", () => {
|
||||
expectMethodMatch(z.promise(z.string()));
|
||||
});
|
||||
|
||||
test("pipe", () => {
|
||||
expectMethodMatch(
|
||||
z
|
||||
.string()
|
||||
.transform((val) => val.length)
|
||||
.pipe(z.number())
|
||||
);
|
||||
});
|
||||
|
||||
test("transform", () => {
|
||||
expectMethodMatch(
|
||||
z.string().transform((val) => val.length),
|
||||
{ unrepresentable: "any" }
|
||||
);
|
||||
});
|
||||
|
||||
test("file", () => {
|
||||
expectMethodMatch(z.file());
|
||||
});
|
||||
|
||||
test("file with mime", () => {
|
||||
expectMethodMatch(z.file().mime("image/png"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("parameters", () => {
|
||||
test("target draft-7", () => {
|
||||
expectMethodMatch(z.string(), { target: "draft-7" });
|
||||
});
|
||||
|
||||
test("target draft-4", () => {
|
||||
expectMethodMatch(z.string(), { target: "draft-4" });
|
||||
});
|
||||
|
||||
test("target openapi-3.0", () => {
|
||||
expectMethodMatch(z.string(), { target: "openapi-3.0" });
|
||||
});
|
||||
|
||||
test("io input", () => {
|
||||
expectMethodMatch(z.string().default("hello"), { io: "input" });
|
||||
});
|
||||
|
||||
test("cycles throw", () => {
|
||||
const schema = z.object({
|
||||
name: z.string(),
|
||||
get subcategories() {
|
||||
return z.array(schema);
|
||||
},
|
||||
});
|
||||
// Both should throw the same error
|
||||
expect(() => z.toJSONSchema(schema, { cycles: "throw" })).toThrow();
|
||||
expect(() => schema.toJSONSchema({ cycles: "throw" })).toThrow();
|
||||
});
|
||||
|
||||
test("reused ref", () => {
|
||||
const shared = z.string();
|
||||
const schema = z.object({
|
||||
a: shared,
|
||||
b: shared,
|
||||
});
|
||||
expectMethodMatch(schema, { reused: "ref" });
|
||||
});
|
||||
});
|
||||
|
||||
describe("edge cases with metadata", () => {
|
||||
test("schema with id metadata", () => {
|
||||
const a = z.string().meta({ id: "hi" });
|
||||
expectMethodMatch(a);
|
||||
});
|
||||
|
||||
test("schema with id then additional metadata", () => {
|
||||
const a = z.string().meta({ id: "hi2" });
|
||||
const b = a.meta({ name: "asdf" });
|
||||
expectMethodMatch(b);
|
||||
});
|
||||
|
||||
test("nested schema with id", () => {
|
||||
const inner = z.string().meta({ id: "inner" });
|
||||
const outer = z.object({ value: inner });
|
||||
expectMethodMatch(outer);
|
||||
});
|
||||
});
|
||||
});
|
||||
2990
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts
generated
vendored
Normal file
2990
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/to-json-schema.test.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
361
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/transform.test.ts
generated
vendored
Normal file
361
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/transform.test.ts
generated
vendored
Normal file
@@ -0,0 +1,361 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("transform ctx.addIssue with parse", () => {
|
||||
const strs = ["foo", "bar"];
|
||||
const schema = z.string().transform((data, ctx) => {
|
||||
const i = strs.indexOf(data);
|
||||
if (i === -1) {
|
||||
ctx.addIssue({
|
||||
input: data,
|
||||
code: "custom",
|
||||
message: `${data} is not one of our allowed strings`,
|
||||
});
|
||||
}
|
||||
return data.length;
|
||||
});
|
||||
const result = schema.safeParse("asdf");
|
||||
expect(result.success).toEqual(false);
|
||||
expect(result.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "asdf is not one of our allowed strings",
|
||||
"path": []
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("transform ctx.addIssue with parseAsync", async () => {
|
||||
const strs = ["foo", "bar"];
|
||||
|
||||
const result = await z
|
||||
.string()
|
||||
.transform(async (data, ctx) => {
|
||||
const i = strs.indexOf(data);
|
||||
if (i === -1) {
|
||||
ctx.addIssue({
|
||||
input: data,
|
||||
code: "custom",
|
||||
message: `${data} is not one of our allowed strings`,
|
||||
});
|
||||
}
|
||||
return data.length;
|
||||
})
|
||||
.safeParseAsync("asdf");
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "asdf is not one of our allowed strings",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("z.NEVER in transform", () => {
|
||||
const foo = z
|
||||
.number()
|
||||
.optional()
|
||||
.transform((val, ctx) => {
|
||||
if (!val) {
|
||||
ctx.addIssue({
|
||||
input: val,
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "bad",
|
||||
});
|
||||
return z.NEVER;
|
||||
}
|
||||
return val;
|
||||
});
|
||||
type foo = z.infer<typeof foo>;
|
||||
expectTypeOf<foo>().toEqualTypeOf<number>();
|
||||
const arg = foo.safeParse(undefined);
|
||||
if (!arg.success) {
|
||||
expect(arg.error.issues[0].message).toEqual("bad");
|
||||
}
|
||||
});
|
||||
|
||||
test("basic transformations", () => {
|
||||
const r1 = z
|
||||
.string()
|
||||
.transform((data) => data.length)
|
||||
.parse("asdf");
|
||||
expect(r1).toEqual(4);
|
||||
});
|
||||
|
||||
test("coercion", () => {
|
||||
const numToString = z.number().transform((n) => String(n));
|
||||
const data = z
|
||||
.object({
|
||||
id: numToString,
|
||||
})
|
||||
.parse({ id: 5 });
|
||||
|
||||
expect(data).toEqual({ id: "5" });
|
||||
});
|
||||
|
||||
test("async coercion", async () => {
|
||||
const numToString = z.number().transform(async (n) => String(n));
|
||||
const data = await z
|
||||
.object({
|
||||
id: numToString,
|
||||
})
|
||||
.parseAsync({ id: 5 });
|
||||
|
||||
expect(data).toEqual({ id: "5" });
|
||||
});
|
||||
|
||||
test("sync coercion async error", async () => {
|
||||
const asyncNumberToString = z.number().transform(async (n) => String(n));
|
||||
expect(() =>
|
||||
z
|
||||
.object({
|
||||
id: asyncNumberToString,
|
||||
})
|
||||
.parse({ id: 5 })
|
||||
).toThrow();
|
||||
// expect(data).toEqual({ id: '5' });
|
||||
});
|
||||
|
||||
test("default", () => {
|
||||
const data = z.string().default("asdf").parse(undefined); // => "asdf"
|
||||
expect(data).toEqual("asdf");
|
||||
});
|
||||
|
||||
test("dynamic default", () => {
|
||||
const data = z
|
||||
.string()
|
||||
.default(() => "string")
|
||||
.parse(undefined); // => "asdf"
|
||||
expect(data).toEqual("string");
|
||||
});
|
||||
|
||||
test("default when property is null or undefined", () => {
|
||||
const data = z
|
||||
.object({
|
||||
foo: z.boolean().nullable().default(true),
|
||||
bar: z.boolean().default(true),
|
||||
})
|
||||
.parse({ foo: null });
|
||||
|
||||
expect(data).toEqual({ foo: null, bar: true });
|
||||
});
|
||||
|
||||
test("default with falsy values", () => {
|
||||
const schema = z.object({
|
||||
emptyStr: z.string().default("def"),
|
||||
zero: z.number().default(5),
|
||||
falseBoolean: z.boolean().default(true),
|
||||
});
|
||||
const input = { emptyStr: "", zero: 0, falseBoolean: true };
|
||||
const output = schema.parse(input);
|
||||
// defaults are not supposed to be used
|
||||
expect(output).toEqual(input);
|
||||
});
|
||||
|
||||
test("object typing", () => {
|
||||
const stringToNumber = z.string().transform((arg) => Number.parseFloat(arg));
|
||||
|
||||
const t1 = z.object({
|
||||
stringToNumber,
|
||||
});
|
||||
|
||||
type t1 = z.input<typeof t1>;
|
||||
type t2 = z.output<typeof t1>;
|
||||
|
||||
expectTypeOf<t1>().toEqualTypeOf<{ stringToNumber: string }>();
|
||||
expectTypeOf<t2>().toEqualTypeOf<{ stringToNumber: number }>();
|
||||
});
|
||||
|
||||
test("transform method overloads", () => {
|
||||
const t1 = z.string().transform((val) => val.toUpperCase());
|
||||
expect(t1.parse("asdf")).toEqual("ASDF");
|
||||
|
||||
const t2 = z.string().transform((val) => val.length);
|
||||
expect(t2.parse("asdf")).toEqual(4);
|
||||
});
|
||||
|
||||
test("multiple transformers", () => {
|
||||
const stringToNumber = z.string().transform((arg) => Number.parseFloat(arg));
|
||||
|
||||
const doubler = stringToNumber.transform((val) => {
|
||||
return val * 2;
|
||||
});
|
||||
expect(doubler.parse("5")).toEqual(10);
|
||||
});
|
||||
|
||||
test("short circuit on dirty", () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.refine(() => false)
|
||||
.transform((val) => val.toUpperCase());
|
||||
const result = schema.safeParse("asdf");
|
||||
expect(result.success).toEqual(false);
|
||||
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const result2 = schema.safeParse(1234);
|
||||
expect(result2.success).toEqual(false);
|
||||
if (!result2.success) {
|
||||
expect(result2.error.issues[0].code).toEqual(z.ZodIssueCode.invalid_type);
|
||||
}
|
||||
});
|
||||
|
||||
test("async short circuit on dirty", async () => {
|
||||
const schema = z
|
||||
.string()
|
||||
.refine(() => false)
|
||||
.transform((val) => val.toUpperCase());
|
||||
const result = await schema.spa("asdf");
|
||||
expect(result.success).toEqual(false);
|
||||
|
||||
expect(result.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const result2 = await schema.spa(1234);
|
||||
expect(result2.success).toEqual(false);
|
||||
|
||||
expect(result2.error).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "string",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected string, received number"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("do not continue by default", () => {
|
||||
const A = z
|
||||
.string()
|
||||
.transform((val, ctx) => {
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
});
|
||||
ctx.addIssue({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
});
|
||||
return val;
|
||||
})
|
||||
.pipe(z.number() as any);
|
||||
expect(A.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
const B = z
|
||||
.string()
|
||||
.transform((val, ctx) => {
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
input: val,
|
||||
});
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
input: val,
|
||||
});
|
||||
return val;
|
||||
})
|
||||
.pipe(z.number() as any);
|
||||
expect(B.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
|
||||
const C = z
|
||||
.string()
|
||||
.transform((val, ctx) => {
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
input: val,
|
||||
continue: true,
|
||||
});
|
||||
ctx.issues.push({
|
||||
code: "custom",
|
||||
message: `custom error`,
|
||||
input: val,
|
||||
continue: true,
|
||||
});
|
||||
return val;
|
||||
})
|
||||
.pipe(z.number() as any);
|
||||
expect(C.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
},
|
||||
{
|
||||
"code": "custom",
|
||||
"message": "custom error",
|
||||
"path": []
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("encode error", () => {
|
||||
const schema = z.string().transform((val) => val.length);
|
||||
expect(() => z.encode(schema, 1234)).toThrowErrorMatchingInlineSnapshot(
|
||||
`[ZodEncodeError: Encountered unidirectional transform during encode: ZodTransform]`
|
||||
);
|
||||
});
|
||||
183
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/tuple.test.ts
generated
vendored
Normal file
183
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/tuple.test.ts
generated
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("successful validation", () => {
|
||||
const testTuple = z.tuple([z.string(), z.number()]);
|
||||
expectTypeOf<typeof testTuple._output>().toEqualTypeOf<[string, number]>();
|
||||
|
||||
const val = testTuple.parse(["asdf", 1234]);
|
||||
expect(val).toEqual(val);
|
||||
|
||||
const r1 = testTuple.safeParse(["asdf", "asdf"]);
|
||||
expect(r1.success).toEqual(false);
|
||||
expect(r1.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
1
|
||||
],
|
||||
"message": "Invalid input: expected number, received string"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const r2 = testTuple.safeParse(["asdf", 1234, true]);
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "too_big",
|
||||
"maximum": 2,
|
||||
"inclusive": true,
|
||||
"origin": "array",
|
||||
"path": [],
|
||||
"message": "Too big: expected array to have <=2 items"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const r3 = testTuple.safeParse({});
|
||||
expect(r3.success).toEqual(false);
|
||||
expect(r3.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "tuple",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected tuple, received object"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("async validation", async () => {
|
||||
const testTuple = z
|
||||
.tuple([z.string().refine(async () => true), z.number().refine(async () => true)])
|
||||
.refine(async () => true);
|
||||
expectTypeOf<typeof testTuple._output>().toEqualTypeOf<[string, number]>();
|
||||
|
||||
const val = await testTuple.parseAsync(["asdf", 1234]);
|
||||
expect(val).toEqual(val);
|
||||
|
||||
const r1 = await testTuple.safeParseAsync(["asdf", "asdf"]);
|
||||
expect(r1.success).toEqual(false);
|
||||
expect(r1.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "number",
|
||||
"code": "invalid_type",
|
||||
"path": [
|
||||
1
|
||||
],
|
||||
"message": "Invalid input: expected number, received string"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const r2 = await testTuple.safeParseAsync(["asdf", 1234, true]);
|
||||
expect(r2.success).toEqual(false);
|
||||
expect(r2.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "too_big",
|
||||
"maximum": 2,
|
||||
"inclusive": true,
|
||||
"origin": "array",
|
||||
"path": [],
|
||||
"message": "Too big: expected array to have <=2 items"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
|
||||
const r3 = await testTuple.safeParseAsync({});
|
||||
expect(r3.success).toEqual(false);
|
||||
expect(r3.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"expected": "tuple",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected tuple, received object"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("tuple with optional elements", () => {
|
||||
const myTuple = z.tuple([z.string(), z.number().optional(), z.string().optional()]).rest(z.boolean());
|
||||
expectTypeOf<typeof myTuple._output>().toEqualTypeOf<[string, number?, string?, ...boolean[]]>();
|
||||
|
||||
const goodData = [["asdf"], ["asdf", 1234], ["asdf", 1234, "asdf"], ["asdf", 1234, "asdf", true, false, true]];
|
||||
for (const data of goodData) {
|
||||
expect(myTuple.parse(data)).toEqual(data);
|
||||
}
|
||||
|
||||
const badData = [
|
||||
["asdf", "asdf"],
|
||||
["asdf", 1234, "asdf", "asdf"],
|
||||
["asdf", 1234, "asdf", true, false, "asdf"],
|
||||
];
|
||||
for (const data of badData) {
|
||||
expect(() => myTuple.parse(data)).toThrow();
|
||||
}
|
||||
});
|
||||
|
||||
test("tuple with optional elements followed by required", () => {
|
||||
const myTuple = z.tuple([z.string(), z.number().optional(), z.string()]).rest(z.boolean());
|
||||
expectTypeOf<typeof myTuple._output>().toEqualTypeOf<[string, number | undefined, string, ...boolean[]]>();
|
||||
|
||||
const goodData = [
|
||||
["asdf", 1234, "asdf"],
|
||||
["asdf", 1234, "asdf", true, false, true],
|
||||
];
|
||||
for (const data of goodData) {
|
||||
expect(myTuple.parse(data)).toEqual(data);
|
||||
}
|
||||
|
||||
const badData = [
|
||||
["asdf"],
|
||||
["asdf", 1234],
|
||||
["asdf", 1234, "asdf", "asdf"],
|
||||
["asdf", 1234, "asdf", true, false, "asdf"],
|
||||
];
|
||||
for (const data of badData) {
|
||||
expect(() => myTuple.parse(data)).toThrow();
|
||||
}
|
||||
});
|
||||
|
||||
test("tuple with all optional elements", () => {
|
||||
const allOptionalTuple = z.tuple([z.string().optional(), z.number().optional(), z.boolean().optional()]);
|
||||
expectTypeOf<typeof allOptionalTuple._output>().toEqualTypeOf<[string?, number?, boolean?]>();
|
||||
|
||||
// Empty array should be valid (all items optional)
|
||||
expect(allOptionalTuple.parse([])).toEqual([]);
|
||||
|
||||
// Partial arrays should be valid
|
||||
expect(allOptionalTuple.parse(["hello"])).toEqual(["hello"]);
|
||||
expect(allOptionalTuple.parse(["hello", 42])).toEqual(["hello", 42]);
|
||||
|
||||
// Full array should be valid
|
||||
expect(allOptionalTuple.parse(["hello", 42, true])).toEqual(["hello", 42, true]);
|
||||
|
||||
// Array that's too long should fail
|
||||
expect(() => allOptionalTuple.parse(["hello", 42, true, "extra"])).toThrow();
|
||||
});
|
||||
|
||||
test("tuple with rest schema", () => {
|
||||
const myTuple = z.tuple([z.string(), z.number()]).rest(z.boolean());
|
||||
expect(myTuple.parse(["asdf", 1234, true, false, true])).toEqual(["asdf", 1234, true, false, true]);
|
||||
|
||||
expect(myTuple.parse(["asdf", 1234])).toEqual(["asdf", 1234]);
|
||||
|
||||
expect(() => myTuple.parse(["asdf", 1234, "asdf"])).toThrow();
|
||||
type t1 = z.output<typeof myTuple>;
|
||||
|
||||
expectTypeOf<t1>().toEqualTypeOf<[string, number, ...boolean[]]>();
|
||||
});
|
||||
|
||||
test("sparse array input", () => {
|
||||
const schema = z.tuple([z.string(), z.number()]);
|
||||
expect(() => schema.parse(new Array(2))).toThrow();
|
||||
});
|
||||
219
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/union.test.ts
generated
vendored
Normal file
219
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/union.test.ts
generated
vendored
Normal file
@@ -0,0 +1,219 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("function parsing", () => {
|
||||
const schema = z.union([z.string().refine(() => false), z.number().refine(() => false)]);
|
||||
const result = schema.safeParse("asdf");
|
||||
expect(result.success).toEqual(false);
|
||||
});
|
||||
|
||||
test("union 2", () => {
|
||||
const result = z.union([z.number(), z.string().refine(() => false)]).safeParse("a");
|
||||
expect(result.success).toEqual(false);
|
||||
});
|
||||
|
||||
test("return valid over invalid", () => {
|
||||
const schema = z.union([
|
||||
z.object({
|
||||
email: z.string().email(),
|
||||
}),
|
||||
z.string(),
|
||||
]);
|
||||
expect(schema.parse("asdf")).toEqual("asdf");
|
||||
expect(schema.parse({ email: "asdlkjf@lkajsdf.com" })).toEqual({
|
||||
email: "asdlkjf@lkajsdf.com",
|
||||
});
|
||||
});
|
||||
|
||||
test("return errors from both union arms", () => {
|
||||
const result = z.union([z.number(), z.boolean()]).safeParse("a");
|
||||
expect(result.success).toEqual(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "invalid_union",
|
||||
"errors": [
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "number",
|
||||
"message": "Invalid input: expected number, received string",
|
||||
"path": [],
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "boolean",
|
||||
"message": "Invalid input: expected boolean, received string",
|
||||
"path": [],
|
||||
},
|
||||
],
|
||||
],
|
||||
"message": "Invalid input",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("options getter", async () => {
|
||||
const union = z.union([z.string(), z.number()]);
|
||||
union.options[0].parse("asdf");
|
||||
union.options[1].parse(1234);
|
||||
await union.options[0].parseAsync("asdf");
|
||||
await union.options[1].parseAsync(1234);
|
||||
});
|
||||
|
||||
test("readonly union", async () => {
|
||||
const options = [z.string(), z.number()] as const;
|
||||
const union = z.union(options);
|
||||
union.parse("asdf");
|
||||
union.parse(12);
|
||||
});
|
||||
|
||||
test("union inferred types", () => {
|
||||
const test = z.object({}).or(z.array(z.object({})));
|
||||
|
||||
type Test = z.output<typeof test>; // <— any
|
||||
expectTypeOf<Test>().toEqualTypeOf<Record<string, never> | Array<Record<string, never>>>();
|
||||
});
|
||||
|
||||
test("union values", () => {
|
||||
const schema = z.union([z.literal("a"), z.literal("b"), z.literal("c")]);
|
||||
|
||||
expect(schema._zod.values).toMatchInlineSnapshot(`
|
||||
Set {
|
||||
"a",
|
||||
"b",
|
||||
"c",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("non-aborted errors", () => {
|
||||
const zItemTest = z.union([
|
||||
z.object({
|
||||
date: z.number(),
|
||||
startDate: z.optional(z.null()),
|
||||
endDate: z.optional(z.null()),
|
||||
}),
|
||||
z
|
||||
.object({
|
||||
date: z.optional(z.null()),
|
||||
startDate: z.number(),
|
||||
endDate: z.number(),
|
||||
})
|
||||
.refine((data) => data.startDate !== data.endDate, {
|
||||
error: "startDate and endDate must be different",
|
||||
path: ["endDate"],
|
||||
}),
|
||||
]);
|
||||
|
||||
const res = zItemTest.safeParse({
|
||||
date: null,
|
||||
startDate: 1,
|
||||
endDate: 1,
|
||||
});
|
||||
|
||||
expect(res).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "custom",
|
||||
"path": [
|
||||
"endDate"
|
||||
],
|
||||
"message": "startDate and endDate must be different"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test("surface continuable errors only if they exist", () => {
|
||||
const schema = z.union([z.boolean(), z.uuid(), z.jwt()]);
|
||||
|
||||
expect(schema.safeParse("asdf")).toMatchInlineSnapshot(`
|
||||
{
|
||||
"error": [ZodError: [
|
||||
{
|
||||
"code": "invalid_union",
|
||||
"errors": [
|
||||
[
|
||||
{
|
||||
"expected": "boolean",
|
||||
"code": "invalid_type",
|
||||
"path": [],
|
||||
"message": "Invalid input: expected boolean, received string"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"origin": "string",
|
||||
"code": "invalid_format",
|
||||
"format": "uuid",
|
||||
"pattern": "/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/",
|
||||
"path": [],
|
||||
"message": "Invalid UUID"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"code": "invalid_format",
|
||||
"format": "jwt",
|
||||
"path": [],
|
||||
"message": "Invalid JWT"
|
||||
}
|
||||
]
|
||||
],
|
||||
"path": [],
|
||||
"message": "Invalid input"
|
||||
}
|
||||
]],
|
||||
"success": false,
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
// z.xor() tests
|
||||
test("z.xor() - exactly one match succeeds", () => {
|
||||
const schema = z.xor([z.string(), z.number()]);
|
||||
expect(schema.parse("hello")).toBe("hello");
|
||||
expect(schema.parse(42)).toBe(42);
|
||||
});
|
||||
|
||||
test("z.xor() - zero matches fails", () => {
|
||||
const schema = z.xor([z.string(), z.number()]);
|
||||
const result = schema.safeParse(true);
|
||||
expect(result.success).toBe(false);
|
||||
});
|
||||
|
||||
test("z.xor() - multiple matches fails", () => {
|
||||
const schema = z.xor([z.string(), z.any()]);
|
||||
const result = schema.safeParse("hello");
|
||||
expect(result.success).toBe(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues[0].code).toBe("invalid_union");
|
||||
expect((result.error.issues[0] as any).inclusive).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
test("z.xor() with custom error message", () => {
|
||||
const schema = z.xor([z.string(), z.number()], "Expected exactly one of string or number");
|
||||
const result = schema.safeParse(true);
|
||||
expect(result.success).toBe(false);
|
||||
if (!result.success) {
|
||||
expect(result.error.issues[0].message).toBe("Expected exactly one of string or number");
|
||||
}
|
||||
});
|
||||
|
||||
test("z.xor() type inference", () => {
|
||||
const schema = z.xor([z.string(), z.number(), z.boolean()]);
|
||||
type Result = z.infer<typeof schema>;
|
||||
expectTypeOf<Result>().toEqualTypeOf<string | number | boolean>();
|
||||
});
|
||||
13
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/url.test.ts
generated
vendored
Normal file
13
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/url.test.ts
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("type inference", () => {
|
||||
const schema = z.string().array();
|
||||
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<string[]>();
|
||||
});
|
||||
|
||||
test("url regex", () => {
|
||||
expect((z.url({ hostname: /^example\.com$/ }).safeParse("http://example.org/").error?.issues[0] as any).pattern).toBe(
|
||||
"^example\\.com$"
|
||||
);
|
||||
});
|
||||
283
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/validations.test.ts
generated
vendored
Normal file
283
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/validations.test.ts
generated
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
import { expect, test } from "vitest";
|
||||
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("string length", async () => {
|
||||
try {
|
||||
await z.string().length(4).parseAsync("asd");
|
||||
} catch (err) {
|
||||
// ("String must contain exactly 4 character(s)");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"exact": true,
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected string to have >=4 characters",
|
||||
"minimum": 4,
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
|
||||
try {
|
||||
await z.string().length(4).parseAsync("asdaa");
|
||||
} catch (err) {
|
||||
// ("String must contain exactly 4 character(s)");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"exact": true,
|
||||
"inclusive": true,
|
||||
"maximum": 4,
|
||||
"message": "Too big: expected string to have <=4 characters",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("string min/max", async () => {
|
||||
try {
|
||||
await z.string().min(4).parseAsync("asd");
|
||||
} catch (err) {
|
||||
// ("String must contain at least 4 character(s)");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected string to have >=4 characters",
|
||||
"minimum": 4,
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("string max", async () => {
|
||||
try {
|
||||
await z.string().max(4).parseAsync("aasdfsdfsd");
|
||||
} catch (err) {
|
||||
// ("String must contain at most 4 character(s)");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 4,
|
||||
"message": "Too big: expected string to have <=4 characters",
|
||||
"origin": "string",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number min", async () => {
|
||||
try {
|
||||
await z.number().min(3).parseAsync(2);
|
||||
} catch (err) {
|
||||
// ("Number must be greater than or equal to 3");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected number to be >=3",
|
||||
"minimum": 3,
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number gte", async () => {
|
||||
try {
|
||||
await z.number().gte(3).parseAsync(2);
|
||||
} catch (err) {
|
||||
// ("Number must be greater than or equal to 3");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected number to be >=3",
|
||||
"minimum": 3,
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number gt", async () => {
|
||||
try {
|
||||
await z.number().gt(3).parseAsync(3);
|
||||
} catch (err) {
|
||||
// ("Number must be greater than or equal to 3");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": false,
|
||||
"message": "Too small: expected number to be >3",
|
||||
"minimum": 3,
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number max", async () => {
|
||||
try {
|
||||
await z.number().max(3).parseAsync(4);
|
||||
} catch (err) {
|
||||
// ("Number must be less than or equal to 3");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 3,
|
||||
"message": "Too big: expected number to be <=3",
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number lte", async () => {
|
||||
try {
|
||||
await z.number().lte(3).parseAsync(4);
|
||||
} catch (err) {
|
||||
// ("Number must be less than or equal to 3");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 3,
|
||||
"message": "Too big: expected number to be <=3",
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number lt", async () => {
|
||||
try {
|
||||
await z.number().lt(3).parseAsync(3);
|
||||
} catch (err) {
|
||||
// ("Number must be less than or equal to 3");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": false,
|
||||
"maximum": 3,
|
||||
"message": "Too big: expected number to be <3",
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number nonnegative", async () => {
|
||||
try {
|
||||
await z.number().nonnegative().parseAsync(-1);
|
||||
} catch (err) {
|
||||
// ("Number must be greater than or equal to 0");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": true,
|
||||
"message": "Too small: expected number to be >=0",
|
||||
"minimum": 0,
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number nonpositive", async () => {
|
||||
try {
|
||||
await z.number().nonpositive().parseAsync(1);
|
||||
} catch (err) {
|
||||
// ("Number must be less than or equal to 0");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": true,
|
||||
"maximum": 0,
|
||||
"message": "Too big: expected number to be <=0",
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number negative", async () => {
|
||||
try {
|
||||
await z.number().negative().parseAsync(1);
|
||||
} catch (err) {
|
||||
// ("Number must be less than 0");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_big",
|
||||
"inclusive": false,
|
||||
"maximum": 0,
|
||||
"message": "Too big: expected number to be <0",
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
|
||||
test("number positive", async () => {
|
||||
try {
|
||||
await z.number().positive().parseAsync(-1);
|
||||
} catch (err) {
|
||||
// ("Number must be greater than 0");
|
||||
expect((err as z.ZodError).issues).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"code": "too_small",
|
||||
"inclusive": false,
|
||||
"message": "Too small: expected number to be >0",
|
||||
"minimum": 0,
|
||||
"origin": "number",
|
||||
"path": [],
|
||||
},
|
||||
]
|
||||
`);
|
||||
}
|
||||
});
|
||||
12
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/void.test.ts
generated
vendored
Normal file
12
mcp-server-ssh/node_modules/zod/src/v4/classic/tests/void.test.ts
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
test("void", () => {
|
||||
const v = z.void();
|
||||
v.parse(undefined);
|
||||
|
||||
expect(() => v.parse(null)).toThrow();
|
||||
expect(() => v.parse("")).toThrow();
|
||||
|
||||
type v = z.infer<typeof v>;
|
||||
expectTypeOf<v>().toEqualTypeOf<void>();
|
||||
});
|
||||
1798
mcp-server-ssh/node_modules/zod/src/v4/core/api.ts
generated
vendored
Normal file
1798
mcp-server-ssh/node_modules/zod/src/v4/core/api.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1293
mcp-server-ssh/node_modules/zod/src/v4/core/checks.ts
generated
vendored
Normal file
1293
mcp-server-ssh/node_modules/zod/src/v4/core/checks.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
15
mcp-server-ssh/node_modules/zod/src/v4/core/config.ts
generated
vendored
Normal file
15
mcp-server-ssh/node_modules/zod/src/v4/core/config.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import type * as errors from "./errors.js";
|
||||
|
||||
export interface $ZodConfig {
|
||||
/** Custom error map. Overrides `config().localeError`. */
|
||||
customError?: errors.$ZodErrorMap | undefined;
|
||||
/** Localized error map. Lowest priority. */
|
||||
localeError?: errors.$ZodErrorMap | undefined;
|
||||
}
|
||||
|
||||
export const globalConfig: $ZodConfig = {};
|
||||
|
||||
export function config(config?: Partial<$ZodConfig>): $ZodConfig {
|
||||
if (config) Object.assign(globalConfig, config);
|
||||
return globalConfig;
|
||||
}
|
||||
138
mcp-server-ssh/node_modules/zod/src/v4/core/core.ts
generated
vendored
Normal file
138
mcp-server-ssh/node_modules/zod/src/v4/core/core.ts
generated
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
import type * as errors from "./errors.js";
|
||||
import type * as schemas from "./schemas.js";
|
||||
import type { Class } from "./util.js";
|
||||
////////////////////////////// CONSTRUCTORS ///////////////////////////////////////
|
||||
|
||||
type ZodTrait = { _zod: { def: any; [k: string]: any } };
|
||||
export interface $constructor<T extends ZodTrait, D = T["_zod"]["def"]> {
|
||||
new (def: D): T;
|
||||
init(inst: T, def: D): asserts inst is T;
|
||||
}
|
||||
|
||||
/** A special constant with type `never` */
|
||||
export const NEVER: never = Object.freeze({
|
||||
status: "aborted",
|
||||
}) as never;
|
||||
|
||||
export /*@__NO_SIDE_EFFECTS__*/ function $constructor<T extends ZodTrait, D = T["_zod"]["def"]>(
|
||||
name: string,
|
||||
initializer: (inst: T, def: D) => void,
|
||||
params?: { Parent?: typeof Class }
|
||||
): $constructor<T, D> {
|
||||
function init(inst: T, def: D) {
|
||||
if (!inst._zod) {
|
||||
Object.defineProperty(inst, "_zod", {
|
||||
value: {
|
||||
def,
|
||||
constr: _,
|
||||
traits: new Set(),
|
||||
},
|
||||
enumerable: false,
|
||||
});
|
||||
}
|
||||
|
||||
if (inst._zod.traits.has(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
inst._zod.traits.add(name);
|
||||
|
||||
initializer(inst, def);
|
||||
|
||||
// support prototype modifications
|
||||
const proto = _.prototype;
|
||||
const keys = Object.keys(proto);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const k = keys[i]!;
|
||||
if (!(k in inst)) {
|
||||
(inst as any)[k] = proto[k].bind(inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// doesn't work if Parent has a constructor with arguments
|
||||
const Parent = params?.Parent ?? Object;
|
||||
class Definition extends Parent {}
|
||||
Object.defineProperty(Definition, "name", { value: name });
|
||||
|
||||
function _(this: any, def: D) {
|
||||
const inst = params?.Parent ? new Definition() : this;
|
||||
init(inst, def);
|
||||
inst._zod.deferred ??= [];
|
||||
for (const fn of inst._zod.deferred) {
|
||||
fn();
|
||||
}
|
||||
return inst;
|
||||
}
|
||||
|
||||
Object.defineProperty(_, "init", { value: init });
|
||||
Object.defineProperty(_, Symbol.hasInstance, {
|
||||
value: (inst: any) => {
|
||||
if (params?.Parent && inst instanceof params.Parent) return true;
|
||||
return inst?._zod?.traits?.has(name);
|
||||
},
|
||||
});
|
||||
Object.defineProperty(_, "name", { value: name });
|
||||
return _ as any;
|
||||
}
|
||||
|
||||
////////////////////////////// UTILITIES ///////////////////////////////////////
|
||||
export const $brand: unique symbol = Symbol("zod_brand");
|
||||
export type $brand<T extends string | number | symbol = string | number | symbol> = {
|
||||
[$brand]: { [k in T]: true };
|
||||
};
|
||||
|
||||
export type $ZodBranded<
|
||||
T extends schemas.SomeType,
|
||||
Brand extends string | number | symbol,
|
||||
Dir extends "in" | "out" | "inout" = "out",
|
||||
> = T &
|
||||
(Dir extends "inout"
|
||||
? { _zod: { input: input<T> & $brand<Brand>; output: output<T> & $brand<Brand> } }
|
||||
: Dir extends "in"
|
||||
? { _zod: { input: input<T> & $brand<Brand> } }
|
||||
: { _zod: { output: output<T> & $brand<Brand> } });
|
||||
|
||||
export type $ZodNarrow<T extends schemas.SomeType, Out> = T & { _zod: { output: Out } };
|
||||
|
||||
export class $ZodAsyncError extends Error {
|
||||
constructor() {
|
||||
super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
|
||||
}
|
||||
}
|
||||
|
||||
export class $ZodEncodeError extends Error {
|
||||
constructor(name: string) {
|
||||
super(`Encountered unidirectional transform during encode: ${name}`);
|
||||
this.name = "ZodEncodeError";
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////// TYPE HELPERS ///////////////////////////////////
|
||||
|
||||
// export type input<T extends schemas.$ZodType> = T["_zod"]["input"];
|
||||
// export type output<T extends schemas.$ZodType> = T["_zod"]["output"];
|
||||
// export type input<T extends schemas.$ZodType> = T["_zod"]["input"];
|
||||
// export type output<T extends schemas.$ZodType> = T["_zod"]["output"];
|
||||
export type input<T> = T extends { _zod: { input: any } } ? T["_zod"]["input"] : unknown;
|
||||
export type output<T> = T extends { _zod: { output: any } } ? T["_zod"]["output"] : unknown;
|
||||
|
||||
export type { output as infer };
|
||||
|
||||
////////////////////////////// CONFIG ///////////////////////////////////////
|
||||
|
||||
export interface $ZodConfig {
|
||||
/** Custom error map. Overrides `config().localeError`. */
|
||||
customError?: errors.$ZodErrorMap | undefined;
|
||||
/** Localized error map. Lowest priority. */
|
||||
localeError?: errors.$ZodErrorMap | undefined;
|
||||
/** Disable JIT schema compilation. Useful in environments that disallow `eval`. */
|
||||
jitless?: boolean | undefined;
|
||||
}
|
||||
|
||||
export const globalConfig: $ZodConfig = {};
|
||||
|
||||
export function config(newConfig?: Partial<$ZodConfig>): $ZodConfig {
|
||||
if (newConfig) Object.assign(globalConfig, newConfig);
|
||||
return globalConfig;
|
||||
}
|
||||
44
mcp-server-ssh/node_modules/zod/src/v4/core/doc.ts
generated
vendored
Normal file
44
mcp-server-ssh/node_modules/zod/src/v4/core/doc.ts
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
type ModeWriter = (doc: Doc, modes: { execution: "sync" | "async" }) => void;
|
||||
|
||||
export class Doc {
|
||||
args!: string[];
|
||||
content: string[] = [];
|
||||
indent = 0;
|
||||
|
||||
constructor(args: string[] = []) {
|
||||
if (this) this.args = args;
|
||||
}
|
||||
|
||||
indented(fn: (doc: Doc) => void) {
|
||||
this.indent += 1;
|
||||
fn(this);
|
||||
this.indent -= 1;
|
||||
}
|
||||
|
||||
write(fn: ModeWriter): void;
|
||||
write(line: string): void;
|
||||
write(arg: any) {
|
||||
if (typeof arg === "function") {
|
||||
(arg as ModeWriter)(this, { execution: "sync" });
|
||||
(arg as ModeWriter)(this, { execution: "async" });
|
||||
return;
|
||||
}
|
||||
|
||||
const content = arg as string;
|
||||
const lines = content.split("\n").filter((x) => x);
|
||||
const minIndent = Math.min(...lines.map((x) => x.length - x.trimStart().length));
|
||||
const dedented = lines.map((x) => x.slice(minIndent)).map((x) => " ".repeat(this.indent * 2) + x);
|
||||
for (const line of dedented) {
|
||||
this.content.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
compile(): any {
|
||||
const F = Function;
|
||||
const args = this?.args;
|
||||
const content = this?.content ?? [``];
|
||||
const lines = [...content.map((x) => ` ${x}`)];
|
||||
// console.log(lines.join("\n"));
|
||||
return new F(...args, lines.join("\n")) as any;
|
||||
}
|
||||
}
|
||||
448
mcp-server-ssh/node_modules/zod/src/v4/core/errors.ts
generated
vendored
Normal file
448
mcp-server-ssh/node_modules/zod/src/v4/core/errors.ts
generated
vendored
Normal file
@@ -0,0 +1,448 @@
|
||||
import type { $ZodCheck, $ZodStringFormats } from "./checks.js";
|
||||
import { $constructor } from "./core.js";
|
||||
import type { $ZodType } from "./schemas.js";
|
||||
import type { StandardSchemaV1 } from "./standard-schema.js";
|
||||
import * as util from "./util.js";
|
||||
|
||||
///////////////////////////
|
||||
//// base type ////
|
||||
///////////////////////////
|
||||
export interface $ZodIssueBase {
|
||||
readonly code?: string;
|
||||
readonly input?: unknown;
|
||||
readonly path: PropertyKey[];
|
||||
readonly message: string;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//// issue subtypes ////
|
||||
////////////////////////////////
|
||||
export type $ZodInvalidTypeExpected =
|
||||
| "string"
|
||||
| "number"
|
||||
| "int"
|
||||
| "boolean"
|
||||
| "bigint"
|
||||
| "symbol"
|
||||
| "undefined"
|
||||
| "null"
|
||||
| "never"
|
||||
| "void"
|
||||
| "date"
|
||||
| "array"
|
||||
| "object"
|
||||
| "tuple"
|
||||
| "record"
|
||||
| "map"
|
||||
| "set"
|
||||
| "file"
|
||||
| "nonoptional"
|
||||
| "nan"
|
||||
| "function"
|
||||
| (string & {}); // class names for instanceof
|
||||
|
||||
export interface $ZodIssueInvalidType<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "invalid_type";
|
||||
readonly expected: $ZodInvalidTypeExpected;
|
||||
readonly input?: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueTooBig<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "too_big";
|
||||
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
|
||||
readonly maximum: number | bigint;
|
||||
readonly inclusive?: boolean;
|
||||
readonly exact?: boolean;
|
||||
readonly input?: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueTooSmall<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "too_small";
|
||||
readonly origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file" | (string & {});
|
||||
readonly minimum: number | bigint;
|
||||
/** True if the allowable range includes the minimum */
|
||||
readonly inclusive?: boolean;
|
||||
/** True if the allowed value is fixed (e.g.` z.length(5)`), not a range (`z.minLength(5)`) */
|
||||
readonly exact?: boolean;
|
||||
readonly input?: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueInvalidStringFormat extends $ZodIssueBase {
|
||||
readonly code: "invalid_format";
|
||||
readonly format: $ZodStringFormats | (string & {});
|
||||
readonly pattern?: string;
|
||||
readonly input?: string;
|
||||
}
|
||||
|
||||
export interface $ZodIssueNotMultipleOf<Input extends number | bigint = number | bigint> extends $ZodIssueBase {
|
||||
readonly code: "not_multiple_of";
|
||||
readonly divisor: number;
|
||||
readonly input?: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueUnrecognizedKeys extends $ZodIssueBase {
|
||||
readonly code: "unrecognized_keys";
|
||||
readonly keys: string[];
|
||||
readonly input?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
interface $ZodIssueInvalidUnionNoMatch extends $ZodIssueBase {
|
||||
readonly code: "invalid_union";
|
||||
readonly errors: $ZodIssue[][];
|
||||
readonly input?: unknown;
|
||||
readonly discriminator?: string | undefined;
|
||||
readonly inclusive?: true;
|
||||
}
|
||||
|
||||
interface $ZodIssueInvalidUnionMultipleMatch extends $ZodIssueBase {
|
||||
readonly code: "invalid_union";
|
||||
readonly errors: [];
|
||||
readonly input?: unknown;
|
||||
readonly discriminator?: string | undefined;
|
||||
readonly inclusive: false;
|
||||
}
|
||||
|
||||
export type $ZodIssueInvalidUnion = $ZodIssueInvalidUnionNoMatch | $ZodIssueInvalidUnionMultipleMatch;
|
||||
|
||||
export interface $ZodIssueInvalidKey<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "invalid_key";
|
||||
readonly origin: "map" | "record";
|
||||
readonly issues: $ZodIssue[];
|
||||
readonly input?: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueInvalidElement<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "invalid_element";
|
||||
readonly origin: "map" | "set";
|
||||
readonly key: unknown;
|
||||
readonly issues: $ZodIssue[];
|
||||
readonly input?: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueInvalidValue<Input = unknown> extends $ZodIssueBase {
|
||||
readonly code: "invalid_value";
|
||||
readonly values: util.Primitive[];
|
||||
readonly input?: Input;
|
||||
}
|
||||
|
||||
export interface $ZodIssueCustom extends $ZodIssueBase {
|
||||
readonly code: "custom";
|
||||
readonly params?: Record<string, any> | undefined;
|
||||
readonly input?: unknown;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
//// first-party string formats ////
|
||||
////////////////////////////////////////////
|
||||
|
||||
export interface $ZodIssueStringCommonFormats extends $ZodIssueInvalidStringFormat {
|
||||
format: Exclude<$ZodStringFormats, "regex" | "jwt" | "starts_with" | "ends_with" | "includes">;
|
||||
}
|
||||
|
||||
export interface $ZodIssueStringInvalidRegex extends $ZodIssueInvalidStringFormat {
|
||||
format: "regex";
|
||||
pattern: string;
|
||||
}
|
||||
|
||||
export interface $ZodIssueStringInvalidJWT extends $ZodIssueInvalidStringFormat {
|
||||
format: "jwt";
|
||||
algorithm?: string;
|
||||
}
|
||||
|
||||
export interface $ZodIssueStringStartsWith extends $ZodIssueInvalidStringFormat {
|
||||
format: "starts_with";
|
||||
prefix: string;
|
||||
}
|
||||
|
||||
export interface $ZodIssueStringEndsWith extends $ZodIssueInvalidStringFormat {
|
||||
format: "ends_with";
|
||||
suffix: string;
|
||||
}
|
||||
|
||||
export interface $ZodIssueStringIncludes extends $ZodIssueInvalidStringFormat {
|
||||
format: "includes";
|
||||
includes: string;
|
||||
}
|
||||
|
||||
export type $ZodStringFormatIssues =
|
||||
| $ZodIssueStringCommonFormats
|
||||
| $ZodIssueStringInvalidRegex
|
||||
| $ZodIssueStringInvalidJWT
|
||||
| $ZodIssueStringStartsWith
|
||||
| $ZodIssueStringEndsWith
|
||||
| $ZodIssueStringIncludes;
|
||||
|
||||
////////////////////////
|
||||
//// utils /////
|
||||
////////////////////////
|
||||
|
||||
export type $ZodIssue =
|
||||
| $ZodIssueInvalidType
|
||||
| $ZodIssueTooBig
|
||||
| $ZodIssueTooSmall
|
||||
| $ZodIssueInvalidStringFormat
|
||||
| $ZodIssueNotMultipleOf
|
||||
| $ZodIssueUnrecognizedKeys
|
||||
| $ZodIssueInvalidUnion
|
||||
| $ZodIssueInvalidKey
|
||||
| $ZodIssueInvalidElement
|
||||
| $ZodIssueInvalidValue
|
||||
| $ZodIssueCustom;
|
||||
|
||||
export type $ZodIssueCode = $ZodIssue["code"];
|
||||
|
||||
export type $ZodInternalIssue<T extends $ZodIssueBase = $ZodIssue> = T extends any ? RawIssue<T> : never;
|
||||
type RawIssue<T extends $ZodIssueBase> = T extends any
|
||||
? util.Flatten<
|
||||
util.MakePartial<T, "message" | "path"> & {
|
||||
/** The input data */
|
||||
readonly input: unknown;
|
||||
/** The schema or check that originated this issue. */
|
||||
readonly inst?: $ZodType | $ZodCheck;
|
||||
/** If `true`, Zod will continue executing checks/refinements after this issue. */
|
||||
readonly continue?: boolean | undefined;
|
||||
} & Record<string, unknown>
|
||||
>
|
||||
: never;
|
||||
|
||||
export type $ZodRawIssue<T extends $ZodIssueBase = $ZodIssue> = $ZodInternalIssue<T>;
|
||||
|
||||
export interface $ZodErrorMap<T extends $ZodIssueBase = $ZodIssue> {
|
||||
// biome-ignore lint:
|
||||
(issue: $ZodRawIssue<T>): { message: string } | string | undefined | null;
|
||||
}
|
||||
|
||||
//////////////////////// ERROR CLASS ////////////////////////
|
||||
|
||||
// const ZOD_ERROR: symbol = Symbol.for("{{zod.error}}");
|
||||
export interface $ZodError<T = unknown> extends Error {
|
||||
type: T;
|
||||
issues: $ZodIssue[];
|
||||
_zod: {
|
||||
output: T;
|
||||
def: $ZodIssue[];
|
||||
};
|
||||
stack?: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
const initializer = (inst: $ZodError, def: $ZodIssue[]): void => {
|
||||
inst.name = "$ZodError";
|
||||
Object.defineProperty(inst, "_zod", {
|
||||
value: inst._zod,
|
||||
enumerable: false,
|
||||
});
|
||||
Object.defineProperty(inst, "issues", {
|
||||
value: def,
|
||||
enumerable: false,
|
||||
});
|
||||
inst.message = JSON.stringify(def, util.jsonStringifyReplacer, 2);
|
||||
|
||||
Object.defineProperty(inst, "toString", {
|
||||
value: () => inst.message,
|
||||
enumerable: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const $ZodError: $constructor<$ZodError> = $constructor("$ZodError", initializer);
|
||||
interface $ZodRealError<T = any> extends $ZodError<T> {}
|
||||
export const $ZodRealError: $constructor<$ZodRealError> = $constructor("$ZodError", initializer, { Parent: Error });
|
||||
|
||||
/////////////////// ERROR UTILITIES ////////////////////////
|
||||
|
||||
// flatten
|
||||
export type $ZodFlattenedError<T, U = string> = _FlattenedError<T, U>;
|
||||
type _FlattenedError<T, U = string> = {
|
||||
formErrors: U[];
|
||||
fieldErrors: {
|
||||
[P in keyof T]?: U[];
|
||||
};
|
||||
};
|
||||
|
||||
export function flattenError<T>(error: $ZodError<T>): _FlattenedError<T>;
|
||||
export function flattenError<T, U>(error: $ZodError<T>, mapper?: (issue: $ZodIssue) => U): _FlattenedError<T, U>;
|
||||
export function flattenError<T, U>(error: $ZodError<T>, mapper = (issue: $ZodIssue) => issue.message as U) {
|
||||
const fieldErrors: Record<PropertyKey, any> = {};
|
||||
const formErrors: U[] = [];
|
||||
for (const sub of error.issues) {
|
||||
if (sub.path.length > 0) {
|
||||
fieldErrors[sub.path[0]!] = fieldErrors[sub.path[0]!] || [];
|
||||
fieldErrors[sub.path[0]!].push(mapper(sub));
|
||||
} else {
|
||||
formErrors.push(mapper(sub));
|
||||
}
|
||||
}
|
||||
return { formErrors, fieldErrors };
|
||||
}
|
||||
|
||||
type _ZodFormattedError<T, U = string> = T extends [any, ...any[]]
|
||||
? { [K in keyof T]?: $ZodFormattedError<T[K], U> }
|
||||
: T extends any[]
|
||||
? { [k: number]: $ZodFormattedError<T[number], U> }
|
||||
: T extends object
|
||||
? util.Flatten<{ [K in keyof T]?: $ZodFormattedError<T[K], U> }>
|
||||
: any;
|
||||
|
||||
export type $ZodFormattedError<T, U = string> = {
|
||||
_errors: U[];
|
||||
} & util.Flatten<_ZodFormattedError<T, U>>;
|
||||
|
||||
export function formatError<T>(error: $ZodError<T>): $ZodFormattedError<T>;
|
||||
export function formatError<T, U>(error: $ZodError<T>, mapper?: (issue: $ZodIssue) => U): $ZodFormattedError<T, U>;
|
||||
export function formatError<T, U>(error: $ZodError<T>, mapper = (issue: $ZodIssue) => issue.message as U) {
|
||||
const fieldErrors: $ZodFormattedError<T> = { _errors: [] } as any;
|
||||
const processError = (error: { issues: $ZodIssue[] }) => {
|
||||
for (const issue of error.issues) {
|
||||
if (issue.code === "invalid_union" && issue.errors.length) {
|
||||
issue.errors.map((issues) => processError({ issues }));
|
||||
} else if (issue.code === "invalid_key") {
|
||||
processError({ issues: issue.issues });
|
||||
} else if (issue.code === "invalid_element") {
|
||||
processError({ issues: issue.issues });
|
||||
} else if (issue.path.length === 0) {
|
||||
(fieldErrors as any)._errors.push(mapper(issue));
|
||||
} else {
|
||||
let curr: any = fieldErrors;
|
||||
let i = 0;
|
||||
while (i < issue.path.length) {
|
||||
const el = issue.path[i]!;
|
||||
const terminal = i === issue.path.length - 1;
|
||||
|
||||
if (!terminal) {
|
||||
curr[el] = curr[el] || { _errors: [] };
|
||||
} else {
|
||||
curr[el] = curr[el] || { _errors: [] };
|
||||
curr[el]._errors.push(mapper(issue));
|
||||
}
|
||||
|
||||
curr = curr[el];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
processError(error);
|
||||
return fieldErrors;
|
||||
}
|
||||
|
||||
export type $ZodErrorTree<T, U = string> = T extends util.Primitive
|
||||
? { errors: U[] }
|
||||
: T extends [any, ...any[]]
|
||||
? { errors: U[]; items?: { [K in keyof T]?: $ZodErrorTree<T[K], U> } }
|
||||
: T extends any[]
|
||||
? { errors: U[]; items?: Array<$ZodErrorTree<T[number], U>> }
|
||||
: T extends object
|
||||
? { errors: U[]; properties?: { [K in keyof T]?: $ZodErrorTree<T[K], U> } }
|
||||
: { errors: U[] };
|
||||
|
||||
export function treeifyError<T>(error: $ZodError<T>): $ZodErrorTree<T>;
|
||||
export function treeifyError<T, U>(error: $ZodError<T>, mapper?: (issue: $ZodIssue) => U): $ZodErrorTree<T, U>;
|
||||
export function treeifyError<T, U>(error: $ZodError<T>, mapper = (issue: $ZodIssue) => issue.message as U) {
|
||||
const result: $ZodErrorTree<T, U> = { errors: [] } as any;
|
||||
const processError = (error: { issues: $ZodIssue[] }, path: PropertyKey[] = []) => {
|
||||
for (const issue of error.issues) {
|
||||
if (issue.code === "invalid_union" && issue.errors.length) {
|
||||
// regular union error
|
||||
issue.errors.map((issues) => processError({ issues }, issue.path));
|
||||
} else if (issue.code === "invalid_key") {
|
||||
processError({ issues: issue.issues }, issue.path);
|
||||
} else if (issue.code === "invalid_element") {
|
||||
processError({ issues: issue.issues }, issue.path);
|
||||
} else {
|
||||
const fullpath = [...path, ...issue.path];
|
||||
if (fullpath.length === 0) {
|
||||
result.errors.push(mapper(issue));
|
||||
continue;
|
||||
}
|
||||
|
||||
let curr: any = result;
|
||||
let i = 0;
|
||||
while (i < fullpath.length) {
|
||||
const el = fullpath[i]!;
|
||||
|
||||
const terminal = i === fullpath.length - 1;
|
||||
if (typeof el === "string") {
|
||||
curr.properties ??= {};
|
||||
curr.properties[el] ??= { errors: [] };
|
||||
curr = curr.properties[el];
|
||||
} else {
|
||||
curr.items ??= [];
|
||||
curr.items[el] ??= { errors: [] };
|
||||
curr = curr.items[el];
|
||||
}
|
||||
|
||||
if (terminal) {
|
||||
curr.errors.push(mapper(issue));
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
processError(error);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Format a ZodError as a human-readable string in the following form.
|
||||
*
|
||||
* From
|
||||
*
|
||||
* ```ts
|
||||
* ZodError {
|
||||
* issues: [
|
||||
* {
|
||||
* expected: 'string',
|
||||
* code: 'invalid_type',
|
||||
* path: [ 'username' ],
|
||||
* message: 'Invalid input: expected string'
|
||||
* },
|
||||
* {
|
||||
* expected: 'number',
|
||||
* code: 'invalid_type',
|
||||
* path: [ 'favoriteNumbers', 1 ],
|
||||
* message: 'Invalid input: expected number'
|
||||
* }
|
||||
* ];
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* to
|
||||
*
|
||||
* ```
|
||||
* username
|
||||
* ✖ Expected number, received string at "username
|
||||
* favoriteNumbers[0]
|
||||
* ✖ Invalid input: expected number
|
||||
* ```
|
||||
*/
|
||||
export function toDotPath(_path: readonly (string | number | symbol | StandardSchemaV1.PathSegment)[]): string {
|
||||
const segs: string[] = [];
|
||||
const path: PropertyKey[] = _path.map((seg: any) => (typeof seg === "object" ? seg.key : seg));
|
||||
for (const seg of path) {
|
||||
if (typeof seg === "number") segs.push(`[${seg}]`);
|
||||
else if (typeof seg === "symbol") segs.push(`[${JSON.stringify(String(seg))}]`);
|
||||
else if (/[^\w$]/.test(seg)) segs.push(`[${JSON.stringify(seg)}]`);
|
||||
else {
|
||||
if (segs.length) segs.push(".");
|
||||
segs.push(seg);
|
||||
}
|
||||
}
|
||||
|
||||
return segs.join("");
|
||||
}
|
||||
|
||||
export function prettifyError(error: StandardSchemaV1.FailureResult): string {
|
||||
const lines: string[] = [];
|
||||
// sort by path length
|
||||
const issues = [...error.issues].sort((a, b) => (a.path ?? []).length - (b.path ?? []).length);
|
||||
|
||||
// Process each issue
|
||||
for (const issue of issues) {
|
||||
lines.push(`✖ ${issue.message}`);
|
||||
if (issue.path?.length) lines.push(` → at ${toDotPath(issue.path)}`);
|
||||
}
|
||||
|
||||
// Convert Map to formatted string
|
||||
return lines.join("\n");
|
||||
}
|
||||
16
mcp-server-ssh/node_modules/zod/src/v4/core/index.ts
generated
vendored
Normal file
16
mcp-server-ssh/node_modules/zod/src/v4/core/index.ts
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
export * from "./core.js";
|
||||
export * from "./parse.js";
|
||||
export * from "./errors.js";
|
||||
export * from "./schemas.js";
|
||||
export * from "./checks.js";
|
||||
export * from "./versions.js";
|
||||
export * as util from "./util.js";
|
||||
export * as regexes from "./regexes.js";
|
||||
export * as locales from "../locales/index.js";
|
||||
export * from "./registries.js";
|
||||
export * from "./doc.js";
|
||||
export * from "./api.js";
|
||||
export * from "./to-json-schema.js";
|
||||
export { toJSONSchema } from "./json-schema-processors.js";
|
||||
export { JSONSchemaGenerator } from "./json-schema-generator.js";
|
||||
export * as JSONSchema from "./json-schema.js";
|
||||
126
mcp-server-ssh/node_modules/zod/src/v4/core/json-schema-generator.ts
generated
vendored
Normal file
126
mcp-server-ssh/node_modules/zod/src/v4/core/json-schema-generator.ts
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
import { allProcessors } from "./json-schema-processors.js";
|
||||
import type * as JSONSchema from "./json-schema.js";
|
||||
import type { $ZodRegistry } from "./registries.js";
|
||||
import type * as schemas from "./schemas.js";
|
||||
import {
|
||||
type JSONSchemaGeneratorParams,
|
||||
type ProcessParams,
|
||||
type Seen,
|
||||
type ToJSONSchemaContext,
|
||||
extractDefs,
|
||||
finalize,
|
||||
initializeContext,
|
||||
process,
|
||||
} from "./to-json-schema.js";
|
||||
|
||||
/**
|
||||
* Parameters for the emit method of JSONSchemaGenerator.
|
||||
* @deprecated Use toJSONSchema function instead
|
||||
*/
|
||||
export type EmitParams = Pick<JSONSchemaGeneratorParams, "cycles" | "reused" | "external">;
|
||||
|
||||
/**
|
||||
* Parameters for JSONSchemaGenerator constructor.
|
||||
* @deprecated Use toJSONSchema function instead
|
||||
*/
|
||||
type JSONSchemaGeneratorConstructorParams = Pick<
|
||||
JSONSchemaGeneratorParams,
|
||||
"metadata" | "target" | "unrepresentable" | "override" | "io"
|
||||
>;
|
||||
|
||||
/**
|
||||
* Legacy class-based interface for JSON Schema generation.
|
||||
* This class wraps the new functional implementation to provide backward compatibility.
|
||||
*
|
||||
* @deprecated Use the `toJSONSchema` function instead for new code.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // Legacy usage (still supported)
|
||||
* const gen = new JSONSchemaGenerator({ target: "draft-07" });
|
||||
* gen.process(schema);
|
||||
* const result = gen.emit(schema);
|
||||
*
|
||||
* // Preferred modern usage
|
||||
* const result = toJSONSchema(schema, { target: "draft-07" });
|
||||
* ```
|
||||
*/
|
||||
export class JSONSchemaGenerator {
|
||||
private ctx: ToJSONSchemaContext;
|
||||
|
||||
/** @deprecated Access via ctx instead */
|
||||
get metadataRegistry(): $ZodRegistry<Record<string, any>> {
|
||||
return this.ctx.metadataRegistry;
|
||||
}
|
||||
/** @deprecated Access via ctx instead */
|
||||
get target() {
|
||||
return this.ctx.target;
|
||||
}
|
||||
/** @deprecated Access via ctx instead */
|
||||
get unrepresentable() {
|
||||
return this.ctx.unrepresentable;
|
||||
}
|
||||
/** @deprecated Access via ctx instead */
|
||||
get override() {
|
||||
return this.ctx.override;
|
||||
}
|
||||
/** @deprecated Access via ctx instead */
|
||||
get io() {
|
||||
return this.ctx.io;
|
||||
}
|
||||
/** @deprecated Access via ctx instead */
|
||||
get counter() {
|
||||
return this.ctx.counter;
|
||||
}
|
||||
set counter(value: number) {
|
||||
this.ctx.counter = value;
|
||||
}
|
||||
/** @deprecated Access via ctx instead */
|
||||
get seen(): Map<schemas.$ZodType, Seen> {
|
||||
return this.ctx.seen;
|
||||
}
|
||||
|
||||
constructor(params?: JSONSchemaGeneratorConstructorParams) {
|
||||
// Normalize target for internal context
|
||||
let normalizedTarget: ToJSONSchemaContext["target"] = params?.target ?? "draft-2020-12";
|
||||
if (normalizedTarget === "draft-4") normalizedTarget = "draft-04";
|
||||
if (normalizedTarget === "draft-7") normalizedTarget = "draft-07";
|
||||
|
||||
this.ctx = initializeContext({
|
||||
processors: allProcessors,
|
||||
target: normalizedTarget,
|
||||
...(params?.metadata && { metadata: params.metadata }),
|
||||
...(params?.unrepresentable && { unrepresentable: params.unrepresentable }),
|
||||
...(params?.override && { override: params.override as any }),
|
||||
...(params?.io && { io: params.io }),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a schema to prepare it for JSON Schema generation.
|
||||
* This must be called before emit().
|
||||
*/
|
||||
process(schema: schemas.$ZodType, _params: ProcessParams = { path: [], schemaPath: [] }): JSONSchema.BaseSchema {
|
||||
return process(schema, this.ctx, _params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit the final JSON Schema after processing.
|
||||
* Must call process() first.
|
||||
*/
|
||||
emit(schema: schemas.$ZodType, _params?: EmitParams): JSONSchema.BaseSchema {
|
||||
// Apply emit params to the context
|
||||
if (_params) {
|
||||
if (_params.cycles) this.ctx.cycles = _params.cycles;
|
||||
if (_params.reused) this.ctx.reused = _params.reused;
|
||||
if (_params.external) this.ctx.external = _params.external;
|
||||
}
|
||||
|
||||
extractDefs(this.ctx, schema);
|
||||
const result = finalize(this.ctx, schema);
|
||||
|
||||
// Strip ~standard property to match old implementation's return type
|
||||
const { "~standard": _, ...plainResult } = result as any;
|
||||
return plainResult as JSONSchema.BaseSchema;
|
||||
}
|
||||
}
|
||||
667
mcp-server-ssh/node_modules/zod/src/v4/core/json-schema-processors.ts
generated
vendored
Normal file
667
mcp-server-ssh/node_modules/zod/src/v4/core/json-schema-processors.ts
generated
vendored
Normal file
@@ -0,0 +1,667 @@
|
||||
import type * as checks from "./checks.js";
|
||||
import type * as JSONSchema from "./json-schema.js";
|
||||
import type { $ZodRegistry } from "./registries.js";
|
||||
import type * as schemas from "./schemas.js";
|
||||
import {
|
||||
type Processor,
|
||||
type RegistryToJSONSchemaParams,
|
||||
type ToJSONSchemaParams,
|
||||
type ZodStandardJSONSchemaPayload,
|
||||
extractDefs,
|
||||
finalize,
|
||||
initializeContext,
|
||||
process,
|
||||
} from "./to-json-schema.js";
|
||||
import { getEnumValues } from "./util.js";
|
||||
|
||||
const formatMap: Partial<Record<checks.$ZodStringFormats, string | undefined>> = {
|
||||
guid: "uuid",
|
||||
url: "uri",
|
||||
datetime: "date-time",
|
||||
json_string: "json-string",
|
||||
regex: "", // do not set
|
||||
};
|
||||
|
||||
// ==================== SIMPLE TYPE PROCESSORS ====================
|
||||
|
||||
export const stringProcessor: Processor<schemas.$ZodString> = (schema, ctx, _json, _params) => {
|
||||
const json = _json as JSONSchema.StringSchema;
|
||||
json.type = "string";
|
||||
const { minimum, maximum, format, patterns, contentEncoding } = schema._zod
|
||||
.bag as schemas.$ZodStringInternals<unknown>["bag"];
|
||||
if (typeof minimum === "number") json.minLength = minimum;
|
||||
if (typeof maximum === "number") json.maxLength = maximum;
|
||||
// custom pattern overrides format
|
||||
if (format) {
|
||||
json.format = formatMap[format as checks.$ZodStringFormats] ?? format;
|
||||
if (json.format === "") delete json.format; // empty format is not valid
|
||||
|
||||
// JSON Schema format: "time" requires a full time with offset or Z
|
||||
// z.iso.time() does not include timezone information, so format: "time" should never be used
|
||||
if (format === "time") {
|
||||
delete json.format;
|
||||
}
|
||||
}
|
||||
if (contentEncoding) json.contentEncoding = contentEncoding;
|
||||
if (patterns && patterns.size > 0) {
|
||||
const regexes = [...patterns];
|
||||
if (regexes.length === 1) json.pattern = regexes[0]!.source;
|
||||
else if (regexes.length > 1) {
|
||||
json.allOf = [
|
||||
...regexes.map((regex) => ({
|
||||
...(ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0"
|
||||
? ({ type: "string" } as const)
|
||||
: {}),
|
||||
pattern: regex.source,
|
||||
})),
|
||||
];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const numberProcessor: Processor<schemas.$ZodNumber> = (schema, ctx, _json, _params) => {
|
||||
const json = _json as JSONSchema.NumberSchema | JSONSchema.IntegerSchema;
|
||||
const { minimum, maximum, format, multipleOf, exclusiveMaximum, exclusiveMinimum } = schema._zod.bag;
|
||||
if (typeof format === "string" && format.includes("int")) json.type = "integer";
|
||||
else json.type = "number";
|
||||
|
||||
if (typeof exclusiveMinimum === "number") {
|
||||
if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") {
|
||||
json.minimum = exclusiveMinimum;
|
||||
json.exclusiveMinimum = true;
|
||||
} else {
|
||||
json.exclusiveMinimum = exclusiveMinimum;
|
||||
}
|
||||
}
|
||||
if (typeof minimum === "number") {
|
||||
json.minimum = minimum;
|
||||
if (typeof exclusiveMinimum === "number" && ctx.target !== "draft-04") {
|
||||
if (exclusiveMinimum >= minimum) delete json.minimum;
|
||||
else delete json.exclusiveMinimum;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof exclusiveMaximum === "number") {
|
||||
if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") {
|
||||
json.maximum = exclusiveMaximum;
|
||||
json.exclusiveMaximum = true;
|
||||
} else {
|
||||
json.exclusiveMaximum = exclusiveMaximum;
|
||||
}
|
||||
}
|
||||
if (typeof maximum === "number") {
|
||||
json.maximum = maximum;
|
||||
if (typeof exclusiveMaximum === "number" && ctx.target !== "draft-04") {
|
||||
if (exclusiveMaximum <= maximum) delete json.maximum;
|
||||
else delete json.exclusiveMaximum;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof multipleOf === "number") json.multipleOf = multipleOf;
|
||||
};
|
||||
|
||||
export const booleanProcessor: Processor<schemas.$ZodBoolean> = (_schema, _ctx, json, _params) => {
|
||||
(json as JSONSchema.BooleanSchema).type = "boolean";
|
||||
};
|
||||
|
||||
export const bigintProcessor: Processor<schemas.$ZodBigInt> = (_schema, ctx, _json, _params) => {
|
||||
if (ctx.unrepresentable === "throw") {
|
||||
throw new Error("BigInt cannot be represented in JSON Schema");
|
||||
}
|
||||
};
|
||||
|
||||
export const symbolProcessor: Processor<schemas.$ZodSymbol> = (_schema, ctx, _json, _params) => {
|
||||
if (ctx.unrepresentable === "throw") {
|
||||
throw new Error("Symbols cannot be represented in JSON Schema");
|
||||
}
|
||||
};
|
||||
|
||||
export const nullProcessor: Processor<schemas.$ZodNull> = (_schema, ctx, json, _params) => {
|
||||
if (ctx.target === "openapi-3.0") {
|
||||
json.type = "string";
|
||||
json.nullable = true;
|
||||
json.enum = [null];
|
||||
} else {
|
||||
json.type = "null";
|
||||
}
|
||||
};
|
||||
|
||||
export const undefinedProcessor: Processor<schemas.$ZodUndefined> = (_schema, ctx, _json, _params) => {
|
||||
if (ctx.unrepresentable === "throw") {
|
||||
throw new Error("Undefined cannot be represented in JSON Schema");
|
||||
}
|
||||
};
|
||||
|
||||
export const voidProcessor: Processor<schemas.$ZodVoid> = (_schema, ctx, _json, _params) => {
|
||||
if (ctx.unrepresentable === "throw") {
|
||||
throw new Error("Void cannot be represented in JSON Schema");
|
||||
}
|
||||
};
|
||||
|
||||
export const neverProcessor: Processor<schemas.$ZodNever> = (_schema, _ctx, json, _params) => {
|
||||
json.not = {};
|
||||
};
|
||||
|
||||
export const anyProcessor: Processor<schemas.$ZodAny> = (_schema, _ctx, _json, _params) => {
|
||||
// empty schema accepts anything
|
||||
};
|
||||
|
||||
export const unknownProcessor: Processor<schemas.$ZodUnknown> = (_schema, _ctx, _json, _params) => {
|
||||
// empty schema accepts anything
|
||||
};
|
||||
|
||||
export const dateProcessor: Processor<schemas.$ZodDate> = (_schema, ctx, _json, _params) => {
|
||||
if (ctx.unrepresentable === "throw") {
|
||||
throw new Error("Date cannot be represented in JSON Schema");
|
||||
}
|
||||
};
|
||||
|
||||
export const enumProcessor: Processor<schemas.$ZodEnum> = (schema, _ctx, json, _params) => {
|
||||
const def = schema._zod.def as schemas.$ZodEnumDef;
|
||||
const values = getEnumValues(def.entries);
|
||||
// Number enums can have both string and number values
|
||||
if (values.every((v) => typeof v === "number")) json.type = "number";
|
||||
if (values.every((v) => typeof v === "string")) json.type = "string";
|
||||
json.enum = values;
|
||||
};
|
||||
|
||||
export const literalProcessor: Processor<schemas.$ZodLiteral> = (schema, ctx, json, _params) => {
|
||||
const def = schema._zod.def as schemas.$ZodLiteralDef<any>;
|
||||
const vals: (string | number | boolean | null)[] = [];
|
||||
for (const val of def.values) {
|
||||
if (val === undefined) {
|
||||
if (ctx.unrepresentable === "throw") {
|
||||
throw new Error("Literal `undefined` cannot be represented in JSON Schema");
|
||||
} else {
|
||||
// do not add to vals
|
||||
}
|
||||
} else if (typeof val === "bigint") {
|
||||
if (ctx.unrepresentable === "throw") {
|
||||
throw new Error("BigInt literals cannot be represented in JSON Schema");
|
||||
} else {
|
||||
vals.push(Number(val));
|
||||
}
|
||||
} else {
|
||||
vals.push(val);
|
||||
}
|
||||
}
|
||||
if (vals.length === 0) {
|
||||
// do nothing (an undefined literal was stripped)
|
||||
} else if (vals.length === 1) {
|
||||
const val = vals[0]!;
|
||||
json.type = val === null ? ("null" as const) : (typeof val as any);
|
||||
if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") {
|
||||
json.enum = [val];
|
||||
} else {
|
||||
json.const = val;
|
||||
}
|
||||
} else {
|
||||
if (vals.every((v) => typeof v === "number")) json.type = "number";
|
||||
if (vals.every((v) => typeof v === "string")) json.type = "string";
|
||||
if (vals.every((v) => typeof v === "boolean")) json.type = "boolean";
|
||||
if (vals.every((v) => v === null)) json.type = "null";
|
||||
json.enum = vals;
|
||||
}
|
||||
};
|
||||
|
||||
export const nanProcessor: Processor<schemas.$ZodNaN> = (_schema, ctx, _json, _params) => {
|
||||
if (ctx.unrepresentable === "throw") {
|
||||
throw new Error("NaN cannot be represented in JSON Schema");
|
||||
}
|
||||
};
|
||||
|
||||
export const templateLiteralProcessor: Processor<schemas.$ZodTemplateLiteral> = (schema, _ctx, json, _params) => {
|
||||
const _json = json as JSONSchema.StringSchema;
|
||||
const pattern = schema._zod.pattern;
|
||||
if (!pattern) throw new Error("Pattern not found in template literal");
|
||||
_json.type = "string";
|
||||
_json.pattern = pattern.source;
|
||||
};
|
||||
|
||||
export const fileProcessor: Processor<schemas.$ZodFile> = (schema, _ctx, json, _params) => {
|
||||
const _json = json as JSONSchema.StringSchema;
|
||||
const file: JSONSchema.StringSchema = {
|
||||
type: "string",
|
||||
format: "binary",
|
||||
contentEncoding: "binary",
|
||||
};
|
||||
|
||||
const { minimum, maximum, mime } = schema._zod.bag as schemas.$ZodFileInternals["bag"];
|
||||
if (minimum !== undefined) file.minLength = minimum;
|
||||
if (maximum !== undefined) file.maxLength = maximum;
|
||||
if (mime) {
|
||||
if (mime.length === 1) {
|
||||
file.contentMediaType = mime[0]!;
|
||||
Object.assign(_json, file);
|
||||
} else {
|
||||
Object.assign(_json, file); // shared props at root
|
||||
_json.anyOf = mime.map((m) => ({ contentMediaType: m })); // only contentMediaType differs
|
||||
}
|
||||
} else {
|
||||
Object.assign(_json, file);
|
||||
}
|
||||
};
|
||||
|
||||
export const successProcessor: Processor<schemas.$ZodSuccess> = (_schema, _ctx, json, _params) => {
|
||||
(json as JSONSchema.BooleanSchema).type = "boolean";
|
||||
};
|
||||
|
||||
export const customProcessor: Processor<schemas.$ZodCustom> = (_schema, ctx, _json, _params) => {
|
||||
if (ctx.unrepresentable === "throw") {
|
||||
throw new Error("Custom types cannot be represented in JSON Schema");
|
||||
}
|
||||
};
|
||||
|
||||
export const functionProcessor: Processor<schemas.$ZodFunction> = (_schema, ctx, _json, _params) => {
|
||||
if (ctx.unrepresentable === "throw") {
|
||||
throw new Error("Function types cannot be represented in JSON Schema");
|
||||
}
|
||||
};
|
||||
|
||||
export const transformProcessor: Processor<schemas.$ZodTransform> = (_schema, ctx, _json, _params) => {
|
||||
if (ctx.unrepresentable === "throw") {
|
||||
throw new Error("Transforms cannot be represented in JSON Schema");
|
||||
}
|
||||
};
|
||||
|
||||
export const mapProcessor: Processor<schemas.$ZodMap> = (_schema, ctx, _json, _params) => {
|
||||
if (ctx.unrepresentable === "throw") {
|
||||
throw new Error("Map cannot be represented in JSON Schema");
|
||||
}
|
||||
};
|
||||
|
||||
export const setProcessor: Processor<schemas.$ZodSet> = (_schema, ctx, _json, _params) => {
|
||||
if (ctx.unrepresentable === "throw") {
|
||||
throw new Error("Set cannot be represented in JSON Schema");
|
||||
}
|
||||
};
|
||||
|
||||
// ==================== COMPOSITE TYPE PROCESSORS ====================
|
||||
|
||||
export const arrayProcessor: Processor<schemas.$ZodArray> = (schema, ctx, _json, params) => {
|
||||
const json = _json as JSONSchema.ArraySchema;
|
||||
const def = schema._zod.def as schemas.$ZodArrayDef;
|
||||
const { minimum, maximum } = schema._zod.bag;
|
||||
if (typeof minimum === "number") json.minItems = minimum;
|
||||
if (typeof maximum === "number") json.maxItems = maximum;
|
||||
|
||||
json.type = "array";
|
||||
json.items = process(def.element, ctx as any, { ...params, path: [...params.path, "items"] });
|
||||
};
|
||||
|
||||
export const objectProcessor: Processor<schemas.$ZodObject> = (schema, ctx, _json, params) => {
|
||||
const json = _json as JSONSchema.ObjectSchema;
|
||||
const def = schema._zod.def as schemas.$ZodObjectDef;
|
||||
json.type = "object";
|
||||
json.properties = {};
|
||||
const shape = def.shape;
|
||||
|
||||
for (const key in shape) {
|
||||
json.properties[key] = process(shape[key]!, ctx as any, {
|
||||
...params,
|
||||
path: [...params.path, "properties", key],
|
||||
});
|
||||
}
|
||||
|
||||
// required keys
|
||||
const allKeys = new Set(Object.keys(shape));
|
||||
const requiredKeys = new Set(
|
||||
[...allKeys].filter((key) => {
|
||||
const v = def.shape[key]!._zod;
|
||||
if (ctx.io === "input") {
|
||||
return v.optin === undefined;
|
||||
} else {
|
||||
return v.optout === undefined;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
if (requiredKeys.size > 0) {
|
||||
json.required = Array.from(requiredKeys);
|
||||
}
|
||||
|
||||
// catchall
|
||||
if (def.catchall?._zod.def.type === "never") {
|
||||
// strict
|
||||
json.additionalProperties = false;
|
||||
} else if (!def.catchall) {
|
||||
// regular
|
||||
if (ctx.io === "output") json.additionalProperties = false;
|
||||
} else if (def.catchall) {
|
||||
json.additionalProperties = process(def.catchall, ctx as any, {
|
||||
...params,
|
||||
path: [...params.path, "additionalProperties"],
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const unionProcessor: Processor<schemas.$ZodUnion> = (schema, ctx, json, params) => {
|
||||
const def = schema._zod.def as schemas.$ZodUnionDef;
|
||||
// Exclusive unions (inclusive === false) use oneOf (exactly one match) instead of anyOf (one or more matches)
|
||||
// This includes both z.xor() and discriminated unions
|
||||
const isExclusive = def.inclusive === false;
|
||||
const options = def.options.map((x, i) =>
|
||||
process(x, ctx as any, {
|
||||
...params,
|
||||
path: [...params.path, isExclusive ? "oneOf" : "anyOf", i],
|
||||
})
|
||||
);
|
||||
if (isExclusive) {
|
||||
json.oneOf = options;
|
||||
} else {
|
||||
json.anyOf = options;
|
||||
}
|
||||
};
|
||||
|
||||
export const intersectionProcessor: Processor<schemas.$ZodIntersection> = (schema, ctx, json, params) => {
|
||||
const def = schema._zod.def as schemas.$ZodIntersectionDef;
|
||||
const a = process(def.left, ctx as any, {
|
||||
...params,
|
||||
path: [...params.path, "allOf", 0],
|
||||
});
|
||||
const b = process(def.right, ctx as any, {
|
||||
...params,
|
||||
path: [...params.path, "allOf", 1],
|
||||
});
|
||||
|
||||
const isSimpleIntersection = (val: any) => "allOf" in val && Object.keys(val).length === 1;
|
||||
const allOf = [
|
||||
...(isSimpleIntersection(a) ? (a.allOf as any[]) : [a]),
|
||||
...(isSimpleIntersection(b) ? (b.allOf as any[]) : [b]),
|
||||
];
|
||||
json.allOf = allOf;
|
||||
};
|
||||
|
||||
export const tupleProcessor: Processor<schemas.$ZodTuple> = (schema, ctx, _json, params) => {
|
||||
const json = _json as JSONSchema.ArraySchema;
|
||||
const def = schema._zod.def as schemas.$ZodTupleDef;
|
||||
json.type = "array";
|
||||
|
||||
const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
|
||||
const restPath =
|
||||
ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
|
||||
|
||||
const prefixItems = def.items.map((x, i) =>
|
||||
process(x, ctx as any, {
|
||||
...params,
|
||||
path: [...params.path, prefixPath, i],
|
||||
})
|
||||
);
|
||||
const rest = def.rest
|
||||
? process(def.rest, ctx as any, {
|
||||
...params,
|
||||
path: [...params.path, restPath, ...(ctx.target === "openapi-3.0" ? [def.items.length] : [])],
|
||||
})
|
||||
: null;
|
||||
|
||||
if (ctx.target === "draft-2020-12") {
|
||||
json.prefixItems = prefixItems;
|
||||
if (rest) {
|
||||
json.items = rest;
|
||||
}
|
||||
} else if (ctx.target === "openapi-3.0") {
|
||||
json.items = {
|
||||
anyOf: prefixItems,
|
||||
};
|
||||
|
||||
if (rest) {
|
||||
json.items.anyOf!.push(rest);
|
||||
}
|
||||
json.minItems = prefixItems.length;
|
||||
if (!rest) {
|
||||
json.maxItems = prefixItems.length;
|
||||
}
|
||||
} else {
|
||||
json.items = prefixItems;
|
||||
if (rest) {
|
||||
json.additionalItems = rest;
|
||||
}
|
||||
}
|
||||
|
||||
// length
|
||||
const { minimum, maximum } = schema._zod.bag as {
|
||||
minimum?: number;
|
||||
maximum?: number;
|
||||
};
|
||||
if (typeof minimum === "number") json.minItems = minimum;
|
||||
if (typeof maximum === "number") json.maxItems = maximum;
|
||||
};
|
||||
|
||||
export const recordProcessor: Processor<schemas.$ZodRecord> = (schema, ctx, _json, params) => {
|
||||
const json = _json as JSONSchema.ObjectSchema;
|
||||
const def = schema._zod.def as schemas.$ZodRecordDef;
|
||||
json.type = "object";
|
||||
|
||||
// For looseRecord with regex patterns, use patternProperties
|
||||
// This correctly represents "only validate keys matching the pattern" semantics
|
||||
// and composes well with allOf (intersections)
|
||||
const keyType = def.keyType as schemas.$ZodTypes;
|
||||
const keyBag = keyType._zod.bag as schemas.$ZodStringInternals<unknown>["bag"] | undefined;
|
||||
const patterns = keyBag?.patterns;
|
||||
|
||||
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
||||
// Use patternProperties for looseRecord with regex patterns
|
||||
const valueSchema = process(def.valueType, ctx as any, {
|
||||
...params,
|
||||
path: [...params.path, "patternProperties", "*"],
|
||||
});
|
||||
json.patternProperties = {};
|
||||
for (const pattern of patterns) {
|
||||
json.patternProperties[pattern.source] = valueSchema;
|
||||
}
|
||||
} else {
|
||||
// Default behavior: use propertyNames + additionalProperties
|
||||
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
|
||||
json.propertyNames = process(def.keyType, ctx as any, {
|
||||
...params,
|
||||
path: [...params.path, "propertyNames"],
|
||||
});
|
||||
}
|
||||
json.additionalProperties = process(def.valueType, ctx as any, {
|
||||
...params,
|
||||
path: [...params.path, "additionalProperties"],
|
||||
});
|
||||
}
|
||||
|
||||
// Add required for keys with discrete values (enum, literal, etc.)
|
||||
const keyValues = keyType._zod.values;
|
||||
if (keyValues) {
|
||||
const validKeyValues = [...keyValues].filter(
|
||||
(v): v is string | number => typeof v === "string" || typeof v === "number"
|
||||
);
|
||||
|
||||
if (validKeyValues.length > 0) {
|
||||
json.required = validKeyValues as string[];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const nullableProcessor: Processor<schemas.$ZodNullable> = (schema, ctx, json, params) => {
|
||||
const def = schema._zod.def as schemas.$ZodNullableDef;
|
||||
const inner = process(def.innerType, ctx as any, params);
|
||||
const seen = ctx.seen.get(schema)!;
|
||||
if (ctx.target === "openapi-3.0") {
|
||||
seen.ref = def.innerType;
|
||||
json.nullable = true;
|
||||
} else {
|
||||
json.anyOf = [inner, { type: "null" }];
|
||||
}
|
||||
};
|
||||
|
||||
export const nonoptionalProcessor: Processor<schemas.$ZodNonOptional> = (schema, ctx, _json, params) => {
|
||||
const def = schema._zod.def as schemas.$ZodNonOptionalDef;
|
||||
process(def.innerType, ctx as any, params);
|
||||
const seen = ctx.seen.get(schema)!;
|
||||
seen.ref = def.innerType;
|
||||
};
|
||||
|
||||
export const defaultProcessor: Processor<schemas.$ZodDefault> = (schema, ctx, json, params) => {
|
||||
const def = schema._zod.def as schemas.$ZodDefaultDef;
|
||||
process(def.innerType, ctx as any, params);
|
||||
const seen = ctx.seen.get(schema)!;
|
||||
seen.ref = def.innerType;
|
||||
json.default = JSON.parse(JSON.stringify(def.defaultValue));
|
||||
};
|
||||
|
||||
export const prefaultProcessor: Processor<schemas.$ZodPrefault> = (schema, ctx, json, params) => {
|
||||
const def = schema._zod.def as schemas.$ZodPrefaultDef;
|
||||
process(def.innerType, ctx as any, params);
|
||||
const seen = ctx.seen.get(schema)!;
|
||||
seen.ref = def.innerType;
|
||||
if (ctx.io === "input") json._prefault = JSON.parse(JSON.stringify(def.defaultValue));
|
||||
};
|
||||
|
||||
export const catchProcessor: Processor<schemas.$ZodCatch> = (schema, ctx, json, params) => {
|
||||
const def = schema._zod.def as schemas.$ZodCatchDef;
|
||||
process(def.innerType, ctx as any, params);
|
||||
const seen = ctx.seen.get(schema)!;
|
||||
seen.ref = def.innerType;
|
||||
let catchValue: any;
|
||||
try {
|
||||
catchValue = def.catchValue(undefined as any);
|
||||
} catch {
|
||||
throw new Error("Dynamic catch values are not supported in JSON Schema");
|
||||
}
|
||||
json.default = catchValue;
|
||||
};
|
||||
|
||||
export const pipeProcessor: Processor<schemas.$ZodPipe> = (schema, ctx, _json, params) => {
|
||||
const def = schema._zod.def as schemas.$ZodPipeDef;
|
||||
const innerType = ctx.io === "input" ? (def.in._zod.def.type === "transform" ? def.out : def.in) : def.out;
|
||||
process(innerType, ctx as any, params);
|
||||
const seen = ctx.seen.get(schema)!;
|
||||
seen.ref = innerType;
|
||||
};
|
||||
|
||||
export const readonlyProcessor: Processor<schemas.$ZodReadonly> = (schema, ctx, json, params) => {
|
||||
const def = schema._zod.def as schemas.$ZodReadonlyDef;
|
||||
process(def.innerType, ctx as any, params);
|
||||
const seen = ctx.seen.get(schema)!;
|
||||
seen.ref = def.innerType;
|
||||
json.readOnly = true;
|
||||
};
|
||||
|
||||
export const promiseProcessor: Processor<schemas.$ZodPromise> = (schema, ctx, _json, params) => {
|
||||
const def = schema._zod.def as schemas.$ZodPromiseDef;
|
||||
process(def.innerType, ctx as any, params);
|
||||
const seen = ctx.seen.get(schema)!;
|
||||
seen.ref = def.innerType;
|
||||
};
|
||||
|
||||
export const optionalProcessor: Processor<schemas.$ZodOptional> = (schema, ctx, _json, params) => {
|
||||
const def = schema._zod.def as schemas.$ZodOptionalDef;
|
||||
process(def.innerType, ctx as any, params);
|
||||
const seen = ctx.seen.get(schema)!;
|
||||
seen.ref = def.innerType;
|
||||
};
|
||||
|
||||
export const lazyProcessor: Processor<schemas.$ZodLazy> = (schema, ctx, _json, params) => {
|
||||
const innerType = (schema as schemas.$ZodLazy)._zod.innerType;
|
||||
process(innerType, ctx as any, params);
|
||||
const seen = ctx.seen.get(schema)!;
|
||||
seen.ref = innerType;
|
||||
};
|
||||
|
||||
// ==================== ALL PROCESSORS ====================
|
||||
|
||||
export const allProcessors: Record<string, Processor<any>> = {
|
||||
string: stringProcessor,
|
||||
number: numberProcessor,
|
||||
boolean: booleanProcessor,
|
||||
bigint: bigintProcessor,
|
||||
symbol: symbolProcessor,
|
||||
null: nullProcessor,
|
||||
undefined: undefinedProcessor,
|
||||
void: voidProcessor,
|
||||
never: neverProcessor,
|
||||
any: anyProcessor,
|
||||
unknown: unknownProcessor,
|
||||
date: dateProcessor,
|
||||
enum: enumProcessor,
|
||||
literal: literalProcessor,
|
||||
nan: nanProcessor,
|
||||
template_literal: templateLiteralProcessor,
|
||||
file: fileProcessor,
|
||||
success: successProcessor,
|
||||
custom: customProcessor,
|
||||
function: functionProcessor,
|
||||
transform: transformProcessor,
|
||||
map: mapProcessor,
|
||||
set: setProcessor,
|
||||
array: arrayProcessor,
|
||||
object: objectProcessor,
|
||||
union: unionProcessor,
|
||||
intersection: intersectionProcessor,
|
||||
tuple: tupleProcessor,
|
||||
record: recordProcessor,
|
||||
nullable: nullableProcessor,
|
||||
nonoptional: nonoptionalProcessor,
|
||||
default: defaultProcessor,
|
||||
prefault: prefaultProcessor,
|
||||
catch: catchProcessor,
|
||||
pipe: pipeProcessor,
|
||||
readonly: readonlyProcessor,
|
||||
promise: promiseProcessor,
|
||||
optional: optionalProcessor,
|
||||
lazy: lazyProcessor,
|
||||
};
|
||||
|
||||
// ==================== TOP-LEVEL toJSONSchema ====================
|
||||
|
||||
export function toJSONSchema<T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
params?: ToJSONSchemaParams
|
||||
): ZodStandardJSONSchemaPayload<T>;
|
||||
export function toJSONSchema(
|
||||
registry: $ZodRegistry<{ id?: string | undefined }>,
|
||||
params?: RegistryToJSONSchemaParams
|
||||
): { schemas: Record<string, ZodStandardJSONSchemaPayload<schemas.$ZodType>> };
|
||||
export function toJSONSchema(
|
||||
input: schemas.$ZodType | $ZodRegistry<{ id?: string | undefined }>,
|
||||
params?: ToJSONSchemaParams | RegistryToJSONSchemaParams
|
||||
): any {
|
||||
if ("_idmap" in input) {
|
||||
// Registry case
|
||||
const registry = input as $ZodRegistry<{ id?: string | undefined }>;
|
||||
const ctx = initializeContext({ ...params, processors: allProcessors });
|
||||
const defs: any = {};
|
||||
|
||||
// First pass: process all schemas to build the seen map
|
||||
for (const entry of registry._idmap.entries()) {
|
||||
const [_, schema] = entry;
|
||||
process(schema, ctx as any);
|
||||
}
|
||||
|
||||
const schemas: Record<string, JSONSchema.BaseSchema> = {};
|
||||
const external = {
|
||||
registry,
|
||||
uri: (params as RegistryToJSONSchemaParams)?.uri,
|
||||
defs,
|
||||
};
|
||||
|
||||
// Update the context with external configuration
|
||||
ctx.external = external;
|
||||
|
||||
// Second pass: emit each schema
|
||||
for (const entry of registry._idmap.entries()) {
|
||||
const [key, schema] = entry;
|
||||
extractDefs(ctx as any, schema);
|
||||
schemas[key] = finalize(ctx as any, schema);
|
||||
}
|
||||
|
||||
if (Object.keys(defs).length > 0) {
|
||||
const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
|
||||
schemas.__shared = {
|
||||
[defsSegment]: defs,
|
||||
};
|
||||
}
|
||||
|
||||
return { schemas };
|
||||
}
|
||||
|
||||
// Single schema case
|
||||
const ctx = initializeContext({ ...params, processors: allProcessors });
|
||||
process(input, ctx as any);
|
||||
extractDefs(ctx as any, input);
|
||||
return finalize(ctx as any, input);
|
||||
}
|
||||
147
mcp-server-ssh/node_modules/zod/src/v4/core/json-schema.ts
generated
vendored
Normal file
147
mcp-server-ssh/node_modules/zod/src/v4/core/json-schema.ts
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
export type Schema =
|
||||
| ObjectSchema
|
||||
| ArraySchema
|
||||
| StringSchema
|
||||
| NumberSchema
|
||||
| IntegerSchema
|
||||
| BooleanSchema
|
||||
| NullSchema;
|
||||
|
||||
// export type JsonType = "object" | "array" | "string" | "number" | "boolean" | "null" | "integer";
|
||||
|
||||
// export interface JSONSchema {
|
||||
// type?: string ;
|
||||
// $id?: string ;
|
||||
// id?: string ;
|
||||
// $schema?: string ;
|
||||
// $ref?: string ;
|
||||
// $anchor?: string ;
|
||||
// $defs?: { [key: string]: JSONSchema } ;
|
||||
// definitions?: { [key: string]: JSONSchema } ;
|
||||
// $comment?: string ;
|
||||
// title?: string ;
|
||||
// description?: string ;
|
||||
// default?: unknown ;
|
||||
// examples?: unknown[] ;
|
||||
// readOnly?: boolean ;
|
||||
// writeOnly?: boolean ;
|
||||
// deprecated?: boolean ;
|
||||
// allOf?: JSONSchema[] ;
|
||||
// anyOf?: JSONSchema[] ;
|
||||
// oneOf?: JSONSchema[] ;
|
||||
// not?: JSONSchema ;
|
||||
// if?: JSONSchema ;
|
||||
// then?: JSONSchema ;
|
||||
// else?: JSONSchema ;
|
||||
// enum?: Array<string | number | boolean | null> ;
|
||||
// const?: string | number | boolean | null ;
|
||||
// [k: string]: unknown;
|
||||
|
||||
// /** A special key used as an intermediate representation of extends-style relationships. Omitted as a $ref with additional properties. */
|
||||
// // _ref?: JSONSchema;
|
||||
// _prefault?: unknown ;
|
||||
// }
|
||||
|
||||
export type _JSONSchema = boolean | JSONSchema;
|
||||
export type JSONSchema = {
|
||||
[k: string]: unknown;
|
||||
$schema?:
|
||||
| "https://json-schema.org/draft/2020-12/schema"
|
||||
| "http://json-schema.org/draft-07/schema#"
|
||||
| "http://json-schema.org/draft-04/schema#";
|
||||
$id?: string;
|
||||
$anchor?: string;
|
||||
$ref?: string;
|
||||
$dynamicRef?: string;
|
||||
$dynamicAnchor?: string;
|
||||
$vocabulary?: Record<string, boolean>;
|
||||
$comment?: string;
|
||||
$defs?: Record<string, JSONSchema>;
|
||||
type?: "object" | "array" | "string" | "number" | "boolean" | "null" | "integer";
|
||||
additionalItems?: _JSONSchema;
|
||||
unevaluatedItems?: _JSONSchema;
|
||||
prefixItems?: _JSONSchema[];
|
||||
items?: _JSONSchema | _JSONSchema[];
|
||||
contains?: _JSONSchema;
|
||||
additionalProperties?: _JSONSchema;
|
||||
unevaluatedProperties?: _JSONSchema;
|
||||
properties?: Record<string, _JSONSchema>;
|
||||
patternProperties?: Record<string, _JSONSchema>;
|
||||
dependentSchemas?: Record<string, _JSONSchema>;
|
||||
propertyNames?: _JSONSchema;
|
||||
if?: _JSONSchema;
|
||||
then?: _JSONSchema;
|
||||
else?: _JSONSchema;
|
||||
allOf?: JSONSchema[];
|
||||
anyOf?: JSONSchema[];
|
||||
oneOf?: JSONSchema[];
|
||||
not?: _JSONSchema;
|
||||
multipleOf?: number;
|
||||
maximum?: number;
|
||||
exclusiveMaximum?: number | boolean;
|
||||
minimum?: number;
|
||||
exclusiveMinimum?: number | boolean;
|
||||
maxLength?: number;
|
||||
minLength?: number;
|
||||
pattern?: string;
|
||||
maxItems?: number;
|
||||
minItems?: number;
|
||||
uniqueItems?: boolean;
|
||||
maxContains?: number;
|
||||
minContains?: number;
|
||||
maxProperties?: number;
|
||||
minProperties?: number;
|
||||
required?: string[];
|
||||
dependentRequired?: Record<string, string[]>;
|
||||
enum?: Array<string | number | boolean | null>;
|
||||
const?: string | number | boolean | null;
|
||||
|
||||
// metadata
|
||||
id?: string;
|
||||
title?: string;
|
||||
description?: string;
|
||||
default?: unknown;
|
||||
deprecated?: boolean;
|
||||
readOnly?: boolean;
|
||||
writeOnly?: boolean;
|
||||
nullable?: boolean;
|
||||
examples?: unknown[];
|
||||
format?: string;
|
||||
contentMediaType?: string;
|
||||
contentEncoding?: string;
|
||||
contentSchema?: JSONSchema;
|
||||
|
||||
// internal
|
||||
_prefault?: unknown;
|
||||
};
|
||||
|
||||
// for backwards compatibility
|
||||
export type BaseSchema = JSONSchema;
|
||||
|
||||
export interface ObjectSchema extends JSONSchema {
|
||||
type: "object";
|
||||
}
|
||||
|
||||
export interface ArraySchema extends JSONSchema {
|
||||
type: "array";
|
||||
}
|
||||
|
||||
export interface StringSchema extends JSONSchema {
|
||||
type: "string";
|
||||
}
|
||||
|
||||
export interface NumberSchema extends JSONSchema {
|
||||
type: "number";
|
||||
}
|
||||
|
||||
export interface IntegerSchema extends JSONSchema {
|
||||
type: "integer";
|
||||
}
|
||||
|
||||
export interface BooleanSchema extends JSONSchema {
|
||||
type: "boolean";
|
||||
}
|
||||
|
||||
export interface NullSchema extends JSONSchema {
|
||||
type: "null";
|
||||
}
|
||||
195
mcp-server-ssh/node_modules/zod/src/v4/core/parse.ts
generated
vendored
Normal file
195
mcp-server-ssh/node_modules/zod/src/v4/core/parse.ts
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
import * as core from "./core.js";
|
||||
import * as errors from "./errors.js";
|
||||
import type * as schemas from "./schemas.js";
|
||||
import * as util from "./util.js";
|
||||
|
||||
export type $ZodErrorClass = { new (issues: errors.$ZodIssue[]): errors.$ZodError };
|
||||
|
||||
/////////// METHODS ///////////
|
||||
export type $Parse = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>,
|
||||
_params?: { callee?: util.AnyFunc; Err?: $ZodErrorClass }
|
||||
) => core.output<T>;
|
||||
|
||||
export const _parse: (_Err: $ZodErrorClass) => $Parse = (_Err) => (schema, value, _ctx, _params) => {
|
||||
const ctx: schemas.ParseContextInternal = _ctx ? Object.assign(_ctx, { async: false }) : { async: false };
|
||||
const result = schema._zod.run({ value, issues: [] }, ctx);
|
||||
if (result instanceof Promise) {
|
||||
throw new core.$ZodAsyncError();
|
||||
}
|
||||
if (result.issues.length) {
|
||||
const e = new (_params?.Err ?? _Err)(result.issues.map((iss) => util.finalizeIssue(iss, ctx, core.config())));
|
||||
util.captureStackTrace(e, _params?.callee);
|
||||
throw e;
|
||||
}
|
||||
return result.value as core.output<typeof schema>;
|
||||
};
|
||||
|
||||
export const parse: $Parse = /* @__PURE__*/ _parse(errors.$ZodRealError);
|
||||
|
||||
export type $ParseAsync = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>,
|
||||
_params?: { callee?: util.AnyFunc; Err?: $ZodErrorClass }
|
||||
) => Promise<core.output<T>>;
|
||||
|
||||
export const _parseAsync: (_Err: $ZodErrorClass) => $ParseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
||||
const ctx: schemas.ParseContextInternal = _ctx ? Object.assign(_ctx, { async: true }) : { async: true };
|
||||
let result = schema._zod.run({ value, issues: [] }, ctx);
|
||||
if (result instanceof Promise) result = await result;
|
||||
if (result.issues.length) {
|
||||
const e = new (params?.Err ?? _Err)(result.issues.map((iss) => util.finalizeIssue(iss, ctx, core.config())));
|
||||
util.captureStackTrace(e, params?.callee);
|
||||
throw e;
|
||||
}
|
||||
return result.value as core.output<typeof schema>;
|
||||
};
|
||||
|
||||
export const parseAsync: $ParseAsync = /* @__PURE__*/ _parseAsync(errors.$ZodRealError);
|
||||
|
||||
export type $SafeParse = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => util.SafeParseResult<core.output<T>>;
|
||||
|
||||
export const _safeParse: (_Err: $ZodErrorClass) => $SafeParse = (_Err) => (schema, value, _ctx) => {
|
||||
const ctx: schemas.ParseContextInternal = _ctx ? { ..._ctx, async: false } : { async: false };
|
||||
const result = schema._zod.run({ value, issues: [] }, ctx);
|
||||
if (result instanceof Promise) {
|
||||
throw new core.$ZodAsyncError();
|
||||
}
|
||||
|
||||
return result.issues.length
|
||||
? {
|
||||
success: false,
|
||||
error: new (_Err ?? errors.$ZodError)(result.issues.map((iss) => util.finalizeIssue(iss, ctx, core.config()))),
|
||||
}
|
||||
: ({ success: true, data: result.value } as any);
|
||||
};
|
||||
export const safeParse: $SafeParse = /* @__PURE__*/ _safeParse(errors.$ZodRealError);
|
||||
|
||||
export type $SafeParseAsync = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: unknown,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => Promise<util.SafeParseResult<core.output<T>>>;
|
||||
|
||||
export const _safeParseAsync: (_Err: $ZodErrorClass) => $SafeParseAsync = (_Err) => async (schema, value, _ctx) => {
|
||||
const ctx: schemas.ParseContextInternal = _ctx ? Object.assign(_ctx, { async: true }) : { async: true };
|
||||
let result = schema._zod.run({ value, issues: [] }, ctx);
|
||||
if (result instanceof Promise) result = await result;
|
||||
|
||||
return result.issues.length
|
||||
? {
|
||||
success: false,
|
||||
error: new _Err(result.issues.map((iss) => util.finalizeIssue(iss, ctx, core.config()))),
|
||||
}
|
||||
: ({ success: true, data: result.value } as any);
|
||||
};
|
||||
|
||||
export const safeParseAsync: $SafeParseAsync = /* @__PURE__*/ _safeParseAsync(errors.$ZodRealError);
|
||||
|
||||
// Codec functions
|
||||
export type $Encode = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => core.input<T>;
|
||||
|
||||
export const _encode: (_Err: $ZodErrorClass) => $Encode = (_Err) => (schema, value, _ctx) => {
|
||||
const ctx = _ctx ? Object.assign(_ctx, { direction: "backward" as const }) : { direction: "backward" as const };
|
||||
return _parse(_Err)(schema, value, ctx as any) as any;
|
||||
};
|
||||
|
||||
export const encode: $Encode = /* @__PURE__*/ _encode(errors.$ZodRealError);
|
||||
|
||||
export type $Decode = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => core.output<T>;
|
||||
|
||||
export const _decode: (_Err: $ZodErrorClass) => $Decode = (_Err) => (schema, value, _ctx) => {
|
||||
return _parse(_Err)(schema, value, _ctx);
|
||||
};
|
||||
|
||||
export const decode: $Decode = /* @__PURE__*/ _decode(errors.$ZodRealError);
|
||||
|
||||
export type $EncodeAsync = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => Promise<core.input<T>>;
|
||||
|
||||
export const _encodeAsync: (_Err: $ZodErrorClass) => $EncodeAsync = (_Err) => async (schema, value, _ctx) => {
|
||||
const ctx = _ctx ? Object.assign(_ctx, { direction: "backward" as const }) : { direction: "backward" as const };
|
||||
return _parseAsync(_Err)(schema, value, ctx as any) as any;
|
||||
};
|
||||
|
||||
export const encodeAsync: $EncodeAsync = /* @__PURE__*/ _encodeAsync(errors.$ZodRealError);
|
||||
|
||||
export type $DecodeAsync = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => Promise<core.output<T>>;
|
||||
|
||||
export const _decodeAsync: (_Err: $ZodErrorClass) => $DecodeAsync = (_Err) => async (schema, value, _ctx) => {
|
||||
return _parseAsync(_Err)(schema, value, _ctx);
|
||||
};
|
||||
|
||||
export const decodeAsync: $DecodeAsync = /* @__PURE__*/ _decodeAsync(errors.$ZodRealError);
|
||||
|
||||
export type $SafeEncode = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => util.SafeParseResult<core.input<T>>;
|
||||
|
||||
export const _safeEncode: (_Err: $ZodErrorClass) => $SafeEncode = (_Err) => (schema, value, _ctx) => {
|
||||
const ctx = _ctx ? Object.assign(_ctx, { direction: "backward" as const }) : { direction: "backward" as const };
|
||||
return _safeParse(_Err)(schema, value, ctx as any) as any;
|
||||
};
|
||||
|
||||
export const safeEncode: $SafeEncode = /* @__PURE__*/ _safeEncode(errors.$ZodRealError);
|
||||
|
||||
export type $SafeDecode = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => util.SafeParseResult<core.output<T>>;
|
||||
|
||||
export const _safeDecode: (_Err: $ZodErrorClass) => $SafeDecode = (_Err) => (schema, value, _ctx) => {
|
||||
return _safeParse(_Err)(schema, value, _ctx);
|
||||
};
|
||||
|
||||
export const safeDecode: $SafeDecode = /* @__PURE__*/ _safeDecode(errors.$ZodRealError);
|
||||
|
||||
export type $SafeEncodeAsync = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.output<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => Promise<util.SafeParseResult<core.input<T>>>;
|
||||
|
||||
export const _safeEncodeAsync: (_Err: $ZodErrorClass) => $SafeEncodeAsync = (_Err) => async (schema, value, _ctx) => {
|
||||
const ctx = _ctx ? Object.assign(_ctx, { direction: "backward" as const }) : { direction: "backward" as const };
|
||||
return _safeParseAsync(_Err)(schema, value, ctx as any) as any;
|
||||
};
|
||||
|
||||
export const safeEncodeAsync: $SafeEncodeAsync = /* @__PURE__*/ _safeEncodeAsync(errors.$ZodRealError);
|
||||
|
||||
export type $SafeDecodeAsync = <T extends schemas.$ZodType>(
|
||||
schema: T,
|
||||
value: core.input<T>,
|
||||
_ctx?: schemas.ParseContext<errors.$ZodIssue>
|
||||
) => Promise<util.SafeParseResult<core.output<T>>>;
|
||||
|
||||
export const _safeDecodeAsync: (_Err: $ZodErrorClass) => $SafeDecodeAsync = (_Err) => async (schema, value, _ctx) => {
|
||||
return _safeParseAsync(_Err)(schema, value, _ctx);
|
||||
};
|
||||
|
||||
export const safeDecodeAsync: $SafeDecodeAsync = /* @__PURE__*/ _safeDecodeAsync(errors.$ZodRealError);
|
||||
183
mcp-server-ssh/node_modules/zod/src/v4/core/regexes.ts
generated
vendored
Normal file
183
mcp-server-ssh/node_modules/zod/src/v4/core/regexes.ts
generated
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
import * as util from "./util.js";
|
||||
|
||||
export const cuid: RegExp = /^[cC][^\s-]{8,}$/;
|
||||
export const cuid2: RegExp = /^[0-9a-z]+$/;
|
||||
export const ulid: RegExp = /^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/;
|
||||
export const xid: RegExp = /^[0-9a-vA-V]{20}$/;
|
||||
export const ksuid: RegExp = /^[A-Za-z0-9]{27}$/;
|
||||
export const nanoid: RegExp = /^[a-zA-Z0-9_-]{21}$/;
|
||||
|
||||
/** ISO 8601-1 duration regex. Does not support the 8601-2 extensions like negative durations or fractional/negative components. */
|
||||
export const duration: RegExp =
|
||||
/^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/;
|
||||
|
||||
/** Implements ISO 8601-2 extensions like explicit +- prefixes, mixing weeks with other units, and fractional/negative components. */
|
||||
export const extendedDuration: RegExp =
|
||||
/^[-+]?P(?!$)(?:(?:[-+]?\d+Y)|(?:[-+]?\d+[.,]\d+Y$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:(?:[-+]?\d+W)|(?:[-+]?\d+[.,]\d+W$))?(?:(?:[-+]?\d+D)|(?:[-+]?\d+[.,]\d+D$))?(?:T(?=[\d+-])(?:(?:[-+]?\d+H)|(?:[-+]?\d+[.,]\d+H$))?(?:(?:[-+]?\d+M)|(?:[-+]?\d+[.,]\d+M$))?(?:[-+]?\d+(?:[.,]\d+)?S)?)??$/;
|
||||
|
||||
/** A regex for any UUID-like identifier: 8-4-4-4-12 hex pattern */
|
||||
export const guid: RegExp = /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/;
|
||||
|
||||
/** Returns a regex for validating an RFC 9562/4122 UUID.
|
||||
*
|
||||
* @param version Optionally specify a version 1-8. If no version is specified, all versions are supported. */
|
||||
export const uuid = (version?: number | undefined): RegExp => {
|
||||
if (!version)
|
||||
return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;
|
||||
return new RegExp(
|
||||
`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`
|
||||
);
|
||||
};
|
||||
export const uuid4: RegExp = /*@__PURE__*/ uuid(4);
|
||||
export const uuid6: RegExp = /*@__PURE__*/ uuid(6);
|
||||
export const uuid7: RegExp = /*@__PURE__*/ uuid(7);
|
||||
|
||||
/** Practical email validation */
|
||||
export const email: RegExp =
|
||||
/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
|
||||
|
||||
/** Equivalent to the HTML5 input[type=email] validation implemented by browsers. Source: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email */
|
||||
export const html5Email: RegExp =
|
||||
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
||||
|
||||
/** The classic emailregex.com regex for RFC 5322-compliant emails */
|
||||
export const rfc5322Email =
|
||||
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
|
||||
/** A loose regex that allows Unicode characters, enforces length limits, and that's about it. */
|
||||
export const unicodeEmail = /^[^\s@"]{1,64}@[^\s@]{1,255}$/u;
|
||||
export const idnEmail = unicodeEmail;
|
||||
|
||||
export const browserEmail: RegExp =
|
||||
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
||||
// from https://thekevinscott.com/emojis-in-javascript/#writing-a-regular-expression
|
||||
|
||||
const _emoji: string = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`;
|
||||
export function emoji(): RegExp {
|
||||
return new RegExp(_emoji, "u");
|
||||
}
|
||||
|
||||
export const ipv4: RegExp =
|
||||
/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
|
||||
export const ipv6: RegExp =
|
||||
/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
|
||||
export const mac = (delimiter?: string): RegExp => {
|
||||
const escapedDelim = util.escapeRegex(delimiter ?? ":");
|
||||
return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
|
||||
};
|
||||
export const cidrv4: RegExp =
|
||||
/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
|
||||
export const cidrv6: RegExp =
|
||||
/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
|
||||
|
||||
// https://stackoverflow.com/questions/7860392/determine-if-string-is-in-base64-using-javascript
|
||||
export const base64: RegExp = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
|
||||
export const base64url: RegExp = /^[A-Za-z0-9_-]*$/;
|
||||
|
||||
// based on https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address
|
||||
// export const hostname: RegExp = /^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+$/;
|
||||
export const hostname: RegExp =
|
||||
/^(?=.{1,253}\.?$)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?)*\.?$/;
|
||||
|
||||
export const domain: RegExp = /^([a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/;
|
||||
|
||||
// https://blog.stevenlevithan.com/archives/validate-phone-number#r4-3 (regex sans spaces)
|
||||
// E.164: leading digit must be 1-9; total digits (excluding '+') between 7-15
|
||||
export const e164: RegExp = /^\+[1-9]\d{6,14}$/;
|
||||
|
||||
// const dateSource = `((\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-((0[13578]|1[02])-(0[1-9]|[12]\\d|3[01])|(0[469]|11)-(0[1-9]|[12]\\d|30)|(02)-(0[1-9]|1\\d|2[0-8])))`;
|
||||
const dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`;
|
||||
export const date: RegExp = /*@__PURE__*/ new RegExp(`^${dateSource}$`);
|
||||
|
||||
function timeSource(args: { precision?: number | null | undefined }) {
|
||||
const hhmm = `(?:[01]\\d|2[0-3]):[0-5]\\d`;
|
||||
const regex =
|
||||
typeof args.precision === "number"
|
||||
? args.precision === -1
|
||||
? `${hhmm}`
|
||||
: args.precision === 0
|
||||
? `${hhmm}:[0-5]\\d`
|
||||
: `${hhmm}:[0-5]\\d\\.\\d{${args.precision}}`
|
||||
: `${hhmm}(?::[0-5]\\d(?:\\.\\d+)?)?`;
|
||||
return regex;
|
||||
}
|
||||
export function time(args: {
|
||||
precision?: number | null;
|
||||
// local?: boolean;
|
||||
}): RegExp {
|
||||
return new RegExp(`^${timeSource(args)}$`);
|
||||
}
|
||||
|
||||
// Adapted from https://stackoverflow.com/a/3143231
|
||||
export function datetime(args: {
|
||||
precision?: number | null;
|
||||
offset?: boolean;
|
||||
local?: boolean;
|
||||
}): RegExp {
|
||||
const time = timeSource({ precision: args.precision });
|
||||
const opts = ["Z"];
|
||||
if (args.local) opts.push("");
|
||||
// if (args.offset) opts.push(`([+-]\\d{2}:\\d{2})`);
|
||||
if (args.offset) opts.push(`([+-](?:[01]\\d|2[0-3]):[0-5]\\d)`);
|
||||
const timeRegex = `${time}(?:${opts.join("|")})`;
|
||||
|
||||
return new RegExp(`^${dateSource}T(?:${timeRegex})$`);
|
||||
}
|
||||
|
||||
export const string = (params?: { minimum?: number | undefined; maximum?: number | undefined }): RegExp => {
|
||||
const regex = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
|
||||
return new RegExp(`^${regex}$`);
|
||||
};
|
||||
|
||||
export const bigint: RegExp = /^-?\d+n?$/;
|
||||
export const integer: RegExp = /^-?\d+$/;
|
||||
export const number: RegExp = /^-?\d+(?:\.\d+)?$/;
|
||||
export const boolean: RegExp = /^(?:true|false)$/i;
|
||||
const _null: RegExp = /^null$/i;
|
||||
export { _null as null };
|
||||
const _undefined: RegExp = /^undefined$/i;
|
||||
export { _undefined as undefined };
|
||||
|
||||
// regex for string with no uppercase letters
|
||||
export const lowercase: RegExp = /^[^A-Z]*$/;
|
||||
// regex for string with no lowercase letters
|
||||
export const uppercase: RegExp = /^[^a-z]*$/;
|
||||
|
||||
// regex for hexadecimal strings (any length)
|
||||
export const hex: RegExp = /^[0-9a-fA-F]*$/;
|
||||
|
||||
// Hash regexes for different algorithms and encodings
|
||||
// Helper function to create base64 regex with exact length and padding
|
||||
function fixedBase64(bodyLength: number, padding: "" | "=" | "=="): RegExp {
|
||||
return new RegExp(`^[A-Za-z0-9+/]{${bodyLength}}${padding}$`);
|
||||
}
|
||||
|
||||
// Helper function to create base64url regex with exact length (no padding)
|
||||
function fixedBase64url(length: number): RegExp {
|
||||
return new RegExp(`^[A-Za-z0-9_-]{${length}}$`);
|
||||
}
|
||||
|
||||
// MD5 (16 bytes): base64 = 24 chars total (22 + "==")
|
||||
export const md5_hex: RegExp = /^[0-9a-fA-F]{32}$/;
|
||||
export const md5_base64: RegExp = /*@__PURE__*/ fixedBase64(22, "==");
|
||||
export const md5_base64url: RegExp = /*@__PURE__*/ fixedBase64url(22);
|
||||
|
||||
// SHA1 (20 bytes): base64 = 28 chars total (27 + "=")
|
||||
export const sha1_hex: RegExp = /^[0-9a-fA-F]{40}$/;
|
||||
export const sha1_base64: RegExp = /*@__PURE__*/ fixedBase64(27, "=");
|
||||
export const sha1_base64url: RegExp = /*@__PURE__*/ fixedBase64url(27);
|
||||
|
||||
// SHA256 (32 bytes): base64 = 44 chars total (43 + "=")
|
||||
export const sha256_hex: RegExp = /^[0-9a-fA-F]{64}$/;
|
||||
export const sha256_base64: RegExp = /*@__PURE__*/ fixedBase64(43, "=");
|
||||
export const sha256_base64url: RegExp = /*@__PURE__*/ fixedBase64url(43);
|
||||
|
||||
// SHA384 (48 bytes): base64 = 64 chars total (no padding)
|
||||
export const sha384_hex: RegExp = /^[0-9a-fA-F]{96}$/;
|
||||
export const sha384_base64: RegExp = /*@__PURE__*/ fixedBase64(64, "");
|
||||
export const sha384_base64url: RegExp = /*@__PURE__*/ fixedBase64url(64);
|
||||
|
||||
// SHA512 (64 bytes): base64 = 88 chars total (86 + "==")
|
||||
export const sha512_hex: RegExp = /^[0-9a-fA-F]{128}$/;
|
||||
export const sha512_base64: RegExp = /*@__PURE__*/ fixedBase64(86, "==");
|
||||
export const sha512_base64url: RegExp = /*@__PURE__*/ fixedBase64url(86);
|
||||
105
mcp-server-ssh/node_modules/zod/src/v4/core/registries.ts
generated
vendored
Normal file
105
mcp-server-ssh/node_modules/zod/src/v4/core/registries.ts
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
import type * as core from "./core.js";
|
||||
import type { $ZodType } from "./schemas.js";
|
||||
|
||||
export const $output: unique symbol = Symbol("ZodOutput");
|
||||
export type $output = typeof $output;
|
||||
export const $input: unique symbol = Symbol("ZodInput");
|
||||
export type $input = typeof $input;
|
||||
|
||||
export type $replace<Meta, S extends $ZodType> = Meta extends $output
|
||||
? core.output<S>
|
||||
: Meta extends $input
|
||||
? core.input<S>
|
||||
: Meta extends (infer M)[]
|
||||
? $replace<M, S>[]
|
||||
: Meta extends (...args: infer P) => infer R
|
||||
? (
|
||||
...args: {
|
||||
[K in keyof P]: $replace<P[K], S>; // tuple
|
||||
}
|
||||
) => $replace<R, S>
|
||||
: // handle objects
|
||||
Meta extends object
|
||||
? { [K in keyof Meta]: $replace<Meta[K], S> }
|
||||
: Meta;
|
||||
|
||||
type MetadataType = object | undefined;
|
||||
export class $ZodRegistry<Meta extends MetadataType = MetadataType, Schema extends $ZodType = $ZodType> {
|
||||
_meta!: Meta;
|
||||
_schema!: Schema;
|
||||
_map: WeakMap<Schema, $replace<Meta, Schema>> = new WeakMap();
|
||||
_idmap: Map<string, Schema> = new Map();
|
||||
|
||||
add<S extends Schema>(
|
||||
schema: S,
|
||||
..._meta: undefined extends Meta ? [$replace<Meta, S>?] : [$replace<Meta, S>]
|
||||
): this {
|
||||
const meta: any = _meta[0];
|
||||
this._map.set(schema, meta!);
|
||||
if (meta && typeof meta === "object" && "id" in meta) {
|
||||
this._idmap.set(meta.id!, schema);
|
||||
}
|
||||
return this as any;
|
||||
}
|
||||
|
||||
clear(): this {
|
||||
this._map = new WeakMap();
|
||||
this._idmap = new Map();
|
||||
return this;
|
||||
}
|
||||
|
||||
remove(schema: Schema): this {
|
||||
const meta: any = this._map.get(schema);
|
||||
if (meta && typeof meta === "object" && "id" in meta) {
|
||||
this._idmap.delete(meta.id!);
|
||||
}
|
||||
this._map.delete(schema);
|
||||
return this;
|
||||
}
|
||||
|
||||
get<S extends Schema>(schema: S): $replace<Meta, S> | undefined {
|
||||
// return this._map.get(schema) as any;
|
||||
|
||||
// inherit metadata
|
||||
const p = schema._zod.parent as Schema;
|
||||
if (p) {
|
||||
const pm: any = { ...(this.get(p) ?? {}) };
|
||||
delete pm.id; // do not inherit id
|
||||
const f = { ...pm, ...this._map.get(schema) } as any;
|
||||
return Object.keys(f).length ? f : undefined;
|
||||
}
|
||||
return this._map.get(schema) as any;
|
||||
}
|
||||
|
||||
has(schema: Schema): boolean {
|
||||
return this._map.has(schema);
|
||||
}
|
||||
}
|
||||
|
||||
export interface JSONSchemaMeta {
|
||||
id?: string | undefined;
|
||||
title?: string | undefined;
|
||||
description?: string | undefined;
|
||||
deprecated?: boolean | undefined;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
|
||||
export interface GlobalMeta extends JSONSchemaMeta {}
|
||||
|
||||
// registries
|
||||
export function registry<T extends MetadataType = MetadataType, S extends $ZodType = $ZodType>(): $ZodRegistry<T, S> {
|
||||
return new $ZodRegistry<T, S>();
|
||||
}
|
||||
|
||||
interface GlobalThisWithRegistry {
|
||||
/**
|
||||
* The globalRegistry instance shared across both CommonJS and ESM builds.
|
||||
* By attaching the registry to `globalThis`, this property ensures a single, deduplicated instance
|
||||
* is used regardless of whether the package is loaded via `require` (CJS) or `import` (ESM).
|
||||
* This prevents dual package hazards and keeps registry state consistent.
|
||||
*/
|
||||
__zod_globalRegistry?: $ZodRegistry<GlobalMeta>;
|
||||
}
|
||||
|
||||
(globalThis as GlobalThisWithRegistry).__zod_globalRegistry ??= registry<GlobalMeta>();
|
||||
export const globalRegistry: $ZodRegistry<GlobalMeta> = (globalThis as GlobalThisWithRegistry).__zod_globalRegistry!;
|
||||
4538
mcp-server-ssh/node_modules/zod/src/v4/core/schemas.ts
generated
vendored
Normal file
4538
mcp-server-ssh/node_modules/zod/src/v4/core/schemas.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
159
mcp-server-ssh/node_modules/zod/src/v4/core/standard-schema.ts
generated
vendored
Normal file
159
mcp-server-ssh/node_modules/zod/src/v4/core/standard-schema.ts
generated
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
/** The Standard interface. */
|
||||
export interface StandardTypedV1<Input = unknown, Output = Input> {
|
||||
/** The Standard properties. */
|
||||
readonly "~standard": StandardTypedV1.Props<Input, Output>;
|
||||
}
|
||||
|
||||
export declare namespace StandardTypedV1 {
|
||||
/** The Standard 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;
|
||||
/** Inferred types associated with the schema. */
|
||||
readonly types?: Types<Input, Output> | undefined;
|
||||
}
|
||||
|
||||
/** The Standard 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. */
|
||||
export type InferInput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["input"];
|
||||
|
||||
/** Infers the output type of a Standard. */
|
||||
export type InferOutput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["output"];
|
||||
}
|
||||
|
||||
/** The Standard Schema interface. */
|
||||
export interface StandardSchemaV1<Input = unknown, Output = Input> {
|
||||
/** The Standard Schema properties. */
|
||||
readonly "~standard": StandardSchemaV1.Props<Input, Output>;
|
||||
}
|
||||
|
||||
export declare namespace StandardSchemaV1 {
|
||||
/** The Standard Schema properties interface. */
|
||||
export interface Props<Input = unknown, Output = Input> extends StandardTypedV1.Props<Input, Output> {
|
||||
/** Validates unknown input values. */
|
||||
readonly validate: (
|
||||
value: unknown,
|
||||
options?: StandardSchemaV1.Options | undefined
|
||||
) => Result<Output> | Promise<Result<Output>>;
|
||||
}
|
||||
|
||||
/** 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 absence of issues indicates success. */
|
||||
readonly issues?: undefined;
|
||||
}
|
||||
|
||||
export interface Options {
|
||||
/** Implicit support for additional vendor-specific parameters, if needed. */
|
||||
readonly libraryOptions?: Record<string, unknown> | 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 types interface. */
|
||||
export interface Types<Input = unknown, Output = Input> extends StandardTypedV1.Types<Input, Output> {}
|
||||
|
||||
/** Infers the input type of a Standard. */
|
||||
export type InferInput<Schema extends StandardTypedV1> = StandardTypedV1.InferInput<Schema>;
|
||||
|
||||
/** Infers the output type of a Standard. */
|
||||
export type InferOutput<Schema extends StandardTypedV1> = StandardTypedV1.InferOutput<Schema>;
|
||||
}
|
||||
|
||||
/** The Standard JSON Schema interface. */
|
||||
export interface StandardJSONSchemaV1<Input = unknown, Output = Input> {
|
||||
/** The Standard JSON Schema properties. */
|
||||
readonly "~standard": StandardJSONSchemaV1.Props<Input, Output>;
|
||||
}
|
||||
|
||||
export declare namespace StandardJSONSchemaV1 {
|
||||
/** The Standard JSON Schema properties interface. */
|
||||
export interface Props<Input = unknown, Output = Input> extends StandardTypedV1.Props<Input, Output> {
|
||||
/** Methods for generating the input/output JSON Schema. */
|
||||
readonly jsonSchema: Converter;
|
||||
}
|
||||
|
||||
/** The Standard JSON Schema converter interface. */
|
||||
export interface Converter {
|
||||
/** Converts the input type to JSON Schema. May throw if conversion is not supported. */
|
||||
readonly input: (options: StandardJSONSchemaV1.Options) => Record<string, unknown>;
|
||||
/** Converts the output type to JSON Schema. May throw if conversion is not supported. */
|
||||
readonly output: (options: StandardJSONSchemaV1.Options) => Record<string, unknown>;
|
||||
}
|
||||
|
||||
/** The target version of the generated JSON Schema.
|
||||
*
|
||||
* It is *strongly recommended* that implementers support `"draft-2020-12"` and `"draft-07"`, as they are both in wide use.
|
||||
*
|
||||
* The `"openapi-3.0"` target is intended as a standardized specifier for OpenAPI 3.0 which is a superset of JSON Schema `"draft-04"`.
|
||||
*
|
||||
* All other targets can be implemented on a best-effort basis. Libraries should throw if they don't support a specified target.
|
||||
*/
|
||||
export type Target =
|
||||
| "draft-2020-12"
|
||||
| "draft-07"
|
||||
| "openapi-3.0"
|
||||
// Accepts any string for future targets while preserving autocomplete
|
||||
| ({} & string);
|
||||
|
||||
/** The options for the input/output methods. */
|
||||
export interface Options {
|
||||
/** Specifies the target version of the generated JSON Schema. Support for all versions is on a best-effort basis. If a given version is not supported, the library should throw. */
|
||||
readonly target: Target;
|
||||
|
||||
/** Implicit support for additional vendor-specific parameters, if needed. */
|
||||
readonly libraryOptions?: Record<string, unknown> | undefined;
|
||||
}
|
||||
|
||||
/** The Standard types interface. */
|
||||
export interface Types<Input = unknown, Output = Input> extends StandardTypedV1.Types<Input, Output> {}
|
||||
|
||||
/** Infers the input type of a Standard. */
|
||||
export type InferInput<Schema extends StandardTypedV1> = StandardTypedV1.InferInput<Schema>;
|
||||
|
||||
/** Infers the output type of a Standard. */
|
||||
export type InferOutput<Schema extends StandardTypedV1> = StandardTypedV1.InferOutput<Schema>;
|
||||
}
|
||||
|
||||
export interface StandardSchemaWithJSONProps<Input = unknown, Output = Input>
|
||||
extends StandardSchemaV1.Props<Input, Output>,
|
||||
StandardJSONSchemaV1.Props<Input, Output> {}
|
||||
|
||||
/**
|
||||
* An interface that combines StandardJSONSchema and StandardSchema.
|
||||
*/
|
||||
export interface StandardSchemaWithJSON<Input = unknown, Output = Input> {
|
||||
"~standard": StandardSchemaWithJSONProps<Input, Output>;
|
||||
}
|
||||
59
mcp-server-ssh/node_modules/zod/src/v4/core/tests/extend.test.ts
generated
vendored
Normal file
59
mcp-server-ssh/node_modules/zod/src/v4/core/tests/extend.test.ts
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
import { expect, test } from "vitest";
|
||||
import * as z from "zod/v4";
|
||||
|
||||
test("safeExtend chaining preserves and overrides properties", () => {
|
||||
const schema1 = z.object({
|
||||
email: z.string(),
|
||||
});
|
||||
|
||||
const schema2 = schema1.safeExtend({
|
||||
email: schema1.shape.email.check(z.email()),
|
||||
});
|
||||
|
||||
const schema3 = schema2.safeExtend({
|
||||
email: schema2.shape.email.or(z.literal("")),
|
||||
});
|
||||
|
||||
schema3.parse({ email: "test@example.com" });
|
||||
});
|
||||
|
||||
test("extend with constructor field in shape", () => {
|
||||
const baseSchema = z.object({
|
||||
name: z.string(),
|
||||
});
|
||||
|
||||
const extendedSchema = baseSchema.extend({
|
||||
constructor: z.string(),
|
||||
age: z.number(),
|
||||
});
|
||||
|
||||
const result = extendedSchema.parse({
|
||||
name: "John",
|
||||
constructor: "Person",
|
||||
age: 30,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
name: "John",
|
||||
constructor: "Person",
|
||||
age: 30,
|
||||
});
|
||||
|
||||
const testCases = [
|
||||
{ name: "Test", constructor: 123, age: 25 },
|
||||
{ name: "Test", constructor: null, age: 25 },
|
||||
{ name: "Test", constructor: true, age: 25 },
|
||||
{ name: "Test", constructor: {}, age: 25 },
|
||||
];
|
||||
|
||||
for (const testCase of testCases) {
|
||||
const anyConstructorSchema = baseSchema.extend({
|
||||
constructor: z.any(),
|
||||
age: z.number(),
|
||||
});
|
||||
|
||||
expect(() => anyConstructorSchema.parse(testCase)).not.toThrow();
|
||||
const parsed = anyConstructorSchema.parse(testCase);
|
||||
expect(parsed).toEqual(testCase);
|
||||
}
|
||||
});
|
||||
46
mcp-server-ssh/node_modules/zod/src/v4/core/tests/index.test.ts
generated
vendored
Normal file
46
mcp-server-ssh/node_modules/zod/src/v4/core/tests/index.test.ts
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
import { expect, expectTypeOf, test } from "vitest";
|
||||
import * as z from "zod/v3";
|
||||
|
||||
test("test", () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
|
||||
test("test2", () => {
|
||||
expect(() => z.string().parse(234)).toThrowErrorMatchingInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "string",
|
||||
"received": "number",
|
||||
"path": [],
|
||||
"message": "Expected string, received number"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
|
||||
test("async validation", async () => {
|
||||
const testTuple = z
|
||||
.tuple([z.string().refine(async () => true), z.number().refine(async () => true)])
|
||||
.refine(async () => true);
|
||||
expectTypeOf<typeof testTuple._output>().toEqualTypeOf<[string, number]>();
|
||||
|
||||
const val = await testTuple.parseAsync(["asdf", 1234]);
|
||||
expect(val).toEqual(val);
|
||||
|
||||
const r1 = await testTuple.safeParseAsync(["asdf", "asdf"]);
|
||||
expect(r1.success).toEqual(false);
|
||||
expect(r1.error!).toMatchInlineSnapshot(`
|
||||
[ZodError: [
|
||||
{
|
||||
"code": "invalid_type",
|
||||
"expected": "number",
|
||||
"received": "string",
|
||||
"path": [
|
||||
1
|
||||
],
|
||||
"message": "Expected number, received string"
|
||||
}
|
||||
]]
|
||||
`);
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user