diff --git a/rfcs/v4-issue-formats/formats.ts b/rfcs/v4-issue-formats/formats.ts new file mode 100644 index 000000000..a74c978c9 --- /dev/null +++ b/rfcs/v4-issue-formats/formats.ts @@ -0,0 +1,254 @@ +type ZodParsedType = string; +type Primitive = string | number | boolean | bigint | symbol | undefined | null; +class ZodError {} + +export enum ZodIssueKind { + invalid_type = "invalid_type", + custom = "custom", + invalid_union = "invalid_union", + invalid_date = "invalid_date", + invalid_string = "invalid_string", + invalid_array = "invalid_array", + invalid_number = "invalid_number", + invalid_set = "invalid_set", + invalid_object = "invalid_object", + invalid_bigint = "invalid_bigint", + invalid_file = "invalid_file", +} + +export enum ZodIssueCode { + invalid_type = "invalid_type", + invalid_literal = "invalid_literal", + custom = "custom", + invalid_union = "invalid_union", + invalid_union_discriminator = "invalid_union_discriminator", + invalid_enum_value = "invalid_enum_value", + unrecognized_keys = "unrecognized_keys", + invalid_arguments = "invalid_arguments", + invalid_return_type = "invalid_return_type", + invalid_date = "invalid_date", + invalid_string = "invalid_string", + too_small = "too_small", + too_big = "too_big", + invalid_intersection_types = "invalid_intersection_types", + not_multiple_of = "not_multiple_of", + not_finite = "not_finite", +} + +// type ZodIssueCode = keyof typeof ZodIssueCode; + +export type ZodIssueBase = { + path: (string | number)[]; + message?: string; + input?: unknown; + code: ZodIssueCode[keyof ZodIssueCode]; + level: "warn" | "error" | "abort"; +}; + +export type ZodInvalidTypeIssue = ZodIssueBase & { + kind: ZodIssueKind.invalid_type; + code: ZodIssueCode.invalid_type; + expected: ZodParsedType; + received: ZodParsedType; +}; + +export type ZodInvalidUnionIssue = ZodIssueBase & { + kind: ZodIssueKind.invalid_union; + code: ZodIssueCode.invalid_union; + unionErrors: ZodError[]; +}; + +// type TooBig = { code: "too_big"; maximum: number }; +// type TooBigInclusive = { code: "too_big"; maximum: number; inclusive: boolean }; +// type TooSmall = { code: "too_small"; minimum: number }; +// type TooSmallInclusive = { +// code: "too_small"; +// minimum: number; +// inclusive: boolean; +// }; + +export type ZodInvalidDateIssue = ZodIssueBase & { + kind: ZodIssueCode.invalid_date; +} & ( + | { code: "too_big"; maximum: number; inclusive: boolean } + | { + code: "too_small"; + minimum: number; + inclusive: boolean; + } + ); + +// there will be some additions here +export type StringValidation = + | "email" + | "url" + | "emoji" + | "uuid" + | "nanoid" + | "regex" + | "cuid" + | "cuid2" + | "ulid" + | "datetime" + | "date" + | "time" + | "duration" + | "ip" + | "base64"; + +export type ZodInvalidStringIssue = ZodIssueBase & + ( + | { + code: "too_small"; + subcode: "number_too_small"; + minimum?: number; + } + | { + kind: ZodIssueCode.invalid_string; + code: "too_big"; + subcode: "number_too_big"; + maximum?: number; + } + | { + kind: ZodIssueCode.invalid_string; + code: "invalid_format"; + format: StringValidation; + pattern?: string; + } + | { + kind: ZodIssueCode.invalid_string; + code: "invalid_format"; + format: "starts_with"; + value: string; + } + | { + kind: ZodIssueCode.invalid_string; + code: "invalid_format"; + format: "ends_with"; + value: string; + } + | { + kind: ZodIssueCode.invalid_string; + code: "invalid_format"; + format: "includes"; + value: string; + } + ); + +export type ZodInvalidObjectIssue = ZodIssueBase & + ( + | { + kind: ZodIssueCode.invalid_object; + code: "missing_keys"; + keys?: string[]; + } + | { + kind: ZodIssueCode.invalid_object; + code: "unrecognized_keys"; + keys?: string[]; + } + ); + +export type ZodInvalidArrayIssue = ZodIssueBase & + ( + | { + kind: ZodIssueCode.invalid_array; + code: "not_unique"; + } + | { + kind: ZodIssueCode.invalid_array; + code: "too_big"; + maximum?: number; + } + | { + kind: ZodIssueCode.invalid_array; + code: "too_small"; + minimum?: number; + } + ); + +export type ZodInvalidNumberIssue = ZodIssueBase & + ( + | { + kind: ZodIssueCode.invalid_number; + code: "too_big"; + + maximum?: number; + exclusive?: boolean; + } + | { + kind: ZodIssueCode.invalid_number; + code: "too_small"; + minimum?: number; + exclusive?: boolean; + } + | { + kind: ZodIssueCode.invalid_number; + code: "not_multiple_of"; + multipleOf?: number; + } + ); + +export type ZodInvalidSetIssue = ZodIssueBase & + ( + | { + code: ZodIssueCode.invalid_set; + code: "too_big"; + maximum?: number; + } + | { + code: ZodIssueCode.invalid_set; + code: "too_small"; + minimum?: number; + } + | { + code: ZodIssueCode.invalid_set; + code: "not_unique"; + } + ); + +export interface ZodInvalidBigIntIssue extends ZodIssueBase { + kind: ZodIssueCode.invalid_bigint; + subcode: "too_big" | "too_small"; + minimum?: number; + maximum?: number; + exclusive?: boolean; +} + +export type ZodInvalidFileIssue = ZodIssueBase & { + type: ZodIssueCode.invalid_file; +} & ( + | { + code: "too_big"; + maximum: number; + } + | { + code: "too_small"; + minimum: number; + } + | { + code: "invalid_mime"; + acceptedTypes: string[]; + } + | { + code: "invalid_name"; + expectedName?: string; + } + ); + +export interface ZodCustomIssue extends ZodIssueBase { + code: ZodIssueCode.custom; + params?: { [k: string]: any }; +} + +export type ZodIssue = + | ZodInvalidTypeIssue + | ZodInvalidUnionIssue + | ZodInvalidStringIssue + | ZodInvalidArrayIssue + | ZodInvalidNumberIssue + | ZodInvalidSetIssue + | ZodInvalidObjectIssue + | ZodInvalidBigIntIssue + | ZodInvalidFileIssue + | ZodCustomIssue; diff --git a/rfcs/v4-issue-formats/index.md b/rfcs/v4-issue-formats/index.md new file mode 100644 index 000000000..e69de29bb diff --git a/rfcs/v4-issue-formats/new_formats.ts b/rfcs/v4-issue-formats/new_formats.ts new file mode 100644 index 000000000..b4b9932ea --- /dev/null +++ b/rfcs/v4-issue-formats/new_formats.ts @@ -0,0 +1,224 @@ +type ZodParsedType = string; +type Primitive = string | number | boolean | bigint | symbol | undefined | null; +class ZodError {} +type flatten = { [k in keyof T]: T[k] } & {}; + +export const ZodIssueCode = { + custom: "custom", + invalid_type: "invalid_type", + invalid_string: "invalid_string", + invalid_number: "invalid_number", + invalid_date: "invalid_date", + invalid_bigint: "invalid_bigint", + invalid_object: "invalid_object", + invalid_array: "invalid_array", + invalid_set: "invalid_set", + invalid_file: "invalid_file", +} as const; +export type ZodIssueCode = typeof ZodIssueCode; + +export type ZodIssueBase = { + path: (string | number)[]; + message?: string; + input?: unknown; + code: string; + level: "warn" | "error" | "abort"; +}; + +export type ZodInvalidTypeIssue = ZodIssueBase & { + code: "invalid_type"; +} & ( + | { + check: ZodParsedType; + received: ZodParsedType; + } + | { + check: "union"; + unionErrors: ZodError[]; + } + | { + check: "literal"; + literalValues: Primitive[]; + } + | { + check: "enum"; + enumValues: (string | number)[]; + } + ); + +export type $StringFormat = + | "email" + | "url" + | "emoji" + | "uuid" + | "nanoid" + | "regex" + | "cuid" + | "cuid2" + | "ulid" + | "datetime" + | "date" + | "time" + | "duration" + | "ip" + | "base64"; + +export type ZodInvalidStringIssue = ZodIssueBase & { + code: "invalid_string"; +} & ( + | { + check: $StringFormat; + } + | { + check: "starts_with"; + value: string; + } + | { + check: "ends_with"; + value: string; + } + | { + check: "includes"; + value: string; + } + | { + check: "min_size"; + minimum: number; + } + | { + check: "max_size"; + maximum: number; + } + | { + check: "size"; + size: number; + } + | { + check: "regex"; + regex: string; + } + ); + +export type ZodInvalidNumberIssue = ZodIssueBase & { + code: "invalid_number"; +} & ( + | { + check: "maximum"; + maximum: number; + } + | { + check: "minimum"; + minimum: number; + } + | { + check: "not_multiple_of"; + multipleOf: number; + } + ); + +export type ZodInvalidDateIssue = ZodIssueBase & { + code: "invalid_date"; +} & ( + | { + check: "maximum"; + maximum: number; + } + | { + check: "minimum"; + minimum: number; + } + ); + +export type ZodInvalidBigIntIssue = ZodIssueBase & { + code: "invalid_bigint"; +} & ( + | { + check: "maximum"; + maximum: bigint; + } + | { + check: "minimum"; + minimum: bigint; + } + | { + check: "not_multiple_of"; + multipleOf: bigint; + } + ); + +export type ZodInvalidObjectIssue = ZodIssueBase & { + code: "invalid_object"; +} & { + check: "unrecognized_keys"; + keys: string[]; +}; + +export type ZodInvalidArrayIssue = ZodIssueBase & { + code: "invalid_array"; +} & ( + | { + check: "min_size"; + minimum: number; + } + | { + check: "max_size"; + maximum: number; + } + | { + check: "size"; + size: number; + } + ); + +export type ZodInvalidSetIssue = ZodIssueBase & { + code: "invalid_set"; +} & ( + | { + check: "min_size"; + minimum: number; + } + | { + check: "max_size"; + maximum: number; + } + | { + check: "size"; + size: number; + } + ); + +export type ZodInvalidFileIssue = ZodIssueBase & { + code: "invalid_file"; +} & ( + | { + check: "min_size"; + minimum: number; + } + | { + check: "max_size"; + maximum: number; + } + ); + +export interface ZodCustomIssues { + custom: { params?: { [k: string]: any } }; + // test: { name: "string" } +} + +type _ZodCustomIssue = + T extends keyof ZodCustomIssues + ? flatten<{ check: T } & ZodCustomIssues[T]> + : never; +type ZodCustomIssue = ZodIssueBase & { code: "custom" } & _ZodCustomIssue; + +export type ZodIssue = + | ZodInvalidTypeIssue + | ZodInvalidStringIssue + | ZodInvalidNumberIssue + | ZodInvalidBigIntIssue + | ZodInvalidDateIssue + | ZodInvalidArrayIssue + | ZodInvalidSetIssue + | ZodInvalidObjectIssue + | ZodInvalidFileIssue + | ZodCustomIssue; diff --git a/rfcs/v4-issue-formats/old_formats.ts b/rfcs/v4-issue-formats/old_formats.ts new file mode 100644 index 000000000..46cf69f14 --- /dev/null +++ b/rfcs/v4-issue-formats/old_formats.ts @@ -0,0 +1,152 @@ +type ZodParsedType = string; +type Primitive = string | number | boolean | bigint | symbol | undefined | null; +class ZodError {} + +export enum ZodIssueCode { + invalid_type = "invalid_type", + invalid_literal = "invalid_literal", + custom = "custom", + invalid_union = "invalid_union", + invalid_union_discriminator = "invalid_union_discriminator", + invalid_enum_value = "invalid_enum_value", + unrecognized_keys = "unrecognized_keys", + invalid_arguments = "invalid_arguments", + invalid_return_type = "invalid_return_type", + invalid_date = "invalid_date", + invalid_string = "invalid_string", + too_small = "too_small", + too_big = "too_big", + invalid_intersection_types = "invalid_intersection_types", + not_multiple_of = "not_multiple_of", + not_finite = "not_finite", +} + +export type ZodIssueBase = { + path: (string | number)[]; + message?: string; + fatal?: boolean; +}; + +export interface ZodInvalidTypeIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_type; + expected: ZodParsedType; + received: ZodParsedType; +} + +export interface ZodInvalidLiteralIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_literal; + expected: unknown; + received: unknown; +} + +export interface ZodUnrecognizedKeysIssue extends ZodIssueBase { + code: typeof ZodIssueCode.unrecognized_keys; + keys: string[]; +} + +export interface ZodInvalidUnionIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_union; + unionErrors: ZodError[]; +} + +export interface ZodInvalidUnionDiscriminatorIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_union_discriminator; + options: Primitive[]; +} + +export interface ZodInvalidEnumValueIssue extends ZodIssueBase { + received: string | number; + code: typeof ZodIssueCode.invalid_enum_value; + options: (string | number)[]; +} + +export interface ZodInvalidArgumentsIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_arguments; + argumentsError: ZodError; +} + +export interface ZodInvalidReturnTypeIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_return_type; + returnTypeError: ZodError; +} + +export interface ZodInvalidDateIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_date; +} + +export type StringValidation = + | "email" + | "url" + | "emoji" + | "uuid" + | "nanoid" + | "regex" + | "cuid" + | "cuid2" + | "ulid" + | "datetime" + | "date" + | "time" + | "duration" + | "ip" + | "base64" + | { includes: string; position?: number } + | { startsWith: string } + | { endsWith: string }; + +export interface ZodInvalidStringIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_string; + validation: StringValidation; +} + +export interface ZodTooSmallIssue extends ZodIssueBase { + code: typeof ZodIssueCode.too_small; + minimum: number | bigint; + inclusive: boolean; + exact?: boolean; + type: "array" | "string" | "number" | "set" | "date" | "bigint"; +} + +export interface ZodTooBigIssue extends ZodIssueBase { + code: typeof ZodIssueCode.too_big; + maximum: number | bigint; + inclusive: boolean; + exact?: boolean; + type: "array" | "string" | "number" | "set" | "date" | "bigint"; +} + +export interface ZodInvalidIntersectionTypesIssue extends ZodIssueBase { + code: typeof ZodIssueCode.invalid_intersection_types; +} + +export interface ZodNotMultipleOfIssue extends ZodIssueBase { + code: typeof ZodIssueCode.not_multiple_of; + multipleOf: number | bigint; +} + +export interface ZodNotFiniteIssue extends ZodIssueBase { + code: typeof ZodIssueCode.not_finite; +} + +export interface ZodCustomIssue extends ZodIssueBase { + code: typeof ZodIssueCode.custom; + params?: { [k: string]: any }; +} + +export type ZodIssue = + | ZodInvalidTypeIssue + | ZodInvalidLiteralIssue + | ZodUnrecognizedKeysIssue + | ZodInvalidUnionIssue + | ZodInvalidUnionDiscriminatorIssue + | ZodInvalidEnumValueIssue + | ZodInvalidArgumentsIssue + | ZodInvalidReturnTypeIssue + | ZodInvalidDateIssue + | ZodInvalidStringIssue + | ZodTooSmallIssue + | ZodTooBigIssue + | ZodInvalidIntersectionTypesIssue + | ZodNotMultipleOfIssue + | ZodNotFiniteIssue + | ZodCustomIssue;