@webilix/helper-library
Version:
JavaScript/TypeScript programming helper library.
170 lines (124 loc) • 5.85 kB
text/typescript
import bigInteger from 'big-integer';
import { RE } from './re';
import { plateLetters } from './shared';
function arrayIn(values: any[], arr: any[]): boolean {
for (const v of values) if (!arr.includes(v)) return false;
return true;
}
function arrayUnique(arr: any[], value?: (v: any) => any): boolean {
return (
arr
.map((v: any) => (value ? value(v) : v))
.filter((v: any, index: number, self: string[]) => self.indexOf(v) === index).length === arr.length
);
}
function isStringBankCard(bankCard: string): boolean {
const numbers: string[] = bankCard.split('');
// Check for all unique numbers
const unique = numbers.filter((n, index: number, self: string[]) => self.indexOf(n) === index);
if (unique.length === 1) return false;
let check: number = 0;
numbers.forEach((n: string, index: number) => {
const charCheck: number = +n * (index % 2 === 0 ? 2 : 1);
check += charCheck > 9 ? charCheck - 9 : charCheck;
});
return check % 10 === 0;
}
function isStringBankSheba(bankSheba: string): boolean {
const sheba = (bankSheba.substring(4) + bankSheba.substring(0, 4))
.toUpperCase()
.replace('I', '18')
.replace('R', '27');
return RE.NUMERIC.get().test(sheba) && bigInteger(sheba).divmod(97).remainder.toJSNumber() === 1;
}
function isStringNationalCode(nationalCode: string): boolean {
const numbers: string[] = nationalCode.split('');
// Check for all unique numbers
const unique = numbers.filter((n, index: number, self: string[]) => self.indexOf(n) === index);
if (unique.length === 1) return false;
let check = 0;
numbers.forEach((n: string, index: number) => {
if (index >= 9) return;
check += (10 - index) * +n;
});
check = check % 11;
check = check < 2 ? check : 11 - check;
return check === +numbers[9];
}
function isStringObjectId(objectId: string): boolean {
if (objectId.length === 12) {
const bytes = Buffer.from(objectId);
return bytes.byteLength === 12;
}
if (objectId.length === 24) return /^[0-9a-fA-F]{24}$/.test(objectId);
return false;
}
function isPlate(value: string[]): boolean;
function isPlate(value: string): boolean;
function isPlate(value: string, join: string): boolean;
function isPlate(value: any, join: string = '-'): boolean {
const plate: string[] = Array.isArray(value) ? value : IS.string(value) ? value.split(join) : [];
if (plate.length !== 4) return false;
// LEFT
if (!IS.STRING.numeric(plate[0]) || plate[0].length !== 2) return false;
// LETTER
if (!IS.string(plate[1]) || !plateLetters.includes(plate[1])) return false;
// RIGHT
if (!IS.STRING.numeric(plate[2]) || plate[2].length !== 3) return false;
// IRAN
if (!IS.STRING.numeric(plate[3]) || plate[3].length !== 2) return false;
return true;
}
export const IS = {
//#region ARRAY
ARRAY: {
in: arrayIn,
unique: arrayUnique,
},
//#endregion
//#region STRING
STRING: {
bankCard: (value: any): boolean =>
IS.string(value) && value.length === 16 && IS.STRING.numeric(value) && isStringBankCard(value),
bankSheba: (value: any): boolean =>
IS.string(value) &&
value.length === 26 &&
value.toUpperCase().substring(0, 2) === 'IR' &&
IS.STRING.numeric(value.substring(2)) &&
isStringBankSheba(value),
color: (value: any): boolean =>
IS.string(value) &&
(RE.HEX_COLOR.get().test(value) || RE.HSL_COLOR.get().test(value) || RE.RGB_COLOR.get().test(value)),
date: (value: any): boolean => IS.string(value) && RE.DATE.get().test(value),
domain: (value: any): boolean => IS.string(value) && RE.DOMAIN.get().test(value),
email: (value: any): boolean => IS.string(value) && RE.EMAIL.get().test(value.toLowerCase()),
hexColor: (value: any): boolean => IS.string(value) && RE.HEX_COLOR.get().test(value),
ip4: (value: any): boolean => IS.string(value) && RE.IP4.get().test(value),
jsonDate: (value: any): boolean => IS.string(value) && RE.JSON_DATE.get().test(value),
mobile: (value: any): boolean => IS.string(value) && RE.MOBILE.get().test(value),
nationalCode: (value: any): boolean =>
IS.string(value) && value.length === 10 && IS.STRING.numeric(value) && isStringNationalCode(value),
number: (value: any): boolean => !IS.empty(value) && IS.string(value) && IS.number(+value),
numeric: (value: any): boolean => IS.string(value) && RE.NUMERIC.get().test(value),
objectId: (value: any): boolean => IS.string(value) && isStringObjectId(value),
time: (value: any): boolean => IS.string(value) && RE.TIME.get().test(value),
url: (value: any): boolean => IS.string(value) && RE.URL.get(true).test(value),
},
//#endregion
//#region VALUE
array: (value: any): boolean => Array.isArray(value),
boolean: (value: any): boolean => typeof value === 'boolean',
date: (value: any): boolean =>
Object.prototype.toString.call(value) === '[object Date]' && !isNaN((value as Date).getTime()),
empty: (value: any): boolean =>
IS.null(value) ||
value === '' ||
(IS.array(value) && value.length === 0) ||
(IS.object(value) && Object.keys(value).length === 0),
null: (value: any): boolean => value === null || value === undefined,
number: (value: any): boolean => typeof value === 'number' && !isNaN(value),
object: (value: any): boolean => value !== null && typeof value == 'object' && !IS.array(value) && !IS.date(value),
plate: isPlate,
string: (value: any): boolean => typeof value === 'string',
//#endregion
};