@decaf-ts/for-couchdb
Version:
template for ts projects
169 lines • 20.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CouchDBPaginator = void 0;
const core_1 = require("@decaf-ts/core");
const db_decorators_1 = require("@decaf-ts/db-decorators");
const constants_1 = require("./../constants.cjs");
/**
* @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);
*/
class CouchDBPaginator extends core_1.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 db_decorators_1.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 db_decorators_1.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 core_1.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 core_1.PagingError("No statement target defined");
const pkDef = (0, db_decorators_1.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(constants_1.CouchDBKeys.SEPARATOR);
originalId.splice(0, 1); // remove the table name
return this.adapter.revert(d, this.clazz, pkDef.id, core_1.Sequence.parseValue(pkDef.props.type, originalId.join(constants_1.CouchDBKeys.SEPARATOR)));
});
this.bookMark = bookmark;
this._currentPage = page;
return results;
}
}
exports.CouchDBPaginator = CouchDBPaginator;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGFnaW5hdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3F1ZXJ5L1BhZ2luYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5Q0FBa0U7QUFDbEUsMkRBQXdFO0FBSXhFLGtEQUEyQztBQUUzQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUJHO0FBQ0gsTUFBYSxnQkFBcUMsU0FBUSxnQkFJekQ7SUFPQzs7Ozs7T0FLRztJQUNILElBQWEsS0FBSztRQUNoQixNQUFNLElBQUksNkJBQWEsQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO0lBQzlFLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILElBQWEsS0FBSztRQUNoQixNQUFNLElBQUksNkJBQWEsQ0FDckIsbURBQW1ELENBQ3BELENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILFlBQ0UsT0FBc0MsRUFDdEMsS0FBaUIsRUFDakIsSUFBWSxFQUNaLEtBQXFCO1FBRXJCLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDTyxPQUFPLENBQUMsWUFBd0I7UUFDeEMsTUFBTSxLQUFLLEdBQWUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDMUQsSUFBSSxLQUFLLENBQUMsS0FBSztZQUFFLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQztRQUUxQyxLQUFLLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7UUFFeEIsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0EwREc7SUFDSCxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQWUsQ0FBQztRQUN6QixNQUFNLFNBQVMsR0FBRyxN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UGFnaW5nRXJyb3IsIFNlcXVlbmNlIH0gZnJvbSBcIkBkZWNhZi10cy9jb3JlXCI7XG5pbXBvcnQgeyBmaW5kUHJpbWFyeUtleSwgSW50ZXJuYWxFcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgTWFuZ29RdWVyeSwgTWFuZ29SZXNwb25zZSB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgQ291Y2hEQkFkYXB0ZXIgfSBmcm9tIFwiLi4vYWRhcHRlclwiO1xuaW1wb3J0IHsgQ291Y2hEQktleXMgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCI7XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIFBhZ2luYXRvciBmb3IgQ291Y2hEQiBxdWVyeSByZXN1bHRzXG4gKiBAc3VtbWFyeSBJbXBsZW1lbnRzIHBhZ2luYXRpb24gZm9yIENvdWNoREIgcXVlcmllcyB1c2luZyBib29rbWFya3MgZm9yIGVmZmljaWVudCBuYXZpZ2F0aW9uIHRocm91Z2ggcmVzdWx0IHNldHNcbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgdGhhdCBleHRlbmRzIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXN1bHQgdHlwZVxuICogQHBhcmFtIHtDb3VjaERCQWRhcHRlcjxhbnksIGFueSwgYW55Pn0gYWRhcHRlciAtIFRoZSBDb3VjaERCIGFkYXB0ZXJcbiAqIEBwYXJhbSB7TWFuZ29RdWVyeX0gcXVlcnkgLSBUaGUgTWFuZ28gcXVlcnkgdG8gcGFnaW5hdGVcbiAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIC0gVGhlIHBhZ2Ugc2l6ZVxuICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gY2xhenogLSBUaGUgbW9kZWwgY29uc3RydWN0b3JcbiAqIEBjbGFzcyBDb3VjaERCUGFnaW5hdG9yXG4gKiBAZXhhbXBsZVxuICogLy8gRXhhbXBsZSBvZiB1c2luZyBDb3VjaERCUGFnaW5hdG9yXG4gKiBjb25zdCBhZGFwdGVyID0gbmV3IE15Q291Y2hEQkFkYXB0ZXIoc2NvcGUpO1xuICogY29uc3QgcXVlcnkgPSB7IHNlbGVjdG9yOiB7IHR5cGU6IFwidXNlclwiIH0gfTtcbiAqIGNvbnN0IHBhZ2luYXRvciA9IG5ldyBDb3VjaERCUGFnaW5hdG9yKGFkYXB0ZXIsIHF1ZXJ5LCAxMCwgVXNlcik7XG4gKlxuICogLy8gR2V0IHRoZSBmaXJzdCBwYWdlXG4gKiBjb25zdCBwYWdlMSA9IGF3YWl0IHBhZ2luYXRvci5wYWdlKDEpO1xuICpcbiAqIC8vIEdldCB0aGUgbmV4dCBwYWdlXG4gKiBjb25zdCBwYWdlMiA9IGF3YWl0IHBhZ2luYXRvci5wYWdlKDIpO1xuICovXG5leHBvcnQgY2xhc3MgQ291Y2hEQlBhZ2luYXRvcjxNIGV4dGVuZHMgTW9kZWwsIFI+IGV4dGVuZHMgUGFnaW5hdG9yPFxuICBNLFxuICBSLFxuICBNYW5nb1F1ZXJ5XG4+IHtcbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBCb29rbWFyayBmb3IgQ291Y2hEQiBwYWdpbmF0aW9uXG4gICAqIEBzdW1tYXJ5IFN0b3JlcyB0aGUgYm9va21hcmsgcmV0dXJuZWQgYnkgQ291Y2hEQiBmb3IgY29udGludWluZyBwYWdpbmF0aW9uXG4gICAqL1xuICBwcml2YXRlIGJvb2tNYXJrPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgdG90YWwgbnVtYmVyIG9mIHBhZ2VzXG4gICAqIEBzdW1tYXJ5IE5vdCBzdXBwb3J0ZWQgaW4gQ291Y2hEQiAtIHRocm93cyBhbiBlcnJvciB3aGVuIGFjY2Vzc2VkXG4gICAqIEByZXR1cm4ge251bWJlcn0gTmV2ZXIgcmV0dXJucyBhcyBpdCB0aHJvd3MgYW4gZXJyb3JcbiAgICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gQWx3YXlzIHRocm93cyBhcyB0aGlzIGZ1bmN0aW9uYWxpdHkgaXMgbm90IGF2YWlsYWJsZSBpbiBDb3VjaERCXG4gICAqL1xuICBvdmVycmlkZSBnZXQgdG90YWwoKTogbnVtYmVyIHtcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgVGhlIHRvdGFsIHBhZ2VzIGFwaSBpcyBub3QgYXZhaWxhYmxlIGZvciBjb3VjaGRiYCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHRvdGFsIHJlY29yZCBjb3VudFxuICAgKiBAc3VtbWFyeSBOb3Qgc3VwcG9ydGVkIGluIENvdWNoREIgLSB0aHJvd3MgYW4gZXJyb3Igd2hlbiBhY2Nlc3NlZFxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IE5ldmVyIHJldHVybnMgYXMgaXQgdGhyb3dzIGFuIGVycm9yXG4gICAqIEB0aHJvd3Mge0ludGVybmFsRXJyb3J9IEFsd2F5cyB0aHJvd3MgYXMgdGhpcyBmdW5jdGlvbmFsaXR5IGlzIG5vdCBhdmFpbGFibGUgaW4gQ291Y2hEQlxuICAgKi9cbiAgb3ZlcnJpZGUgZ2V0IGNvdW50KCk6IG51bWJlciB7XG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXG4gICAgICBgVGhlIHJlY29yZCBjb3VudCBhcGkgaXMgbm90IGF2YWlsYWJsZSBmb3IgY291Y2hkYmBcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IENvdWNoREJQYWdpbmF0b3IgaW5zdGFuY2VcbiAgICogQHN1bW1hcnkgSW5pdGlhbGl6ZXMgYSBwYWdpbmF0b3IgZm9yIENvdWNoREIgcXVlcnkgcmVzdWx0c1xuICAgKiBAcGFyYW0ge0NvdWNoREJBZGFwdGVyPGFueSwgYW55LCBhbnk+fSBhZGFwdGVyIC0gVGhlIENvdWNoREIgYWRhcHRlclxuICAgKiBAcGFyYW0ge01hbmdvUXVlcnl9IHF1ZXJ5IC0gVGhlIE1hbmdvIHF1ZXJ5IHRvIHBhZ2luYXRlXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIC0gVGhlIHBhZ2Ugc2l6ZVxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBjbGF6eiAtIFRoZSBtb2RlbCBjb25zdHJ1Y3RvclxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgYWRhcHRlcjogQ291Y2hEQkFkYXB0ZXI8YW55LCBhbnksIGFueT4sXG4gICAgcXVlcnk6IE1hbmdvUXVlcnksXG4gICAgc2l6ZTogbnVtYmVyLFxuICAgIGNsYXp6OiBDb25zdHJ1Y3RvcjxNPlxuICApIHtcbiAgICBzdXBlcihhZGFwdGVyLCBxdWVyeSwgc2l6ZSwgY2xhenopO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcmVwYXJlcyBhIHF1ZXJ5IGZvciBwYWdpbmF0aW9uXG4gICAqIEBzdW1tYXJ5IE1vZGlmaWVzIHRoZSByYXcgcXVlcnkgdG8gaW5jbHVkZSBwYWdpbmF0aW9uIHBhcmFtZXRlcnNcbiAgICogQHBhcmFtIHtNYW5nb1F1ZXJ5fSByYXdTdGF0ZW1lbnQgLSBUaGUgb3JpZ2luYWwgTWFuZ28gcXVlcnlcbiAgICogQHJldHVybiB7TWFuZ29RdWVyeX0gVGhlIHByZXBhcmVkIHF1ZXJ5IHdpdGggcGFnaW5hdGlvbiBwYXJhbWV0ZXJzXG4gICAqL1xuICBwcm90ZWN0ZWQgcHJlcGFyZShyYXdTdGF0ZW1lbnQ6IE1hbmdvUXVlcnkpOiBNYW5nb1F1ZXJ5IHtcbiAgICBjb25zdCBxdWVyeTogTWFuZ29RdWVyeSA9IE9iamVjdC5hc3NpZ24oe30sIHJhd1N0YXRlbWVudCk7XG4gICAgaWYgKHF1ZXJ5LmxpbWl0KSB0aGlzLmxpbWl0ID0gcXVlcnkubGltaXQ7XG5cbiAgICBxdWVyeS5saW1pdCA9IHRoaXMuc2l6ZTtcblxuICAgIHJldHVybiBxdWVyeTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgc3BlY2lmaWMgcGFnZSBvZiByZXN1bHRzXG4gICAqIEBzdW1tYXJ5IEV4ZWN1dGVzIHRoZSBxdWVyeSB3aXRoIHBhZ2luYXRpb24gYW5kIHByb2Nlc3NlcyB0aGUgcmVzdWx0c1xuICAgKiBAcGFyYW0ge251bWJlcn0gW3BhZ2U9MV0gLSBUaGUgcGFnZSBudW1iZXIgdG8gcmV0cmlldmVcbiAgICogQHJldHVybiB7UHJvbWlzZTxSW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiByZXN1bHRzXG4gICAqIEB0aHJvd3Mge1BhZ2luZ0Vycm9yfSBJZiB0cnlpbmcgdG8gYWNjZXNzIGEgcGFnZSBvdGhlciB0aGFuIHRoZSBmaXJzdCB3aXRob3V0IGEgYm9va21hcmssIG9yIGlmIG5vIGNsYXNzIGlzIGRlZmluZWRcbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgQ2xpZW50XG4gICAqICAgcGFydGljaXBhbnQgQ291Y2hEQlBhZ2luYXRvclxuICAgKiAgIHBhcnRpY2lwYW50IEFkYXB0ZXJcbiAgICogICBwYXJ0aWNpcGFudCBDb3VjaERCXG4gICAqXG4gICAqICAgQ2xpZW50LT4+Q291Y2hEQlBhZ2luYXRvcjogcGFnZShwYWdlTnVtYmVyKVxuICAgKiAgIE5vdGUgb3ZlciBDb3VjaERCUGFnaW5hdG9yOiBDbG9uZSBzdGF0ZW1lbnRcbiAgICogICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogdmFsaWRhdGVQYWdlKHBhZ2UpXG4gICAqXG4gICAqICAgYWx0IHBhZ2UgIT09IDFcbiAgICogICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBDaGVjayBib29rbWFya1xuICAgKiAgICAgYWx0IE5vIGJvb2ttYXJrXG4gICAqICAgICAgIENvdWNoREJQYWdpbmF0b3ItLT4+Q2xpZW50OiBUaHJvdyBQYWdpbmdFcnJvclxuICAgKiAgICAgZWxzZSBIYXMgYm9va21hcmtcbiAgICogICAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IEFkZCBib29rbWFyayB0byBzdGF0ZW1lbnRcbiAgICogICAgIGVuZFxuICAgKiAgIGVuZFxuICAgKlxuICAgKiAgIENvdWNoREJQYWdpbmF0b3ItPj5BZGFwdGVyOiByYXcoc3RhdGVtZW50LCBmYWxzZSlcbiAgICogICBBZGFwdGVyLT4+Q291Y2hEQjogRXhlY3V0ZSBxdWVyeVxuICAgKiAgIENvdWNoREItLT4+QWRhcHRlcjogUmV0dXJuIHJlc3VsdHNcbiAgICogICBBZGFwdGVyLS0+PkNvdWNoREJQYWdpbmF0b3I6IFJldHVybiBNYW5nb1Jlc3BvbnNlXG4gICAqXG4gICAqICAgTm90ZSBvdmVyIENvdWNoREJQYWdpbmF0b3I6IFByb2Nlc3MgcmVzdWx0c1xuICAgKlxuICAgKiAgIGFsdCBIYXMgd2FybmluZ1xuICAgKiAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IExvZyB3YXJuaW5nXG4gICAqICAgZW5kXG4gICAqXG4gICAqICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IENoZWNrIGZvciBjbGF6elxuICAgKlxuICAgKiAgIGFsdCBObyBjbGF6elxuICAgKiAgICAgQ291Y2hEQlBhZ2luYXRvci0tPj5DbGllbnQ6IFRocm93IFBhZ2luZ0Vycm9yXG4gICAqICAgZWxzZSBIYXMgY2xhenpcbiAgICogICAgIENvdWNoREJQYWdpbmF0b3ItPj5Db3VjaERCUGFnaW5hdG9yOiBGaW5kIHByaW1hcnkga2V5XG4gICAqXG4gICAqICAgICBhbHQgSGFzIGZpZWxkcyBpbiBzdGF0ZW1lbnRcbiAgICogICAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IFVzZSBkb2NzIGRpcmVjdGx5XG4gICAqICAgICBlbHNlIE5vIGZpZWxkc1xuICAgKiAgICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogUHJvY2VzcyBlYWNoIGRvY3VtZW50XG4gICAqICAgICAgIGxvb3AgRm9yIGVhY2ggZG9jdW1lbnRcbiAgICogICAgICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogRXh0cmFjdCBvcmlnaW5hbCBJRFxuICAgKiAgICAgICAgIENvdWNoREJQYWdpbmF0b3ItPj5BZGFwdGVyOiByZXZlcnQoZG9jLCBjbGF6eiwgcGtEZWYuaWQsIHBhcnNlZElkKVxuICAgKiAgICAgICBlbmRcbiAgICogICAgIGVuZFxuICAgKlxuICAgKiAgICAgQ291Y2hEQlBhZ2luYXRvci0+PkNvdWNoREJQYWdpbmF0b3I6IFN0b3JlIGJvb2ttYXJrXG4gICAqICAgICBDb3VjaERCUGFnaW5hdG9yLT4+Q291Y2hEQlBhZ2luYXRvcjogVXBkYXRlIGN1cnJlbnRQYWdlXG4gICAqICAgICBDb3VjaERCUGFnaW5hdG9yLS0+PkNsaWVudDogUmV0dXJuIHJlc3VsdHNcbiAgICogICBlbmRcbiAgICovXG4gIGFzeW5jIHBhZ2UocGFnZTogbnVtYmVyID0gMSk6IFByb21pc2U8UltdPiB7XG4gICAgY29uc3Qgc3RhdGVtZW50ID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5zdGF0ZW1lbnQpO1xuXG4gICBpZiAoIXRoaXMuX3JlY29yZENvdW50IHx8ICF0aGlzLl90b3RhbFBhZ2VzKSB7XG4gICAgICAgIHRoaXMuX3RvdGFsUGFnZXMgPSB0aGlzLl9yZWNvcmRDb3VudCA9IDA7XG4gICAgICAgIGNvbnN0IHJlc3VsdHM6IFJbXSA9IGF3YWl0IHRoaXMuYWRhcHRlci5yYXcoeyAuLi5zdGF0ZW1lbnQsIGxpbWl0OiB1bmRlZmluZWQgfSkgfHwgW107XG4gICAgICAgIHRoaXMuX3JlY29yZENvdW50ID0gcmVzdWx0cy5sZW5ndGg7XG4gICAgICAgIGlmICh0aGlzLl9yZWNvcmRDb3VudCA+IDApIHtcbiAgICAgICAgICAgIGNvbnN0IHNpemUgPSBzdGF0ZW1lbnQ/LmxpbWl0IHx8IHRoaXMuc2l6ZTtcbiAgICAgICAgICAgIHRoaXMuX3RvdGFsUGFnZXMgPSBNYXRoLmNlaWwodGhpcy5fcmVjb3JkQ291bnQgLyBzaXplKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMudmFsaWRhdGVQYWdlKHBhZ2UpO1xuXG4gICAgaWYgKHBhZ2UgIT09IDEpIHtcbiAgICAgIGlmICghdGhpcy5ib29rTWFyaylcbiAgICAgICAgdGhyb3cgbmV3IFBhZ2luZ0Vycm9yKFwiTm8gYm9va21hcmsuIERpZCB5b3Ugc3RhcnQgaW4gdGhlIGZpcnN0IHBhZ2U/XCIpO1xuICAgICAgc3RhdGVtZW50W1wiYm9va21hcmtcIl0gPSB0aGlzLmJvb2tNYXJrO1xuICAgIH1cbiAgICBjb25zdCByYXdSZXN1bHQ6IE1hbmdvUmVzcG9uc2U8YW55PiA9IGF3YWl0IHRoaXMuYWRhcHRlci5yYXcoXG4gICAgICBzdGF0ZW1lbnQsXG4gICAgICBmYWxzZVxuICAgICk7XG5cbiAgICBjb25zdCB7IGRvY3MsIGJvb2ttYXJrLCB3YXJuaW5nIH0gPSByYXdSZXN1bHQ7XG4gICAgaWYgKHdhcm5pbmcpIGNvbnNvbGUud2Fybih3YXJuaW5nKTtcbiAgICBpZiAoIXRoaXMuY2xhenopIHRocm93IG5ldyBQYWdpbmdFcnJvcihcIk5vIHN0YXRlbWVudCB0YXJnZXQgZGVmaW5lZFwiKTtcbiAgICBjb25zdCBwa0RlZiA9IGZpbmRQcmltYXJ5S2V5KG5ldyB0aGlzLmNsYXp6KCkpO1xuICAgIGNvbnN0IHJlc3VsdHMgPVxuICAgICAgc3RhdGVtZW50LmZpZWxkcyAmJiBzdGF0ZW1lbnQuZmllbGRzLmxlbmd0aFxuICAgICAgICA/IGRvY3MgLy8gaGFzIGZpZWxkcyBtZWFucyBpdHMgbm90IGZ1bGwgbW9kZWxcbiAgICAgICAgOiBkb2NzLm1hcCgoZDogYW55KSA9PiB7XG4gICAgICAgICAgICAvL25vIGZpZWxkcyBtZWFucyB3ZSBuZWVkIHRvIHJldmVydCB0byBzYXZpbmcgcHJvY2Vzc1xuICAgICAgICAgICAgY29uc3Qgb3JpZ2luYWxJZCA9IGQuX2lkLnNwbGl0KENvdWNoREJLZXlzLlNFUEFSQVRPUik7XG4gICAgICAgICAgICBvcmlnaW5hbElkLnNwbGljZSgwLCAxKTsgLy8gcmVtb3ZlIHRoZSB0YWJsZSBuYW1lXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnJldmVydChcbiAgICAgICAgICAgICAgZCxcbiAgICAgICAgICAgICAgdGhpcy5jbGF6eixcbiAgICAgICAgICAgICAgcGtEZWYuaWQsXG4gICAgICAgICAgICAgIFNlcXVlbmNlLnBhcnNlVmFsdWUoXG4gICAgICAgICAgICAgICAgcGtEZWYucHJvcHMudHlwZSxcbiAgICAgICAgICAgICAgICBvcmlnaW5hbElkLmpvaW4oQ291Y2hEQktleXMuU0VQQVJBVE9SKVxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0pO1xuICAgIHRoaXMuYm9va01hcmsgPSBib29rbWFyaztcbiAgICB0aGlzLl9jdXJyZW50UGFnZSA9IHBhZ2U7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH1cbn1cbiJdfQ==