model-layer
Version:
195 lines • 6.31 kB
JavaScript
"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