@pebula/metap
Version:
meta-programming tools
1,303 lines (1,284 loc) • 41.5 kB
JavaScript
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