astro-ghostcms/.pnpm-store/v3/files/6d/d9ce28c985448feda4c950915b8...

567 lines
20 KiB
Plaintext

"use strict";
/**
* This module defines nodes used to define types and validations for objects and interfaces.
*/
// tslint:disable:no-shadowed-variable prefer-for-of
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
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 extendStatics(d, b);
};
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 });
exports.basicTypes = exports.BasicType = exports.TParamList = exports.TParam = exports.param = exports.TFunc = exports.func = exports.TProp = exports.TOptional = exports.opt = exports.TIface = exports.iface = exports.TEnumLiteral = exports.enumlit = exports.TEnumType = exports.enumtype = exports.TIntersection = exports.intersection = exports.TUnion = exports.union = exports.TTuple = exports.tuple = exports.TArray = exports.array = exports.TLiteral = exports.lit = exports.TName = exports.name = exports.TType = void 0;
var util_1 = require("./util");
/** Node that represents a type. */
var TType = /** @class */ (function () {
function TType() {
}
return TType;
}());
exports.TType = TType;
/** Parses a type spec into a TType node. */
function parseSpec(typeSpec) {
return typeof typeSpec === "string" ? name(typeSpec) : typeSpec;
}
function getNamedType(suite, name) {
var ttype = suite[name];
if (!ttype) {
throw new Error("Unknown type " + name);
}
return ttype;
}
/**
* Defines a type name, either built-in, or defined in this suite. It can typically be included in
* the specs as just a plain string.
*/
function name(value) { return new TName(value); }
exports.name = 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;
}
TName.prototype.getChecker = function (suite, strict, allowedProps) {
var _this = this;
var ttype = getNamedType(suite, this.name);
var checker = ttype.getChecker(suite, strict, allowedProps);
if (ttype instanceof BasicType || ttype instanceof TName) {
return checker;
}
// For complex types, add an additional "is not a <Type>" message on failure.
return function (value, ctx) { return checker(value, ctx) ? true : ctx.fail(null, _this._failMsg, 0); };
};
return TName;
}(TType));
exports.TName = TName;
/**
* Defines a literal value, e.g. lit('hello') or lit(123).
*/
function lit(value) { return new TLiteral(value); }
exports.lit = lit;
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;
}
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;
/**
* Defines an array type, e.g. array('number').
*/
function array(typeSpec) { return new TArray(parseSpec(typeSpec)); }
exports.array = array;
var TArray = /** @class */ (function (_super) {
__extends(TArray, _super);
function TArray(ttype) {
var _this = _super.call(this) || this;
_this.ttype = ttype;
return _this;
}
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 (var i = 0; i < value.length; i++) {
var ok = itemChecker(value[i], ctx);
if (!ok) {
return ctx.fail(i, null, 1);
}
}
return true;
};
};
return TArray;
}(TType));
exports.TArray = TArray;
/**
* Defines a tuple type, e.g. tuple('string', 'number').
*/
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;
var TTuple = /** @class */ (function (_super) {
__extends(TTuple, _super);
function TTuple(ttypes) {
var _this = _super.call(this) || this;
_this.ttypes = ttypes;
return _this;
}
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 (var i = 0; i < itemCheckers.length; i++) {
var ok = itemCheckers[i](value[i], ctx);
if (!ok) {
return ctx.fail(i, null, 1);
}
}
return true;
};
if (!strict) {
return checker;
}
return function (value, ctx) {
if (!checker(value, ctx)) {
return false;
}
return value.length <= itemCheckers.length ? true :
ctx.fail(itemCheckers.length, "is extraneous", 2);
};
};
return TTuple;
}(TType));
exports.TTuple = TTuple;
/**
* Defines a union type, e.g. union('number', 'null').
*/
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;
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");
}
_this._failMsg = "is none of " + names.join(", ");
}
else {
_this._failMsg = "is none of " + otherTypes + " types";
}
return _this;
}
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) {
return true;
}
}
ctx.resolveUnion(ur);
return ctx.fail(null, _this._failMsg, 0);
};
};
return TUnion;
}(TType));
exports.TUnion = TUnion;
/**
* Defines an intersection type, e.g. intersection('number', 'null').
*/
function intersection() {
var typeSpec = [];
for (var _i = 0; _i < arguments.length; _i++) {
typeSpec[_i] = arguments[_i];
}
return new TIntersection(typeSpec.map(function (t) { return parseSpec(t); }));
}
exports.intersection = intersection;
var TIntersection = /** @class */ (function (_super) {
__extends(TIntersection, _super);
function TIntersection(ttypes) {
var _this = _super.call(this) || this;
_this.ttypes = ttypes;
return _this;
}
TIntersection.prototype.getChecker = function (suite, strict) {
var allowedProps = new Set();
var itemCheckers = this.ttypes.map(function (t) { return t.getChecker(suite, strict, allowedProps); });
return function (value, ctx) {
var ok = itemCheckers.every(function (checker) { return checker(value, ctx); });
if (ok) {
return true;
}
return ctx.fail(null, null, 0);
};
};
return TIntersection;
}(TType));
exports.TIntersection = TIntersection;
/**
* Defines an enum type, e.g. enum({'A': 1, 'B': 2}).
*/
function enumtype(values) {
return new TEnumType(values);
}
exports.enumtype = enumtype;
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;
}
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;
/**
* Defines a literal enum value, such as Direction.Up, specified as enumlit("Direction", "Up").
*/
function enumlit(name, prop) {
return new TEnumLiteral(name, prop);
}
exports.enumlit = enumlit;
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;
}
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");
}
var val = ttype.members[this.prop];
if (!ttype.members.hasOwnProperty(this.prop)) {
throw new Error("Unknown value " + this.enumName + "." + this.prop + " used in enumlit");
}
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(function (name) { return makeIfaceProp(name, props[name]); });
}
function makeIfaceProp(name, prop) {
return prop instanceof TOptional ?
new TProp(name, prop.ttype, true) :
new TProp(name, parseSpec(prop), false);
}
/**
* Defines an interface. The first argument is an array of interfaces that it extends, and the
* second is an array of properties.
*/
function iface(bases, props) {
return new TIface(bases, makeIfaceProps(props));
}
exports.iface = iface;
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;
}
TIface.prototype.getChecker = function (suite, strict, allowedProps) {
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.
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 (var i = 0; i < baseCheckers.length; i++) {
if (!baseCheckers[i](value, ctx)) {
return false;
}
}
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_1, "is missing", 1);
}
}
else {
var ok = propCheckers[i](v, ctx);
if (!ok) {
return ctx.fail(name_1, null, 1);
}
}
}
return true;
};
if (!strict) {
return checker;
}
var propSet = this.propSet;
if (allowedProps) {
this.propSet.forEach(function (prop) { return allowedProps.add(prop); });
propSet = allowedProps;
}
// In strict mode, check also for unknown enumerable properties.
return function (value, ctx) {
if (!checker(value, ctx)) {
return false;
}
for (var prop in value) {
if (!propSet.has(prop)) {
return ctx.fail(prop, "is extraneous", 2);
}
}
return true;
};
};
return TIface;
}(TType));
exports.TIface = TIface;
/**
* Defines an optional property on an interface.
*/
function opt(typeSpec) { return new TOptional(parseSpec(typeSpec)); }
exports.opt = opt;
var TOptional = /** @class */ (function (_super) {
__extends(TOptional, _super);
function TOptional(ttype) {
var _this = _super.call(this) || this;
_this.ttype = ttype;
return _this;
}
TOptional.prototype.getChecker = function (suite, strict) {
var itemChecker = this.ttype.getChecker(suite, strict);
return function (value, ctx) {
return value === undefined || itemChecker(value, ctx);
};
};
return TOptional;
}(TType));
exports.TOptional = TOptional;
/**
* Defines a property in an interface.
*/
var TProp = /** @class */ (function () {
function TProp(name, ttype, isOpt) {
this.name = name;
this.ttype = ttype;
this.isOpt = isOpt;
}
return TProp;
}());
exports.TProp = TProp;
/**
* Defines a function. The first argument declares the function's return type, the rest declare
* its parameters.
*/
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;
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;
}
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;
/**
* Defines a function parameter.
*/
function param(name, typeSpec, isOpt) {
return new TParam(name, parseSpec(typeSpec), Boolean(isOpt));
}
exports.param = param;
var TParam = /** @class */ (function () {
function TParam(name, ttype, isOpt) {
this.name = name;
this.ttype = ttype;
this.isOpt = isOpt;
}
return TParam;
}());
exports.TParam = TParam;
/**
* Defines a function parameter list.
*/
var TParamList = /** @class */ (function (_super) {
__extends(TParamList, _super);
function TParamList(params) {
var _this = _super.call(this) || this;
_this.params = params;
return _this;
}
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 (var i = 0; i < itemCheckers.length; i++) {
var p = _this.params[i];
if (value[i] === undefined) {
if (isParamRequired[i]) {
return ctx.fail(p.name, "is missing", 1);
}
}
else {
var ok = itemCheckers[i](value[i], ctx);
if (!ok) {
return ctx.fail(p.name, null, 1);
}
}
}
return true;
};
if (!strict) {
return checker;
}
return function (value, ctx) {
if (!checker(value, ctx)) {
return false;
}
return value.length <= itemCheckers.length ? true :
ctx.fail(itemCheckers.length, "is extraneous", 2);
};
};
return TParamList;
}(TType));
exports.TParamList = TParamList;
/**
* Single TType implementation for all basic built-in types.
*/
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;
}
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;
/**
* Defines the suite of basic types.
*/
exports.basicTypes = {
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"),
Date: new BasicType(getIsNativeChecker("[object Date]"), "is not a Date"),
RegExp: new BasicType(getIsNativeChecker("[object RegExp]"), "is not a RegExp"),
};
// This approach for checking native object types mirrors that of lodash. Its advantage over
// `isinstance` is that it can still return true for native objects created in different JS
// execution environments.
var nativeToString = Object.prototype.toString;
function getIsNativeChecker(tag) {
return function (v) { return typeof v === "object" && v && nativeToString.call(v) === tag; };
}
if (typeof Buffer !== "undefined") {
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 (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);
}