UNPKG

@ortoo/angular-resource

Version:

Magical CRUD resource management for angular

216 lines 26.2 kB
// tslint:disable max-classes-per-file import * as jiff from 'jiff'; import * as moment from 'moment'; import { Subject } from 'rxjs/Subject'; import { ObjectUnsubscribedError } from 'rxjs/util/ObjectUnsubscribedError'; import { clone } from 'lodash'; import { isObject } from 'lodash'; import { isString } from 'lodash'; import { map } from 'lodash'; let hiddenKeyRegex = /^\$+/; let TIMESTAMP_RE = /^(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+)|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d)|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d)$/; // tslint:disable-line max-line-length export function convertJsonDates(jsonData) { let outObj; if (Array.isArray(jsonData)) { outObj = []; } else { outObj = {}; } for (let key of Object.keys(jsonData)) { let val = jsonData[key]; let res = val; if (isString(val)) { // The value is a string - does it match any of our things we want to convert if (TIMESTAMP_RE.test(val)) { // We're probably a timestamp let dt = moment(val); if (dt.isValid()) { res = dt.toDate(); } } } else if (Array.isArray(val) || isObject(val)) { res = convertJsonDates(val); } outObj[key] = res; } return outObj; } export function toJSON(obj) { return JSON.parse(JSON.stringify(obj)); } export function diff(obj1, obj2) { obj1 = toJSON(obj1); obj2 = toJSON(obj2); return jiff.diff(obj1, obj2); } export function applyPatch(res, patch) { // Go to JSON - don't do anything with dates let obj = JSON.parse(JSON.stringify(res, toJsonReplacer)); obj = jiff.patch(patch, obj); // Go back to dates etc obj = convertJsonDates(obj); removeResValues(res); setResValues(res, obj); } export function mergeObjects(mine, old, yours) { // Make copies - we might modify the objects if ids dont exist mine = clone(mine); old = clone(old); // First sort out _id's. We could have a new id if one doesn't exist on mine and old if (!mine._id && !old._id && yours._id) { mine._id = yours._id; old._id = yours._id; } // We also need to convert into and out of dates mine = toJSON(mine); old = toJSON(old); yours = toJSON(yours); let yourpatch = jiff.diff(old, yours); let mypatch = jiff.diff(old, mine); let mypaths = map(mypatch, 'path'); let patch = yourpatch.filter((patchval) => { return mypaths.indexOf(patchval.path) === -1; }); let patched = jiff.patch(patch, mine); return convertJsonDates(patched); } export function forEachVal(res, cb) { for (let key in res) { if (!hiddenKeyRegex.test(key)) { cb(res, key); } } } export function toJsonReplacer(key, value) { let val = value; if (isString(key) && key.charAt(0) === '$') { val = undefined; } return val; } export function fromJsonReviver(_, value) { let val = value; if (isString(value) && TIMESTAMP_RE.test(value)) { let dt = moment(value); if (dt.isValid()) { val = dt.toDate(); } } return val; } export function toObject(res) { // The toJsonReplacer gets rid of attributes beginning with $ and the fromJsonReviver // converts date strings back into dates let str = JSON.stringify(res, toJsonReplacer); try { return JSON.parse(str, fromJsonReviver); } catch (err) { // Older versions of IE8 throw 'Out of stack space' errors if we use a reviver function // due to the bug described here: http://support.microsoft.com/kb/976662. Everyone hates // IE if (err.message === 'Out of stack space') { return convertJsonDates(JSON.parse(str)); } throw (err); } } export function removeResValues(res) { forEachVal(res, (_, key) => { delete res[key]; }); } export function setResValues(res, vals) { for (let key of Object.keys(vals)) { res[key] = vals[key]; } } export function persistentStorageKey(url) { return 'or2ws:' + url; } export function advancedStorage(localForage) { return localForage.driver() !== 'localStorageWrapper'; } // lifted from here -> http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523 export function uuid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { let r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); // tslint:disable-line return v.toString(16); }); } export class Deferred { constructor() { /* A method to resolve the associated Promise with the value passed. * If the promise is already settled it does nothing. * * @param {anything} value : This value is used to resolve the promise * If the value is a Promise then the associated promise assumes the state * of Promise passed as value. */ this.resolve = null; /* A method to reject the assocaited Promise with the value passed. * If the promise is already settled it does nothing. * * @param {anything} reason: The reason for the rejection of the Promise. * Generally its an Error object. If however a Promise is passed, then the Promise * itself will be the reason for rejection no matter the state of the Promise. */ this.reject = null; /* A newly created Pomise object. * Initially in pending state. */ this.promise = new Promise((resolve, reject) => { this.resolve = resolve; this.reject = reject; }); Object.freeze(this); } } export function isSubscribableOrPromise(value) { return value && (typeof value.subscribe === 'function' || typeof value.then === 'function'); } // Like BehaviorSubject but waits for a promise to resolve export class ResolvedSubject extends Subject { constructor(promise) { super(); promise.then(val => { this._resolved = true; this.next(val); }); } get value() { return this.getValue(); } getValue() { if (this.hasError) { throw this.thrownError; } else if (this.closed) { throw new ObjectUnsubscribedError(); } else { return this._value; } } next(value) { if (this._resolved) { this._value = value; super.next(value); } } _subscribe(subscriber) { const subscription = super._subscribe(subscriber); if (this._resolved && subscription && !subscription.closed) { subscriber.next(this._value); } return subscription; } } export function convertToResolvedSubject(subject, promise) { let resolvedSub = new ResolvedSubject(promise); subject.subscribe(resolvedSub); return resolvedSub; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiL0BvcnRvby9hbmd1bGFyLXJlc291cmNlLyIsInNvdXJjZXMiOlsidXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsc0NBQXNDO0FBRXRDLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBR2pDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFHdkMsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFFNUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUMvQixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDbEMsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUk3QixJQUFJLGNBQWMsR0FBRyxNQUFNLENBQUM7QUFFNUIsSUFBSSxZQUFZLEdBQUcsNklBQTZJLENBQUMsQ0FBQyxzQ0FBc0M7QUFFeE0sTUFBTSwyQkFBMkIsUUFBYTtJQUM1QyxJQUFJLE1BQU0sQ0FBQztJQUNYLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzVCLE1BQU0sR0FBRyxFQUFFLENBQUM7SUFDZCxDQUFDO0lBQUMsSUFBSSxDQUFDLENBQUM7UUFDTixNQUFNLEdBQUcsRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUNELEdBQUcsQ0FBQyxDQUFDLElBQUksR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RDLElBQUksR0FBRyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN4QixJQUFJLEdBQUcsR0FBRyxHQUFHLENBQUM7UUFDZCxFQUFFLENBQUMs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QixDQUFDO0lBQ0gsQ0FBQztJQUVTLFVBQVUsQ0FBQyxVQUF5QjtRQUM1QyxNQUFNLFlBQVksR0FBRyxLQUFLLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2xELEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksWUFBWSxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDekQsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDakMsQ0FBQztRQUNELE1BQU0sQ0FBQyxZQUFZLENBQUM7SUFDdEIsQ0FBQztDQUNGO0FBRUQsTUFBTSxtQ0FBc0MsT0FBbUIsRUFBRSxPQUFtQjtJQUNsRixJQUFJLFdBQVcsR0FBRyxJQUFJLGVBQWUsQ0FBSSxPQUFPLENBQUMsQ0FBQztJQUNsRCxPQUFPLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQy9CLE1BQU0sQ0FBQyxXQUFXLENBQUM7QUFDckIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIHRzbGludDpkaXNhYmxlIG1heC1jbGFzc2VzLXBlci1maWxlXG5cbmltcG9ydCAqIGFzIGppZmYgZnJvbSAnamlmZic7XG5pbXBvcnQgKiBhcyBtb21lbnQgZnJvbSAnbW9tZW50JztcblxuaW1wb3J0IHsgU3Vic2NyaWJhYmxlT3JQcm9taXNlIH0gZnJvbSAncnhqcy9PYnNlcnZhYmxlJztcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzL1N1YmplY3QnO1xuaW1wb3J0IHsgU3Vic2NyaWJlciB9IGZyb20gJ3J4anMvU3Vic2NyaWJlcic7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzL1N1YnNjcmlwdGlvbic7XG5pbXBvcnQgeyBPYmplY3RVbnN1YnNjcmliZWRFcnJvciB9IGZyb20gJ3J4anMvdXRpbC9PYmplY3RVbnN1YnNjcmliZWRFcnJvcic7XG5cbmltcG9ydCB7IGNsb25lIH0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IGlzT2JqZWN0IH0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IGlzU3RyaW5nIH0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IG1hcCB9IGZyb20gJ2xvZGFzaCc7XG5cbmltcG9ydCB7IERlZmVycmVkIGFzIElEZWZlcnJlZCwgSlNPTlBhdGNoLCBMb2NhbEZvcmFnZSB9IGZyb20gJy4vdHlwZXMnO1xuXG5sZXQgaGlkZGVuS2V5UmVnZXggPSAvXlxcJCsvO1xuXG5sZXQgVElNRVNUQU1QX1JFID0gL14oXFxkezR9LVswMV1cXGQtWzAtM11cXGRUWzAtMl1cXGQ6WzAtNV1cXGQ6WzAtNV1cXGRcXC5cXGQrKXwoXFxkezR9LVswMV1cXGQtWzAtM11cXGRUWzAtMl1cXGQ6WzAtNV1cXGQ6WzAtNV1cXGQpfChcXGR7NH0tWzAxXVxcZC1bMC0zXVxcZFRbMC0yXVxcZDpbMC01XVxcZCkkLzsgLy8gdHNsaW50OmRpc2FibGUtbGluZSBtYXgtbGluZS1sZW5ndGhcblxuZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnRKc29uRGF0ZXMoanNvbkRhdGE6IGFueSkge1xuICBsZXQgb3V0T2JqO1xuICBpZiAoQXJyYXkuaXNBcnJheShqc29uRGF0YSkpIHtcbiAgICBvdXRPYmogPSBbXTtcbiAgfSBlbHNlIHtcbiAgICBvdXRPYmogPSB7fTtcbiAgfVxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMoanNvbkRhdGEpKSB7XG4gICAgbGV0IHZhbCA9IGpzb25EYXRhW2tleV07XG4gICAgbGV0IHJlcyA9IHZhbDtcbiAgICBpZiAoaXNTdHJpbmcodmFsKSkge1xuICAgICAgLy8gVGhlIHZhbHVlIGlzIGEgc3RyaW5nIC0gZG9lcyBpdCBtYXRjaCBhbnkgb2Ygb3VyIHRoaW5ncyB3ZSB3YW50IHRvIGNvbnZlcnRcbiAgICAgIGlmIChUSU1FU1RBTVBfUkUudGVzdCh2YWwpKSB7XG4gICAgICAgIC8vIFdlJ3JlIHByb2JhYmx5IGEgdGltZXN0YW1wXG4gICAgICAgIGxldCBkdCA9IG1vbWVudCh2YWwpO1xuICAgICAgICBpZiAoZHQuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgcmVzID0gZHQudG9EYXRlKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkodmFsKSB8fCBpc09iamVjdCh2YWwpKSB7XG4gICAgICByZXMgPSBjb252ZXJ0SnNvbkRhdGVzKHZhbCk7XG4gICAgfVxuXG4gICAgb3V0T2JqW2tleV0gPSByZXM7XG4gIH1cblxuICByZXR1cm4gb3V0T2JqO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9KU09OKG9iajogYW55KSB7XG4gIHJldHVybiBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KG9iaikpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGlmZihvYmoxOiBhbnksIG9iajI6IGFueSkge1xuICBvYmoxID0gdG9KU09OKG9iajEpO1xuICBvYmoyID0gdG9KU09OKG9iajIpO1xuXG4gIHJldHVybiBqaWZmLmRpZmYob2JqMSwgb2JqMik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVBhdGNoKHJlczogYW55LCBwYXRjaDogSlNPTlBhdGNoKSB7XG4gIC8vIEdvIHRvIEpTT04gLSBkb24ndCBkbyBhbnl0aGluZyB3aXRoIGRhdGVzXG4gIGxldCBvYmogPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHJlcywgdG9Kc29uUmVwbGFjZXIpKTtcbiAgb2JqID0gamlmZi5wYXRjaChwYXRjaCwgb2JqKTtcblxuICAvLyBHbyBiYWNrIHRvIGRhdGVzIGV0Y1xuICBvYmogPSBjb252ZXJ0SnNvbkRhdGVzKG9iaik7XG5cbiAgcmVtb3ZlUmVzVmFsdWVzKHJlcyk7XG4gIHNldFJlc1ZhbHVlcyhyZXMsIG9iaik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtZXJnZU9iamVjdHMobWluZTogYW55LCBvbGQ6IGFueSwgeW91cnM6IGFueSkge1xuXG4gIC8vIE1ha2UgY29waWVzIC0gd2UgbWlnaHQgbW9kaWZ5IHRoZSBvYmplY3RzIGlmIGlkcyBkb250IGV4aXN0XG4gIG1pbmUgPSBjbG9uZShtaW5lKTtcbiAgb2xkID0gY2xvbmUob2xkKTtcblxuICAvLyBGaXJzdCBzb3J0IG91dCBfaWQncy4gV2UgY291bGQgaGF2ZSBhIG5ldyBpZCBpZiBvbmUgZG9lc24ndCBleGlzdCBvbiBtaW5lIGFuZCBvbGRcbiAgaWYgKCFtaW5lLl9pZCAmJiAhb2xkLl9pZCAmJiB5b3Vycy5faWQpIHtcbiAgICBtaW5lLl9pZCA9IHlvdXJzLl9pZDtcbiAgICBvbGQuX2lkID0geW91cnMuX2lkO1xuICB9XG5cbiAgLy8gV2UgYWxzbyBuZWVkIHRvIGNvbnZlcnQgaW50byBhbmQgb3V0IG9mIGRhdGVzXG4gIG1pbmUgPSB0b0pTT04obWluZSk7XG4gIG9sZCA9IHRvSlNPTihvbGQpO1xuICB5b3VycyA9IHRvSlNPTih5b3Vycyk7XG5cbiAgbGV0IHlvdXJwYXRjaCA9IGppZmYuZGlmZihvbGQsIHlvdXJzKTtcbiAgbGV0IG15cGF0Y2ggPSBqaWZmLmRpZmYob2xkLCBtaW5lKTtcblxuICBsZXQgbXlwYXRocyA9IG1hcChteXBhdGNoLCAncGF0aCcpO1xuICBsZXQgcGF0Y2ggPSB5b3VycGF0Y2guZmlsdGVyKChwYXRjaHZhbDogYW55KSA9PiB7XG4gICAgcmV0dXJuIG15cGF0aHMuaW5kZXhPZihwYXRjaHZhbC5wYXRoKSA9PT0gLTE7XG4gIH0pO1xuXG4gIGxldCBwYXRjaGVkID0gamlmZi5wYXRjaChwYXRjaCwgbWluZSk7XG4gIHJldHVybiBjb252ZXJ0SnNvbkRhdGVzKHBhdGNoZWQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZm9yRWFjaFZhbChyZXM6IGFueSwgY2I6IEZ1bmN0aW9uKSB7XG4gIGZvciAobGV0IGtleSBpbiByZXMpIHtcbiAgICBpZiAoIWhpZGRlbktleVJlZ2V4LnRlc3Qoa2V5KSkge1xuICAgICAgY2IocmVzLCBrZXkpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9Kc29uUmVwbGFjZXIoa2V5OiBhbnksIHZhbHVlOiBhbnkpIHtcbiAgbGV0IHZhbCA9IHZhbHVlO1xuICBpZiAoaXNTdHJpbmcoa2V5KSAmJiBrZXkuY2hhckF0KDApID09PSAnJCcpIHtcbiAgICB2YWwgPSB1bmRlZmluZWQ7XG4gIH1cblxuICByZXR1cm4gdmFsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZnJvbUpzb25SZXZpdmVyKF86IGFueSwgdmFsdWU6IGFueSkge1xuICBsZXQgdmFsID0gdmFsdWU7XG4gIGlmIChpc1N0cmluZyh2YWx1ZSkgJiYgVElNRVNUQU1QX1JFLnRlc3QodmFsdWUpKSB7XG4gICAgbGV0IGR0ID0gbW9tZW50KHZhbHVlKTtcbiAgICBpZiAoZHQuaXNWYWxpZCgpKSB7XG4gICAgICB2YWwgPSBkdC50b0RhdGUoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdmFsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9PYmplY3QocmVzOiBhbnkpIHtcbiAgLy8gVGhlIHRvSnNvblJlcGxhY2VyIGdldHMgcmlkIG9mIGF0dHJpYnV0ZXMgYmVnaW5uaW5nIHdpdGggJCBhbmQgdGhlIGZyb21Kc29uUmV2aXZlclxuICAvLyBjb252ZXJ0cyBkYXRlIHN0cmluZ3MgYmFjayBpbnRvIGRhdGVzXG4gIGxldCBzdHIgPSBKU09OLnN0cmluZ2lmeShyZXMsIHRvSnNvblJlcGxhY2VyKTtcblxuICB0cnkge1xuICAgIHJldHVybiBKU09OLnBhcnNlKHN0ciwgZnJvbUpzb25SZXZpdmVyKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgLy8gT2xkZXIgdmVyc2lvbnMgb2YgSUU4IHRocm93ICdPdXQgb2Ygc3RhY2sgc3BhY2UnIGVycm9ycyBpZiB3ZSB1c2UgYSByZXZpdmVyIGZ1bmN0aW9uXG4gICAgLy8gZHVlIHRvIHRoZSBidWcgZGVzY3JpYmVkIGhlcmU6IGh0dHA6Ly9zdXBwb3J0Lm1pY3Jvc29mdC5jb20va2IvOTc2NjYyLiBFdmVyeW9uZSBoYXRlc1xuICAgIC8vIElFXG4gICAgaWYgKGVyci5tZXNzYWdlID09PSAnT3V0IG9mIHN0YWNrIHNwYWNlJykge1xuICAgICAgcmV0dXJuIGNvbnZlcnRKc29uRGF0ZXMoSlNPTi5wYXJzZShzdHIpKTtcbiAgICB9XG5cbiAgICB0aHJvdyhlcnIpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW1vdmVSZXNWYWx1ZXMocmVzOiBhbnkpIHtcbiAgZm9yRWFjaFZhbChyZXMsIChfOiBhbnksIGtleTogYW55KSA9PiB7XG4gICAgZGVsZXRlIHJlc1trZXldO1xuICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldFJlc1ZhbHVlcyhyZXM6IGFueSwgdmFsczogYW55KSB7XG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyh2YWxzKSkge1xuICAgIHJlc1trZXldID0gdmFsc1trZXldO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwZXJzaXN0ZW50U3RvcmFnZUtleSh1cmw6IHN0cmluZykge1xuICByZXR1cm4gJ29yMndzOicgKyB1cmw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhZHZhbmNlZFN0b3JhZ2UobG9jYWxGb3JhZ2U6IExvY2FsRm9yYWdlKSB7XG4gIHJldHVybiBsb2NhbEZvcmFnZS5kcml2ZXIoKSAhPT0gJ2xvY2FsU3RvcmFnZVdyYXBwZXInO1xufVxuXG4vLyBsaWZ0ZWQgZnJvbSBoZXJlIC0+IGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMTA1MDM0L2hvdy10by1jcmVhdGUtYS1ndWlkLXV1aWQtaW4tamF2YXNjcmlwdC8yMTE3NTIzIzIxMTc1MjNcbmV4cG9ydCBmdW5jdGlvbiB1dWlkKCkge1xuICByZXR1cm4gJ3h4eHh4eHh4LXh4eHgtNHh4eC15eHh4LXh4eHh4eHh4eHh4eCcucmVwbGFjZSgvW3h5XS9nLCBjID0+IHtcbiAgICBsZXQgciA9IE1hdGgucmFuZG9tKCkqMTZ8MCwgdiA9IGMgPT0gJ3gnID8gciA6IChyJjB4M3wweDgpOyAvLyB0c2xpbnQ6ZGlzYWJsZS1saW5lXG4gICAgcmV0dXJuIHYudG9TdHJpbmcoMTYpO1xuICB9KTtcbn1cblxuZXhwb3J0IGNsYXNzIERlZmVycmVkPFQ+IGltcGxlbWVudHMgSURlZmVycmVkPFQ+IHtcbiAgcHVibGljIHByb21pc2U6IFByb21pc2U8VD47XG4gIHB1YmxpYyByZXNvbHZlOiAodmFsPzogVCkgPT4gdm9pZDtcbiAgcHVibGljIHJlamVjdDogKGVycjogRXJyb3IpID0+IHZvaWQ7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgLyogQSBtZXRob2QgdG8gcmVzb2x2ZSB0aGUgYXNzb2NpYXRlZCBQcm9taXNlIHdpdGggdGhlIHZhbHVlIHBhc3NlZC5cbiAgICAgKiBJZiB0aGUgcHJvbWlzZSBpcyBhbHJlYWR5IHNldHRsZWQgaXQgZG9lcyBub3RoaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHthbnl0aGluZ30gdmFsdWUgOiBUaGlzIHZhbHVlIGlzIHVzZWQgdG8gcmVzb2x2ZSB0aGUgcHJvbWlzZVxuICAgICAqIElmIHRoZSB2YWx1ZSBpcyBhIFByb21pc2UgdGhlbiB0aGUgYXNzb2NpYXRlZCBwcm9taXNlIGFzc3VtZXMgdGhlIHN0YXRlXG4gICAgICogb2YgUHJvbWlzZSBwYXNzZWQgYXMgdmFsdWUuXG4gICAgICovXG4gICAgdGhpcy5yZXNvbHZlID0gbnVsbDtcblxuICAgIC8qIEEgbWV0aG9kIHRvIHJlamVjdCB0aGUgYXNzb2NhaXRlZCBQcm9taXNlIHdpdGggdGhlIHZhbHVlIHBhc3NlZC5cbiAgICAgKiBJZiB0aGUgcHJvbWlzZSBpcyBhbHJlYWR5IHNldHRsZWQgaXQgZG9lcyBub3RoaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHthbnl0aGluZ30gcmVhc29uOiBUaGUgcmVhc29uIGZvciB0aGUgcmVqZWN0aW9uIG9mIHRoZSBQcm9taXNlLlxuICAgICAqIEdlbmVyYWxseSBpdHMgYW4gRXJyb3Igb2JqZWN0LiBJZiBob3dldmVyIGEgUHJvbWlzZSBpcyBwYXNzZWQsIHRoZW4gdGhlIFByb21pc2VcbiAgICAgKiBpdHNlbGYgd2lsbCBiZSB0aGUgcmVhc29uIGZvciByZWplY3Rpb24gbm8gbWF0dGVyIHRoZSBzdGF0ZSBvZiB0aGUgUHJvbWlzZS5cbiAgICAgKi9cbiAgICB0aGlzLnJlamVjdCA9IG51bGw7XG5cbiAgICAvKiBBIG5ld2x5IGNyZWF0ZWQgUG9taXNlIG9iamVjdC5cbiAgICAgKiBJbml0aWFsbHkgaW4gcGVuZGluZyBzdGF0ZS5cbiAgICAgKi9cbiAgICB0aGlzLnByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0aGlzLnJlc29sdmUgPSByZXNvbHZlO1xuICAgICAgdGhpcy5yZWplY3QgPSByZWplY3Q7XG4gICAgfSk7XG4gICAgT2JqZWN0LmZyZWV6ZSh0aGlzKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNTdWJzY3JpYmFibGVPclByb21pc2U8VD4odmFsdWU6IGFueSk6IHZhbHVlIGlzIFN1YnNjcmliYWJsZU9yUHJvbWlzZTxUPiB7XG4gIHJldHVybiB2YWx1ZSAmJiAodHlwZW9mIHZhbHVlLnN1YnNjcmliZSA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgdmFsdWUudGhlbiA9PT0gJ2Z1bmN0aW9uJyk7XG59XG5cbi8vIExpa2UgQmVoYXZpb3JTdWJqZWN0IGJ1dCB3YWl0cyBmb3IgYSBwcm9taXNlIHRvIHJlc29sdmVcbmV4cG9ydCBjbGFzcyBSZXNvbHZlZFN1YmplY3Q8VD4gZXh0ZW5kcyBTdWJqZWN0PFQ+IHtcbiAgcHJpdmF0ZSBfdmFsdWU6IFQ7XG4gIHByaXZhdGUgX3Jlc29sdmVkOiBib29sZWFuO1xuXG4gIGNvbnN0cnVjdG9yKHByb21pc2U6IFByb21pc2U8VD4pIHtcbiAgICBzdXBlcigpO1xuXG4gICAgcHJvbWlzZS50aGVuKHZhbCA9PiB7XG4gICAgICB0aGlzLl9yZXNvbHZlZCA9IHRydWU7XG4gICAgICB0aGlzLm5leHQodmFsKTtcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdmFsdWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0VmFsdWUoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRWYWx1ZSgpIHtcbiAgICBpZiAodGhpcy5oYXNFcnJvcikge1xuICAgICAgdGhyb3cgdGhpcy50aHJvd25FcnJvcjtcbiAgICB9IGVsc2UgaWYgKHRoaXMuY2xvc2VkKSB7XG4gICAgICB0aHJvdyBuZXcgT2JqZWN0VW5zdWJzY3JpYmVkRXJyb3IoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuX3ZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBuZXh0KHZhbHVlOiBUKSB7XG4gICAgaWYgKHRoaXMuX3Jlc29sdmVkKSB7XG4gICAgICB0aGlzLl92YWx1ZSA9IHZhbHVlO1xuICAgICAgc3VwZXIubmV4dCh2YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIF9zdWJzY3JpYmUoc3Vic2NyaWJlcjogU3Vic2NyaWJlcjxUPik6IFN1YnNjcmlwdGlvbiB7XG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gc3VwZXIuX3N1YnNjcmliZShzdWJzY3JpYmVyKTtcbiAgICBpZiAodGhpcy5fcmVzb2x2ZWQgJiYgc3Vic2NyaXB0aW9uICYmICFzdWJzY3JpcHRpb24uY2xvc2VkKSB7XG4gICAgICAgIHN1YnNjcmliZXIubmV4dCh0aGlzLl92YWx1ZSk7XG4gICAgfVxuICAgIHJldHVybiBzdWJzY3JpcHRpb247XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbnZlcnRUb1Jlc29sdmVkU3ViamVjdDxUPihzdWJqZWN0OiBTdWJqZWN0PFQ+LCBwcm9taXNlOiBQcm9taXNlPFQ+KSB7XG4gIGxldCByZXNvbHZlZFN1YiA9IG5ldyBSZXNvbHZlZFN1YmplY3Q8VD4ocHJvbWlzZSk7XG4gIHN1YmplY3Quc3Vic2NyaWJlKHJlc29sdmVkU3ViKTtcbiAgcmV0dXJuIHJlc29sdmVkU3ViO1xufVxuIl19