UNPKG

@pebula/metap

Version:
1,792 lines (1,780 loc) 104 kB
import { isFunction, stringify, isString, isNumber, isStaticDecorator, ensureTargetIsType, Mixin, MixinFree, isUndefined, getProtoChain } from '@pebula/utils'; import { __decorate, __metadata } from 'tslib'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const ERROR_EXEC_TYPE = Symbol('Throw'); class Errors { /** * Returns a marked Errors repository where the next call to an error object will throw. * * e.g. `errors.THROW().decorator(...)` will throw * @template THIS * @this {THIS} * @return {THIS} */ get throw() { return Object.assign(Object.create((/** @type {?} */ (this))), { [ERROR_EXEC_TYPE]: 'throw' }); } /** * @protected */ constructor() { // support for post instantiation mixins on the prototype (plugins) - don't use new. Errors.create(this); } /** * @param {?} target * @param {?} message * @param {?=} propertyName * @return {?} */ decorator(target, message, propertyName) { /** @type {?} */ const CLS = isFunction(target) ? target : target.constructor; if (!propertyName) { return this.ERROR(`Invalid decorator @ ${stringify(CLS)}}: ${message}`); } else { /** @type {?} */ const dot = CLS === target ? '#' : '.'; return this.ERROR(`Invalid decorator @ ${stringify(target)}${dot}${stringify(propertyName)}: ${message}`); } } /** * @param {?} model * @param {?} message * @return {?} */ model(model, message) { return this.ERROR(`Model Error [${stringify(model)}]: ${message}`); } /** * @param {?} model * @param {?} expectedCol * @return {?} */ modelSingleCol(model, expectedCol) { return this.ERROR(`Model Error:` + expectedCol ? `Expected a COLLECTION but got an OBJECT [Target: ${stringify(model)}]` : `Expected an OBJECT but got a COLLECTION [Target: ${stringify(model)}]`); } /** * \@internal * @template T * @param {?} message * @param {?=} assign * @return {?} */ ERROR(message, assign) { /** @type {?} */ const err = new Error(message); if (assign) { Object.assign(err, assign); } if (this[ERROR_EXEC_TYPE] === 'throw') { throw err; } else { return (/** @type {?} */ (err)); } } /** * Creates a new TargetStore instance. * @param {?=} instance optional, used internally * @return {?} */ static create(instance) { /** @type {?} */ const errors = instance || Object.create(Errors.prototype); return errors; } } /** @type {?} */ const errors = Errors.create(); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const emptyIterator = { /** * @return {?} */ next() { return { value: null, done: true }; }, /** * @return {?} */ [Symbol.iterator]() { return emptyIterator; } }; // TODO: move to separate package along with other utils on @tdm/core /** * A dual map, key->key->value * @template K, K1, V */ class DualKeyMap { constructor() { this.map = new Map(); this[Symbol.toStringTag] = 'Map'; } /** * @param {?} type * @param {?=} id * @return {?} */ has(type, id) { if (id === undefined) { return this.map.has(type); } else { /** @type {?} */ const t = this.map.get(type); return t ? t.has(id) : false; } } /** * @param {?} type * @param {?=} id * @return {?} */ get(type, id) { /** @type {?} */ const t = this.map.get(type); return id === undefined ? t : t && t.get(id); } /** * @param {?} type * @param {?=} id * @return {?} */ delete(type, id) { if (id === undefined) { return this.map.delete(type); } else { /** @type {?} */ const t = this.map.get(type); return !(t && t.delete(id)); } } /** * @param {?} type * @param {?} idOrMap * @param {?=} value * @return {?} */ set(type, idOrMap, value) { if (idOrMap instanceof Map) { if (arguments.length === 2) { this.map.set(type, idOrMap); } } else { /** @type {?} */ const t = this.map.get(type) || new Map(); t.set(idOrMap, value); this.map.set(type, t); } } /** * @param {?=} type * @return {?} */ clear(type) { if (type === undefined) { this.map.clear(); } { /** @type {?} */ const t = this.map.get(type); t && t.clear(); } } /** * @param {?} callbackfn * @param {?} type * @param {?=} thisArg * @return {?} */ forEach(callbackfn, type, thisArg) { if (callbackfn === true) { this.map.forEach((/** @type {?} */ (type)), thisArg); } else { /** @type {?} */ const t = this.map.get((/** @type {?} */ (type))); t && t.forEach((/** @type {?} */ (callbackfn)), thisArg); } } /** * @param {?=} type * @return {?} */ entries(type) { if (type === undefined) { return this.map.entries(); } else { /** @type {?} */ const t = this.map.get((/** @type {?} */ (type))); return t ? t.entries() : this.makeEmptyIterator(); } } /** * @param {?=} type * @return {?} */ keys(type) { if (type === undefined) { return this.map.keys(); } else { /** @type {?} */ const t = this.map.get((/** @type {?} */ (type))); return t ? t.keys() : this.makeEmptyIterator(); } } /** * @param {?=} type * @return {?} */ values(type) { if (type === undefined) { return this.map.values(); } else { /** @type {?} */ const t = this.map.get((/** @type {?} */ (type))); return t ? t.values() : this.makeEmptyIterator(); } } /** * @return {?} */ get size() { return this.map.size; } /** * @param {?} type * @return {?} */ sizeOf(type) { /** @type {?} */ const t = this.map.get(type); return t ? t.size : 0; } /** * @private * @return {?} */ makeEmptyIterator() { return emptyIterator; } /** * @return {?} */ [Symbol.iterator]() { return this.map[Symbol.iterator](); } } if (false) { /** * @type {?} * @protected */ DualKeyMap.prototype.map; /* Skipping unnamed member: readonly [Symbol.toStringTag]: 'Map' = 'Map';*/ } /** * The child of Map and Set * @template K, V */ class KeySet { constructor() { this.map = new Map(); } /** * @param {?} key * @param {?=} value * @return {?} */ has(key, value) { if (arguments.length === 1) { return this.map.has(key); } else { /** @type {?} */ const t = this.map.get(key); return t ? t.has(value) : false; } } /** * @param {?} key * @param {?=} index * @return {?} */ get(key, index) { if (arguments.length === 1) { return this.map.get(key); } else { /** @type {?} */ const set = this.map.get(key); if (set) { return SetExt.index(set, index); } } } /** * Set's the Set for a key. * @param {?} key * @param {?=} set An optional set, if not supplied a new Set is created. * @return {?} */ set(key, set) { if (!set) { set = new Set(); } this.map.set(key, set); return set; } /** * @template THIS * @this {THIS} * @param {?} key * @param {?} value * @return {THIS} */ add(key, value) { /** @type {?} */ const t = (/** @type {?} */ (this)).map.get(key) || new Set(); t.add(value); (/** @type {?} */ (this)).map.set(key, t); return (/** @type {?} */ (this)); } /** * @param {?=} key * @return {?} */ clear(key) { if (!key) { this.map.clear(); } else { /** @type {?} */ const t = this.map.get(key); t && t.clear(); } } /** * @param {?} key * @param {?=} value * @return {?} */ delete(key, value) { if (arguments.length === 1) { return this.delete(key); } else { /** @type {?} */ const t = this.map.get(key); return t ? t.delete(value) : false; } } /** * @param {?} key * @param {?} callbackfn * @param {?=} thisArg * @return {?} */ forEach(key, callbackfn, thisArg) { /** @type {?} */ const t = this.map.get(key); if (t) { t.forEach(callbackfn, thisArg); } } /** * Returns the amount of map entries * @return {?} */ get size() { return this.map.size; } /** * @param {?} key * @return {?} */ sizeOf(key) { /** @type {?} */ const t = this.map.get(key); return t ? t.size : 0; } } if (false) { /** @type {?} */ KeySet.prototype.map; } /** * @template T */ class SetExt extends Set { /** * @return {?} */ first() { return SetExt.first(this); } /** * @param {?} index * @return {?} */ index(index) { return SetExt.index(this, index); } /** * @return {?} */ asArray() { return SetExt.asArray(this); } /** * @param {?} subset * @return {?} */ isSuperset(subset) { return SetExt.isSuperset(this, subset); } /** * @param {...?} source * @return {?} */ combine(...source) { SetExt.combine(this, ...source); } /** * Deduct all of the sources * @param {...?} source * returns the target * @return {?} */ deduct(...source) { SetExt.deduct(this, ...source); } /** * @param {...?} source * @return {?} */ union(...source) { return SetExt.union((/** @type {?} */ (SetExt)), (/** @type {?} */ (this)), ...source); } /** * Returns all the items that were in this set and the supplied set. * @param {?} set * @return {?} */ intersection(set) { return SetExt.intersection(this, (/** @type {?} */ (set)), true); } /** * Returns all the items that are in this set, but not in the target set. * Returns a new SetExt instance. * @param {?} set * @return {?} */ difference(set) { return SetExt.difference(this, (/** @type {?} */ (set)), true); } /** * Returns all the items that were not in this set and the supplied set. * Returns a new SetExt instance. * @param {?} set * @return {?} */ negative(set) { return SetExt.negative(this, (/** @type {?} */ (set)), true); } /** * @template T * @param {?} set * @return {?} */ static first(set) { return set.values().next().value; } /** * @template T * @param {?} set * @param {?} index * @return {?} */ static index(set, index) { /** @type {?} */ const iterator = set.values(); for (let i = 0; i < index; i++) { if (iterator.next().done) { return undefined; } } return iterator.next().value; } /** * @template T * @param {?} set * @return {?} */ static asArray(set) { return Array.from(set); } /** * @param {?} set * @param {?} subset * @return {?} */ static isSuperset(set, subset) { // ohh NGC!!! /** * @param {?} v * @return {?} */ function x(v) { return !set.has(v); } return !SetExt.asArray(subset).some(x); } /** * @template T * @param {?} target * @param {...?} source * @return {?} */ static combine(target, ...source) { for (let i = 0, len = source.length; i < len; i++) { /** @type {?} */ const arr = Array.isArray(source[i]) ? source[i] : SetExt.asArray(source[i]); for (let z = 0, lenZ = arr.length; z < lenZ; z++) { if (!target.has(arr[z])) { target.add(arr[z]); } } } return target; } /** * Deduct all of the sources from the target. * @template T * @param {?} target * @param {...?} source * returns the target * @return {?} */ static deduct(target, ...source) { for (let i = 0, len = source.length; i < len; i++) { /** @type {?} */ const arr = SetExt.asArray(source[i]); for (let z = 0, lenZ = arr.length; z < lenZ; z++) { target.delete(arr[z]); } } return target; } /** * @template T * @param {...?} source * @return {?} */ static union(...source) { /** @type {?} */ const union = typeof source[0] === 'function' ? new ((/** @type {?} */ (source.shift())))() : new Set(); SetExt.combine(union, ...source); return union; } /** * Returns all the items that were in both sets. * @template T * @param {?} setA * @param {?} setB * @param {?=} initSetExt * @return {?} */ static intersection(setA, setB, initSetExt) { /** @type {?} */ const intersection = initSetExt ? new SetExt() : new Set(); /** @type {?} */ const arr = SetExt.asArray(setB); for (let z = 0, lenZ = arr.length; z < lenZ; z++) { if (setA.has(arr[z])) { intersection.add(arr[z]); } } return (/** @type {?} */ (intersection)); } /** * Returns all the items that are in source set, but not in the target set. * @template T * @param {?} source * @param {?} target * @param {?=} initSetExt * @return {?} */ static difference(source, target, initSetExt) { /** @type {?} */ const difference = initSetExt ? new SetExt(source) : new Set(source); /** @type {?} */ const arr = SetExt.asArray(target); for (let z = 0, lenZ = arr.length; z < lenZ; z++) { difference.delete(arr[z]); } return (/** @type {?} */ (difference)); } /** * Returns all the items that were not in both sets. * @template T * @param {?} source * @param {?} target * @param {?=} initSetExt * @return {?} */ static negative(source, target, initSetExt) { /** @type {?} */ const negative = initSetExt ? new SetExt(source) : new Set(source); /** @type {?} */ const arr = SetExt.asArray(target); for (let z = 0, lenZ = arr.length; z < lenZ; z++) { if (negative.has(arr[z])) { negative.delete(arr[z]); } else { negative.add(arr[z]); } } return (/** @type {?} */ (negative)); } } class MapExt { /** * Merge source map into target map. * @template K, V * @param {?} target * @param {?} source * @param {?=} diffOnly if true will only merge keys from source that does not exist on target. * @return {?} */ static mergeInto(target, source, diffOnly) { /** @type {?} */ const arr = MapExt.asKeyArray(source); for (let i = 0, len = arr.length; i < len; i++) { if (!diffOnly || !target.has(arr[i])) { target.set(arr[i], source.get(arr[i])); } } return target; } /** * Set the values of an array into a map * @template K, V * @param {?} arr * @param {?} keySelector A function returning the key to be used in the map * @param {?=} map The map to set on, optional. If not set a new map is created. * @param {?=} diffOnly Set only new values, optional. Valid only if a map is supplied. * @return {?} */ static fromArray(arr, keySelector, map, diffOnly) { if (!(map instanceof Map)) { map = new Map(); diffOnly = false; } for (let i = 0, len = arr.length; i < len; i++) { /** @type {?} */ const key = keySelector(arr[i]); if (!diffOnly || !map.has(key)) { map.set(key, arr[i]); } } return map; } /** * @template K, V * @param {?} map * @return {?} */ static asKeyValArray(map) { return Array.from(map.entries()); } /** * @template K, V * @param {?} map * @return {?} */ static asKeyArray(map) { return Array.from(map.keys()); } /** * @template K, V * @param {?} map * @return {?} */ static asValArray(map) { return Array.from(map.values()); } /** * @template K, V * @param {?} map * @return {?} */ static asObjectLiteral(map) { /** * @param {?} prev * @param {?} curr * @return {?} */ function x(prev, curr) { prev[curr.toString()] = map.get(curr); return prev; } ; return MapExt.asKeyArray(map).reduce(x, {}); } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const reflection = { /** * @param {?} target * @param {?} key * @return {?} */ designType(target, key) { return ((/** @type {?} */ (Reflect))).getMetadata('design:type', target, key); }, /** * @param {?} target * @param {?} key * @return {?} */ paramTypes(target, key) { return ((/** @type {?} */ (Reflect))).getMetadata('design:paramtypes', target, key); } }; /** * @param {?} getter * @return {?} */ function LazyInit(getter) { return (/** * @param {?} target * @param {?} propertyKey * @param {?=} descriptor * @return {?} */ (target, propertyKey, descriptor) => { if (descriptor) { throw new Error('LazyInit can only decorate properties'); } Object.defineProperty(target, propertyKey, { configurable: true, /** * @return {?} */ get() { /** @type {?} */ const ret = getter.call(this); Object.defineProperty(this, propertyKey, { value: ret }); return ret; } }); }); } const ɵ0 = /** * @return {?} */ function () { /** @type {?} */ const findRemove = (/** * @template T * @param {?} arr * @param {?} predicate * @param {?=} thisArg * @return {?} */ (arr, predicate, thisArg) => { /** @type {?} */ const idx = arr.findIndex(predicate, thisArg); if (idx > -1) { return arr.splice(idx, 1)[0]; } }); return { findRemove }; }; /** * \@pluginApi * @type {?} */ const array = ((ɵ0))(); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @record */ function NamingStrategyFn() { } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @abstract */ class BaseMetadata { /** * @param {?} decoratorInfo */ constructor(decoratorInfo) { this.decoratorInfo = decoratorInfo; this.name = decoratorInfo.name; } } if (false) { /** * The property name that the decorator wraps, if it wraps a property, member or constructor param. * \@return * @type {?} */ BaseMetadata.prototype.name; /** @type {?} */ BaseMetadata.prototype.decoratorInfo; } /** * @abstract */ class BaseParamMetadata extends BaseMetadata { /** * @return {?} */ get paramIndex() { return this.decoratorInfo.paramIndex; } /** * @param {?} di * @param {?} target */ constructor(di, target) { super(di); this.paramType = reflection.paramTypes(target.prototype, this.name)[di.paramIndex]; } } if (false) { /** @type {?} */ BaseParamMetadata.prototype.paramType; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @param {?} from * @param {?} fallback * @return {?} */ function propAliasConfig(from, fallback) { /** @type {?} */ let incoming; /** @type {?} */ let outgoing; if (!from) { incoming = outgoing = fallback; } else if (isString(from)) { incoming = outgoing = from; } else { incoming = from.incoming || fallback; outgoing = from.outgoing || fallback; } return { incoming, outgoing }; } /** * @param {?} from * @return {?} */ function propTransformConfig(from) { /** @type {?} */ let incoming; /** @type {?} */ let outgoing; if (isFunction(from)) { incoming = outgoing = from; } else if (from) { if (isFunction(from.incoming)) { incoming = from.incoming; } if (isFunction(from.outgoing)) { outgoing = from.outgoing; } } return { incoming, outgoing }; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const eventHandlers = new KeySet(); /** @type {?} */ const metaInitHandlers = new KeySet(); /** * Event listeners registration object for lifecycle metadata events on a target. * * \@pluginApi * \@mixable * \@singleton */ class TargetEvents { /** * @protected */ constructor() { // support for post instantiation mixins on the prototype (plugins) - don't use new. TargetEvents.create(this); } /** * @template TMetaArgs, TMetaClass, Z * @param {?} metaClass * @return {?} */ metaInit(metaClass) { return { /** * @param {?} handler * @return {?} */ run(handler) { metaInitHandlers.add(metaClass, handler); } }; } /** * Fired when the {\@link TargetMetadata} instance is created for the target) * * FireBefore: processType * @param {?} handler * @return {?} */ createMetadata(handler) { if (isFunction(handler)) { eventHandlers.add('createMetadata', handler); } } /** * Fired before the type is processed, after extending all metadata. * This event is not guaranteed to fire, it will fire only if the type is decorated with an appropriate decorator. * * FireAfter: createMetadata * FireBefore: processType * @param {?} handler * @return {?} */ beforeProcessType(handler) { if (isFunction(handler)) { eventHandlers.add('beforeProcessType', handler); } } /** * Fired when the type is processed, after extending all metadata. * This event is not guaranteed to fire, it will fire only if the type is decorated with an appropriate decorator. * * FireAfter: beforeProcessType * @param {?} handler * @return {?} */ processType(handler) { if (isFunction(handler)) { eventHandlers.add('processType', handler); } } /** * @param {?=} instance * @return {?} */ static create(instance) { /** @type {?} */ const targetStore = instance || Object.create(TargetEvents.prototype); targetStore.FIRE = EVENT_FIRE; return targetStore; } } if (false) { /** @type {?} */ TargetEvents.prototype.FIRE; } const ɵ0$1 = /** * @param {?} target * @return {?} */ (target) => fireTargetEvent('createMetadata', target), ɵ1 = /** * @param {?} target * @return {?} */ (target) => fireTargetEvent('beforeProcessType', target), ɵ2 = /** * @param {?} target * @return {?} */ (target) => fireTargetEvent('processType', target); /** @type {?} */ const EVENT_FIRE = { /** * @template TMetaArgs, TMetaClass, Z * @param {?} metaClass * @param {?} target * @param {?} value * @param {?=} metaArgs * @return {?} */ metaInit(metaClass, target, value, metaArgs) { /** @type {?} */ const eventMap = metaInitHandlers.get(metaClass); if (eventMap) { Array.from(eventMap.values()).forEach((/** * @param {?} handler * @return {?} */ handler => handler(target, value, metaArgs))); } }, createMetadata: (ɵ0$1), beforeProcessType: (ɵ1), processType: (ɵ2) }; /** @type {?} */ const targetEvents = TargetEvents.create(); /** * @param {?} event * @param {?} target * @return {?} */ function fireTargetEvent(event, target) { /** @type {?} */ const eventMap = eventHandlers.get(event); if (eventMap) { Array.from(eventMap.values()).forEach((/** * @param {?} handler * @return {?} */ handler => handler(target))); } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const lazyRefKey = Symbol('lazyRef'); /** @type {?} */ const toString = (/** * @return {?} */ function () { return stringify(this()); }); const ɵ0$2 = toString; /** * Allows to refer to references which are not yet defined. * * For instance, `lazyRef` is used when the `token` which we need to refer to for the purposes of * DI is declared, * but not yet defined. It is also used when the `token` which we use when creating a query is not * yet defined. * * ### Example * {\@example core/di/ts/forward_ref/forward_ref_spec.ts region='forward_ref'} * \@experimental * @template T * @param {?} lazyRefFn * @return {?} */ function lazyRef(lazyRefFn) { lazyRefFn[lazyRefKey] = lazyRef; lazyRefFn.toString = toString; return (/** @type {?} */ (lazyRefFn)); } (function (lazyRef) { /** * Lazily retrieves the reference value from a lazyRef. * * Acts as the identity function when given a non-forward-ref value. * * ### Example ([live demo](http://plnkr.co/edit/GU72mJrk1fiodChcmiDR?p=preview)) * * {\@example core/di/ts/forward_ref/forward_ref_spec.ts region='resolve_forward_ref'} * * See: {\@link lazyRef} * \@experimental * @param {?} type * @return {?} */ function resolve(type) { return isFunction(type) && type[lazyRefKey] === lazyRef ? type() : type; } lazyRef.resolve = resolve; })(lazyRef || (lazyRef = {})); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * Proxy definition for the current metadata class on an other metadata class. * * ProxyHost enables syntax sugar, where a user can avoid setting Decorators and set the metadata in one place. * For example: * * ```ts * class MyModel { * \@Prop() name: string; * * \@Prop() age: number; * } * ``` * * Say we want to exclude the property `age`: * * ```ts * class MyModel { * \@Prop() name: string; * * \@Prop() \@Exclude() age: number; * } * ``` * * If `\@Exclude` defines a \@Prop as a ProxyHost we can: * * ```ts * class MyModel { * \@Prop() name: string; * * \@Prop({exclude: true}) age: number; * } * ``` * * While this example doesn't seem to do much it actually does. * * - We can omit the import of `Exclude`, less code. * - We reduced the definition boilerplate, in this example its not much but others can have a big impact. * - The code is more readable, less decorators equals better readability. Prop holds the whole schema. * * * * Note that a property decorators and define a proxy in a class decorator allowing multiple properties * to be set from the root. * * Consider a model that uses multiple extensions (http, ng-dynamic-forms, etc...) having to define all of the * different decorators over and over has an impact, both over the payload and the developer experience. * * @record * @template T */ function ProxyHostMetadataArgs() { } if (false) { /** * The proxy metadata class * @type {?} */ ProxyHostMetadataArgs.prototype.host; /** * The key on the proxy metadata class arguments interface, this key is looked up and if set * the value is taken as the metadata arguments object for the current metadata class. * * > Defining a key on the proxy metadata arguments interface will result in a type error since typescript * will not recognize the key, to solve that a type extension is required. A ProxyHost can not be set without a type * extension * * Example: Creating a type extension to `PropMetadataArgs` * declare module './prop' { * interface PropMetadataArgs { * exclude?: true | ExcludeMetadataArgs; * } * } * @type {?} */ ProxyHostMetadataArgs.prototype.containerKey; /** * When true, treats an array as a collection where each value is a instance of the metadata. * This enables settings multiple metadata values. * @type {?|undefined} */ ProxyHostMetadataArgs.prototype.forEach; /** * An optional transformation function, allows changing the metadata arguments. * @param {?} metaArgs * @return {?} */ ProxyHostMetadataArgs.prototype.before = function (metaArgs) { }; } /** * @record * @template TMetaArgs, TMetaClass */ function MetaClassMetadataArgs() { } if (false) { /** * When true, the metadata is saved under the global key. * * > Global key logic is implemented throughout the library, make sure to follow this logic when * implementing custom behavior (for example, overriding the default factory and/or register methods) * Since most custom implementation are metadata class specific this should be an issue. * * * \@default undefined; * @type {?|undefined} */ MetaClassMetadataArgs.prototype.single; /** * A Metadata class to inherit the MetaClassMetadataArgs from. * * Note that the MetaClassMetadataArgs used to defined the parent are used and not the * MetaClassMetadata instance. * @type {?|undefined} */ MetaClassMetadataArgs.prototype.inherit; /** * Defines a proxy for the current metadata class on an other metadata class. * See {\@link ProxyHostMetadataArgs} * @type {?|undefined} */ MetaClassMetadataArgs.prototype.proxy; /** * Register the metadata instance. * This operation save the instance in the targetStore. * \@param meta * @type {?|undefined} */ MetaClassMetadataArgs.prototype.register; /** * Optional implementation of extend logic FOR non-single metadata, logic that handles 1 type extending another type. * If not set, the Metadata class is not extendable and will not inherit metadata from child types. * If the method returns undefined it will also not extend the Metadata class. * * 'to' can be undefined, if so it means that that Metadata class was never assigned to the type. * * #### You can set on of the predefined extend functions. * - prop: An extending implementation suitable for property decorators. Expecting a `Map<TdmPropertyKey, T>`, it * will merge the source into the target. * * \@param from * \@param to * \@param meta * \@param meta.from the target source * \@param meta.to the target target * \@return the new extended value. * @type {?|undefined} */ MetaClassMetadataArgs.prototype.extend; /** * Optional implementation of extend logic FOR single metadata, logic that handles one type extending another type. * If not set, the Metadata class is not extendable and will not inherit metadata from child types. * If the method returns undefined it will also not extend the Metadata class. * * 'to' can be undefined, if so it means that that Metadata class was never assigned to the type. * * \@param from * \@param to * \@param meta * \@return the new extended value. * @type {?|undefined} */ MetaClassMetadataArgs.prototype.extendSingle; /** * A list of supported decoration targets for a metadata class. * If not set (or empty list) all of the targets are allowed. * @type {?|undefined} */ MetaClassMetadataArgs.prototype.allowOn; /** * An optional function, that is invoked right after the metadata class is created for the meta-class. * Note that this event run ONCE for every meta-class class, which happens when the decorator \@MetaClass is invoked. * @type {?|undefined} */ MetaClassMetadataArgs.prototype.onCreated; /** * Additional decorators to run before the decorator for this meta-class invokes. * Note that the factory function run's before but the actual decorators run after * @type {?|undefined} */ MetaClassMetadataArgs.prototype.decorateBefore; /** * Additional decorators to run after the decorator for this meta-class invokes. * Note that the factory function run's after but the actual decorators run before * @type {?|undefined} */ MetaClassMetadataArgs.prototype.decorateAfter; /** * Create a new metadata instance. * @this {?} * @param {?} metaArgs * @param {?} target * @param {?} info * @param {?=} key * @param {?=} desc * @return {?} */ MetaClassMetadataArgs.prototype.factory = function (metaArgs, target, info, key, desc) { }; } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @param {...?} args * @return {?} */ function decoratorInfo(...args) { if (isFunction(args[0]) && !args[1]) { // target is function and key is not set return { type: 'class' }; } else { /** @type {?} */ const type = args.length === 3 && isNumber(args[2]) ? 'param' : 'member'; /** @type {?} */ const result = { type, name: args[1], isStatic: isStaticDecorator(args[0]), hasDescriptor: args.length === 3 && type === 'member' }; if (type === 'param') { result.paramIndex = args[2]; } return result; } } /** @type {?} */ const registerHelpers = (/** @type {?} */ ({})); /** @type {?} */ const extendHelpers = (/** @type {?} */ ({})); /** * @param {?} type * @param {?} name * @param {?} helperFn * @return {?} */ function setMetaHelper(type, name, helperFn) { switch (type) { case 'extend': extendHelpers[name] = helperFn; break; case 'register': registerHelpers[name] = helperFn; break; default: break; } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const store = new Map(); /** * A token representing single items (see {\@link MetaClassMetadataArgs.single}) * Use this token as a key for single items in TargetMetadata */ class GLOBAL_KEY { } // tslint:disable-line:class-name // tslint:disable-line:class-name /** * Represents management and control logic for metadata class's * @template TMetaArgs, TMetaClass, Z */ // tslint:disable-next-line:max-classes-per-file class MetaClassMetadata { /** * @private * @param {?} target * @param {?=} metaArgs */ constructor(target, metaArgs) { this.target = target; this.metaArgs = metaArgs; this.proxyTo = []; if (!this.metaArgs) { this.metaArgs = {}; } else { if (metaArgs.inherit) { this.metaArgs = metaArgs = Object.assign({}, MetaClass.get(metaArgs.inherit).metaArgs, metaArgs); } if (metaArgs.factory) { this.factory = metaArgs.factory; } if (metaArgs.register) { if (isString(metaArgs.register)) { this.register = registerHelpers[metaArgs.register]; } else if (isFunction(metaArgs.register)) { this.register = metaArgs.register; } } if (metaArgs.proxy) { /** @type {?} */ const proxy = (/** @type {?} */ (metaArgs.proxy)); proxy.metaClass = this; MetaClass.get(metaArgs.proxy.host).proxyTo.push(proxy); } if (metaArgs.extend) { if (metaArgs.single === true) { // TODO: make error message clear; throw new Error('Extending a single class is done using extendSingle'); } if (isString(metaArgs.extend)) { this.extend = extendHelpers[metaArgs.extend]; } else if (isFunction(metaArgs.extend)) { this.extend = metaArgs.extend; } } if (isFunction(metaArgs.extendSingle)) { if (metaArgs.single !== true) { // TODO: make error message clear; throw new Error('Extending a non-single class is done using extend'); } this.extendSingle = metaArgs.extendSingle; } if (isFunction(metaArgs.onCreated)) { metaArgs.onCreated(this); } } } /** * Create a new instance of the metadata class * @param {?} metaArgs * @param {?} target * @param {?=} key * @param {?=} desc * @return {?} */ create(metaArgs, target, key, desc) { return this.createCurry(metaArgs, target, key, desc)(); } /** * @param {?} metaArgs * @param {?} target * @param {?=} key * @param {?=} desc * @return {?} */ createCurry(metaArgs, target, key, desc) { /** @type {?} */ const info = decoratorInfo(target, key, desc); /** @type {?} */ const allowOn = this.metaArgs.allowOn; if (allowOn && allowOn.length > 0) { if (info.type === 'class') { if (allowOn.indexOf('class') === -1) { throw new Error(`Metadata class ${stringify(this.target)} can not decorate a class (${stringify(target)})`); } } else if (info.isStatic) { if (allowOn.indexOf('staticMember') === -1) { throw new Error(`Metadata class ${stringify(this.target)} can not decorate a static member (${stringify(target)}#${key.toString()})`); } } else if (info.type === 'param') { if (allowOn.indexOf('param') === -1) { throw new Error(`Metadata class ${stringify(this.target)} can not decorate a param (${stringify(target)}#${key.toString()})`); } } else { if (allowOn.indexOf('member') === -1) { throw new Error(`Metadata class ${stringify(this.target)} can not decorate an instance member ` + `(${stringify(target.constructor)}.${key.toString()})`); } } } /** @type {?} */ const meta = this.factory(metaArgs, target, info, key, desc); /** @type {?} */ const curry = (/** @type {?} */ (((/** * @param {?=} _meta * @return {?} */ (_meta) => { if (!_meta) { _meta = meta; } // in case factory return undefined if (!_meta) { return; } this.register(_meta); /** @type {?} */ const chain = this.singleChain(_meta); if (chain) { // we use this class's register implementation for all chain.forEach((/** * @param {?} c * @return {?} */ c => this.register(c))); } targetEvents.FIRE.metaInit(_meta.metaClassKey, _meta.target, _meta.metaValue, metaArgs); /** @type {?} */ const proxies = this.findProxies(metaArgs); proxies.forEach((/** * @param {?} ra * @return {?} */ ra => { if (ra) { // we check since findProxies returns undefined when no key on metadata arguments was found for (let i = 0, len = ra.args.length; i < len; i++) { ra.meta.create(ra.args[i], target, key, desc); } } })); return meta && meta.metaValue; })))); curry.meta = meta; return curry; } /** * @param {...?} args * @return {?} */ createDecorator(...args) { return (/** @type {?} */ (((/** * @param {?} def * @return {?} */ (def) => { return (/** * @param {?} target * @param {?} key * @param {?=} desc * @return {?} */ (target, key, desc) => { const { decorateBefore, decorateAfter } = this.metaArgs; /** @type {?} */ const post = isFunction(decorateBefore) ? decorateBefore(def) : []; /** @type {?} */ const pre = isFunction(decorateAfter) ? decorateAfter(def) : []; for (const d of pre) { d(target, key, desc); } this.create(def, target, key, desc); for (const d of post) { d(target, key, desc); } }); })))); } /** * \@internal * @param {?} metaArgs * @param {?} target * @param {?} info * @param {?=} key * @param {?=} desc * @return {?} */ factory(metaArgs, target, info, key, desc) { /** @type {?} */ const type = ensureTargetIsType(target); /** @type {?} */ const meta = { info, target: type, metaClassKey: this.target, metaPropKey: this.metaArgs.single === true ? GLOBAL_KEY : info.name, metaValue: new this.target(metaArgs, info, type) }; return meta; } /** * Given a MetaClassInstanceDetails, if its a single metadata (single) and has a chain (inherit) * it will go up the chain and create MetaClassInstanceDetails that match the given one just with * the inherited class as the metaClass property. * * This is used to allow registering inheriting single metadata classes. * For example, a ModelMetadata might get extended by an adapter resource, the only metadata class * registered is the extending one, if we will not register the ModelMetadata token as well logic * that expects to find it will fail. * @private * @param {?} meta * @return {?} */ singleChain(meta) { if (this.metaArgs.single === true && this.metaArgs.inherit) { /** @type {?} */ const parentMeta = Object.create(meta); parentMeta.metaClassKey = this.metaArgs.inherit; /** @type {?} */ const deep = getMetaClass(this.metaArgs.inherit).singleChain(meta); return deep ? [parentMeta, ...deep] : [parentMeta]; } } /** * @private * @param {?} metaArgs * @return {?} */ findProxies(metaArgs) { /** @type {?} */ const results = []; if (metaArgs) { // we need to take into account parent metadata if (this.metaArgs.inherit) { results.splice(0, 0, ...MetaClass.get(this.metaArgs.inherit).findProxies(metaArgs)); } /** @type {?} */ const local = this.proxyTo.map((/** * @param {?} proxy * @return {?} */ proxy => { if (metaArgs.hasOwnProperty(proxy.containerKey)) { /** @type {?} */ const myMetaArgs = isFunction(proxy.before) ? proxy.before(metaArgs[proxy.containerKey]) : metaArgs[proxy.containerKey]; delete metaArgs[proxy.containerKey]; return proxy.forEach === true && Array.isArray(myMetaArgs) ? { meta: proxy.metaClass, args: myMetaArgs } : { meta: proxy.metaClass, args: [myMetaArgs] }; } })); results.splice(results.length, 0, ...local); } return results; } /** * A factory for {\@link MetaClassMetadata} instances * * > This will create an instance of a metadata class container. * A Metadata container can create instances of the metadata class it "contains", thus, the instance * returned from the static `create` method also has a 'create' method however that instance level * `create` method is a factory for instance of the metadata class, not the container. * * @template TMetaArgs, TMetaClass * @param {?} target * @param {?=} metaArgs * @return {?} */ static create(target, metaArgs) { return new MetaClassMetadata(target, metaArgs); } } if (false) { /** * @type {?} * @private */ MetaClassMetadata.prototype.proxyTo; /** * \@internal * set by target-store.ts * @type {?} */ MetaClassMetadata.prototype.register; /** * \@internal * @type {?} */ MetaClassMetadata.prototype.extend; /** @type {?} */ MetaClassMetadata.prototype.extendSingle; /** @type {?} */ MetaClassMetadata.prototype.target; /** @type {?} */ MetaClassMetadata.prototype.metaArgs; } /** * @template TMetaArgs, TMetaClass * @param {?} target * @return {?} */ function getMetaClass(target) { return store.get(target); } /** * @template TMetaArgs, TMetaClass, Z * @param {?=} metaArgs * @return {?} */ function MetaClass(metaArgs) { return (/** * @param {?} target * @return {?} */ (target) => { store.set(target, MetaClassMetadata.create(target, metaArgs)); }); } // tslint:disable-next-line:no-namespace (function (MetaClass) { /** * Creates a metadata class instance. * This is a shortcut for `MetaClass.get(MyMetadataClass).create(...); * @template TMetaArgs, TMetaClass, Z * @param {?} metaClass * @param {?} metaArgs * @param {?} target * @param {?=} key * @param {?=} desc * @return {?} */ function create(metaClass, metaArgs, target, key, desc) { return store.get(metaClass).create(metaArgs, target, key, desc); } MetaClass.create = create; /** * @template TMetaArgs, TMetaClass, Z * @param {?} metaClass * @param {...?} args * @return {?} */ function decorator(metaClass, ...args) { return (/** @type {?} */ (store.get(metaClass).createDecorator())); } MetaClass.decorator = decorator; /** * @param {?} fn * @return {?} */ function defaultRegistrator(fn) { MetaClassMetadata.prototype['register'] = fn; } MetaClass.defaultRegistrator = defaultRegistrator; })(MetaClass || (MetaClass = {})); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @record */ function DecoratorInfo() { } if (false) { /** @type {?} */ DecoratorInfo.prototype.type; /** @type {?|unde