UNPKG

typia

Version:

Superfast runtime validators with only one line

120 lines (111 loc) • 4 kB
import RandExp from "randexp"; const ALPHABETS = "abcdefghijklmnopqrstuvwxyz"; /* ----------------------------------------------------------- REGULAR ----------------------------------------------------------- */ export const boolean = () => Math.random() < 0.5; export const integer = (min?: number, max?: number) => { min ??= 0; max ??= 100; return Math.floor(Math.random() * (max - min + 1)) + min; }; export const bigint = (min?: bigint, max?: bigint) => BigInt(integer(Number(min ?? BigInt(0)), Number(max ?? BigInt(100)))); export const number = (min?: number, max?: number) => { min ??= 0; max ??= 100; return Math.random() * (max - min) + min; }; export const string = (length?: number): string => new Array(length ?? integer(5, 10)) .fill(0) .map(() => ALPHABETS[integer(0, ALPHABETS.length - 1)]) .join(""); export const array = <T>( closure: (index: number) => T, count?: number, unique?: boolean, ): T[] => { count ??= length(); unique ??= false; if (unique === false) return new Array(count ?? length()) .fill(0) .map((_e, index) => closure(index)); else { const set = new Set<T>(); while (set.size < count) set.add(closure(set.size)); return Array.from(set); } }; export const pick = <T>(array: T[]): T => array[integer(0, array.length - 1)]!; export const length = () => integer(0, 3); export const pattern = (regex: RegExp): string => { const r: RandExp = new RandExp(regex); for (let i: number = 0; i < 10; ++i) { const str: string = r.gen(); if (regex.test(str)) return str; } return r.gen(); }; /* ----------------------------------------------------------- SECIAL FORMATS ----------------------------------------------------------- */ // SPECIAL CHARACTERS export const byte = () => "vt7ekz4lIoNTTS9sDQYdWKharxIFAR54+z/umIxSgUM="; export const password = () => string(integer(4, 16)); export const regex = () => "/^(?:(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)$/"; export const uuid = () => "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { const r = (Math.random() * 16) | 0; const v = c === "x" ? r : (r & 0x3) | 0x8; return v.toString(16); }); // ADDRESSES export const email = () => `${string(10)}@${string(10)}.${string(3)}`; export const hostname = () => `${string(10)}.${string(3)}`; export const idnEmail = () => email(); export const idnHostname = () => hostname(); export const iri = () => url(); export const iriReference = () => url(); export const ipv4 = () => array(() => integer(0, 255), 4).join("."); export const ipv6 = (): string => array(() => integer(0, 65535).toString(16), 8).join(":"); export const uri = () => url(); export const uriReference = () => url(); export const uriTemplate = () => url(); export const url = () => `https://${string(10)}.${string(3)}`; // TIMESTAMPS export const datetime = (min?: number, max?: number) => new Date( number(min ?? Date.now() - 30 * DAY, max ?? Date.now() + 7 * DAY), ).toISOString(); export const date = (min?: number, max?: number) => new Date(number(min ?? 0, max ?? Date.now() * 2)) .toISOString() .substring(0, 10); export const time = () => new Date(number(0, DAY)).toISOString().substring(11); export const duration = () => { const period: string = durate([ ["Y", integer(0, 100)], ["M", integer(0, 12)], ["D", integer(0, 31)], ]); const time: string = durate([ ["H", integer(0, 24)], ["M", integer(0, 60)], ["S", integer(0, 60)], ]); if (period.length + time.length === 0) return "PT0S"; return `P${period}${time.length ? "T" : ""}${time}`; }; // POINTERS export const jsonPointer = () => `/components/schemas/${string(10)}`; export const relativeJsonPointer = () => `${integer(0, 10)}#`; const DAY = 86400000; const durate = (elements: [string, number][]) => elements .filter(([_unit, value]) => value !== 0) .map(([unit, value]) => `${value}${unit}`) .join("");