ts-interface-checker
Advanced tools
Comparing version 0.1.6 to 0.1.7
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const types_1 = require("./types"); | ||
const util_1 = require("./util"); | ||
var types_1 = require("./types"); | ||
var util_1 = require("./util"); | ||
/** | ||
@@ -42,8 +42,14 @@ * Export functions used to define interfaces. | ||
*/ | ||
function createCheckers(...typeSuite) { | ||
const fullSuite = Object.assign({}, types_1.basicTypes, ...typeSuite); | ||
const checkers = {}; | ||
for (const suite of typeSuite) { | ||
for (const name of Object.keys(suite)) { | ||
checkers[name] = new Checker(fullSuite, suite[name]); | ||
function createCheckers() { | ||
var typeSuite = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
typeSuite[_i] = arguments[_i]; | ||
} | ||
var fullSuite = Object.assign.apply(Object, [{}, types_1.basicTypes].concat(typeSuite)); | ||
var checkers = {}; | ||
for (var _a = 0, typeSuite_1 = typeSuite; _a < typeSuite_1.length; _a++) { | ||
var suite_1 = typeSuite_1[_a]; | ||
for (var _b = 0, _c = Object.keys(suite_1); _b < _c.length; _b++) { | ||
var name = _c[_b]; | ||
checkers[name] = new Checker(fullSuite, suite_1[name]); | ||
} | ||
@@ -58,5 +64,5 @@ } | ||
*/ | ||
class Checker { | ||
var Checker = /** @class */ (function () { | ||
// Create checkers by using `createCheckers()` function. | ||
constructor(suite, ttype) { | ||
function Checker(suite, ttype) { | ||
this.suite = suite; | ||
@@ -66,3 +72,4 @@ this.ttype = ttype; | ||
if (ttype instanceof types_1.TIface) { | ||
for (const p of ttype.props) { | ||
for (var _i = 0, _a = ttype.props; _i < _a.length; _i++) { | ||
var p = _a[_i]; | ||
this.props.set(p.name, p.ttype); | ||
@@ -77,3 +84,3 @@ } | ||
*/ | ||
check(value) { return this._doCheck(this.checkerPlain, value); } | ||
Checker.prototype.check = function (value) { return this._doCheck(this.checkerPlain, value); }; | ||
/** | ||
@@ -83,5 +90,5 @@ * A fast check for whether or not the given value satisfies this Checker's type. This returns | ||
*/ | ||
test(value) { | ||
Checker.prototype.test = function (value) { | ||
return this.checkerPlain(value, new util_1.NoopContext()); | ||
} | ||
}; | ||
/** | ||
@@ -91,5 +98,5 @@ * Returns an error object describing the errors if the given value does not satisfy this | ||
*/ | ||
validate(value) { | ||
Checker.prototype.validate = function (value) { | ||
return this._doValidate(this.checkerPlain, value); | ||
} | ||
}; | ||
/** | ||
@@ -100,3 +107,3 @@ * Check that the given value satisfies this checker's type strictly. This checks that objects | ||
*/ | ||
strictCheck(value) { return this._doCheck(this.checkerStrict, value); } | ||
Checker.prototype.strictCheck = function (value) { return this._doCheck(this.checkerStrict, value); }; | ||
/** | ||
@@ -106,5 +113,5 @@ * A fast strict check for whether or not the given value satisfies this Checker's type. Returns | ||
*/ | ||
strictTest(value) { | ||
Checker.prototype.strictTest = function (value) { | ||
return this.checkerStrict(value, new util_1.NoopContext()); | ||
} | ||
}; | ||
/** | ||
@@ -114,5 +121,5 @@ * Returns an error object describing the errors if the given value does not satisfy this | ||
*/ | ||
strictValidate(value) { | ||
Checker.prototype.strictValidate = function (value) { | ||
return this._doValidate(this.checkerStrict, value); | ||
} | ||
}; | ||
/** | ||
@@ -122,9 +129,9 @@ * If this checker is for an interface, returns a Checker for the type required for the given | ||
*/ | ||
getProp(prop) { | ||
const ttype = this.props.get(prop); | ||
Checker.prototype.getProp = function (prop) { | ||
var ttype = this.props.get(prop); | ||
if (!ttype) { | ||
throw new Error(`Type has no property ${prop}`); | ||
throw new Error("Type has no property " + prop); | ||
} | ||
return new Checker(this.suite, ttype); | ||
} | ||
}; | ||
/** | ||
@@ -138,6 +145,6 @@ * If this checker is for an interface, returns a Checker for the argument-list required to call | ||
*/ | ||
methodArgs(methodName) { | ||
const tfunc = this._getMethod(methodName); | ||
Checker.prototype.methodArgs = function (methodName) { | ||
var tfunc = this._getMethod(methodName); | ||
return new Checker(this.suite, tfunc.paramList); | ||
} | ||
}; | ||
/** | ||
@@ -147,10 +154,10 @@ * If this checker is for an interface, returns a Checker for the return value of the given | ||
*/ | ||
methodResult(methodName) { | ||
const tfunc = this._getMethod(methodName); | ||
Checker.prototype.methodResult = function (methodName) { | ||
var tfunc = this._getMethod(methodName); | ||
return new Checker(this.suite, tfunc.result); | ||
} | ||
}; | ||
/** | ||
* If this checker is for a function, returns a Checker for its argument-list. | ||
*/ | ||
getArgs() { | ||
Checker.prototype.getArgs = function () { | ||
if (!(this.ttype instanceof types_1.TFunc)) { | ||
@@ -160,7 +167,7 @@ throw new Error("getArgs() applied to non-function"); | ||
return new Checker(this.suite, this.ttype.paramList); | ||
} | ||
}; | ||
/** | ||
* If this checker is for a function, returns a Checker for its result. | ||
*/ | ||
getResult() { | ||
Checker.prototype.getResult = function () { | ||
if (!(this.ttype instanceof types_1.TFunc)) { | ||
@@ -170,40 +177,41 @@ throw new Error("getResult() applied to non-function"); | ||
return new Checker(this.suite, this.ttype.result); | ||
} | ||
}; | ||
/** | ||
* Return the type for which this is a checker. | ||
*/ | ||
getType() { | ||
Checker.prototype.getType = function () { | ||
return this.ttype; | ||
} | ||
}; | ||
/** | ||
* Actual implementation of check() and strictCheck(). | ||
*/ | ||
_doCheck(checkerFunc, value) { | ||
const noopCtx = new util_1.NoopContext(); | ||
Checker.prototype._doCheck = function (checkerFunc, value) { | ||
var noopCtx = new util_1.NoopContext(); | ||
if (!checkerFunc(value, noopCtx)) { | ||
const detailCtx = new util_1.DetailContext(); | ||
var detailCtx = new util_1.DetailContext(); | ||
checkerFunc(value, detailCtx); | ||
throw detailCtx.getError(); | ||
} | ||
} | ||
_doValidate(checkerFunc, value) { | ||
const noopCtx = new util_1.NoopContext(); | ||
}; | ||
Checker.prototype._doValidate = function (checkerFunc, value) { | ||
var noopCtx = new util_1.NoopContext(); | ||
if (checkerFunc(value, noopCtx)) { | ||
return null; | ||
} | ||
const detailCtx = new util_1.DetailContext(); | ||
var detailCtx = new util_1.DetailContext(); | ||
checkerFunc(value, detailCtx); | ||
return detailCtx.getErrorDetail(); | ||
} | ||
_getMethod(methodName) { | ||
const ttype = this.props.get(methodName); | ||
}; | ||
Checker.prototype._getMethod = function (methodName) { | ||
var ttype = this.props.get(methodName); | ||
if (!ttype) { | ||
throw new Error(`Type has no property ${methodName}`); | ||
throw new Error("Type has no property " + methodName); | ||
} | ||
if (!(ttype instanceof types_1.TFunc)) { | ||
throw new Error(`Property ${methodName} is not a method`); | ||
throw new Error("Property " + methodName + " is not a method"); | ||
} | ||
return ttype; | ||
} | ||
} | ||
}; | ||
return Checker; | ||
}()); | ||
exports.Checker = Checker; |
@@ -6,7 +6,20 @@ "use strict"; | ||
// tslint:disable:no-shadowed-variable prefer-for-of | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return function (d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const util_1 = require("./util"); | ||
var util_1 = require("./util"); | ||
/** Node that represents a type. */ | ||
class TType { | ||
} | ||
var TType = /** @class */ (function () { | ||
function TType() { | ||
} | ||
return TType; | ||
}()); | ||
exports.TType = TType; | ||
@@ -18,5 +31,5 @@ /** Parses a type spec into a TType node. */ | ||
function getNamedType(suite, name) { | ||
const ttype = suite[name]; | ||
var ttype = suite[name]; | ||
if (!ttype) { | ||
throw new Error(`Unknown type ${name}`); | ||
throw new Error("Unknown type " + name); | ||
} | ||
@@ -31,11 +44,14 @@ return ttype; | ||
exports.name = name; | ||
class TName extends TType { | ||
constructor(name) { | ||
super(); | ||
this.name = name; | ||
this._failMsg = `is not a ${name}`; | ||
var TName = /** @class */ (function (_super) { | ||
__extends(TName, _super); | ||
function TName(name) { | ||
var _this = _super.call(this) || this; | ||
_this.name = name; | ||
_this._failMsg = "is not a " + name; | ||
return _this; | ||
} | ||
getChecker(suite, strict) { | ||
const ttype = getNamedType(suite, this.name); | ||
const checker = ttype.getChecker(suite, strict); | ||
TName.prototype.getChecker = function (suite, strict) { | ||
var _this = this; | ||
var ttype = getNamedType(suite, this.name); | ||
var checker = ttype.getChecker(suite, strict); | ||
if (ttype instanceof BasicType || ttype instanceof TName) { | ||
@@ -45,5 +61,6 @@ return checker; | ||
// For complex types, add an additional "is not a <Type>" message on failure. | ||
return (value, ctx) => checker(value, ctx) ? true : ctx.fail(null, this._failMsg, 0); | ||
} | ||
} | ||
return function (value, ctx) { return checker(value, ctx) ? true : ctx.fail(null, _this._failMsg, 0); }; | ||
}; | ||
return TName; | ||
}(TType)); | ||
exports.TName = TName; | ||
@@ -55,13 +72,17 @@ /** | ||
exports.lit = lit; | ||
class TLiteral extends TType { | ||
constructor(value) { | ||
super(); | ||
this.value = value; | ||
this.name = JSON.stringify(value); | ||
this._failMsg = `is not ${this.name}`; | ||
var TLiteral = /** @class */ (function (_super) { | ||
__extends(TLiteral, _super); | ||
function TLiteral(value) { | ||
var _this = _super.call(this) || this; | ||
_this.value = value; | ||
_this.name = JSON.stringify(value); | ||
_this._failMsg = "is not " + _this.name; | ||
return _this; | ||
} | ||
getChecker(suite, strict) { | ||
return (value, ctx) => (value === this.value) ? true : ctx.fail(null, this._failMsg, -1); | ||
} | ||
} | ||
TLiteral.prototype.getChecker = function (suite, strict) { | ||
var _this = this; | ||
return function (value, ctx) { return (value === _this.value) ? true : ctx.fail(null, _this._failMsg, -1); }; | ||
}; | ||
return TLiteral; | ||
}(TType)); | ||
exports.TLiteral = TLiteral; | ||
@@ -73,15 +94,17 @@ /** | ||
exports.array = array; | ||
class TArray extends TType { | ||
constructor(ttype) { | ||
super(); | ||
this.ttype = ttype; | ||
var TArray = /** @class */ (function (_super) { | ||
__extends(TArray, _super); | ||
function TArray(ttype) { | ||
var _this = _super.call(this) || this; | ||
_this.ttype = ttype; | ||
return _this; | ||
} | ||
getChecker(suite, strict) { | ||
const itemChecker = this.ttype.getChecker(suite, strict); | ||
return (value, ctx) => { | ||
TArray.prototype.getChecker = function (suite, strict) { | ||
var itemChecker = this.ttype.getChecker(suite, strict); | ||
return function (value, ctx) { | ||
if (!Array.isArray(value)) { | ||
return ctx.fail(null, "is not an array", 0); | ||
} | ||
for (let i = 0; i < value.length; i++) { | ||
const ok = itemChecker(value[i], ctx); | ||
for (var i = 0; i < value.length; i++) { | ||
var ok = itemChecker(value[i], ctx); | ||
if (!ok) { | ||
@@ -93,4 +116,5 @@ return ctx.fail(i, null, 1); | ||
}; | ||
} | ||
} | ||
}; | ||
return TArray; | ||
}(TType)); | ||
exports.TArray = TArray; | ||
@@ -100,19 +124,25 @@ /** | ||
*/ | ||
function tuple(...typeSpec) { | ||
return new TTuple(typeSpec.map((t) => parseSpec(t))); | ||
function tuple() { | ||
var typeSpec = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
typeSpec[_i] = arguments[_i]; | ||
} | ||
return new TTuple(typeSpec.map(function (t) { return parseSpec(t); })); | ||
} | ||
exports.tuple = tuple; | ||
class TTuple extends TType { | ||
constructor(ttypes) { | ||
super(); | ||
this.ttypes = ttypes; | ||
var TTuple = /** @class */ (function (_super) { | ||
__extends(TTuple, _super); | ||
function TTuple(ttypes) { | ||
var _this = _super.call(this) || this; | ||
_this.ttypes = ttypes; | ||
return _this; | ||
} | ||
getChecker(suite, strict) { | ||
const itemCheckers = this.ttypes.map((t) => t.getChecker(suite, strict)); | ||
const checker = (value, ctx) => { | ||
TTuple.prototype.getChecker = function (suite, strict) { | ||
var itemCheckers = this.ttypes.map(function (t) { return t.getChecker(suite, strict); }); | ||
var checker = function (value, ctx) { | ||
if (!Array.isArray(value)) { | ||
return ctx.fail(null, "is not an array", 0); | ||
} | ||
for (let i = 0; i < itemCheckers.length; i++) { | ||
const ok = itemCheckers[i](value[i], ctx); | ||
for (var i = 0; i < itemCheckers.length; i++) { | ||
var ok = itemCheckers[i](value[i], ctx); | ||
if (!ok) { | ||
@@ -127,3 +157,3 @@ return ctx.fail(i, null, 1); | ||
} | ||
return (value, ctx) => { | ||
return function (value, ctx) { | ||
if (!checker(value, ctx)) { | ||
@@ -135,4 +165,5 @@ return false; | ||
}; | ||
} | ||
} | ||
}; | ||
return TTuple; | ||
}(TType)); | ||
exports.TTuple = TTuple; | ||
@@ -142,29 +173,36 @@ /** | ||
*/ | ||
function union(...typeSpec) { | ||
return new TUnion(typeSpec.map((t) => parseSpec(t))); | ||
function union() { | ||
var typeSpec = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
typeSpec[_i] = arguments[_i]; | ||
} | ||
return new TUnion(typeSpec.map(function (t) { return parseSpec(t); })); | ||
} | ||
exports.union = union; | ||
class TUnion extends TType { | ||
constructor(ttypes) { | ||
super(); | ||
this.ttypes = ttypes; | ||
const names = ttypes.map((t) => t instanceof TName || t instanceof TLiteral ? t.name : null) | ||
.filter((n) => n); | ||
const otherTypes = ttypes.length - names.length; | ||
var TUnion = /** @class */ (function (_super) { | ||
__extends(TUnion, _super); | ||
function TUnion(ttypes) { | ||
var _this = _super.call(this) || this; | ||
_this.ttypes = ttypes; | ||
var names = ttypes.map(function (t) { return t instanceof TName || t instanceof TLiteral ? t.name : null; }) | ||
.filter(function (n) { return n; }); | ||
var otherTypes = ttypes.length - names.length; | ||
if (names.length) { | ||
if (otherTypes > 0) { | ||
names.push(`${otherTypes} more`); | ||
names.push(otherTypes + " more"); | ||
} | ||
this._failMsg = `is none of ${names.join(", ")}`; | ||
_this._failMsg = "is none of " + names.join(", "); | ||
} | ||
else { | ||
this._failMsg = `is none of ${otherTypes} types`; | ||
_this._failMsg = "is none of " + otherTypes + " types"; | ||
} | ||
return _this; | ||
} | ||
getChecker(suite, strict) { | ||
const itemCheckers = this.ttypes.map((t) => t.getChecker(suite, strict)); | ||
return (value, ctx) => { | ||
const ur = ctx.unionResolver(); | ||
for (let i = 0; i < itemCheckers.length; i++) { | ||
const ok = itemCheckers[i](value, ur.createContext()); | ||
TUnion.prototype.getChecker = function (suite, strict) { | ||
var _this = this; | ||
var itemCheckers = this.ttypes.map(function (t) { return t.getChecker(suite, strict); }); | ||
return function (value, ctx) { | ||
var ur = ctx.unionResolver(); | ||
for (var i = 0; i < itemCheckers.length; i++) { | ||
var ok = itemCheckers[i](value, ur.createContext()); | ||
if (ok) { | ||
@@ -175,6 +213,7 @@ return true; | ||
ctx.resolveUnion(ur); | ||
return ctx.fail(null, this._failMsg, 0); | ||
return ctx.fail(null, _this._failMsg, 0); | ||
}; | ||
} | ||
} | ||
}; | ||
return TUnion; | ||
}(TType)); | ||
exports.TUnion = TUnion; | ||
@@ -188,14 +227,20 @@ /** | ||
exports.enumtype = enumtype; | ||
class TEnumType extends TType { | ||
constructor(members) { | ||
super(); | ||
this.members = members; | ||
this.validValues = new Set(); | ||
this._failMsg = "is not a valid enum value"; | ||
this.validValues = new Set(Object.keys(members).map((name) => members[name])); | ||
var TEnumType = /** @class */ (function (_super) { | ||
__extends(TEnumType, _super); | ||
function TEnumType(members) { | ||
var _this = _super.call(this) || this; | ||
_this.members = members; | ||
_this.validValues = new Set(); | ||
_this._failMsg = "is not a valid enum value"; | ||
_this.validValues = new Set(Object.keys(members).map(function (name) { return members[name]; })); | ||
return _this; | ||
} | ||
getChecker(suite, strict) { | ||
return (value, ctx) => (this.validValues.has(value) ? true : ctx.fail(null, this._failMsg, 0)); | ||
} | ||
} | ||
TEnumType.prototype.getChecker = function (suite, strict) { | ||
var _this = this; | ||
return function (value, ctx) { | ||
return (_this.validValues.has(value) ? true : ctx.fail(null, _this._failMsg, 0)); | ||
}; | ||
}; | ||
return TEnumType; | ||
}(TType)); | ||
exports.TEnumType = TEnumType; | ||
@@ -209,24 +254,28 @@ /** | ||
exports.enumlit = enumlit; | ||
class TEnumLiteral extends TType { | ||
constructor(enumName, prop) { | ||
super(); | ||
this.enumName = enumName; | ||
this.prop = prop; | ||
this._failMsg = `is not ${enumName}.${prop}`; | ||
var TEnumLiteral = /** @class */ (function (_super) { | ||
__extends(TEnumLiteral, _super); | ||
function TEnumLiteral(enumName, prop) { | ||
var _this = _super.call(this) || this; | ||
_this.enumName = enumName; | ||
_this.prop = prop; | ||
_this._failMsg = "is not " + enumName + "." + prop; | ||
return _this; | ||
} | ||
getChecker(suite, strict) { | ||
const ttype = getNamedType(suite, this.enumName); | ||
TEnumLiteral.prototype.getChecker = function (suite, strict) { | ||
var _this = this; | ||
var ttype = getNamedType(suite, this.enumName); | ||
if (!(ttype instanceof TEnumType)) { | ||
throw new Error(`Type ${this.enumName} used in enumlit is not an enum type`); | ||
throw new Error("Type " + this.enumName + " used in enumlit is not an enum type"); | ||
} | ||
const val = ttype.members[this.prop]; | ||
var val = ttype.members[this.prop]; | ||
if (!ttype.members.hasOwnProperty(this.prop)) { | ||
throw new Error(`Unknown value ${this.enumName}.${this.prop} used in enumlit`); | ||
throw new Error("Unknown value " + this.enumName + "." + this.prop + " used in enumlit"); | ||
} | ||
return (value, ctx) => (value === val) ? true : ctx.fail(null, this._failMsg, -1); | ||
} | ||
} | ||
return function (value, ctx) { return (value === val) ? true : ctx.fail(null, _this._failMsg, -1); }; | ||
}; | ||
return TEnumLiteral; | ||
}(TType)); | ||
exports.TEnumLiteral = TEnumLiteral; | ||
function makeIfaceProps(props) { | ||
return Object.keys(props).map((name) => makeIfaceProp(name, props[name])); | ||
return Object.keys(props).map(function (name) { return makeIfaceProp(name, props[name]); }); | ||
} | ||
@@ -246,20 +295,25 @@ function makeIfaceProp(name, prop) { | ||
exports.iface = iface; | ||
class TIface extends TType { | ||
constructor(bases, props) { | ||
super(); | ||
this.bases = bases; | ||
this.props = props; | ||
this.propSet = new Set(props.map((p) => p.name)); | ||
var TIface = /** @class */ (function (_super) { | ||
__extends(TIface, _super); | ||
function TIface(bases, props) { | ||
var _this = _super.call(this) || this; | ||
_this.bases = bases; | ||
_this.props = props; | ||
_this.propSet = new Set(props.map(function (p) { return p.name; })); | ||
return _this; | ||
} | ||
getChecker(suite, strict) { | ||
const baseCheckers = this.bases.map((b) => getNamedType(suite, b).getChecker(suite, strict)); | ||
const propCheckers = this.props.map((prop) => prop.ttype.getChecker(suite, strict)); | ||
const testCtx = new util_1.NoopContext(); | ||
TIface.prototype.getChecker = function (suite, strict) { | ||
var _this = this; | ||
var baseCheckers = this.bases.map(function (b) { return getNamedType(suite, b).getChecker(suite, strict); }); | ||
var propCheckers = this.props.map(function (prop) { return prop.ttype.getChecker(suite, strict); }); | ||
var testCtx = new util_1.NoopContext(); | ||
// Consider a prop required if it's not optional AND does not allow for undefined as a value. | ||
const isPropRequired = this.props.map((prop, i) => !prop.isOpt && !propCheckers[i](undefined, testCtx)); | ||
const checker = (value, ctx) => { | ||
var isPropRequired = this.props.map(function (prop, i) { | ||
return !prop.isOpt && !propCheckers[i](undefined, testCtx); | ||
}); | ||
var checker = function (value, ctx) { | ||
if (typeof value !== "object" || value === null) { | ||
return ctx.fail(null, "is not an object", 0); | ||
} | ||
for (let i = 0; i < baseCheckers.length; i++) { | ||
for (var i = 0; i < baseCheckers.length; i++) { | ||
if (!baseCheckers[i](value, ctx)) { | ||
@@ -269,14 +323,14 @@ return false; | ||
} | ||
for (let i = 0; i < propCheckers.length; i++) { | ||
const name = this.props[i].name; | ||
const v = value[name]; | ||
for (var i = 0; i < propCheckers.length; i++) { | ||
var name_1 = _this.props[i].name; | ||
var v = value[name_1]; | ||
if (v === undefined) { | ||
if (isPropRequired[i]) { | ||
return ctx.fail(name, "is missing", 1); | ||
return ctx.fail(name_1, "is missing", 1); | ||
} | ||
} | ||
else { | ||
const ok = propCheckers[i](v, ctx); | ||
var ok = propCheckers[i](v, ctx); | ||
if (!ok) { | ||
return ctx.fail(name, null, 1); | ||
return ctx.fail(name_1, null, 1); | ||
} | ||
@@ -291,8 +345,8 @@ } | ||
// In strict mode, check also for unknown enumerable properties. | ||
return (value, ctx) => { | ||
return function (value, ctx) { | ||
if (!checker(value, ctx)) { | ||
return false; | ||
} | ||
for (const prop in value) { | ||
if (!this.propSet.has(prop)) { | ||
for (var prop in value) { | ||
if (!_this.propSet.has(prop)) { | ||
return ctx.fail(prop, "is extraneous", 2); | ||
@@ -303,4 +357,5 @@ } | ||
}; | ||
} | ||
} | ||
}; | ||
return TIface; | ||
}(TType)); | ||
exports.TIface = TIface; | ||
@@ -312,7 +367,8 @@ /** | ||
exports.opt = opt; | ||
class TOptional { | ||
constructor(ttype) { | ||
var TOptional = /** @class */ (function () { | ||
function TOptional(ttype) { | ||
this.ttype = ttype; | ||
} | ||
} | ||
return TOptional; | ||
}()); | ||
exports.TOptional = TOptional; | ||
@@ -322,4 +378,4 @@ /** | ||
*/ | ||
class TProp { | ||
constructor(name, ttype, isOpt) { | ||
var TProp = /** @class */ (function () { | ||
function TProp(name, ttype, isOpt) { | ||
this.name = name; | ||
@@ -329,3 +385,4 @@ this.ttype = ttype; | ||
} | ||
} | ||
return TProp; | ||
}()); | ||
exports.TProp = TProp; | ||
@@ -336,18 +393,25 @@ /** | ||
*/ | ||
function func(resultSpec, ...params) { | ||
function func(resultSpec) { | ||
var params = []; | ||
for (var _i = 1; _i < arguments.length; _i++) { | ||
params[_i - 1] = arguments[_i]; | ||
} | ||
return new TFunc(new TParamList(params), parseSpec(resultSpec)); | ||
} | ||
exports.func = func; | ||
class TFunc extends TType { | ||
constructor(paramList, result) { | ||
super(); | ||
this.paramList = paramList; | ||
this.result = result; | ||
var TFunc = /** @class */ (function (_super) { | ||
__extends(TFunc, _super); | ||
function TFunc(paramList, result) { | ||
var _this = _super.call(this) || this; | ||
_this.paramList = paramList; | ||
_this.result = result; | ||
return _this; | ||
} | ||
getChecker(suite, strict) { | ||
return (value, ctx) => { | ||
TFunc.prototype.getChecker = function (suite, strict) { | ||
return function (value, ctx) { | ||
return typeof value === "function" ? true : ctx.fail(null, "is not a function", 0); | ||
}; | ||
} | ||
} | ||
}; | ||
return TFunc; | ||
}(TType)); | ||
exports.TFunc = TFunc; | ||
@@ -361,4 +425,4 @@ /** | ||
exports.param = param; | ||
class TParam { | ||
constructor(name, ttype, isOpt) { | ||
var TParam = /** @class */ (function () { | ||
function TParam(name, ttype, isOpt) { | ||
this.name = name; | ||
@@ -368,3 +432,4 @@ this.ttype = ttype; | ||
} | ||
} | ||
return TParam; | ||
}()); | ||
exports.TParam = TParam; | ||
@@ -374,17 +439,22 @@ /** | ||
*/ | ||
class TParamList extends TType { | ||
constructor(params) { | ||
super(); | ||
this.params = params; | ||
var TParamList = /** @class */ (function (_super) { | ||
__extends(TParamList, _super); | ||
function TParamList(params) { | ||
var _this = _super.call(this) || this; | ||
_this.params = params; | ||
return _this; | ||
} | ||
getChecker(suite, strict) { | ||
const itemCheckers = this.params.map((t) => t.ttype.getChecker(suite, strict)); | ||
const testCtx = new util_1.NoopContext(); | ||
const isParamRequired = this.params.map((param, i) => !param.isOpt && !itemCheckers[i](undefined, testCtx)); | ||
const checker = (value, ctx) => { | ||
TParamList.prototype.getChecker = function (suite, strict) { | ||
var _this = this; | ||
var itemCheckers = this.params.map(function (t) { return t.ttype.getChecker(suite, strict); }); | ||
var testCtx = new util_1.NoopContext(); | ||
var isParamRequired = this.params.map(function (param, i) { | ||
return !param.isOpt && !itemCheckers[i](undefined, testCtx); | ||
}); | ||
var checker = function (value, ctx) { | ||
if (!Array.isArray(value)) { | ||
return ctx.fail(null, "is not an array", 0); | ||
} | ||
for (let i = 0; i < itemCheckers.length; i++) { | ||
const p = this.params[i]; | ||
for (var i = 0; i < itemCheckers.length; i++) { | ||
var p = _this.params[i]; | ||
if (value[i] === undefined) { | ||
@@ -396,3 +466,3 @@ if (isParamRequired[i]) { | ||
else { | ||
const ok = itemCheckers[i](value[i], ctx); | ||
var ok = itemCheckers[i](value[i], ctx); | ||
if (!ok) { | ||
@@ -408,3 +478,3 @@ return ctx.fail(p.name, null, 1); | ||
} | ||
return (value, ctx) => { | ||
return function (value, ctx) { | ||
if (!checker(value, ctx)) { | ||
@@ -416,4 +486,5 @@ return false; | ||
}; | ||
} | ||
} | ||
}; | ||
return TParamList; | ||
}(TType)); | ||
exports.TParamList = TParamList; | ||
@@ -423,12 +494,16 @@ /** | ||
*/ | ||
class BasicType extends TType { | ||
constructor(validator, message) { | ||
super(); | ||
this.validator = validator; | ||
this.message = message; | ||
var BasicType = /** @class */ (function (_super) { | ||
__extends(BasicType, _super); | ||
function BasicType(validator, message) { | ||
var _this = _super.call(this) || this; | ||
_this.validator = validator; | ||
_this.message = message; | ||
return _this; | ||
} | ||
getChecker(suite, strict) { | ||
return (value, ctx) => this.validator(value) ? true : ctx.fail(null, this.message, 0); | ||
} | ||
} | ||
BasicType.prototype.getChecker = function (suite, strict) { | ||
var _this = this; | ||
return function (value, ctx) { return _this.validator(value) ? true : ctx.fail(null, _this.message, 0); }; | ||
}; | ||
return BasicType; | ||
}(TType)); | ||
exports.BasicType = BasicType; | ||
@@ -439,20 +514,24 @@ /** | ||
exports.basicTypes = { | ||
any: new BasicType((v) => true, "is invalid"), | ||
number: new BasicType((v) => (typeof v === "number"), "is not a number"), | ||
object: new BasicType((v) => (typeof v === "object" && v), "is not an object"), | ||
boolean: new BasicType((v) => (typeof v === "boolean"), "is not a boolean"), | ||
string: new BasicType((v) => (typeof v === "string"), "is not a string"), | ||
symbol: new BasicType((v) => (typeof v === "symbol"), "is not a symbol"), | ||
void: new BasicType((v) => (v == null), "is not void"), | ||
undefined: new BasicType((v) => (v === undefined), "is not undefined"), | ||
null: new BasicType((v) => (v === null), "is not null"), | ||
never: new BasicType((v) => false, "is unexpected"), | ||
any: new BasicType(function (v) { return true; }, "is invalid"), | ||
number: new BasicType(function (v) { return (typeof v === "number"); }, "is not a number"), | ||
object: new BasicType(function (v) { return (typeof v === "object" && v); }, "is not an object"), | ||
boolean: new BasicType(function (v) { return (typeof v === "boolean"); }, "is not a boolean"), | ||
string: new BasicType(function (v) { return (typeof v === "string"); }, "is not a string"), | ||
symbol: new BasicType(function (v) { return (typeof v === "symbol"); }, "is not a symbol"), | ||
void: new BasicType(function (v) { return (v == null); }, "is not void"), | ||
undefined: new BasicType(function (v) { return (v === undefined); }, "is not undefined"), | ||
null: new BasicType(function (v) { return (v === null); }, "is not null"), | ||
never: new BasicType(function (v) { return false; }, "is unexpected"), | ||
}; | ||
if (typeof Buffer !== "undefined") { | ||
exports.basicTypes.Buffer = new BasicType((v) => Buffer.isBuffer(v), "is not a Buffer"); | ||
exports.basicTypes.Buffer = new BasicType(function (v) { return Buffer.isBuffer(v); }, "is not a Buffer"); | ||
} | ||
var _loop_1 = function (array_1) { | ||
exports.basicTypes[array_1.name] = new BasicType(function (v) { return (v instanceof array_1); }, "is not a " + array_1.name); | ||
}; | ||
// Support typed arrays of various flavors | ||
for (const array of [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, | ||
Int32Array, Uint32Array, Float32Array, Float64Array, ArrayBuffer]) { | ||
exports.basicTypes[array.name] = new BasicType((v) => (v instanceof array), `is not a ${array.name}`); | ||
for (var _i = 0, _a = [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, | ||
Int32Array, Uint32Array, Float32Array, Float64Array, ArrayBuffer]; _i < _a.length; _i++) { | ||
var array_1 = _a[_i]; | ||
_loop_1(array_1); | ||
} |
124
dist/util.js
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return function (d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -7,8 +17,11 @@ /** | ||
*/ | ||
class VError extends Error { | ||
constructor(path, message) { | ||
super(message); | ||
this.path = path; | ||
var VError = /** @class */ (function (_super) { | ||
__extends(VError, _super); | ||
function VError(path, message) { | ||
var _this = _super.call(this, message) || this; | ||
_this.path = path; | ||
return _this; | ||
} | ||
} | ||
return VError; | ||
}(Error)); | ||
exports.VError = VError; | ||
@@ -20,10 +33,13 @@ /** | ||
*/ | ||
class NoopContext { | ||
fail(relPath, message, score) { | ||
var NoopContext = /** @class */ (function () { | ||
function NoopContext() { | ||
} | ||
NoopContext.prototype.fail = function (relPath, message, score) { | ||
return false; | ||
} | ||
unionResolver() { return this; } | ||
createContext() { return this; } | ||
resolveUnion(ur) { } | ||
} | ||
}; | ||
NoopContext.prototype.unionResolver = function () { return this; }; | ||
NoopContext.prototype.createContext = function () { return this; }; | ||
NoopContext.prototype.resolveUnion = function (ur) { }; | ||
return NoopContext; | ||
}()); | ||
exports.NoopContext = NoopContext; | ||
@@ -33,4 +49,4 @@ /** | ||
*/ | ||
class DetailContext { | ||
constructor() { | ||
var DetailContext = /** @class */ (function () { | ||
function DetailContext() { | ||
// Stack of property names and associated messages for reporting helpful error messages. | ||
@@ -43,3 +59,3 @@ this._propNames = [""]; | ||
} | ||
fail(relPath, message, score) { | ||
DetailContext.prototype.fail = function (relPath, message, score) { | ||
this._propNames.push(relPath); | ||
@@ -49,10 +65,11 @@ this._messages.push(message); | ||
return false; | ||
} | ||
unionResolver() { | ||
}; | ||
DetailContext.prototype.unionResolver = function () { | ||
return new DetailUnionResolver(); | ||
} | ||
resolveUnion(unionResolver) { | ||
const u = unionResolver; | ||
let best = null; | ||
for (const ctx of u.contexts) { | ||
}; | ||
DetailContext.prototype.resolveUnion = function (unionResolver) { | ||
var u = unionResolver; | ||
var best = null; | ||
for (var _i = 0, _a = u.contexts; _i < _a.length; _i++) { | ||
var ctx = _a[_i]; | ||
if (!best || ctx._score >= best._score) { | ||
@@ -63,32 +80,33 @@ best = ctx; | ||
if (best && best._score > 0) { | ||
this._propNames.push(...best._propNames); | ||
this._messages.push(...best._messages); | ||
(_b = this._propNames).push.apply(_b, best._propNames); | ||
(_c = this._messages).push.apply(_c, best._messages); | ||
} | ||
} | ||
getError() { | ||
let path = "value"; | ||
const msgParts = []; | ||
for (let i = this._propNames.length - 1; i >= 0; i--) { | ||
const p = this._propNames[i]; | ||
path += (typeof p === "number") ? `[${p}]` : (p ? `.${p}` : ""); | ||
const m = this._messages[i]; | ||
var _b, _c; | ||
}; | ||
DetailContext.prototype.getError = function () { | ||
var path = "value"; | ||
var msgParts = []; | ||
for (var i = this._propNames.length - 1; i >= 0; i--) { | ||
var p = this._propNames[i]; | ||
path += (typeof p === "number") ? "[" + p + "]" : (p ? "." + p : ""); | ||
var m = this._messages[i]; | ||
if (m) { | ||
msgParts.push(`${path} ${m}`); | ||
msgParts.push(path + " " + m); | ||
} | ||
} | ||
return new VError(path, msgParts.join("; ")); | ||
} | ||
getErrorDetail() { | ||
let path = "value"; | ||
const details = []; | ||
for (let i = this._propNames.length - 1; i >= 0; i--) { | ||
const p = this._propNames[i]; | ||
path += (typeof p === "number") ? `[${p}]` : (p ? `.${p}` : ""); | ||
const message = this._messages[i]; | ||
}; | ||
DetailContext.prototype.getErrorDetail = function () { | ||
var path = "value"; | ||
var details = []; | ||
for (var i = this._propNames.length - 1; i >= 0; i--) { | ||
var p = this._propNames[i]; | ||
path += (typeof p === "number") ? "[" + p + "]" : (p ? "." + p : ""); | ||
var message = this._messages[i]; | ||
if (message) { | ||
details.push({ path, message }); | ||
details.push({ path: path, message: message }); | ||
} | ||
} | ||
let detail = null; | ||
for (let i = details.length - 1; i >= 0; i--) { | ||
var detail = null; | ||
for (var i = details.length - 1; i >= 0; i--) { | ||
if (detail) { | ||
@@ -100,14 +118,16 @@ details[i].nested = [detail]; | ||
return detail; | ||
} | ||
} | ||
}; | ||
return DetailContext; | ||
}()); | ||
exports.DetailContext = DetailContext; | ||
class DetailUnionResolver { | ||
constructor() { | ||
var DetailUnionResolver = /** @class */ (function () { | ||
function DetailUnionResolver() { | ||
this.contexts = []; | ||
} | ||
createContext() { | ||
const ctx = new DetailContext(); | ||
DetailUnionResolver.prototype.createContext = function () { | ||
var ctx = new DetailContext(); | ||
this.contexts.push(ctx); | ||
return ctx; | ||
} | ||
} | ||
}; | ||
return DetailUnionResolver; | ||
}()); |
{ | ||
"name": "ts-interface-checker", | ||
"version": "0.1.6", | ||
"version": "0.1.7", | ||
"description": "Runtime library to validate data against TypeScript interfaces", | ||
@@ -5,0 +5,0 @@ "main": "dist/index", |
58507
1158