UNPKG

escss-estest

Version:

Non-intrusive JavaScript runtime validator

561 lines (505 loc) 12.5 kB
declare type _ALLOWED_TYPES = | "array" | "bigint" | "boolean" | "function" | "null" | "number" | "object" | "string" | "symbol" | "undefined"; type _ArraySchema<Type> = Type extends (infer U)[] ? U : Type; type _ObjectSchema<Type> = { [P in keyof Type]: Type[P] extends (infer U)[] ? [U extends object ? _ObjectSchema<U> : _ALLOWED_TYPES] : Type[P] extends object ? _ObjectSchema<Type[P]> : _ALLOWED_TYPES; }; declare type _TypeClass< Type extends _ALLOWED_TYPES, Input, > = Type extends "array" ? _Array<Input> : Type extends "bigint" ? _BigInt : Type extends "boolean" ? _Boolean : Type extends "function" ? _Function : Type extends "null" ? _Null : Type extends "number" ? _Number : Type extends "object" ? _Object<Input extends object ? Input : object> : Type extends "string" ? _String : Type extends "symbol" ? _Symbol : Type extends "undefined" ? _Undefined : never; declare interface _Common<Type extends _ALLOWED_TYPES, Input = unknown> { /** * @example * // more helpful information * ESTest('foo', 'string').describe('a helpful information') */ describe(): _TypeClass<Type, Input>; } declare interface _Array<Input> extends _Common<"array", Input> { /** * @example * // [1, 2, 3].length >= 3 * ESTest([1, 2, 3], 'array').min(3) // pass */ min(inputValue: number): _Array<Input>; /** * @example * // [1, 2, 3].length <= 3 * ESTest([1, 2, 3], 'array').max(3) // pass */ max(inputValue: number): _Array<Input>; /** * @example * // [1, 2, 3].length === 3 * ESTest([1, 2, 3], 'array').length(3) // pass */ length(inputValue: number): _Array<Input>; /** * @example * // Note: schema() only accepts 'object'. * * ESTest(data, 'array', 'custom error msg').schema({ * name: 'string', * 'msg?': 'string', * more: { * a: 'number', * 'b?': 'number', * } * }) * * ESTest(data, 'array', 'custom error msg').schema({ * name: 'string', * 'msg?': 'string', * more: [{ * a: 'number', * 'b?': 'number', * }] * }) */ schema( arg: _ArraySchema<Input> extends object ? _ObjectSchema<_ArraySchema<Input>> : never, ): _Array<Input>; /** * @example * // "single case" cross field validation * * const data = [{ * password: '123', * checkPassword: '123' * }] * * // pass * ESTest(data, 'array') * .schema({ * password: 'string', * checkPassword: 'string', * }) * .refine(val => val[0].password === val[0].checkPassword, 'password mismatch') */ refine(fn: (arg: Input) => boolean, message: string): void; /** * @example * // "multiple cases" cross field validation * * const data = [{ * name: 'mike', * checkName: 'mike', * password: '123', * checkPassword: '123' * }] * * // pass * ESTest(data, 'array') * .schema({ * name: 'string', * checkName: 'string', * password: 'string', * checkPassword: 'string', * }) * .superRefine((val, ctx) => { * // case 1 * if (val[0].name !== val[0].checkName) { * ctx.addIssue('name mismatch') * } * * // case 2 * if (val[0].password !== val[0].checkPassword) { * ctx.addIssue('password mismatch') * } * }) */ superRefine( fn: ( arg: Input, ctx: { addIssue: (message: string) => void; }, ) => void, ): void; } declare interface _BigInt extends _Common<"bigint"> { /** * @example * // 5n < 10n * ESTest(5n, 'bigint').less(10n) // pass */ less(inputValue: bigint): _BigInt; /** * @example * // 5n <= 10n * ESTest(5n, 'bigint').max(10n) // pass */ max(inputValue: bigint): _BigInt; /** * @example * // 15n > 10n * ESTest(15n, 'bigint').greater(10n) // pass */ greater(inputValue: bigint): _BigInt; /** * @example * // 15n >= 10n * ESTest(15n, 'bigint').min(10n) // pass */ min(inputValue: bigint): _BigInt; /** * @example * // 15n > 0n * ESTest(15n, 'bigint').positive() // pass */ positive(): _BigInt; /** * @example * // -15n < 0n * ESTest(-15n, 'bigint').negative() // pass */ negative(): _BigInt; /** * @example * // 15n % 3n === 0n * ESTest(15n, 'bigint').multiple(3n) // pass */ multiple(inputValue: bigint): _BigInt; } declare interface _Boolean extends _Common<"boolean"> {} declare interface _Function extends _Common<"function"> {} declare interface _Null extends _Common<"null"> {} declare interface _Number extends _Common<"number"> { /** * @example * // 5 < 10 * ESTest(5, 'number').less(10) // pass */ less(inputValue: number): _Number; /** * @example * // 5 <= 10 * ESTest(5, 'number').max(10) // pass */ max(inputValue: number): _Number; /** * @example * // 15 > 10 * ESTest(15, 'number').greater(10) // pass */ greater(inputValue: number): _Number; /** * @example * // 15 >= 10 * ESTest(15, 'number').min(10) // pass */ min(inputValue: number): _Number; /** * @example * // Number.isInteger(15) * ESTest(15, 'number').integer() // pass */ integer(inputValue: number): _Number; /** * @example * // 15 > 0 * ESTest(15, 'number').positive() // pass */ positive(): _Number; /** * @example * // -15 < 0 * ESTest(-15, 'number').negative() // pass */ negative(): _Number; /** * @example * // 15 % 3 === 0 * ESTest(15, 'number').multiple(3) // pass */ multiple(inputValue: number): _Number; } declare interface _Object<Input extends object = object> extends _Common< "object", Input > { /** * @example * // Note: schema() only accepts 'object'. * * ESTest(data, 'object', 'demo is {}').schema({ * a: 'string', * demo: { * x: 'number', * 'y?': 'number', * } * }) * * ESTest(data, 'object', 'demo is {}[]').schema({ * a: 'string', * demo: [{ * x: 'number', * 'y?': 'number', * }] * }) */ schema(arg: _ObjectSchema<Input>): _Object<Input>; /** * @example * // "single case" cross field validation * * const data = { * password: '123', * checkPassword: '123' * } * * // pass * ESTest(data, 'object') * .schema({ * password: 'string', * checkPassword: 'string', * }) * .refine(val => val.password === val.checkPassword, 'password mismatch') */ refine(fn: (arg: Input) => boolean, message: string): void; /** * @example * // "multiple cases" cross field validation * * const data = { * name: 'mike', * checkName: 'mike', * password: '123', * checkPassword: '123' * } * * // pass * ESTest(data, 'object') * .schema({ * name: 'string', * checkName: 'string', * password: 'string', * checkPassword: 'string', * }) * .superRefine((val, ctx) => { * // case 1 * if (val.name !== val.checkName) { * ctx.addIssue('name mismatch') // create an error msg * } * * // case 2 * if (val.password !== val.checkPassword) { * ctx.addIssue('password mismatch') // create an error msg * } * }) */ superRefine( fn: ( arg: Input, ctx: { /** * create an error msg */ addIssue: (message: string) => void; }, ) => void, ): void; } declare interface _String extends _Common<"string"> { /** * @example * // 'foo'.length <= 10 * ESTest('foo', 'string').max(10) // pass */ max(inputValue: number): _String; /** * @example * // 'foo'.length >= 1 * ESTest('foo', 'string').min(1) // pass */ min(inputValue: number): _String; /** * @example * // 'foo'.length === 3 * ESTest('foo', 'string').length(3) // pass */ length(inputValue: number): _String; /** * @example * // Zod's default email regex (Gmail rules) * ESTest("foo@gmail.com", "string").email(); // pass * * // Equivalent to the HTML5 input[type=email] validation implemented by browsers. * ESTest("john.doe+@example-domain.com", "string").email("html5Email"); // pass * * // The classic emailregex.com regex for RFC 5322-compliant emails * ESTest("user.tag+filter@sub.example-domain.co.uk", "string").email("rfc5322Email"); // pass * * // A loose regex that allows Unicode characters, enforces length limits, and that's about it. * ESTest("user.name123@example-domain.com", "string").email("unicodeEmail"); // pass */ email(inputValue: string): _String; /** * @example * ESTest('550e8400-e29b-41d4-a716-446655440000', 'string').uuid4() // pass */ uuid4(): _String; /** * @example * ESTest('0189c7e4-3b8a-7e3b-8291-4e6f2b1a4c7d', 'string').uuid7() // pass */ uuid7(): _String; /** * @example * ESTest('foo bar', 'string').regex(/(foo|bar)/) // pass */ regex(inputValue: RegExp): _String; /** * @example * ESTest('SGVsbG8gd29ybGQh', 'string').base64() // pass */ base64(): _String; /** * @example * ESTest('Zm9vYmFyXzEyMw', 'string').base64url() // pass */ base64url(): _String; /** * @example * ESTest('192.168.1.1', 'string').ip4() // pass */ ip4(): _String; /** * @example * ESTest('2001:0db8:85a3:0000:0000:8a2e:0370:7334', 'string').ip6() // pass */ ip6(): _String; /** * @example * ESTest('192.168.0.0/16', 'string').cidr4() // pass */ cidr4(): _String; /** * @example * ESTest('2001:0db8:85a3:0000:0000:8a2e:0370:7334/16', 'string').cidr6() // pass */ cidr6(): _String; /** * @example * ESTest('🌀', 'string').emoji() // pass */ emoji(): _String; /** * @example * // international phone * ESTest('+886912345678', 'string').e164() // pass * ESTest('+14151234567', 'string').e164() // pass * */ e164(): _String; /** * @example * ESTest('foobar', 'string').lowercase() // pass */ lowercase(): _String; } declare interface _Symbol extends _Common<"symbol"> {} declare interface _Undefined extends _Common<"undefined"> {} /** * output a `console.error(...)` * @see https://github.com/ESCSS-labs/ESCSS-ESTest * @example * ESTest("Hello world", "string", "custom message here") // pass * ESTest(1, "number").max(10) // pass * ESTest([1, '123'], "array") // pass * ESTest({name: 'Mark'}, "object") // pass */ export declare function ESTest<Type extends _ALLOWED_TYPES, Input>( input: Input, type: Type, message?: string, ): _TypeClass<Type, Input>; /** * output a `throw new Error(...)` * @see https://github.com/ESCSS-labs/ESCSS-ESTest * @example * unSafeESTest("Hello world", "string", "custom message here") // pass * unSafeESTest(1, "number").max(10) // pass * unSafeESTest([1, '123'], "array") // pass * unSafeESTest({name: 'Mark'}, "object") // pass */ export declare function unSafeESTest<Type extends _ALLOWED_TYPES, Input>( input: Input, type: Type, message?: string, ): _TypeClass<Type, Input>; /** * output a `console.error(...)` * @see https://github.com/ESCSS-labs/ESCSS-ESTest * @example * // wrap the function to provide a default message scope for the library * function ESTest(input, type, message = "[libraryName] your message for others to help debugging!!") { * return ESTestForLibrary(input, type, message) * } */ export declare function ESTestForLibrary<Type extends _ALLOWED_TYPES, Input>( input: Input, type: Type, message?: string, ): _TypeClass<Type, Input>; declare global { var __ESCSS_ESTEST__: { /** * @example * globalThis.__ESCSS_ESTEST__.message = "Please report this issue to ..."; * * @see https://github.com/ESCSS-labs/ESCSS-ESTest */ message: string; /** * - true: disable checking for performance * - false (default): output a `console.error(...)` * * Note: `unSafeESTest()` will not be affected (security) * * @see https://github.com/ESCSS-labs/ESCSS-ESTest */ isESTestDisabled: boolean; /** * Show usage reports * @see https://github.com/ESCSS-labs/ESCSS-ESTest */ analysis: object; }; }