type-transformer
Version:
Transformation / serialization / deserialization of plain JavaScript objects to typed objects and vice versa
862 lines (846 loc) • 34.8 kB
JavaScript
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
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);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
function __values(o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
}
var Direction;
(function (Direction) {
Direction["PLAIN_TO_TYPED"] = "PLAIN_TO_TYPED";
Direction["TYPED_TO_PLAIN"] = "TYPED_TO_PLAIN";
})(Direction || (Direction = {}));
var Visibility;
(function (Visibility) {
Visibility["EXPOSE"] = "EXPOSE";
Visibility["EXCLUDE"] = "EXCLUDE";
})(Visibility || (Visibility = {}));
var Selectable = /** @class */ (function () {
function Selectable() {
this.selectors = [];
}
/**
* Add a select function, possibly with options, that is asked if this
* selectable should be selected for a transformation.
* @param selector A function that is passed the object to be transformed,
* the transformation direction and the options. So the
* options can be used to prametrize the function.
* @param options An object implementing SelectOptions.
*/
Selectable.prototype.addSelector = function (selector, options) {
this.selectors.push([selector, options]);
};
/**
* Is this selectable to be selected for the given object and direction?
* @returns either `Visibility.EXPOSE` or `Visibility.EXCLUDE` if there
* is an explicit answer, `undefined` otherwise.
*/
Selectable.prototype.selected = function (obj, direction) {
var e_1, _a;
var decision = this.defaultVisibility;
try {
for (var _b = __values(this.selectors), _c = _b.next(); !_c.done; _c = _b.next()) {
var _d = __read(_c.value, 2), selectFn = _d[0], options = _d[1];
if (!options || this.doesSelectorApply(obj, direction, options)) {
if (!selectFn(obj, direction, options)) {
return Visibility.EXCLUDE;
}
decision = Visibility.EXPOSE;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
return decision;
};
Selectable.prototype.doesSelectorApply = function (obj, direction, options) {
if (options.toPlainOnly && direction !== Direction.TYPED_TO_PLAIN) {
return false;
}
if (options.toTypedOnly && direction !== Direction.PLAIN_TO_TYPED) {
return false;
}
return true;
};
return Selectable;
}());
var AlwaysExpose = function () { return true; }; // tslint:disable-line variable-name
var AlwaysExclude = function () { return false; }; // tslint:disable-line variable-name
var Schema = /** @class */ (function () {
function Schema(registry, type) {
this.registry = registry;
this.type = type;
this.inherits = false;
this._fields = new Map();
this._postProcessors = [];
}
Schema.prototype.getField = function (fieldName) {
var field = this._fields.get(fieldName);
if (!field) {
field = new Field(fieldName);
this._fields.set(fieldName, field);
}
return field;
};
Object.defineProperty(Schema.prototype, "defaultVisibility", {
get: function () {
if (this._defaultVisibility) {
return this._defaultVisibility;
}
if (this.inherits) {
var parent_1 = this.getAncestor();
if (parent_1) {
return parent_1.defaultVisibility;
}
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(Schema.prototype, "fields", {
/**
* Get all fields defined in this schema and its ancestors as an iterator.
*/
get: function () {
var e_1, _a, e_2, _b;
if (!this.inherits) {
return this._fields.values();
}
var allFields = new Map();
try {
for (var _c = __values(this.inheritanceChain()), _d = _c.next(); !_d.done; _d = _c.next()) {
var member = _d.value;
try {
for (var _e = __values(member._fields.values()), _f = _e.next(); !_f.done; _f = _e.next()) {
var field = _f.value;
if (!allFields.has(field.name)) {
allFields.set(field.name, field);
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_f && !_f.done && (_b = _e.return)) _b.call(_e);
}
finally { if (e_2) throw e_2.error; }
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_1) throw e_1.error; }
}
return allFields.values();
},
enumerable: true,
configurable: true
});
Schema.prototype.excludeAll = function () {
this._defaultVisibility = Visibility.EXCLUDE;
return this;
};
Schema.prototype.exposeAll = function () {
this._defaultVisibility = Visibility.EXPOSE;
return this;
};
Schema.prototype.inherit = function () {
this.inherits = true;
return this;
};
Schema.prototype.postProcess = function (postProcessFn, options) {
this._postProcessors.push(new ObjectTransformer(postProcessFn, options));
return this;
};
Schema.prototype.getPostProcessors = function (obj, direction) {
return this._postProcessors
.filter(function (postProcessor) {
var visibility = postProcessor.selected(obj, direction);
// if there is no explicit visibility we do the transform
return !visibility || visibility === Visibility.EXPOSE;
});
};
/**
* Get a list of all schemas in the inheritance chain of this schema (including itself).
*/
Schema.prototype.inheritanceChain = function () {
var parentSchema;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
parentSchema = this;
_a.label = 1;
case 1: return [4 /*yield*/, parentSchema];
case 2:
_a.sent();
_a.label = 3;
case 3:
if (parentSchema = parentSchema.getAncestor()) return [3 /*break*/, 1];
_a.label = 4;
case 4: return [2 /*return*/];
}
});
};
/**
* Get the nearest ancestor schema.
*/
Schema.prototype.getAncestor = function () {
var parentType = this.type;
var parentSchema;
while (Object.prototype !== (parentType = Object.getPrototypeOf(parentType))) {
parentSchema = this.registry.getSchema(parentType);
if (parentSchema) {
return parentSchema;
}
}
};
return Schema;
}());
var Field = /** @class */ (function (_super) {
__extends(Field, _super);
function Field(name) {
var _this = _super.call(this) || this;
_this.name = name;
_this._transformers = [];
return _this;
}
Field.prototype.select = function (selectFn) {
this.addSelector(selectFn);
return this;
};
Field.prototype.exclude = function (options) {
this.addSelector(AlwaysExclude, options);
return this;
};
Field.prototype.expose = function (options) {
this.addSelector(AlwaysExpose, options);
if (options) {
this._propName = options.propName;
}
return this;
};
Field.prototype.nested = function (type) {
this.nestedType = type;
return this;
};
Field.prototype.transform = function (transformFn, options) {
var transformer = new ValueTransformer(transformFn, options);
this._transformers.push(transformer);
return this;
};
Field.prototype.getValueTransformers = function (obj, direction) {
return this._transformers
.filter(function (transformer) {
var visibility = transformer.selected(obj, direction);
// if there is no explicit visibility we do the transform
return !visibility || visibility === Visibility.EXPOSE;
});
};
Object.defineProperty(Field.prototype, "propName", {
get: function () {
return this._propName || this.name;
},
enumerable: true,
configurable: true
});
return Field;
}(Selectable));
var Transformer = /** @class */ (function (_super) {
__extends(Transformer, _super);
function Transformer(transformFn, options) {
var _this = _super.call(this) || this;
_this.transformFn = transformFn;
if (options) {
_this.addSelector(AlwaysExpose, options);
// if we have options, we don't want the transformation if the
// conditions in the options are not met
_this.defaultVisibility = Visibility.EXCLUDE;
}
return _this;
}
Transformer.prototype.transform = function (inValue, targetObj, direction) {
return this.transformFn(inValue, targetObj, direction);
};
return Transformer;
}(Selectable));
var ValueTransformer = /** @class */ (function (_super) {
__extends(ValueTransformer, _super);
function ValueTransformer() {
return _super !== null && _super.apply(this, arguments) || this;
}
return ValueTransformer;
}(Transformer));
var ObjectTransformer = /** @class */ (function (_super) {
__extends(ObjectTransformer, _super);
function ObjectTransformer() {
return _super !== null && _super.apply(this, arguments) || this;
}
return ObjectTransformer;
}(Transformer));
var SchemaRegistry = /** @class */ (function () {
function SchemaRegistry() {
this.schemasByType = new Map();
}
SchemaRegistry.prototype.getOrCreateSchema = function (type) {
var schema = this.schemasByType.get(type);
if (!schema) {
schema = new Schema(this, type);
this.schemasByType.set(type, schema);
}
return schema;
};
SchemaRegistry.prototype.getSchema = function (type) {
return this.schemasByType.get(type);
};
SchemaRegistry.prototype.clear = function () {
this.schemasByType.clear();
};
return SchemaRegistry;
}());
var defaultSchemaRegistry = new SchemaRegistry();
var CircularRefStrategy;
(function (CircularRefStrategy) {
CircularRefStrategy["NONE"] = "NONE";
CircularRefStrategy["BREAK"] = "BREAK";
CircularRefStrategy["RESOLVE"] = "RESOLVE";
CircularRefStrategy["ERROR"] = "ERROR"; // throw an Error when a circular reference is detected
})(CircularRefStrategy || (CircularRefStrategy = {}));
var ReferenceNode = /** @class */ (function () {
function ReferenceNode(object, referencedBy) {
this.object = object;
this.referencedBy = new Map();
if (referencedBy) {
this.referencedBy.set(referencedBy.object, referencedBy);
}
}
/**
* Checks if the object of this node is referenced by the given object.
*/
ReferenceNode.prototype.isReferencedBy = function (object) {
var e_1, _a;
if (this.referencedBy.has(object)) {
return true;
}
try {
for (var _b = __values(this.referencedBy.values()), _c = _b.next(); !_c.done; _c = _b.next()) {
var reference = _c.value;
if (reference.isReferencedBy(object)) {
return true;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
return false;
};
/**
* Gets the object that references the given one, if any.
*/
ReferenceNode.prototype.getReferencing = function (object) {
var e_2, _a;
if (this.referencedBy.has(object)) {
return this.referencedBy.get(object).targetObject;
}
try {
for (var _b = __values(this.referencedBy.values()), _c = _b.next(); !_c.done; _c = _b.next()) {
var reference = _c.value;
var referencing = reference.getReferencing(object);
if (referencing) {
return referencing;
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_2) throw e_2.error; }
}
};
ReferenceNode.prototype.addReferencer = function (node) {
this.referencedBy.set(node.object, node);
};
return ReferenceNode;
}());
var ReferenceGraph = /** @class */ (function () {
function ReferenceGraph(circularStrategy) {
this.nodeStack = [];
this.allNodes = new Map();
this.circularStrategy = CircularRefStrategy.BREAK;
if (circularStrategy) {
this.circularStrategy = circularStrategy;
}
}
Object.defineProperty(ReferenceGraph.prototype, "current", {
get: function () {
if (this.nodeStack.length) {
return this.nodeStack[this.nodeStack.length - 1];
}
},
enumerable: true,
configurable: true
});
/**
* Check if a value would introduce a circular dependency.
* If so, react according to the configured strategy (@see CircularRefStrategy).
* If not, call the @param handleValue() function.
* @param targetObject the (empty) object that is populated by handleValue
* @returns the result of either the handling of a circular dependency
* or the @param targetObject
*/
ReferenceGraph.prototype.preventCircularDependencies = function (value, targetObject, handleValue) {
if (this.circularStrategy !== CircularRefStrategy.NONE
&& this.isCircularReference(value)) {
return this.handleCircularReference(value);
}
else {
var refNode = this.descend(value);
refNode.targetObject = targetObject;
var result = handleValue();
this.ascend();
return result;
}
};
ReferenceGraph.prototype.descend = function (object) {
var currentNode = this.current;
var node = this.allNodes.get(object);
if (node && currentNode) {
node.addReferencer(currentNode);
}
else {
node = new ReferenceNode(object, currentNode);
this.allNodes.set(object, node);
}
this.nodeStack.push(node);
return node;
};
ReferenceGraph.prototype.ascend = function () {
this.nodeStack.pop();
};
ReferenceGraph.prototype.isCircularReference = function (referred) {
if (!this.allNodes.has(referred)) {
return false;
}
return this.current.isReferencedBy(referred);
};
ReferenceGraph.prototype.handleCircularReference = function (referred) {
switch (this.circularStrategy) {
case CircularRefStrategy.BREAK:
return undefined;
case CircularRefStrategy.ERROR:
throw new Error('A circular reference was detected.');
case CircularRefStrategy.RESOLVE:
return this.current.getReferencing(referred);
default:
throw new Error('Unkown strategy for handling circular references: '
+ this.circularStrategy);
}
};
return ReferenceGraph;
}());
var Transformer$1 = /** @class */ (function () {
function Transformer(options) {
this.options = options;
this.referenceGraph = new ReferenceGraph(options.circularRefStrategy);
}
Transformer.prototype.toPlain = function (typed, sourceType, existingTarget) {
var _this = this;
var value = typed;
if (typeof value === 'object' && value !== null) {
if (value.toJS) {
value = value.toJS();
}
var _a = __read(this.getTargetObject(value, undefined, existingTarget), 2), isArray_1 = _a[0], plain_1 = _a[1];
if (!sourceType && value.constructor !== Object) {
sourceType = value.constructor;
}
value = this.referenceGraph.preventCircularDependencies(value, plain_1, function () {
var e_1, _a, e_2, _b;
if (isArray_1) {
try {
for (var _c = __values(value), _d = _c.next(); !_d.done; _d = _c.next()) {
var subValue = _d.value;
subValue = _this.toPlain(subValue);
plain_1.push(subValue);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_1) throw e_1.error; }
}
}
else {
var fields = _this.getFields(Direction.TYPED_TO_PLAIN, value, sourceType);
try {
for (var fields_1 = __values(fields), fields_1_1 = fields_1.next(); !fields_1_1.done; fields_1_1 = fields_1.next()) {
var _e = __read(fields_1_1.value, 2), fieldName = _e[0], field = _e[1];
_this.applyFieldToPlain(value, plain_1, fieldName, field);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (fields_1_1 && !fields_1_1.done && (_b = fields_1.return)) _b.call(fields_1);
}
finally { if (e_2) throw e_2.error; }
}
}
return plain_1;
});
}
var schema = this.getSchema(sourceType);
value = this.postProcessObject(typed, value, Direction.TYPED_TO_PLAIN, schema);
return value;
};
Transformer.prototype.applyFieldToPlain = function (source, target, fieldName, field) {
var e_3, _a;
var propName = fieldName;
var subValue = source[fieldName];
if (subValue === undefined && this.options.skipUndefinedProperties) {
return;
}
if (typeof subValue === 'function') {
subValue = source[fieldName]();
}
if (field) {
propName = field.propName instanceof Function
? field.propName(source, Direction.TYPED_TO_PLAIN)
: field.propName;
var valueTransformers = field.getValueTransformers(source, Direction.TYPED_TO_PLAIN);
try {
for (var valueTransformers_1 = __values(valueTransformers), valueTransformers_1_1 = valueTransformers_1.next(); !valueTransformers_1_1.done; valueTransformers_1_1 = valueTransformers_1.next()) {
var valueTransformer = valueTransformers_1_1.value;
subValue = valueTransformer.transform(subValue, source, Direction.TYPED_TO_PLAIN);
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (valueTransformers_1_1 && !valueTransformers_1_1.done && (_a = valueTransformers_1.return)) _a.call(valueTransformers_1);
}
finally { if (e_3) throw e_3.error; }
}
}
subValue = this.toPlain(subValue);
target[propName] = subValue;
return target;
};
Transformer.prototype.toTyped = function (plain, targetType, existingTarget) {
var _this = this;
var value = plain;
if (typeof value === 'object' && value !== null) {
var _a = __read(this.getTargetObject(value, targetType, existingTarget), 2), isArray_2 = _a[0], target_1 = _a[1];
return this.referenceGraph.preventCircularDependencies(value, target_1, function () {
var e_4, _a, e_5, _b;
if (isArray_2) {
try {
for (var _c = __values(value), _d = _c.next(); !_d.done; _d = _c.next()) {
var subValue = _d.value;
subValue = _this.toTyped(subValue, targetType);
target_1.push(subValue);
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_4) throw e_4.error; }
}
}
else {
var fields = _this.getFields(Direction.PLAIN_TO_TYPED, value, targetType);
try {
for (var fields_2 = __values(fields), fields_2_1 = fields_2.next(); !fields_2_1.done; fields_2_1 = fields_2.next()) {
var _e = __read(fields_2_1.value, 2), fieldName = _e[0], field = _e[1];
target_1 = _this.applyFieldToTyped(value, target_1, fieldName, field);
}
}
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (fields_2_1 && !fields_2_1.done && (_b = fields_2.return)) _b.call(fields_2);
}
finally { if (e_5) throw e_5.error; }
}
}
return target_1;
});
}
var schema = this.getSchema(targetType);
value = this.postProcessObject(plain, value, Direction.PLAIN_TO_TYPED, schema);
return value;
};
Transformer.prototype.applyFieldToTyped = function (source, target, fieldName, field) {
var e_6, _a;
var propName = fieldName;
var subType;
if (field) {
propName = field.propName instanceof Function
? field.propName(source, Direction.TYPED_TO_PLAIN)
: field.propName;
subType = field.nestedType;
}
var subValue = source[propName];
if (field) {
var valueTransformers = field.getValueTransformers(source, Direction.PLAIN_TO_TYPED);
try {
for (var valueTransformers_2 = __values(valueTransformers), valueTransformers_2_1 = valueTransformers_2.next(); !valueTransformers_2_1.done; valueTransformers_2_1 = valueTransformers_2.next()) {
var valueTransformer = valueTransformers_2_1.value;
subValue = valueTransformer.transform(subValue, source, Direction.PLAIN_TO_TYPED);
}
}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
try {
if (valueTransformers_2_1 && !valueTransformers_2_1.done && (_a = valueTransformers_2.return)) _a.call(valueTransformers_2);
}
finally { if (e_6) throw e_6.error; }
}
}
subValue = this.toTyped(subValue, subType);
if (target.set && target.constructor.name === 'Map') {
target = target.set(fieldName, subValue);
}
else {
target[fieldName] = subValue;
}
return target;
};
Transformer.prototype.postProcessObject = function (source, target, direction, schema) {
var e_7, _a;
if (schema) {
var postProcessors = schema.getPostProcessors(source, direction);
try {
for (var postProcessors_1 = __values(postProcessors), postProcessors_1_1 = postProcessors_1.next(); !postProcessors_1_1.done; postProcessors_1_1 = postProcessors_1.next()) {
var postProcessor = postProcessors_1_1.value;
target = postProcessor.transform(source, target, direction);
}
}
catch (e_7_1) { e_7 = { error: e_7_1 }; }
finally {
try {
if (postProcessors_1_1 && !postProcessors_1_1.done && (_a = postProcessors_1.return)) _a.call(postProcessors_1);
}
finally { if (e_7) throw e_7.error; }
}
}
return target;
};
Transformer.prototype.getFields = function (direction, object, type) {
var e_8, _a;
var defaultVisibility = Visibility.EXPOSE;
var schema = this.getSchema(type);
if (schema && schema.defaultVisibility) {
defaultVisibility = schema.defaultVisibility;
}
var fields = new Map();
if (defaultVisibility === Visibility.EXPOSE) {
Object.keys(object).forEach(function (key) { return fields.set(key, undefined); });
}
if (schema) {
try {
for (var _b = __values(schema.fields), _c = _b.next(); !_c.done; _c = _b.next()) {
var field = _c.value;
var fieldVisibility = field.selected(object, direction) || defaultVisibility;
if (fieldVisibility === Visibility.EXPOSE) {
fields.set(field.name, field);
}
else if (fieldVisibility === Visibility.EXCLUDE) {
fields.delete(field.name);
}
}
}
catch (e_8_1) { e_8 = { error: e_8_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_8) throw e_8.error; }
}
}
return fields;
};
Transformer.prototype.getSchema = function (type) {
return type ? this.options.registry.getSchema(type) : undefined;
};
/**
* Get the (empty) object to put the source values on.
* @param value The source value
* @param targetType The optional type of the target
* @param existingTarget An object that should be used as target
*/
Transformer.prototype.getTargetObject = function (value, targetType, existingTarget) {
var isArray = value instanceof Array || value instanceof Set;
var target = existingTarget ? existingTarget :
isArray ? [] :
targetType ? new targetType() :
{};
return [isArray, target];
};
return Transformer;
}());
/**
* Marks a property or class as included in the process of transformation.
*/
function expose(options) {
return function (object, propertyName) {
if (object instanceof Function) {
var schema = defaultSchemaRegistry.getOrCreateSchema(object);
schema.exposeAll();
}
else if (propertyName) {
var schema = defaultSchemaRegistry.getOrCreateSchema(object.constructor);
schema.getField(propertyName).expose(options);
}
};
}
/**
* Marks a property or class as excluded in the process of transformation.
*/
function exclude() {
return function (object, propertyName) {
if (object instanceof Function) {
var schema = defaultSchemaRegistry.getOrCreateSchema(object);
schema.excludeAll();
}
else if (propertyName) {
var schema = defaultSchemaRegistry.getOrCreateSchema(object.constructor);
schema.getField(propertyName).exclude();
}
};
}
/**
* Define a function that dynamically selects a property.
*/
function select(selectFn) {
return function (object, propertyName) {
if (propertyName) {
var schema = defaultSchemaRegistry.getOrCreateSchema(object.constructor);
schema.getField(propertyName).select(selectFn);
}
else {
throw 'Cannot use "@select" on a class.';
}
};
}
/**
* Creates a schema for a class that inherits from the schemas of the parent classes.
*/
function inherit() {
return function (object) {
var schema = defaultSchemaRegistry.getOrCreateSchema(object);
schema.inherit();
};
}
function createRegistry() {
return new SchemaRegistry();
}
function createSchema(type, registry) {
registry = registry || defaultSchemaRegistry;
return registry.getOrCreateSchema(type);
}
function typedToPlain(object, options, existingObject) {
var transformer = new Transformer$1(getOptions(options));
return transformer.toPlain(object, undefined, existingObject);
}
function plainToTyped(object, targetType, options, existingObject) {
var transformer = new Transformer$1(getOptions(options));
return transformer.toTyped(object, targetType, existingObject);
}
function getOptions(options) {
options = options || {};
if (!options.registry) {
options.registry = defaultSchemaRegistry;
}
return options;
}
export { createRegistry, createSchema, typedToPlain, plainToTyped, CircularRefStrategy, expose, exclude, select, inherit, Direction, Visibility, Selectable };
//# sourceMappingURL=type-transformer.es.js.map