container.ts
Version:
Modular application framework
249 lines • 10.6 kB
JavaScript
;
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 __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
Object.defineProperty(exports, "__esModule", { value: true });
var lodash_1 = require("lodash");
var error_1 = require("../error");
var field_1 = require("./field");
/** Schema error codes. */
var ESchemaError;
(function (ESchemaError) {
ESchemaError["Field"] = "SchemaError.Field";
ESchemaError["Value"] = "SchemaError.Value";
})(ESchemaError = exports.ESchemaError || (exports.ESchemaError = {}));
/** Schema error class. */
var SchemaError = /** @class */ (function (_super) {
__extends(SchemaError, _super);
function SchemaError(code, cause, context) {
var _this = _super.call(this, { name: "SchemaError", value: __assign({ code: code }, context) }, cause) || this;
_this.isSchemaError = true;
return _this;
}
return SchemaError;
}(error_1.ErrorChain));
exports.SchemaError = SchemaError;
var Schema = /** @class */ (function () {
function Schema(schema) {
this.schema = schema;
/** Used for isSchema static method. */
this.isSchema = true;
}
/** Returns true if input instance of Schema. */
Schema.isSchema = function (schema) {
var instanceOf = schema instanceof Schema;
var hasProperty = !!schema.isSchema;
return instanceOf || hasProperty;
};
/** Returns true if input instance of SchemaError. */
Schema.isSchemaError = function (error) {
var instanceOf = error instanceof SchemaError;
var hasProperty = !!error.isSchemaError;
return instanceOf || hasProperty;
};
/**
* Construct new schema by merging existing schemas.
* Accepts schema definition objects or existing Schema class instances.
*/
Schema.extend = function () {
var schemas = [];
for (var _i = 0; _i < arguments.length; _i++) {
schemas[_i] = arguments[_i];
}
var schemaDefinitions = schemas.map(function (s) {
return Schema.isSchema(s) ? s.schema : s;
});
return new Schema(lodash_1.assign.apply(void 0, __spreadArrays([{}], schemaDefinitions)));
};
/**
* Construct new schema using this as a base.
* Accepts schema definition objects or existing Schema class instances.
*/
Schema.prototype.extend = function () {
var schemas = [];
for (var _i = 0; _i < arguments.length; _i++) {
schemas[_i] = arguments[_i];
}
return Schema.extend.apply(Schema, __spreadArrays([this.schema], schemas));
};
/** Validate input data, transform strings to typed values. */
Schema.prototype.validate = function (data, mask, parentKey, schema) {
if (parentKey === void 0) { parentKey = ""; }
if (schema === void 0) { schema = this.schema; }
var validated = lodash_1.isArray(schema) ? [] : {};
this.map(data, validated, schema, Schema.mapValidateHandlers, mask, parentKey);
return validated;
};
/** Format input data, transform typed values to object of strings for serialisation. */
Schema.prototype.format = function (data, mask, parentKey, schema) {
if (parentKey === void 0) { parentKey = ""; }
if (schema === void 0) { schema = this.schema; }
var formatted = lodash_1.isArray(schema) ? [] : {};
this.map(data, formatted, schema, Schema.mapFormatHandlers, mask, parentKey);
return formatted;
};
/** Helper for iterating over schema fields. */
Schema.prototype.map = function (input, output, schema, handlers, mask, parentKey) {
var _this = this;
if (parentKey === void 0) { parentKey = ""; }
if (lodash_1.isArray(schema)) {
var schemaArray_1 = schema;
if (schemaArray_1[0] === "*") {
// Wildcard asterisk, map all data indexes to field.
lodash_1.keys(input).map(function (key) { return _this.mapHandler(input, output, mask, parentKey, handlers, schemaArray_1[1], key); });
}
else {
// Else for each value in schema array.
schemaArray_1.map(function (value, index) { return _this.mapHandler(input, output, mask, parentKey, handlers, value, index); });
}
}
else {
var schemaMap_1 = schema;
if (schemaMap_1["*"] != null) {
// If wildcard asterisk is present, map all data keys to field.
lodash_1.keys(input).map(function (key) { return _this.mapHandler(input, output, mask, parentKey, handlers, schemaMap_1["*"], key); });
}
else {
// Else for each key in schema map.
lodash_1.keys(schemaMap_1).map(function (key) { return _this.mapHandler(input, output, mask, parentKey, handlers, schemaMap_1[key], key); });
}
}
};
Schema.prototype.mapHandler = function (input, output, mask, parentKey, handlers, value, key) {
// Key path construction for error messages.
var path = parentKey + "." + key;
// Handle masked fields if defined.
var mapMask;
if (mask != null) {
if (!lodash_1.get(mask, key, false)) {
// Field(s) are masked.
return;
}
else if (lodash_1.isObject(mask[key])) {
// Map mask argument.
mapMask = mask[key];
}
}
try {
if (value instanceof field_1.Field) {
// Value is field class instance.
var field = value;
handlers.isField(input, output, field, key, mapMask, path);
}
else if (lodash_1.isArray(value)) {
// Value is a schema array object.
var schemaArray = value;
handlers.isSchemaArray(input, output, this, schemaArray, key, mapMask, path);
}
else if (lodash_1.isObject(value)) {
// Value is schema map object.
var schemaMap = value;
handlers.isSchemaMap(input, output, this, schemaMap, key, mapMask, path);
}
else if (value === "*") {
// Wildcard asterisk, accept all data.
output[key] = input[key];
}
else {
// Invalid schema field value.
throw new SchemaError(ESchemaError.Value, value, { path: path });
}
}
catch (error) {
// Schema error wrapper.
if (Schema.isSchemaError(error)) {
throw error;
}
else {
throw new SchemaError(ESchemaError.Field, error, { path: path });
}
}
};
Schema.mapValidateHandlers = {
isSchemaArray: function (input, output, schema, array, key, mask, parentKey) {
// Make recursive call for internal data arrays.
output[key] = schema.validate(input[key], mask, parentKey, array);
},
isSchemaMap: function (input, output, schema, map, key, mask, parentKey) {
// Make recursive call for internal data maps.
output[key] = schema.validate(input[key], mask, parentKey, map);
},
isField: function (input, output, field, key, mask, parentKey) {
// Call validate method of field, only assign output if defined.
var validated = field.validate(input[key], { mask: mask, parentKey: parentKey });
if (validated != null) {
output[key] = validated;
}
}
};
Schema.mapFormatHandlers = {
isSchemaArray: function (input, output, schema, array, key, mask, parentKey) {
// Make recursive call for internal data arrays.
output[key] = schema.format(input[key], mask, parentKey, array);
},
isSchemaMap: function (input, output, schema, map, key, mask, parentKey) {
// Make recursive call for internal data maps.
output[key] = schema.format(input[key], mask, parentKey, map);
},
isField: function (input, output, field, key, mask, keyRoot) {
// Call format method of field.
var formatted = field.format(input[key], { mask: mask, keyRoot: keyRoot });
if (formatted != null) {
output[key] = formatted;
}
}
};
return Schema;
}());
exports.Schema = Schema;
var SchemaField = /** @class */ (function (_super) {
__extends(SchemaField, _super);
function SchemaField(instanceOrSchema) {
var _this = _super.call(this) || this;
if (Schema.isSchema(instanceOrSchema)) {
_this.schema = instanceOrSchema;
}
else {
_this.schema = new Schema(instanceOrSchema);
}
return _this;
}
SchemaField.prototype.validate = function (value, context) {
if (context === void 0) { context = {}; }
return this.schema.validate(value, context.mask, context.parentKey);
};
SchemaField.prototype.format = function (value, context) {
return this.schema.format(value, context.mask, context.parentKey);
};
return SchemaField;
}(field_1.Field));
exports.SchemaField = SchemaField;
//# sourceMappingURL=schema.js.map