/** * MARK: Data */ export type DataVal = string | number | boolean | Date | symbol | null | unknown | DataObject | DataVal[]; export type DataObject = { [key: string]: DataVal; }; export type GenericObject = { [key: string]: any; }; export type TV = { [K in keyof T]: T[K] extends Array ? string : T[K] extends Record ? TV | string : string; }; export type RulesRawVal = string | (string | RulesRaw)[] | RulesRaw; export type RulesRaw = { [key: string]: RulesRawVal; }; export type RuleFn = (...args: any[]) => boolean; export type RuleExtension = RuleFn | RegExp | (string | number)[] | TV; export type DeepMutable = T extends string ? T : T extends number ? T : T extends boolean ? T : T extends bigint ? T : T extends symbol ? T : T extends null ? T : T extends Date ? T : T extends undefined ? T : T extends Function ? T : T extends object ? { -readonly [K in keyof T]: DeepMutable; } : T; /** * MARK: Inferrence */ type ExtractGuard = T extends (val: unknown, ...args: any[]) => val is infer R ? R : never; type RuleMap> = { [K in keyof Rules]: ExtractGuard; }; type ExtractRuleName = S extends `${infer Word}|${infer _}` ? Word : S extends `${infer Word}:${infer _}` ? Word : S; type RemoveNegation = S extends `!${infer Rest}` ? Rest : S; /** * Recursively infer the type for a schema. * - If the schema value is a string, we use InferRuleTypeFromStore. * - If it’s an array (conditional group), we take the union of the inferences. * - If it’s an object, we recursively map its keys. */ export type InferredSchema = {}> = S extends string ? S extends `?${infer Rest}` ? (Rest extends '' ? undefined : InferredSchema, Rules> | undefined) : (S extends `literal:${infer Literal}` ? Literal : S extends `[${infer Inner}]${infer Rest}` ? InferredSchema[] : S extends `{${infer Inner}}${infer Rest}` ? { [key: string]: InferredSchema; } : ExtractRuleName> extends keyof RuleMap ? RuleMap[ExtractRuleName>] : unknown) : S extends Array ? InferredSchema : S extends object ? { [K in keyof S]: InferredSchema; } : unknown; export type MappedExtensions, Rules extends Record = {}> = { [K in keyof Ext]: Ext[K] extends RegExp ? (val: unknown, ...args: any[]) => val is string : Ext[K] extends (infer U)[] ? (val: unknown, ...args: any[]) => val is U : Ext[K] extends (...args: any[]) => any ? Ext[K] : Ext[K] extends Record ? (val: unknown, ...args: any[]) => val is DeepMutable> : unknown; }; export type MergeExtensions, E2 extends Record> = Omit & E2; /** * MARK: Validation */ export type ValidationError = { idx?: number; msg: string; params: DataVal[]; }; export type ValidationIterable = { unique: boolean; max: number; min: number; handler: (v: unknown) => null | { len: number; values: unknown[]; }; }; export type ValidationRules = { nested: false; iterable: ValidationIterable | false; list: { type: string; params: [unknown, boolean][]; params_length: number; not: boolean; msg: string; }[]; list_length: number; }; export type ValidationGroup = { key: string; sometimes: boolean; rules: (ValidationRules | ValidationNested)[]; }; export type ValidationNested = { nested: true; plan: ValidationGroup[]; }; export type ValidationResult = { /** * Whether or not the validation was valid */ is_valid: boolean; /** * Integer value defining how many fields were invalid in the provided data object */ count: number; /** * Errors object which will be filled with the errors of the validation result if there are any. * * Take note: 'NO_DATA' is set when no data was passed to the validator. * * Example: {b: [{msg: 'number', params: []}]} */ errors: 'NO_DATA' | { [key: string]: ValidationError[]; }; }; export {};