UNPKG

model-layer

Version:
195 lines 6.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Type = void 0; const errors_1 = require("../errors"); const utils_1 = require("../utils"); const FORBIDDEN_PRIMARY_KEYS = [ "row", "primaryKey", "primaryValue" ]; const Types = {}; class Type { constructor(params) { this.const = false; if (params.primary) { this.primary = true; } this.type = params.type; this.required = params.required || params.primary || false; if (Array.isArray(params.enum)) { this.enum = params.enum; } // default can be: false, 0, or function if ("default" in params) { if (typeof params.default === "function") { this.default = params.default; } else { this.default = () => params.default; } } // custom prepare not null value, after default prepare if (typeof params.prepare === "function") { const prepareByType = this.prepare.bind(this); const customPrepare = params.prepare; this.prepare = (value, key, model) => { value = prepareByType(value, key, model); if (value != null) { value = customPrepare(value, key, model); } return value; }; } if (typeof params.toJSON === "function") { this.toJSON = params.toJSON; } // custom validate by RegExp or function if ("validate" in params) { // validate by required, enum, "unique" (ArrayType) const validateByType = this.validate.bind(this); if (typeof params.validate === "function") { const customValidate = params.validate; this.validate = (value, modelKey) => { return (validateByType(value, modelKey) && (value == null || customValidate(value, modelKey))); }; } else if (params.validate instanceof RegExp) { const regExp = params.validate; this.validate = (value, modelKey) => { return (validateByType(value, modelKey) && (value == null || regExp.test(value))); }; } else { throw new errors_1.InvalidValidationError({ invalidValue: utils_1.invalidValuesAsString(params.validate) }); } } // validate key for models with "*" if ("key" in params) { const customValidateKey = params.key; if (customValidateKey instanceof RegExp) { this.validateKey = (modelKey) => { return customValidateKey.test(modelKey); }; } else if (typeof customValidateKey === "function") { this.validateKey = customValidateKey; } else { throw new errors_1.InvalidKeyValidationError({ invalidValue: utils_1.invalidValuesAsString(customValidateKey) }); } } // don't change value if (params.const) { this.const = true; } if (params.clone) { this.clone = params.clone; } if (params.equal) { this.equal = params.equal; } } static registerType(name, SomeType) { Types[name] = SomeType; } // create type by params static create(description, key) { const isTypeHelper = (typeof description === "function" && description.isTypeHelper === true); if (isTypeHelper) { description = description(); } const isPlainDescription = (description && description.type); // structure: {prop: "number"} // or // structure: {prop: ["number"]} // or // structure: {prop: SomeModel} // or // structure: {prop: {}} if (!isPlainDescription) { description = { type: description }; } // prepare description: ["string"] // to { type: "array", element: {type: "string"} } for (const typeName in Types) { const SomeType = Types[typeName]; // CustomType can use some variations for declare structure SomeType.prepareDescription(description, key); } // find CustomType by name const CustomType = Types[description.type]; if (!CustomType) { throw new errors_1.UnknownTypeError({ key, type: description.type }); } if (description.primary) { const Model = Type.Model; const isReserved = (key in Model.prototype || FORBIDDEN_PRIMARY_KEYS.includes(key)); if (isReserved) { throw new errors_1.ReservedWordForPrimaryKeyError({ key }); } } try { description = new CustomType(description); } catch (err) { err.message = key + ": " + err.message; throw err; } // structure must be static Object.freeze(description); return description; } // default behavior static prepareDescription(description, key) { // redefine me return description; } default() { return null; } validateKey(key) { return true; } validate(value, key) { if (this.enum) { if (value != null) { return this.enum.includes(value); } } return true; } prepare(value, key, model) { return value; } toJSON(value, stack) { return value; } clone(value, stack, parentModel) { return this.toJSON(value, stack); } typeAsString() { return this.type; } equal(selfValue, otherValue, stack) { return selfValue === otherValue; } } exports.Type = Type; //# sourceMappingURL=Type.js.map