container.ts
Version:
Modular application framework
239 lines • 9.66 kB
JavaScript
;
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 });
var error_1 = require("../error");
var Field_1 = require("./Field");
/** Schema error class. */
var SchemaError = /** @class */ (function (_super) {
__extends(SchemaError, _super);
function SchemaError(keys, cause) {
return _super.call(this, { name: "SchemaError", value: keys }, cause) || this;
}
return SchemaError;
}(error_1.ErrorChain));
exports.SchemaError = SchemaError;
/** Build schema class from input map. */
function buildSchema(schema) {
if (schema === void 0) { schema = {}; }
var NewSchema = /** @class */ (function (_super) {
__extends(NewSchema, _super);
function NewSchema() {
return _super !== null && _super.apply(this, arguments) || this;
}
NewSchema.SCHEMA = schema;
return NewSchema;
}(Schema));
return NewSchema;
}
exports.buildSchema = buildSchema;
var Schema = /** @class */ (function () {
function Schema() {
}
/**
* Returns true if value is a Schema class object.
* Used to test for child schemas during validation/formatting.
*/
Schema.isSchema = function (value) {
var isFunction = (typeof value === "function");
var hasSchemaProperty = (value.SCHEMA != null);
return (isFunction && hasSchemaProperty);
};
/**
* Helper for iterating over schema fields.
*/
Schema.map = function (inp, out, schema, mask, dataKeys, keyRoot, handlers) {
if (mask === void 0) { mask = null; }
if (dataKeys === void 0) { dataKeys = []; }
if (keyRoot === void 0) { keyRoot = ""; }
if (handlers === void 0) { handlers = {}; }
if (Array.isArray(schema)) {
var schemaArray_1 = schema;
if (schemaArray_1[0] === "*") {
// Wildcard asterisk, map all data indexes to field.
dataKeys.map(function (key) {
Schema.mapHandler(inp, out, mask, keyRoot, handlers, schemaArray_1[1], key);
});
}
else {
// Else for each value in schema array.
schemaArray_1.map(function (value, index) {
Schema.mapHandler(inp, out, mask, keyRoot, handlers, value, index);
});
}
}
else {
var schemaMap_1 = schema;
if (schemaMap_1["*"] != null) {
// If wildcard asterisk is present, map all data keys to field.
dataKeys.map(function (key) {
Schema.mapHandler(inp, out, mask, keyRoot, handlers, schemaMap_1["*"], key);
});
}
else {
// Else for each key in schema map.
Object.keys(schemaMap_1).map(function (key) {
Schema.mapHandler(inp, out, mask, keyRoot, handlers, schemaMap_1[key], key);
});
}
}
};
/**
* Validate input data, transform strings to typed values.
* All static validation rules are applied, undefined data validation
* callbacks must provide a default value, null or throw an error.
* @param data Input data.
*/
Schema.validate = function (data, mask, keyRoot, schema) {
if (keyRoot === void 0) { keyRoot = ""; }
if (schema === void 0) { schema = this.SCHEMA; }
var validated = Array.isArray(schema) ? [] : {};
Schema.map(data, validated, schema, mask, Object.keys(data || {}), keyRoot, Schema.validateMapHandlers);
return validated;
};
/**
* Format input data, transform typed values to object of strings for serialisation.
* Classes static format rules are applied where data is available.
* @param data Input data.
*/
Schema.format = function (data, mask, keyRoot, schema) {
if (keyRoot === void 0) { keyRoot = ""; }
if (schema === void 0) { schema = this.SCHEMA; }
var formatted = Array.isArray(schema) ? [] : {};
Schema.map(data, formatted, schema, mask, Object.keys(data || {}), keyRoot, Schema.formatMapHandlers);
return formatted;
};
/** Internal schema map handler. */
Schema.mapHandler = function (inp, out, mask, keyRoot, handlers, value, key) {
// Expand key root.
var subkeyRoot = keyRoot + "." + key;
// Handle masked fields if defined.
var submask;
if (mask != null) {
if (!mask[key]) {
// Field(s) are masked.
return;
}
else if (typeof mask[key] === "object") {
// Subfield mask argument.
submask = mask[key];
}
}
try {
if (Schema.isSchema(value) && (!!handlers.isSchema)) {
// Value is child schema.
var childSchema = value;
handlers.isSchema(inp, out, childSchema, key, submask, subkeyRoot);
}
else if ((value instanceof Field_1.Field) && (!!handlers.isField)) {
// Value is field class instance.
var field = value;
handlers.isField(inp, out, field, key);
}
else if (Array.isArray(value) && (!!handlers.isSchemaArray)) {
// Value is a schema array object.
var schemaArray = value;
handlers.isSchemaArray(inp, out, schemaArray, key, submask, subkeyRoot);
}
else if ((typeof value === "object") && (!!handlers.isSchemaMap)) {
// Value is schema map object.
var schemaMap = value;
handlers.isSchemaMap(inp, out, schemaMap, key, submask, subkeyRoot);
}
else if ((typeof value === "string") && (value === "*")) {
// Wildcard asterisk, accept all data.
out[key] = inp[key];
}
else {
// Unknown schema field value.
throw new SchemaError(subkeyRoot, value);
}
}
catch (error) {
// Schema error wrapper.
if (error instanceof SchemaError) {
throw error;
}
else {
throw new SchemaError(subkeyRoot, error);
}
}
};
/** Schema array or map, override in child classes. */
Schema.SCHEMA = {};
Schema.validateMapHandlers = {
isSchemaArray: function (inp, out, array, key, submask, keyRoot) {
// Make recursive call for internal data arrays.
// Only assign output if array has length.
var output = Schema.validate(inp[key], submask, keyRoot, array);
if (output.length > 0) {
out[key] = output;
}
},
isSchemaMap: function (inp, out, map, key, submask, keyRoot) {
// Make recursive call for internal data maps.
// Only assign output if at least one field validated.
var output = Schema.validate(inp[key], submask, keyRoot, map);
if (Object.keys(output).length > 0) {
out[key] = output;
}
},
isSchema: function (inp, out, schema, key, submask, keyRoot) {
// Call static method of child schema.
// Only assign output if at least one field validated.
var output = schema.validate(inp[key], submask, keyRoot);
if (Object.keys(output).length > 0) {
out[key] = output;
}
},
isField: function (inp, out, field, key) {
// Call validate method of field.
// Only assign output if defined.
var output = field.validate(inp[key]);
if (output != null) {
out[key] = output;
}
},
};
Schema.formatMapHandlers = {
isSchemaArray: function (inp, out, array, key, submask, keyRoot) {
// Make recursive call for internal data arrays.
var output = Schema.format(inp[key], submask, keyRoot, array);
if (output.length > 0) {
out[key] = output;
}
},
isSchemaMap: function (inp, out, map, key, submask, keyRoot) {
// Make recursive call for internal data maps.
var output = Schema.format(inp[key], submask, keyRoot, map);
if (Object.keys(output).length > 0) {
out[key] = output;
}
},
isSchema: function (inp, out, schema, key, submask, keyRoot) {
// Call static method if child schema.
var output = schema.format(inp[key], submask, keyRoot);
if (Object.keys(output).length > 0) {
out[key] = output;
}
},
isField: function (inp, out, field, key) {
// Call format method of field.
var output = field.format(inp[key]);
if (output != null) {
out[key] = output;
}
},
};
return Schema;
}());
exports.Schema = Schema;
//# sourceMappingURL=Schema.js.map