typia
Version:
Superfast runtime validators with only one line
120 lines (111 loc) • 4 kB
text/typescript
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("");