@pro-script/as-is
Version:
Check your types at runtime with ESNext syntax by meta programing in node.js and browser with interfaces, types, strict object and more.
483 lines (470 loc) • 16.5 kB
JavaScript
import { date_, generator_, structural_, withLengthEmpty, withLengthNotEmpty } from './values.js';
let filePath, env;
try { env = process?.env?.NODE_ENV } catch (e){ env = 'esm' }
switch(env){
case 'esm': filePath = '../dist/as-is.esm.mjs';
// case 'esm': filePath = '../index.js';
break;
case 'browser': filePath = '../dist/as-is.browser.js';
// case 'browser': filePath = '../index.js';
break;
default:
filePath = '../index.js';
}
const modules = await import(filePath);
import MacroInitialization from './macro.js';
import MacroInstance from './macroTests/instance.macro.test.js';
import MacroValues from './macroTests/values.macro.test.js';
const { Checker, BaseInterface, MicroTest, Utility, primitiveTypes, structuralTypes,
otherTypes, aliasTypes } = modules?.Checker ? modules: window;
const checker = new Checker({ 'IF/ELSE/END': true, strict: true, Enum: true, utility: true });
const { multi, Interface, Type, as, is, IF, ELSE, END, optional, get, macro, strict, Enum } = checker;
const { START, STOP, FINISH, METHOD, PROPERTY, IS, CHECK, passed, failed } = new MicroTest({ is, as });
import * as values_ from './values.js';
const values = Object.assign({}, values_);
const types = [...primitiveTypes,...structuralTypes,...otherTypes.map(_=>_.alias),...aliasTypes.map(_=>_.alias)];
const examples = [...values.primitive_, ...values.structural_];
const enumExample = Enum.weekday({
[Enum.step]: 1,
Monday: 1,
Tuesday: Enum.inc,
Wednesday: Enum.dec,
Thursday: Enum.inc,
Friday: Enum.dec,
Saturday: 'day off',
Sunday: 'super day off'
});
is.node() && (
values.buffer_ = new Buffer.alloc(5),
values.structural_.push(values.buffer_)
);
let { IUser } = Interface({
IUser: {
name: as.string,
birthDate: as.date,
prop: multi`nullStringNumberUndefined`
}
});
const { TUser } = Type({
TUser: {
name: as.string,
birthDate: as.date,
avatar: (value)=> {
as.stringUndefined(value);
return value;
}
}
});
START.all
{
START.macro
{
[MacroInitialization].macro;
const results = [
_ => this.is.a.first.macro,
/this.is.a.second macro/,
'this is a third macro',
0xDad
].macro;
IS.array(results);
CHECK.RESULTS0(results[0] === 'macro value');
CHECK.RESULTS1(results[1] === 2);
}
STOP.macro
START.macros
{
IS.array(get.macros());
}
STOP.macros
START.Instance
{
[MacroInstance].macro;
[
'check.constructor',
'check.class',
'check.methods'
].macro;
PROPERTY.get(checker);
}
STOP.Instance
START.getType
{
CHECK['get.type'](!!get.type())
values.primitive_.forEach((type) => CHECK[get.type(type)](!!get.type(type)));
values.structural_.forEach((type) => CHECK[get.type(type)](!!get.type(type)));
}
STOP.getType
START.CheckMethods
{
['alias', 'CheckPlatform', 'iterator', 'nullish', 'bun', 'browser', 'browserFromList', 'node', 'any',
'multiCheck', 'multiType', 'defineMethod', 'duplicateError', 'numerous', 'primitive', 'array', 'json',
'json5', 'empty', 'notEmpty', 'date', 'null', 'structural', 'class']
.forEach((methodName) => METHOD[methodName](Checker));
IS.class(BaseInterface);
}
STOP.CheckMethods
START.CheckValues
{ [MacroValues].macro;
[_ => check.values].macro;
}
STOP.CheckValues
START.newValidatorsPositive
{
if (is.node() || is.bun()) {
IS.undefined(values.iterable.forEach((item) => CHECK.iterable(is.iterable(item))))
IS.object(is.argument(values.object_) && as.argument(values.object_))
IS.array(is.argument(values.array_) && as.argument(values.array_))
IS.undefined(is.nullish() && as.nullish())
IS.process(is.node() && as.node())
} else if (is.browser()) {
IS.undefined(values.iterable.forEach((item) => CHECK.iterable(is.iterable(item))))
IS.object(is.argument(values.object_) && as.argument(values.object_))
IS.array(is.argument(values.array_) && as.argument(values.array_))
IS.undefined(is.nullish() && as.nullish())
// IS.Navigator(is.browser() && as.browser())
}
}
STOP.newValidatorsPositive
START.newValidatorsNegative
{
if (is.node() || is.bun()) {
values.iterable.forEach((item) => CHECK[`not iterable`](!is.iterable(0)));
CHECK['not argument'](!is.argument(values.error_));
try {
as.argument(values.error_)
} catch (e) {
CHECK[`as.argument(values.error_) throw an error`](true);
}
CHECK['not nullish'](!is.nullish(values.error_));
try {
as.nullish(values.error_)
} catch (e) {
CHECK[`as.nullish(values.error_) throw an error`](true);
}
CHECK['not browser'](!is.browser());
try {
as.browser()
} catch (e) {
CHECK[`as.browser() throw an error`](true);
}
} else if (is.browser()) {
values.iterable.forEach((item) => CHECK[`not iterable`](!is.iterable(0)));
CHECK['not argument'](!is.argument(values.error_));
try {
as.argument(values.error_)
} catch (e) {
CHECK[`as.generator(values.error_) throw an error`](true);
}
CHECK['not nullish'](!is.nullish(values.error_));
try {
as.nullish(values.error_)
} catch (e) {
CHECK[`as.nullish(values.error_) throw an error`](true);
}
CHECK['not node'](!is.node());
try {
as.node()
} catch (e) {
CHECK[`as.node() throw an error`](true);
}
}
}
STOP.newValidatorsNegative
START.if_else
{
function someFunction(name, age, friends,
_ = [as.stringNumberArray(name),
as.undefinedNumberArray(age),
as.undefinedArray(friends)
]) {
IF.string(name) && is.number(age) && is.array(friends) ? (
as.array(_) && as.notEmpty(_) && as.true(_.length == 3)
) : ELSE.string(name) && is.array(age) ? (
friends = age,
age = undefined
) : ELSE.number(name) && is.array(age) ? (
friends = age,
age = name,
name = undefined
) : ELSE.array(name) ? (
friends = name,
name = undefined
) : END;
return {name, age, friends};
};
let {name, age, friends} = someFunction('Rick', 25, ['Mike', 'Liza']);
CHECK[`name === 'Rick'`](name === 'Rick');
CHECK['age === 25'](age === 25);
CHECK[`friends.includes('Mike')`](friends.includes('Mike'));
CHECK[`friends.includes('Liza')`](friends.includes('Liza'));
({name, age, friends} = someFunction('Rick', ['Mike', 'Liza']))
CHECK[`name === 'Rick'`](name === 'Rick');
CHECK['is.undefined(age)'](is.undefined(age));
CHECK[`friends.includes('Mike')`](friends.includes('Mike'));
CHECK[`friends.includes('Liza')`](friends.includes('Liza'));
({name, age, friends} = someFunction(25, ['Mike', 'Liza']))
CHECK['is.undefined(name)'](is.undefined(name));
CHECK['age === 25'](age === 25);
CHECK[`friends.includes('Mike')`](friends.includes('Mike'));
CHECK[`friends.includes('Liza')`](friends.includes('Liza'));
({name, age, friends} = someFunction(['Mike', 'Liza']))
CHECK['is.undefined(name)'](is.undefined(name));
CHECK['is.undefined(age)'](is.undefined(age));
CHECK[`friends.includes('Mike')`](friends.includes('Mike'));
CHECK[`friends.includes('Liza')`](friends.includes('Liza'));
}
STOP.if_else;
START.primitivesPositive
{
values.primitive_.forEach((type) => {
as[get.type(type)](type);
CHECK[get.type(type)](!!get.type(type));
});
}
STOP.primitivesPositive
START.structuralPositive
{
values.structural_.forEach((type) => {
as[get.type(type)](type);
CHECK[get.type(type)](!!get.type(type));
});
}
STOP.structuralPositive
START.primitivesNegative
{
values.primitive_.forEach((type) => {
CHECK[`it's not a(an) ${get.type(type)}`](!is[get.type(type)]({}));
try {
as[get.type(type)]({})
} catch (e) {
CHECK[`as.${get.type(type)}({}) throw an error`](true);
}
});
}
STOP.primitivesNegative
START.structuralNegative
{
values.structural_.forEach((type) => {
CHECK[`it's not a(an) ${get.type(type)}`](!is[get.type(type)](0));
try {
as[get.type(type)](0)
} catch (e) {
CHECK[`as.${get.type(type)}(0) throw an error`](true);
}
});
}
STOP.structuralNegative
START.aliasPositive
{
CHECK.optional(!optional.string());
CHECK.optionalFalse(optional.Boolean(false));
CHECK.generator(is.generator(values.generator_));
}
STOP.aliasPositive
START.aliasNegative
{
CHECK[`not a generator`](!is.generator(values.string_));
try {
as.generator(0)
} catch (e) {
CHECK[`as.generator(0) throw an error`](true);
}
}
STOP.aliasNegative
START.otherTypesPositive
{
values.withLengthEmpty.forEach((type) => {
as.empty(type);
CHECK[`empty ${get.type(type)}`](is.empty(type));
});
values.withLengthNotEmpty.forEach((type) => {
as.notEmpty(type);
CHECK[`notEmpty ${get.type(type)}`](is.notEmpty(type));
});
IS.date(values.date_);
as.date(values.date_);
IS.null(values.null_);
as.null(values.null_);
IS.json(values.json_);
as.json(values.json_);
IS.json5(values.json5_);
as.json5(values.json5_);
IS.class(Checker);
as.class(Checker);
}
STOP.otherTypesPositive
START.otherTypesNegative
{
values.withLengthNotEmpty.forEach((type) => {
try {
as.empty(type)
} catch (e) {
CHECK[`as.empty(${type}) throw an error`](true);
}
CHECK[`empty ${get.type(type)}`](!is.empty(type));
});
values.withLengthEmpty.forEach((type) => {
try {
as.notEmpty(type)
} catch (e) {
CHECK[`as.notEmpty(${type}) throw an error`](true);
}
CHECK[`notEmpty ${get.type(type)}`](!is.notEmpty(type));
});
try {
as.date({})
} catch (e) {
CHECK[`as.date(${{}}) throw an error`](true);
}
CHECK[`not is.date${{}}`](!is.date({}));
try {
as.null({})
} catch (e) {
CHECK[`as.null(${{}}) throw an error`](true);
}
CHECK[`not is.json${{}}`](!is.json({}));
try {
as.json({})
} catch (e) {
CHECK[`as.json(${{}}) throw an error`](true);
}
CHECK[`not is.json${{}}`](!is.json({}));
try {
as.json5({})
} catch (e) {
CHECK[`as.json5(${{}}) throw an error`](true);
}
CHECK[`not is.json5${{}}`](!is.json5({}));
try {
as.class({})
} catch (e) {
CHECK[`as.class(${{}}) throw an error`](true);
}
CHECK[`not is.class${{}}`](!is.class({}));
}
STOP.otherTypesNegative
START.numerousTypePositive
{
values.primitiveTypes.forEach((type) => values.primitive_.forEach((value) => {
if (type === get.type(value)) {
CHECK[`in object is.${type}s()`](is[`${type}s`]({prop1: value, prop2: value}));
CHECK[`in array is.${type}s()`](is[`${type}s`]([value, value, value]));
CHECK[`in set is.${type}s()`](is[`${type}s`](new Set([value, value, value])));
const mapValues = new Map();
mapValues.set('1', value);
mapValues.set('2', value);
mapValues.set('3', value);
CHECK[`in map is.${type}s()`](is[`${type}s`](mapValues));
}
}));
}
STOP.numerousTypePositive
START.numerousTypeNegative;
values.primitiveTypes.forEach((type)=> values.primitive_.forEach((value)=> {
if(type === get.type(value)){
try {
CHECK[`not in object is.${type}s()`](!is[`${type}s`]({prop1: [], prop2: []}));
CHECK[`not in array is.${type}s()`](!is[`${type}s`]([[], [], []]));
CHECK[`not in set is.${type}s()`](!is[`${type}s`](new Set([{}, {}, {}])));
CHECK[`not in map is.${type}s()`](!is[`${type}s`]({}));
} catch (e) {
CHECK[`in object, array, set, map throw an error`](true);
}
}
}));
STOP.numerousTypeNegative;
START.multiTypePositive
{
examples.forEach((value)=> IS[types.join('').replaceAll(',','')](value));
}
STOP.multiTypePositive
START.multiTypeNegative
{
const primitives = primitiveTypes.join('').replaceAll(',','');
const structurals = structuralTypes.join('').replaceAll(',','');
const otherTypesCollection = otherTypes.map(_=>_.alias);
const aliasTypesCollection = aliasTypes.map(_=>_.alias);
try {
as[primitives]({});
} catch (e) {
CHECK[`as.${primitives}({}) throw an error`](true);
}
try {
as[structurals](0);
} catch (e) {
CHECK[`as.${structurals}(${0}) throw an error`](true);
}
try {
as[otherTypesCollection](0);
} catch (e) {
CHECK[`as.${otherTypesCollection}(${0}) throw an error`](true);
}
try {
as[aliasTypesCollection](0);
} catch (e) {
CHECK[`as.${aliasTypesCollection}(${0}) throw an error`](true);
}
}
STOP.multiTypeNegative
START.EnumPositive
{
console.log(as.Enum(enumExample));
IS.Enum(enumExample);
}
STOP.EnumPositive
START.EnumNegative
{
try {
as.Enum({})
} catch (e) {
CHECK[`as.Enum(${{}}) throw an error`](true);
}
}
STOP.EnumNegative
START.EnumWeekdayPositive
{
IS.weekday('Monday');
}
STOP.EnumWeekdayPositive
START.EnumWeekdayNegative
{
try {
as.weekday('WeekDay')
} catch (e) {
CHECK[`as.weekday('WeekDay') throw an error`](true);
}
}
STOP.EnumWeekdayNegative
START.InterfacePositive
{
IS.object(IUser = { name: 'string', birthDate: new Date()});
IS.object(as.IUser = { name: 'string', birthDate: new Date()});
IS.object(as.IUser = { name: 'string', birthDate: new Date(), prop: undefined});
IS.object(as.IUser = { name: 'string', birthDate: new Date(), prop: null});
}
STOP.InterfacePositive
START.InterfaceNegative
{
try {
as.IUser = { name: 0, birthDate: new Date()}
} catch (e) {
CHECK[`as.IUser(${{}}) throw an error`](true);
}
}
STOP.InterfaceNegative
START.TypePositive
{
IS.object(as.TUser({ name: 'string', birthDate: new Date()}));
IS.object(as.TUser({ name: 'string', birthDate: new Date(), avatar: 'https://www.youtube.com'}));
}
STOP.TypePositive
START.TypeNegative
{
try {
as.TUser({ name: 0, birthDate: new Date()});
} catch (e) {
CHECK[`as.TUser(${{}}) throw an error`](true);
}
}
STOP.TypeNegative
} FINISH.all;