UNPKG

@pebula/metap

Version:
1,303 lines (1,284 loc) 41.5 kB
import { MetaClass, PropMetadata, ExcludeMetadata, RelationMetadata, TypeMetadata, targetStore, ModelMetadata, array, LazyInit, BaseSerializer, BaseDeserializer, DualKeyMap } from '@pebula/metap/internal'; export { BaseDeserializer, BaseSerializer, Errors, ModelClassBase, ModelClassCollection, PlainObjectMapper, errors } from '@pebula/metap/internal'; import { __values, __extends, __read, __decorate, __metadata } from 'tslib'; import { getProtoChain, isFunction, isPrimitive } from '@pebula/utils'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /* We need to do some funky stuff for angular compiler... If we wont, the output d.ts files will be messed up For example: export const Prop = MetaClass.decorator(PropMetadata, true); WILL BECOME IN "d.ts" export declare const Prop: (def?: import("../../../../../dist/@pebula/metap/internal/pebula-metap-internal").PropMetadataArgs) => (target: any, propertyKey?: string | number | symbol, descOrIndex?: number | PropertyDescriptor) => any; This will happen because ngc doesn't know how properly get the symbol declaration so it fallbacks to the import style.... */ /** * \@propertyDecorator instance * \@param def * @type {?} */ var Prop = MetaClass.decorator(PropMetadata, true); /** * \@propertyDecorator instance * \@param def * @type {?} */ var Exclude = MetaClass.decorator(ExcludeMetadata, true); /** * \@propertyDecorator instance * \@param def * @type {?} */ var Relation = MetaClass.decorator(RelationMetadata, true); /** * \@propertyDecorator instance * \@param def * @type {?} */ var Type = MetaClass.decorator(TypeMetadata); /** * \@propertyDecorator instance * @return {?} */ function Identity() { return (/** * @param {?} target * @param {?} key * @return {?} */ function (target, key) { targetStore.getTargetMeta((/** @type {?} */ (target.constructor))).model().identity = key; }); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * \@propertyDecorator static * @param {?=} metaArgs * @return {?} */ function Model(metaArgs) { return (/** * @param {?} target * @return {?} */ function (target) { /** @type {?} */ var metaClass = MetaClass.create(ModelMetadata, metaArgs, target); processModel(target, metaClass, metaClass.skip !== true); }); } /** * Takes a model and process it. * The first step is to extend the target, if it inherits. * The second step is calling the build() method on the metadata class which will * start the event life-cycle. * @param {?} target * @param {?} metaClass * @param {?=} build * @return {?} */ function processModel(target, metaClass, build) { var e_1, _a; try { for (var _b = __values(getProtoChain(target)), _c = _b.next(); !_c.done; _c = _b.next()) { var proto = _c.value; if (target !== proto && targetStore.hasTarget(proto)) { targetStore.extend(proto, target); } } } 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; } } if (build) { metaClass.build(); } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @record */ function CompiledTransformation() { } if (false) { /** * Excluded members that doesn't have a \@Prop decorator. * All \@Exclude instructions on members with \@Prop instructions are add to the PoClassPropertyMap * @type {?} */ CompiledTransformation.prototype.excluded; /** @type {?} */ CompiledTransformation.prototype.instructions; } /** * @param {?} value * @param {?} prop * @return {?} */ function transformValueOut(value, prop) { if (prop && prop.transform && prop.transform.outgoing) { return prop.transform.outgoing(value); } return value; } /** * @param {?} value * @param {?} prop * @return {?} */ function transformValueIn(value, prop) { if (prop && prop.transform && prop.transform.incoming) { return prop.transform.incoming(value); } return value; } /** * @param {?} e * @return {?} */ function excludedPredicate(e) { return e.name === this; } var InclusivePropertyContainer = /** @class */ (function () { function InclusivePropertyContainer(target, compiled, predicate, renamer) { this.target = target; this.compiled = compiled; this.predicate = predicate; this.renamer = renamer; } /** * @param {?} keys * @param {?} cb * @return {?} */ InclusivePropertyContainer.prototype.forEach = /** * @param {?} keys * @param {?} cb * @return {?} */ function (keys, cb) { /** @type {?} */ var len = keys.length; /** @type {?} */ var instructions = this.compiled.instructions.slice(); /** @type {?} */ var excluded = this.compiled.excluded.slice(); for (var i = 0; i < len; i++) { /** @type {?} */ var prop = array.findRemove(instructions, this.predicate, keys[i]) || { cls: keys[i], obj: keys[i], exclude: array.findRemove(excluded, excludedPredicate, keys[i]) }; if (!prop.exclude) { // we only transform names for ad-hoc properties. registered @Prop's are transformed // when the prop is compiled. if (!prop.prop && this.renamer) { this.renamer(prop); } cb(prop); } } }; /** * A forEach loop on all instructions including excluded instructions and properties not in "keys" but in metadata. * It is recommended to use "forEach" unless the mapper implementation has different transformation strategies. * @param keys * @param cb */ /** * A forEach loop on all instructions including excluded instructions and properties not in "keys" but in metadata. * It is recommended to use "forEach" unless the mapper implementation has different transformation strategies. * @param {?} keys * @param {?} cb * @return {?} */ InclusivePropertyContainer.prototype.forEachRaw = /** * A forEach loop on all instructions including excluded instructions and properties not in "keys" but in metadata. * It is recommended to use "forEach" unless the mapper implementation has different transformation strategies. * @param {?} keys * @param {?} cb * @return {?} */ function (keys, cb) { /** @type {?} */ var len = keys.length; /** @type {?} */ var instructions = this.compiled.instructions.slice(); /** @type {?} */ var excluded = this.compiled.excluded.slice(); for (var i = 0; i < len; i++) { /** @type {?} */ var prop = array.findRemove(instructions, this.predicate, keys[i]) || { cls: keys[i], obj: keys[i], exclude: array.findRemove(excluded, excludedPredicate, keys[i]) }; // we only transform names for ad-hoc properties. registered @Prop's are transformed // when the prop is compiled. if (!prop.prop && this.renamer) { this.renamer(prop); } cb(prop); } len = instructions.length; for (var i = 0; i < len; i++) { /** @type {?} */ var prop = instructions[i]; // we only transform names for ad-hoc properties. registered @Prop's are transformed // when the prop is compiled. if (!prop.prop && this.renamer) { this.renamer(prop); } cb(prop); } }; return InclusivePropertyContainer; }()); if (false) { /** @type {?} */ InclusivePropertyContainer.prototype.target; /** * @type {?} * @private */ InclusivePropertyContainer.prototype.compiled; /** * @type {?} * @private */ InclusivePropertyContainer.prototype.predicate; /** * @type {?} * @private */ InclusivePropertyContainer.prototype.renamer; } var ExclusivePropertyContainer = /** @class */ (function () { function ExclusivePropertyContainer(target, compiled) { this.target = target; this.compiled = compiled; } /** * @param {?} keys * @param {?} cb * @return {?} */ ExclusivePropertyContainer.prototype.forEach = /** * @param {?} keys * @param {?} cb * @return {?} */ function (keys, cb) { /** @type {?} */ var instructions = this.compiled.instructions; // No need to apply transformNameStrategy, it is cached in the instructions. for (var i = 0, len = instructions.length; i < len; i++) { !instructions[i].exclude && cb(instructions[i]); } }; /** * A forEach loop on all instructions including excluded instructions and properties not in "keys" but in metadata. * It is recommended to use "forEach" unless the mapper implementation has different transformation strategies. * @param keys * @param cb */ /** * A forEach loop on all instructions including excluded instructions and properties not in "keys" but in metadata. * It is recommended to use "forEach" unless the mapper implementation has different transformation strategies. * @param {?} keys * @param {?} cb * @return {?} */ ExclusivePropertyContainer.prototype.forEachRaw = /** * A forEach loop on all instructions including excluded instructions and properties not in "keys" but in metadata. * It is recommended to use "forEach" unless the mapper implementation has different transformation strategies. * @param {?} keys * @param {?} cb * @return {?} */ function (keys, cb) { /** @type {?} */ var instructions = this.compiled.instructions; for (var i = 0, len = instructions.length; i < len; i++) { cb(instructions[i]); } }; return ExclusivePropertyContainer; }()); if (false) { /** @type {?} */ ExclusivePropertyContainer.prototype.target; /** * @type {?} * @private */ ExclusivePropertyContainer.prototype.compiled; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var TransformationError = /** @class */ (function (_super) { __extends(TransformationError, _super); function TransformationError(message) { return _super.call(this, message) || this; } /** * @param {?} expectedCol * @return {?} */ TransformationError.coll_obj = /** * @param {?} expectedCol * @return {?} */ function (expectedCol) { return new TransformationError(expectedCol ? "Expected a collection but got an object" : "Expected an object but got a collection"); }; return TransformationError; }(Error)); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * Returns an array of 2 property names, first is the name of the transformed output * second is the name of the property name to transform. * Used for applying NamingStrategyConfig based on the TransformDir * @param {?} dir * @param {?} transformNameStrategy * @return {?} */ function namingStrategyMap(dir, transformNameStrategy) { return transformNameStrategy && isFunction(transformNameStrategy[dir]); } /** * \@internal * @template T, Z * @param {?} meta * @param {?} dir * @return {?} */ function getInstructions(meta, dir) { // all excluded instructions for this type // this array will be filtered to hold only @Exclude without @Prop /** @type {?} */ var excluded = meta .getValues(ExcludeMetadata) .filter((/** * @param {?} e * @return {?} */ function (e) { return !e.from || e.from === dir; })); /** @type {?} */ var model = meta.model(); // in exclusive mode there is no point in have 2 transformation strategies. // incoming is never there since incoming keys are not calculated, only defined Props. if (model.transformStrategy === 'exclusive') { dir = 'outgoing'; } // only apply naming strategy on outgoing, incoming has no effect here /** @type {?} */ var naming = namingStrategyMap(dir, model.transformNameStrategy); /** @type {?} */ var fkMap = new Map(); // TODO: move to for loop /** @type {?} */ var instructions = meta.getValues(PropMetadata).map((/** * @param {?} prop * @return {?} */ function (prop) { /** @type {?} */ var obj = { cls: prop.name, obj: prop.alias[dir], exclude: array.findRemove(excluded, (/** * @param {?} e * @return {?} */ function (e) { return e.name === prop.name; })), prop: prop }; // apply naming strategy when DONT HAVE ALIAS! if (!obj.exclude && naming && obj.cls === obj.obj) { obj.obj = model.transformNameStrategy[dir](obj.cls); } // store the PoClassPropertyMap of a belongsTo PropMetadata relation // and the PoClassPropertyMap of all foreign key PropMetadata. // These arr actually matching pairs of a belongTo relation and it's fk // (not all belongsTo has fk, only different property name is a fk) // // At the end, go through the stored PropMetadata and see if matching pairs found (2 values in array) // for all of them, swap the prop names so: // belongsTo PoClassPropertyMap will output (deserialize) to the original fk property name // foreignKey PoClassPropertyMap wil input (serialize) to the belongsTo property name // this swap make the deserialize/serialize process transparent to fk mismatch defined on the model. // De/Serialize implementations are only responsible to return the right object // (e.g. detect when a key is incoming, return obj instead) if (prop.relation) { /** @type {?} */ var arr = fkMap.get(prop) || []; arr[0] = obj; fkMap.set(prop, arr); } else if (prop.foreignKeyOf) { /** @type {?} */ var arr = fkMap.get(prop.foreignKeyOf) || []; arr[1] = obj; fkMap.set(prop.foreignKeyOf, arr); } return obj; })); Array.from(fkMap.entries()).forEach((/** * @param {?} __0 * @return {?} */ function (_a) { var _b = __read(_a, 2), k = _b[0], v = _b[1]; if (v.length === 2) { // this is a swap v[0].obj = (/** @type {?} */ (v[1].cls)); v[1].cls = (/** @type {?} */ (k.name)); // v[0].cls === k.name } })); return { excluded: excluded, instructions: instructions }; } /** * @param {?} p * @return {?} */ function serializePredicate(p) { return p.cls === this; } /** * @param {?} p * @return {?} */ function deserializePredicate(p) { return p.obj === this; } var ɵ0 = /** * @this {?} * @return {?} */ function () { /** @type {?} */ var idKey = this.meta.getIdentityKey(); if (idKey) { return (this.hasOwnProperty('incoming') ? this.incoming : this.outgoing).instructions.find((/** * @param {?} p * @return {?} */ function (p) { return p.prop.name === idKey; })); } }, ɵ1 = /** * @this {?} * @return {?} */ function () { return getInstructions(this.meta, 'incoming'); }, ɵ2 = /** * @this {?} * @return {?} */ function () { return getInstructions(this.meta, 'outgoing'); }, ɵ3 = /** * @this {?} * @return {?} */ function () { /** @type {?} */ var model = this.meta.model(); if (model.transformStrategy === 'exclusive') { return new ExclusivePropertyContainer(this.meta.target, this.incoming); } else { /** @type {?} */ var rename = namingStrategyMap('incoming', model.transformNameStrategy) ? (/** * @param {?} prop * @return {?} */ function (prop) { return (prop.cls = model.transformNameStrategy.incoming(prop.obj)); }) : undefined; return new InclusivePropertyContainer(this.meta.target, this.incoming, deserializePredicate, rename); } }, ɵ4 = /** * @this {?} * @return {?} */ function () { /** @type {?} */ var model = this.meta.model(); if (model.transformStrategy === 'exclusive') { return new ExclusivePropertyContainer(this.meta.target, this.outgoing); } else { /** @type {?} */ var rename = namingStrategyMap('outgoing', model.transformNameStrategy) ? (/** * @param {?} prop * @return {?} */ function (prop) { return (prop.obj = model.transformNameStrategy.outgoing(prop.cls)); }) : undefined; return new InclusivePropertyContainer(this.meta.target, this.outgoing, serializePredicate, rename); } }; // @dynamic /** * A TargetSerializationContext is the running context of a mapper for a specific target class that * can serialize and deserialize instances of the target class. * It will run the mapper, provide input and parse results * @template T, Z */ var TargetSerializationContext = /** @class */ (function () { function TargetSerializationContext(meta) { this.meta = meta; } /** * @param {?} mapper * @return {?} */ TargetSerializationContext.prototype.serialize = /** * @param {?} mapper * @return {?} */ function (mapper) { return mapper.serialize(this.outgoingContainer); }; /** * Deserialize a single target. * Does not support collection deserialization, if mapper is a collection will throw. * @param mapper * @param target */ /** * Deserialize a single target. * Does not support collection deserialization, if mapper is a collection will throw. * @param {?} mapper * @param {?} target * @return {?} */ TargetSerializationContext.prototype.deserialize = /** * Deserialize a single target. * Does not support collection deserialization, if mapper is a collection will throw. * @param {?} mapper * @param {?} target * @return {?} */ function (mapper, target) { /** @type {?} */ var cb = (/** * @param {?} prop * @return {?} */ function (prop) { /** @type {?} */ var propMeta = (prop.prop && prop.prop.foreignKeyOf) || prop.prop; target[prop.cls] = transformValueIn(mapper.getValue(prop.obj, propMeta), propMeta); }); if (isFunction(mapper.setRef)) { mapper.setRef(target); } if (mapper.raw === true) { this.incomingContainer.forEachRaw(mapper.getKeys(), cb); } else { this.incomingContainer.forEach(mapper.getKeys(), cb); } if (isFunction(mapper.getIdentity)) { if (this.identity) { /** @type {?} */ var ident = transformValueIn(mapper.getIdentity(), this.identity.prop); if (ident) { target[this.identity.cls] = ident; } } } }; __decorate([ LazyInit((ɵ0)), __metadata("design:type", Object) ], TargetSerializationContext.prototype, "identity", void 0); __decorate([ LazyInit((ɵ1)), __metadata("design:type", Object) ], TargetSerializationContext.prototype, "incoming", void 0); __decorate([ LazyInit((ɵ2)), __metadata("design:type", Object) ], TargetSerializationContext.prototype, "outgoing", void 0); __decorate([ LazyInit((ɵ3)), __metadata("design:type", Object) ], TargetSerializationContext.prototype, "incomingContainer", void 0); __decorate([ LazyInit((ɵ4)), __metadata("design:type", Object) ], TargetSerializationContext.prototype, "outgoingContainer", void 0); return TargetSerializationContext; }()); if (false) { /** * @type {?} * @protected */ TargetSerializationContext.prototype.identity; /** * @type {?} * @protected */ TargetSerializationContext.prototype.incoming; /** * @type {?} * @protected */ TargetSerializationContext.prototype.outgoing; /** * @type {?} * @protected */ TargetSerializationContext.prototype.incomingContainer; /** * @type {?} * @protected */ TargetSerializationContext.prototype.outgoingContainer; /** * @type {?} * @protected */ TargetSerializationContext.prototype.meta; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ var targetSerializationContextStore = new Map(); /** * @param {?} targetMeta * @return {?} */ function getTargetSerializationContext(targetMeta) { /** @type {?} */ var ctx = targetSerializationContextStore.get(targetMeta); if (!ctx) { ctx = new TargetSerializationContext(targetMeta); targetSerializationContextStore.set(targetMeta, ctx); } return ctx; } /** * @template TMeta * @param {?} targetMeta * @param {?} mapper * @return {?} */ function serializeTargetMeta(targetMeta, mapper) { return getTargetSerializationContext(targetMeta).serialize(mapper); } /** * @template TMeta * @param {?} targetMeta * @param {?} mapper * @param {?} target * @param {?=} plain * @return {?} */ function deserializeTargetMeta(targetMeta, mapper, target, plain) { if (plain === void 0) { plain = false; } if (mapper.isCollection) { if (!Array.isArray(target)) { throw TransformationError.coll_obj(true); } /** @type {?} */ var refItems = target.splice(0, target.length); /** @type {?} */ var identKey_1 = targetStore.getIdentityKey(targetMeta.target, 'incoming'); var _loop_1 = function () { /** @type {?} */ var t = void 0; // compare current item to map with a list of items that if we, if we got. // if match use that instance. // TODO: Move compare to the global store, so logic can change without bugs. if (refItems.length > 0 && isFunction(mapper.getIdentity)) { /** @type {?} */ var incomingIdent_1 = mapper.getIdentity(); t = array.findRemove(refItems, (/** * @param {?} item * @return {?} */ function (item) { return item[identKey_1] === incomingIdent_1; })); } if (!t) { t = plain ? {} : targetMeta.model().factory(false); } getTargetSerializationContext(targetMeta).deserialize(mapper, t); target.push(t); }; while (mapper.next()) { _loop_1(); } } else { if (Array.isArray(target)) { throw TransformationError.coll_obj(false); } getTargetSerializationContext(targetMeta).deserialize(mapper, target); } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ var PlainObject = /** @class */ (function () { function PlainObject() { } PlainObject = __decorate([ Model({ resName: 'InternalPlainObject' }) ], PlainObject); return PlainObject; }()); /** * @param {?} mapper * @param {?} instanceOrTarget * @param {?=} target * @return {?} */ function serialize(mapper, instanceOrTarget, target) { if (mapper instanceof BaseSerializer) { /** @type {?} */ var meta = targetStore.getTargetMeta(instanceOrTarget); if (meta) { return serializeTargetMeta(meta, mapper); } } else { /** @type {?} */ var meta = targetStore.getTargetMeta(target || instanceOrTarget.constructor); if (meta) { return serializeTargetMeta(meta, mapper.serializer(instanceOrTarget)); } } } /** * Automatically serialize an instance. * This method will serialize an instance by first trying to locate the target using the `constructor` function. * If a target is found and if it's a model target (i.e. ModelMetadata) it will try to get the mapper assign for that * model. * * If no target, model or mapper was found it will use the fallbackMapper mapper provided, or `directMapper` * if no fallback is provided provided. * * Note that when provided a fallback mapper, make sure it is able to serialize unknown targets. (plain objects) * @param {?} instance * @param {?=} fallbackMapper * @return {?} */ function autoSerialize(instance, fallbackMapper) { /** @type {?} */ var tMeta = targetStore.getTargetMeta((/** @type {?} */ (instance.constructor))); /** @type {?} */ var mapper = (tMeta && tMeta.hasModel && tMeta.model().mapper) || fallbackMapper || directMapper; return serialize(mapper, instance); } /** * @param {?} mapper * @param {?=} plainObject * @param {?=} type * @param {?=} instance * @return {?} */ function deserialize(mapper, plainObject, type, instance) { /** @type {?} */ var deserializer; if (mapper instanceof BaseDeserializer) { instance = plainObject; deserializer = mapper; } else { deserializer = mapper.deserializer(plainObject, type); } if (targetStore.hasTarget(deserializer.sourceType)) { /** @type {?} */ var meta = targetStore.getTargetMeta(deserializer.sourceType); /** @type {?} */ var result = instance || meta.model().factory(deserializer.isCollection); deserializeTargetMeta(meta, deserializer, result); return result; } else { /** @type {?} */ var meta = targetStore.getTargetMeta(PlainObject); /** @type {?} */ var result = instance || deserializer.isCollection ? [] : {}; deserializeTargetMeta(meta, deserializer, result, true); return result; } } /** * Automatically de-serialize an object to/into an instance. * This method will de-serialize an object by first trying to locate a model (i.e. ModelMetadata) for the target. * If a model is found it will try to get the mapper assign for that model. * * If no model or mapper was found it will use the fallbackMapper mapper provided, or `directMapper` * if no fallback is provided provided. * * @template T, Z * @param {?} plainObject * @param {?} type * @param {?=} instance * @param {?=} fallbackMapper * @return {?} */ function autoDeserialize(plainObject, type, instance, fallbackMapper) { if (instance === void 0) { instance = null; } /** @type {?} */ var tMeta = targetStore.getTargetMeta(type); /** @type {?} */ var mapper = (tMeta && tMeta.hasModel && tMeta.model().mapper) || fallbackMapper || directMapper; return deserialize(mapper, plainObject, type, instance); } /** * Performs a deep clone to the resource using serialization and deserialization, which means that all rules apply (i.e \@Exclude) * * @template T * @param {?} resource the resource (instance) to clone * @param {?=} serializationFactory Optional, The [[SerializationFactory]] to use, defaults to [[directMapper]]. * @return {?} */ function clone(resource, serializationFactory) { return autoDeserialize(autoSerialize(resource, serializationFactory), (/** @type {?} */ (resource.constructor)), null, serializationFactory); } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * A mapper that has no mapping effect. * Maps every property on the source to the same property on the target. * This mapper does not support non primitive id's * @template T, Z */ var /** * A mapper that has no mapping effect. * Maps every property on the source to the same property on the target. * This mapper does not support non primitive id's * @template T, Z */ DirectDeserializeMapper = /** @class */ (function (_super) { __extends(DirectDeserializeMapper, _super); function DirectDeserializeMapper(source, sourceType, plainMapper) { var _this = _super.call(this, source, sourceType, plainMapper) || this; _this.idx = -1; if (!(_this instanceof DirectChildDeserializeMapper)) { _this.existing = new DualKeyMap(); } _this.identity = targetStore.getIdentityKey(_this.sourceType, 'outgoing'); _this.isCollection = Array.isArray(source); if (!_this.isCollection) { _this.current = _this.source; } return _this; } /** * @param {?} value * @return {?} */ DirectDeserializeMapper.prototype.setRef = /** * @param {?} value * @return {?} */ function (value) { if (this.current) { this.existing.set(this.sourceType, this.getIdentity(), value); } }; Object.defineProperty(DirectDeserializeMapper.prototype, "ref", { get: /** * @protected * @return {?} */ function () { if (this.current) { return this.existing.get(this.sourceType, this.getIdentity()); } }, enumerable: true, configurable: true }); /** * @return {?} */ DirectDeserializeMapper.prototype.getIdentity = /** * @return {?} */ function () { // TODO: Move to the global store, so logic can change without bugs. return this.current[this.identity]; }; /** * @return {?} */ DirectDeserializeMapper.prototype.next = /** * @return {?} */ function () { if (this.isCollection) { this.current = this.source[++this.idx]; return !!this.current; } else { return false; } }; /** * @return {?} */ DirectDeserializeMapper.prototype.getKeys = /** * @return {?} */ function () { return Object.keys(this.current); }; /** * @param {?} key * @param {?=} prop * @return {?} */ DirectDeserializeMapper.prototype.getValue = /** * @param {?} key * @param {?=} prop * @return {?} */ function (key, prop) { /** @type {?} */ var value = this.current[key]; if (prop) { // The adapter has the responsibility to manage relationships. // It doesn't care about key matching (e.g. key in property customer_id but property is customer) // it get's a value and the property to assign to, the adapter should check if the value it got // was an id or an object. // this relationship handling logic makes this whole adapter support only primitive ID properties. // if we have primitives we treat them as id's and create an object. // later we wil check if this value is in cache, if not create it. // if its not a primitive, it will process as a full object included in the payload. /** @type {?} */ var rel = this.getRelationQuery(prop, value); if (rel) { value = rel; } if (targetStore.hasTarget(prop.type.ref)) { return (this.getCache(prop.type.ref, value) || this.deserialize(value, prop)); } } return typeof value === 'object' ? this.plainMapper.deserialize(value) : value; }; /** * @protected * @param {?} value * @param {?} prop * @return {?} */ DirectDeserializeMapper.prototype.deserialize = /** * @protected * @param {?} value * @param {?} prop * @return {?} */ function (value, prop) { /** @type {?} */ var deserializer = this.ref ? new DirectChildDeserializeMapper(value, prop.type.ref, this.existing, this.plainMapper) : directMapper.deserializer(value, prop.type.ref, this.plainMapper); return deserialize(deserializer); }; /** * Returns a relationship object with the identity property set. * This object can then be used by the cache to identify if a value is cached or not (using the type & identity comb) */ /** * Returns a relationship object with the identity property set. * This object can then be used by the cache to identify if a value is cached or not (using the type & identity comb) * @protected * @param {?} prop * @param {?} value * @return {?} */ DirectDeserializeMapper.prototype.getRelationQuery = /** * Returns a relationship object with the identity property set. * This object can then be used by the cache to identify if a value is cached or not (using the type & identity comb) * @protected * @param {?} prop * @param {?} value * @return {?} */ function (prop, value) { var _a; if (prop.relation && isPrimitive(value)) { return _a = {}, _a[targetStore.getIdentityKey((/** @type {?} */ (prop.type.ref)), 'outgoing')] = value, _a; } }; /** * @protected * @param {?} type * @param {?} value * @return {?} */ DirectDeserializeMapper.prototype.getCache = /** * @protected * @param {?} type * @param {?} value * @return {?} */ function (type, value) { /** @type {?} */ var idKey = targetStore.getIdentityKey(type, 'outgoing'); /** @type {?} */ var idVal = idKey && value[idKey]; if (idVal) { return this.existing.get(type, idVal); } }; return DirectDeserializeMapper; }(BaseDeserializer)); if (false) { /** @type {?} */ DirectDeserializeMapper.prototype.isCollection; /** * @type {?} * @protected */ DirectDeserializeMapper.prototype.existing; /** * @type {?} * @protected */ DirectDeserializeMapper.prototype.current; /** * @type {?} * @protected */ DirectDeserializeMapper.prototype.identity; /** * @type {?} * @private */ DirectDeserializeMapper.prototype.idx; } // tslint:disable-next-line var // tslint:disable-next-line DirectChildDeserializeMapper = /** @class */ (function (_super) { __extends(DirectChildDeserializeMapper, _super); function DirectChildDeserializeMapper(source, sourceType, existing, plainMapper) { var _this = _super.call(this, source, sourceType, plainMapper) || this; _this.existing = existing; return _this; } return DirectChildDeserializeMapper; }(DirectDeserializeMapper)); if (false) { /** * @type {?} * @protected */ DirectChildDeserializeMapper.prototype.existing; } // tslint:disable-next-line var // tslint:disable-next-line DirectSerializeMapper = /** @class */ (function (_super) { __extends(DirectSerializeMapper, _super); function DirectSerializeMapper() { return _super !== null && _super.apply(this, arguments) || this; } /** * @param {?} container * @return {?} */ DirectSerializeMapper.prototype.serialize = /** * @param {?} container * @return {?} */ function (container) { if (!this.cache) { this.cache = new Map(); } if (Array.isArray(this.source)) { return this.serializeCollection(this.source, container); } else { return this.serializeObject(this.source, container); } }; /** * @private * @param {?} obj * @param {?} container * @return {?} */ DirectSerializeMapper.prototype.serializeObject = /** * @private * @param {?} obj * @param {?} container * @return {?} */ function (obj, container) { var _this = this; /** @type {?} */ var data = {}; /** @type {?} */ var cb = (/** * @param {?} pMap * @return {?} */ function (pMap) { /** @type {?} */ var p = pMap.prop; if (p && targetStore.hasTarget(p.type.ref)) { /** @type {?} */ var type = p.type.ref; if (p.relation && !p.type.container) { /** @type {?} */ var idKey_1 = targetStore.getIdentityKey(type); // if the rel points to a different fk property name, @tdm will make sure prop.obj is that fk. data[pMap.obj] = obj[pMap.cls][idKey_1]; } else { data[pMap.obj] = serialize(new DirectChildSerializeMapper(obj[pMap.cls], _this.cache, _this.plainMapper), type); } } else { /** @type {?} */ var newVal = _this.plainMapper.serialize(transformValueOut(obj[pMap.cls], p)); data[pMap.obj] = newVal; } }); container.forEach(Object.keys(obj), cb); /** @type {?} */ var idKey = targetStore.getIdentityKey(container.target); if (idKey !== targetStore.getIdentityKey(container.target, 'outgoing')) { delete data[idKey]; } return data; }; /** * @private * @param {?} arr * @param {?} container * @return {?} */ DirectSerializeMapper.prototype.serializeCollection = /** * @private * @param {?} arr * @param {?} container * @return {?} */ function (arr, container) { var _this = this; return arr.map((/** * @param {?} s * @return {?} */ function (s) { return _this.serializeObject(s, container); })); }; return DirectSerializeMapper; }(BaseSerializer)); if (false) { /** * @type {?} * @protected */ DirectSerializeMapper.prototype.cache; } // tslint:disable-next-line var // tslint:disable-next-line DirectChildSerializeMapper = /** @class */ (function (_super) { __extends(DirectChildSerializeMapper, _super); function DirectChildSerializeMapper(source, cache, plainMapper) { var _this = _super.call(this, source, plainMapper) || this; _this.cache = cache; return _this; } return DirectChildSerializeMapper; }(DirectSerializeMapper)); if (false) { /** * @type {?} * @protected */ DirectChildSerializeMapper.prototype.cache; } /** @type {?} */ var directMapper = { serializer: /** * @param {?} source * @param {?=} plainMapper * @return {?} */ function (source, plainMapper) { return new DirectSerializeMapper(source, plainMapper); }, deserializer: /** * @template T, Z * @param {?} source * @param {?} sourceType * @param {?=} plainMapper * @return {?} */ function (source, sourceType, plainMapper) { return new DirectDeserializeMapper(source, sourceType, plainMapper); } }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { DirectDeserializeMapper, DirectSerializeMapper, Exclude, Identity, Model, Prop, Relation, Type, autoDeserialize, autoSerialize, clone, deserialize, deserializeTargetMeta, directMapper, serialize, serializeTargetMeta }; //# sourceMappingURL=pebula-metap.js.map