UNPKG

ngx-airbrush

Version:

Angular client for jsonapi/Graphiti backends

370 lines 28 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ import { HttpParams } from '@angular/common/http'; /** * @template T */ export class Scope { /** * @param {?} service */ constructor(service) { /* tslint:disable:variable-name */ this._pagination = {}; this._filter = {}; this._sort = {}; this._fields = {}; this._include = []; this._stats = {}; this.service = service; } /* tslint:enable:variable-name */ /** * @private * @template T * @param {?} old * @return {?} */ static clone(old) { /** @type {?} */ const clone = new Scope(old.service); /** @type {?} */ const clonedAttr = cloneDeep(old, 'service'); clone._pagination = clonedAttr._pagination; clone._filter = clonedAttr._filter; clone._sort = clonedAttr._sort; clone._fields = clonedAttr._fields; clone._include = clonedAttr._include; clone._stats = clonedAttr._stats; return clone; } /** * @param {?=} options * @return {?} */ all(options) { /** @type {?} */ const params = this.buildParams(); options = options || {}; return this.service.all(Object.assign({ params }, options)); } /** * @param {?} id * @return {?} */ find(id) { /** @type {?} */ const params = this.buildParams(); return this.service.find(id, params); } /** * @param {?} pageNumber * @return {?} */ page(pageNumber) { /** @type {?} */ const clone = Scope.clone(this); clone._pagination.number = pageNumber; return clone; } /** * @param {?} size * @return {?} */ per(size) { /** @type {?} */ const clone = Scope.clone(this); clone._pagination.size = size; return clone; } /** * @param {?} clause * @return {?} */ where(clause) { /** @type {?} */ const clone = Scope.clone(this); for (const key in clause) { if (clause.hasOwnProperty(key)) { clone._filter[key] = clause[key]; } } return clone; } /** * @param {?} clause * @return {?} */ stats(clause) { /** @type {?} */ const clone = Scope.clone(this); for (const key in clause) { if (clause.hasOwnProperty(key)) { clone._stats[key] = clause[key]; } } return clone; } /** * @param {?} clause * @return {?} */ order(clause) { /** @type {?} */ const clone = Scope.clone(this); if (typeof clause === 'string') { clone._sort[clause] = 'asc'; return clone; } // else for (const key in clause) { if (clause.hasOwnProperty(key)) { clone._sort[key] = clause[key]; } } return clone; } /** * @param {?} clause * @return {?} */ select(clause) { /** @type {?} */ const clone = Scope.clone(this); if (Array.isArray(clause) || typeof clause === 'string') { /** @type {?} */ const type = clone.service.getModelConfig().type; clone._fields[type] = clause; return clone; } // else for (const key in clause) { if (clause.hasOwnProperty(key)) { clone._fields[key] = clause[key]; } } return clone; } /** * @param {?} clause * @return {?} */ includes(clause) { /** @type {?} */ const clone = Scope.clone(this); if (Array.isArray(clause)) { clone._include.push(...clause); } else { clone._include.push(clause); } return clone; } /** * @private * @return {?} */ buildParams() { /** @type {?} */ const params = { page: this._pagination, filter: this._filter, sort: this.stringifySorts(this._sort), fields: this._fields, stats: this._stats, include: this.stringifyIncludes(this._include), }; return this.serializeParams(params); } /** * @private * @param {?} sorts * @return {?} */ stringifySorts(sorts) { if (!sorts || Object.keys(sorts).length === 0) { return []; } /** @type {?} */ const params = []; for (let key in sorts) { if (sorts.hasOwnProperty(key)) { if (sorts[key] !== 'asc') { key = `-${key}`; } params.push(key); } } return params; } /** * @private * @param {?} includes * @return {?} */ stringifyIncludes(includes) { if (!includes || (Object.keys(includes).length === 0 && includes.length === 0)) { return []; } /** @type {?} */ const params = []; if (Array.isArray(includes)) { /** @type {?} */ const array = includes.map((/** * @param {?} elt * @return {?} */ elt => this.stringifyIncludes(elt))).reduce((/** * @param {?} res * @param {?} elt1 * @return {?} */ (res, elt1) => { res.push(...elt1); return res; }), []); params.push(...array); return params; } // else if (typeof includes === 'object') { for (const key in includes) { if (includes.hasOwnProperty(key)) { /** @type {?} */ const array = this.stringifyIncludes(includes[key]).map((/** * @param {?} incl * @return {?} */ incl => `${key}.${incl}`)); params.push(...array); } } return params; } // else (is a string) params.push(includes); return params; } /** * @private * @param {?} obj * @param {?=} params * @return {?} */ serializeParams(obj, params) { if (!params) { params = new HttpParams(); } for (const key in obj) { if (!obj.hasOwnProperty(key) || !obj[key]) { continue; } /** @type {?} */ const value = obj[key]; if (Array.isArray(value)) { if (value.length > 0) { params = params.append(key, value.join(',')); } continue; } // else if (typeof value === 'object') { for (const subKey in value) { if (!value.hasOwnProperty(subKey)) { continue; } /** @type {?} */ const elt = {}; /** @type {?} */ const k = `${key}[${subKey}]`; elt[k] = value[subKey]; params = this.serializeParams(elt, params); } continue; } // else params = params.append(key, value); } return params; } } if (false) { /** * @type {?} * @private */ Scope.prototype.service; /** * @type {?} * @private */ Scope.prototype._pagination; /** * @type {?} * @private */ Scope.prototype._filter; /** * @type {?} * @private */ Scope.prototype._sort; /** * @type {?} * @private */ Scope.prototype._fields; /** * @type {?} * @private */ Scope.prototype._include; /** * @type {?} * @private */ Scope.prototype._stats; } /** * @param {?} obj * @param {?=} omit * @return {?} */ function cloneDeep(obj, omit) { omit = omit || []; omit = typeof omit === 'string' ? [omit] : omit; // Handle simple types if (!obj || typeof obj !== 'object') { return obj; } // Handle Date if (obj instanceof Date) { /** @type {?} */ const copy = new Date(); copy.setTime(obj.getTime()); return copy; } // Handle Array if (obj instanceof Array) { /** @type {?} */ const copy = []; for (let i = 0, len = obj.length; i < len; i++) { copy[i] = cloneDeep(obj[i]); } return copy; } // Handle Object if (obj instanceof Object) { /** @type {?} */ const copy = {}; Object.keys(obj).filter((/** * @param {?} key * @return {?} */ key => !omit.includes(key))).forEach((/** * @param {?} key * @return {?} */ key => { copy[key] = cloneDeep(obj[key]); })); return copy; } throw new Error('Unable to copy obj! Its type isn\'t supported.'); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NvcGUuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtYWlyYnJ1c2gvIiwic291cmNlcyI6WyJsaWIvc2NvcGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7OztBQWdCbEQsTUFBTSxPQUFPLEtBQUs7Ozs7SUF3QmhCLFlBQVksT0FBOEI7O1FBcEJsQyxnQkFBVyxHQUFjLEVBQUUsQ0FBQztRQUM1QixZQUFPLEdBQWdCLEVBQUUsQ0FBQztRQUMxQixVQUFLLEdBQWMsRUFBRSxDQUFDO1FBQ3RCLFlBQU8sR0FBZSxFQUFFLENBQUM7UUFDekIsYUFBUSxHQUFpQixFQUFFLENBQUM7UUFDNUIsV0FBTSxHQUFlLEVBQUUsQ0FBQztRQWdCOUIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDekIsQ0FBQzs7Ozs7Ozs7SUFkTyxNQUFNLENBQUMsS0FBSyxDQUF5QixHQUFhOztjQUNsRCxLQUFLLEdBQUcsSUFBSSxLQUFLLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQzs7Y0FDOUIsVUFBVSxHQUFHLFNBQVMsQ0FBQyxHQUFHLEVBQUUsU0FBUyxDQUFDO1FBQzVDLEtBQUssQ0FBQyxXQUFXLEdBQUcsVUFBVSxDQUFDLFdBQVcsQ0FBQztRQUMzQyxLQUFLLENBQUMsT0FBTyxHQUFPLFVBQVUsQ0FBQyxPQUFPLENBQUM7UUFDdkMsS0FBSyxDQUFDLEtBQUssR0FBUyxVQUFVLENBQUMsS0FBSyxDQUFDO1FBQ3JDLEtBQUssQ0FBQyxPQUFPLEdBQU8sVUFBVSxDQUFDLE9BQU8sQ0FBQztRQUN2QyxLQUFLLENBQUMsUUFBUSxHQUFNLFVBQVUsQ0FBQyxRQUFRLENBQUM7UUFDeEMsS0FBSyxDQUFDLE1BQU0sR0FBUSxVQUFVLENBQUMsTUFBTSxDQUFDO1FBQ3RDLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQzs7Ozs7SUFTTSxHQUFHLENBQUMsT0FBZ0M7O2NBQ25DLE1BQU0sR0FB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QixPQUFPLElBQUksQ0FBQztLQUNiO0lBRUQsZUFBZTtJQUNmLElBQUksR0FBRyxZQUFZLEtBQUssRUFBRTs7Y0FDbEIsSUFBSSxHQUFHLEVBQUU7UUFDZixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQzlDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDN0I7UUFDRCxPQUFPLElBQUksQ0FBQztLQUNiO0lBRUQsZ0JBQWdCO0lBQ2hCLElBQUksR0FBRyxZQUFZLE1BQU0sRUFBRTs7Y0FDbkIsSUFBSSxHQUFHLEVBQUU7UUFDZixNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU07Ozs7UUFBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBQyxDQUFDLE9BQU87Ozs7UUFBQyxHQUFHLENBQUMsRUFBRTtZQUNoRSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ2xDLENBQUMsRUFBQyxDQUFDO1FBQ0gsT0FBTyxJQUFJLENBQUM7S0FDYjtJQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztBQUNwRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSHR0cFBhcmFtcyB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgSnNvbmFwaUJhc2VTZXJ2aWNlIH0gZnJvbSAnLi9qc29uYXBpLWJhc2Uuc2VydmljZSc7XG5pbXBvcnQgeyBSZXNvdXJjZUJhc2UgfSBmcm9tICcuL3Jlc291cmNlLWJhc2UubW9kZWwnO1xuaW1wb3J0IHtcbiAgUGFnZVNjb3BlLFxuICBTb3J0U2NvcGUsXG4gIEZpZWxkU2NvcGUsXG4gIEZpbHRlclNjb3BlLFxuICBTdGF0c1Njb3BlLFxuICBJbmNsdWRlU2NvcGUsXG4gIEluY2x1ZGVBcmcsXG59IGZyb20gJy4vaW50ZXJmYWNlcy9xdWVyeS5pbnRlcmZhY2UnO1xuXG5cbmV4cG9ydCBjbGFzcyBTY29wZTxUIGV4dGVuZHMgUmVzb3VyY2VCYXNlPiB7XG4gIHByaXZhdGUgc2VydmljZTogSnNvbmFwaUJhc2VTZXJ2aWNlPFQ+O1xuXG4gIC8qIHRzbGludDpkaXNhYmxlOnZhcmlhYmxlLW5hbWUgKi9cbiAgcHJpdmF0ZSBfcGFnaW5hdGlvbjogUGFnZVNjb3BlID0ge307XG4gIHByaXZhdGUgX2ZpbHRlcjogRmlsdGVyU2NvcGUgPSB7fTtcbiAgcHJpdmF0ZSBfc29ydDogU29ydFNjb3BlID0ge307XG4gIHByaXZhdGUgX2ZpZWxkczogRmllbGRTY29wZSA9IHt9O1xuICBwcml2YXRlIF9pbmNsdWRlOiBJbmNsdWRlQXJnW10gPSBbXTtcbiAgcHJpdmF0ZSBfc3RhdHM6IFN0YXRzU2NvcGUgPSB7fTtcbiAgLyogdHNsaW50OmVuYWJsZTp2YXJpYWJsZS1uYW1lICovXG5cbiAgcHJpdmF0ZSBzdGF0aWMgY2xvbmU8VCBleHRlbmRzIFJlc291cmNlQmFzZT4ob2xkOiBTY29wZTxUPik6IFNjb3BlPFQ+IHtcbiAgICBjb25zdCBjbG9uZSA9IG5ldyBTY29wZShvbGQuc2VydmljZSk7XG4gICAgY29uc3QgY2xvbmVkQXR0ciA9IGNsb25lRGVlcChvbGQsICdzZXJ2aWNlJyk7XG4gICAgY2xvbmUuX3BhZ2luYXRpb24gPSBjbG9uZWRBdHRyLl9wYWdpbmF0aW9uO1xuICAgIGNsb25lLl9maWx0ZXIgICAgID0gY2xvbmVkQXR0ci5fZmlsdGVyO1xuICAgIGNsb25lLl9zb3J0ICAgICAgID0gY2xvbmVkQXR0ci5fc29ydDtcbiAgICBjbG9uZS5fZmllbGRzICAgICA9IGNsb25lZEF0dHIuX2ZpZWxkcztcbiAgICBjbG9uZS5faW5jbHVkZSAgICA9IGNsb25lZEF0dHIuX2luY2x1ZGU7XG4gICAgY2xvbmUuX3N0YXRzICAgICAgPSBjbG9uZWRBdHRyLl9zdGF0cztcbiAgICByZXR1cm4gY2xvbmU7XG4gIH1cblxuICBjb25zdHJ1Y3RvcihzZXJ2aWNlOiBKc29uYXBpQmFzZVNlcnZpY2U8VD4pIHtcbiAgICB0aGlzLnNlcnZpY2UgPSBzZXJ2aWNlO1xuICB9XG5cbiAgcHVibGljIGFsbCgpOiBPYnNlcnZhYmxlPFRbXT47XG4gIHB1YmxpYyBhbGwob3B0aW9uczogeyBtZXRhZGF0YTogdHJ1ZSB9KTogT2JzZXJ2YWJsZTx7IGRhdGE6IFRbXSwgbWV0YTogYW55IH0+O1xuXG4gIHB1YmxpYyBhbGwob3B0aW9ucz86IHsgbWV0YWRhdGE/OiBib29sZWFuIH0pOiBPYnNlcnZhYmxlPFRbXT4gfCBPYnNlcnZhYmxlPHsgZGF0YTogVFtdLCBtZXRhOiBhbnkgfT4ge1xuICAgIGNvbnN0IHBhcmFtcyA9IHRoaXMuYnVpbGRQYXJhbXMoKTtcbiAgICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgICByZXR1cm4gdGhpcy5zZXJ2aWNlLmFsbCh7IHBhcmFtcywgLi4ub3B0aW9ucyB9KTtcbiAgfVxuXG4gIHB1YmxpYyBmaW5kKGlkOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFQ+IHtcbiAgICBjb25zdCBwYXJhbXMgPSB0aGlzLmJ1aWxkUGFyYW1zKCk7XG4gICAgcmV0dXJuIHRoaXMuc2VydmljZS5maW5kKGlkLCBwYXJhbXMpO1xuICB9XG5cbiAgcHVibGljIHBhZ2UocGFnZU51bWJlcjogbnVtYmVyKTogU2NvcGU8VD4ge1xuICAgIGNvbnN0IGNsb25lID0gU2NvcGUuY2xvbmUodGhpcyk7XG5cbiAgICBjbG9uZS5fcGFnaW5hdGlvbi5udW1iZXIgPSBwYWdlTnVtYmVyO1xuICAgIHJldHVybiBjbG9uZTtcbiAgfVxuXG4gIHB1YmxpYyBwZXIoc2l6ZTogbnVtYmVyKTogU2NvcGU8VD4ge1xuICAgIGNvbnN0IGNsb25lID0gU2NvcGUuY2xvbmUodGhpcyk7XG5cbiAgICBjbG9uZS5fcGFnaW5hdGlvbi5zaXplID0gc2l6ZTtcbiAgICByZXR1cm4gY2xvbmU7XG4gIH1cblxuICBwdWJsaWMgd2hlcmUoY2xhdXNlOiBGaWx0ZXJTY29wZSk6IFNjb3BlPFQ+IHtcbiAgICBjb25zdCBjbG9uZSA9IFNjb3BlLmNsb25lKHRoaXMpO1xuXG4gICAgZm9yIChjb25zdCBrZXkgaW4gY2xhdXNlKSB7XG4gICAgICBpZiAoY2xhdXNlLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgY2xvbmUuX2ZpbHRlcltrZXldID0gY2xhdXNlW2tleV07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjbG9uZTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0cyhjbGF1c2U6IFN0YXRzU2NvcGUpOiBTY29wZTxUPiB7XG4gICAgY29uc3QgY2xvbmUgPSBTY29wZS5jbG9uZSh0aGlzKTtcblxuICAgIGZvciAoY29uc3Qga2V5IGluIGNsYXVzZSkge1xuICAgICAgaWYgKGNsYXVzZS5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgIGNsb25lLl9zdGF0c1trZXldID0gY2xhdXNlW2tleV07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBjbG9uZTtcbiAgfVxuXG4gIHB1YmxpYyBvcmRlcihjbGF1c2U6IFNvcnRTY29wZSB8IHN0cmluZyk6IFNjb3BlPFQ+IHtcbiAgICBjb25zdCBjbG9uZSA9IFNjb3BlLmNsb25lKHRoaXMpO1xuXG4gICAgaWYgKHR5cGVvZiBjbGF1c2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjbG9uZS5fc29ydFtjbGF1c2VdID0gJ2FzYyc7XG4gICAgICByZXR1cm4gY2xvbmU7XG4gICAgfSAvLyBlbHNlXG4gICAgZm9yIChjb25zdCBrZXkgaW4gY2xhdXNlKSB7XG4gICAgICBpZiAoY2xhdXNlLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgY2xvbmUuX3NvcnRba2V5XSA9IGNsYXVzZVtrZXldO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjbG9uZTtcbiAgfVxuXG4gIHB1YmxpYyBzZWxlY3QoY2xhdXNlOiBGaWVsZFNjb3BlIHwgc3RyaW5nIHwgc3RyaW5nW10pOiBTY29wZTxUPiB7XG4gICAgY29uc3QgY2xvbmUgPSBTY29wZS5jbG9uZSh0aGlzKTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KGNsYXVzZSkgfHwgdHlwZW9mIGNsYXVzZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGNvbnN0IHR5cGUgPSBjbG9uZS5zZXJ2aWNlLmdldE1vZGVsQ29uZmlnKCkudHlwZTtcbiAgICAgIGNsb25lLl9maWVsZHNbdHlwZV0gPSBjbGF1c2U7XG4gICAgICByZXR1cm4gY2xvbmU7XG4gICAgfSAvLyBlbHNlXG4gICAgZm9yIChjb25zdCBrZXkgaW4gY2xhdXNlKSB7XG4gICAgICBpZiAoY2xhdXNlLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgY2xvbmUuX2ZpZWxkc1trZXldID0gY2xhdXNlW2tleV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsb25lO1xuICB9XG5cbiAgcHVibGljIGluY2x1ZGVzKGNsYXVzZTogSW5jbHVkZVNjb3BlKTogU2NvcGU8VD4ge1xuICAgIGNvbnN0IGNsb25lID0gU2NvcGUuY2xvbmUodGhpcyk7XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShjbGF1c2UpKSB7XG4gICAgICBjbG9uZS5faW5jbHVkZS5wdXNoKC4uLmNsYXVzZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNsb25lLl9pbmNsdWRlLnB1c2goY2xhdXNlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2xvbmU7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkUGFyYW1zKCk6IEh0dHBQYXJhbXMge1xuICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgIHBhZ2U6IHRoaXMuX3BhZ2luYXRpb24sXG4gICAgICBmaWx0ZXI6IHRoaXMuX2ZpbHRlcixcbiAgICAgIHNvcnQ6IHRoaXMuc3RyaW5naWZ5U29ydHModGhpcy5fc29ydCksXG4gICAgICBmaWVsZHM6IHRoaXMuX2ZpZWxkcyxcbiAgICAgIHN0YXRzOiB0aGlzLl9zdGF0cyxcbiAgICAgIGluY2x1ZGU6IHRoaXMuc3RyaW5naWZ5SW5jbHVkZXModGhpcy5faW5jbHVkZSksXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5zZXJpYWxpemVQYXJhbXMocGFyYW1zKTtcbiAgfVxuXG4gIHByaXZhdGUgc3RyaW5naWZ5U29ydHMoc29ydHM6IFNvcnRTY29wZSB8IHVuZGVmaW5lZCk6IHN0cmluZ1tdIHtcbiAgICBpZiAoIXNvcnRzIHx8IE9iamVjdC5rZXlzKHNvcnRzKS5sZW5ndGggPT09IDApIHsgcmV0dXJuIFtdOyB9XG5cbiAgICBjb25zdCBwYXJhbXM6IHN0cmluZ1tdID0gW107XG5cbiAgICBmb3IgKGxldCBrZXkgaW4gc29ydHMpIHtcbiAgICAgIGlmIChzb3J0cy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgIGlmIChzb3J0c1trZXldICE9PSAnYXNjJykgeyBrZXkgPSBgLSR7a2V5fWA7IH1cbiAgICAgICAgcGFyYW1zLnB1c2goa2V5KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcGFyYW1zO1xuICB9XG5cbiAgcHJpdmF0ZSBzdHJpbmdpZnlJbmNsdWRlcyhpbmNsdWRlczogSW5jbHVkZVNjb3BlIHwgdW5kZWZpbmVkKTogc3RyaW5nW10ge1xuICAgIGlmICghaW5jbHVkZXMgfHwgKE9iamVjdC5rZXlzKGluY2x1ZGVzKS5sZW5ndGggPT09IDAgJiYgaW5jbHVkZXMubGVuZ3RoID09PSAwKSkgeyByZXR1cm4gW107IH1cbiAgICBjb25zdCBwYXJhbXM6IHN0cmluZ1tdID0gW107XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShpbmNsdWRlcykpIHtcbiAgICAgIGNvbnN0IGFycmF5ID0gaW5jbHVkZXMubWFwKGVsdCA9PiB0aGlzLnN0cmluZ2lmeUluY2x1ZGVzKGVsdCkpLnJlZHVjZSgocmVzLCBlbHQxKSA9PiB7IHJlcy5wdXNoKC4uLmVsdDEpOyByZXR1cm4gcmVzOyB9LCBbXSk7XG4gICAgICBwYXJhbXMucHVzaCguLi5hcnJheSk7XG4gICAgICByZXR1cm4gcGFyYW1zO1xuICAgIH0gLy8gZWxzZVxuICAgIGlmICh0eXBlb2YgaW5jbHVkZXMgPT09ICdvYmplY3QnKSB7XG4gICAgICBmb3IgKGNvbnN0IGtleSBpbiBpbmNsdWRlcykge1xuICAgICAgICBpZiAoaW5jbHVkZXMuaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgIGNvbnN0IGFycmF5ID0gdGhpcy5zdHJpbmdpZnlJbmNsdWRlcyhpbmNsdWRlc1trZXldKS5tYXAoaW5jbCA9PiBgJHtrZXl9LiR7aW5jbH1gKTtcbiAgICAgICAgICBwYXJhbXMucHVzaCguLi5hcnJheSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBwYXJhbXM7XG4gICAgfSAvLyBlbHNlIChpcyBhIHN0cmluZylcbiAgICBwYXJhbXMucHVzaChpbmNsdWRlcyk7XG4gICAgcmV0dXJuIHBhcmFtcztcbiAgfVxuXG4gIHByaXZhdGUgc2VyaWFsaXplUGFyYW1zKG9iajogYW55LCBwYXJhbXM/OiBIdHRwUGFyYW1zKTogSHR0cFBhcmFtcyB7XG4gICAgaWYgKCFwYXJhbXMpIHsgcGFyYW1zID0gbmV3IEh0dHBQYXJhbXMoKTsgfVxuICAgIGZvciAoY29uc3Qga2V5IGluIG9iaikge1xuICAgICAgaWYgKCFvYmouaGFzT3duUHJvcGVydHkoa2V5KSB8fCAhb2JqW2tleV0pIHsgY29udGludWU7IH1cblxuICAgICAgY29uc3QgdmFsdWUgPSBvYmpba2V5XTtcblxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgIGlmICh2YWx1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgcGFyYW1zID0gcGFyYW1zLmFwcGVuZChrZXksIHZhbHVlLmpvaW4oJywnKSk7XG4gICAgICAgIH1cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICAvLyBlbHNlXG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jykge1xuICAgICAgICBmb3IgKGNvbnN0IHN1YktleSBpbiB2YWx1ZSkge1xuICAgICAgICAgIGlmICghdmFsdWUuaGFzT3duUHJvcGVydHkoc3ViS2V5KSkgeyBjb250aW51ZTsgfVxuXG4gICAgICAgICAgY29uc3QgZWx0ID0ge307XG4gICAgICAgICAgY29uc3QgayA9IGAke2tleX1bJHtzdWJLZXl9XWA7XG4gICAgICAgICAgZWx0W2tdID0gdmFsdWVbc3ViS2V5XTtcbiAgICAgICAgICBwYXJhbXMgPSB0aGlzLnNlcmlhbGl6ZVBhcmFtcyhlbHQsIHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICAvLyBlbHNlXG4gICAgICBwYXJhbXMgPSBwYXJhbXMuYXBwZW5kKGtleSwgdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwYXJhbXM7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2xvbmVEZWVwKG9iaiwgb21pdD86IHN0cmluZyB8IHN0cmluZ1tdKSB7XG4gIG9taXQgPSBvbWl0IHx8IFtdO1xuICBvbWl0ID0gdHlwZW9mIG9taXQgPT09ICdzdHJpbmcnID8gW29taXRdIDogb21pdDtcblxuICAvLyBIYW5kbGUgc2ltcGxlIHR5cGVzXG4gIGlmICghb2JqIHx8IHR5cGVvZiBvYmogIT09ICdvYmplY3QnKSB7IHJldHVybiBvYmo7IH1cblxuICAvLyBIYW5kbGUgRGF0ZVxuICBpZiAob2JqIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgIGNvbnN0IGNvcHkgPSBuZXcgRGF0ZSgpO1xuICAgIGNvcHkuc2V0VGltZShvYmouZ2V0VGltZSgpKTtcbiAgICByZXR1cm4gY29weTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBBcnJheVxuICBpZiAob2JqIGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICBjb25zdCBjb3B5ID0gW107XG4gICAgZm9yIChsZXQgaSA9IDAsIGxlbiA9IG9iai5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgY29weVtpXSA9IGNsb25lRGVlcChvYmpbaV0pO1xuICAgIH1cbiAgICByZXR1cm4gY29weTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBPYmplY3RcbiAgaWYgKG9iaiBpbnN0YW5jZW9mIE9iamVjdCkge1xuICAgIGNvbnN0IGNvcHkgPSB7fTtcbiAgICBPYmplY3Qua2V5cyhvYmopLmZpbHRlcihrZXkgPT4gIW9taXQuaW5jbHVkZXMoa2V5KSkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgY29weVtrZXldID0gY2xvbmVEZWVwKG9ialtrZXldKTtcbiAgICB9KTtcbiAgICByZXR1cm4gY29weTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGNvcHkgb2JqISBJdHMgdHlwZSBpc25cXCd0IHN1cHBvcnRlZC4nKTtcbn1cbiJdfQ==