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