UNPKG

ngx-decorate

Version:

Useful decorators for Angular 2 and above

591 lines (554 loc) 19.6 kB
/*! MIT License Copyright (c) 2018 Art Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define('ngx-decorate', ['exports'], factory) : (factory((global.NgxDecorate = {}))); }(this, (function (exports) { 'use strict'; /** * Call .markForCheck() on the change detector ref whenever this property is written to. * * @param propName Property at which the change detector can be found * @param conf Optional configuration */ function CdrProp(propName, conf) { if (conf === void 0) { conf = {}; } return function (target, key) { var _a; var sym = Symbol("value:" + key.toString()); var defaultDescriptor = { configurable: true, enumerable: true }; Object.defineProperties(target, (_a = {}, _a[sym] = { configurable: false, enumerable: false, value: conf.default || target[key], writable: true }, _a[key] = Object.assign(defaultDescriptor, conf.desc || {}, { get: function () { return this[sym]; }, set: function (v) { this[sym] = v; if (!conf.destroyed || !this[conf.destroyed]) { this[propName].markForCheck(); } } }), _a)); }; } /** @internal */ function ensureSymbol(target, symbol, value) { if (!target[symbol]) { Object.defineProperty(target, symbol, { configurable: false, enumerable: false, value: value, writable: false }); } return target[symbol]; } /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ function __values(o) { var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; if (m) return m.call(o); return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; } /** @internal */ function defineImmutable(target, prop, value) { Object.defineProperty(target, prop, { configurable: false, enumerable: false, value: value, writable: false }); } /** @internal */ function toAbridged(lifecycle) { if (lifecycle === 2 /* POST_INIT */ || lifecycle === 0 /* PRE_INIT */) { return 0 /* INIT */; } return 1 /* DESTROY */; } /** @internal */ var _unsubscribe = Symbol('unsubscribe'); /** @internal */ var _complete = Symbol('complete'); /** @internal */ var _lazySubj = Symbol('lazySubj'); /** @internal */ var _destroyed = Symbol('destroyed'); /** @internal */ var _init = Symbol('init'); /** @internal */ var _setProp = Symbol('setProp'); /** @internal */ var _subscrTo = Symbol('subscrTo'); /** @internal */ var _subscrToSubs = Symbol('subscrToSubs'); /** @internal */ var _hookMgr = Symbol('hookMgr'); /** @internal */ function ngOnDestroy() { //mock } /** @internal */ function ngOnInit() { // mock } /** @internal */ var HookManager = /** @class */ (function () { function HookManager(proto) { this.proto = proto; this.postDestroys = new Set(); this.postInits = new Set(); this.preDestroys = new Set(); this.preInits = new Set(); this.origInit = proto.ngOnInit || ngOnInit; this.origDestroy = proto.ngOnDestroy || ngOnDestroy; } Object.defineProperty(HookManager.prototype, "newDestroy", { get: function () { var value = this.newFn(this.preDestroys, this.postDestroys, this.origDestroy); defineImmutable(this, 'newDestroy', value); return value; }, enumerable: true, configurable: true }); Object.defineProperty(HookManager.prototype, "newInit", { get: function () { var value = this.newFn(this.preInits, this.postInits, this.origInit); defineImmutable(this, 'newInit', value); return value; }, enumerable: true, configurable: true }); HookManager.for = function (proto) { if (!proto[_hookMgr]) { defineImmutable(proto, _hookMgr, new HookManager(proto)); } return proto[_hookMgr]; }; HookManager.prototype.add = function (lifecycle, hookFn) { this.hooks(lifecycle).add(hookFn); var type = toAbridged(lifecycle); if (type === 1 /* DESTROY */) { this.proto.ngOnDestroy = this.preDestroys.size || this.postDestroys.size ? this.newDestroy : this.origDestroy; } else { this.proto.ngOnInit = this.preInits.size || this.postInits.size ? this.newInit : this.origInit; } }; HookManager.prototype.hooks = function (lifecycle) { switch (lifecycle) { case 0 /* PRE_INIT */: return this.preInits; case 1 /* PRE_DESTROY */: return this.preDestroys; case 2 /* POST_INIT */: return this.postInits; default: return this.postDestroys; } }; HookManager.prototype.newFn = function (pres, posts, orig) { return function () { var e_1, _a, e_2, _b; try { try { for (var pres_1 = __values(pres), pres_1_1 = pres_1.next(); !pres_1_1.done; pres_1_1 = pres_1.next()) { var fn = pres_1_1.value; fn(this); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (pres_1_1 && !pres_1_1.done && (_a = pres_1.return)) _a.call(pres_1); } finally { if (e_1) throw e_1.error; } } orig.apply(this, arguments); } finally { try { for (var posts_1 = __values(posts), posts_1_1 = posts_1.next(); !posts_1_1.done; posts_1_1 = posts_1.next()) { var fn = posts_1_1.value; fn(this); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (posts_1_1 && !posts_1_1.done && (_b = posts_1.return)) _b.call(posts_1); } finally { if (e_2) throw e_2.error; } } } }; }; return HookManager; }()); defineImmutable(HookManager.prototype, Symbol.toStringTag, 'HookManager'); /** @internal */ function mkPropertyKeyDecorator(symbolKey, hook, lc) { return function (target, prop) { ensureSymbol(target, symbolKey, []).push(prop); HookManager.for(target).add(lc, hook); }; } /** @internal */ function unsubArray(props) { var e_1, _a; try { for (var props_1 = __values(props), props_1_1 = props_1.next(); !props_1_1.done; props_1_1 = props_1.next()) { var sub = props_1_1.value; sub.unsubscribe(); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (props_1_1 && !props_1_1.done && (_a = props_1.return)) _a.call(props_1); } finally { if (e_1) throw e_1.error; } } } /** @internal */ function processProp(prop) { if (prop) { if (Array.isArray(prop)) { unsubArray(prop); } else { prop.unsubscribe(); } } } /** @internal */ function unsubscribe(self) { var e_2, _a, e_3, _b; if (self[_unsubscribe]) { try { for (var _c = __values(self[_unsubscribe]), _d = _c.next(); !_d.done; _d = _c.next()) { var prop = _d.value; processProp(self[prop]); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_d && !_d.done && (_a = _c.return)) _a.call(_c); } finally { if (e_2) throw e_2.error; } } } if (self[_subscrToSubs]) { try { for (var _e = __values(self[_subscrToSubs]), _f = _e.next(); !_f.done; _f = _e.next()) { var prop = _f.value; processProp(prop); } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (_f && !_f.done && (_b = _e.return)) _b.call(_e); } finally { if (e_3) throw e_3.error; } } } } /** * Automatically unsubscribe from the subscription(s) present at this property. * The property can be either a single subscription or an array of subscriptions. */ function Unsubscribe() { return mkPropertyKeyDecorator(_unsubscribe, unsubscribe, 3 /* POST_DESTROY */); } /** @internal */ function completeArray(inp) { var e_1, _a; try { for (var inp_1 = __values(inp), inp_1_1 = inp_1.next(); !inp_1_1.done; inp_1_1 = inp_1.next()) { var c = inp_1_1.value; c.complete(); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (inp_1_1 && !inp_1_1.done && (_a = inp_1.return)) _a.call(inp_1); } finally { if (e_1) throw e_1.error; } } } /** @internal */ function processProp$1(prop) { if (prop) { if (Array.isArray(prop)) { completeArray(prop); } else { prop.complete(); } } } /** @internal */ function complete(self) { var e_1, _a; if (self[_complete]) { try { for (var _b = __values(self[_complete]), _c = _b.next(); !_c.done; _c = _b.next()) { var prop = _c.value; processProp$1(self[prop]); } } 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; } } } } /** * Automatically completes the subjects and event emitters at this property. * The property can be either a single object or an array of objects. */ function Complete() { return mkPropertyKeyDecorator(_complete, complete, 3 /* POST_DESTROY */); } /** @internal */ function lazySubj(self) { if (Array.isArray(self[_lazySubj])) { completeArray(self[_lazySubj]); } } /** * Decorate a getter that returns a subject. The subject will automatically get completed * when the component/service/pipe is destroyed. */ function LazySubject() { return function (_target, key, desc) { var orig = desc.get; if (!orig) { throw new Error('LazySubject can only decorate getters'); } desc.get = function () { var value = orig.apply(this, arguments); Object.defineProperty(this, key, { configurable: true, enumerable: desc.enumerable, value: value }); ensureSymbol(this, _lazySubj, []).push(value); return value; }; HookManager.for(_target).add(3 /* POST_DESTROY */, lazySubj); }; } /** @internal */ function destroyed(self) { if (self[_destroyed]) { self[self[_destroyed]] = true; } } /** Set the given property to true when the component is destroyed */ function TrackDestroyed() { return function (target, value) { defineImmutable(target, _destroyed, value); HookManager.for(target).add(1 /* PRE_DESTROY */, destroyed); }; } /** @internal */ function setProp(self) { var e_1, _a; if (self[_setProp]) { try { for (var _b = __values(self[_setProp]), _c = _b.next(); !_c.done; _c = _b.next()) { var p = _c.value; self[p.prop] = p.value; } } 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; } } } } /** * Mark the property as a subject setter. When written to, it will call .next(value) on the subject. * The decorator's <b>default</b> config option only works on items that make use of the OnInit hook, * i.e. it will <b>not</b> work for services and pipes. * * Because the <b>default</b> config option utilises the OnInit hook, it should not be used on * properties that are component inputs as the input would get overridden during the hook. * * @param subjectPropName Name of the property at which the subject resides * @param conf Optional configuration */ function SubjectSetter(subjectPropName, conf) { if (conf === void 0) { conf = {}; } return function (target, prop) { var _a; var symbolValue = Symbol("subjectSetter:" + prop.toString()); var defaultDescriptor = { configurable: true, enumerable: true }; var defaultValue = conf.default || target[prop]; if (defaultValue) { ensureSymbol(target, _setProp, []) .push({ prop: prop, value: defaultValue }); HookManager.for(target).add(2 /* POST_INIT */, setProp); } Object.defineProperties(target, (_a = {}, _a[symbolValue] = { configurable: false, enumerable: false, value: defaultValue, writable: true }, _a[prop] = Object.assign(defaultDescriptor, conf.desc || {}, { get: function () { return this[symbolValue]; }, set: function (v) { this[symbolValue] = v; this[subjectPropName].next(v); } }), _a)); }; } /** @internal */ function init(self) { if (self[_init]) { self[self[_init]] = true; } } /** Set the given property to true when the component is initialised */ function TrackInit() { return function (target, value) { defineImmutable(target, _init, value); HookManager.for(target).add(0 /* PRE_INIT */, init); }; } /** @internal */ function processSource(self, source, subs) { var subscrFn; var cdrProp = source.cfg.cdrProp; if (cdrProp) { subscrFn = function (v) { self[source.target] = v; self[source.cfg.cdrProp].markForCheck(); }; } else { subscrFn = function (v) { self[source.target] = v; }; } subs.push(self[source.source].subscribe(subscrFn, console.error)); } /** @internal */ function subscribeTo(self) { var e_1, _a; var sources = self[_subscrTo]; if (sources) { var subs = ensureSymbol(self, _subscrToSubs, []); try { for (var sources_1 = __values(sources), sources_1_1 = sources_1.next(); !sources_1_1.done; sources_1_1 = sources_1.next()) { var source = sources_1_1.value; if (self[source.source]) { processSource(self, source, subs); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (sources_1_1 && !sources_1_1.done && (_a = sources_1.return)) _a.call(sources_1); } finally { if (e_1) throw e_1.error; } } } } /** * Subscribe to an observable and set its last emitted value to this property * * This decorator requires the ngOnInit hook and therefore will only work with directives and components. * * @param prop Property at which the observable resides * @param cfg Optional configuration */ function SubscribeTo(prop, cfg) { if (cfg === void 0) { cfg = {}; } return function (target, key) { ensureSymbol(target, _subscrTo, []) .push({ cfg: cfg, source: prop, target: key }); var mgr = HookManager.for(target); mgr.add(2 /* POST_INIT */, subscribeTo); mgr.add(3 /* POST_DESTROY */, unsubscribe); }; } exports.CdrProp = CdrProp; exports.Unsubscribe = Unsubscribe; exports.Complete = Complete; exports.LazySubject = LazySubject; exports.TrackDestroyed = TrackDestroyed; exports.SubjectSetter = SubjectSetter; exports.TrackInit = TrackInit; exports.SubscribeTo = SubscribeTo; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=umd.js.map