UNPKG

@pebula/metap

Version:
1,162 lines (1,143 loc) 35.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 { getProtoChain, isFunction, isPrimitive } from '@pebula/utils'; import { __decorate, __metadata } from 'tslib'; /** * @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 {?} */ const Prop = MetaClass.decorator(PropMetadata, true); /** * \@propertyDecorator instance * \@param def * @type {?} */ const Exclude = MetaClass.decorator(ExcludeMetadata, true); /** * \@propertyDecorator instance * \@param def * @type {?} */ const Relation = MetaClass.decorator(RelationMetadata, true); /** * \@propertyDecorator instance * \@param def * @type {?} */ const Type = MetaClass.decorator(TypeMetadata); /** * \@propertyDecorator instance * @return {?} */ function Identity() { return (/** * @param {?} target * @param {?} key * @return {?} */ (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 {?} */ (target) => { /** @type {?} */ const 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) { for (let proto of getProtoChain(target)) { if (target !== proto && targetStore.hasTarget(proto)) { targetStore.extend(proto, target); } } 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; } class InclusivePropertyContainer { /** * @param {?} target * @param {?} compiled * @param {?} predicate * @param {?=} renamer */ constructor(target, compiled, predicate, renamer) { this.target = target; this.compiled = compiled; this.predicate = predicate; this.renamer = renamer; } /** * @param {?} keys * @param {?} cb * @return {?} */ forEach(keys, cb) { /** @type {?} */ let len = keys.length; /** @type {?} */ const instructions = this.compiled.instructions.slice(); /** @type {?} */ const excluded = this.compiled.excluded.slice(); for (let i = 0; i < len; i++) { /** @type {?} */ let 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 * @return {?} */ forEachRaw(keys, cb) { /** @type {?} */ let len = keys.length; /** @type {?} */ const instructions = this.compiled.instructions.slice(); /** @type {?} */ const excluded = this.compiled.excluded.slice(); for (let i = 0; i < len; i++) { /** @type {?} */ let 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 (let i = 0; i < len; i++) { /** @type {?} */ let 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); } } } if (false) { /** @type {?} */ InclusivePropertyContainer.prototype.target; /** * @type {?} * @private */ InclusivePropertyContainer.prototype.compiled; /** * @type {?} * @private */ InclusivePropertyContainer.prototype.predicate; /** * @type {?} * @private */ InclusivePropertyContainer.prototype.renamer; } class ExclusivePropertyContainer { /** * @param {?} target * @param {?} compiled */ constructor(target, compiled) { this.target = target; this.compiled = compiled; } /** * @param {?} keys * @param {?} cb * @return {?} */ forEach(keys, cb) { /** @type {?} */ const instructions = this.compiled.instructions; // No need to apply transformNameStrategy, it is cached in the instructions. for (let 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 * @return {?} */ forEachRaw(keys, cb) { /** @type {?} */ const instructions = this.compiled.instructions; for (let i = 0, len = instructions.length; i < len; i++) { cb(instructions[i]); } } } 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 */ class TransformationError extends Error { /** * @param {?=} message */ constructor(message) { super(message); } /** * @param {?} expectedCol * @return {?} */ static coll_obj(expectedCol) { return new TransformationError(expectedCol ? `Expected a collection but got an object` : `Expected an object but got a collection`); } } /** * @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 {?} */ const excluded = meta .getValues(ExcludeMetadata) .filter((/** * @param {?} e * @return {?} */ e => !e.from || e.from === dir)); /** @type {?} */ const 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 {?} */ const naming = namingStrategyMap(dir, model.transformNameStrategy); /** @type {?} */ const fkMap = new Map(); // TODO: move to for loop /** @type {?} */ const instructions = meta.getValues(PropMetadata).map((/** * @param {?} prop * @return {?} */ prop => { /** @type {?} */ const obj = { cls: prop.name, obj: prop.alias[dir], exclude: array.findRemove(excluded, (/** * @param {?} e * @return {?} */ e => e.name === prop.name)), 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 {?} */ const arr = fkMap.get(prop) || []; arr[0] = obj; fkMap.set(prop, arr); } else if (prop.foreignKeyOf) { /** @type {?} */ const arr = fkMap.get(prop.foreignKeyOf) || []; arr[1] = obj; fkMap.set(prop.foreignKeyOf, arr); } return obj; })); Array.from(fkMap.entries()).forEach((/** * @param {?} __0 * @return {?} */ ([k, v]) => { 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, instructions }; } /** * @param {?} p * @return {?} */ function serializePredicate(p) { return p.cls === this; } /** * @param {?} p * @return {?} */ function deserializePredicate(p) { return p.obj === this; } const ɵ0 = /** * @this {?} * @return {?} */ function () { /** @type {?} */ const idKey = this.meta.getIdentityKey(); if (idKey) { return (this.hasOwnProperty('incoming') ? this.incoming : this.outgoing).instructions.find((/** * @param {?} p * @return {?} */ p => 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 {?} */ const model = this.meta.model(); if (model.transformStrategy === 'exclusive') { return new ExclusivePropertyContainer(this.meta.target, this.incoming); } else { /** @type {?} */ const rename = namingStrategyMap('incoming', model.transformNameStrategy) ? (/** * @param {?} prop * @return {?} */ prop => (prop.cls = model.transformNameStrategy.incoming(prop.obj))) : undefined; return new InclusivePropertyContainer(this.meta.target, this.incoming, deserializePredicate, rename); } }, ɵ4 = /** * @this {?} * @return {?} */ function () { /** @type {?} */ const model = this.meta.model(); if (model.transformStrategy === 'exclusive') { return new ExclusivePropertyContainer(this.meta.target, this.outgoing); } else { /** @type {?} */ const rename = namingStrategyMap('outgoing', model.transformNameStrategy) ? (/** * @param {?} prop * @return {?} */ prop => (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 */ class TargetSerializationContext { /** * @param {?} meta */ constructor(meta) { this.meta = meta; } /** * @param {?} mapper * @return {?} */ serialize(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 * @return {?} */ deserialize(mapper, target) { /** @type {?} */ const cb = (/** * @param {?} prop * @return {?} */ (prop) => { /** @type {?} */ const 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 {?} */ const 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); 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 {?} */ const targetSerializationContextStore = new Map(); /** * @param {?} targetMeta * @return {?} */ function getTargetSerializationContext(targetMeta) { /** @type {?} */ let 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 = false) { if (mapper.isCollection) { if (!Array.isArray(target)) { throw TransformationError.coll_obj(true); } /** @type {?} */ const refItems = target.splice(0, target.length); /** @type {?} */ const identKey = targetStore.getIdentityKey(targetMeta.target, 'incoming'); while (mapper.next()) { /** @type {?} */ let t; // 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 {?} */ const incomingIdent = mapper.getIdentity(); t = array.findRemove(refItems, (/** * @param {?} item * @return {?} */ item => item[identKey] === incomingIdent)); } if (!t) { t = plain ? {} : targetMeta.model().factory(false); } getTargetSerializationContext(targetMeta).deserialize(mapper, t); target.push(t); } } 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 */ let PlainObject = class PlainObject { }; PlainObject = __decorate([ Model({ resName: 'InternalPlainObject' }) ], PlainObject); /** * @param {?} mapper * @param {?} instanceOrTarget * @param {?=} target * @return {?} */ function serialize(mapper, instanceOrTarget, target) { if (mapper instanceof BaseSerializer) { /** @type {?} */ const meta = targetStore.getTargetMeta(instanceOrTarget); if (meta) { return serializeTargetMeta(meta, mapper); } } else { /** @type {?} */ const 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 {?} */ const tMeta = targetStore.getTargetMeta((/** @type {?} */ (instance.constructor))); /** @type {?} */ const 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 {?} */ let deserializer; if (mapper instanceof BaseDeserializer) { instance = plainObject; deserializer = mapper; } else { deserializer = mapper.deserializer(plainObject, type); } if (targetStore.hasTarget(deserializer.sourceType)) { /** @type {?} */ const meta = targetStore.getTargetMeta(deserializer.sourceType); /** @type {?} */ const result = instance || meta.model().factory(deserializer.isCollection); deserializeTargetMeta(meta, deserializer, result); return result; } else { /** @type {?} */ const meta = targetStore.getTargetMeta(PlainObject); /** @type {?} */ const 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 = null, fallbackMapper) { /** @type {?} */ const tMeta = targetStore.getTargetMeta(type); /** @type {?} */ const 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 */ class DirectDeserializeMapper extends BaseDeserializer { /** * @param {?} source * @param {?} sourceType * @param {?=} plainMapper */ constructor(source, sourceType, plainMapper) { super(source, sourceType, plainMapper); 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; } } /** * @param {?} value * @return {?} */ setRef(value) { if (this.current) { this.existing.set(this.sourceType, this.getIdentity(), value); } } /** * @protected * @return {?} */ get ref() { if (this.current) { return this.existing.get(this.sourceType, this.getIdentity()); } } /** * @return {?} */ getIdentity() { // TODO: Move to the global store, so logic can change without bugs. return this.current[this.identity]; } /** * @return {?} */ next() { if (this.isCollection) { this.current = this.source[++this.idx]; return !!this.current; } else { return false; } } /** * @return {?} */ getKeys() { return Object.keys(this.current); } /** * @param {?} key * @param {?=} prop * @return {?} */ getValue(key, prop) { /** @type {?} */ let 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 {?} */ const 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 {?} */ deserialize(value, prop) { /** @type {?} */ const 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) * @protected * @param {?} prop * @param {?} value * @return {?} */ getRelationQuery(prop, value) { if (prop.relation && isPrimitive(value)) { return { [targetStore.getIdentityKey((/** @type {?} */ (prop.type.ref)), 'outgoing')]: value }; } } /** * @protected * @param {?} type * @param {?} value * @return {?} */ getCache(type, value) { /** @type {?} */ const idKey = targetStore.getIdentityKey(type, 'outgoing'); /** @type {?} */ const idVal = idKey && value[idKey]; if (idVal) { return this.existing.get(type, idVal); } } } 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 class DirectChildDeserializeMapper extends DirectDeserializeMapper { /** * @param {?} source * @param {?} sourceType * @param {?} existing * @param {?} plainMapper */ constructor(source, sourceType, existing, plainMapper) { super(source, sourceType, plainMapper); this.existing = existing; } } if (false) { /** * @type {?} * @protected */ DirectChildDeserializeMapper.prototype.existing; } // tslint:disable-next-line class DirectSerializeMapper extends BaseSerializer { /** * @param {?} container * @return {?} */ serialize(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 {?} */ serializeObject(obj, container) { /** @type {?} */ const data = {}; /** @type {?} */ const cb = (/** * @param {?} pMap * @return {?} */ (pMap) => { /** @type {?} */ const p = pMap.prop; if (p && targetStore.hasTarget(p.type.ref)) { /** @type {?} */ const type = p.type.ref; if (p.relation && !p.type.container) { /** @type {?} */ const idKey = 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]; } else { data[pMap.obj] = serialize(new DirectChildSerializeMapper(obj[pMap.cls], this.cache, this.plainMapper), type); } } else { /** @type {?} */ const newVal = this.plainMapper.serialize(transformValueOut(obj[pMap.cls], p)); data[pMap.obj] = newVal; } }); container.forEach(Object.keys(obj), cb); /** @type {?} */ const idKey = targetStore.getIdentityKey(container.target); if (idKey !== targetStore.getIdentityKey(container.target, 'outgoing')) { delete data[idKey]; } return data; } /** * @private * @param {?} arr * @param {?} container * @return {?} */ serializeCollection(arr, container) { return arr.map((/** * @param {?} s * @return {?} */ s => this.serializeObject(s, container))); } } if (false) { /** * @type {?} * @protected */ DirectSerializeMapper.prototype.cache; } // tslint:disable-next-line class DirectChildSerializeMapper extends DirectSerializeMapper { /** * @param {?} source * @param {?} cache * @param {?} plainMapper */ constructor(source, cache, plainMapper) { super(source, plainMapper); this.cache = cache; } } if (false) { /** * @type {?} * @protected */ DirectChildSerializeMapper.prototype.cache; } /** @type {?} */ const directMapper = { /** * @param {?} source * @param {?=} plainMapper * @return {?} */ serializer(source, plainMapper) { return new DirectSerializeMapper(source, plainMapper); }, /** * @template T, Z * @param {?} source * @param {?} sourceType * @param {?=} plainMapper * @return {?} */ deserializer(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