UNPKG

@decaf-ts/for-couchdb

Version:
165 lines 20.7 kB
import { Paginator, PagingError, Sequence } from "@decaf-ts/core"; import { findPrimaryKey, InternalError } from "@decaf-ts/db-decorators"; import { CouchDBKeys } from "./../constants.js"; /** * @description Paginator for CouchDB query results * @summary Implements pagination for CouchDB queries using bookmarks for efficient navigation through result sets * @template M - The model type that extends Model * @template R - The result type * @param {CouchDBAdapter<any, any, any>} adapter - The CouchDB adapter * @param {MangoQuery} query - The Mango query to paginate * @param {number} size - The page size * @param {Constructor<M>} clazz - The model constructor * @class CouchDBPaginator * @example * // Example of using CouchDBPaginator * const adapter = new MyCouchDBAdapter(scope); * const query = { selector: { type: "user" } }; * const paginator = new CouchDBPaginator(adapter, query, 10, User); * * // Get the first page * const page1 = await paginator.page(1); * * // Get the next page * const page2 = await paginator.page(2); */ export class CouchDBPaginator extends Paginator { /** * @description Gets the total number of pages * @summary Not supported in CouchDB - throws an error when accessed * @return {number} Never returns as it throws an error * @throws {InternalError} Always throws as this functionality is not available in CouchDB */ get total() { throw new InternalError(`The total pages api is not available for couchdb`); } /** * @description Gets the total record count * @summary Not supported in CouchDB - throws an error when accessed * @return {number} Never returns as it throws an error * @throws {InternalError} Always throws as this functionality is not available in CouchDB */ get count() { throw new InternalError(`The record count api is not available for couchdb`); } /** * @description Creates a new CouchDBPaginator instance * @summary Initializes a paginator for CouchDB query results * @param {CouchDBAdapter<any, any, any>} adapter - The CouchDB adapter * @param {MangoQuery} query - The Mango query to paginate * @param {number} size - The page size * @param {Constructor<M>} clazz - The model constructor */ constructor(adapter, query, size, clazz) { super(adapter, query, size, clazz); } /** * @description Prepares a query for pagination * @summary Modifies the raw query to include pagination parameters * @param {MangoQuery} rawStatement - The original Mango query * @return {MangoQuery} The prepared query with pagination parameters */ prepare(rawStatement) { const query = Object.assign({}, rawStatement); if (query.limit) this.limit = query.limit; query.limit = this.size; return query; } /** * @description Retrieves a specific page of results * @summary Executes the query with pagination and processes the results * @param {number} [page=1] - The page number to retrieve * @return {Promise<R[]>} A promise that resolves to an array of results * @throws {PagingError} If trying to access a page other than the first without a bookmark, or if no class is defined * @mermaid * sequenceDiagram * participant Client * participant CouchDBPaginator * participant Adapter * participant CouchDB * * Client->>CouchDBPaginator: page(pageNumber) * Note over CouchDBPaginator: Clone statement * CouchDBPaginator->>CouchDBPaginator: validatePage(page) * * alt page !== 1 * CouchDBPaginator->>CouchDBPaginator: Check bookmark * alt No bookmark * CouchDBPaginator-->>Client: Throw PagingError * else Has bookmark * CouchDBPaginator->>CouchDBPaginator: Add bookmark to statement * end * end * * CouchDBPaginator->>Adapter: raw(statement, false) * Adapter->>CouchDB: Execute query * CouchDB-->>Adapter: Return results * Adapter-->>CouchDBPaginator: Return MangoResponse * * Note over CouchDBPaginator: Process results * * alt Has warning * CouchDBPaginator->>CouchDBPaginator: Log warning * end * * CouchDBPaginator->>CouchDBPaginator: Check for clazz * * alt No clazz * CouchDBPaginator-->>Client: Throw PagingError * else Has clazz * CouchDBPaginator->>CouchDBPaginator: Find primary key * * alt Has fields in statement * CouchDBPaginator->>CouchDBPaginator: Use docs directly * else No fields * CouchDBPaginator->>CouchDBPaginator: Process each document * loop For each document * CouchDBPaginator->>CouchDBPaginator: Extract original ID * CouchDBPaginator->>Adapter: revert(doc, clazz, pkDef.id, parsedId) * end * end * * CouchDBPaginator->>CouchDBPaginator: Store bookmark * CouchDBPaginator->>CouchDBPaginator: Update currentPage * CouchDBPaginator-->>Client: Return results * end */ async page(page = 1) { const statement = Object.assign({}, this.statement); if (!this._recordCount || !this._totalPages) { this._totalPages = this._recordCount = 0; const results = await this.adapter.raw({ ...statement, limit: undefined }) || []; this._recordCount = results.length; if (this._recordCount > 0) { const size = statement?.limit || this.size; this._totalPages = Math.ceil(this._recordCount / size); } } this.validatePage(page); if (page !== 1) { if (!this.bookMark) throw new PagingError("No bookmark. Did you start in the first page?"); statement["bookmark"] = this.bookMark; } const rawResult = await this.adapter.raw(statement, false); const { docs, bookmark, warning } = rawResult; if (warning) console.warn(warning); if (!this.clazz) throw new PagingError("No statement target defined"); const pkDef = findPrimaryKey(new this.clazz()); const results = statement.fields && statement.fields.length ? docs // has fields means its not full model : docs.map((d) => { //no fields means we need to revert to saving process const originalId = d._id.split(CouchDBKeys.SEPARATOR); originalId.splice(0, 1); // remove the table name return this.adapter.revert(d, this.clazz, pkDef.id, Sequence.parseValue(pkDef.props.type, originalId.join(CouchDBKeys.SEPARATOR))); }); this.bookMark = bookmark; this._currentPage = page; return results; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGFnaW5hdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3F1ZXJ5L1BhZ2luYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBSXhFLE9BQU8sRUFBRSxXQUFXLEVBQUUsMEJBQXFCO0FBRTNDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFDSCxNQUFNLE9BQU8sZ0JBQXFDLFNBQVEsU0FJekQ7SUFPQzs7Ozs7T0FLRztJQUNILElBQWEsS0FBSztRQUNoQixNQUFNLElBQUksYUFBYSxDQUFDLGtEQUFrRCxDQUFDLENBQUM7SUFDOUUsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsSUFBYSxLQUFLO1FBQ2hCLE1BQU0sSUFBSSxhQUFhLENBQ3JCLG1EQUFtRCxDQUNwRCxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxZQUNFLE9BQXNDLEVBQ3RDLEtBQWlCLEVBQ2pCLElBQVksRUFDWixLQUFxQjtRQUVyQixLQUFLLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDckMsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ08sT0FBTyxDQUFDLFlBQXdCO1FBQ3hDLE1BQU0sS0FBSyxHQUFlLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLFlBQVksQ0FBQyxDQUFDO1FBQzFELElBQUksS0FBSyxDQUFDLEtBQUs7WUFBRSxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFFMUMsS0FBSyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBRXhCLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVEOzs7Ozs7Ozs7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RyxJQUFJLENBQUM7UUFDekIsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFnaW5hdG9yLCBQYWdpbmdFcnJvciwgU2VxdWVuY2UgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IGZpbmRQcmltYXJ5S2V5LCBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBNYW5nb1F1ZXJ5LCBNYW5nb1Jlc3BvbnNlIH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3RvciwgTW9kZWwgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBDb3VjaERCQWRhcHRlciB9IGZyb20gXCIuLi9hZGFwdGVyXCI7XG5pbXBvcnQgeyBDb3VjaERCS2V5cyB9IGZyb20gXCIuLi9jb25zdGFudHNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUGFnaW5hdG9yIGZvciBDb3VjaERCIHF1ZXJ5IHJlc3VsdHNcbiAqIEBzdW1tYXJ5IEltcGxlbWVudHMgcGFnaW5hdGlvbiBmb3IgQ291Y2hEQiBxdWVyaWVzIHVzaW5nIGJvb2ttYXJrcyBmb3IgZWZmaWNpZW50IG5hdmlnYXRpb24gdGhyb3VnaCByZXN1bHQgc2V0c1xuICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZSB0aGF0IGV4dGVuZHMgTW9kZWxcbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJlc3VsdCB0eXBlXG4gKiBAcGFyYW0ge0NvdWNoREJBZGFwdGVyPGFueSwgYW55LCBhbnk+fSBhZGFwdGVyIC0gVGhlIENvdWNoREIgYWRhcHRlclxuICogQHBhcmFtIHtNYW5nb1F1ZXJ5fSBxdWVyeSAtIFRoZSBNYW5nbyBxdWVyeSB0byBwYWdpbmF0ZVxuICogQHBhcmFtIHtudW1iZXJ9IHNpemUgLSBUaGUgcGFnZSBzaXplXG4gKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBjbGF6eiAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvclxuICogQGNsYXNzIENvdWNoREJQYWdpbmF0b3JcbiAqIEBleGFtcGxlXG4gKiAvLyBFeGFtcGxlIG9mIHVzaW5nIENvdWNoREJQYWdpbmF0b3JcbiAqIGNvbnN0IGFkYXB0ZXIgPSBuZXcgTXlDb3VjaERCQWRhcHRlcihzY29wZSk7XG4gKiBjb25zdCBxdWVyeSA9IHsgc2VsZWN0b3I6IHsgdHlwZTogXCJ1c2VyXCIgfSB9O1xuICogY29uc3QgcGFnaW5hdG9yID0gbmV3IENvdWNoREJQYWdpbmF0b3IoYWRhcHRlciwgcXVlcnksIDEwLCBVc2VyKTtcbiAqXG4gKiAvLyBHZXQgdGhlIGZpcnN0IHBhZ2VcbiAqIGNvbnN0IHBhZ2UxID0gYXdhaXQgcGFnaW5hdG9yLnBhZ2UoMSk7XG4gKlxuICogLy8gR2V0IHRoZSBuZXh0IHBhZ2VcbiAqIGNvbnN0IHBhZ2UyID0gYXdhaXQgcGFnaW5hdG9yLnBhZ2UoMik7XG4gKi9cbmV4cG9ydCBjbGFzcyBDb3VjaERCUGFnaW5hdG9yPE0gZXh0ZW5kcyBNb2RlbCwgUj4gZXh0ZW5kcyBQYWdpbmF0b3I8XG4gIE0sXG4gIFIsXG4gIE1hbmdvUXVlcnlcbj4ge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEJvb2ttYXJrIGZvciBDb3VjaERCIHBhZ2luYXRpb25cbiAgICogQHN1bW1hcnkgU3RvcmVzIHRoZSBib29rbWFyayByZXR1cm5lZCBieSBDb3VjaERCIGZvciBjb250aW51aW5nIHBhZ2luYXRpb25cbiAgICovXG4gIHByaXZhdGUgYm9va01hcms/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBHZXRzIHRoZSB0b3RhbCBudW1iZXIgb2YgcGFnZXNcbiAgICogQHN1bW1hcnkgTm90IHN1cHBvcnRlZCBpbiBDb3VjaERCIC0gdGhyb3dzIGFuIGVycm9yIHdoZW4gYWNjZXNzZWRcbiAgICogQHJldHVybiB7bnVtYmVyfSBOZXZlciByZXR1cm5zIGFzIGl0IHRocm93cyBhbiBlcnJvclxuICAgKiBAdGhyb3dzIHtJbnRlcm5hbEVycm9yfSBBbHdheXMgdGhyb3dzIGFzIHRoaXMgZnVuY3Rpb25hbGl0eSBpcyBub3QgYXZhaWxhYmxlIGluIENvdWNoREJcbiAgICovXG4gIG92ZXJyaWRlIGdldCB0b3RhbCgpOiBudW1iZXIge1xuICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBUaGUgdG90YWwgcGFnZXMgYXBpIGlzIG5vdCBhdmFpbGFibGUgZm9yIGNvdWNoZGJgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgdG90YWwgcmVjb3JkIGNvdW50XG4gICAqIEBzdW1tYXJ5IE5vdCBzdXBwb3J0ZWQgaW4gQ291Y2hEQiAtIHRocm93cyBhbiBlcnJvciB3aGVuIGFjY2Vzc2VkXG4gICAqIEByZXR1cm4ge251bWJlcn0gTmV2ZXIgcmV0dXJucyBhcyBpdCB0aHJvd3MgYW4gZXJyb3JcbiAgICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gQWx3YXlzIHRocm93cyBhcyB0aGlzIGZ1bmN0aW9uYWxpdHkgaXMgbm90IGF2YWlsYWJsZSBpbiBDb3VjaERCXG4gICAqL1xuICBvdmVycmlkZSBnZXQgY291bnQoKTogbnVtYmVyIHtcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgIGBUaGUgcmVjb3JkIGNvdW50IGFwaSBpcyBub3QgYXZhaWxhYmxlIGZvciBjb3VjaGRiYFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgQ291Y2hEQlBhZ2luYXRvciBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyBhIHBhZ2luYXRvciBmb3IgQ291Y2hEQiBxdWVyeSByZXN1bHRzXG4gICAqIEBwYXJhbSB7Q291Y2hEQkFkYXB0ZXI8YW55LCBhbnksIGFueT59IGFkYXB0ZXIgLSBUaGUgQ291Y2hEQiBhZGFwdGVyXG4gICAqIEBwYXJhbSB7TWFuZ29RdWVyeX0gcXVlcnkgLSBUaGUgTWFuZ28gcXVlcnkgdG8gcGFnaW5hdGVcbiAgICogQHBhcmFtIHtudW1iZXJ9IHNpemUgLSBUaGUgcGFnZSBzaXplXG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IGNsYXp6IC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBhZGFwdGVyOiBDb3VjaERCQWRhcHRlcjxhbnksIGFueSwgYW55PixcbiAgICBxdWVyeTogTWFuZ29RdWVyeSxcbiAgICBzaXplOiBudW1iZXIsXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+XG4gICkge1xuICAgIHN1cGVyKGFkYXB0ZXIsIHF1ZXJ5LCBzaXplLCBjbGF6eik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGEgcXVlcnkgZm9yIHBhZ2luYXRpb25cbiAgICogQHN1bW1hcnkgTW9kaWZpZXMgdGhlIHJhdyBxdWVyeSB0byBpbmNsdWRlIHBhZ2luYXRpb24gcGFyYW1ldGVyc1xuICAgKiBAcGFyYW0ge01hbmdvUXVlcnl9IHJhd1N0YXRlbWVudCAtIFRoZSBvcmlnaW5hbCBNYW5nbyBxdWVyeVxuICAgKiBAcmV0dXJuIHtNYW5nb1F1ZXJ5fSBUaGUgcHJlcGFyZWQgcXVlcnkgd2l0aCBwYWdpbmF0aW9uIHBhcmFtZXRlcnNcbiAgICovXG4gIHByb3RlY3RlZCBwcmVwYXJlKHJhd1N0YXRlbWVudDogTWFuZ29RdWVyeSk6IE1hbmdvUXVlcnkge1xuICAgIGNvbnN0IHF1ZXJ5OiBNYW5nb1F1ZXJ5ID0gT2JqZWN0LmFzc2lnbih7fSwgcmF3U3RhdGVtZW50KTtcbiAgICBpZiAocXVlcnkubGltaXQpIHRoaXMubGltaXQgPSBxdWVyeS5saW1pdDtcblxuICAgIHF1ZXJ5LmxpbWl0ID0gdGhpcy5zaXplO1xuXG4gICAgcmV0dXJuIHF1ZXJ5O1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBSZXRyaWV2ZXMgYSBzcGVjaWZpYyBwYWdlIG9mIHJlc3VsdHNcbiAgICogQHN1bW1hcnkgRXhlY3V0ZXMgdGhlIHF1ZXJ5IHdpdGggcGFnaW5hdGlvbiBhbmQgcHJvY2Vzc2VzIHRoZSByZXN1bHRzXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbcGFnZT0xXSAtIFRoZSBwYWdlIG51bWJlciB0byByZXRyaWV2ZVxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJbXT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IG9mIHJlc3VsdHNcbiAgICogQHRocm93cyB7UGFnaW5nRXJyb3J9IElmIHRyeWluZyB0byBhY2Nlc3MgYSBwYWdlIG90aGVyIHRoYW4gdGhlIGZpcnN0IHdpdGhvdXQgYSBib29rbWFyaywgb3IgaWYgbm8gY2xhc3MgaXMgZGVmaW5lZFxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAgICogICBwYXJ0aWNpcGFudCBDb3VjaERCUGFnaW5hdG9yXG4gICAqICAgcGFydGljaXBhbnQgQWRhcHRlclxuICAgKiAgIHBhcnRpY2lwYW50IENvdWNoREJcbiAgICpcbiAgICogICBDbGllbnQtPj5Db3VjaERCUGFnaW5hdG9yOiBwYWdlKHBhZ2VOdW1iZXIpXG4gICAqICAgTm90ZSBvdmVyIENvdWNoREJQYWdpbmF0b3I6IENsb25lIHN0YXRlbWVudFxuICAgKiAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiB2YWxpZGF0ZVBhZ2UocGFnZSlcbiAgICpcbiAgICogICBhbHQgcGFnZSAhPT0gMVxuICAgKiAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IENoZWNrIGJvb2ttYXJrXG4gICAqICAgICBhbHQgTm8gYm9va21hcmtcbiAgICogICAgICAgQ291Y2hEQlBhZ2luYXRvci0tPj5DbGllbnQ6IFRocm93IFBhZ2luZ0Vycm9yXG4gICAqICAgICBlbHNlIEhhcyBib29rbWFya1xuICAgKiAgICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogQWRkIGJvb2ttYXJrIHRvIHN0YXRlbWVudFxuICAgKiAgICAgZW5kXG4gICAqICAgZW5kXG4gICAqXG4gICAqICAgQ291Y2hEQlBhZ2luYXRvci0+PkFkYXB0ZXI6IHJhdyhzdGF0ZW1lbnQsIGZhbHNlKVxuICAgKiAgIEFkYXB0ZXItPj5Db3VjaERCOiBFeGVjdXRlIHF1ZXJ5XG4gICAqICAgQ291Y2hEQi0tPj5BZGFwdGVyOiBSZXR1cm4gcmVzdWx0c1xuICAgKiAgIEFkYXB0ZXItLT4+Q291Y2hEQlBhZ2luYXRvcjogUmV0dXJuIE1hbmdvUmVzcG9uc2VcbiAgICpcbiAgICogICBOb3RlIG92ZXIgQ291Y2hEQlBhZ2luYXRvcjogUHJvY2VzcyByZXN1bHRzXG4gICAqXG4gICAqICAgYWx0IEhhcyB3YXJuaW5nXG4gICAqICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogTG9nIHdhcm5pbmdcbiAgICogICBlbmRcbiAgICpcbiAgICogICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogQ2hlY2sgZm9yIGNsYXp6XG4gICAqXG4gICAqICAgYWx0IE5vIGNsYXp6XG4gICAqICAgICBDb3VjaERCUGFnaW5hdG9yLS0+PkNsaWVudDogVGhyb3cgUGFnaW5nRXJyb3JcbiAgICogICBlbHNlIEhhcyBjbGF6elxuICAgKiAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IEZpbmQgcHJpbWFyeSBrZXlcbiAgICpcbiAgICogICAgIGFsdCBIYXMgZmllbGRzIGluIHN0YXRlbWVudFxuICAgKiAgICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogVXNlIGRvY3MgZGlyZWN0bHlcbiAgICogICAgIGVsc2UgTm8gZmllbGRzXG4gICAqICAgICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBQcm9jZXNzIGVhY2ggZG9jdW1lbnRcbiAgICogICAgICAgbG9vcCBGb3IgZWFjaCBkb2N1bWVudFxuICAgKiAgICAgICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBFeHRyYWN0IG9yaWdpbmFsIElEXG4gICAqICAgICAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkFkYXB0ZXI6IHJldmVydChkb2MsIGNsYXp6LCBwa0RlZi5pZCwgcGFyc2VkSWQpXG4gICAqICAgICAgIGVuZFxuICAgKiAgICAgZW5kXG4gICAqXG4gICAqICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogU3RvcmUgYm9va21hcmtcbiAgICogICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBVcGRhdGUgY3VycmVudFBhZ2VcbiAgICogICAgIENvdWNoREJQYWdpbmF0b3ItLT4+Q2xpZW50OiBSZXR1cm4gcmVzdWx0c1xuICAgKiAgIGVuZFxuICAgKi9cbiAgYXN5bmMgcGFnZShwYWdlOiBudW1iZXIgPSAxKTogUHJvbWlzZTxSW10+IHtcbiAgICBjb25zdCBzdGF0ZW1lbnQgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLnN0YXRlbWVudCk7XG5cbiAgIGlmICghdGhpcy5fcmVjb3JkQ291bnQgfHwgIXRoaXMuX3RvdGFsUGFnZXMpIHtcbiAgICAgICAgdGhpcy5fdG90YWxQYWdlcyA9IHRoaXMuX3JlY29yZENvdW50ID0gMDtcbiAgICAgICAgY29uc3QgcmVzdWx0czogUltdID0gYXdhaXQgdGhpcy5hZGFwdGVyLnJhdyh7IC4uLnN0YXRlbWVudCwgbGltaXQ6IHVuZGVmaW5lZCB9KSB8fCBbXTtcbiAgICAgICAgdGhpcy5fcmVjb3JkQ291bnQgPSByZXN1bHRzLmxlbmd0aDtcbiAgICAgICAgaWYgKHRoaXMuX3JlY29yZENvdW50ID4gMCkge1xuICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IHN0YXRlbWVudD8ubGltaXQgfHwgdGhpcy5zaXplO1xuICAgICAgICAgICAgdGhpcy5fdG90YWxQYWdlcyA9IE1hdGguY2VpbCh0aGlzLl9yZWNvcmRDb3VudCAvIHNpemUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy52YWxpZGF0ZVBhZ2UocGFnZSk7XG5cbiAgICBpZiAocGFnZSAhPT0gMSkge1xuICAgICAgaWYgKCF0aGlzLmJvb2tNYXJrKVxuICAgICAgICB0aHJvdyBuZXcgUGFnaW5nRXJyb3IoXCJObyBib29rbWFyay4gRGlkIHlvdSBzdGFydCBpbiB0aGUgZmlyc3QgcGFnZT9cIik7XG4gICAgICBzdGF0ZW1lbnRbXCJib29rbWFya1wiXSA9IHRoaXMuYm9va01hcms7XG4gICAgfVxuICAgIGNvbnN0IHJhd1Jlc3VsdDogTWFuZ29SZXNwb25zZTxhbnk+ID0gYXdhaXQgdGhpcy5hZGFwdGVyLnJhdyhcbiAgICAgIHN0YXRlbWVudCxcbiAgICAgIGZhbHNlXG4gICAgKTtcblxuICAgIGNvbnN0IHsgZG9jcywgYm9va21hcmssIHdhcm5pbmcgfSA9IHJhd1Jlc3VsdDtcbiAgICBpZiAod2FybmluZykgY29uc29sZS53YXJuKHdhcm5pbmcpO1xuICAgIGlmICghdGhpcy5jbGF6eikgdGhyb3cgbmV3IFBhZ2luZ0Vycm9yKFwiTm8gc3RhdGVtZW50IHRhcmdldCBkZWZpbmVkXCIpO1xuICAgIGNvbnN0IHBrRGVmID0gZmluZFByaW1hcnlLZXkobmV3IHRoaXMuY2xhenooKSk7XG4gICAgY29uc3QgcmVzdWx0cyA9XG4gICAgICBzdGF0ZW1lbnQuZmllbGRzICYmIHN0YXRlbWVudC5maWVsZHMubGVuZ3RoXG4gICAgICAgID8gZG9jcyAvLyBoYXMgZmllbGRzIG1lYW5zIGl0cyBub3QgZnVsbCBtb2RlbFxuICAgICAgICA6IGRvY3MubWFwKChkOiBhbnkpID0+IHtcbiAgICAgICAgICAgIC8vbm8gZmllbGRzIG1lYW5zIHdlIG5lZWQgdG8gcmV2ZXJ0IHRvIHNhdmluZyBwcm9jZXNzXG4gICAgICAgICAgICBjb25zdCBvcmlnaW5hbElkID0gZC5faWQuc3BsaXQoQ291Y2hEQktleXMuU0VQQVJBVE9SKTtcbiAgICAgICAgICAgIG9yaWdpbmFsSWQuc3BsaWNlKDAsIDEpOyAvLyByZW1vdmUgdGhlIHRhYmxlIG5hbWVcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KFxuICAgICAgICAgICAgICBkLFxuICAgICAgICAgICAgICB0aGlzLmNsYXp6LFxuICAgICAgICAgICAgICBwa0RlZi5pZCxcbiAgICAgICAgICAgICAgU2VxdWVuY2UucGFyc2VWYWx1ZShcbiAgICAgICAgICAgICAgICBwa0RlZi5wcm9wcy50eXBlLFxuICAgICAgICAgICAgICAgIG9yaWdpbmFsSWQuam9pbihDb3VjaERCS2V5cy5TRVBBUkFUT1IpXG4gICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSk7XG4gICAgdGhpcy5ib29rTWFyayA9IGJvb2ttYXJrO1xuICAgIHRoaXMuX2N1cnJlbnRQYWdlID0gcGFnZTtcbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxufVxuIl19