@autometa/overloaded
Advanced tools
| import type { SignatureDefinitionInput } from "../core/signature"; | ||
| import type { OverloadHandler, ValidatorInstance } from "../core/types"; | ||
| export interface DefMetadata { | ||
| readonly name?: string; | ||
| readonly description?: string; | ||
| } | ||
| type ValidatorValues<T extends readonly ValidatorInstance[]> = { | ||
| [K in keyof T]: T[K] extends ValidatorInstance<infer V> ? V : unknown; | ||
| }; | ||
| type DefInput = string | DefMetadata | ValidatorInstance; | ||
| type DefContinuation = <TInputs extends readonly DefInput[]>(...inputs: TInputs) => DefBuilder<ExtractValidators<TInputs>>; | ||
| type ExtractValidators<T extends readonly unknown[]> = T extends readonly [] ? [] : T extends readonly [infer Head, ...infer Rest] ? Head extends ValidatorInstance ? readonly [Head, ...ExtractValidators<Rest extends readonly unknown[] ? Rest : []>] : Head extends string | DefMetadata ? ExtractValidators<Rest extends readonly unknown[] ? Rest : []> : ExtractValidators<Rest extends readonly unknown[] ? Rest : []> : []; | ||
| export interface DefBuilder<TValidators extends readonly ValidatorInstance[]> { | ||
| match<TReturn>(handler: (...args: ValidatorValues<TValidators>) => TReturn): SignatureDefinitionInput; | ||
| throws(error: new (message?: string) => Error, message?: string): SignatureDefinitionInput; | ||
| } | ||
| export declare function def(strings: TemplateStringsArray, ...placeholders: unknown[]): DefContinuation; | ||
| export declare function def<TInputs extends readonly DefInput[]>(...inputs: TInputs): DefBuilder<ExtractValidators<TInputs>>; | ||
| export declare function fallback(handler: OverloadHandler): SignatureDefinitionInput; | ||
| export declare function fallback(description: string, handler: OverloadHandler): SignatureDefinitionInput; | ||
| export declare function fallback(metadata: DefMetadata, handler: OverloadHandler): SignatureDefinitionInput; | ||
| export declare function overloads<TDefinitions extends ReadonlyArray<SignatureDefinitionInput>>(...definitions: TDefinitions): { | ||
| use(args: unknown[]): unknown; | ||
| }; | ||
| export {}; |
| import type { SignatureDefinitionInput } from "../core/signature"; | ||
| import type { OverloadHandler, ThrowsSpec, ValidatorInstance } from "../core/types"; | ||
| export interface SignatureBuilderState { | ||
| readonly name?: string; | ||
| readonly description?: string; | ||
| readonly validators: ValidatorInstance[]; | ||
| readonly handler?: OverloadHandler; | ||
| readonly throws?: ThrowsSpec; | ||
| readonly fallback: boolean; | ||
| } | ||
| export declare class SignatureBuilder { | ||
| private readonly state; | ||
| private constructor(); | ||
| static create(validators: ValidatorInstance[], name?: string, description?: string): SignatureBuilder; | ||
| withHandler(handler: OverloadHandler): SignatureBuilder; | ||
| withThrows(spec: ThrowsSpec): SignatureBuilder; | ||
| markFallback(): SignatureBuilder; | ||
| build(): SignatureDefinitionInput; | ||
| } |
| import type { NormalizedSignature, SignatureFailureReport } from "./types"; | ||
| export declare class AmbiguousOverloadError extends Error { | ||
| readonly matches: ReadonlyArray<NormalizedSignature>; | ||
| constructor(message: string, matches: ReadonlyArray<NormalizedSignature>); | ||
| } | ||
| export declare class NoOverloadMatchedError extends Error { | ||
| readonly args: ReadonlyArray<unknown>; | ||
| readonly failures: ReadonlyArray<SignatureFailureReport>; | ||
| constructor(args: ReadonlyArray<unknown>, failures: ReadonlyArray<SignatureFailureReport>); | ||
| } |
| import { type SignatureDefinitionInput } from "./signature"; | ||
| import type { NormalizedSignature } from "./types"; | ||
| export declare class Matcher { | ||
| private readonly signatures; | ||
| private readonly fallback; | ||
| constructor(signatures: ReadonlyArray<NormalizedSignature>); | ||
| static from(definitions: ReadonlyArray<SignatureDefinitionInput>): Matcher; | ||
| use(args: unknown[]): unknown; | ||
| private evaluateSignature; | ||
| private getBestScore; | ||
| } |
| import type { NormalizedSignature, OverloadHandler, ThrowsSpec, ValidatorInstance } from "./types"; | ||
| export interface SignatureDefinition { | ||
| readonly name?: string; | ||
| readonly description?: string; | ||
| readonly validators: ReadonlyArray<ValidatorInstance>; | ||
| readonly handler?: OverloadHandler; | ||
| readonly throws?: ThrowsSpec; | ||
| readonly fallback?: boolean; | ||
| } | ||
| export declare function normalizeSignatures(definitions: ReadonlyArray<SignatureDefinition>): NormalizedSignature[]; | ||
| export declare function normalizeDefinition(definition: SignatureDefinition, id?: number): NormalizedSignature; | ||
| export type { SignatureDefinition as SignatureDefinitionInput }; |
| export type ValidationPath = Array<string | number>; | ||
| export interface ValidationIssue { | ||
| readonly path: ValidationPath; | ||
| readonly message: string; | ||
| readonly expected?: unknown; | ||
| readonly actual?: unknown; | ||
| } | ||
| export interface ValidationResult<T = unknown> { | ||
| readonly ok: boolean; | ||
| readonly issues: ValidationIssue[]; | ||
| readonly value?: T; | ||
| } | ||
| export interface ValidatorInstance<T = unknown> { | ||
| readonly optional: boolean; | ||
| readonly specificity: number; | ||
| readonly summary: string; | ||
| validate(value: unknown, path: ValidationPath): ValidationResult<T>; | ||
| } | ||
| export type OverloadHandler = (...args: unknown[]) => unknown; | ||
| export interface ThrowsSpec { | ||
| readonly error: new (message?: string) => Error; | ||
| readonly message?: string; | ||
| } | ||
| export interface NormalizedSignature { | ||
| readonly id: number; | ||
| readonly name?: string; | ||
| readonly description?: string; | ||
| readonly validators: ReadonlyArray<ValidatorInstance>; | ||
| readonly minArity: number; | ||
| readonly requiredArity: number; | ||
| readonly maxArity: number; | ||
| readonly specificity: number; | ||
| readonly fallback: boolean; | ||
| readonly handler?: OverloadHandler; | ||
| readonly throws?: ThrowsSpec; | ||
| } | ||
| export type MatchScore = readonly [ | ||
| specificity: number, | ||
| requiredArity: number, | ||
| exactArity: number, | ||
| order: number | ||
| ]; | ||
| export interface SignatureFailureReport { | ||
| readonly signature: NormalizedSignature; | ||
| readonly issues: ValidationIssue[]; | ||
| readonly expected: string[]; | ||
| } |
+1014
| 'use strict'; | ||
| // src/core/errors.ts | ||
| var AmbiguousOverloadError = class extends Error { | ||
| constructor(message, matches) { | ||
| super(message); | ||
| this.name = "AmbiguousOverloadError"; | ||
| this.matches = matches; | ||
| } | ||
| }; | ||
| var NoOverloadMatchedError = class extends Error { | ||
| constructor(args, failures) { | ||
| super(buildMessage(args, failures)); | ||
| this.name = "NoOverloadMatchedError"; | ||
| this.args = args; | ||
| this.failures = failures; | ||
| } | ||
| }; | ||
| function buildMessage(args, failures) { | ||
| const header = `No overload matched for (${args.map(stringifyArg).join(", ")})`; | ||
| const detail = failures.map((failure2) => { | ||
| const signatureLabel = failure2.signature.name ?? `overload#${failure2.signature.id}`; | ||
| const expected = failure2.expected.join(", "); | ||
| const issues = failure2.issues.map((issue) => ` - ${formatPath(issue.path)} ${issue.message}`).join("\n"); | ||
| return [`\u2022 ${signatureLabel}`, ` Expected: ${expected}`, issues].filter(Boolean).join("\n"); | ||
| }).join("\n\n"); | ||
| return [header, detail].filter(Boolean).join("\n\n"); | ||
| } | ||
| function stringifyArg(value) { | ||
| if (value === null) { | ||
| return "null"; | ||
| } | ||
| if (value === void 0) { | ||
| return "undefined"; | ||
| } | ||
| if (typeof value === "string") { | ||
| return `"${value}"`; | ||
| } | ||
| if (typeof value === "function") { | ||
| return value.name ? `[Function ${value.name}]` : "[Function anonymous]"; | ||
| } | ||
| if (typeof value === "object") { | ||
| const ctorName = value?.constructor?.name; | ||
| if (ctorName && ctorName !== "Object") { | ||
| return `[${ctorName}]`; | ||
| } | ||
| try { | ||
| return JSON.stringify(value); | ||
| } catch { | ||
| return "[object]"; | ||
| } | ||
| } | ||
| return String(value); | ||
| } | ||
| function formatPath(path) { | ||
| if (path.length === 0) { | ||
| return ""; | ||
| } | ||
| return path.map((segment) => typeof segment === "number" ? `[${segment}]` : segment).join("."); | ||
| } | ||
| // src/core/signature.ts | ||
| function normalizeSignatures(definitions) { | ||
| return definitions.map((definition, index) => normalizeSignature(definition, index)); | ||
| } | ||
| function normalizeSignature(definition, id) { | ||
| const validators = [...definition.validators]; | ||
| const fallback2 = definition.fallback ?? false; | ||
| const requiredArity = countRequired(validators); | ||
| const minArity = fallback2 ? 0 : requiredArity; | ||
| const maxArity = validators.length; | ||
| const specificity = validators.reduce(sumSpecificity, 0); | ||
| return { | ||
| id, | ||
| validators, | ||
| minArity, | ||
| requiredArity, | ||
| maxArity, | ||
| specificity, | ||
| fallback: fallback2, | ||
| ...definition.name !== void 0 ? { name: definition.name } : {}, | ||
| ...definition.description !== void 0 ? { description: definition.description } : {}, | ||
| ...definition.handler !== void 0 ? { handler: definition.handler } : {}, | ||
| ...definition.throws !== void 0 ? { throws: definition.throws } : {} | ||
| }; | ||
| } | ||
| function countRequired(validators) { | ||
| return validators.reduce((count, validator) => validator.optional ? count : count + 1, 0); | ||
| } | ||
| function sumSpecificity(total, validator) { | ||
| return total + validator.specificity; | ||
| } | ||
| function normalizeDefinition(definition, id = 0) { | ||
| return normalizeSignature(definition, id); | ||
| } | ||
| // src/core/matcher.ts | ||
| var Matcher = class _Matcher { | ||
| constructor(signatures) { | ||
| const normalized = [...signatures]; | ||
| const fallback2 = normalized.find((signature) => signature.fallback); | ||
| this.fallback = fallback2; | ||
| this.signatures = normalized.filter((signature) => !signature.fallback); | ||
| } | ||
| static from(definitions) { | ||
| const signatures = normalizeSignatures(definitions); | ||
| return new _Matcher(signatures); | ||
| } | ||
| use(args) { | ||
| const matches = []; | ||
| const failures = []; | ||
| for (const signature of this.signatures) { | ||
| const evaluation = this.evaluateSignature(signature, args); | ||
| if (evaluation.ok) { | ||
| matches.push({ signature, score: evaluation.score }); | ||
| } else { | ||
| failures.push({ | ||
| signature, | ||
| issues: evaluation.issues, | ||
| expected: signature.validators.map( | ||
| (validator) => validator.optional ? `${validator.summary}?` : validator.summary | ||
| ) | ||
| }); | ||
| } | ||
| } | ||
| if (matches.length === 0) { | ||
| if (this.fallback?.handler) { | ||
| return this.fallback.handler(...args); | ||
| } | ||
| throw new NoOverloadMatchedError(args, failures); | ||
| } | ||
| const bestScore = this.getBestScore(matches.map((match) => match.score)); | ||
| const bestMatches = matches.filter((match) => isSameScore(match.score, bestScore)); | ||
| if (bestMatches.length > 1) { | ||
| throw new AmbiguousOverloadError( | ||
| "Multiple overloads match with identical specificity", | ||
| bestMatches.map((match) => match.signature) | ||
| ); | ||
| } | ||
| const [winnerEntry] = bestMatches; | ||
| if (!winnerEntry) { | ||
| throw new Error("Unable to resolve a matching overload despite scoring."); | ||
| } | ||
| const { signature: winner } = winnerEntry; | ||
| if (winner.throws) { | ||
| const { error, message } = winner.throws; | ||
| throw new error(message); | ||
| } | ||
| if (!winner.handler) { | ||
| throw new Error("Matched overload does not have an associated handler"); | ||
| } | ||
| return winner.handler(...args); | ||
| } | ||
| evaluateSignature(signature, args) { | ||
| const issues = []; | ||
| if (args.length < signature.minArity || args.length > signature.maxArity) { | ||
| issues.push({ | ||
| path: [], | ||
| message: `Received ${args.length} arguments, expected between ${signature.minArity} and ${signature.maxArity}`, | ||
| expected: `${signature.minArity}-${signature.maxArity}`, | ||
| actual: args.length | ||
| }); | ||
| return { ok: false, issues }; | ||
| } | ||
| for (const [index, validator] of signature.validators.entries()) { | ||
| const value = args[index]; | ||
| const path = ["arg", index]; | ||
| if (value === void 0 && index >= args.length) { | ||
| if (!validator.optional) { | ||
| issues.push({ path, message: "Argument is required but missing", expected: validator.summary }); | ||
| return { ok: false, issues }; | ||
| } | ||
| continue; | ||
| } | ||
| if (value === void 0 && validator.optional) { | ||
| continue; | ||
| } | ||
| const result = validator.validate(value, path); | ||
| if (!result.ok) { | ||
| issues.push(...result.issues); | ||
| return { ok: false, issues }; | ||
| } | ||
| } | ||
| if (args.length > signature.validators.length) { | ||
| const extraArgs = args.length - signature.validators.length; | ||
| for (let offset = 0; offset < extraArgs; offset++) { | ||
| const index = signature.validators.length + offset; | ||
| issues.push({ | ||
| path: ["arg", index], | ||
| message: "Unexpected argument", | ||
| actual: args[index] | ||
| }); | ||
| } | ||
| return { ok: false, issues }; | ||
| } | ||
| const score = [ | ||
| signature.specificity, | ||
| signature.requiredArity, | ||
| args.length === signature.validators.length ? 1 : 0, | ||
| signature.id | ||
| ]; | ||
| return { ok: true, score }; | ||
| } | ||
| getBestScore(scores) { | ||
| return scores.reduce((best, current) => { | ||
| if (compareScores(current, best) > 0) { | ||
| return current; | ||
| } | ||
| return best; | ||
| }); | ||
| } | ||
| }; | ||
| function compareScores(a, b) { | ||
| const [aSpecificity, aRequiredArity, aExactArity, aOrder] = a; | ||
| const [bSpecificity, bRequiredArity, bExactArity, bOrder] = b; | ||
| if (aSpecificity !== bSpecificity) { | ||
| return aSpecificity > bSpecificity ? 1 : -1; | ||
| } | ||
| if (aRequiredArity !== bRequiredArity) { | ||
| return aRequiredArity > bRequiredArity ? 1 : -1; | ||
| } | ||
| if (aExactArity !== bExactArity) { | ||
| return aExactArity > bExactArity ? 1 : -1; | ||
| } | ||
| if (aOrder !== bOrder) { | ||
| return aOrder > bOrder ? 1 : -1; | ||
| } | ||
| return 0; | ||
| } | ||
| function isSameScore(a, b) { | ||
| return compareScores(a, b) === 0; | ||
| } | ||
| // src/validators/base.ts | ||
| function createValidator(config) { | ||
| const optional = config.optional ?? false; | ||
| const specificity = config.specificity; | ||
| const summary = config.summary; | ||
| return { | ||
| optional, | ||
| specificity, | ||
| summary, | ||
| validate(value, path) { | ||
| const collected = []; | ||
| const context = createRuntimeContext(path, collected); | ||
| const outcome = config.validate(value, context); | ||
| return normalizeOutcome(outcome, collected, path, summary); | ||
| } | ||
| }; | ||
| } | ||
| function success(value) { | ||
| if (value === void 0) { | ||
| return { ok: true, issues: [] }; | ||
| } | ||
| return { ok: true, issues: [], value }; | ||
| } | ||
| function failure(issue) { | ||
| return { | ||
| ok: false, | ||
| issues: Array.isArray(issue) ? issue : [issue] | ||
| }; | ||
| } | ||
| function createRuntimeContext(path, sink) { | ||
| return { | ||
| path, | ||
| report(issue) { | ||
| sink.push({ | ||
| path: issue.path ?? path, | ||
| message: issue.message, | ||
| expected: issue.expected, | ||
| actual: issue.actual | ||
| }); | ||
| }, | ||
| child(segment) { | ||
| return createRuntimeContext([...path, segment], sink); | ||
| } | ||
| }; | ||
| } | ||
| function normalizeOutcome(outcome, collected, path, summary) { | ||
| if (outcome === void 0) { | ||
| return finalize(collected, path, summary, true); | ||
| } | ||
| if (typeof outcome === "boolean") { | ||
| const ok2 = outcome && collected.length === 0; | ||
| return finalize(collected, path, summary, ok2); | ||
| } | ||
| const mergedIssues = [...collected, ...outcome.issues.map((issue) => ensurePath(issue, path))]; | ||
| const ok = outcome.ok && mergedIssues.length === 0 ? true : outcome.ok; | ||
| const issues = !ok && mergedIssues.length === 0 ? [{ path, message: `Value did not satisfy ${summary}` }] : mergedIssues; | ||
| if (outcome.value === void 0) { | ||
| return { ok, issues }; | ||
| } | ||
| return { ok, issues, value: outcome.value }; | ||
| } | ||
| function ensurePath(issue, fallback2) { | ||
| if (issue.path.length > 0) { | ||
| return issue; | ||
| } | ||
| return { ...issue, path: fallback2 }; | ||
| } | ||
| function finalize(collected, path, summary, ok) { | ||
| if (ok) { | ||
| return { ok: true, issues: [] }; | ||
| } | ||
| const issues = collected.length > 0 ? collected : [{ path, message: `Value did not satisfy ${summary}` }]; | ||
| return { ok: false, issues }; | ||
| } | ||
| // src/validators/primitives.ts | ||
| function string(options = {}) { | ||
| const hasConstraints = options.minLength !== void 0 || options.maxLength !== void 0 || options.pattern !== void 0 || options.predicate !== void 0; | ||
| const specificity = options.specificity ?? (hasConstraints ? 3 : 2); | ||
| const summary = options.summary ?? "string"; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (typeof value !== "string") { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.minLength !== void 0 && value.length < options.minLength) { | ||
| ctx.report({ | ||
| message: `Expected string length \u2265 ${options.minLength}, received ${value.length}`, | ||
| actual: value, | ||
| expected: `${summary} length \u2265 ${options.minLength}` | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.maxLength !== void 0 && value.length > options.maxLength) { | ||
| ctx.report({ | ||
| message: `Expected string length \u2264 ${options.maxLength}, received ${value.length}`, | ||
| actual: value, | ||
| expected: `${summary} length \u2264 ${options.maxLength}` | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.pattern && !options.pattern.test(value)) { | ||
| ctx.report({ | ||
| message: `Expected string to match ${options.pattern}`, | ||
| actual: value, | ||
| expected: `${summary} matching ${options.pattern}` | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.predicate && !options.predicate(value)) { | ||
| ctx.report({ | ||
| message: `String predicate failed`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| }); | ||
| } | ||
| function number(options = {}) { | ||
| const hasConstraints = options.min !== void 0 || options.max !== void 0 || options.integer === true || options.finite === true || options.predicate !== void 0; | ||
| const specificity = options.specificity ?? (hasConstraints ? 3 : 2); | ||
| const summary = options.summary ?? "number"; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (typeof value !== "number" || Number.isNaN(value)) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.finite && !Number.isFinite(value)) { | ||
| ctx.report({ | ||
| message: `Expected finite number`, | ||
| actual: value, | ||
| expected: `${summary} (finite)` | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.integer && !Number.isInteger(value)) { | ||
| ctx.report({ | ||
| message: `Expected integer`, | ||
| actual: value, | ||
| expected: `${summary} (integer)` | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.min !== void 0 && value < options.min) { | ||
| ctx.report({ | ||
| message: `Expected number \u2265 ${options.min}, received ${value}`, | ||
| actual: value, | ||
| expected: `${summary} \u2265 ${options.min}` | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.max !== void 0 && value > options.max) { | ||
| ctx.report({ | ||
| message: `Expected number \u2264 ${options.max}, received ${value}`, | ||
| actual: value, | ||
| expected: `${summary} \u2264 ${options.max}` | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.predicate && !options.predicate(value)) { | ||
| ctx.report({ | ||
| message: `Number predicate failed`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| }); | ||
| } | ||
| function boolean(options = {}) { | ||
| const summary = options.summary ?? "boolean"; | ||
| const specificity = options.specificity ?? 2; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (typeof value !== "boolean") { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| }); | ||
| } | ||
| function literal(expected, options = {}) { | ||
| const values = Array.isArray(expected) ? expected : [expected]; | ||
| const describeLiteral = options.describeValue ?? describeValue; | ||
| const summary = options.summary ?? formatLiteralSummary(values.map((value) => describeLiteral(value))); | ||
| const specificity = options.specificity ?? 5; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (!values.some((candidate) => Object.is(candidate, value))) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| }); | ||
| } | ||
| function unknown(options = {}) { | ||
| const summary = options.summary ?? "unknown"; | ||
| const specificity = options.specificity ?? 0; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate() { | ||
| return true; | ||
| } | ||
| }); | ||
| } | ||
| function func(options = {}) { | ||
| const summary = options.summary ?? "function"; | ||
| const hasArityConstraint = options.arity !== void 0; | ||
| const specificity = options.specificity ?? (hasArityConstraint ? 3 : 2); | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (typeof value !== "function") { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.arity !== void 0 && value.length !== options.arity) { | ||
| ctx.report({ | ||
| message: `Expected function arity ${options.arity}, received ${value.length}`, | ||
| actual: value.length, | ||
| expected: options.arity | ||
| }); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| }); | ||
| } | ||
| function typeOf(ctor, options = {}) { | ||
| const summary = options.summary ?? `typeof ${ctor.name || "<anonymous>"}`; | ||
| const specificity = options.specificity ?? 3; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (value === void 0 && options.optional) { | ||
| return true; | ||
| } | ||
| if (value !== ctor) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| }); | ||
| } | ||
| function describeValue(value) { | ||
| if (value === null) { | ||
| return "null"; | ||
| } | ||
| if (value === void 0) { | ||
| return "undefined"; | ||
| } | ||
| if (typeof value === "string") { | ||
| return `"${value}"`; | ||
| } | ||
| if (typeof value === "number") { | ||
| return Number.isNaN(value) ? "NaN" : value.toString(); | ||
| } | ||
| if (typeof value === "boolean") { | ||
| return value ? "true" : "false"; | ||
| } | ||
| if (typeof value === "function") { | ||
| return value.name ? `[Function ${value.name}]` : "[Function anonymous]"; | ||
| } | ||
| if (Array.isArray(value)) { | ||
| return `[${value.map(describeValue).join(", ")}]`; | ||
| } | ||
| if (typeof value === "object") { | ||
| try { | ||
| return JSON.stringify(value); | ||
| } catch { | ||
| return "[object]"; | ||
| } | ||
| } | ||
| return String(value); | ||
| } | ||
| function formatLiteralSummary(values) { | ||
| const [first, ...rest] = values; | ||
| if (first === void 0) { | ||
| return "<empty>"; | ||
| } | ||
| if (rest.length === 0) { | ||
| return first; | ||
| } | ||
| return [first, ...rest].join(" | "); | ||
| } | ||
| // src/validators/composite.ts | ||
| function array(validator, options = {}) { | ||
| const validators = Array.isArray(validator) ? [...validator] : [validator]; | ||
| const summary = options.summary ?? `array<${validators.map((item) => item.summary).join(" | ") || "unknown"}>`; | ||
| const specificity = options.specificity ?? 3; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (!Array.isArray(value)) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.length !== void 0 && value.length !== options.length) { | ||
| ctx.report({ | ||
| message: `Expected array length ${options.length}, received ${value.length}`, | ||
| actual: value.length, | ||
| expected: options.length | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.minLength !== void 0 && value.length < options.minLength) { | ||
| ctx.report({ | ||
| message: `Expected minimum length ${options.minLength}, received ${value.length}`, | ||
| actual: value.length, | ||
| expected: options.minLength | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.maxLength !== void 0 && value.length > options.maxLength) { | ||
| ctx.report({ | ||
| message: `Expected maximum length ${options.maxLength}, received ${value.length}`, | ||
| actual: value.length, | ||
| expected: options.maxLength | ||
| }); | ||
| return false; | ||
| } | ||
| for (const [index, element] of value.entries()) { | ||
| const elementPath = [...ctx.path, index]; | ||
| let matched = false; | ||
| let issues = []; | ||
| for (const candidate of validators) { | ||
| const result = candidate.validate(element, elementPath); | ||
| if (result.ok) { | ||
| matched = true; | ||
| break; | ||
| } | ||
| issues = [...issues, ...result.issues]; | ||
| } | ||
| if (!matched) { | ||
| if (issues.length > 0) { | ||
| forwardIssues(ctx, issues); | ||
| } else { | ||
| ctx.report({ | ||
| path: elementPath, | ||
| message: `Element did not satisfy ${summary}`, | ||
| actual: element | ||
| }); | ||
| } | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| }); | ||
| } | ||
| function tuple(validators, options = {}) { | ||
| const summary = options.summary ?? `tuple<[${validators.map((item) => item.summary).join(", ")}]>`; | ||
| const specificity = options.specificity ?? 4; | ||
| const requiredCount = validators.reduce((count, validator) => validator.optional ? count : count + 1, 0); | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (!Array.isArray(value)) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| if (value.length < requiredCount) { | ||
| ctx.report({ | ||
| message: `Expected at least ${requiredCount} elements, received ${value.length}`, | ||
| actual: value.length, | ||
| expected: requiredCount | ||
| }); | ||
| return false; | ||
| } | ||
| if (!options.allowExtra && value.length > validators.length) { | ||
| ctx.report({ | ||
| message: `Expected at most ${validators.length} elements, received ${value.length}`, | ||
| actual: value.length, | ||
| expected: validators.length | ||
| }); | ||
| return false; | ||
| } | ||
| for (const [index, validator] of validators.entries()) { | ||
| if (!validator) { | ||
| continue; | ||
| } | ||
| const elementPath = [...ctx.path, index]; | ||
| const element = value[index]; | ||
| if (element === void 0 && index >= value.length) { | ||
| if (!validator.optional) { | ||
| ctx.report({ | ||
| path: elementPath, | ||
| message: "Tuple element is required but missing" | ||
| }); | ||
| return false; | ||
| } | ||
| continue; | ||
| } | ||
| if (element === void 0 && validator.optional) { | ||
| continue; | ||
| } | ||
| const result = validator.validate(element, elementPath); | ||
| if (!result.ok) { | ||
| forwardIssues(ctx, result.issues); | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| }); | ||
| } | ||
| function shape(schema, options = {}) { | ||
| const keys = Object.keys(schema); | ||
| const summary = options.summary ?? `shape<{${keys.join(", ")}}>`; | ||
| const specificity = options.specificity ?? 4; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (typeof value !== "object" || value === null || Array.isArray(value)) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| const record = value; | ||
| for (const key of keys) { | ||
| const validator = schema[key]; | ||
| if (!validator) { | ||
| continue; | ||
| } | ||
| const elementPath = [...ctx.path, key]; | ||
| if (!Object.prototype.hasOwnProperty.call(record, key)) { | ||
| if (!validator.optional) { | ||
| ctx.report({ | ||
| path: elementPath, | ||
| message: "Property is required but missing" | ||
| }); | ||
| return false; | ||
| } | ||
| continue; | ||
| } | ||
| const propertyValue = record[key]; | ||
| const result = validator.validate(propertyValue, elementPath); | ||
| if (!result.ok) { | ||
| forwardIssues(ctx, result.issues); | ||
| return false; | ||
| } | ||
| } | ||
| if (!options.allowUnknownProperties) { | ||
| for (const key of Object.keys(record)) { | ||
| if (!schema[key]) { | ||
| ctx.report({ | ||
| path: [...ctx.path, key], | ||
| message: `Unexpected property "${key}"` | ||
| }); | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| }); | ||
| } | ||
| function union(validators, options = {}) { | ||
| if (validators.length === 0) { | ||
| throw new Error("union requires at least one validator"); | ||
| } | ||
| const summary = options.summary ?? `union<${validators.map((validator) => validator.summary).join(" | ")}>`; | ||
| const specificity = options.specificity ?? validators.reduce((max, validator) => Math.max(max, validator.specificity), 0); | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| const issues = []; | ||
| for (const validator of validators) { | ||
| const result = validator.validate(value, ctx.path); | ||
| if (result.ok) { | ||
| return true; | ||
| } | ||
| issues.push(...result.issues); | ||
| } | ||
| if (issues.length === 0) { | ||
| ctx.report({ | ||
| message: `Value did not satisfy ${summary}`, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| for (const issue of issues) { | ||
| ctx.report(issue); | ||
| } | ||
| return false; | ||
| } | ||
| }); | ||
| } | ||
| function intersection(validators, options = {}) { | ||
| if (validators.length === 0) { | ||
| throw new Error("intersection requires at least one validator"); | ||
| } | ||
| const summary = options.summary ?? `intersection<${validators.map((validator) => validator.summary).join(" & ")}>`; | ||
| const specificity = options.specificity ?? validators.reduce((total, validator) => total + validator.specificity, 0); | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| for (const validator of validators) { | ||
| const result = validator.validate(value, ctx.path); | ||
| if (!result.ok) { | ||
| for (const issue of result.issues) { | ||
| ctx.report(issue); | ||
| } | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| }); | ||
| } | ||
| function instanceOf(ctor, validator, options = {}) { | ||
| const name = ctor.name || "<anonymous>"; | ||
| const summary = options.summary ?? `instanceof ${name}`; | ||
| const specificity = options.specificity ?? (validator ? Math.max(validator.specificity + 1, 4) : 4); | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (value === void 0 && options.optional) { | ||
| return true; | ||
| } | ||
| if (!(value instanceof ctor)) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| if (!validator) { | ||
| return true; | ||
| } | ||
| const result = validator.validate(value, ctx.path); | ||
| if (!result.ok) { | ||
| forwardIssues(ctx, result.issues); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| }); | ||
| } | ||
| function forwardIssues(ctx, issues) { | ||
| for (const issue of issues) { | ||
| ctx.report(issue); | ||
| } | ||
| } | ||
| // src/authoring/signature-builder.ts | ||
| var SignatureBuilder = class _SignatureBuilder { | ||
| constructor(state) { | ||
| this.state = state; | ||
| } | ||
| static create(validators, name, description) { | ||
| const normalizedValidators = [...validators]; | ||
| let state = { | ||
| validators: normalizedValidators, | ||
| fallback: false | ||
| }; | ||
| if (name !== void 0) { | ||
| state = { ...state, name }; | ||
| } | ||
| if (description !== void 0) { | ||
| state = { ...state, description }; | ||
| } | ||
| return new _SignatureBuilder(state); | ||
| } | ||
| withHandler(handler) { | ||
| return new _SignatureBuilder({ ...this.state, handler }); | ||
| } | ||
| withThrows(spec) { | ||
| const nextState = spec.message === void 0 ? { ...this.state, throws: { error: spec.error } } : { ...this.state, throws: spec }; | ||
| return new _SignatureBuilder(nextState); | ||
| } | ||
| markFallback() { | ||
| return new _SignatureBuilder({ ...this.state, fallback: true }); | ||
| } | ||
| build() { | ||
| return { | ||
| validators: this.state.validators, | ||
| fallback: this.state.fallback, | ||
| ...this.state.name ? { name: this.state.name } : {}, | ||
| ...this.state.description ? { description: this.state.description } : {}, | ||
| ...this.state.handler ? { handler: this.state.handler } : {}, | ||
| ...this.state.throws ? { throws: this.state.throws } : {} | ||
| }; | ||
| } | ||
| }; | ||
| // src/authoring/overloads.ts | ||
| function def(...inputs) { | ||
| const [first] = inputs; | ||
| if (isTemplateLiteral(first)) { | ||
| const name = first[0] ?? ""; | ||
| return (...later) => buildDef({ name }, later); | ||
| } | ||
| return buildDef({}, inputs); | ||
| } | ||
| function fallback(...args) { | ||
| const [first, maybeHandler] = args; | ||
| let metadata = {}; | ||
| let handler; | ||
| if (typeof first === "function") { | ||
| handler = first; | ||
| } else if (typeof first === "string") { | ||
| metadata = { description: first }; | ||
| handler = maybeHandler; | ||
| } else { | ||
| metadata = first ?? {}; | ||
| handler = maybeHandler; | ||
| } | ||
| if (typeof handler !== "function") { | ||
| throw new Error("fallback requires a handler function"); | ||
| } | ||
| const builder = SignatureBuilder.create([], metadata.name ?? "fallback", metadata.description).withHandler(handler).markFallback(); | ||
| return builder.build(); | ||
| } | ||
| function overloads(...definitions) { | ||
| const matcher = Matcher.from(definitions); | ||
| return { | ||
| use(args) { | ||
| return matcher.use(args); | ||
| } | ||
| }; | ||
| } | ||
| function buildDef(initialMetadata, inputs) { | ||
| const { metadata, validators } = splitMetadataAndValidators(inputs, initialMetadata); | ||
| if (validators.length === 0) { | ||
| throw new Error("def requires at least one validator"); | ||
| } | ||
| const builder = SignatureBuilder.create([...validators], metadata.name, metadata.description); | ||
| return { | ||
| match(handler) { | ||
| return builder.withHandler(handler).build(); | ||
| }, | ||
| throws(errorCtor, message) { | ||
| const spec = message === void 0 ? { error: errorCtor } : { error: errorCtor, message }; | ||
| return builder.withThrows(spec).build(); | ||
| } | ||
| }; | ||
| } | ||
| function splitMetadataAndValidators(inputs, initial) { | ||
| const queue = [...inputs]; | ||
| let metadata = { ...initial }; | ||
| if (queue.length > 0 && typeof queue[0] === "string") { | ||
| const description = queue.shift(); | ||
| if (description.length > 0) { | ||
| metadata = { ...metadata, description }; | ||
| } | ||
| } | ||
| if (queue.length > 0 && isMetadata(queue[0])) { | ||
| const metaArg = queue.shift(); | ||
| metadata = { ...metadata, ...metaArg }; | ||
| } | ||
| const validators = []; | ||
| for (const candidate of queue) { | ||
| if (!isValidator(candidate)) { | ||
| throw new Error("def expects validators after metadata"); | ||
| } | ||
| validators.push(candidate); | ||
| } | ||
| return { metadata, validators }; | ||
| } | ||
| function isValidator(value) { | ||
| return Boolean(value) && typeof value === "object" && typeof value.validate === "function"; | ||
| } | ||
| function isMetadata(value) { | ||
| if (!value || typeof value !== "object") { | ||
| return false; | ||
| } | ||
| if (isValidator(value)) { | ||
| return false; | ||
| } | ||
| const candidate = value; | ||
| return "name" in candidate || "description" in candidate; | ||
| } | ||
| function isTemplateLiteral(value) { | ||
| return Array.isArray(value) && Object.prototype.hasOwnProperty.call(value, "raw"); | ||
| } | ||
| exports.AmbiguousOverloadError = AmbiguousOverloadError; | ||
| exports.Matcher = Matcher; | ||
| exports.NoOverloadMatchedError = NoOverloadMatchedError; | ||
| exports.SignatureBuilder = SignatureBuilder; | ||
| exports.array = array; | ||
| exports.boolean = boolean; | ||
| exports.createValidator = createValidator; | ||
| exports.def = def; | ||
| exports.failure = failure; | ||
| exports.fallback = fallback; | ||
| exports.func = func; | ||
| exports.instanceOf = instanceOf; | ||
| exports.intersection = intersection; | ||
| exports.literal = literal; | ||
| exports.normalizeDefinition = normalizeDefinition; | ||
| exports.normalizeSignatures = normalizeSignatures; | ||
| exports.number = number; | ||
| exports.overloads = overloads; | ||
| exports.shape = shape; | ||
| exports.string = string; | ||
| exports.success = success; | ||
| exports.tuple = tuple; | ||
| exports.typeOf = typeOf; | ||
| exports.union = union; | ||
| exports.unknown = unknown; | ||
| //# sourceMappingURL=out.js.map | ||
| //# sourceMappingURL=index.cjs.map |
Sorry, the diff of this file is too big to display
| import type { ValidationIssue, ValidationPath, ValidationResult, ValidatorInstance } from "../core/types"; | ||
| export interface ValidatorOptions { | ||
| readonly optional?: boolean; | ||
| readonly specificity?: number; | ||
| } | ||
| export interface ValidatorRuntimeContext { | ||
| readonly path: ValidationPath; | ||
| report(issue: ReportableIssue): void; | ||
| child(segment: string | number): ValidatorRuntimeContext; | ||
| } | ||
| export interface ReportableIssue { | ||
| readonly message: string; | ||
| readonly expected?: unknown; | ||
| readonly actual?: unknown; | ||
| readonly path?: ValidationPath; | ||
| } | ||
| export type ValidatorOutcome<T> = boolean | void | ValidationResult<T>; | ||
| export interface CreateValidatorConfig<T> { | ||
| readonly summary: string; | ||
| readonly specificity: number; | ||
| readonly optional?: boolean; | ||
| readonly validate: (value: unknown, ctx: ValidatorRuntimeContext) => ValidatorOutcome<T>; | ||
| } | ||
| export declare function createValidator<T>(config: CreateValidatorConfig<T>): ValidatorInstance<T>; | ||
| export declare function success<T>(value?: T): ValidationResult<T>; | ||
| export declare function failure(issue: ValidationIssue | ValidationIssue[]): ValidationResult<never>; |
| import type { ValidatorInstance } from "../core/types"; | ||
| import { type ValidatorOptions } from "./base"; | ||
| export interface ArrayValidatorOptions extends ValidatorOptions { | ||
| readonly minLength?: number; | ||
| readonly maxLength?: number; | ||
| readonly length?: number; | ||
| readonly summary?: string; | ||
| } | ||
| export interface TupleValidatorOptions extends ValidatorOptions { | ||
| readonly allowExtra?: boolean; | ||
| readonly summary?: string; | ||
| } | ||
| export interface ShapeValidatorOptions extends ValidatorOptions { | ||
| readonly allowUnknownProperties?: boolean; | ||
| readonly summary?: string; | ||
| } | ||
| export interface UnionValidatorOptions extends ValidatorOptions { | ||
| readonly summary?: string; | ||
| } | ||
| export interface IntersectionValidatorOptions extends ValidatorOptions { | ||
| readonly summary?: string; | ||
| } | ||
| export interface InstanceValidatorOptions extends ValidatorOptions { | ||
| readonly summary?: string; | ||
| } | ||
| type ValidatorValue<T> = T extends ValidatorInstance<infer V> ? V : never; | ||
| type UnionValues<T extends readonly ValidatorInstance[]> = ValidatorValue<T[number]>; | ||
| type IntersectionValues<T extends readonly ValidatorInstance[]> = T extends readonly [infer Head, ...infer Rest] ? Head extends ValidatorInstance<infer V> ? Rest extends readonly ValidatorInstance[] ? V & IntersectionValues<Rest> : V : never : unknown; | ||
| export declare function array<T>(validator: ValidatorInstance<T> | ReadonlyArray<ValidatorInstance<T>>, options?: ArrayValidatorOptions): ValidatorInstance<T[]>; | ||
| export declare function tuple<T extends readonly ValidatorInstance[]>(validators: T, options?: TupleValidatorOptions): ValidatorInstance<unknown[]>; | ||
| export declare function shape<TSchema extends Record<string, ValidatorInstance>>(schema: TSchema, options?: ShapeValidatorOptions): ValidatorInstance<Record<string, unknown>>; | ||
| export declare function union<T extends readonly ValidatorInstance[]>(validators: T, options?: UnionValidatorOptions): ValidatorInstance<UnionValues<T>>; | ||
| export declare function intersection<T extends readonly ValidatorInstance[]>(validators: T, options?: IntersectionValidatorOptions): ValidatorInstance<IntersectionValues<T>>; | ||
| export declare function instanceOf<T>(ctor: new (...args: never[]) => T, validator?: ValidatorInstance, options?: InstanceValidatorOptions): ValidatorInstance<T>; | ||
| export {}; |
| import type { ValidatorInstance } from "../core/types"; | ||
| import { type ValidatorOptions } from "./base"; | ||
| export interface StringValidatorOptions extends ValidatorOptions { | ||
| readonly minLength?: number; | ||
| readonly maxLength?: number; | ||
| readonly pattern?: RegExp; | ||
| readonly predicate?: (value: string) => boolean; | ||
| readonly summary?: string; | ||
| } | ||
| export interface NumberValidatorOptions extends ValidatorOptions { | ||
| readonly min?: number; | ||
| readonly max?: number; | ||
| readonly integer?: boolean; | ||
| readonly finite?: boolean; | ||
| readonly predicate?: (value: number) => boolean; | ||
| readonly summary?: string; | ||
| } | ||
| export interface BooleanValidatorOptions extends ValidatorOptions { | ||
| readonly summary?: string; | ||
| } | ||
| export interface LiteralValidatorOptions<T> extends ValidatorOptions { | ||
| readonly summary?: string; | ||
| readonly describeValue?: (value: T) => string; | ||
| } | ||
| export interface UnknownValidatorOptions extends ValidatorOptions { | ||
| readonly summary?: string; | ||
| } | ||
| export interface FunctionValidatorOptions extends ValidatorOptions { | ||
| readonly arity?: number; | ||
| readonly summary?: string; | ||
| } | ||
| export interface TypeOfValidatorOptions extends ValidatorOptions { | ||
| readonly summary?: string; | ||
| } | ||
| export declare function string(options?: StringValidatorOptions): ValidatorInstance<string>; | ||
| export declare function number(options?: NumberValidatorOptions): ValidatorInstance<number>; | ||
| export declare function boolean(options?: BooleanValidatorOptions): ValidatorInstance<boolean>; | ||
| export declare function literal<T>(expectedValue: T, options?: LiteralValidatorOptions<T>): ValidatorInstance<T>; | ||
| export declare function literal<T>(expectedValues: ReadonlyArray<T>, options?: LiteralValidatorOptions<T>): ValidatorInstance<T>; | ||
| export declare function unknown(options?: UnknownValidatorOptions): ValidatorInstance<unknown>; | ||
| export declare function func(options?: FunctionValidatorOptions): ValidatorInstance<(...args: unknown[]) => unknown>; | ||
| export declare function typeOf<TConstructor extends new (...args: never[]) => unknown>(ctor: TConstructor, options?: TypeOfValidatorOptions): ValidatorInstance<TConstructor>; | ||
| export declare function describeValue(value: unknown): string; |
+10
-517
@@ -1,517 +0,10 @@ | ||
| import * as myzod from 'myzod'; | ||
| import { Infer } from 'myzod'; | ||
| import * as myzod_libs_types from 'myzod/libs/types'; | ||
| declare class Accumulator<T> extends Array<T | Accumulator<T>> { | ||
| asString(depth?: number): string; | ||
| } | ||
| declare const ShapeValidationSchema: myzod.ObjectType<{ | ||
| exhaustive: myzod.OptionalType<myzod.BooleanType>; | ||
| instance: myzod.OptionalType<myzod.ObjectType<{}>>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type ShapeOptions = Infer<typeof ShapeValidationSchema>; | ||
| type ShapeValidatorOpts = Infer<typeof ShapeValidationSchema>; | ||
| declare class ShapeArgument<T extends ShapeType, TRaw extends FromShape<T>> extends BaseArgument<TRaw> { | ||
| typeName: string; | ||
| options?: ShapeOptions; | ||
| reference: T; | ||
| constructor(args: (string | T | ShapeOptions)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertObject(value: unknown): void; | ||
| assertExhaustive(value: unknown): void; | ||
| assertShapeMatches(value: unknown | undefined | null): void; | ||
| assertIsInstance(value: unknown, instance?: any): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function shape<T extends ShapeType>(reference: T): ShapeArgument<T, FromShape<T>>; | ||
| declare function shape<T extends ShapeType>(name: string, reference: T): ShapeArgument<T, FromShape<T>>; | ||
| declare function shape<T extends ShapeType>(name: string, reference: T, options?: ShapeOptions): ShapeArgument<T, FromShape<T>>; | ||
| declare function shape<T extends ShapeType>(reference: T, options?: ShapeOptions): ShapeArgument<T, FromShape<T>>; | ||
| type OverloadAction = (...args: any[]) => any; | ||
| declare class Overload<TArgs extends AnyArg[], TAction extends OverloadAction> { | ||
| readonly name: string | undefined; | ||
| readonly description: string | undefined; | ||
| readonly args: TArgs; | ||
| readonly actionOrError: TAction | Error; | ||
| readonly fallback: boolean; | ||
| constructor(name: string | undefined, description: string | undefined, args: TArgs, actionOrError: TAction | Error, fallback?: boolean); | ||
| isMatch(args: ArgumentType[]): boolean; | ||
| typeStringArray(): string[]; | ||
| getReport(index: number, realArgs: unknown[]): string; | ||
| } | ||
| type AnyArg = BaseArgument<ArgumentType>; | ||
| type ValidatorArgumentTuple<T> = { | ||
| [K in keyof T]: T[K] extends AnyArg ? T[K] extends ShapeArgument<infer _, infer TShape> ? TShape : T[K] extends BaseArgument<infer Q> ? Q : never : never; | ||
| }; | ||
| type ArgumentTypes<T> = { | ||
| [K in keyof T]: T[K] extends AnyArg ? T[K] extends infer U ? U : never : never; | ||
| }; | ||
| type ReturnTypeTuple<T> = { | ||
| [K in keyof T]: T[K] extends Overload<infer _TArgs, infer TAction> ? ReturnType<TAction> extends [infer THead, ...infer TTail] ? [THead, ...TTail] : ReturnType<TAction> : never; | ||
| }; | ||
| type ReturnTypes<T> = T extends Overload<AnyArg[], OverloadAction>[] ? ReturnTypeTuple<T> extends infer K ? K extends unknown[] ? K[number] : never : never : never; | ||
| type AnyType = any; | ||
| type Primitive = string | number | boolean | undefined | null; | ||
| type Ephemeral = unknown; | ||
| type Shape = { | ||
| [key: string]: ArgumentType; | ||
| }; | ||
| type Array$1 = { | ||
| [key: number]: ArgumentType; | ||
| }; | ||
| type Tuple = [ArgumentType, ...ArgumentType[]]; | ||
| type ArgumentType = Shape | Array$1 | Tuple | Primitive | Ephemeral; | ||
| type CamelCase<T extends string> = T extends `${infer _TPrefix} ${infer _TSuffix}` ? { | ||
| error: `argument names should not contain spaces. Please update '${T}'`; | ||
| } : T; | ||
| type FromTuple<T extends BaseArgument<ArgumentType>[]> = { | ||
| [key in keyof T]: T[key] extends BaseArgument<infer K> ? K : never; | ||
| }; | ||
| type TupleType = [AnyArg, ...AnyArg[]]; | ||
| type ShapeType = { | ||
| [key: string]: AnyArg; | ||
| }; | ||
| type InstanceType<T extends Record<string, unknown>> = { | ||
| [K in keyof T]: T[K]; | ||
| }; | ||
| type FromShape<T> = T extends ShapeType ? { | ||
| [K in keyof T]: T[K] extends BaseArgument<infer TArg> ? TArg : T[K] extends ShapeArgument<infer _, infer TShape> ? TShape : never; | ||
| } : never; | ||
| type InferArg<T> = { | ||
| [K in keyof T]: T[K] extends BaseArgument<infer TArg> ? TArg : T[K] extends ShapeArgument<infer _, infer TShape> ? TShape : never; | ||
| }; | ||
| type FromFunction<T extends BaseArgument<ArgumentType>[]> = { | ||
| [key in keyof T]: T[key] extends BaseArgument<infer K> ? K : never; | ||
| }; | ||
| type FunctionType = (...args: AnyType[]) => AnyType | void | Promise<AnyType | void>; | ||
| type Class<T> = { | ||
| new (...args: any): T; | ||
| }; | ||
| type AbstractClass<T> = Function & { | ||
| prototype: T; | ||
| }; | ||
| declare const BaseArgumentSchema: myzod.ObjectType<{ | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type ArgumentOptions = Infer<typeof BaseArgumentSchema>; | ||
| declare abstract class BaseArgument<TType> { | ||
| #private; | ||
| example?: TType; | ||
| abstract typeName: string; | ||
| protected _accumulator: Accumulator<string>; | ||
| readonly options?: ArgumentOptions; | ||
| argName?: string; | ||
| argCategory: string; | ||
| get accumulator(): Accumulator<string>; | ||
| get index(): number; | ||
| get identifier(): string | number; | ||
| withIndex(index: number): this; | ||
| abstract isTypeMatch(type: unknown): boolean; | ||
| baseAssertions(value?: unknown): asserts value; | ||
| assertIsDefined(value: unknown, optional?: boolean | { | ||
| undefined?: boolean | undefined; | ||
| null?: boolean | undefined; | ||
| } | undefined): void; | ||
| assertTestSucceeds(value: unknown, test?: unknown): void; | ||
| protected shouldAssert(value: unknown, optional?: boolean | { | ||
| undefined?: boolean | undefined; | ||
| null?: boolean | undefined; | ||
| } | undefined): boolean; | ||
| abstract validate(value: unknown, parent?: BaseArgument<ArgumentType>): boolean; | ||
| protected fmt(message: string, padDepth?: number): string; | ||
| or<K>(second: BaseArgument<K>): BaseArgument<TType | K>; | ||
| } | ||
| declare class UnionArgument<T, K> extends BaseArgument<T | K> { | ||
| readonly first: BaseArgument<T>; | ||
| readonly second: BaseArgument<K>; | ||
| get typeName(): string; | ||
| constructor(first: BaseArgument<T>, second: BaseArgument<K>); | ||
| assertUnion(actual: T | K): void; | ||
| isTypeMatch(type: unknown): boolean; | ||
| validate(value: T | K): boolean; | ||
| } | ||
| declare function or<T, K>(first: BaseArgument<T>, second: BaseArgument<K>): BaseArgument<T | K>; | ||
| declare const StringValidatorOpsSchema: myzod.ObjectType<{ | ||
| minLength: myzod.OptionalType<myzod.NumberType>; | ||
| maxLength: myzod.OptionalType<myzod.NumberType>; | ||
| includes: myzod.OptionalType<myzod.StringType>; | ||
| equals: myzod.OptionalType<myzod.StringType>; | ||
| in: myzod.OptionalType<myzod.ArrayType<myzod.StringType>>; | ||
| startsWith: myzod.OptionalType<myzod.StringType>; | ||
| endsWith: myzod.OptionalType<myzod.StringType>; | ||
| pattern: myzod.OptionalType<myzod.ObjectType<{ | ||
| source: myzod.StringType; | ||
| }>>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type StringValidatorOpts = Infer<typeof StringValidatorOpsSchema> & { | ||
| pattern?: RegExp; | ||
| test?: (arg: string) => boolean; | ||
| }; | ||
| declare class StringArgument<T extends string> extends BaseArgument<T> { | ||
| typeName: string; | ||
| options?: StringValidatorOpts; | ||
| constructor(args?: (string | StringValidatorOpts)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertStringLessThanMax(str: string, max?: number | undefined): void; | ||
| assertStringGreaterThanMin(str: unknown, min?: number | undefined): void; | ||
| assertStringIncludes(str: unknown, value?: string | undefined): void; | ||
| assertStringIn(str: unknown, value?: string[] | undefined): void; | ||
| assertStringEquals(str: unknown, value?: string | undefined): void; | ||
| assertStringMatches(str: unknown, pattern?: ({ | ||
| source: string; | ||
| } & RegExp) | undefined): void; | ||
| assertString(str?: unknown): void; | ||
| assertinArray(str: unknown, array?: string[] | undefined): void; | ||
| validate(value: string): boolean; | ||
| } | ||
| declare function string(): StringArgument<string>; | ||
| declare function string(opts: StringValidatorOpts): StringArgument<string>; | ||
| declare function string(name: string): StringArgument<string>; | ||
| declare function string(name: string, opts: StringValidatorOpts): BaseArgument<string>; | ||
| declare const NumberValidationSchema: myzod.ObjectType<{ | ||
| max: myzod.OptionalType<myzod.NumberType>; | ||
| min: myzod.OptionalType<myzod.NumberType>; | ||
| equals: myzod.OptionalType<myzod.NumberType>; | ||
| type: myzod.OptionalType<myzod.UnionType<[myzod_libs_types.LiteralType<"int">, myzod_libs_types.LiteralType<"float">]>>; | ||
| in: myzod.OptionalType<myzod.ArrayType<myzod.NumberType>>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type NumberValidatorOpts = Infer<typeof NumberValidationSchema> & { | ||
| test: (arg: number) => boolean; | ||
| }; | ||
| declare class NumberArgument<T extends number> extends BaseArgument<T> { | ||
| typeName: string; | ||
| options?: NumberValidatorOpts | undefined; | ||
| constructor(args: (NumberValidatorOpts | string)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertNumber(num?: unknown): void; | ||
| assertNumberEquals(num: unknown, equals?: number | undefined): void; | ||
| assertNumberLessThanMax(num: unknown, max?: number | undefined): void; | ||
| assertNumberGreaterThanMin(num: unknown, min?: number | undefined): void; | ||
| assertInArray(val: unknown, value?: number): boolean | undefined; | ||
| assertType(value: unknown, type?: "int" | "float" | undefined): void; | ||
| validate(value: number): boolean; | ||
| } | ||
| declare function number(): NumberArgument<number>; | ||
| declare function number(opts: NumberValidatorOpts): NumberArgument<number>; | ||
| declare function number(name: string): NumberArgument<number>; | ||
| declare function number(name: string, opts: NumberValidatorOpts): NumberArgument<number>; | ||
| declare const BooleaValidationSchema: myzod.ObjectType<{ | ||
| equals: myzod.OptionalType<myzod.BooleanType>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type BooleanValidatorOpts = Infer<typeof BooleaValidationSchema>; | ||
| declare class BooleanArgument<T extends boolean = boolean> extends BaseArgument<T> { | ||
| typeName: string; | ||
| options?: BooleanValidatorOpts; | ||
| constructor(args: (BooleanValidatorOpts | string)[]); | ||
| assertBoolean(actual?: boolean): asserts actual; | ||
| assertEquals(actual: boolean): void; | ||
| isTypeMatch(type: unknown): boolean; | ||
| validate(value: boolean): boolean; | ||
| } | ||
| declare function boolean(): BooleanArgument<boolean>; | ||
| declare function boolean(opts: BooleanValidatorOpts): BooleanArgument<boolean>; | ||
| declare function boolean(name: string): BooleanArgument<boolean>; | ||
| declare function boolean(name: string, opts: BooleanValidatorOpts): BaseArgument<boolean>; | ||
| type FromArray<T> = T extends infer TArray ? TArray extends BaseArgument<infer TArg>[] ? TArg[] : never : never; | ||
| type ArrayType = AnyArg[]; | ||
| declare const ArrayValidationSchema: myzod.ObjectType<{ | ||
| maxLength: myzod.OptionalType<myzod.NumberType>; | ||
| minLength: myzod.OptionalType<myzod.NumberType>; | ||
| length: myzod.OptionalType<myzod.NumberType>; | ||
| includes: myzod.OptionalType<myzod.UnknownType>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type ArrayValidatorOpts = Infer<typeof ArrayValidationSchema>; | ||
| declare class ArrayArgument<T extends ArrayType, TRaw extends FromArray<T>> extends BaseArgument<TRaw> { | ||
| typeName: string; | ||
| types: string[]; | ||
| options: ArrayValidatorOpts; | ||
| reference: T; | ||
| constructor(args: (string | T | ArrayValidatorOpts)[]); | ||
| assertIsArray(values: unknown): void; | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertLengthLessThanMax(values: unknown, length?: number | undefined): void; | ||
| assertLengthGreaterThanMin(values: unknown, length?: number | undefined): void; | ||
| assertLengthEquals(values: unknown, length?: number | undefined): void; | ||
| assertIncludes(values: unknown, item?: unknown): void; | ||
| assertPermittedType(values: unknown): void; | ||
| assertChildValidations(values: unknown): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function array<P extends AnyArg[], T extends ArgumentTypes<P>>(name: string, acceptedTypes: T): ArrayArgument<P, FromArray<T>>; | ||
| declare function array<P extends AnyArg[], T extends ArgumentTypes<P>>(acceptedTypes: T): ArrayArgument<P, FromArray<T>>; | ||
| declare function array<P extends AnyArg[], T extends ArgumentTypes<P>>(name: string, acceptedTypes: T, options: ArrayValidatorOpts): ArrayArgument<P, FromArray<T>>; | ||
| declare function array<P extends AnyArg[], T extends ArgumentTypes<P>>(acceptedTypes: T, options: ArrayValidatorOpts): ArrayArgument<P, FromArray<T>>; | ||
| declare const TupleValidationSchema: myzod.ObjectType<{ | ||
| includes: myzod.OptionalType<myzod.UnknownType>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type TupleValidatorOpts = Infer<typeof TupleValidationSchema>; | ||
| declare class TupleArgument<T extends TupleType, TRaw extends FromTuple<T>> extends BaseArgument<TRaw> { | ||
| options?: TupleValidatorOpts; | ||
| typeName: string; | ||
| types: string[]; | ||
| readonly reference: T; | ||
| constructor(args: (string | T | TupleValidatorOpts)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertIsTuple(values: unknown): asserts values is T; | ||
| assertIncludes(values: unknown, item?: unknown): void; | ||
| assertLength(values: unknown[], length?: number): void; | ||
| assertPermittedType(values: unknown): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function tuple<P extends TupleType, T extends ArgumentTypes<P>>(name: string, acceptedTypes: T, options?: TupleValidatorOpts): TupleArgument<T, FromTuple<T>>; | ||
| declare function tuple<P extends TupleType, T extends ArgumentTypes<P>>(acceptedTypes: T, options?: TupleValidatorOpts): TupleArgument<T, FromTuple<T>>; | ||
| declare const DateValidationOptsSchema: myzod.ObjectType<{ | ||
| before: myzod.OptionalType<myzod.DateType>; | ||
| after: myzod.OptionalType<myzod.DateType>; | ||
| equals: myzod.OptionalType<myzod.DateType>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type DateValidatorOpts = Infer<typeof DateValidationOptsSchema>; | ||
| declare const DateConstructorArgumentSchema: myzod.ArrayType<myzod.UnionType<[myzod.StringType, myzod.OptionalType<myzod.ObjectType<{ | ||
| before: myzod.OptionalType<myzod.DateType>; | ||
| after: myzod.OptionalType<myzod.DateType>; | ||
| equals: myzod.OptionalType<myzod.DateType>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>>]>>; | ||
| type DateArguments = Infer<typeof DateConstructorArgumentSchema>; | ||
| declare class DateArgument<T extends Date> extends BaseArgument<T> { | ||
| typeName: string; | ||
| isTypeMatch(type: unknown): boolean; | ||
| options?: DateValidatorOpts; | ||
| constructor(args: DateArguments); | ||
| assertBefore(value: unknown, before?: Date | undefined): void; | ||
| assertAfter(value: unknown, after?: Date | undefined): void; | ||
| assertEquals(value: unknown, equals?: Date | undefined): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function date(): DateArgument<Date>; | ||
| declare function date(name: string): DateArgument<Date>; | ||
| declare function date(name: string, options: DateValidatorOpts): DateArgument<Date>; | ||
| declare function date(options: DateValidatorOpts): DateArgument<Date>; | ||
| declare class UnknownArgument<T extends unknown> extends BaseArgument<T> { | ||
| typeName: string; | ||
| options?: ArgumentOptions; | ||
| constructor(args: (string | ArgumentOptions)[]); | ||
| isTypeMatch(_type: unknown): boolean; | ||
| validate(_value: number): boolean; | ||
| } | ||
| declare function unknown(): UnknownArgument<unknown>; | ||
| declare function unknown(name: string, opts: ArgumentOptions): UnknownArgument<unknown>; | ||
| declare function unknown(opts: ArgumentOptions): UnknownArgument<unknown>; | ||
| declare const InstanceOptionsArgumentSchema: myzod.ObjectType<{ | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type InstanceOptions = Infer<typeof InstanceOptionsArgumentSchema>; | ||
| declare class InstanceArgument<TClass extends { | ||
| constructor: unknown; | ||
| }, TShape extends ShapeArgument<any, Partial<TClass>>> extends BaseArgument<TClass> { | ||
| typeName: string; | ||
| blueprint: Class<TClass>; | ||
| options?: InstanceOptions; | ||
| shape: TShape; | ||
| constructor(args: (string | Class<TClass> | TShape)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertIsInstance(value: unknown): void; | ||
| assertShapeArguments(value: unknown): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function instance<TClass extends { | ||
| constructor: unknown; | ||
| }, TShape extends ShapeArgument<any, Partial<TClass>>>(blueprint: Class<TClass> | AbstractClass<TClass>, shape?: TShape | null, options?: InstanceOptions): InstanceArgument<TClass, TShape>; | ||
| declare function instance<TClass extends { | ||
| constructor: unknown; | ||
| }, TShape extends ShapeArgument<any, Partial<TClass>>>(name: string, blueprint: Class<TClass> | AbstractClass<TClass>, shape?: TShape | null, options?: InstanceOptions): InstanceArgument<TClass, TShape>; | ||
| declare const FunctionValidationSchema: myzod.ObjectType<{ | ||
| maxArgLength: myzod.OptionalType<myzod.NumberType>; | ||
| minArgLength: myzod.OptionalType<myzod.NumberType>; | ||
| argLength: myzod.OptionalType<myzod.NumberType>; | ||
| name: myzod.OptionalType<myzod.StringType>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type FunctionValidatorOptions = Infer<typeof FunctionValidationSchema>; | ||
| declare class FunctionArgument<T extends FunctionType> extends BaseArgument<T> { | ||
| typeName: string; | ||
| types: string[]; | ||
| readonly name?: string; | ||
| readonly options?: FunctionValidatorOptions; | ||
| constructor(args: (string | FunctionValidatorOptions | undefined)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertIsFunction(value: unknown): asserts value is T; | ||
| assertLengthLessThanMax(value: unknown, length?: number | undefined): void; | ||
| assertLengthGreaterThanMin(value: unknown, length?: number | undefined): void; | ||
| assertLengthEquals(value: unknown, length?: number | undefined): void; | ||
| assertName(value: unknown, name?: string | undefined): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function func<T extends FunctionType>(): FunctionArgument<T>; | ||
| declare function func<T extends FunctionType>(name: string): FunctionArgument<T>; | ||
| declare function func<T extends FunctionType>(name: string, options?: FunctionValidatorOptions): FunctionArgument<T>; | ||
| declare function func<T extends FunctionType>(options: FunctionValidatorOptions): FunctionArgument<T>; | ||
| declare const NilValidatorOpsSchema: myzod.ObjectType<{ | ||
| equals: myzod.OptionalType<myzod.UnionType<[myzod_libs_types.LiteralType<"null">, myzod_libs_types.LiteralType<"undefined">]>>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type NilValidatorOpts = Infer<typeof NilValidatorOpsSchema> & { | ||
| pattern?: RegExp; | ||
| }; | ||
| declare class NilArgument<T extends null | undefined> extends BaseArgument<T> { | ||
| typeName: string; | ||
| options?: NilValidatorOpts; | ||
| constructor(args?: (string | NilValidatorOpts)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertIsNullOrUndefined(value: unknown): void; | ||
| assertIsNull(value: unknown): void; | ||
| assertIsUndefined(value: unknown): void; | ||
| validate(value: string): boolean; | ||
| } | ||
| declare function nil(): NilArgument<null | undefined>; | ||
| declare function nil(opts: NilValidatorOpts): NilArgument<null | undefined>; | ||
| declare function nil(name: string): NilArgument<null | undefined>; | ||
| declare function nil(name: string, opts: NilValidatorOpts): BaseArgument<null | undefined>; | ||
| declare class TypeArgument<T extends Class<unknown> | AbstractClass<unknown>> extends BaseArgument<T> { | ||
| typeName: string; | ||
| types: string[]; | ||
| readonly name?: string; | ||
| readonly type: T; | ||
| constructor(strOrT: string | T, type?: T); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertType(value: unknown, match?: T): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function type<T extends Class<unknown> | AbstractClass<unknown>>(type: T): TypeArgument<T>; | ||
| declare function type<T extends Class<unknown> | AbstractClass<unknown>>(name: string, type: Class<T>): TypeArgument<T>; | ||
| /** | ||
| * Entrypoint for overload implementations. Accepts parameter validators and their matching | ||
| * function implementations. Once complete, pass the function args to `.use(args)` to execute | ||
| * your overloads. If none are matching and no fallback is provided, an error will be thrown. | ||
| * | ||
| * ```ts | ||
| * function foo(a: string, b: number): void; | ||
| * function foo(...args: (string | number)[]){ | ||
| * return overloads( | ||
| * def(string(), number()).match((a, b)=>{...}) | ||
| * fallback().match((a, b)=>{...}) | ||
| * ).use(args) | ||
| * } | ||
| * ``` | ||
| * @param args | ||
| * @returns | ||
| */ | ||
| declare function overloads<T extends Overload<AnyArg[], OverloadAction>[]>(...args: T): { | ||
| use: (actualArgs: unknown[]) => ReturnTypes<T>; | ||
| }; | ||
| /** | ||
| * Creates a new set of parameters which should match one overloaded | ||
| * function/method implementation. Returns an object containing a matcher | ||
| * function which will be executed when the arguments match the params list | ||
| * | ||
| * ```ts | ||
| * function foo(a: string, b: number): void; | ||
| * function foo(...args: (string | number)[]){ | ||
| * return overloads( | ||
| * def(string(), number()).match((a, b)=>{ | ||
| * const modifiedA = doStringThing(a); | ||
| * const modifiedB = doNumberThing(modifiedA, b); | ||
| * }) | ||
| * ).use(args) | ||
| * } | ||
| * ``` | ||
| * @param args - a rest argument of Arguments, provided by type functions (`string()`, `number()` etc) | ||
| * @returns | ||
| */ | ||
| declare function def(name: TemplateStringsArray): ((<P extends AnyArg[], T extends ArgumentTypes<P>>(description: string, ...args: T) => ParamReturn<P, T>) & (<P extends AnyArg[], T extends ArgumentTypes<P>>(...args: T) => ParamReturn<P, T>)); | ||
| declare function def<P extends AnyArg[], T extends ArgumentTypes<P>>(description: string, ...args: T): ParamReturn<P, T>; | ||
| declare function def<P extends AnyArg[], T extends ArgumentTypes<P>>(...args: T): ParamReturn<P, T>; | ||
| type ParamReturn<P extends AnyArg[], T extends ArgumentTypes<P>> = { | ||
| /** | ||
| * Implementation for a specific overload. When the arguments passed match this functions | ||
| * parent overload, the arguments will be passed to this functions parameters. | ||
| * | ||
| * The return value will be used in a union in the final return value of the overloading function/method | ||
| * @param implementation | ||
| * @returns | ||
| */ | ||
| matches: <K>( | ||
| /** @ts-expect-error This is valid, just isn't being picked up as tuple type for some reason. **/ | ||
| implementation: (...implArgs: ValidatorArgumentTuple<T>) => K | ||
| /** @ts-expect-error This is valid, just isn't being picked up as tuple type for some reason. **/ | ||
| ) => Overload<P, (...implArgs: ValidatorArgumentTuple<T>) => K>; | ||
| }; | ||
| declare function fallback<P extends ArgumentType[], K>(description: string, implementation: (...args: P) => K): Overload<AnyArg[], (...args: P) => K>; | ||
| declare function fallback<P extends ArgumentType[], K>(implementation: (...args: P) => K): Overload<AnyArg[], (...args: P) => K>; | ||
| export { AbstractClass, AnyType, ArgumentType, ArgumentOptions as ArgumentValidatorOpts, Array$1 as Array, ArrayValidatorOpts, BaseArgument, BooleanValidatorOpts, CamelCase, Class, DateValidatorOpts, Ephemeral, FromFunction, FromShape, FromTuple, FunctionValidatorOptions as FunctionOptions, FunctionType, InferArg, InstanceType, NilValidatorOpts, NumberValidatorOpts, Primitive, Shape, ShapeType, ShapeValidatorOpts, StringValidatorOpts, Tuple, TupleType, TupleValidatorOpts as TupleValidationOptions, TypeArgument, UnionArgument, array, boolean, date, def, fallback, func, instance, nil, number, or, overloads, shape, string, tuple, type, unknown }; | ||
| export { Matcher } from "./core/matcher"; | ||
| export type { NormalizedSignature, ValidatorInstance, ValidationIssue, ValidationResult, ValidationPath, MatchScore, SignatureFailureReport, OverloadHandler, ThrowsSpec, } from "./core/types"; | ||
| export { normalizeDefinition, normalizeSignatures } from "./core/signature"; | ||
| export type { SignatureDefinitionInput } from "./core/signature"; | ||
| export { AmbiguousOverloadError, NoOverloadMatchedError } from "./core/errors"; | ||
| export { createValidator, failure, success, type ValidatorOptions, type ValidatorRuntimeContext, } from "./validators/base"; | ||
| export { string, number, boolean, literal, unknown, func, typeOf } from "./validators/primitives"; | ||
| export { array, tuple, shape, union, intersection, instanceOf } from "./validators/composite"; | ||
| export { def, fallback, overloads } from "./authoring/overloads"; | ||
| export { SignatureBuilder } from "./authoring/signature-builder"; |
+868
-1266
@@ -1,1386 +0,988 @@ | ||
| "use strict"; | ||
| var __create = Object.create; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __getProtoOf = Object.getPrototypeOf; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| // src/core/errors.ts | ||
| var AmbiguousOverloadError = class extends Error { | ||
| constructor(message, matches) { | ||
| super(message); | ||
| this.name = "AmbiguousOverloadError"; | ||
| this.matches = matches; | ||
| } | ||
| return to; | ||
| }; | ||
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( | ||
| // If the importer is in node compatibility mode or this is not an ESM | ||
| // file that has been converted to a CommonJS file using a Babel- | ||
| // compatible transform (i.e. "__esModule" has not been set), then set | ||
| // "default" to the CommonJS "module.exports" for node compatibility. | ||
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, | ||
| mod | ||
| )); | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var __accessCheck = (obj, member, msg) => { | ||
| if (!member.has(obj)) | ||
| throw TypeError("Cannot " + msg); | ||
| }; | ||
| var __privateGet = (obj, member, getter) => { | ||
| __accessCheck(obj, member, "read from private field"); | ||
| return getter ? getter.call(obj) : member.get(obj); | ||
| }; | ||
| var __privateAdd = (obj, member, value) => { | ||
| if (member.has(obj)) | ||
| throw TypeError("Cannot add the same private member more than once"); | ||
| member instanceof WeakSet ? member.add(obj) : member.set(obj, value); | ||
| }; | ||
| var __privateSet = (obj, member, value, setter) => { | ||
| __accessCheck(obj, member, "write to private field"); | ||
| setter ? setter.call(obj, value) : member.set(obj, value); | ||
| return value; | ||
| }; | ||
| // src/index.ts | ||
| var src_exports = {}; | ||
| __export(src_exports, { | ||
| BaseArgument: () => BaseArgument, | ||
| TypeArgument: () => TypeArgument, | ||
| UnionArgument: () => UnionArgument, | ||
| array: () => array4, | ||
| boolean: () => boolean2, | ||
| date: () => date, | ||
| def: () => def, | ||
| fallback: () => fallback, | ||
| func: () => func, | ||
| instance: () => instance, | ||
| nil: () => nil, | ||
| number: () => number2, | ||
| or: () => or, | ||
| overloads: () => overloads, | ||
| shape: () => shape, | ||
| string: () => string, | ||
| tuple: () => tuple2, | ||
| type: () => type, | ||
| unknown: () => unknown4 | ||
| }); | ||
| module.exports = __toCommonJS(src_exports); | ||
| // src/arguments/string-argument.ts | ||
| var import_git_diff = __toESM(require("git-diff"), 1); | ||
| var import_myzod2 = require("myzod"); | ||
| // src/arguments/base-argument.ts | ||
| var import_myzod = require("myzod"); | ||
| // src/arguments/accumulator.ts | ||
| var Accumulator = class _Accumulator extends Array { | ||
| asString(depth = 0) { | ||
| let str2 = ""; | ||
| for (const value of this) { | ||
| if (typeof value === "string") { | ||
| str2 += " ".repeat(depth) + value + "\n"; | ||
| } | ||
| if (value instanceof _Accumulator) { | ||
| str2 += value.asString(depth + 1) + "\n"; | ||
| } | ||
| } | ||
| return str2; | ||
| var NoOverloadMatchedError = class extends Error { | ||
| constructor(args, failures) { | ||
| super(buildMessage(args, failures)); | ||
| this.name = "NoOverloadMatchedError"; | ||
| this.args = args; | ||
| this.failures = failures; | ||
| } | ||
| }; | ||
| // src/arguments/base-argument.ts | ||
| var BaseArgumentSchema = (0, import_myzod.object)({ | ||
| optional: (0, import_myzod.boolean)().or( | ||
| (0, import_myzod.object)({ | ||
| undefined: (0, import_myzod.boolean)().optional(), | ||
| null: (0, import_myzod.boolean)().optional() | ||
| }) | ||
| ).optional(), | ||
| test: (0, import_myzod.unknown)().optional() | ||
| }); | ||
| var _index; | ||
| var BaseArgument = class { | ||
| constructor() { | ||
| this._accumulator = new Accumulator(); | ||
| this.argCategory = "Arg"; | ||
| __privateAdd(this, _index, void 0); | ||
| function buildMessage(args, failures) { | ||
| const header = `No overload matched for (${args.map(stringifyArg).join(", ")})`; | ||
| const detail = failures.map((failure2) => { | ||
| const signatureLabel = failure2.signature.name ?? `overload#${failure2.signature.id}`; | ||
| const expected = failure2.expected.join(", "); | ||
| const issues = failure2.issues.map((issue) => ` - ${formatPath(issue.path)} ${issue.message}`).join("\n"); | ||
| return [`\u2022 ${signatureLabel}`, ` Expected: ${expected}`, issues].filter(Boolean).join("\n"); | ||
| }).join("\n\n"); | ||
| return [header, detail].filter(Boolean).join("\n\n"); | ||
| } | ||
| function stringifyArg(value) { | ||
| if (value === null) { | ||
| return "null"; | ||
| } | ||
| get accumulator() { | ||
| return this._accumulator; | ||
| if (value === void 0) { | ||
| return "undefined"; | ||
| } | ||
| get index() { | ||
| return __privateGet(this, _index); | ||
| if (typeof value === "string") { | ||
| return `"${value}"`; | ||
| } | ||
| get identifier() { | ||
| return this.argName ?? this.index ?? "unnamed arg"; | ||
| if (typeof value === "function") { | ||
| return value.name ? `[Function ${value.name}]` : "[Function anonymous]"; | ||
| } | ||
| withIndex(index) { | ||
| __privateSet(this, _index, index); | ||
| return this; | ||
| } | ||
| baseAssertions(value) { | ||
| this.assertIsDefined(value); | ||
| this.assertTestSucceeds(value); | ||
| } | ||
| assertIsDefined(value, optional = this.options?.optional) { | ||
| if (optional === true) { | ||
| return; | ||
| if (typeof value === "object") { | ||
| const ctorName = value?.constructor?.name; | ||
| if (ctorName && ctorName !== "Object") { | ||
| return `[${ctorName}]`; | ||
| } | ||
| if (optional && optional.null == true && value === null) { | ||
| return; | ||
| try { | ||
| return JSON.stringify(value); | ||
| } catch { | ||
| return "[object]"; | ||
| } | ||
| if (optional && optional.undefined == true && value === void 0) { | ||
| return; | ||
| } | ||
| if (value === void 0 || value === null) { | ||
| const message = `Expected ${this.typeName} to be defined but found ${value}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertTestSucceeds(value, test = this.options?.test) { | ||
| if (value === void 0 || value === null) { | ||
| return; | ||
| } | ||
| const realTest = test; | ||
| if (realTest) { | ||
| const result = realTest(value); | ||
| if (result === true) { | ||
| return; | ||
| } | ||
| const message = `Expected ${value} to evaluate to true but was ${result}.`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| return String(value); | ||
| } | ||
| function formatPath(path) { | ||
| if (path.length === 0) { | ||
| return ""; | ||
| } | ||
| shouldAssert(value, optional = this.options?.optional) { | ||
| if (optional === true) { | ||
| return true; | ||
| } | ||
| if (optional && optional.null === true && value == null) { | ||
| return true; | ||
| } | ||
| if (optional && optional.undefined == true && value == void 0) { | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
| fmt(message, padDepth = 0) { | ||
| const pad = " ".repeat(padDepth); | ||
| return `${pad}${this.argCategory}[${this.identifier}]: ${message}`; | ||
| } | ||
| or(second) { | ||
| return or(this, second); | ||
| } | ||
| }; | ||
| _index = new WeakMap(); | ||
| var UnionArgument = class extends BaseArgument { | ||
| constructor(first, second) { | ||
| super(); | ||
| this.first = first; | ||
| this.second = second; | ||
| } | ||
| get typeName() { | ||
| return this.first ? this.first.typeName : this.second.typeName; | ||
| } | ||
| assertUnion(actual) { | ||
| if (!this.first.isTypeMatch(actual) && !this.second.isTypeMatch(actual)) { | ||
| this.accumulator.push( | ||
| `Arg[${this.identifier}]:Expected ${actual} to be one of ${this.first.typeName} or ${this.second.typeName}.` | ||
| ); | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return typeof type2 === this.typeName; | ||
| } | ||
| validate(value) { | ||
| this.assertUnion(value); | ||
| if (this.first) { | ||
| this.first.validate(value); | ||
| } | ||
| if (this.second && !this.first) { | ||
| this.second.validate(value); | ||
| } | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function or(first, second) { | ||
| return new UnionArgument(first, second); | ||
| return path.map((segment) => typeof segment === "number" ? `[${segment}]` : segment).join("."); | ||
| } | ||
| // src/arguments/string-argument.ts | ||
| var StringValidatorOpsSchema = (0, import_myzod2.object)({ | ||
| minLength: (0, import_myzod2.number)().optional(), | ||
| maxLength: (0, import_myzod2.number)().optional(), | ||
| includes: (0, import_myzod2.string)().optional(), | ||
| equals: (0, import_myzod2.string)().optional(), | ||
| in: (0, import_myzod2.array)((0, import_myzod2.string)()).optional(), | ||
| startsWith: (0, import_myzod2.string)().optional(), | ||
| endsWith: (0, import_myzod2.string)().optional(), | ||
| pattern: (0, import_myzod2.object)({ source: (0, import_myzod2.string)() }, { allowUnknown: true }).optional() | ||
| }).and(BaseArgumentSchema); | ||
| var StringArgumentConstructorSchema = (0, import_myzod2.tuple)([ | ||
| (0, import_myzod2.string)(), | ||
| StringValidatorOpsSchema | ||
| ]).or((0, import_myzod2.tuple)([(0, import_myzod2.string)().or(StringValidatorOpsSchema)])).or((0, import_myzod2.tuple)([])); | ||
| var StringArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "string"; | ||
| if (!args) { | ||
| return; | ||
| } | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| // src/core/signature.ts | ||
| function normalizeSignatures(definitions) { | ||
| return definitions.map((definition, index) => normalizeSignature(definition, index)); | ||
| } | ||
| function normalizeSignature(definition, id) { | ||
| const validators = [...definition.validators]; | ||
| const fallback2 = definition.fallback ?? false; | ||
| const requiredArity = countRequired(validators); | ||
| const minArity = fallback2 ? 0 : requiredArity; | ||
| const maxArity = validators.length; | ||
| const specificity = validators.reduce(sumSpecificity, 0); | ||
| return { | ||
| id, | ||
| validators, | ||
| minArity, | ||
| requiredArity, | ||
| maxArity, | ||
| specificity, | ||
| fallback: fallback2, | ||
| ...definition.name !== void 0 ? { name: definition.name } : {}, | ||
| ...definition.description !== void 0 ? { description: definition.description } : {}, | ||
| ...definition.handler !== void 0 ? { handler: definition.handler } : {}, | ||
| ...definition.throws !== void 0 ? { throws: definition.throws } : {} | ||
| }; | ||
| } | ||
| function countRequired(validators) { | ||
| return validators.reduce((count, validator) => validator.optional ? count : count + 1, 0); | ||
| } | ||
| function sumSpecificity(total, validator) { | ||
| return total + validator.specificity; | ||
| } | ||
| function normalizeDefinition(definition, id = 0) { | ||
| return normalizeSignature(definition, id); | ||
| } | ||
| // src/core/matcher.ts | ||
| var Matcher = class _Matcher { | ||
| constructor(signatures) { | ||
| const normalized = [...signatures]; | ||
| const fallback2 = normalized.find((signature) => signature.fallback); | ||
| this.fallback = fallback2; | ||
| this.signatures = normalized.filter((signature) => !signature.fallback); | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 === this.typeName || typeof type2 === this.typeName; | ||
| static from(definitions) { | ||
| const signatures = normalizeSignatures(definitions); | ||
| return new _Matcher(signatures); | ||
| } | ||
| assertStringLessThanMax(str2, max = this.options?.maxLength) { | ||
| if (typeof max === "number" && typeof str2 === "string" && str2.length > max) { | ||
| const message = `Expected ${str2} to have less than ${max} characters but found ${str2.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| use(args) { | ||
| const matches = []; | ||
| const failures = []; | ||
| for (const signature of this.signatures) { | ||
| const evaluation = this.evaluateSignature(signature, args); | ||
| if (evaluation.ok) { | ||
| matches.push({ signature, score: evaluation.score }); | ||
| } else { | ||
| failures.push({ | ||
| signature, | ||
| issues: evaluation.issues, | ||
| expected: signature.validators.map( | ||
| (validator) => validator.optional ? `${validator.summary}?` : validator.summary | ||
| ) | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| assertStringGreaterThanMin(str2, min = this.options?.minLength) { | ||
| if (typeof min === "number" && typeof str2 === "string" && str2.length < min) { | ||
| const message = `Expected ${str2} to have at least ${min} characters but found ${str2.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| if (matches.length === 0) { | ||
| if (this.fallback?.handler) { | ||
| return this.fallback.handler(...args); | ||
| } | ||
| throw new NoOverloadMatchedError(args, failures); | ||
| } | ||
| } | ||
| assertStringIncludes(str2, value = this.options?.includes) { | ||
| if (typeof str2 === "string" && typeof value === "string" && !str2.includes(value)) { | ||
| const message = `Expected ${str2} to include ${value} but the substring could not be found`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| const bestScore = this.getBestScore(matches.map((match) => match.score)); | ||
| const bestMatches = matches.filter((match) => isSameScore(match.score, bestScore)); | ||
| if (bestMatches.length > 1) { | ||
| throw new AmbiguousOverloadError( | ||
| "Multiple overloads match with identical specificity", | ||
| bestMatches.map((match) => match.signature) | ||
| ); | ||
| } | ||
| } | ||
| assertStringIn(str2, value = this.options?.in) { | ||
| if (typeof str2 === "string" && Array.isArray(value) && !value.includes(str2)) { | ||
| const message = `Expected ${str2} to be a member of list ${JSON.stringify( | ||
| value | ||
| )} but the substring could not be found`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| const [winnerEntry] = bestMatches; | ||
| if (!winnerEntry) { | ||
| throw new Error("Unable to resolve a matching overload despite scoring."); | ||
| } | ||
| } | ||
| assertStringEquals(str2, value = this.options?.equals) { | ||
| if (typeof str2 === "string" && typeof value === "string" && str2 !== value) { | ||
| const diff = (0, import_git_diff.default)(str2, value); | ||
| const message = `Expected ${str2} to equal ${value} but did not. Diff: | ||
| ${diff}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| const { signature: winner } = winnerEntry; | ||
| if (winner.throws) { | ||
| const { error, message } = winner.throws; | ||
| throw new error(message); | ||
| } | ||
| } | ||
| assertStringMatches(str2, pattern = this.options?.pattern) { | ||
| if (typeof str2 === "string" && pattern instanceof RegExp && !pattern.test(str2)) { | ||
| const message = `Expected ${pattern} to match pattern ${pattern.source} but it did not`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| if (!winner.handler) { | ||
| throw new Error("Matched overload does not have an associated handler"); | ||
| } | ||
| return winner.handler(...args); | ||
| } | ||
| assertString(str2) { | ||
| if (typeof str2 !== "string" && !this.options?.optional) { | ||
| const message = `Expected argument to be of type 'string' but was: [${typeof str2}] ${str2}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| evaluateSignature(signature, args) { | ||
| const issues = []; | ||
| if (args.length < signature.minArity || args.length > signature.maxArity) { | ||
| issues.push({ | ||
| path: [], | ||
| message: `Received ${args.length} arguments, expected between ${signature.minArity} and ${signature.maxArity}`, | ||
| expected: `${signature.minArity}-${signature.maxArity}`, | ||
| actual: args.length | ||
| }); | ||
| return { ok: false, issues }; | ||
| } | ||
| } | ||
| assertinArray(str2, array9 = this.options?.in) { | ||
| if (typeof str2 === "string" && Array.isArray(array9) && !array9.includes(str2)) { | ||
| const message = `Expected ${array9} to include ${str2} but it was not`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| for (const [index, validator] of signature.validators.entries()) { | ||
| const value = args[index]; | ||
| const path = ["arg", index]; | ||
| if (value === void 0 && index >= args.length) { | ||
| if (!validator.optional) { | ||
| issues.push({ path, message: "Argument is required but missing", expected: validator.summary }); | ||
| return { ok: false, issues }; | ||
| } | ||
| continue; | ||
| } | ||
| if (value === void 0 && validator.optional) { | ||
| continue; | ||
| } | ||
| const result = validator.validate(value, path); | ||
| if (!result.ok) { | ||
| issues.push(...result.issues); | ||
| return { ok: false, issues }; | ||
| } | ||
| } | ||
| if (args.length > signature.validators.length) { | ||
| const extraArgs = args.length - signature.validators.length; | ||
| for (let offset = 0; offset < extraArgs; offset++) { | ||
| const index = signature.validators.length + offset; | ||
| issues.push({ | ||
| path: ["arg", index], | ||
| message: "Unexpected argument", | ||
| actual: args[index] | ||
| }); | ||
| } | ||
| return { ok: false, issues }; | ||
| } | ||
| const score = [ | ||
| signature.specificity, | ||
| signature.requiredArity, | ||
| args.length === signature.validators.length ? 1 : 0, | ||
| signature.id | ||
| ]; | ||
| return { ok: true, score }; | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertString(value); | ||
| this.assertStringEquals(value); | ||
| this.assertStringLessThanMax(value); | ||
| this.assertStringGreaterThanMin(value); | ||
| this.assertinArray(value); | ||
| this.assertStringIncludes(value); | ||
| this.assertStringMatches(value); | ||
| return this.accumulator.length === 0; | ||
| getBestScore(scores) { | ||
| return scores.reduce((best, current) => { | ||
| if (compareScores(current, best) > 0) { | ||
| return current; | ||
| } | ||
| return best; | ||
| }); | ||
| } | ||
| }; | ||
| function string(...args) { | ||
| StringArgumentConstructorSchema.parse(args); | ||
| return new StringArgument(args); | ||
| } | ||
| // src/arguments/number-argument.ts | ||
| var import_myzod3 = require("myzod"); | ||
| var NumberValidationSchema = (0, import_myzod3.object)({ | ||
| max: (0, import_myzod3.number)().optional(), | ||
| min: (0, import_myzod3.number)().optional(), | ||
| equals: (0, import_myzod3.number)().optional(), | ||
| type: (0, import_myzod3.literal)("int").or((0, import_myzod3.literal)("float")).optional(), | ||
| in: (0, import_myzod3.array)((0, import_myzod3.number)()).optional() | ||
| }).and(BaseArgumentSchema); | ||
| var NumberArgumentParamsSchema = (0, import_myzod3.array)((0, import_myzod3.string)().or(NumberValidationSchema)); | ||
| var NumberArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "number"; | ||
| if (!args) { | ||
| return; | ||
| } | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| function compareScores(a, b) { | ||
| const [aSpecificity, aRequiredArity, aExactArity, aOrder] = a; | ||
| const [bSpecificity, bRequiredArity, bExactArity, bOrder] = b; | ||
| if (aSpecificity !== bSpecificity) { | ||
| return aSpecificity > bSpecificity ? 1 : -1; | ||
| } | ||
| isTypeMatch(type2) { | ||
| return typeof type2 === this.typeName; | ||
| if (aRequiredArity !== bRequiredArity) { | ||
| return aRequiredArity > bRequiredArity ? 1 : -1; | ||
| } | ||
| assertNumber(num4) { | ||
| if (typeof num4 !== "number") { | ||
| const message = `Expected value to be a number but was [${typeof num4}]: ${num4}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| if (aExactArity !== bExactArity) { | ||
| return aExactArity > bExactArity ? 1 : -1; | ||
| } | ||
| assertNumberEquals(num4, equals = this.options?.equals) { | ||
| if (typeof num4 !== "number" && typeof num4 !== "bigint") { | ||
| return; | ||
| } | ||
| if (equals !== void 0 && num4 !== equals) { | ||
| const message = `Expected ${num4} to equal ${equals} but did not.`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| if (aOrder !== bOrder) { | ||
| return aOrder > bOrder ? 1 : -1; | ||
| } | ||
| assertNumberLessThanMax(num4, max = this.options?.max) { | ||
| if (num4 === void 0) { | ||
| return; | ||
| } | ||
| if (typeof num4 !== "number" && typeof num4 !== "bigint") { | ||
| return; | ||
| } | ||
| if (max !== void 0 && num4 > max) { | ||
| const message = `Expected number ${num4} to be less than max value ${max}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertNumberGreaterThanMin(num4, min = this.options?.min) { | ||
| if (num4 === void 0) { | ||
| return; | ||
| } | ||
| if (typeof num4 !== "number" && typeof num4 !== "bigint") { | ||
| return; | ||
| } | ||
| if (min !== void 0 && num4 < min) { | ||
| const message = `Expected number to be greater than minimum value ${min}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertInArray(val, value) { | ||
| if (import_myzod3.number === void 0) { | ||
| return; | ||
| } | ||
| if (typeof import_myzod3.number !== "number" && typeof import_myzod3.number !== "bigint") { | ||
| return; | ||
| } | ||
| if (value && Array.isArray(value) && !value.includes(val)) { | ||
| const message = `Expected ${value} to include ${val} but it was not`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| assertType(value, type2 = this.options?.type) { | ||
| if (import_myzod3.number === void 0) { | ||
| return; | ||
| } | ||
| if (typeof value !== "number") { | ||
| return; | ||
| } | ||
| if (type2 === "float" && Number.isInteger(value)) { | ||
| const message = `Expected number '${value}' to be a float but was an integer`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| if (type2 === "int" && !Number.isInteger(value)) { | ||
| const message = `Expected number '${value}' to be an integer but was a float`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertNumber(value); | ||
| this.assertNumberEquals(value); | ||
| this.assertInArray(value); | ||
| this.assertNumberGreaterThanMin(value); | ||
| this.assertNumberLessThanMax(value); | ||
| this.assertType(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function number2(...args) { | ||
| NumberArgumentParamsSchema.parse(args); | ||
| return new NumberArgument(args); | ||
| return 0; | ||
| } | ||
| function isSameScore(a, b) { | ||
| return compareScores(a, b) === 0; | ||
| } | ||
| // src/arguments/boolean-argument.ts | ||
| var import_myzod4 = require("myzod"); | ||
| var BooleaValidationSchema = (0, import_myzod4.object)({ | ||
| equals: (0, import_myzod4.boolean)().optional() | ||
| // "not" equals property | ||
| }).and(BaseArgumentSchema); | ||
| var BooleanArgumentConstructorSchema = (0, import_myzod4.array)( | ||
| (0, import_myzod4.string)().or(BooleaValidationSchema) | ||
| ); | ||
| var BooleanArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "boolean"; | ||
| if (!args) { | ||
| return; | ||
| // src/validators/base.ts | ||
| function createValidator(config) { | ||
| const optional = config.optional ?? false; | ||
| const specificity = config.specificity; | ||
| const summary = config.summary; | ||
| return { | ||
| optional, | ||
| specificity, | ||
| summary, | ||
| validate(value, path) { | ||
| const collected = []; | ||
| const context = createRuntimeContext(path, collected); | ||
| const outcome = config.validate(value, context); | ||
| return normalizeOutcome(outcome, collected, path, summary); | ||
| } | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| }; | ||
| } | ||
| function success(value) { | ||
| if (value === void 0) { | ||
| return { ok: true, issues: [] }; | ||
| } | ||
| assertBoolean(actual) { | ||
| if (actual === void 0) { | ||
| return; | ||
| return { ok: true, issues: [], value }; | ||
| } | ||
| function failure(issue) { | ||
| return { | ||
| ok: false, | ||
| issues: Array.isArray(issue) ? issue : [issue] | ||
| }; | ||
| } | ||
| function createRuntimeContext(path, sink) { | ||
| return { | ||
| path, | ||
| report(issue) { | ||
| sink.push({ | ||
| path: issue.path ?? path, | ||
| message: issue.message, | ||
| expected: issue.expected, | ||
| actual: issue.actual | ||
| }); | ||
| }, | ||
| child(segment) { | ||
| return createRuntimeContext([...path, segment], sink); | ||
| } | ||
| if (actual !== void 0 && typeof actual !== "boolean") { | ||
| this.accumulator.push( | ||
| `Arg[${this.identifier}]: Expected boolean but found [type: ${typeof actual}]${actual}` | ||
| ); | ||
| } | ||
| }; | ||
| } | ||
| function normalizeOutcome(outcome, collected, path, summary) { | ||
| if (outcome === void 0) { | ||
| return finalize(collected, path, summary, true); | ||
| } | ||
| assertEquals(actual) { | ||
| if (actual === void 0) { | ||
| return; | ||
| } | ||
| const equals = this.options?.equals; | ||
| if (actual !== void 0 && equals !== void 0 && actual !== equals) { | ||
| this.accumulator.push( | ||
| `Arg[${this.identifier}]:Expected ${actual} to equal ${boolean2} but did not.` | ||
| ); | ||
| } | ||
| if (typeof outcome === "boolean") { | ||
| const ok2 = outcome && collected.length === 0; | ||
| return finalize(collected, path, summary, ok2); | ||
| } | ||
| isTypeMatch(type2) { | ||
| return typeof type2 === this.typeName; | ||
| const mergedIssues = [...collected, ...outcome.issues.map((issue) => ensurePath(issue, path))]; | ||
| const ok = outcome.ok && mergedIssues.length === 0 ? true : outcome.ok; | ||
| const issues = !ok && mergedIssues.length === 0 ? [{ path, message: `Value did not satisfy ${summary}` }] : mergedIssues; | ||
| if (outcome.value === void 0) { | ||
| return { ok, issues }; | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertBoolean(value); | ||
| this.assertEquals(value); | ||
| return this.accumulator.length === 0; | ||
| return { ok, issues, value: outcome.value }; | ||
| } | ||
| function ensurePath(issue, fallback2) { | ||
| if (issue.path.length > 0) { | ||
| return issue; | ||
| } | ||
| }; | ||
| function boolean2(...args) { | ||
| BooleanArgumentConstructorSchema.parse(args); | ||
| return new BooleanArgument(args); | ||
| return { ...issue, path: fallback2 }; | ||
| } | ||
| function finalize(collected, path, summary, ok) { | ||
| if (ok) { | ||
| return { ok: true, issues: [] }; | ||
| } | ||
| const issues = collected.length > 0 ? collected : [{ path, message: `Value did not satisfy ${summary}` }]; | ||
| return { ok: false, issues }; | ||
| } | ||
| // src/arguments/array-argument.ts | ||
| var import_myzod5 = require("myzod"); | ||
| var ArrayValidationSchema = (0, import_myzod5.object)({ | ||
| maxLength: (0, import_myzod5.number)().optional(), | ||
| minLength: (0, import_myzod5.number)().optional(), | ||
| length: (0, import_myzod5.number)().optional(), | ||
| includes: (0, import_myzod5.unknown)().optional() | ||
| }).and(BaseArgumentSchema); | ||
| var ArrayArgumentParamSchema = (0, import_myzod5.array)( | ||
| (0, import_myzod5.string)().or((0, import_myzod5.array)((0, import_myzod5.unknown)())).or(ArrayValidationSchema) | ||
| ); | ||
| var ArrayArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "Array"; | ||
| this.types = []; | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object" && Array.isArray(args[0])) { | ||
| this.reference = args[0]; | ||
| } | ||
| if (typeof args[1] === "object" && Array.isArray(args[1])) { | ||
| this.reference = args[1]; | ||
| } | ||
| if (typeof args[1] === "object" && !Array.isArray(args[1])) { | ||
| this.options = args[1]; | ||
| } | ||
| if (typeof args[2] === "object" && !Array.isArray(args[2])) { | ||
| this.options = args[2]; | ||
| } | ||
| for (const value of this.reference) { | ||
| if (!this.types.includes(value.typeName)) { | ||
| this.types.push(value.typeName); | ||
| // src/validators/primitives.ts | ||
| function string(options = {}) { | ||
| const hasConstraints = options.minLength !== void 0 || options.maxLength !== void 0 || options.pattern !== void 0 || options.predicate !== void 0; | ||
| const specificity = options.specificity ?? (hasConstraints ? 3 : 2); | ||
| const summary = options.summary ?? "string"; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (typeof value !== "string") { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| assertIsArray(values) { | ||
| if (!Array.isArray(values)) { | ||
| const message = `Expected value to be an array but found ${typeof values}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return Array.isArray(type2); | ||
| } | ||
| assertLengthLessThanMax(values, length2 = this.options?.maxLength) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (Array.isArray(values)) { | ||
| if (length2 && values?.length > length2) { | ||
| const message = `Expected value to be an array with max length ${length2} but was ${values?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| if (options.minLength !== void 0 && value.length < options.minLength) { | ||
| ctx.report({ | ||
| message: `Expected string length \u2265 ${options.minLength}, received ${value.length}`, | ||
| actual: value, | ||
| expected: `${summary} length \u2265 ${options.minLength}` | ||
| }); | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| assertLengthGreaterThanMin(values, length2 = this.options?.minLength) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (Array.isArray(values)) { | ||
| if (length2 && values?.length < length2) { | ||
| const message = `Expected value to be an array with min length ${length2} but was ${values?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| if (options.maxLength !== void 0 && value.length > options.maxLength) { | ||
| ctx.report({ | ||
| message: `Expected string length \u2264 ${options.maxLength}, received ${value.length}`, | ||
| actual: value, | ||
| expected: `${summary} length \u2264 ${options.maxLength}` | ||
| }); | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| assertLengthEquals(values, length2 = this.options?.length) { | ||
| if (length2 && Array.isArray(values)) { | ||
| if (length2 !== values?.length) { | ||
| const message = `Expected array to have length ${length2} but was ${values?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| if (options.pattern && !options.pattern.test(value)) { | ||
| ctx.report({ | ||
| message: `Expected string to match ${options.pattern}`, | ||
| actual: value, | ||
| expected: `${summary} matching ${options.pattern}` | ||
| }); | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| assertIncludes(values, item = this.options?.includes) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (item && Array.isArray(values)) { | ||
| if (!values.includes(item)) { | ||
| const message = `Expected array to have length ${length} but was ${values?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| if (options.predicate && !options.predicate(value)) { | ||
| ctx.report({ | ||
| message: `String predicate failed`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| } | ||
| assertPermittedType(values) { | ||
| if (!Array.isArray(values)) { | ||
| return; | ||
| } | ||
| for (const value of values) { | ||
| if (!this.types.includes(typeof value)) { | ||
| const index = values.indexOf(value); | ||
| const message = `Expected array to contain only known types ${this.types} but index [${index}] contains ${typeof value}: '${JSON.stringify( | ||
| value | ||
| )}'; ${JSON.stringify(values)}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| }); | ||
| } | ||
| function number(options = {}) { | ||
| const hasConstraints = options.min !== void 0 || options.max !== void 0 || options.integer === true || options.finite === true || options.predicate !== void 0; | ||
| const specificity = options.specificity ?? (hasConstraints ? 3 : 2); | ||
| const summary = options.summary ?? "number"; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (typeof value !== "number" || Number.isNaN(value)) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| assertChildValidations(values) { | ||
| if (!Array.isArray(values)) { | ||
| return; | ||
| } | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| for (const value of values) { | ||
| const matching = this.reference.find((it) => it.isTypeMatch(value)); | ||
| if (!matching) { | ||
| const message = `Expected array value to be one of ${this.types} but found ${typeof value}:`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| this.accumulator.push(...this.reference.map((it) => it.accumulator)); | ||
| if (options.finite && !Number.isFinite(value)) { | ||
| ctx.report({ | ||
| message: `Expected finite number`, | ||
| actual: value, | ||
| expected: `${summary} (finite)` | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.integer && !Number.isInteger(value)) { | ||
| ctx.report({ | ||
| message: `Expected integer`, | ||
| actual: value, | ||
| expected: `${summary} (integer)` | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.min !== void 0 && value < options.min) { | ||
| ctx.report({ | ||
| message: `Expected number \u2265 ${options.min}, received ${value}`, | ||
| actual: value, | ||
| expected: `${summary} \u2265 ${options.min}` | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.max !== void 0 && value > options.max) { | ||
| ctx.report({ | ||
| message: `Expected number \u2264 ${options.max}, received ${value}`, | ||
| actual: value, | ||
| expected: `${summary} \u2264 ${options.max}` | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.predicate && !options.predicate(value)) { | ||
| ctx.report({ | ||
| message: `Number predicate failed`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertIsArray(value); | ||
| this.assertLengthEquals(value); | ||
| this.assertLengthGreaterThanMin(value); | ||
| this.assertLengthLessThanMax(value); | ||
| this.assertPermittedType(value); | ||
| this.assertIncludes(value); | ||
| this.assertChildValidations(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function array4(...args) { | ||
| ArrayArgumentParamSchema.parse(args); | ||
| return new ArrayArgument(args); | ||
| }); | ||
| } | ||
| // src/arguments/tuple-argument.ts | ||
| var import_myzod6 = require("myzod"); | ||
| var TupleValidationSchema = (0, import_myzod6.object)({ | ||
| includes: (0, import_myzod6.unknown)().optional() | ||
| }).and(BaseArgumentSchema); | ||
| var TupleArgumentParamSchema = (0, import_myzod6.array)( | ||
| (0, import_myzod6.string)().or((0, import_myzod6.array)((0, import_myzod6.unknown)())).or(TupleValidationSchema) | ||
| ); | ||
| var TupleArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "object"; | ||
| this.types = []; | ||
| if (!args) { | ||
| throw new Error( | ||
| `A TupleArgument requires a reference array of BaseArguments to construct. Provided args: ${args}` | ||
| ); | ||
| } | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (Array.isArray(args[0])) { | ||
| this.reference = args[0]; | ||
| } | ||
| if (Array.isArray(args[1])) { | ||
| this.reference = args[1]; | ||
| } | ||
| if (!this.reference) { | ||
| throw new Error( | ||
| `A TupleArgument requires a reference array of BaseArguments to construct. Provided args: ${args}` | ||
| ); | ||
| } | ||
| this.reference.forEach((it, idx) => { | ||
| this.types.push(it.typeName); | ||
| it.withIndex(idx).argCategory = "Element"; | ||
| }); | ||
| } | ||
| isTypeMatch(type2) { | ||
| return Array.isArray(type2); | ||
| } | ||
| assertIsTuple(values) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (!Array.isArray(values)) { | ||
| const message = `Expected value to be an array but found ${typeof values}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertIncludes(values, item = this.options?.includes) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (item && Array.isArray(values)) { | ||
| if (!values.includes(item)) { | ||
| const message = `Expected array to have length ${length} but was ${values?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| function boolean(options = {}) { | ||
| const summary = options.summary ?? "boolean"; | ||
| const specificity = options.specificity ?? 2; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (typeof value !== "boolean") { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| } | ||
| assertLength(values, length2 = this.types.length) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (length2 && values?.length <= length2) { | ||
| this.accumulator.push( | ||
| `Expected value to be an array with max length ${length2} but was ${values?.length}` | ||
| ); | ||
| } | ||
| } | ||
| assertPermittedType(values) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (!Array.isArray(values)) { | ||
| return; | ||
| } | ||
| const errors = []; | ||
| for (let i = 0; i < this.types.length; i++) { | ||
| const reference = this.reference[i]; | ||
| const actual = values[i]; | ||
| if (!reference.validate(actual)) { | ||
| errors.push(reference); | ||
| }); | ||
| } | ||
| function literal(expected, options = {}) { | ||
| const values = Array.isArray(expected) ? expected : [expected]; | ||
| const describeLiteral = options.describeValue ?? describeValue; | ||
| const summary = options.summary ?? formatLiteralSummary(values.map((value) => describeLiteral(value))); | ||
| const specificity = options.specificity ?? 5; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (!values.some((candidate) => Object.is(candidate, value))) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| if (errors.length > 0) { | ||
| const message = `Expected all tuple values to be valid but found:`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| errors.forEach((it) => this.accumulator.push(it.accumulator)); | ||
| }); | ||
| } | ||
| function unknown(options = {}) { | ||
| const summary = options.summary ?? "unknown"; | ||
| const specificity = options.specificity ?? 0; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate() { | ||
| return true; | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertIsTuple(value); | ||
| this.assertPermittedType(value); | ||
| this.assertIncludes(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function tuple2(...args) { | ||
| TupleArgumentParamSchema.parse(args); | ||
| return new TupleArgument(args); | ||
| }); | ||
| } | ||
| // src/arguments/shape-argument.ts | ||
| var import_myzod7 = require("myzod"); | ||
| var ShapeValidationSchema = (0, import_myzod7.object)({ | ||
| exhaustive: (0, import_myzod7.boolean)().optional(), | ||
| instance: (0, import_myzod7.object)({}, { allowUnknown: true }).optional() | ||
| }).and(BaseArgumentSchema); | ||
| var ShapeArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "object"; | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args.shift(); | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.reference = args.shift(); | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (!this.reference) { | ||
| throw new Error(`Shape Argument must be provided a reference object`); | ||
| } | ||
| for (const key in this.reference) { | ||
| const name = this.reference[key].argName; | ||
| if (!name) { | ||
| this.reference[key].argName = key; | ||
| this.reference[key].argCategory = "Property"; | ||
| function func(options = {}) { | ||
| const summary = options.summary ?? "function"; | ||
| const hasArityConstraint = options.arity !== void 0; | ||
| const specificity = options.specificity ?? (hasArityConstraint ? 3 : 2); | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (typeof value !== "function") { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 === this.typeName || typeof type2 === this.typeName; | ||
| } | ||
| assertObject(value) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (typeof value !== "object") { | ||
| const message = `Expected value to be an ${this.typeName} but was [type: ${typeof value}]: '${value}'`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertExhaustive(value) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (this.options?.exhaustive === void 0 || this.options?.exhaustive === false) { | ||
| return; | ||
| } | ||
| const asObj = value; | ||
| const refKeys = Object.keys(this.reference); | ||
| const valKeys = Object.keys(asObj); | ||
| if (refKeys.length != valKeys.length) { | ||
| for (const property of valKeys) { | ||
| if (!(property in this.reference)) { | ||
| const message = `Argument value contains property '${property}' which is not known for object with keys [${refKeys.map((it) => `'${it}'`).join()}]`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| if (options.arity !== void 0 && value.length !== options.arity) { | ||
| ctx.report({ | ||
| message: `Expected function arity ${options.arity}, received ${value.length}`, | ||
| actual: value.length, | ||
| expected: options.arity | ||
| }); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| } | ||
| assertShapeMatches(value) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| const refShape = this.reference; | ||
| const asObj = value; | ||
| for (const key in refShape) { | ||
| const reference = refShape[key]; | ||
| const actual = value && asObj[key]; | ||
| if (!reference.validate(actual)) { | ||
| const message = `Expected all properties to be valid but found:`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| if (reference.accumulator.length > 0) { | ||
| this.accumulator.push(reference.accumulator); | ||
| } | ||
| }); | ||
| } | ||
| function typeOf(ctor, options = {}) { | ||
| const summary = options.summary ?? `typeof ${ctor.name || "<anonymous>"}`; | ||
| const specificity = options.specificity ?? 3; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (value === void 0 && options.optional) { | ||
| return true; | ||
| } | ||
| if (value !== ctor) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| }); | ||
| } | ||
| function describeValue(value) { | ||
| if (value === null) { | ||
| return "null"; | ||
| } | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| assertIsInstance(value, instance2 = this.options?.instance) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (instance2 && !(value instanceof instance2)) { | ||
| const message = `Expected shape to be an instance of ${instance2} but was not`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| if (value === void 0) { | ||
| return "undefined"; | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertObject(value); | ||
| this.assertExhaustive(value); | ||
| this.assertShapeMatches(value); | ||
| this.assertIsInstance(value); | ||
| return this._accumulator.length === 0; | ||
| if (typeof value === "string") { | ||
| return `"${value}"`; | ||
| } | ||
| }; | ||
| var ShapeArgumentParamsSchema = (0, import_myzod7.array)( | ||
| (0, import_myzod7.string)().or((0, import_myzod7.object)({}).allowUnknownKeys()).or(ShapeValidationSchema).optional() | ||
| ); | ||
| function shape(...args) { | ||
| ShapeArgumentParamsSchema.parse(args); | ||
| return new ShapeArgument(args); | ||
| } | ||
| // src/arguments/date-argument.ts | ||
| var import_myzod8 = require("myzod"); | ||
| var DateValidationOptsSchema = (0, import_myzod8.object)({ | ||
| before: (0, import_myzod8.date)().optional(), | ||
| after: (0, import_myzod8.date)().optional(), | ||
| equals: (0, import_myzod8.date)().optional() | ||
| }).and(BaseArgumentSchema); | ||
| var DateConstructorArgumentSchema = (0, import_myzod8.array)( | ||
| (0, import_myzod8.string)().or(DateValidationOptsSchema.optional()) | ||
| ); | ||
| var DateArgument = class _DateArgument extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "Date"; | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| if (typeof value === "number") { | ||
| return Number.isNaN(value) ? "NaN" : value.toString(); | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 instanceof _DateArgument; | ||
| if (typeof value === "boolean") { | ||
| return value ? "true" : "false"; | ||
| } | ||
| assertBefore(value, before = this.options?.before) { | ||
| if (!before || !(value instanceof Date)) { | ||
| return; | ||
| } | ||
| if (value >= before) { | ||
| const message = `Expected date '${value}' to be earlier than '${before}'`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| if (typeof value === "function") { | ||
| return value.name ? `[Function ${value.name}]` : "[Function anonymous]"; | ||
| } | ||
| assertAfter(value, after = this.options?.after) { | ||
| if (!after || !(value instanceof Date)) { | ||
| return; | ||
| } | ||
| if (value <= after) { | ||
| const message = `Expected date '${value}' to be later than '${after}'`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| if (Array.isArray(value)) { | ||
| return `[${value.map(describeValue).join(", ")}]`; | ||
| } | ||
| assertEquals(value, equals = this.options?.equals) { | ||
| if (!equals || !(value instanceof Date)) { | ||
| return; | ||
| if (typeof value === "object") { | ||
| try { | ||
| return JSON.stringify(value); | ||
| } catch { | ||
| return "[object]"; | ||
| } | ||
| if (value !== equals) { | ||
| const message = `Expected date '${value}' to be equal to '${equals}'`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertBefore(value); | ||
| this.assertAfter(value); | ||
| this.assertEquals(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function date(...args) { | ||
| return new DateArgument(args); | ||
| return String(value); | ||
| } | ||
| // src/arguments/unknown-argument.ts | ||
| var import_myzod9 = require("myzod"); | ||
| var UnknownArgumentParamsSchema = (0, import_myzod9.array)( | ||
| (0, import_myzod9.string)().or(BaseArgumentSchema).optional() | ||
| ).max(2); | ||
| var UnknownArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "unknown"; | ||
| this.options = { optional: true }; | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| function formatLiteralSummary(values) { | ||
| const [first, ...rest] = values; | ||
| if (first === void 0) { | ||
| return "<empty>"; | ||
| } | ||
| isTypeMatch(_type) { | ||
| throw true; | ||
| if (rest.length === 0) { | ||
| return first; | ||
| } | ||
| validate(_value) { | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function unknown4(...args) { | ||
| UnknownArgumentParamsSchema.parse(args); | ||
| return new UnknownArgument(args); | ||
| return [first, ...rest].join(" | "); | ||
| } | ||
| // src/arguments/instance-argument.ts | ||
| var import_myzod10 = require("myzod"); | ||
| var InstanceConstructorArgumentSchema = (0, import_myzod10.object)({}); | ||
| var InstanceOptionsArgumentSchema = (0, import_myzod10.object)({}).and(BaseArgumentSchema); | ||
| var InstanceArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "object"; | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args.shift(); | ||
| // src/validators/composite.ts | ||
| function array(validator, options = {}) { | ||
| const validators = Array.isArray(validator) ? [...validator] : [validator]; | ||
| const summary = options.summary ?? `array<${validators.map((item) => item.summary).join(" | ") || "unknown"}>`; | ||
| const specificity = options.specificity ?? 3; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (!Array.isArray(value)) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.length !== void 0 && value.length !== options.length) { | ||
| ctx.report({ | ||
| message: `Expected array length ${options.length}, received ${value.length}`, | ||
| actual: value.length, | ||
| expected: options.length | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.minLength !== void 0 && value.length < options.minLength) { | ||
| ctx.report({ | ||
| message: `Expected minimum length ${options.minLength}, received ${value.length}`, | ||
| actual: value.length, | ||
| expected: options.minLength | ||
| }); | ||
| return false; | ||
| } | ||
| if (options.maxLength !== void 0 && value.length > options.maxLength) { | ||
| ctx.report({ | ||
| message: `Expected maximum length ${options.maxLength}, received ${value.length}`, | ||
| actual: value.length, | ||
| expected: options.maxLength | ||
| }); | ||
| return false; | ||
| } | ||
| for (const [index, element] of value.entries()) { | ||
| const elementPath = [...ctx.path, index]; | ||
| let matched = false; | ||
| let issues = []; | ||
| for (const candidate of validators) { | ||
| const result = candidate.validate(element, elementPath); | ||
| if (result.ok) { | ||
| matched = true; | ||
| break; | ||
| } | ||
| issues = [...issues, ...result.issues]; | ||
| } | ||
| if (!matched) { | ||
| if (issues.length > 0) { | ||
| forwardIssues(ctx, issues); | ||
| } else { | ||
| ctx.report({ | ||
| path: elementPath, | ||
| message: `Element did not satisfy ${summary}`, | ||
| actual: element | ||
| }); | ||
| } | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| if (typeof args[0] === "function") { | ||
| this.blueprint = args.shift(); | ||
| }); | ||
| } | ||
| function tuple(validators, options = {}) { | ||
| const summary = options.summary ?? `tuple<[${validators.map((item) => item.summary).join(", ")}]>`; | ||
| const specificity = options.specificity ?? 4; | ||
| const requiredCount = validators.reduce((count, validator) => validator.optional ? count : count + 1, 0); | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (!Array.isArray(value)) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| if (value.length < requiredCount) { | ||
| ctx.report({ | ||
| message: `Expected at least ${requiredCount} elements, received ${value.length}`, | ||
| actual: value.length, | ||
| expected: requiredCount | ||
| }); | ||
| return false; | ||
| } | ||
| if (!options.allowExtra && value.length > validators.length) { | ||
| ctx.report({ | ||
| message: `Expected at most ${validators.length} elements, received ${value.length}`, | ||
| actual: value.length, | ||
| expected: validators.length | ||
| }); | ||
| return false; | ||
| } | ||
| for (const [index, validator] of validators.entries()) { | ||
| if (!validator) { | ||
| continue; | ||
| } | ||
| const elementPath = [...ctx.path, index]; | ||
| const element = value[index]; | ||
| if (element === void 0 && index >= value.length) { | ||
| if (!validator.optional) { | ||
| ctx.report({ | ||
| path: elementPath, | ||
| message: "Tuple element is required but missing" | ||
| }); | ||
| return false; | ||
| } | ||
| continue; | ||
| } | ||
| if (element === void 0 && validator.optional) { | ||
| continue; | ||
| } | ||
| const result = validator.validate(element, elementPath); | ||
| if (!result.ok) { | ||
| forwardIssues(ctx, result.issues); | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.shape = args.shift(); | ||
| }); | ||
| } | ||
| function shape(schema, options = {}) { | ||
| const keys = Object.keys(schema); | ||
| const summary = options.summary ?? `shape<{${keys.join(", ")}}>`; | ||
| const specificity = options.specificity ?? 4; | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (typeof value !== "object" || value === null || Array.isArray(value)) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| const record = value; | ||
| for (const key of keys) { | ||
| const validator = schema[key]; | ||
| if (!validator) { | ||
| continue; | ||
| } | ||
| const elementPath = [...ctx.path, key]; | ||
| if (!Object.prototype.hasOwnProperty.call(record, key)) { | ||
| if (!validator.optional) { | ||
| ctx.report({ | ||
| path: elementPath, | ||
| message: "Property is required but missing" | ||
| }); | ||
| return false; | ||
| } | ||
| continue; | ||
| } | ||
| const propertyValue = record[key]; | ||
| const result = validator.validate(propertyValue, elementPath); | ||
| if (!result.ok) { | ||
| forwardIssues(ctx, result.issues); | ||
| return false; | ||
| } | ||
| } | ||
| if (!options.allowUnknownProperties) { | ||
| for (const key of Object.keys(record)) { | ||
| if (!schema[key]) { | ||
| ctx.report({ | ||
| path: [...ctx.path, key], | ||
| message: `Unexpected property "${key}"` | ||
| }); | ||
| return false; | ||
| } | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| if (typeof args[0] === "undefined") { | ||
| args.shift(); | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args.shift(); | ||
| } | ||
| }); | ||
| } | ||
| function union(validators, options = {}) { | ||
| if (validators.length === 0) { | ||
| throw new Error("union requires at least one validator"); | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 instanceof this.blueprint; | ||
| } | ||
| assertIsInstance(value) { | ||
| if (value !== void 0 && this.blueprint && !(value instanceof this.blueprint)) { | ||
| const message = `Expected value of ${value} to be an instance of ${this.blueprint.name} but it was not.`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| const summary = options.summary ?? `union<${validators.map((validator) => validator.summary).join(" | ")}>`; | ||
| const specificity = options.specificity ?? validators.reduce((max, validator) => Math.max(max, validator.specificity), 0); | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| const issues = []; | ||
| for (const validator of validators) { | ||
| const result = validator.validate(value, ctx.path); | ||
| if (result.ok) { | ||
| return true; | ||
| } | ||
| issues.push(...result.issues); | ||
| } | ||
| if (issues.length === 0) { | ||
| ctx.report({ | ||
| message: `Value did not satisfy ${summary}`, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| for (const issue of issues) { | ||
| ctx.report(issue); | ||
| } | ||
| return false; | ||
| } | ||
| }); | ||
| } | ||
| function intersection(validators, options = {}) { | ||
| if (validators.length === 0) { | ||
| throw new Error("intersection requires at least one validator"); | ||
| } | ||
| assertShapeArguments(value) { | ||
| if (!this.shape) { | ||
| return; | ||
| const summary = options.summary ?? `intersection<${validators.map((validator) => validator.summary).join(" & ")}>`; | ||
| const specificity = options.specificity ?? validators.reduce((total, validator) => total + validator.specificity, 0); | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| for (const validator of validators) { | ||
| const result = validator.validate(value, ctx.path); | ||
| if (!result.ok) { | ||
| for (const issue of result.issues) { | ||
| ctx.report(issue); | ||
| } | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| if (!value || !this.blueprint || !(value instanceof this.blueprint)) { | ||
| return; | ||
| }); | ||
| } | ||
| function instanceOf(ctor, validator, options = {}) { | ||
| const name = ctor.name || "<anonymous>"; | ||
| const summary = options.summary ?? `instanceof ${name}`; | ||
| const specificity = options.specificity ?? (validator ? Math.max(validator.specificity + 1, 4) : 4); | ||
| return createValidator({ | ||
| summary, | ||
| specificity, | ||
| optional: options.optional ?? false, | ||
| validate(value, ctx) { | ||
| if (value === void 0 && options.optional) { | ||
| return true; | ||
| } | ||
| if (!(value instanceof ctor)) { | ||
| ctx.report({ | ||
| message: `Expected ${summary} but received ${describeValue(value)}`, | ||
| actual: value, | ||
| expected: summary | ||
| }); | ||
| return false; | ||
| } | ||
| if (!validator) { | ||
| return true; | ||
| } | ||
| const result = validator.validate(value, ctx.path); | ||
| if (!result.ok) { | ||
| forwardIssues(ctx, result.issues); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| this.shape.validate(value); | ||
| if (this.shape.accumulator.length > 0) { | ||
| this.accumulator.push(this.shape.accumulator); | ||
| } | ||
| }); | ||
| } | ||
| function forwardIssues(ctx, issues) { | ||
| for (const issue of issues) { | ||
| ctx.report(issue); | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertIsInstance(value); | ||
| this.assertShapeArguments(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function instance(...args) { | ||
| return new InstanceArgument(args); | ||
| } | ||
| // src/arguments/function-argument.ts | ||
| var import_myzod11 = require("myzod"); | ||
| var FunctionValidationSchema = (0, import_myzod11.object)({ | ||
| maxArgLength: (0, import_myzod11.number)().optional(), | ||
| minArgLength: (0, import_myzod11.number)().optional(), | ||
| argLength: (0, import_myzod11.number)().optional(), | ||
| name: (0, import_myzod11.string)().optional() | ||
| }).and(BaseArgumentSchema); | ||
| var FunctionArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "function"; | ||
| this.types = []; | ||
| if (typeof args[0] === "string") { | ||
| this.name = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| // src/authoring/signature-builder.ts | ||
| var SignatureBuilder = class _SignatureBuilder { | ||
| constructor(state) { | ||
| this.state = state; | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 === this.typeName || typeof type2 === this.typeName; | ||
| } | ||
| assertIsFunction(value) { | ||
| if (value === void 0) { | ||
| return; | ||
| static create(validators, name, description) { | ||
| const normalizedValidators = [...validators]; | ||
| let state = { | ||
| validators: normalizedValidators, | ||
| fallback: false | ||
| }; | ||
| if (name !== void 0) { | ||
| state = { ...state, name }; | ||
| } | ||
| if (typeof value !== "function") { | ||
| const message = `Expected function arguments to be a function but found ${typeof value}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| if (description !== void 0) { | ||
| state = { ...state, description }; | ||
| } | ||
| return new _SignatureBuilder(state); | ||
| } | ||
| assertLengthLessThanMax(value, length2 = this.options?.maxArgLength) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (typeof value !== "function") { | ||
| return; | ||
| } | ||
| if (length2 && value?.length <= length2) { | ||
| const message = `Expected function arguments to be an array with max length ${length2} but was ${value?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| withHandler(handler) { | ||
| return new _SignatureBuilder({ ...this.state, handler }); | ||
| } | ||
| assertLengthGreaterThanMin(value, length2 = this.options?.maxArgLength) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (typeof value !== "function") { | ||
| return; | ||
| } | ||
| if (length2 && value?.length >= length2) { | ||
| const message = `Expected function arguments to be an array with min length ${length2} but was ${value?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| withThrows(spec) { | ||
| const nextState = spec.message === void 0 ? { ...this.state, throws: { error: spec.error } } : { ...this.state, throws: spec }; | ||
| return new _SignatureBuilder(nextState); | ||
| } | ||
| assertLengthEquals(value, length2 = this.options?.argLength) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (typeof value !== "function") { | ||
| return; | ||
| } | ||
| if (length2 !== void 0 && length2 !== value?.length) { | ||
| const message = `Expected function arguments to have length ${length2} but was ${value?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| markFallback() { | ||
| return new _SignatureBuilder({ ...this.state, fallback: true }); | ||
| } | ||
| assertName(value, name = this.options?.name) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (typeof value !== "function") { | ||
| return; | ||
| } | ||
| if (name && value.name === name) { | ||
| const message = `Expected function to have name ${name} but was ${value?.name}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| build() { | ||
| return { | ||
| validators: this.state.validators, | ||
| fallback: this.state.fallback, | ||
| ...this.state.name ? { name: this.state.name } : {}, | ||
| ...this.state.description ? { description: this.state.description } : {}, | ||
| ...this.state.handler ? { handler: this.state.handler } : {}, | ||
| ...this.state.throws ? { throws: this.state.throws } : {} | ||
| }; | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertIsFunction(value); | ||
| this.assertLengthEquals(value); | ||
| this.assertLengthGreaterThanMin(value); | ||
| this.assertLengthLessThanMax(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function func(...args) { | ||
| return new FunctionArgument(args); | ||
| } | ||
| // src/arguments/nil-argument.ts | ||
| var import_myzod12 = __toESM(require("myzod"), 1); | ||
| var NilValidatorOpsSchema = (0, import_myzod12.object)({ | ||
| equals: import_myzod12.default.literal("null").or(import_myzod12.default.literal("undefined")).optional() | ||
| }).and(BaseArgumentSchema); | ||
| var NilArgumentConstructorSchema = (0, import_myzod12.tuple)([(0, import_myzod12.string)(), NilValidatorOpsSchema]).or((0, import_myzod12.tuple)([(0, import_myzod12.string)().or(NilValidatorOpsSchema)])).or((0, import_myzod12.tuple)([])); | ||
| var NilArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "undefined"; | ||
| if (!args) { | ||
| return; | ||
| } | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| // src/authoring/overloads.ts | ||
| function def(...inputs) { | ||
| const [first] = inputs; | ||
| if (isTemplateLiteral(first)) { | ||
| const name = first[0] ?? ""; | ||
| return (...later) => buildDef({ name }, later); | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 === null || type2 === void 0; | ||
| return buildDef({}, inputs); | ||
| } | ||
| function fallback(...args) { | ||
| const [first, maybeHandler] = args; | ||
| let metadata = {}; | ||
| let handler; | ||
| if (typeof first === "function") { | ||
| handler = first; | ||
| } else if (typeof first === "string") { | ||
| metadata = { description: first }; | ||
| handler = maybeHandler; | ||
| } else { | ||
| metadata = first ?? {}; | ||
| handler = maybeHandler; | ||
| } | ||
| assertIsNullOrUndefined(value) { | ||
| if (value == null && value !== void 0) { | ||
| const msg = `Expected ${this.typeName} to be null or undefined but found ${value}`; | ||
| this.accumulator.push(this.fmt(msg)); | ||
| } | ||
| if (typeof handler !== "function") { | ||
| throw new Error("fallback requires a handler function"); | ||
| } | ||
| assertIsNull(value) { | ||
| if ((this.options?.equals === "undefined" || !this.options?.equals) && value === void 0) { | ||
| return; | ||
| } | ||
| if (value !== null) { | ||
| const msg = `Expected ${this.typeName} to be null but found ${value}`; | ||
| this.accumulator.push(this.fmt(msg)); | ||
| } | ||
| } | ||
| assertIsUndefined(value) { | ||
| if (this.options?.equals === "null" && value === null) { | ||
| return; | ||
| } | ||
| if (value !== void 0) { | ||
| const msg = `Expected ${this.typeName} to be undefined but found ${value}`; | ||
| this.accumulator.push(this.fmt(msg)); | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.assertIsUndefined(value); | ||
| this.assertIsNull(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function nil(...args) { | ||
| NilArgumentConstructorSchema.parse(args); | ||
| return new NilArgument(args); | ||
| const builder = SignatureBuilder.create([], metadata.name ?? "fallback", metadata.description).withHandler(handler).markFallback(); | ||
| return builder.build(); | ||
| } | ||
| // src/arguments/type-argument.ts | ||
| var TypeArgument = class extends BaseArgument { | ||
| constructor(strOrT, type2) { | ||
| super(); | ||
| this.typeName = "function"; | ||
| this.types = []; | ||
| if (strOrT === "string") { | ||
| this.name = strOrT; | ||
| this.type = type2; | ||
| function overloads(...definitions) { | ||
| const matcher = Matcher.from(definitions); | ||
| return { | ||
| use(args) { | ||
| return matcher.use(args); | ||
| } | ||
| if (typeof strOrT === "function") { | ||
| this.type = strOrT; | ||
| } | ||
| if (typeof type2 === "function") { | ||
| this.type = type2; | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 === this.typeName || typeof type2 === this.typeName; | ||
| } | ||
| assertType(value, match = this.type) { | ||
| if (value === match) { | ||
| return; | ||
| } | ||
| this.accumulator.push( | ||
| this.fmt( | ||
| `Expected value of ${value} to be of type ${match.name} but it was not.` | ||
| ) | ||
| ); | ||
| } | ||
| validate(value) { | ||
| this.assertIsDefined(value); | ||
| this.baseAssertions(value); | ||
| this.assertType(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function type(nameOrType, type2) { | ||
| return new TypeArgument(nameOrType, type2); | ||
| }; | ||
| } | ||
| // src/overloads.ts | ||
| var Overloads = class { | ||
| constructor(overloads2) { | ||
| this.overloads = overloads2; | ||
| function buildDef(initialMetadata, inputs) { | ||
| const { metadata, validators } = splitMetadataAndValidators(inputs, initialMetadata); | ||
| if (validators.length === 0) { | ||
| throw new Error("def requires at least one validator"); | ||
| } | ||
| match(args) { | ||
| for (const overload of this.overloads) { | ||
| const match = overload.isMatch(args); | ||
| if (match && overload.actionOrError instanceof Function) { | ||
| return overload.actionOrError(...args); | ||
| } | ||
| if (match && overload.actionOrError instanceof Error) { | ||
| throw overload.actionOrError; | ||
| } | ||
| const builder = SignatureBuilder.create([...validators], metadata.name, metadata.description); | ||
| return { | ||
| match(handler) { | ||
| return builder.withHandler(handler).build(); | ||
| }, | ||
| throws(errorCtor, message) { | ||
| const spec = message === void 0 ? { error: errorCtor } : { error: errorCtor, message }; | ||
| return builder.withThrows(spec).build(); | ||
| } | ||
| const fallback2 = this.overloads.find((it) => it.fallback === true); | ||
| if (fallback2 && fallback2.actionOrError instanceof Function) { | ||
| return fallback2.actionOrError(...args); | ||
| } | ||
| const reports = this.overloads.map((it, idx) => it.getReport(idx, args)).join("\n\n"); | ||
| throw new Error(`No overloaded function implementation was found for | ||
| function(${args.join(", ")}){} | ||
| ${reports}`); | ||
| } | ||
| }; | ||
| function overloads(...args) { | ||
| const overloads2 = new Overloads(args); | ||
| return { | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| use: (actualArgs) => overloads2.match(actualArgs) | ||
| }; | ||
| } | ||
| // src/dispose-description.ts | ||
| function disposeDescription(args) { | ||
| if (typeof args[0] === "string") { | ||
| return args.shift(); | ||
| function splitMetadataAndValidators(inputs, initial) { | ||
| const queue = [...inputs]; | ||
| let metadata = { ...initial }; | ||
| if (queue.length > 0 && typeof queue[0] === "string") { | ||
| const description = queue.shift(); | ||
| if (description.length > 0) { | ||
| metadata = { ...metadata, description }; | ||
| } | ||
| } | ||
| return ""; | ||
| } | ||
| function disposeTaggedTemplate(args) { | ||
| if (Array.isArray(args[0])) { | ||
| return [args[0][0], true]; | ||
| if (queue.length > 0 && isMetadata(queue[0])) { | ||
| const metaArg = queue.shift(); | ||
| metadata = { ...metadata, ...metaArg }; | ||
| } | ||
| return ["", false]; | ||
| } | ||
| // src/formatting.ts | ||
| var import_colors_cli = __toESM(require("colors-cli"), 1); | ||
| function colorCompareArgStrings(expected, actual) { | ||
| const maxLength = Math.max(expected.length, actual.length); | ||
| const firstAccumulator = []; | ||
| const secondAccumulator = []; | ||
| for (let i = 0; i < maxLength; i++) { | ||
| const firstArg = expected[i]; | ||
| const secondArg = actual[i]; | ||
| if (firstArg !== secondArg) { | ||
| firstAccumulator.push(import_colors_cli.default.yellow(firstArg)); | ||
| secondAccumulator.push(import_colors_cli.default.red(secondArg)); | ||
| } else { | ||
| firstAccumulator.push(import_colors_cli.default.green(firstArg)); | ||
| secondAccumulator.push(import_colors_cli.default.green(secondArg)); | ||
| const validators = []; | ||
| for (const candidate of queue) { | ||
| if (!isValidator(candidate)) { | ||
| throw new Error("def expects validators after metadata"); | ||
| } | ||
| validators.push(candidate); | ||
| } | ||
| return [firstAccumulator, secondAccumulator]; | ||
| return { metadata, validators }; | ||
| } | ||
| function argStringArray(args) { | ||
| return args.map((arg) => { | ||
| const type2 = typeof arg; | ||
| const asRecord = arg; | ||
| if (typeof asRecord === "object" && "constructor" in asRecord) { | ||
| return asRecord.constructor.name; | ||
| } | ||
| return type2; | ||
| }); | ||
| function isValidator(value) { | ||
| return Boolean(value) && typeof value === "object" && typeof value.validate === "function"; | ||
| } | ||
| // src/overload.ts | ||
| var Overload = class { | ||
| constructor(name, description, args, actionOrError, fallback2 = false) { | ||
| this.name = name; | ||
| this.description = description; | ||
| this.args = args; | ||
| this.actionOrError = actionOrError; | ||
| this.fallback = fallback2; | ||
| args.forEach((arg, idx) => arg.withIndex(idx)); | ||
| function isMetadata(value) { | ||
| if (!value || typeof value !== "object") { | ||
| return false; | ||
| } | ||
| isMatch(args) { | ||
| if (args === void 0 || args === null) { | ||
| args = []; | ||
| } | ||
| for (let i = 0; i < this.args.length; i++) { | ||
| const argWrapper = this.args[i]; | ||
| const arg = args[i]; | ||
| if (!argWrapper.validate(arg)) { | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| if (isValidator(value)) { | ||
| return false; | ||
| } | ||
| typeStringArray() { | ||
| return this.args.map((it) => it.typeName); | ||
| } | ||
| getReport(index, realArgs) { | ||
| const expectedTypeStrings = this.typeStringArray(); | ||
| const actualTypeStrings = argStringArray(realArgs); | ||
| const compare = colorCompareArgStrings( | ||
| expectedTypeStrings, | ||
| actualTypeStrings | ||
| ); | ||
| return `Overload[${index}] did not match because: | ||
| Expected: ${compare[0].join(", ")} | ||
| Actual : ${compare[1].join(", ")} | ||
| ${this.args.filter((it) => it.accumulator.length > 0).map((it) => it.accumulator.join("\n\n "))}`; | ||
| } | ||
| }; | ||
| // src/def.ts | ||
| function def(...args) { | ||
| const [name, isNamed] = disposeTaggedTemplate(args); | ||
| if (isNamed) { | ||
| return (...args2) => { | ||
| const description2 = disposeDescription(args2); | ||
| return { | ||
| /** | ||
| * Implementation for a specific overload. When the arguments passed match this functions | ||
| * parent overload, the arguments will be passed to this functions parameters. | ||
| * | ||
| * The return value will be used in a union in the final return value of the overloading function/method | ||
| * @param implementation | ||
| * @returns | ||
| */ | ||
| matches: (implementation) => { | ||
| return new Overload(name, description2, args2, implementation); | ||
| } | ||
| }; | ||
| }; | ||
| } | ||
| const description = disposeDescription(args); | ||
| return { | ||
| /** | ||
| * Implementation for a specific overload. When the arguments passed match this functions | ||
| * parent overload, the arguments will be passed to this functions parameters. | ||
| * | ||
| * The return value will be used in a union in the final return value of the overloading function/method | ||
| * @param implementation | ||
| * @returns | ||
| */ | ||
| matches: (implementation) => { | ||
| return new Overload(name, description, args, implementation); | ||
| }, | ||
| throws: (message, errorType) => { | ||
| return new Overload(name, description, args, errorType ?? Error); | ||
| } | ||
| }; | ||
| const candidate = value; | ||
| return "name" in candidate || "description" in candidate; | ||
| } | ||
| function isTemplateLiteral(value) { | ||
| return Array.isArray(value) && Object.prototype.hasOwnProperty.call(value, "raw"); | ||
| } | ||
| // src/fallback.ts | ||
| function fallback(...args) { | ||
| const description = disposeDescription(args); | ||
| const [implementation] = args; | ||
| return new Overload( | ||
| "fallback", | ||
| description, | ||
| [], | ||
| implementation, | ||
| true | ||
| ); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| BaseArgument, | ||
| TypeArgument, | ||
| UnionArgument, | ||
| array, | ||
| boolean, | ||
| date, | ||
| def, | ||
| fallback, | ||
| func, | ||
| instance, | ||
| nil, | ||
| number, | ||
| or, | ||
| overloads, | ||
| shape, | ||
| string, | ||
| tuple, | ||
| type, | ||
| unknown | ||
| }); | ||
| export { AmbiguousOverloadError, Matcher, NoOverloadMatchedError, SignatureBuilder, array, boolean, createValidator, def, failure, fallback, func, instanceOf, intersection, literal, normalizeDefinition, normalizeSignatures, number, overloads, shape, string, success, tuple, typeOf, union, unknown }; | ||
| //# sourceMappingURL=out.js.map | ||
| //# sourceMappingURL=index.js.map |
+31
-26
| { | ||
| "name": "@autometa/overloaded", | ||
| "version": "0.3.2", | ||
| "version": "1.0.0-rc.0", | ||
| "description": "Function and method overloading made easy.", | ||
| "type": "module", | ||
| "main": "dist/index.js", | ||
| "module": "./dist/esm/index.js", | ||
| "types": "./dist/index.d.ts", | ||
| "type": "module", | ||
| "description": "Function and method overloading made easy", | ||
| "homepage": "https://github.com/Bendat/autometa/tree/main/libraries/overloaded", | ||
| "author": "Ben Aherne", | ||
| "license": "MIT", | ||
| "module": "dist/index.js", | ||
| "types": "dist/index.d.ts", | ||
| "files": [ | ||
| "dist" | ||
| ], | ||
| "exports": { | ||
| "import": "./dist/esm/index.js", | ||
| "import": "./dist/index.js", | ||
| "require": "./dist/index.js", | ||
| "default": "./dist/esm/index.js", | ||
| "default": "./dist/index.js", | ||
| "types": "./dist/index.d.ts" | ||
| }, | ||
| "license": "MIT", | ||
| "devDependencies": { | ||
| "@types/git-diff": "^2.0.3", | ||
| "@types/node": "^18.11.18", | ||
| "@typescript-eslint/eslint-plugin": "^5.0.0", | ||
| "@typescript-eslint/parser": "^5.0.0", | ||
| "@vitest/coverage-c8": "^0.32.2", | ||
| "@vitest/coverage-istanbul": "^0.31.0", | ||
| "@types/uuid": "^9.0.1", | ||
| "@typescript-eslint/eslint-plugin": "^5.54.1", | ||
| "@typescript-eslint/parser": "^5.54.1", | ||
| "eslint": "^8.37.0", | ||
| "istanbul": "^0.4.5", | ||
| "prettier": "^2.8.3", | ||
| "eslint-config-prettier": "^8.3.0", | ||
| "rimraf": "^4.1.2", | ||
| "tsconfig": "0.7.0", | ||
| "tsup": "^7.2.0", | ||
| "typescript": "^4.9.5", | ||
| "vitest": "0.34.6" | ||
| "vitest": "1.4.0", | ||
| "tsconfig": "0.7.0", | ||
| "tsup-config": "0.1.0", | ||
| "eslint-config-custom": "0.6.0" | ||
| }, | ||
@@ -41,12 +41,17 @@ "dependencies": { | ||
| "scripts": { | ||
| "type-check": "tsc --noEmit -p tsconfig.dev.json", | ||
| "type-check:watch": "tsc --noEmit --watch -p tsconfig.dev.json", | ||
| "build": "tsup && pnpm run build:types", | ||
| "build:types": "rimraf tsconfig.types.tsbuildinfo && tsc --build tsconfig.types.json", | ||
| "build:watch": "tsup --watch", | ||
| "dev": "tsup --watch", | ||
| "test": "vitest run --passWithNoTests", | ||
| "coverage": "vitest run --coverage", | ||
| "prettify": "prettier --config .prettierrc 'src/**/*.ts' --write", | ||
| "test:watch": "vitest --passWithNoTests", | ||
| "test:ui": "vitest --ui --passWithNoTests", | ||
| "coverage": "vitest run --coverage --passWithNoTests", | ||
| "lint": "eslint . --max-warnings 0", | ||
| "clean": "rimraf dist", | ||
| "lint:fix": "eslint . --fix", | ||
| "build": "tsup", | ||
| "build:watch": "tsup --watch" | ||
| }, | ||
| "readme": "# Overloaded\n\nOverloads as easy to make as they are to use.\n\nInspired by [zod](https://zod.dev/) and [myzod](https://github.com/davidmdm/myzod)\n\n## Quick Start\n\n### Contrived Example:\n\n```ts\nexport function myFunc(a: string): string;\nexport function myFunc(a: string, b: number): string;\nexport function myFunc(a: string, b: string): string;\nexport function myFunc(a: string, b: { a: string; b: number[] }): string;\nexport function myFunc(a: string, b: MyClassBuilder): MyClass;\nexport function myFunc(...args: unknown) {\n return overloads(\n // optional name 'a' // type of 'a' inferred as 'string'\n def(string(\"a\")).matches((a) => `hello ${a}`),\n\n // simply declare each argument as you expect it. The first match will\n // be executed\n def(string(\"a\"), number(\"b\")).matches((a, b) => `hello ${a}`.repeat(b)),\n\n // Verify complex (even nested) objects, arrays, tuples.\n def(string(\"a\"), shape({ a: string(), arr: array([number()]) })).matches(\n (a, b) => b.arr.map((num) => `${num}: hello ${a}: ${b.a}`)\n ),\n\n // Check for an instance of a class. Optionally provide a 'shape' as above\n def(string(\"a\"), instance(\"b\", MyClassBuilder)).matches(\n (name, myClassBuilder) => myClassBuilder.setName(name).build()\n ),\n\n // validate actual values - useful for configurable, non overloaded functions\n // or implementing the strategy pattern.\n def(\n string(\"a\", { equals: \"admin\" }),\n string(\"b\", { in: [\"buyer\", \"seller\"] })\n ).matches((a) => `hello ${a}`),\n\n // Throw an error if no matching overload, or define a fallback\n fallback((...args: unknown[]) => {\n // .. do some fallback stuff\n })\n ).use(args);\n}\n```\n\n### Install\n\n```sh\nnpm add @autometa/overloaded\n```\n\n```sh\nyarn add @autometa/overloaded\n```\n\n```sh\npnpm add @autometa/overloaded\n```\n\n### Function & Method Overloads\n\nFunction and method overloads are an elegant way to expose multiple definition signatures\nfor a function which help intellisense and display more clear intent about the purpose\nof your function for a given input.\n\nImagine a function with the following requirements\n\n- Accepts two values, `a` and `b`\n- Both `a` and `b` can be either a `string` or a `number`.\n- If `a` is a `string` then `b` must be a `string`.\n- If `a` is a `number` then `b` must be a `number`.\n- When `a` and `b` are string, return a tuple [a, b]\n- When `a` and `b` are numbers, return the sum of the numbers.\n\nThis isn't a terribly useful function but that's okay.\n\nThe 'simplest' approach is to use discriminated unions <sub>(... aren't they all?)</sub>.\n\n```ts\nfunction add(\n a: string | number,\n b: string | number\n): [string, string] | number {\n // ...\n}\n```\n\nThis is fine but unless the above requirements are documented somewhere the consumer\nwill not be able to immediately understand how to use this function.\n\nThe solution is overloads. To make this function better for our consumer we can\nadd two new signatures:\n\n```ts\nfunction add(a: string, b: string): [string, string];\nfunction add(a: number, b: number): number;\nfunction add(\n a: string | number,\n b: string | number\n): [string, string] | number {\n // ...\n}\n```\n\nNow for our consumers this function makes a lot of sense. Once they provide a valid value for `a`, the\ntypes `b` and `return` will automatically be inferred according to our requirements. We can even\ndocument each overload separately.\n\n```ts\n/**\n * blah blah blah\n */\nfunction add(a: string, b: string): [string, string];\n/**\n * blah blah blah\n */\nfunction add(a: number, b: number): number;\nfunction add(\n a: string | number,\n b: string | number\n): [string, string] | number {\n // ...\n}\n```\n\n#### Implementing an overload\n\nWhile our function is nice to use, implementing it is a bit more grueling.\nWe need to check our types and perform the correct behavior, also accounting\nfor error states:\n\n```ts\nfunction add(a: string, b: string): [string, string];\nfunction add(a: number, b: number): number;\nfunction add(\n a: string | number,\n b: string | number\n): [string, string] | number {\n if (typeof a === \"string\") {\n if (typeof b === \"string\") {\n return [a, b];\n } else {\n throw new Error(\"a & b must both be strings\");\n }\n }\n if (typeof a === \"number\") {\n if (typeof b === \"number\") {\n return a + b;\n } else {\n throw new Error(\"a & b must both be numbers\");\n }\n }\n\n throw new Error(\"unknown types a & b must be string or number\");\n}\n```\n\nFor just two variables with two primitive types, this is pretty rough.\nWe can imagine then how it might look if `a` and `b` can be completely different types from each other - including more complex types like objects and arrays which require even more validation.\n\nAt some point the the function parameter list becomes unmaintainable\nat the base level, which is easily resolved with a rest param.\n\n```ts\nfunction add(a: string, b: string): [string, string];\nfunction add(a: number, b: number): number;\nfunction add(a: [string, boolean], b: MyLibOpts): number;\nfunction add(...args: unknown[]): [string, string] | number {}\n```\n\nOkay so how does **_Overloaded_** help?\n\n### Implementing an overload in _Overloaded_\n\nUsing overloaded to build your function and method overloads is simple.\nCall the `overloads` function with your `param` overloads, then pass\nthe real arguments.\n\nOverloaded functions are defined by the function pair `def` and it's child function `match`. Def accepts a rest param array of `BaseArguments`.\nA `BaseArgument` can be created by it's corresponding function. So `StringArgument` has a `string()` factory function, while `BooleanArgument`\nhas the factory function `boolean()`. `def` returns an object\ncontaining a `match` function. `match` accepts a function who's parameter\nsignature will be inferred from the preceding `def`.\n\nI.E. for `def(string(), string())`, the `match` callback\nwill accept exactly 2 arguments which must be strings:\n\n```ts\n// ---------------------- V 'a' and 'b' both inferred as 'string'\ndef(string(), string()).match((a, b)=>}{})\n// okay but redundant\ndef(string(), string()).match((a: string, b: string)=>}{});\n// bad - ts error\ndef(string(), string()).match((a: string, b: number)=>}{});\n```\n\nOverloads can also have a fallback which is executed if no match is found.\n\nSticking with our original 2 overloads:\n\n```ts\nimport { overloads, def, string, number } from \"@autometa/overloaded\";\n\nfunction add(a: string, b: string): [string, string];\nfunction add(a: number, b: number): number;\nfunction add(\n // 'unknown' instead of union is also fine here\n ...args: (string | number)[]\n){\n return overloads(\n def(string(), string()).match((a, b) => [a, b]),\n def(number(), number()).match((a, b) => a + b),\n fallback((a, b) => {\n const types = [typeof a, typeof b];\n const message = `Expected \"a\" and \"b\" to be of the same type, either string or number. Found: ${types}`;\n throw new Error(message);\n })\n ).use(args);\n}\n```\n\nAnd that's it. We now have an equivalent implementation as what we started with.\n\nThe return types for the base function definition will be inferred as a union\nof the return types of each `match`. If no matching overload is found, an error will be thrown\nhighlighting each overload and provided context as to why it was not matched.\n\nIn the above example, the inferred return type is `[string, string] | number `\n\n### Arguments\n\nWe saw Arguments in our above example. They are factory functions\nnamed approximately the same as their corresponding type.\n\nSome like the above can be called with no additional arguments. Some require additional context.\nAll argument factories can be named. It is suggested these names match the name\nin the corresponding overload. Rewriting the above example:\n\n```ts\nimport { overloads, def, string, number } from \"@autometa/overloaded\";\nfunction add(a: string, b: string): [string, string];\nfunction add(a: number, b: number): number;\nfunction add(\n ...args: (string | number)[]\n // ...args: unknown[] // generalized alternative\n){\n return overloads(\n def(string('a'), string('b')).match((a, b) => [a, b])\n def(number('a'), number('b')).match((a, b) => a + b)\n // // if using individual args like (a: string, b: string) pass an array [a, b] to `use`\n ).use(args);\n}\n```\n\n**Note:** It is not necessary for all overload parameters to share the same names. Likewise it is not necessary overloaded argument factories to share the same name across overloads.\n\nThe name is optional, and is used primarily for context when an error is thrown. If no\nname is provided, the arguments index in the parameter list will be used instead.\n\n### Assertions\n\nAssertions are an additional layer of overload matching which can be employed. Validations\nmean that Overloaded can have useful applications in non-overloaded functions also. Each\ntype factory has its own set of validations which can be used. Using string here as an example:\n\n```ts\nimport { admin, buyer, seller } from \"./user-actions\";\n\ntype UserTypes = \"admin\" | \"buyer\" | \"seller\";\n\nfunction performUserAction(userType: UserTypes, data: unknown) {\n return overloads(\n def(string(\"userType\", { equals: \"admin\" }), unknown(\"data\")).match(\n (_userType, data) => {\n return admin.action(data);\n }\n ),\n def(string(\"userType\", { equals: \"buyer\" }), unknown(\"data\")).match(\n (_userType, data) => {\n return buyer.action(data);\n }\n ),\n def(string(\"userType\", { equals: \"seller\" }), unknown(\"data\")).match(\n (_userType, data) => {\n return seller.action(data);\n }\n )\n ).use([userType]);\n}\n```\n\nCongratulations. You have implemented... an over-engineered switch statement!\n\nHowever there are other checks like 'minLength', 'maxLength', 'startsWith' etc which can be composed together to simplify filtering logic for some domains. Each argument type has it's own assertions.\n\nAssertions can of course also be used within an overloaded function or method to\nprovide additional filtering.\n\nAssertions are used for filtering, and do not throw errors by themselves.\n\n**Note** Some assertions are ignored if an invalid type is passed. For example,\nmost string assertions will not be executed if a number or boolean or object is\npassed. In that case the assertion executed will be on the type itself.\n\n### Fallback\n\nIf no overloads match the provided argument an Error will be thrown\ndetailing why each overload failed to match.\n\nAlternatively it is possible to provide a 'fallback' which\nwill be executed instead of an error being thrown. The fallback\nwill receive a rest param of arguments with types being `unknown`\n\nA Fallback is defined with the `fallback` function.\n\n```ts\nimport { overloads, def, string, number } from \"@autometa/overloaded\";\n\nfunction add(a: string, b: string): [string, string];\nfunction add(a: number, b: number): number;\n\nfunction add(\n ...args: (string | number)[] // 'unknown' is a union is also fine here\n) {\n return overloads(\n def(string(), string()).match((a, b) => [a, b]),\n def(number(), number()).match((a, b) => a + b),\n fallback((...args: unknown[]) => console.log(args))\n ).use(args);\n}\n```\n\n## Normalize Constructor or function arguments\n\n```ts\ndeclare class MyObject {\n constructor(name: string | undefined, widgets: string[] | undefined);\n}\nfunction makeMyClass(name: string): MyObject;\nfunction makeMyClass(widgets: string[]): MyObject;\nfunction makeMyClass(name: string, widgets: string[]): MyObject;\nfunction makeMyClass(...args: (string | string[])[]) {\n return overloads(\n // Create an instance with only a name\n def(string(\"name\")).matches((name) => new MyObject(name, undefined)),\n // Create an instance with only its list of widgets\n def(array(\"widgets\", [string()])).matches(\n (name, widgets) => new MyObject(undefined, widgets)\n ),\n // Create an instance with both a name and its list of widgets\n def(string(\"name\"), array(\"widgets\", [string()])).matches(\n (name, widgets) => new MyObject(name, widgets)\n ),\n // No match - Throw an error\n fallback((...args) => {\n throw new Error(\n `A 'MyObject' instance requires either a name, a list of widgets or both. Received: ${args}`\n );\n })\n ).use(args);\n}\n```\n\n## Factory Function\n\nConvert a plain javascript object to a DTO instance. Pretend\nwe have a `plainToDto` function which creates a new instance of a class\nand assigns the values from a raw object to its instance properties\n\n```ts\nabstract class User {\n name: string;\n registered: Date;\n}\nclass AdminUser extends User {\n permissions: (\"read\" | \"write\" | \"ban\" | \"unban\" | \"sticky\")[];\n}\nclass HobbyUser extends User {\n interests: string[];\n}\nclass PaidUser extends User {\n interests: string[];\n tier: number;\n badges: number[];\n}\n\n// return type inferred as\n// AdminUser | HobbyUser | PaidUser\n// Throws an error if no match found.\nfunction createUserDto(user: unknown) {\n return overloads(\n def(shape({ permissions: array([string()]) })).matches((user) => {\n return plainToDto(AdminUser, user);\n }),\n def(shape({ interests: array([string()]) })).matches((user) => {\n return plainToDto(HobbyUser, user);\n }),\n def(shape({ tier: number() })).matches((user) => {\n return plainToDto(PaidUser, user);\n })\n ).use([user]);\n}\n```\n\n## Overload Descriptions\n\nOverloads can take an optional description. Simply provide a string as the\nfirst parameter of an overload. This can be used to document the purpose\nof this particular overload, but won't get lost if things move around\nlike a comment.\n\n```ts\nfunction myOverloadedFunction(...args: unknown[]) {\n return overloads(\n param(\n \"return a FooWidgetWrapper when the first argument is a FooWidget\",\n instance(FooWidget)\n ).matches((widget) => {\n // ... do stuff\n return myNewFooWidgetWrapper;\n })\n ).use(args);\n}\n```\n\n## Naming overloads with `String Templates`\n\n_Please be aware the following is kind of cursed_\n\nIt is possible to name an overload by providing a template string\nliteral before the function call. This can be used in addition to or instead\nof the description.\n\nNames let you produce overloads that vaguely resemble a function definition.\n\n```ts\nreturn overloads(\n def`doThingA`(string(), number()).matches((a, b) => {\n return a.repeat(b);\n }),\n def`doThingB`(string(), string()).matches((a, b) => {\n return `${a} ${b}`;\n })\n);\n\n// Using description\nreturn overloads(\n def`doThingA`(\n \"some additional context about doing thing A\",\n string(),\n number()\n ).matches((a, b) => {\n return a.repeat(b);\n }),\n def`doThingB`(\n \"some other context about doing thing B\",\n string(),\n string()\n ).matches((a, b) => {\n return `${a} ${b}`;\n })\n);\n```\n\n## Argument Types\n\n### Primitives\n\nThe \"primitives\", `string`, `number` and `boolean` are represented by factories\nof matching name. Each accepts a name and assertion options.\n\n#### **String**\n\nMatches an argument in the same position which is a string.\n\n```ts\ndef(string(\"a\")).matches((a) => `Foo: ${a}`);\n```\n\nAssertions:\n\n_equals_: Asserts that two strings are exactly equal\n\n```ts\ndef(string(\"a\", { equals: \"user\" })).matches((a) => UserFactory);\n```\n\n_minLength_: Asserts that any string passed will have at _least_ `n` characters (inclusive), where `n` is the value passed to `minLength`\n\n```ts\ndef(string(\"a\", { minLength: 10 })).matches((a) => `Foo: ${a}`);\n// name is optional\ndef(string({ minLength: 10 })).matches((a) => `Foo: ${a}`);\n```\n\n_maxLength_: Asserts that any string passed will have at _most_ `n` characters (inclusive),\nwhere `n` is the value passed to `minLength`\n\n```ts\ndef(string(\"a\", { maxLength: 10 })).matches((a) => `Foo: ${a}`);\n```\n\n_includes_: Asserts that any string passed includes some substring.\n\n```ts\ndef(string(\"a\", { includes: \"users\" })).matches((a) => usersFactory(a));\n```\n\n_startsWith_: Asserts that a string starts with a specific substring.\n\n```ts\ndef(string(\"a\", { startsWith: \"users\" })).matches((a) => mySettings[a]);\n```\n\n_endsWith_: Asserts that a string ends with a specific substring.\n\n```ts\ndef(string(\"a\", { endsWith: \"users\" })).matches((a) => mySettings[a]);\n```\n\n_in_: Asserts that a string is part of an array.\n\n```ts\ndef(string(\"a\", { in: [\"group1\", \"group2\"] })).matches((a) => this.getGroup(a));\n```\n\n#### **Number**\n\nMatches a parameter which of type `number`.\n\nAssertions:\n\n_min_: Asserts that a number has at least some minimum value (inclusive)\n\n```ts\ndef(number(\"a\", { min: 0 })).matches((a) => myArray[a]);\n```\n\n_max_: Asserts that a number has at most some maximum value (inclusive)\n\n```ts\ndef(number(\"a\", { max: 0 })).matches((a) => throw new Error(`'a' must be positive`));\n```\n\n_in_: Asserts that a number is part of an array.\n\n```ts\ndef(string(\"a\", { in: [101, 102] })).matches((a) =>\n this.courses.enroll.math(a)\n);\n```\n\n_equals_: Asserts that the provided number is exactly equal to the expected.\n\n```ts\ndef(string(\"a\", { equals: 101 })).matches((a) => DalmatianCoatFactory);\n```\n\n_types_: Asserts that the provided value is either an integer\nor a float value.\n\n```ts\ndef(string(\"a\", { type: \"float\" })).matches((a) => a * MY_CONST);\ndef(string(\"a\", { type: \"int\" })).matches((a) => MY_ENUM[a]);\n```\n\n**boolean** assertions\n\n- equals\n\n### Arrays and Tuples\n\nArrays and tuples are similar to each other, but arrays\naccept a list of possible type options with indeterminate\nlength (unless asserted against), while a tuple is an array\nof fixed length with deterministic type options.\n\n**array**\n\n```ts\ndef(array([string(), number()])).match((a: (string | number)[]) => {\n // ...\n});\n```\n\n**Assertions**\n\n- minLength\n- maxLength\n- includes\n\n**tuple**\n\n```ts\ndef(tuple([string(), number()])).match((a: [string, number]) => {\n // ...\n});\n```\n\n**Assertions**\n\n- includes\n\n### Shapes\n\nShapes represent anonymous objects and class instances. It accepts\nan object whose keys match the expected object and whose values\nare Argument types. By default, only properties with keys defined in the `shape`\nwill be used to match.\nIf the real value passed to the overloaded function contains additional\nkeys, they will not be considered for validation, unless the `exhaustive` option is set to true.\n\n```ts\ndef(shape({ a: string(), b: tuple([number(), boolean()]) })).match(\n ({ a, b }) => {\n console.log(a);\n console.log(b[0]);\n console.log(b[1]);\n }\n);\n```\n\n**Assertions**\n\n- exhaustive\n - If true, validation of an overload will fail if the received argument has keys which are not defined by the overload.\n- instance\n - A Class blueprint/prototype from which the provided value should be extended.\n\n### Function\n\nFunctions have minimal validation, providing only a shape\nand an optional argument list length.\n\n```ts\ndef(func<(a: string) => void>()).match((fn) => fn(\"hi\"));\n```\n\n**Assertions**\n\n- length\n - The expected length of the parameter list.\n\n### Unknown\n\nCatch-all/wildcard argument with no typing. Will check if the value\nis defined, which can be overwritten.\n\n```ts\ndef(string(), unknown(), number()).match((a: string, b: unknown, c: number) => {\n // ...\n});\n```\n\n### Date\n\nMatches an instance of the Node `Date` class.\n\n```ts\nimport { yesterdayDate } from \"./my-date-utils\";\n\ndef(date({ before: yesterdayDate() })).match((a: Date) => {\n // ...\n});\n```\n\n**Assertions**\n\n- before\n - Checks that this provided date is chronologically earlier than the configured date\n- after\n - Checks that this provided date is chronologically later than the configured date\n- equal\n - Checks that this provided date is chronologically equal to the configured date\n\n### Instance\n\nMatches an argument which is an instance of a provided class (also referred to here as a blueprint). Optionally accepts a `shape`, which is used to validate the individual\nproperties of the instance.\n\n```ts\ndef(instance(MyClass, shape({ name: string(), age: number() }))).match(\n (a: MyClass) => {\n // ...\n }\n);\n```\n\nInstance assertions can be defined in the `shape` argument.\n" | ||
| "prettify": "prettier --config .prettierrc 'src/**/*.ts' --write", | ||
| "clean": "rimraf dist" | ||
| } | ||
| } |
+2
-693
@@ -1,694 +0,3 @@ | ||
| # Overloaded | ||
| # Introduction | ||
| Overloads as easy to make as they are to use. | ||
| Inspired by [zod](https://zod.dev/) and [myzod](https://github.com/davidmdm/myzod) | ||
| ## Quick Start | ||
| ### Contrived Example: | ||
| ```ts | ||
| export function myFunc(a: string): string; | ||
| export function myFunc(a: string, b: number): string; | ||
| export function myFunc(a: string, b: string): string; | ||
| export function myFunc(a: string, b: { a: string; b: number[] }): string; | ||
| export function myFunc(a: string, b: MyClassBuilder): MyClass; | ||
| export function myFunc(...args: unknown) { | ||
| return overloads( | ||
| // optional name 'a' // type of 'a' inferred as 'string' | ||
| def(string("a")).matches((a) => `hello ${a}`), | ||
| // simply declare each argument as you expect it. The first match will | ||
| // be executed | ||
| def(string("a"), number("b")).matches((a, b) => `hello ${a}`.repeat(b)), | ||
| // Verify complex (even nested) objects, arrays, tuples. | ||
| def(string("a"), shape({ a: string(), arr: array([number()]) })).matches( | ||
| (a, b) => b.arr.map((num) => `${num}: hello ${a}: ${b.a}`) | ||
| ), | ||
| // Check for an instance of a class. Optionally provide a 'shape' as above | ||
| def(string("a"), instance("b", MyClassBuilder)).matches( | ||
| (name, myClassBuilder) => myClassBuilder.setName(name).build() | ||
| ), | ||
| // validate actual values - useful for configurable, non overloaded functions | ||
| // or implementing the strategy pattern. | ||
| def( | ||
| string("a", { equals: "admin" }), | ||
| string("b", { in: ["buyer", "seller"] }) | ||
| ).matches((a) => `hello ${a}`), | ||
| // Throw an error if no matching overload, or define a fallback | ||
| fallback((...args: unknown[]) => { | ||
| // .. do some fallback stuff | ||
| }) | ||
| ).use(args); | ||
| } | ||
| ``` | ||
| ### Install | ||
| ```sh | ||
| npm add @autometa/overloaded | ||
| ``` | ||
| ```sh | ||
| yarn add @autometa/overloaded | ||
| ``` | ||
| ```sh | ||
| pnpm add @autometa/overloaded | ||
| ``` | ||
| ### Function & Method Overloads | ||
| Function and method overloads are an elegant way to expose multiple definition signatures | ||
| for a function which help intellisense and display more clear intent about the purpose | ||
| of your function for a given input. | ||
| Imagine a function with the following requirements | ||
| - Accepts two values, `a` and `b` | ||
| - Both `a` and `b` can be either a `string` or a `number`. | ||
| - If `a` is a `string` then `b` must be a `string`. | ||
| - If `a` is a `number` then `b` must be a `number`. | ||
| - When `a` and `b` are string, return a tuple [a, b] | ||
| - When `a` and `b` are numbers, return the sum of the numbers. | ||
| This isn't a terribly useful function but that's okay. | ||
| The 'simplest' approach is to use discriminated unions <sub>(... aren't they all?)</sub>. | ||
| ```ts | ||
| function add( | ||
| a: string | number, | ||
| b: string | number | ||
| ): [string, string] | number { | ||
| // ... | ||
| } | ||
| ``` | ||
| This is fine but unless the above requirements are documented somewhere the consumer | ||
| will not be able to immediately understand how to use this function. | ||
| The solution is overloads. To make this function better for our consumer we can | ||
| add two new signatures: | ||
| ```ts | ||
| function add(a: string, b: string): [string, string]; | ||
| function add(a: number, b: number): number; | ||
| function add( | ||
| a: string | number, | ||
| b: string | number | ||
| ): [string, string] | number { | ||
| // ... | ||
| } | ||
| ``` | ||
| Now for our consumers this function makes a lot of sense. Once they provide a valid value for `a`, the | ||
| types `b` and `return` will automatically be inferred according to our requirements. We can even | ||
| document each overload separately. | ||
| ```ts | ||
| /** | ||
| * blah blah blah | ||
| */ | ||
| function add(a: string, b: string): [string, string]; | ||
| /** | ||
| * blah blah blah | ||
| */ | ||
| function add(a: number, b: number): number; | ||
| function add( | ||
| a: string | number, | ||
| b: string | number | ||
| ): [string, string] | number { | ||
| // ... | ||
| } | ||
| ``` | ||
| #### Implementing an overload | ||
| While our function is nice to use, implementing it is a bit more grueling. | ||
| We need to check our types and perform the correct behavior, also accounting | ||
| for error states: | ||
| ```ts | ||
| function add(a: string, b: string): [string, string]; | ||
| function add(a: number, b: number): number; | ||
| function add( | ||
| a: string | number, | ||
| b: string | number | ||
| ): [string, string] | number { | ||
| if (typeof a === "string") { | ||
| if (typeof b === "string") { | ||
| return [a, b]; | ||
| } else { | ||
| throw new Error("a & b must both be strings"); | ||
| } | ||
| } | ||
| if (typeof a === "number") { | ||
| if (typeof b === "number") { | ||
| return a + b; | ||
| } else { | ||
| throw new Error("a & b must both be numbers"); | ||
| } | ||
| } | ||
| throw new Error("unknown types a & b must be string or number"); | ||
| } | ||
| ``` | ||
| For just two variables with two primitive types, this is pretty rough. | ||
| We can imagine then how it might look if `a` and `b` can be completely different types from each other - including more complex types like objects and arrays which require even more validation. | ||
| At some point the the function parameter list becomes unmaintainable | ||
| at the base level, which is easily resolved with a rest param. | ||
| ```ts | ||
| function add(a: string, b: string): [string, string]; | ||
| function add(a: number, b: number): number; | ||
| function add(a: [string, boolean], b: MyLibOpts): number; | ||
| function add(...args: unknown[]): [string, string] | number {} | ||
| ``` | ||
| Okay so how does **_Overloaded_** help? | ||
| ### Implementing an overload in _Overloaded_ | ||
| Using overloaded to build your function and method overloads is simple. | ||
| Call the `overloads` function with your `param` overloads, then pass | ||
| the real arguments. | ||
| Overloaded functions are defined by the function pair `def` and it's child function `match`. Def accepts a rest param array of `BaseArguments`. | ||
| A `BaseArgument` can be created by it's corresponding function. So `StringArgument` has a `string()` factory function, while `BooleanArgument` | ||
| has the factory function `boolean()`. `def` returns an object | ||
| containing a `match` function. `match` accepts a function who's parameter | ||
| signature will be inferred from the preceding `def`. | ||
| I.E. for `def(string(), string())`, the `match` callback | ||
| will accept exactly 2 arguments which must be strings: | ||
| ```ts | ||
| // ---------------------- V 'a' and 'b' both inferred as 'string' | ||
| def(string(), string()).match((a, b)=>}{}) | ||
| // okay but redundant | ||
| def(string(), string()).match((a: string, b: string)=>}{}); | ||
| // bad - ts error | ||
| def(string(), string()).match((a: string, b: number)=>}{}); | ||
| ``` | ||
| Overloads can also have a fallback which is executed if no match is found. | ||
| Sticking with our original 2 overloads: | ||
| ```ts | ||
| import { overloads, def, string, number } from "@autometa/overloaded"; | ||
| function add(a: string, b: string): [string, string]; | ||
| function add(a: number, b: number): number; | ||
| function add( | ||
| // 'unknown' instead of union is also fine here | ||
| ...args: (string | number)[] | ||
| ){ | ||
| return overloads( | ||
| def(string(), string()).match((a, b) => [a, b]), | ||
| def(number(), number()).match((a, b) => a + b), | ||
| fallback((a, b) => { | ||
| const types = [typeof a, typeof b]; | ||
| const message = `Expected "a" and "b" to be of the same type, either string or number. Found: ${types}`; | ||
| throw new Error(message); | ||
| }) | ||
| ).use(args); | ||
| } | ||
| ``` | ||
| And that's it. We now have an equivalent implementation as what we started with. | ||
| The return types for the base function definition will be inferred as a union | ||
| of the return types of each `match`. If no matching overload is found, an error will be thrown | ||
| highlighting each overload and provided context as to why it was not matched. | ||
| In the above example, the inferred return type is `[string, string] | number ` | ||
| ### Arguments | ||
| We saw Arguments in our above example. They are factory functions | ||
| named approximately the same as their corresponding type. | ||
| Some like the above can be called with no additional arguments. Some require additional context. | ||
| All argument factories can be named. It is suggested these names match the name | ||
| in the corresponding overload. Rewriting the above example: | ||
| ```ts | ||
| import { overloads, def, string, number } from "@autometa/overloaded"; | ||
| function add(a: string, b: string): [string, string]; | ||
| function add(a: number, b: number): number; | ||
| function add( | ||
| ...args: (string | number)[] | ||
| // ...args: unknown[] // generalized alternative | ||
| ){ | ||
| return overloads( | ||
| def(string('a'), string('b')).match((a, b) => [a, b]) | ||
| def(number('a'), number('b')).match((a, b) => a + b) | ||
| // // if using individual args like (a: string, b: string) pass an array [a, b] to `use` | ||
| ).use(args); | ||
| } | ||
| ``` | ||
| **Note:** It is not necessary for all overload parameters to share the same names. Likewise it is not necessary overloaded argument factories to share the same name across overloads. | ||
| The name is optional, and is used primarily for context when an error is thrown. If no | ||
| name is provided, the arguments index in the parameter list will be used instead. | ||
| ### Assertions | ||
| Assertions are an additional layer of overload matching which can be employed. Validations | ||
| mean that Overloaded can have useful applications in non-overloaded functions also. Each | ||
| type factory has its own set of validations which can be used. Using string here as an example: | ||
| ```ts | ||
| import { admin, buyer, seller } from "./user-actions"; | ||
| type UserTypes = "admin" | "buyer" | "seller"; | ||
| function performUserAction(userType: UserTypes, data: unknown) { | ||
| return overloads( | ||
| def(string("userType", { equals: "admin" }), unknown("data")).match( | ||
| (_userType, data) => { | ||
| return admin.action(data); | ||
| } | ||
| ), | ||
| def(string("userType", { equals: "buyer" }), unknown("data")).match( | ||
| (_userType, data) => { | ||
| return buyer.action(data); | ||
| } | ||
| ), | ||
| def(string("userType", { equals: "seller" }), unknown("data")).match( | ||
| (_userType, data) => { | ||
| return seller.action(data); | ||
| } | ||
| ) | ||
| ).use([userType]); | ||
| } | ||
| ``` | ||
| Congratulations. You have implemented... an over-engineered switch statement! | ||
| However there are other checks like 'minLength', 'maxLength', 'startsWith' etc which can be composed together to simplify filtering logic for some domains. Each argument type has it's own assertions. | ||
| Assertions can of course also be used within an overloaded function or method to | ||
| provide additional filtering. | ||
| Assertions are used for filtering, and do not throw errors by themselves. | ||
| **Note** Some assertions are ignored if an invalid type is passed. For example, | ||
| most string assertions will not be executed if a number or boolean or object is | ||
| passed. In that case the assertion executed will be on the type itself. | ||
| ### Fallback | ||
| If no overloads match the provided argument an Error will be thrown | ||
| detailing why each overload failed to match. | ||
| Alternatively it is possible to provide a 'fallback' which | ||
| will be executed instead of an error being thrown. The fallback | ||
| will receive a rest param of arguments with types being `unknown` | ||
| A Fallback is defined with the `fallback` function. | ||
| ```ts | ||
| import { overloads, def, string, number } from "@autometa/overloaded"; | ||
| function add(a: string, b: string): [string, string]; | ||
| function add(a: number, b: number): number; | ||
| function add( | ||
| ...args: (string | number)[] // 'unknown' is a union is also fine here | ||
| ) { | ||
| return overloads( | ||
| def(string(), string()).match((a, b) => [a, b]), | ||
| def(number(), number()).match((a, b) => a + b), | ||
| fallback((...args: unknown[]) => console.log(args)) | ||
| ).use(args); | ||
| } | ||
| ``` | ||
| ## Normalize Constructor or function arguments | ||
| ```ts | ||
| declare class MyObject { | ||
| constructor(name: string | undefined, widgets: string[] | undefined); | ||
| } | ||
| function makeMyClass(name: string): MyObject; | ||
| function makeMyClass(widgets: string[]): MyObject; | ||
| function makeMyClass(name: string, widgets: string[]): MyObject; | ||
| function makeMyClass(...args: (string | string[])[]) { | ||
| return overloads( | ||
| // Create an instance with only a name | ||
| def(string("name")).matches((name) => new MyObject(name, undefined)), | ||
| // Create an instance with only its list of widgets | ||
| def(array("widgets", [string()])).matches( | ||
| (name, widgets) => new MyObject(undefined, widgets) | ||
| ), | ||
| // Create an instance with both a name and its list of widgets | ||
| def(string("name"), array("widgets", [string()])).matches( | ||
| (name, widgets) => new MyObject(name, widgets) | ||
| ), | ||
| // No match - Throw an error | ||
| fallback((...args) => { | ||
| throw new Error( | ||
| `A 'MyObject' instance requires either a name, a list of widgets or both. Received: ${args}` | ||
| ); | ||
| }) | ||
| ).use(args); | ||
| } | ||
| ``` | ||
| ## Factory Function | ||
| Convert a plain javascript object to a DTO instance. Pretend | ||
| we have a `plainToDto` function which creates a new instance of a class | ||
| and assigns the values from a raw object to its instance properties | ||
| ```ts | ||
| abstract class User { | ||
| name: string; | ||
| registered: Date; | ||
| } | ||
| class AdminUser extends User { | ||
| permissions: ("read" | "write" | "ban" | "unban" | "sticky")[]; | ||
| } | ||
| class HobbyUser extends User { | ||
| interests: string[]; | ||
| } | ||
| class PaidUser extends User { | ||
| interests: string[]; | ||
| tier: number; | ||
| badges: number[]; | ||
| } | ||
| // return type inferred as | ||
| // AdminUser | HobbyUser | PaidUser | ||
| // Throws an error if no match found. | ||
| function createUserDto(user: unknown) { | ||
| return overloads( | ||
| def(shape({ permissions: array([string()]) })).matches((user) => { | ||
| return plainToDto(AdminUser, user); | ||
| }), | ||
| def(shape({ interests: array([string()]) })).matches((user) => { | ||
| return plainToDto(HobbyUser, user); | ||
| }), | ||
| def(shape({ tier: number() })).matches((user) => { | ||
| return plainToDto(PaidUser, user); | ||
| }) | ||
| ).use([user]); | ||
| } | ||
| ``` | ||
| ## Overload Descriptions | ||
| Overloads can take an optional description. Simply provide a string as the | ||
| first parameter of an overload. This can be used to document the purpose | ||
| of this particular overload, but won't get lost if things move around | ||
| like a comment. | ||
| ```ts | ||
| function myOverloadedFunction(...args: unknown[]) { | ||
| return overloads( | ||
| param( | ||
| "return a FooWidgetWrapper when the first argument is a FooWidget", | ||
| instance(FooWidget) | ||
| ).matches((widget) => { | ||
| // ... do stuff | ||
| return myNewFooWidgetWrapper; | ||
| }) | ||
| ).use(args); | ||
| } | ||
| ``` | ||
| ## Naming overloads with `String Templates` | ||
| _Please be aware the following is kind of cursed_ | ||
| It is possible to name an overload by providing a template string | ||
| literal before the function call. This can be used in addition to or instead | ||
| of the description. | ||
| Names let you produce overloads that vaguely resemble a function definition. | ||
| ```ts | ||
| return overloads( | ||
| def`doThingA`(string(), number()).matches((a, b) => { | ||
| return a.repeat(b); | ||
| }), | ||
| def`doThingB`(string(), string()).matches((a, b) => { | ||
| return `${a} ${b}`; | ||
| }) | ||
| ); | ||
| // Using description | ||
| return overloads( | ||
| def`doThingA`( | ||
| "some additional context about doing thing A", | ||
| string(), | ||
| number() | ||
| ).matches((a, b) => { | ||
| return a.repeat(b); | ||
| }), | ||
| def`doThingB`( | ||
| "some other context about doing thing B", | ||
| string(), | ||
| string() | ||
| ).matches((a, b) => { | ||
| return `${a} ${b}`; | ||
| }) | ||
| ); | ||
| ``` | ||
| ## Argument Types | ||
| ### Primitives | ||
| The "primitives", `string`, `number` and `boolean` are represented by factories | ||
| of matching name. Each accepts a name and assertion options. | ||
| #### **String** | ||
| Matches an argument in the same position which is a string. | ||
| ```ts | ||
| def(string("a")).matches((a) => `Foo: ${a}`); | ||
| ``` | ||
| Assertions: | ||
| _equals_: Asserts that two strings are exactly equal | ||
| ```ts | ||
| def(string("a", { equals: "user" })).matches((a) => UserFactory); | ||
| ``` | ||
| _minLength_: Asserts that any string passed will have at _least_ `n` characters (inclusive), where `n` is the value passed to `minLength` | ||
| ```ts | ||
| def(string("a", { minLength: 10 })).matches((a) => `Foo: ${a}`); | ||
| // name is optional | ||
| def(string({ minLength: 10 })).matches((a) => `Foo: ${a}`); | ||
| ``` | ||
| _maxLength_: Asserts that any string passed will have at _most_ `n` characters (inclusive), | ||
| where `n` is the value passed to `minLength` | ||
| ```ts | ||
| def(string("a", { maxLength: 10 })).matches((a) => `Foo: ${a}`); | ||
| ``` | ||
| _includes_: Asserts that any string passed includes some substring. | ||
| ```ts | ||
| def(string("a", { includes: "users" })).matches((a) => usersFactory(a)); | ||
| ``` | ||
| _startsWith_: Asserts that a string starts with a specific substring. | ||
| ```ts | ||
| def(string("a", { startsWith: "users" })).matches((a) => mySettings[a]); | ||
| ``` | ||
| _endsWith_: Asserts that a string ends with a specific substring. | ||
| ```ts | ||
| def(string("a", { endsWith: "users" })).matches((a) => mySettings[a]); | ||
| ``` | ||
| _in_: Asserts that a string is part of an array. | ||
| ```ts | ||
| def(string("a", { in: ["group1", "group2"] })).matches((a) => this.getGroup(a)); | ||
| ``` | ||
| #### **Number** | ||
| Matches a parameter which of type `number`. | ||
| Assertions: | ||
| _min_: Asserts that a number has at least some minimum value (inclusive) | ||
| ```ts | ||
| def(number("a", { min: 0 })).matches((a) => myArray[a]); | ||
| ``` | ||
| _max_: Asserts that a number has at most some maximum value (inclusive) | ||
| ```ts | ||
| def(number("a", { max: 0 })).matches((a) => throw new Error(`'a' must be positive`)); | ||
| ``` | ||
| _in_: Asserts that a number is part of an array. | ||
| ```ts | ||
| def(string("a", { in: [101, 102] })).matches((a) => | ||
| this.courses.enroll.math(a) | ||
| ); | ||
| ``` | ||
| _equals_: Asserts that the provided number is exactly equal to the expected. | ||
| ```ts | ||
| def(string("a", { equals: 101 })).matches((a) => DalmatianCoatFactory); | ||
| ``` | ||
| _types_: Asserts that the provided value is either an integer | ||
| or a float value. | ||
| ```ts | ||
| def(string("a", { type: "float" })).matches((a) => a * MY_CONST); | ||
| def(string("a", { type: "int" })).matches((a) => MY_ENUM[a]); | ||
| ``` | ||
| **boolean** assertions | ||
| - equals | ||
| ### Arrays and Tuples | ||
| Arrays and tuples are similar to each other, but arrays | ||
| accept a list of possible type options with indeterminate | ||
| length (unless asserted against), while a tuple is an array | ||
| of fixed length with deterministic type options. | ||
| **array** | ||
| ```ts | ||
| def(array([string(), number()])).match((a: (string | number)[]) => { | ||
| // ... | ||
| }); | ||
| ``` | ||
| **Assertions** | ||
| - minLength | ||
| - maxLength | ||
| - includes | ||
| **tuple** | ||
| ```ts | ||
| def(tuple([string(), number()])).match((a: [string, number]) => { | ||
| // ... | ||
| }); | ||
| ``` | ||
| **Assertions** | ||
| - includes | ||
| ### Shapes | ||
| Shapes represent anonymous objects and class instances. It accepts | ||
| an object whose keys match the expected object and whose values | ||
| are Argument types. By default, only properties with keys defined in the `shape` | ||
| will be used to match. | ||
| If the real value passed to the overloaded function contains additional | ||
| keys, they will not be considered for validation, unless the `exhaustive` option is set to true. | ||
| ```ts | ||
| def(shape({ a: string(), b: tuple([number(), boolean()]) })).match( | ||
| ({ a, b }) => { | ||
| console.log(a); | ||
| console.log(b[0]); | ||
| console.log(b[1]); | ||
| } | ||
| ); | ||
| ``` | ||
| **Assertions** | ||
| - exhaustive | ||
| - If true, validation of an overload will fail if the received argument has keys which are not defined by the overload. | ||
| - instance | ||
| - A Class blueprint/prototype from which the provided value should be extended. | ||
| ### Function | ||
| Functions have minimal validation, providing only a shape | ||
| and an optional argument list length. | ||
| ```ts | ||
| def(func<(a: string) => void>()).match((fn) => fn("hi")); | ||
| ``` | ||
| **Assertions** | ||
| - length | ||
| - The expected length of the parameter list. | ||
| ### Unknown | ||
| Catch-all/wildcard argument with no typing. Will check if the value | ||
| is defined, which can be overwritten. | ||
| ```ts | ||
| def(string(), unknown(), number()).match((a: string, b: unknown, c: number) => { | ||
| // ... | ||
| }); | ||
| ``` | ||
| ### Date | ||
| Matches an instance of the Node `Date` class. | ||
| ```ts | ||
| import { yesterdayDate } from "./my-date-utils"; | ||
| def(date({ before: yesterdayDate() })).match((a: Date) => { | ||
| // ... | ||
| }); | ||
| ``` | ||
| **Assertions** | ||
| - before | ||
| - Checks that this provided date is chronologically earlier than the configured date | ||
| - after | ||
| - Checks that this provided date is chronologically later than the configured date | ||
| - equal | ||
| - Checks that this provided date is chronologically equal to the configured date | ||
| ### Instance | ||
| Matches an argument which is an instance of a provided class (also referred to here as a blueprint). Optionally accepts a `shape`, which is used to validate the individual | ||
| properties of the instance. | ||
| ```ts | ||
| def(instance(MyClass, shape({ name: string(), age: number() }))).match( | ||
| (a: MyClass) => { | ||
| // ... | ||
| } | ||
| ); | ||
| ``` | ||
| Instance assertions can be defined in the `shape` argument. | ||
| There's nothing here yet |
Sorry, the diff of this file is not supported yet
| module.exports = { | ||
| root: true, | ||
| extends: ["custom"], | ||
| }; |
-130
| # Gherkin | ||
| ## 0.3.2 | ||
| ### Patch Changes | ||
| - 04ed85d: feat: added HTP client based on axios | ||
| ## 0.3.1 | ||
| ### Patch Changes | ||
| - e243e8b4: fix: globally scoped hooks not executing | ||
| ## 0.3.0 | ||
| ### Minor Changes | ||
| - 554b77e: Releasing packages | ||
| ## 0.2.9 | ||
| ### Patch Changes | ||
| - 06785c2: Typos in docs | ||
| ## 0.2.8 | ||
| ### Patch Changes | ||
| - 42badf4: CLeaned up dependencies | ||
| ## 0.2.7 | ||
| ### Patch Changes | ||
| - adeb833: Updated package.json dependencies, moved some todevDependencies, removed others | ||
| ## 0.2.6 | ||
| ### Patch Changes | ||
| - 6a4a9ac: Swapped project type to "composite", unified build system for most projects | ||
| - Updated dependencies [6a4a9ac] | ||
| - @autometa/types@0.3.1 | ||
| ## 0.2.5 | ||
| ### Patch Changes | ||
| - 61f6294: Fix: build not importing when downloaded through npm | ||
| - 61f6294: Changed 'main' file in overloaded | ||
| - 61f6294: Fixed missing npmignores | ||
| - 61f6294: Replaced 'Chalk' library with 'colors-cli' | ||
| ## 0.2.4 | ||
| ### Patch Changes | ||
| - 83cc218: Fix: build not importing when downloaded through npm | ||
| - 83cc218: Changed 'main' file in overloaded | ||
| - 83cc218: Fixed missing npmignores | ||
| ## 0.2.3 | ||
| ### Patch Changes | ||
| - 6915447: Fix: build not importing when downloaded through npm | ||
| - 6915447: Fixed missing npmignores | ||
| ## 0.2.2 | ||
| ### Patch Changes | ||
| - 0bb7108: Fix: build not importing when downloaded through npm | ||
| ## 0.2.1 | ||
| ### Patch Changes | ||
| - 939bc8f: Fixed issue with importing 'src' directory without a relative path | ||
| ## 0.2.0 | ||
| ### Minor Changes | ||
| - b48f577: Added initial implemention of scopes and updated `overloads` | ||
| - b48f577: Renamed 'params' to def and added template string support | ||
| ### Patch Changes | ||
| - b48f577: fixed def being exported as params | ||
| - Updated dependencies [b48f577] | ||
| - @autometa/gherkin@0.3.0 | ||
| - @autometa/types@0.3.0 | ||
| - @autometa/dto-builder@0.9.1 | ||
| ## 0.1.2 | ||
| ### Patch Changes | ||
| - Updated dependencies [a874510] | ||
| - @autometa/dto-builder@0.9.0 | ||
| - @autometa/gherkin@0.2.5 | ||
| ## 0.1.1 | ||
| ### Patch Changes | ||
| - e7aa10e: Updated readme with more examples, fixed the 'func' argument not being available | ||
| ## 0.1.0 | ||
| ### Minor Changes | ||
| - bc5e12c: Added 'overloaded' package for overloaded or pattern matched functins and methods | ||
| ### Patch Changes | ||
| - Updated dependencies [bc5e12c] | ||
| - @autometa/gherkin@0.2.4 | ||
| ## 0.0.2 | ||
| ### Patch Changes | ||
| - Updated dependencies [cfc35f4] | ||
| - @autometa/dto-builder@0.7.1 | ||
| - @autometa/gherkin@0.2.1 | ||
| - @autometa/types@0.2.1 |
-1338
| var __accessCheck = (obj, member, msg) => { | ||
| if (!member.has(obj)) | ||
| throw TypeError("Cannot " + msg); | ||
| }; | ||
| var __privateGet = (obj, member, getter) => { | ||
| __accessCheck(obj, member, "read from private field"); | ||
| return getter ? getter.call(obj) : member.get(obj); | ||
| }; | ||
| var __privateAdd = (obj, member, value) => { | ||
| if (member.has(obj)) | ||
| throw TypeError("Cannot add the same private member more than once"); | ||
| member instanceof WeakSet ? member.add(obj) : member.set(obj, value); | ||
| }; | ||
| var __privateSet = (obj, member, value, setter) => { | ||
| __accessCheck(obj, member, "write to private field"); | ||
| setter ? setter.call(obj, value) : member.set(obj, value); | ||
| return value; | ||
| }; | ||
| // src/arguments/string-argument.ts | ||
| import gitDiff from "git-diff"; | ||
| import { array, string as zstring, object as object2, number, tuple } from "myzod"; | ||
| // src/arguments/base-argument.ts | ||
| import { object, boolean, unknown } from "myzod"; | ||
| // src/arguments/accumulator.ts | ||
| var Accumulator = class _Accumulator extends Array { | ||
| asString(depth = 0) { | ||
| let str2 = ""; | ||
| for (const value of this) { | ||
| if (typeof value === "string") { | ||
| str2 += " ".repeat(depth) + value + "\n"; | ||
| } | ||
| if (value instanceof _Accumulator) { | ||
| str2 += value.asString(depth + 1) + "\n"; | ||
| } | ||
| } | ||
| return str2; | ||
| } | ||
| }; | ||
| // src/arguments/base-argument.ts | ||
| var BaseArgumentSchema = object({ | ||
| optional: boolean().or( | ||
| object({ | ||
| undefined: boolean().optional(), | ||
| null: boolean().optional() | ||
| }) | ||
| ).optional(), | ||
| test: unknown().optional() | ||
| }); | ||
| var _index; | ||
| var BaseArgument = class { | ||
| constructor() { | ||
| this._accumulator = new Accumulator(); | ||
| this.argCategory = "Arg"; | ||
| __privateAdd(this, _index, void 0); | ||
| } | ||
| get accumulator() { | ||
| return this._accumulator; | ||
| } | ||
| get index() { | ||
| return __privateGet(this, _index); | ||
| } | ||
| get identifier() { | ||
| return this.argName ?? this.index ?? "unnamed arg"; | ||
| } | ||
| withIndex(index) { | ||
| __privateSet(this, _index, index); | ||
| return this; | ||
| } | ||
| baseAssertions(value) { | ||
| this.assertIsDefined(value); | ||
| this.assertTestSucceeds(value); | ||
| } | ||
| assertIsDefined(value, optional = this.options?.optional) { | ||
| if (optional === true) { | ||
| return; | ||
| } | ||
| if (optional && optional.null == true && value === null) { | ||
| return; | ||
| } | ||
| if (optional && optional.undefined == true && value === void 0) { | ||
| return; | ||
| } | ||
| if (value === void 0 || value === null) { | ||
| const message = `Expected ${this.typeName} to be defined but found ${value}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertTestSucceeds(value, test = this.options?.test) { | ||
| if (value === void 0 || value === null) { | ||
| return; | ||
| } | ||
| const realTest = test; | ||
| if (realTest) { | ||
| const result = realTest(value); | ||
| if (result === true) { | ||
| return; | ||
| } | ||
| const message = `Expected ${value} to evaluate to true but was ${result}.`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| shouldAssert(value, optional = this.options?.optional) { | ||
| if (optional === true) { | ||
| return true; | ||
| } | ||
| if (optional && optional.null === true && value == null) { | ||
| return true; | ||
| } | ||
| if (optional && optional.undefined == true && value == void 0) { | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
| fmt(message, padDepth = 0) { | ||
| const pad = " ".repeat(padDepth); | ||
| return `${pad}${this.argCategory}[${this.identifier}]: ${message}`; | ||
| } | ||
| or(second) { | ||
| return or(this, second); | ||
| } | ||
| }; | ||
| _index = new WeakMap(); | ||
| var UnionArgument = class extends BaseArgument { | ||
| constructor(first, second) { | ||
| super(); | ||
| this.first = first; | ||
| this.second = second; | ||
| } | ||
| get typeName() { | ||
| return this.first ? this.first.typeName : this.second.typeName; | ||
| } | ||
| assertUnion(actual) { | ||
| if (!this.first.isTypeMatch(actual) && !this.second.isTypeMatch(actual)) { | ||
| this.accumulator.push( | ||
| `Arg[${this.identifier}]:Expected ${actual} to be one of ${this.first.typeName} or ${this.second.typeName}.` | ||
| ); | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return typeof type2 === this.typeName; | ||
| } | ||
| validate(value) { | ||
| this.assertUnion(value); | ||
| if (this.first) { | ||
| this.first.validate(value); | ||
| } | ||
| if (this.second && !this.first) { | ||
| this.second.validate(value); | ||
| } | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function or(first, second) { | ||
| return new UnionArgument(first, second); | ||
| } | ||
| // src/arguments/string-argument.ts | ||
| var StringValidatorOpsSchema = object2({ | ||
| minLength: number().optional(), | ||
| maxLength: number().optional(), | ||
| includes: zstring().optional(), | ||
| equals: zstring().optional(), | ||
| in: array(zstring()).optional(), | ||
| startsWith: zstring().optional(), | ||
| endsWith: zstring().optional(), | ||
| pattern: object2({ source: zstring() }, { allowUnknown: true }).optional() | ||
| }).and(BaseArgumentSchema); | ||
| var StringArgumentConstructorSchema = tuple([ | ||
| zstring(), | ||
| StringValidatorOpsSchema | ||
| ]).or(tuple([zstring().or(StringValidatorOpsSchema)])).or(tuple([])); | ||
| var StringArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "string"; | ||
| if (!args) { | ||
| return; | ||
| } | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 === this.typeName || typeof type2 === this.typeName; | ||
| } | ||
| assertStringLessThanMax(str2, max = this.options?.maxLength) { | ||
| if (typeof max === "number" && typeof str2 === "string" && str2.length > max) { | ||
| const message = `Expected ${str2} to have less than ${max} characters but found ${str2.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertStringGreaterThanMin(str2, min = this.options?.minLength) { | ||
| if (typeof min === "number" && typeof str2 === "string" && str2.length < min) { | ||
| const message = `Expected ${str2} to have at least ${min} characters but found ${str2.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertStringIncludes(str2, value = this.options?.includes) { | ||
| if (typeof str2 === "string" && typeof value === "string" && !str2.includes(value)) { | ||
| const message = `Expected ${str2} to include ${value} but the substring could not be found`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertStringIn(str2, value = this.options?.in) { | ||
| if (typeof str2 === "string" && Array.isArray(value) && !value.includes(str2)) { | ||
| const message = `Expected ${str2} to be a member of list ${JSON.stringify( | ||
| value | ||
| )} but the substring could not be found`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertStringEquals(str2, value = this.options?.equals) { | ||
| if (typeof str2 === "string" && typeof value === "string" && str2 !== value) { | ||
| const diff = gitDiff(str2, value); | ||
| const message = `Expected ${str2} to equal ${value} but did not. Diff: | ||
| ${diff}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertStringMatches(str2, pattern = this.options?.pattern) { | ||
| if (typeof str2 === "string" && pattern instanceof RegExp && !pattern.test(str2)) { | ||
| const message = `Expected ${pattern} to match pattern ${pattern.source} but it did not`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertString(str2) { | ||
| if (typeof str2 !== "string" && !this.options?.optional) { | ||
| const message = `Expected argument to be of type 'string' but was: [${typeof str2}] ${str2}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertinArray(str2, array9 = this.options?.in) { | ||
| if (typeof str2 === "string" && Array.isArray(array9) && !array9.includes(str2)) { | ||
| const message = `Expected ${array9} to include ${str2} but it was not`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertString(value); | ||
| this.assertStringEquals(value); | ||
| this.assertStringLessThanMax(value); | ||
| this.assertStringGreaterThanMin(value); | ||
| this.assertinArray(value); | ||
| this.assertStringIncludes(value); | ||
| this.assertStringMatches(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function string(...args) { | ||
| StringArgumentConstructorSchema.parse(args); | ||
| return new StringArgument(args); | ||
| } | ||
| // src/arguments/number-argument.ts | ||
| import { string as string2, object as object3, number as num, literal, array as array2 } from "myzod"; | ||
| var NumberValidationSchema = object3({ | ||
| max: num().optional(), | ||
| min: num().optional(), | ||
| equals: num().optional(), | ||
| type: literal("int").or(literal("float")).optional(), | ||
| in: array2(num()).optional() | ||
| }).and(BaseArgumentSchema); | ||
| var NumberArgumentParamsSchema = array2(string2().or(NumberValidationSchema)); | ||
| var NumberArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "number"; | ||
| if (!args) { | ||
| return; | ||
| } | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return typeof type2 === this.typeName; | ||
| } | ||
| assertNumber(num4) { | ||
| if (typeof num4 !== "number") { | ||
| const message = `Expected value to be a number but was [${typeof num4}]: ${num4}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertNumberEquals(num4, equals = this.options?.equals) { | ||
| if (typeof num4 !== "number" && typeof num4 !== "bigint") { | ||
| return; | ||
| } | ||
| if (equals !== void 0 && num4 !== equals) { | ||
| const message = `Expected ${num4} to equal ${equals} but did not.`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertNumberLessThanMax(num4, max = this.options?.max) { | ||
| if (num4 === void 0) { | ||
| return; | ||
| } | ||
| if (typeof num4 !== "number" && typeof num4 !== "bigint") { | ||
| return; | ||
| } | ||
| if (max !== void 0 && num4 > max) { | ||
| const message = `Expected number ${num4} to be less than max value ${max}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertNumberGreaterThanMin(num4, min = this.options?.min) { | ||
| if (num4 === void 0) { | ||
| return; | ||
| } | ||
| if (typeof num4 !== "number" && typeof num4 !== "bigint") { | ||
| return; | ||
| } | ||
| if (min !== void 0 && num4 < min) { | ||
| const message = `Expected number to be greater than minimum value ${min}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertInArray(val, value) { | ||
| if (num === void 0) { | ||
| return; | ||
| } | ||
| if (typeof num !== "number" && typeof num !== "bigint") { | ||
| return; | ||
| } | ||
| if (value && Array.isArray(value) && !value.includes(val)) { | ||
| const message = `Expected ${value} to include ${val} but it was not`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| assertType(value, type2 = this.options?.type) { | ||
| if (num === void 0) { | ||
| return; | ||
| } | ||
| if (typeof value !== "number") { | ||
| return; | ||
| } | ||
| if (type2 === "float" && Number.isInteger(value)) { | ||
| const message = `Expected number '${value}' to be a float but was an integer`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| if (type2 === "int" && !Number.isInteger(value)) { | ||
| const message = `Expected number '${value}' to be an integer but was a float`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertNumber(value); | ||
| this.assertNumberEquals(value); | ||
| this.assertInArray(value); | ||
| this.assertNumberGreaterThanMin(value); | ||
| this.assertNumberLessThanMax(value); | ||
| this.assertType(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function number2(...args) { | ||
| NumberArgumentParamsSchema.parse(args); | ||
| return new NumberArgument(args); | ||
| } | ||
| // src/arguments/boolean-argument.ts | ||
| import { object as object4, string as string3, boolean as bool, array as array3 } from "myzod"; | ||
| var BooleaValidationSchema = object4({ | ||
| equals: bool().optional() | ||
| // "not" equals property | ||
| }).and(BaseArgumentSchema); | ||
| var BooleanArgumentConstructorSchema = array3( | ||
| string3().or(BooleaValidationSchema) | ||
| ); | ||
| var BooleanArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "boolean"; | ||
| if (!args) { | ||
| return; | ||
| } | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| } | ||
| assertBoolean(actual) { | ||
| if (actual === void 0) { | ||
| return; | ||
| } | ||
| if (actual !== void 0 && typeof actual !== "boolean") { | ||
| this.accumulator.push( | ||
| `Arg[${this.identifier}]: Expected boolean but found [type: ${typeof actual}]${actual}` | ||
| ); | ||
| } | ||
| } | ||
| assertEquals(actual) { | ||
| if (actual === void 0) { | ||
| return; | ||
| } | ||
| const equals = this.options?.equals; | ||
| if (actual !== void 0 && equals !== void 0 && actual !== equals) { | ||
| this.accumulator.push( | ||
| `Arg[${this.identifier}]:Expected ${actual} to equal ${boolean2} but did not.` | ||
| ); | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return typeof type2 === this.typeName; | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertBoolean(value); | ||
| this.assertEquals(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function boolean2(...args) { | ||
| BooleanArgumentConstructorSchema.parse(args); | ||
| return new BooleanArgument(args); | ||
| } | ||
| // src/arguments/array-argument.ts | ||
| import { | ||
| object as object5, | ||
| number as num2, | ||
| array as arr, | ||
| unknown as unknown2, | ||
| string as string4 | ||
| } from "myzod"; | ||
| var ArrayValidationSchema = object5({ | ||
| maxLength: num2().optional(), | ||
| minLength: num2().optional(), | ||
| length: num2().optional(), | ||
| includes: unknown2().optional() | ||
| }).and(BaseArgumentSchema); | ||
| var ArrayArgumentParamSchema = arr( | ||
| string4().or(arr(unknown2())).or(ArrayValidationSchema) | ||
| ); | ||
| var ArrayArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "Array"; | ||
| this.types = []; | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object" && Array.isArray(args[0])) { | ||
| this.reference = args[0]; | ||
| } | ||
| if (typeof args[1] === "object" && Array.isArray(args[1])) { | ||
| this.reference = args[1]; | ||
| } | ||
| if (typeof args[1] === "object" && !Array.isArray(args[1])) { | ||
| this.options = args[1]; | ||
| } | ||
| if (typeof args[2] === "object" && !Array.isArray(args[2])) { | ||
| this.options = args[2]; | ||
| } | ||
| for (const value of this.reference) { | ||
| if (!this.types.includes(value.typeName)) { | ||
| this.types.push(value.typeName); | ||
| } | ||
| } | ||
| } | ||
| assertIsArray(values) { | ||
| if (!Array.isArray(values)) { | ||
| const message = `Expected value to be an array but found ${typeof values}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return Array.isArray(type2); | ||
| } | ||
| assertLengthLessThanMax(values, length2 = this.options?.maxLength) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (Array.isArray(values)) { | ||
| if (length2 && values?.length > length2) { | ||
| const message = `Expected value to be an array with max length ${length2} but was ${values?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| } | ||
| assertLengthGreaterThanMin(values, length2 = this.options?.minLength) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (Array.isArray(values)) { | ||
| if (length2 && values?.length < length2) { | ||
| const message = `Expected value to be an array with min length ${length2} but was ${values?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| } | ||
| assertLengthEquals(values, length2 = this.options?.length) { | ||
| if (length2 && Array.isArray(values)) { | ||
| if (length2 !== values?.length) { | ||
| const message = `Expected array to have length ${length2} but was ${values?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| } | ||
| assertIncludes(values, item = this.options?.includes) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (item && Array.isArray(values)) { | ||
| if (!values.includes(item)) { | ||
| const message = `Expected array to have length ${length} but was ${values?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| } | ||
| assertPermittedType(values) { | ||
| if (!Array.isArray(values)) { | ||
| return; | ||
| } | ||
| for (const value of values) { | ||
| if (!this.types.includes(typeof value)) { | ||
| const index = values.indexOf(value); | ||
| const message = `Expected array to contain only known types ${this.types} but index [${index}] contains ${typeof value}: '${JSON.stringify( | ||
| value | ||
| )}'; ${JSON.stringify(values)}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| } | ||
| assertChildValidations(values) { | ||
| if (!Array.isArray(values)) { | ||
| return; | ||
| } | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| for (const value of values) { | ||
| const matching = this.reference.find((it) => it.isTypeMatch(value)); | ||
| if (!matching) { | ||
| const message = `Expected array value to be one of ${this.types} but found ${typeof value}:`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| this.accumulator.push(...this.reference.map((it) => it.accumulator)); | ||
| } | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertIsArray(value); | ||
| this.assertLengthEquals(value); | ||
| this.assertLengthGreaterThanMin(value); | ||
| this.assertLengthLessThanMax(value); | ||
| this.assertPermittedType(value); | ||
| this.assertIncludes(value); | ||
| this.assertChildValidations(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function array4(...args) { | ||
| ArrayArgumentParamSchema.parse(args); | ||
| return new ArrayArgument(args); | ||
| } | ||
| // src/arguments/tuple-argument.ts | ||
| import { object as object6, array as array5, string as string5, unknown as unknown3 } from "myzod"; | ||
| var TupleValidationSchema = object6({ | ||
| includes: unknown3().optional() | ||
| }).and(BaseArgumentSchema); | ||
| var TupleArgumentParamSchema = array5( | ||
| string5().or(array5(unknown3())).or(TupleValidationSchema) | ||
| ); | ||
| var TupleArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "object"; | ||
| this.types = []; | ||
| if (!args) { | ||
| throw new Error( | ||
| `A TupleArgument requires a reference array of BaseArguments to construct. Provided args: ${args}` | ||
| ); | ||
| } | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (Array.isArray(args[0])) { | ||
| this.reference = args[0]; | ||
| } | ||
| if (Array.isArray(args[1])) { | ||
| this.reference = args[1]; | ||
| } | ||
| if (!this.reference) { | ||
| throw new Error( | ||
| `A TupleArgument requires a reference array of BaseArguments to construct. Provided args: ${args}` | ||
| ); | ||
| } | ||
| this.reference.forEach((it, idx) => { | ||
| this.types.push(it.typeName); | ||
| it.withIndex(idx).argCategory = "Element"; | ||
| }); | ||
| } | ||
| isTypeMatch(type2) { | ||
| return Array.isArray(type2); | ||
| } | ||
| assertIsTuple(values) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (!Array.isArray(values)) { | ||
| const message = `Expected value to be an array but found ${typeof values}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertIncludes(values, item = this.options?.includes) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (item && Array.isArray(values)) { | ||
| if (!values.includes(item)) { | ||
| const message = `Expected array to have length ${length} but was ${values?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| } | ||
| assertLength(values, length2 = this.types.length) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (length2 && values?.length <= length2) { | ||
| this.accumulator.push( | ||
| `Expected value to be an array with max length ${length2} but was ${values?.length}` | ||
| ); | ||
| } | ||
| } | ||
| assertPermittedType(values) { | ||
| if (values === void 0) { | ||
| return; | ||
| } | ||
| if (!Array.isArray(values)) { | ||
| return; | ||
| } | ||
| const errors = []; | ||
| for (let i = 0; i < this.types.length; i++) { | ||
| const reference = this.reference[i]; | ||
| const actual = values[i]; | ||
| if (!reference.validate(actual)) { | ||
| errors.push(reference); | ||
| } | ||
| } | ||
| if (errors.length > 0) { | ||
| const message = `Expected all tuple values to be valid but found:`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| errors.forEach((it) => this.accumulator.push(it.accumulator)); | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertIsTuple(value); | ||
| this.assertPermittedType(value); | ||
| this.assertIncludes(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function tuple2(...args) { | ||
| TupleArgumentParamSchema.parse(args); | ||
| return new TupleArgument(args); | ||
| } | ||
| // src/arguments/shape-argument.ts | ||
| import { string as string6, object as object7, boolean as boolean3, array as array6 } from "myzod"; | ||
| var ShapeValidationSchema = object7({ | ||
| exhaustive: boolean3().optional(), | ||
| instance: object7({}, { allowUnknown: true }).optional() | ||
| }).and(BaseArgumentSchema); | ||
| var ShapeArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "object"; | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args.shift(); | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.reference = args.shift(); | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (!this.reference) { | ||
| throw new Error(`Shape Argument must be provided a reference object`); | ||
| } | ||
| for (const key in this.reference) { | ||
| const name = this.reference[key].argName; | ||
| if (!name) { | ||
| this.reference[key].argName = key; | ||
| this.reference[key].argCategory = "Property"; | ||
| } | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 === this.typeName || typeof type2 === this.typeName; | ||
| } | ||
| assertObject(value) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (typeof value !== "object") { | ||
| const message = `Expected value to be an ${this.typeName} but was [type: ${typeof value}]: '${value}'`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertExhaustive(value) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (this.options?.exhaustive === void 0 || this.options?.exhaustive === false) { | ||
| return; | ||
| } | ||
| const asObj = value; | ||
| const refKeys = Object.keys(this.reference); | ||
| const valKeys = Object.keys(asObj); | ||
| if (refKeys.length != valKeys.length) { | ||
| for (const property of valKeys) { | ||
| if (!(property in this.reference)) { | ||
| const message = `Argument value contains property '${property}' which is not known for object with keys [${refKeys.map((it) => `'${it}'`).join()}]`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| assertShapeMatches(value) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| const refShape = this.reference; | ||
| const asObj = value; | ||
| for (const key in refShape) { | ||
| const reference = refShape[key]; | ||
| const actual = value && asObj[key]; | ||
| if (!reference.validate(actual)) { | ||
| const message = `Expected all properties to be valid but found:`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| if (reference.accumulator.length > 0) { | ||
| this.accumulator.push(reference.accumulator); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| assertIsInstance(value, instance2 = this.options?.instance) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (instance2 && !(value instanceof instance2)) { | ||
| const message = `Expected shape to be an instance of ${instance2} but was not`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertObject(value); | ||
| this.assertExhaustive(value); | ||
| this.assertShapeMatches(value); | ||
| this.assertIsInstance(value); | ||
| return this._accumulator.length === 0; | ||
| } | ||
| }; | ||
| var ShapeArgumentParamsSchema = array6( | ||
| string6().or(object7({}).allowUnknownKeys()).or(ShapeValidationSchema).optional() | ||
| ); | ||
| function shape(...args) { | ||
| ShapeArgumentParamsSchema.parse(args); | ||
| return new ShapeArgument(args); | ||
| } | ||
| // src/arguments/date-argument.ts | ||
| import { date as dt, object as object8, string as string7, array as array7 } from "myzod"; | ||
| var DateValidationOptsSchema = object8({ | ||
| before: dt().optional(), | ||
| after: dt().optional(), | ||
| equals: dt().optional() | ||
| }).and(BaseArgumentSchema); | ||
| var DateConstructorArgumentSchema = array7( | ||
| string7().or(DateValidationOptsSchema.optional()) | ||
| ); | ||
| var DateArgument = class _DateArgument extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "Date"; | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 instanceof _DateArgument; | ||
| } | ||
| assertBefore(value, before = this.options?.before) { | ||
| if (!before || !(value instanceof Date)) { | ||
| return; | ||
| } | ||
| if (value >= before) { | ||
| const message = `Expected date '${value}' to be earlier than '${before}'`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertAfter(value, after = this.options?.after) { | ||
| if (!after || !(value instanceof Date)) { | ||
| return; | ||
| } | ||
| if (value <= after) { | ||
| const message = `Expected date '${value}' to be later than '${after}'`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertEquals(value, equals = this.options?.equals) { | ||
| if (!equals || !(value instanceof Date)) { | ||
| return; | ||
| } | ||
| if (value !== equals) { | ||
| const message = `Expected date '${value}' to be equal to '${equals}'`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertBefore(value); | ||
| this.assertAfter(value); | ||
| this.assertEquals(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function date(...args) { | ||
| return new DateArgument(args); | ||
| } | ||
| // src/arguments/unknown-argument.ts | ||
| import { array as array8, string as string8 } from "myzod"; | ||
| var UnknownArgumentParamsSchema = array8( | ||
| string8().or(BaseArgumentSchema).optional() | ||
| ).max(2); | ||
| var UnknownArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "unknown"; | ||
| this.options = { optional: true }; | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| } | ||
| isTypeMatch(_type) { | ||
| throw true; | ||
| } | ||
| validate(_value) { | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function unknown4(...args) { | ||
| UnknownArgumentParamsSchema.parse(args); | ||
| return new UnknownArgument(args); | ||
| } | ||
| // src/arguments/instance-argument.ts | ||
| import { object as object9 } from "myzod"; | ||
| var InstanceConstructorArgumentSchema = object9({}); | ||
| var InstanceOptionsArgumentSchema = object9({}).and(BaseArgumentSchema); | ||
| var InstanceArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "object"; | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args.shift(); | ||
| } | ||
| if (typeof args[0] === "function") { | ||
| this.blueprint = args.shift(); | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.shape = args.shift(); | ||
| } | ||
| if (typeof args[0] === "undefined") { | ||
| args.shift(); | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args.shift(); | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 instanceof this.blueprint; | ||
| } | ||
| assertIsInstance(value) { | ||
| if (value !== void 0 && this.blueprint && !(value instanceof this.blueprint)) { | ||
| const message = `Expected value of ${value} to be an instance of ${this.blueprint.name} but it was not.`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertShapeArguments(value) { | ||
| if (!this.shape) { | ||
| return; | ||
| } | ||
| if (!value || !this.blueprint || !(value instanceof this.blueprint)) { | ||
| return; | ||
| } | ||
| this.shape.validate(value); | ||
| if (this.shape.accumulator.length > 0) { | ||
| this.accumulator.push(this.shape.accumulator); | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertIsInstance(value); | ||
| this.assertShapeArguments(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function instance(...args) { | ||
| return new InstanceArgument(args); | ||
| } | ||
| // src/arguments/function-argument.ts | ||
| import { object as object10, number as num3, string as str } from "myzod"; | ||
| var FunctionValidationSchema = object10({ | ||
| maxArgLength: num3().optional(), | ||
| minArgLength: num3().optional(), | ||
| argLength: num3().optional(), | ||
| name: str().optional() | ||
| }).and(BaseArgumentSchema); | ||
| var FunctionArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "function"; | ||
| this.types = []; | ||
| if (typeof args[0] === "string") { | ||
| this.name = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 === this.typeName || typeof type2 === this.typeName; | ||
| } | ||
| assertIsFunction(value) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (typeof value !== "function") { | ||
| const message = `Expected function arguments to be a function but found ${typeof value}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertLengthLessThanMax(value, length2 = this.options?.maxArgLength) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (typeof value !== "function") { | ||
| return; | ||
| } | ||
| if (length2 && value?.length <= length2) { | ||
| const message = `Expected function arguments to be an array with max length ${length2} but was ${value?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertLengthGreaterThanMin(value, length2 = this.options?.maxArgLength) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (typeof value !== "function") { | ||
| return; | ||
| } | ||
| if (length2 && value?.length >= length2) { | ||
| const message = `Expected function arguments to be an array with min length ${length2} but was ${value?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertLengthEquals(value, length2 = this.options?.argLength) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (typeof value !== "function") { | ||
| return; | ||
| } | ||
| if (length2 !== void 0 && length2 !== value?.length) { | ||
| const message = `Expected function arguments to have length ${length2} but was ${value?.length}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| assertName(value, name = this.options?.name) { | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (value === void 0) { | ||
| return; | ||
| } | ||
| if (typeof value !== "function") { | ||
| return; | ||
| } | ||
| if (name && value.name === name) { | ||
| const message = `Expected function to have name ${name} but was ${value?.name}`; | ||
| this.accumulator.push(this.fmt(message)); | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.baseAssertions(value); | ||
| this.assertIsFunction(value); | ||
| this.assertLengthEquals(value); | ||
| this.assertLengthGreaterThanMin(value); | ||
| this.assertLengthLessThanMax(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function func(...args) { | ||
| return new FunctionArgument(args); | ||
| } | ||
| // src/arguments/nil-argument.ts | ||
| import z, { string as zstring2, object as object11, tuple as tuple3 } from "myzod"; | ||
| var NilValidatorOpsSchema = object11({ | ||
| equals: z.literal("null").or(z.literal("undefined")).optional() | ||
| }).and(BaseArgumentSchema); | ||
| var NilArgumentConstructorSchema = tuple3([zstring2(), NilValidatorOpsSchema]).or(tuple3([zstring2().or(NilValidatorOpsSchema)])).or(tuple3([])); | ||
| var NilArgument = class extends BaseArgument { | ||
| constructor(args) { | ||
| super(); | ||
| this.typeName = "undefined"; | ||
| if (!args) { | ||
| return; | ||
| } | ||
| if (typeof args[0] === "string") { | ||
| this.argName = args[0]; | ||
| } | ||
| if (typeof args[0] === "object") { | ||
| this.options = args[0]; | ||
| } | ||
| if (typeof args[1] === "object") { | ||
| this.options = args[1]; | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 === null || type2 === void 0; | ||
| } | ||
| assertIsNullOrUndefined(value) { | ||
| if (value == null && value !== void 0) { | ||
| const msg = `Expected ${this.typeName} to be null or undefined but found ${value}`; | ||
| this.accumulator.push(this.fmt(msg)); | ||
| } | ||
| } | ||
| assertIsNull(value) { | ||
| if ((this.options?.equals === "undefined" || !this.options?.equals) && value === void 0) { | ||
| return; | ||
| } | ||
| if (value !== null) { | ||
| const msg = `Expected ${this.typeName} to be null but found ${value}`; | ||
| this.accumulator.push(this.fmt(msg)); | ||
| } | ||
| } | ||
| assertIsUndefined(value) { | ||
| if (this.options?.equals === "null" && value === null) { | ||
| return; | ||
| } | ||
| if (value !== void 0) { | ||
| const msg = `Expected ${this.typeName} to be undefined but found ${value}`; | ||
| this.accumulator.push(this.fmt(msg)); | ||
| } | ||
| } | ||
| validate(value) { | ||
| this.assertIsUndefined(value); | ||
| this.assertIsNull(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function nil(...args) { | ||
| NilArgumentConstructorSchema.parse(args); | ||
| return new NilArgument(args); | ||
| } | ||
| // src/arguments/type-argument.ts | ||
| var TypeArgument = class extends BaseArgument { | ||
| constructor(strOrT, type2) { | ||
| super(); | ||
| this.typeName = "function"; | ||
| this.types = []; | ||
| if (strOrT === "string") { | ||
| this.name = strOrT; | ||
| this.type = type2; | ||
| } | ||
| if (typeof strOrT === "function") { | ||
| this.type = strOrT; | ||
| } | ||
| if (typeof type2 === "function") { | ||
| this.type = type2; | ||
| } | ||
| } | ||
| isTypeMatch(type2) { | ||
| return type2 === this.typeName || typeof type2 === this.typeName; | ||
| } | ||
| assertType(value, match = this.type) { | ||
| if (value === match) { | ||
| return; | ||
| } | ||
| this.accumulator.push( | ||
| this.fmt( | ||
| `Expected value of ${value} to be of type ${match.name} but it was not.` | ||
| ) | ||
| ); | ||
| } | ||
| validate(value) { | ||
| this.assertIsDefined(value); | ||
| this.baseAssertions(value); | ||
| this.assertType(value); | ||
| return this.accumulator.length === 0; | ||
| } | ||
| }; | ||
| function type(nameOrType, type2) { | ||
| return new TypeArgument(nameOrType, type2); | ||
| } | ||
| // src/overloads.ts | ||
| var Overloads = class { | ||
| constructor(overloads2) { | ||
| this.overloads = overloads2; | ||
| } | ||
| match(args) { | ||
| for (const overload of this.overloads) { | ||
| const match = overload.isMatch(args); | ||
| if (match && overload.actionOrError instanceof Function) { | ||
| return overload.actionOrError(...args); | ||
| } | ||
| if (match && overload.actionOrError instanceof Error) { | ||
| throw overload.actionOrError; | ||
| } | ||
| } | ||
| const fallback2 = this.overloads.find((it) => it.fallback === true); | ||
| if (fallback2 && fallback2.actionOrError instanceof Function) { | ||
| return fallback2.actionOrError(...args); | ||
| } | ||
| const reports = this.overloads.map((it, idx) => it.getReport(idx, args)).join("\n\n"); | ||
| throw new Error(`No overloaded function implementation was found for | ||
| function(${args.join(", ")}){} | ||
| ${reports}`); | ||
| } | ||
| }; | ||
| function overloads(...args) { | ||
| const overloads2 = new Overloads(args); | ||
| return { | ||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
| use: (actualArgs) => overloads2.match(actualArgs) | ||
| }; | ||
| } | ||
| // src/dispose-description.ts | ||
| function disposeDescription(args) { | ||
| if (typeof args[0] === "string") { | ||
| return args.shift(); | ||
| } | ||
| return ""; | ||
| } | ||
| function disposeTaggedTemplate(args) { | ||
| if (Array.isArray(args[0])) { | ||
| return [args[0][0], true]; | ||
| } | ||
| return ["", false]; | ||
| } | ||
| // src/formatting.ts | ||
| import cli from "colors-cli"; | ||
| function colorCompareArgStrings(expected, actual) { | ||
| const maxLength = Math.max(expected.length, actual.length); | ||
| const firstAccumulator = []; | ||
| const secondAccumulator = []; | ||
| for (let i = 0; i < maxLength; i++) { | ||
| const firstArg = expected[i]; | ||
| const secondArg = actual[i]; | ||
| if (firstArg !== secondArg) { | ||
| firstAccumulator.push(cli.yellow(firstArg)); | ||
| secondAccumulator.push(cli.red(secondArg)); | ||
| } else { | ||
| firstAccumulator.push(cli.green(firstArg)); | ||
| secondAccumulator.push(cli.green(secondArg)); | ||
| } | ||
| } | ||
| return [firstAccumulator, secondAccumulator]; | ||
| } | ||
| function argStringArray(args) { | ||
| return args.map((arg) => { | ||
| const type2 = typeof arg; | ||
| const asRecord = arg; | ||
| if (typeof asRecord === "object" && "constructor" in asRecord) { | ||
| return asRecord.constructor.name; | ||
| } | ||
| return type2; | ||
| }); | ||
| } | ||
| // src/overload.ts | ||
| var Overload = class { | ||
| constructor(name, description, args, actionOrError, fallback2 = false) { | ||
| this.name = name; | ||
| this.description = description; | ||
| this.args = args; | ||
| this.actionOrError = actionOrError; | ||
| this.fallback = fallback2; | ||
| args.forEach((arg, idx) => arg.withIndex(idx)); | ||
| } | ||
| isMatch(args) { | ||
| if (args === void 0 || args === null) { | ||
| args = []; | ||
| } | ||
| for (let i = 0; i < this.args.length; i++) { | ||
| const argWrapper = this.args[i]; | ||
| const arg = args[i]; | ||
| if (!argWrapper.validate(arg)) { | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| typeStringArray() { | ||
| return this.args.map((it) => it.typeName); | ||
| } | ||
| getReport(index, realArgs) { | ||
| const expectedTypeStrings = this.typeStringArray(); | ||
| const actualTypeStrings = argStringArray(realArgs); | ||
| const compare = colorCompareArgStrings( | ||
| expectedTypeStrings, | ||
| actualTypeStrings | ||
| ); | ||
| return `Overload[${index}] did not match because: | ||
| Expected: ${compare[0].join(", ")} | ||
| Actual : ${compare[1].join(", ")} | ||
| ${this.args.filter((it) => it.accumulator.length > 0).map((it) => it.accumulator.join("\n\n "))}`; | ||
| } | ||
| }; | ||
| // src/def.ts | ||
| function def(...args) { | ||
| const [name, isNamed] = disposeTaggedTemplate(args); | ||
| if (isNamed) { | ||
| return (...args2) => { | ||
| const description2 = disposeDescription(args2); | ||
| return { | ||
| /** | ||
| * Implementation for a specific overload. When the arguments passed match this functions | ||
| * parent overload, the arguments will be passed to this functions parameters. | ||
| * | ||
| * The return value will be used in a union in the final return value of the overloading function/method | ||
| * @param implementation | ||
| * @returns | ||
| */ | ||
| matches: (implementation) => { | ||
| return new Overload(name, description2, args2, implementation); | ||
| } | ||
| }; | ||
| }; | ||
| } | ||
| const description = disposeDescription(args); | ||
| return { | ||
| /** | ||
| * Implementation for a specific overload. When the arguments passed match this functions | ||
| * parent overload, the arguments will be passed to this functions parameters. | ||
| * | ||
| * The return value will be used in a union in the final return value of the overloading function/method | ||
| * @param implementation | ||
| * @returns | ||
| */ | ||
| matches: (implementation) => { | ||
| return new Overload(name, description, args, implementation); | ||
| }, | ||
| throws: (message, errorType) => { | ||
| return new Overload(name, description, args, errorType ?? Error); | ||
| } | ||
| }; | ||
| } | ||
| // src/fallback.ts | ||
| function fallback(...args) { | ||
| const description = disposeDescription(args); | ||
| const [implementation] = args; | ||
| return new Overload( | ||
| "fallback", | ||
| description, | ||
| [], | ||
| implementation, | ||
| true | ||
| ); | ||
| } | ||
| export { | ||
| BaseArgument, | ||
| TypeArgument, | ||
| UnionArgument, | ||
| array4 as array, | ||
| boolean2 as boolean, | ||
| date, | ||
| def, | ||
| fallback, | ||
| func, | ||
| instance, | ||
| nil, | ||
| number2 as number, | ||
| or, | ||
| overloads, | ||
| shape, | ||
| string, | ||
| tuple2 as tuple, | ||
| type, | ||
| unknown4 as unknown | ||
| }; | ||
| //# sourceMappingURL=index.js.map |
Sorry, the diff of this file is too big to display
-517
| import * as myzod from 'myzod'; | ||
| import { Infer } from 'myzod'; | ||
| import * as myzod_libs_types from 'myzod/libs/types'; | ||
| declare class Accumulator<T> extends Array<T | Accumulator<T>> { | ||
| asString(depth?: number): string; | ||
| } | ||
| declare const ShapeValidationSchema: myzod.ObjectType<{ | ||
| exhaustive: myzod.OptionalType<myzod.BooleanType>; | ||
| instance: myzod.OptionalType<myzod.ObjectType<{}>>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type ShapeOptions = Infer<typeof ShapeValidationSchema>; | ||
| type ShapeValidatorOpts = Infer<typeof ShapeValidationSchema>; | ||
| declare class ShapeArgument<T extends ShapeType, TRaw extends FromShape<T>> extends BaseArgument<TRaw> { | ||
| typeName: string; | ||
| options?: ShapeOptions; | ||
| reference: T; | ||
| constructor(args: (string | T | ShapeOptions)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertObject(value: unknown): void; | ||
| assertExhaustive(value: unknown): void; | ||
| assertShapeMatches(value: unknown | undefined | null): void; | ||
| assertIsInstance(value: unknown, instance?: any): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function shape<T extends ShapeType>(reference: T): ShapeArgument<T, FromShape<T>>; | ||
| declare function shape<T extends ShapeType>(name: string, reference: T): ShapeArgument<T, FromShape<T>>; | ||
| declare function shape<T extends ShapeType>(name: string, reference: T, options?: ShapeOptions): ShapeArgument<T, FromShape<T>>; | ||
| declare function shape<T extends ShapeType>(reference: T, options?: ShapeOptions): ShapeArgument<T, FromShape<T>>; | ||
| type OverloadAction = (...args: any[]) => any; | ||
| declare class Overload<TArgs extends AnyArg[], TAction extends OverloadAction> { | ||
| readonly name: string | undefined; | ||
| readonly description: string | undefined; | ||
| readonly args: TArgs; | ||
| readonly actionOrError: TAction | Error; | ||
| readonly fallback: boolean; | ||
| constructor(name: string | undefined, description: string | undefined, args: TArgs, actionOrError: TAction | Error, fallback?: boolean); | ||
| isMatch(args: ArgumentType[]): boolean; | ||
| typeStringArray(): string[]; | ||
| getReport(index: number, realArgs: unknown[]): string; | ||
| } | ||
| type AnyArg = BaseArgument<ArgumentType>; | ||
| type ValidatorArgumentTuple<T> = { | ||
| [K in keyof T]: T[K] extends AnyArg ? T[K] extends ShapeArgument<infer _, infer TShape> ? TShape : T[K] extends BaseArgument<infer Q> ? Q : never : never; | ||
| }; | ||
| type ArgumentTypes<T> = { | ||
| [K in keyof T]: T[K] extends AnyArg ? T[K] extends infer U ? U : never : never; | ||
| }; | ||
| type ReturnTypeTuple<T> = { | ||
| [K in keyof T]: T[K] extends Overload<infer _TArgs, infer TAction> ? ReturnType<TAction> extends [infer THead, ...infer TTail] ? [THead, ...TTail] : ReturnType<TAction> : never; | ||
| }; | ||
| type ReturnTypes<T> = T extends Overload<AnyArg[], OverloadAction>[] ? ReturnTypeTuple<T> extends infer K ? K extends unknown[] ? K[number] : never : never : never; | ||
| type AnyType = any; | ||
| type Primitive = string | number | boolean | undefined | null; | ||
| type Ephemeral = unknown; | ||
| type Shape = { | ||
| [key: string]: ArgumentType; | ||
| }; | ||
| type Array$1 = { | ||
| [key: number]: ArgumentType; | ||
| }; | ||
| type Tuple = [ArgumentType, ...ArgumentType[]]; | ||
| type ArgumentType = Shape | Array$1 | Tuple | Primitive | Ephemeral; | ||
| type CamelCase<T extends string> = T extends `${infer _TPrefix} ${infer _TSuffix}` ? { | ||
| error: `argument names should not contain spaces. Please update '${T}'`; | ||
| } : T; | ||
| type FromTuple<T extends BaseArgument<ArgumentType>[]> = { | ||
| [key in keyof T]: T[key] extends BaseArgument<infer K> ? K : never; | ||
| }; | ||
| type TupleType = [AnyArg, ...AnyArg[]]; | ||
| type ShapeType = { | ||
| [key: string]: AnyArg; | ||
| }; | ||
| type InstanceType<T extends Record<string, unknown>> = { | ||
| [K in keyof T]: T[K]; | ||
| }; | ||
| type FromShape<T> = T extends ShapeType ? { | ||
| [K in keyof T]: T[K] extends BaseArgument<infer TArg> ? TArg : T[K] extends ShapeArgument<infer _, infer TShape> ? TShape : never; | ||
| } : never; | ||
| type InferArg<T> = { | ||
| [K in keyof T]: T[K] extends BaseArgument<infer TArg> ? TArg : T[K] extends ShapeArgument<infer _, infer TShape> ? TShape : never; | ||
| }; | ||
| type FromFunction<T extends BaseArgument<ArgumentType>[]> = { | ||
| [key in keyof T]: T[key] extends BaseArgument<infer K> ? K : never; | ||
| }; | ||
| type FunctionType = (...args: AnyType[]) => AnyType | void | Promise<AnyType | void>; | ||
| type Class<T> = { | ||
| new (...args: any): T; | ||
| }; | ||
| type AbstractClass<T> = Function & { | ||
| prototype: T; | ||
| }; | ||
| declare const BaseArgumentSchema: myzod.ObjectType<{ | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type ArgumentOptions = Infer<typeof BaseArgumentSchema>; | ||
| declare abstract class BaseArgument<TType> { | ||
| #private; | ||
| example?: TType; | ||
| abstract typeName: string; | ||
| protected _accumulator: Accumulator<string>; | ||
| readonly options?: ArgumentOptions; | ||
| argName?: string; | ||
| argCategory: string; | ||
| get accumulator(): Accumulator<string>; | ||
| get index(): number; | ||
| get identifier(): string | number; | ||
| withIndex(index: number): this; | ||
| abstract isTypeMatch(type: unknown): boolean; | ||
| baseAssertions(value?: unknown): asserts value; | ||
| assertIsDefined(value: unknown, optional?: boolean | { | ||
| undefined?: boolean | undefined; | ||
| null?: boolean | undefined; | ||
| } | undefined): void; | ||
| assertTestSucceeds(value: unknown, test?: unknown): void; | ||
| protected shouldAssert(value: unknown, optional?: boolean | { | ||
| undefined?: boolean | undefined; | ||
| null?: boolean | undefined; | ||
| } | undefined): boolean; | ||
| abstract validate(value: unknown, parent?: BaseArgument<ArgumentType>): boolean; | ||
| protected fmt(message: string, padDepth?: number): string; | ||
| or<K>(second: BaseArgument<K>): BaseArgument<TType | K>; | ||
| } | ||
| declare class UnionArgument<T, K> extends BaseArgument<T | K> { | ||
| readonly first: BaseArgument<T>; | ||
| readonly second: BaseArgument<K>; | ||
| get typeName(): string; | ||
| constructor(first: BaseArgument<T>, second: BaseArgument<K>); | ||
| assertUnion(actual: T | K): void; | ||
| isTypeMatch(type: unknown): boolean; | ||
| validate(value: T | K): boolean; | ||
| } | ||
| declare function or<T, K>(first: BaseArgument<T>, second: BaseArgument<K>): BaseArgument<T | K>; | ||
| declare const StringValidatorOpsSchema: myzod.ObjectType<{ | ||
| minLength: myzod.OptionalType<myzod.NumberType>; | ||
| maxLength: myzod.OptionalType<myzod.NumberType>; | ||
| includes: myzod.OptionalType<myzod.StringType>; | ||
| equals: myzod.OptionalType<myzod.StringType>; | ||
| in: myzod.OptionalType<myzod.ArrayType<myzod.StringType>>; | ||
| startsWith: myzod.OptionalType<myzod.StringType>; | ||
| endsWith: myzod.OptionalType<myzod.StringType>; | ||
| pattern: myzod.OptionalType<myzod.ObjectType<{ | ||
| source: myzod.StringType; | ||
| }>>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type StringValidatorOpts = Infer<typeof StringValidatorOpsSchema> & { | ||
| pattern?: RegExp; | ||
| test?: (arg: string) => boolean; | ||
| }; | ||
| declare class StringArgument<T extends string> extends BaseArgument<T> { | ||
| typeName: string; | ||
| options?: StringValidatorOpts; | ||
| constructor(args?: (string | StringValidatorOpts)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertStringLessThanMax(str: string, max?: number | undefined): void; | ||
| assertStringGreaterThanMin(str: unknown, min?: number | undefined): void; | ||
| assertStringIncludes(str: unknown, value?: string | undefined): void; | ||
| assertStringIn(str: unknown, value?: string[] | undefined): void; | ||
| assertStringEquals(str: unknown, value?: string | undefined): void; | ||
| assertStringMatches(str: unknown, pattern?: ({ | ||
| source: string; | ||
| } & RegExp) | undefined): void; | ||
| assertString(str?: unknown): void; | ||
| assertinArray(str: unknown, array?: string[] | undefined): void; | ||
| validate(value: string): boolean; | ||
| } | ||
| declare function string(): StringArgument<string>; | ||
| declare function string(opts: StringValidatorOpts): StringArgument<string>; | ||
| declare function string(name: string): StringArgument<string>; | ||
| declare function string(name: string, opts: StringValidatorOpts): BaseArgument<string>; | ||
| declare const NumberValidationSchema: myzod.ObjectType<{ | ||
| max: myzod.OptionalType<myzod.NumberType>; | ||
| min: myzod.OptionalType<myzod.NumberType>; | ||
| equals: myzod.OptionalType<myzod.NumberType>; | ||
| type: myzod.OptionalType<myzod.UnionType<[myzod_libs_types.LiteralType<"int">, myzod_libs_types.LiteralType<"float">]>>; | ||
| in: myzod.OptionalType<myzod.ArrayType<myzod.NumberType>>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type NumberValidatorOpts = Infer<typeof NumberValidationSchema> & { | ||
| test: (arg: number) => boolean; | ||
| }; | ||
| declare class NumberArgument<T extends number> extends BaseArgument<T> { | ||
| typeName: string; | ||
| options?: NumberValidatorOpts | undefined; | ||
| constructor(args: (NumberValidatorOpts | string)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertNumber(num?: unknown): void; | ||
| assertNumberEquals(num: unknown, equals?: number | undefined): void; | ||
| assertNumberLessThanMax(num: unknown, max?: number | undefined): void; | ||
| assertNumberGreaterThanMin(num: unknown, min?: number | undefined): void; | ||
| assertInArray(val: unknown, value?: number): boolean | undefined; | ||
| assertType(value: unknown, type?: "int" | "float" | undefined): void; | ||
| validate(value: number): boolean; | ||
| } | ||
| declare function number(): NumberArgument<number>; | ||
| declare function number(opts: NumberValidatorOpts): NumberArgument<number>; | ||
| declare function number(name: string): NumberArgument<number>; | ||
| declare function number(name: string, opts: NumberValidatorOpts): NumberArgument<number>; | ||
| declare const BooleaValidationSchema: myzod.ObjectType<{ | ||
| equals: myzod.OptionalType<myzod.BooleanType>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type BooleanValidatorOpts = Infer<typeof BooleaValidationSchema>; | ||
| declare class BooleanArgument<T extends boolean = boolean> extends BaseArgument<T> { | ||
| typeName: string; | ||
| options?: BooleanValidatorOpts; | ||
| constructor(args: (BooleanValidatorOpts | string)[]); | ||
| assertBoolean(actual?: boolean): asserts actual; | ||
| assertEquals(actual: boolean): void; | ||
| isTypeMatch(type: unknown): boolean; | ||
| validate(value: boolean): boolean; | ||
| } | ||
| declare function boolean(): BooleanArgument<boolean>; | ||
| declare function boolean(opts: BooleanValidatorOpts): BooleanArgument<boolean>; | ||
| declare function boolean(name: string): BooleanArgument<boolean>; | ||
| declare function boolean(name: string, opts: BooleanValidatorOpts): BaseArgument<boolean>; | ||
| type FromArray<T> = T extends infer TArray ? TArray extends BaseArgument<infer TArg>[] ? TArg[] : never : never; | ||
| type ArrayType = AnyArg[]; | ||
| declare const ArrayValidationSchema: myzod.ObjectType<{ | ||
| maxLength: myzod.OptionalType<myzod.NumberType>; | ||
| minLength: myzod.OptionalType<myzod.NumberType>; | ||
| length: myzod.OptionalType<myzod.NumberType>; | ||
| includes: myzod.OptionalType<myzod.UnknownType>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type ArrayValidatorOpts = Infer<typeof ArrayValidationSchema>; | ||
| declare class ArrayArgument<T extends ArrayType, TRaw extends FromArray<T>> extends BaseArgument<TRaw> { | ||
| typeName: string; | ||
| types: string[]; | ||
| options: ArrayValidatorOpts; | ||
| reference: T; | ||
| constructor(args: (string | T | ArrayValidatorOpts)[]); | ||
| assertIsArray(values: unknown): void; | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertLengthLessThanMax(values: unknown, length?: number | undefined): void; | ||
| assertLengthGreaterThanMin(values: unknown, length?: number | undefined): void; | ||
| assertLengthEquals(values: unknown, length?: number | undefined): void; | ||
| assertIncludes(values: unknown, item?: unknown): void; | ||
| assertPermittedType(values: unknown): void; | ||
| assertChildValidations(values: unknown): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function array<P extends AnyArg[], T extends ArgumentTypes<P>>(name: string, acceptedTypes: T): ArrayArgument<P, FromArray<T>>; | ||
| declare function array<P extends AnyArg[], T extends ArgumentTypes<P>>(acceptedTypes: T): ArrayArgument<P, FromArray<T>>; | ||
| declare function array<P extends AnyArg[], T extends ArgumentTypes<P>>(name: string, acceptedTypes: T, options: ArrayValidatorOpts): ArrayArgument<P, FromArray<T>>; | ||
| declare function array<P extends AnyArg[], T extends ArgumentTypes<P>>(acceptedTypes: T, options: ArrayValidatorOpts): ArrayArgument<P, FromArray<T>>; | ||
| declare const TupleValidationSchema: myzod.ObjectType<{ | ||
| includes: myzod.OptionalType<myzod.UnknownType>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type TupleValidatorOpts = Infer<typeof TupleValidationSchema>; | ||
| declare class TupleArgument<T extends TupleType, TRaw extends FromTuple<T>> extends BaseArgument<TRaw> { | ||
| options?: TupleValidatorOpts; | ||
| typeName: string; | ||
| types: string[]; | ||
| readonly reference: T; | ||
| constructor(args: (string | T | TupleValidatorOpts)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertIsTuple(values: unknown): asserts values is T; | ||
| assertIncludes(values: unknown, item?: unknown): void; | ||
| assertLength(values: unknown[], length?: number): void; | ||
| assertPermittedType(values: unknown): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function tuple<P extends TupleType, T extends ArgumentTypes<P>>(name: string, acceptedTypes: T, options?: TupleValidatorOpts): TupleArgument<T, FromTuple<T>>; | ||
| declare function tuple<P extends TupleType, T extends ArgumentTypes<P>>(acceptedTypes: T, options?: TupleValidatorOpts): TupleArgument<T, FromTuple<T>>; | ||
| declare const DateValidationOptsSchema: myzod.ObjectType<{ | ||
| before: myzod.OptionalType<myzod.DateType>; | ||
| after: myzod.OptionalType<myzod.DateType>; | ||
| equals: myzod.OptionalType<myzod.DateType>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type DateValidatorOpts = Infer<typeof DateValidationOptsSchema>; | ||
| declare const DateConstructorArgumentSchema: myzod.ArrayType<myzod.UnionType<[myzod.StringType, myzod.OptionalType<myzod.ObjectType<{ | ||
| before: myzod.OptionalType<myzod.DateType>; | ||
| after: myzod.OptionalType<myzod.DateType>; | ||
| equals: myzod.OptionalType<myzod.DateType>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>>]>>; | ||
| type DateArguments = Infer<typeof DateConstructorArgumentSchema>; | ||
| declare class DateArgument<T extends Date> extends BaseArgument<T> { | ||
| typeName: string; | ||
| isTypeMatch(type: unknown): boolean; | ||
| options?: DateValidatorOpts; | ||
| constructor(args: DateArguments); | ||
| assertBefore(value: unknown, before?: Date | undefined): void; | ||
| assertAfter(value: unknown, after?: Date | undefined): void; | ||
| assertEquals(value: unknown, equals?: Date | undefined): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function date(): DateArgument<Date>; | ||
| declare function date(name: string): DateArgument<Date>; | ||
| declare function date(name: string, options: DateValidatorOpts): DateArgument<Date>; | ||
| declare function date(options: DateValidatorOpts): DateArgument<Date>; | ||
| declare class UnknownArgument<T extends unknown> extends BaseArgument<T> { | ||
| typeName: string; | ||
| options?: ArgumentOptions; | ||
| constructor(args: (string | ArgumentOptions)[]); | ||
| isTypeMatch(_type: unknown): boolean; | ||
| validate(_value: number): boolean; | ||
| } | ||
| declare function unknown(): UnknownArgument<unknown>; | ||
| declare function unknown(name: string, opts: ArgumentOptions): UnknownArgument<unknown>; | ||
| declare function unknown(opts: ArgumentOptions): UnknownArgument<unknown>; | ||
| declare const InstanceOptionsArgumentSchema: myzod.ObjectType<{ | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type InstanceOptions = Infer<typeof InstanceOptionsArgumentSchema>; | ||
| declare class InstanceArgument<TClass extends { | ||
| constructor: unknown; | ||
| }, TShape extends ShapeArgument<any, Partial<TClass>>> extends BaseArgument<TClass> { | ||
| typeName: string; | ||
| blueprint: Class<TClass>; | ||
| options?: InstanceOptions; | ||
| shape: TShape; | ||
| constructor(args: (string | Class<TClass> | TShape)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertIsInstance(value: unknown): void; | ||
| assertShapeArguments(value: unknown): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function instance<TClass extends { | ||
| constructor: unknown; | ||
| }, TShape extends ShapeArgument<any, Partial<TClass>>>(blueprint: Class<TClass> | AbstractClass<TClass>, shape?: TShape | null, options?: InstanceOptions): InstanceArgument<TClass, TShape>; | ||
| declare function instance<TClass extends { | ||
| constructor: unknown; | ||
| }, TShape extends ShapeArgument<any, Partial<TClass>>>(name: string, blueprint: Class<TClass> | AbstractClass<TClass>, shape?: TShape | null, options?: InstanceOptions): InstanceArgument<TClass, TShape>; | ||
| declare const FunctionValidationSchema: myzod.ObjectType<{ | ||
| maxArgLength: myzod.OptionalType<myzod.NumberType>; | ||
| minArgLength: myzod.OptionalType<myzod.NumberType>; | ||
| argLength: myzod.OptionalType<myzod.NumberType>; | ||
| name: myzod.OptionalType<myzod.StringType>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type FunctionValidatorOptions = Infer<typeof FunctionValidationSchema>; | ||
| declare class FunctionArgument<T extends FunctionType> extends BaseArgument<T> { | ||
| typeName: string; | ||
| types: string[]; | ||
| readonly name?: string; | ||
| readonly options?: FunctionValidatorOptions; | ||
| constructor(args: (string | FunctionValidatorOptions | undefined)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertIsFunction(value: unknown): asserts value is T; | ||
| assertLengthLessThanMax(value: unknown, length?: number | undefined): void; | ||
| assertLengthGreaterThanMin(value: unknown, length?: number | undefined): void; | ||
| assertLengthEquals(value: unknown, length?: number | undefined): void; | ||
| assertName(value: unknown, name?: string | undefined): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function func<T extends FunctionType>(): FunctionArgument<T>; | ||
| declare function func<T extends FunctionType>(name: string): FunctionArgument<T>; | ||
| declare function func<T extends FunctionType>(name: string, options?: FunctionValidatorOptions): FunctionArgument<T>; | ||
| declare function func<T extends FunctionType>(options: FunctionValidatorOptions): FunctionArgument<T>; | ||
| declare const NilValidatorOpsSchema: myzod.ObjectType<{ | ||
| equals: myzod.OptionalType<myzod.UnionType<[myzod_libs_types.LiteralType<"null">, myzod_libs_types.LiteralType<"undefined">]>>; | ||
| optional: myzod.OptionalType<myzod.UnionType<[myzod.BooleanType, myzod.ObjectType<{ | ||
| undefined: myzod.OptionalType<myzod.BooleanType>; | ||
| null: myzod.OptionalType<myzod.BooleanType>; | ||
| }>]>>; | ||
| test: myzod.OptionalType<myzod.UnknownType>; | ||
| }>; | ||
| type NilValidatorOpts = Infer<typeof NilValidatorOpsSchema> & { | ||
| pattern?: RegExp; | ||
| }; | ||
| declare class NilArgument<T extends null | undefined> extends BaseArgument<T> { | ||
| typeName: string; | ||
| options?: NilValidatorOpts; | ||
| constructor(args?: (string | NilValidatorOpts)[]); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertIsNullOrUndefined(value: unknown): void; | ||
| assertIsNull(value: unknown): void; | ||
| assertIsUndefined(value: unknown): void; | ||
| validate(value: string): boolean; | ||
| } | ||
| declare function nil(): NilArgument<null | undefined>; | ||
| declare function nil(opts: NilValidatorOpts): NilArgument<null | undefined>; | ||
| declare function nil(name: string): NilArgument<null | undefined>; | ||
| declare function nil(name: string, opts: NilValidatorOpts): BaseArgument<null | undefined>; | ||
| declare class TypeArgument<T extends Class<unknown> | AbstractClass<unknown>> extends BaseArgument<T> { | ||
| typeName: string; | ||
| types: string[]; | ||
| readonly name?: string; | ||
| readonly type: T; | ||
| constructor(strOrT: string | T, type?: T); | ||
| isTypeMatch(type: unknown): boolean; | ||
| assertType(value: unknown, match?: T): void; | ||
| validate(value: unknown): boolean; | ||
| } | ||
| declare function type<T extends Class<unknown> | AbstractClass<unknown>>(type: T): TypeArgument<T>; | ||
| declare function type<T extends Class<unknown> | AbstractClass<unknown>>(name: string, type: Class<T>): TypeArgument<T>; | ||
| /** | ||
| * Entrypoint for overload implementations. Accepts parameter validators and their matching | ||
| * function implementations. Once complete, pass the function args to `.use(args)` to execute | ||
| * your overloads. If none are matching and no fallback is provided, an error will be thrown. | ||
| * | ||
| * ```ts | ||
| * function foo(a: string, b: number): void; | ||
| * function foo(...args: (string | number)[]){ | ||
| * return overloads( | ||
| * def(string(), number()).match((a, b)=>{...}) | ||
| * fallback().match((a, b)=>{...}) | ||
| * ).use(args) | ||
| * } | ||
| * ``` | ||
| * @param args | ||
| * @returns | ||
| */ | ||
| declare function overloads<T extends Overload<AnyArg[], OverloadAction>[]>(...args: T): { | ||
| use: (actualArgs: unknown[]) => ReturnTypes<T>; | ||
| }; | ||
| /** | ||
| * Creates a new set of parameters which should match one overloaded | ||
| * function/method implementation. Returns an object containing a matcher | ||
| * function which will be executed when the arguments match the params list | ||
| * | ||
| * ```ts | ||
| * function foo(a: string, b: number): void; | ||
| * function foo(...args: (string | number)[]){ | ||
| * return overloads( | ||
| * def(string(), number()).match((a, b)=>{ | ||
| * const modifiedA = doStringThing(a); | ||
| * const modifiedB = doNumberThing(modifiedA, b); | ||
| * }) | ||
| * ).use(args) | ||
| * } | ||
| * ``` | ||
| * @param args - a rest argument of Arguments, provided by type functions (`string()`, `number()` etc) | ||
| * @returns | ||
| */ | ||
| declare function def(name: TemplateStringsArray): ((<P extends AnyArg[], T extends ArgumentTypes<P>>(description: string, ...args: T) => ParamReturn<P, T>) & (<P extends AnyArg[], T extends ArgumentTypes<P>>(...args: T) => ParamReturn<P, T>)); | ||
| declare function def<P extends AnyArg[], T extends ArgumentTypes<P>>(description: string, ...args: T): ParamReturn<P, T>; | ||
| declare function def<P extends AnyArg[], T extends ArgumentTypes<P>>(...args: T): ParamReturn<P, T>; | ||
| type ParamReturn<P extends AnyArg[], T extends ArgumentTypes<P>> = { | ||
| /** | ||
| * Implementation for a specific overload. When the arguments passed match this functions | ||
| * parent overload, the arguments will be passed to this functions parameters. | ||
| * | ||
| * The return value will be used in a union in the final return value of the overloading function/method | ||
| * @param implementation | ||
| * @returns | ||
| */ | ||
| matches: <K>( | ||
| /** @ts-expect-error This is valid, just isn't being picked up as tuple type for some reason. **/ | ||
| implementation: (...implArgs: ValidatorArgumentTuple<T>) => K | ||
| /** @ts-expect-error This is valid, just isn't being picked up as tuple type for some reason. **/ | ||
| ) => Overload<P, (...implArgs: ValidatorArgumentTuple<T>) => K>; | ||
| }; | ||
| declare function fallback<P extends ArgumentType[], K>(description: string, implementation: (...args: P) => K): Overload<AnyArg[], (...args: P) => K>; | ||
| declare function fallback<P extends ArgumentType[], K>(implementation: (...args: P) => K): Overload<AnyArg[], (...args: P) => K>; | ||
| export { AbstractClass, AnyType, ArgumentType, ArgumentOptions as ArgumentValidatorOpts, Array$1 as Array, ArrayValidatorOpts, BaseArgument, BooleanValidatorOpts, CamelCase, Class, DateValidatorOpts, Ephemeral, FromFunction, FromShape, FromTuple, FunctionValidatorOptions as FunctionOptions, FunctionType, InferArg, InstanceType, NilValidatorOpts, NumberValidatorOpts, Primitive, Shape, ShapeType, ShapeValidatorOpts, StringValidatorOpts, Tuple, TupleType, TupleValidatorOpts as TupleValidationOptions, TypeArgument, UnionArgument, array, boolean, date, def, fallback, func, instance, nil, number, or, overloads, shape, string, tuple, type, unknown }; |
| import type { Options } from "tsup"; | ||
| export const tsup: Options = { | ||
| clean: true, // clean up the dist folder | ||
| dts: true, // generate dts files | ||
| sourcemap:true, // generate sourcemaps | ||
| format: ["cjs", "esm"], // generate cjs and esm files | ||
| skipNodeModulesBundle: true, | ||
| entryPoints: ["src/index.ts"], | ||
| target: "es2020", | ||
| outDir: "dist", | ||
| legacyOutput: true, | ||
| external: ["dist"], | ||
| }; |
Sorry, the diff of this file is too big to display
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
No website
QualityPackage does not have a website.
13
-7.14%17
30.77%209558
-40.9%2223
-30.29%2
100%3
-99.57%1
Infinity%