narrows
Version:
Super lean and simple object validation with TypeScript support.
143 lines • 5.53 kB
JavaScript
;
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
to[j] = from[i];
return to;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.report = exports.nullable = exports.optional = exports.all = exports.any = exports.tuple = exports.record = exports.instance = exports.array = exports.object = exports.literal = exports.nil = exports.empty = exports.number = exports.string = exports.boolean = void 0;
var isObject = function (x) {
return typeof x === "object" && x !== null;
};
// -------------------------------- //
// - - - PRIMITIVE VALIDATORS - - - //
// -------------------------------- //
/** Returns true if and only if x is a boolean. */
var boolean = function (x) { return typeof x === "boolean"; };
exports.boolean = boolean;
/** Returns true if and only if x is a string. */
var string = function (x) { return typeof x === "string"; };
exports.string = string;
/** Returns true if and only if x is a number. */
var number = function (x) { return typeof x === "number"; };
exports.number = number;
/** Returns true if and only if x is undefined. */
var empty = function (x) { return x === undefined; };
exports.empty = empty;
/** Returns true if and only if x is null. */
var nil = function (x) { return x === null; };
exports.nil = nil;
/** Returns true if and only if x is strictly equal to y. */
var literal = function (y) {
return function (x) {
return x === y;
};
};
exports.literal = literal;
// ------------------------------ //
// - - - COMPLEX VALIDATORS - - - //
// ------------------------------ //
/** Returns true if and only if x is an object where each value matches the given validator. */
var object = function (validator) {
return function (x) {
return isObject(x) && Object.values(x).every(validator);
};
};
exports.object = object;
/** Returns true if and only if x is an array where each element matches the given validator. */
var array = function (validator) {
return function (x) {
return Array.isArray(x) && x.every(validator);
};
};
exports.array = array;
/** Returns true if and only if x is an instance of the given type. */
var instance = function (base) {
return function (x) {
return x instanceof base;
};
};
exports.instance = instance;
// ------------------------------//
// - - - SCHEMA VALIDATORS - - - //
// ------------------------------//
/** Returns true if and only if x is an object where each value matches the validator at the corresponding key in the schema. */
var record = function (schema) {
return function (x) {
return isObject(x) &&
Object.entries(schema).every(function (_a) {
var key = _a[0], validate = _a[1];
return validate(x[key]);
});
};
};
exports.record = record;
/** Returns true if and only if x is an array where each element matches the validator at the corresponding index in the schema. */
var tuple = function () {
var schema = [];
for (var _i = 0; _i < arguments.length; _i++) {
schema[_i] = arguments[_i];
}
return function (x) {
return Array.isArray(x) && schema.every(function (validator, i) { return validator(x[i]); });
};
};
exports.tuple = tuple;
// ----------------------- //
// - - - COMBINATORS - - - //
// ----------------------- //
/** Returns true if and only if x matches any of the given validators. */
var any = function () {
var validators = [];
for (var _i = 0; _i < arguments.length; _i++) {
validators[_i] = arguments[_i];
}
return function (x) {
return validators.some(function (validator) { return validator(x); });
};
};
exports.any = any;
/** Returns true if and only if x matches all of the given validators. */
var all = function () {
var validators = [];
for (var _i = 0; _i < arguments.length; _i++) {
validators[_i] = arguments[_i];
}
return function (x) {
return validators.every(function (validator) { return validator(x); });
};
};
exports.all = all;
/** Returns true if and only if x matches the given validator or is undefined. */
var optional = function (validator) { return exports.any(exports.empty, validator); };
exports.optional = optional;
/** Returns true if and only if x matches the given validator or is null. */
var nullable = function (validator) { return exports.any(exports.nil, validator); };
exports.nullable = nullable;
// --------------------- //
// - - - REPORTING - - - //
// --------------------- //
var canProxy = function (x) {
return x !== null && (typeof x === "object" || typeof x === "function");
};
function spy(source, report, path) {
if (path === void 0) { path = []; }
if (!canProxy(source))
return source;
return new Proxy(source, {
get: function (target, property) {
var value = target[property];
var next = __spreadArray(__spreadArray([], path), [property]);
report(next);
return canProxy(value) ? spy(value, report, next) : value;
}
});
}
/** Takes a validator and an object to be validated. Returns null if the object is valid, or the path to the invalid property. */
function report(validate, object) {
var path = [];
var passed = validate(spy(object, function (current) { return (path = current); }));
return passed ? null : path;
}
exports.report = report;
//# sourceMappingURL=index.js.map