UNPKG

@decaf-ts/for-postgres

Version:
182 lines 18.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PostgresPaginator = void 0; const core_1 = require("@decaf-ts/core"); /** * @description Paginator for PostgreSQL query results * @summary Implements pagination for PostgreSQL queries using LIMIT and OFFSET for efficient navigation through result sets * @template M - The model type that extends Model * @template R - The result type * @param {PostgresAdapter<any, any, any>} adapter - The PostgreSQL adapter * @param {PostgresQuery} query - The PostgresSQL query to paginate * @param {number} size - The page size * @param {Constructor<M>} clazz - The model constructor * @class PostgresPaginator * @example * // Example of using PostgreSQLPaginator * const adapter = new MyPostgreSQLAdapter(pool); * const query = { table: "users" }; * const paginator = new PostgreSQLPaginator(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 PostgresPaginator extends core_1.Paginator { /** * @description Gets the total number of pages * @summary Returns the total number of pages based on the record count and page size * @return {number} The total number of pages */ get total() { return this._totalPages; } /** * @description Gets the total record count * @summary Returns the total number of records matching the query * @return {number} The total record count */ get count() { return this._recordCount; } /** * @description Creates a new PostgreSQLPaginator instance * @summary Initializes a paginator for PostgreSQL query results * @param {PostgresAdapter} adapter - The PostgreSQL adapter * @param {PostgreSQLQuery} query - The PostgreSQL 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 {PostgresQuery} rawStatement - The original PostgreSQL query * @return {PostgresQuery} The prepared query with pagination parameters */ prepare(rawStatement) { const query = { ...rawStatement }; 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 an invalid page or if no class is defined * @mermaid * sequenceDiagram * participant Client * participant PostgreSQLPaginator * participant Adapter * participant PostgreSQL * * Client->>PostgreSQLPaginator: page(pageNumber) * Note over PostgreSQLPaginator: Clone statement * * alt First time or need count * PostgreSQLPaginator->>Adapter: Get total count * Adapter->>PostgreSQL: Execute COUNT query * PostgreSQL-->>Adapter: Return count * Adapter-->>PostgreSQLPaginator: Return count * PostgreSQLPaginator->>PostgreSQLPaginator: Calculate total pages * end * * PostgreSQLPaginator->>PostgreSQLPaginator: validatePage(page) * PostgreSQLPaginator->>PostgreSQLPaginator: Calculate offset * PostgreSQLPaginator->>PostgreSQLPaginator: Add limit and offset to query * * PostgreSQLPaginator->>Adapter: raw(statement, false) * Adapter->>PostgreSQL: Execute query * PostgreSQL-->>Adapter: Return results * Adapter-->>PostgreSQLPaginator: Return PostgreSQLResponse * * Note over PostgreSQLPaginator: Process results * * PostgreSQLPaginator->>PostgreSQLPaginator: Check for clazz * * alt No clazz * PostgreSQLPaginator-->>Client: Throw PagingError * else Has clazz * PostgreSQLPaginator->>PostgreSQLPaginator: Find primary key * * alt Has columns in statement * PostgreSQLPaginator->>PostgreSQLPaginator: Use rows directly * else No columns * PostgreSQLPaginator->>PostgreSQLPaginator: Process each row * loop For each row * PostgreSQLPaginator->>Adapter: revert(row, clazz, pkDef.id, id) * end * end * * PostgreSQLPaginator->>PostgreSQLPaginator: Update currentPage * PostgreSQLPaginator-->>Client: Return results * end */ async page(page = 1) { throw new Error(`Not implemented yet`); // const statement = { ...this.statement }; // // // Get total count if not already calculated // if (!this._recordCount || !this._totalPages) { // this._totalPages = this._recordCount = 0; // // // Create a count query based on the original query // const countQuery: PostgresQuery = { // ...statement, // count: true, // limit: undefined, // offset: undefined, // }; // // const countResult: QueryResult = await this.adapter.raw( // countQuery, // false // ); // this._recordCount = parseInt(countResult.rows[0]?.count || "0", 10); // // if (this._recordCount > 0) { // const size = statement?.limit || this.size; // this._totalPages = Math.ceil(this._recordCount / size); // } // } // // this.validatePage(page); // // // Calculate offset based on page number // const offset = (page - 1) * this.size; // statement.limit = this.size; // statement.offset = offset; // // const result: PostgreSQLResponse<any> = await this.adapter.raw( // statement, // false // ); // // if (!this.clazz) throw new PagingError("No statement target defined"); // // const pkDef = findPrimaryKey(new this.clazz()); // const rows = result.rows || []; // // const results = // statement.columns && statement.columns.length // ? rows // has columns means it's not full model // : rows.map((row: any) => { // return this.adapter.revert( // row, // this.clazz, // pkDef.id, // Sequence.parseValue(pkDef.props.type, row[PostgreSQLKeys.ID]) // ); // }); // // this._currentPage = page; // return results as R[]; } } exports.PostgresPaginator = PostgresPaginator; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGFnaW5hdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3F1ZXJ5L1BhZ2luYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5Q0FBMkM7QUFLM0M7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXFCRztBQUNILE1BQWEsaUJBQXNDLFNBQVEsZ0JBSTFEO0lBQ0M7Ozs7T0FJRztJQUNILElBQWEsS0FBSztRQUNoQixPQUFPLElBQUksQ0FBQyxXQUFXLENBQUM7SUFDMUIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxJQUFhLEtBQUs7UUFDaEIsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQzNCLENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsWUFDRSxPQUF3QixFQUN4QixLQUFvQixFQUNwQixJQUFZLEVBQ1osS0FBcUI7UUFFckIsS0FBSyxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3JDLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNPLE9BQU8sQ0FBQyxZQUEyQjtRQUMzQyxNQUFNLEtBQUssR0FBa0IsRUFBRSxHQUFHLFlBQVksRUFBRSxDQUFDO1FBQ2pELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0FzREc7SUFDSCxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQWUsQ0FBQztRQUN6QixNQUFNLElBQUksS0FBSyxDQUFDLHFCQUFxQixDQUFDLENBQUM7UUFDdkMsMkNBQTJDO1FBQzNDLEVBQUU7UUFDRiwrQ0FBK0M7UUFDL0MsaURBQWlEO1FBQ2pELDhDQUE4QztRQUM5QyxFQUFFO1FBQ0Ysd0RBQXdEO1FBQ3hELHdDQUF3QztRQUN4QyxvQkFBb0I7UUFDcEIsbUJBQW1CO1FBQ25CLHdCQUF3QjtRQUN4Qix5QkFBeUI7UUFDekIsT0FBTztRQUNQLEVBQUU7UUFDRiw2REFBNkQ7UUFDN0Qsa0JBQWtCO1FBQ2xCLFlBQVk7UUFDWixPQUFPO1FBQ1AseUVBQXlFO1FBQ3pFLEVBQUU7UUFDRixpQ0FBaUM7UUFDakMsa0RBQWtEO1FBQ2xELDhEQUE4RDtRQUM5RCxNQUFNO1FBQ04sSUFBSTtRQUNKLEVBQUU7UUFDRiwyQkFBMkI7UUFDM0IsRUFBRTtRQUNGLDJDQUEyQztRQUMzQyx5Q0FBeUM7UUFDekMsK0JBQStCO1FBQy9CLDZCQUE2QjtRQUM3QixFQUFFO1FBQ0Ysa0VBQWtFO1FBQ2xFLGVBQWU7UUFDZixVQUFVO1FBQ1YsS0FBSztRQUNMLEVBQUU7UUFDRix5RUFBeUU7UUFDekUsRUFBRTtRQUNGLGtEQUFrRDtRQUNsRCxrQ0FBa0M7UUFDbEMsRUFBRTtRQUNGLGtCQUFrQjtRQUNsQixrREFBa0Q7UUFDbEQsc0RBQXNEO1FBQ3RELGlDQUFpQztRQUNqQyxzQ0FBc0M7UUFDdEMsaUJBQWlCO1FBQ2pCLHdCQUF3QjtRQUN4QixzQkFBc0I7UUFDdEIsMEVBQTBFO1FBQzFFLGFBQWE7UUFDYixZQUFZO1FBQ1osRUFBRTtRQUNGLDRCQUE0QjtRQUM1Qix5QkFBeUI7SUFDM0IsQ0FBQztDQUNGO0FBdEtELDhDQXNLQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBhZ2luYXRvciB9IGZyb20gXCJAZGVjYWYtdHMvY29yZVwiO1xuaW1wb3J0IHsgUG9zdGdyZXNRdWVyeSB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgUG9zdGdyZXNBZGFwdGVyIH0gZnJvbSBcIi4uL2FkYXB0ZXJcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUGFnaW5hdG9yIGZvciBQb3N0Z3JlU1FMIHF1ZXJ5IHJlc3VsdHNcbiAqIEBzdW1tYXJ5IEltcGxlbWVudHMgcGFnaW5hdGlvbiBmb3IgUG9zdGdyZVNRTCBxdWVyaWVzIHVzaW5nIExJTUlUIGFuZCBPRkZTRVQgZm9yIGVmZmljaWVudCBuYXZpZ2F0aW9uIHRocm91Z2ggcmVzdWx0IHNldHNcbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgdGhhdCBleHRlbmRzIE1vZGVsXG4gKiBAdGVtcGxhdGUgUiAtIFRoZSByZXN1bHQgdHlwZVxuICogQHBhcmFtIHtQb3N0Z3Jlc0FkYXB0ZXI8YW55LCBhbnksIGFueT59IGFkYXB0ZXIgLSBUaGUgUG9zdGdyZVNRTCBhZGFwdGVyXG4gKiBAcGFyYW0ge1Bvc3RncmVzUXVlcnl9IHF1ZXJ5IC0gVGhlIFBvc3RncmVzU1FMIHF1ZXJ5IHRvIHBhZ2luYXRlXG4gKiBAcGFyYW0ge251bWJlcn0gc2l6ZSAtIFRoZSBwYWdlIHNpemVcbiAqIEBwYXJhbSB7Q29uc3RydWN0b3I8TT59IGNsYXp6IC0gVGhlIG1vZGVsIGNvbnN0cnVjdG9yXG4gKiBAY2xhc3MgUG9zdGdyZXNQYWdpbmF0b3JcbiAqIEBleGFtcGxlXG4gKiAvLyBFeGFtcGxlIG9mIHVzaW5nIFBvc3RncmVTUUxQYWdpbmF0b3JcbiAqIGNvbnN0IGFkYXB0ZXIgPSBuZXcgTXlQb3N0Z3JlU1FMQWRhcHRlcihwb29sKTtcbiAqIGNvbnN0IHF1ZXJ5ID0geyB0YWJsZTogXCJ1c2Vyc1wiIH07XG4gKiBjb25zdCBwYWdpbmF0b3IgPSBuZXcgUG9zdGdyZVNRTFBhZ2luYXRvcihhZGFwdGVyLCBxdWVyeSwgMTAsIFVzZXIpO1xuICpcbiAqIC8vIEdldCB0aGUgZmlyc3QgcGFnZVxuICogY29uc3QgcGFnZTEgPSBhd2FpdCBwYWdpbmF0b3IucGFnZSgxKTtcbiAqXG4gKiAvLyBHZXQgdGhlIG5leHQgcGFnZVxuICogY29uc3QgcGFnZTIgPSBhd2FpdCBwYWdpbmF0b3IucGFnZSgyKTtcbiAqL1xuZXhwb3J0IGNsYXNzIFBvc3RncmVzUGFnaW5hdG9yPE0gZXh0ZW5kcyBNb2RlbCwgUj4gZXh0ZW5kcyBQYWdpbmF0b3I8XG4gIE0sXG4gIFIsXG4gIFBvc3RncmVzUXVlcnlcbj4ge1xuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHRvdGFsIG51bWJlciBvZiBwYWdlc1xuICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSB0b3RhbCBudW1iZXIgb2YgcGFnZXMgYmFzZWQgb24gdGhlIHJlY29yZCBjb3VudCBhbmQgcGFnZSBzaXplXG4gICAqIEByZXR1cm4ge251bWJlcn0gVGhlIHRvdGFsIG51bWJlciBvZiBwYWdlc1xuICAgKi9cbiAgb3ZlcnJpZGUgZ2V0IHRvdGFsKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX3RvdGFsUGFnZXM7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIEdldHMgdGhlIHRvdGFsIHJlY29yZCBjb3VudFxuICAgKiBAc3VtbWFyeSBSZXR1cm5zIHRoZSB0b3RhbCBudW1iZXIgb2YgcmVjb3JkcyBtYXRjaGluZyB0aGUgcXVlcnlcbiAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgdG90YWwgcmVjb3JkIGNvdW50XG4gICAqL1xuICBvdmVycmlkZSBnZXQgY291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fcmVjb3JkQ291bnQ7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBuZXcgUG9zdGdyZVNRTFBhZ2luYXRvciBpbnN0YW5jZVxuICAgKiBAc3VtbWFyeSBJbml0aWFsaXplcyBhIHBhZ2luYXRvciBmb3IgUG9zdGdyZVNRTCBxdWVyeSByZXN1bHRzXG4gICAqIEBwYXJhbSB7UG9zdGdyZXNBZGFwdGVyfSBhZGFwdGVyIC0gVGhlIFBvc3RncmVTUUwgYWRhcHRlclxuICAgKiBAcGFyYW0ge1Bvc3RncmVTUUxRdWVyeX0gcXVlcnkgLSBUaGUgUG9zdGdyZVNRTCBxdWVyeSB0byBwYWdpbmF0ZVxuICAgKiBAcGFyYW0ge251bWJlcn0gc2l6ZSAtIFRoZSBwYWdlIHNpemVcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gY2xhenogLSBUaGUgbW9kZWwgY29uc3RydWN0b3JcbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIGFkYXB0ZXI6IFBvc3RncmVzQWRhcHRlcixcbiAgICBxdWVyeTogUG9zdGdyZXNRdWVyeSxcbiAgICBzaXplOiBudW1iZXIsXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+XG4gICkge1xuICAgIHN1cGVyKGFkYXB0ZXIsIHF1ZXJ5LCBzaXplLCBjbGF6eik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGEgcXVlcnkgZm9yIHBhZ2luYXRpb25cbiAgICogQHN1bW1hcnkgTW9kaWZpZXMgdGhlIHJhdyBxdWVyeSB0byBpbmNsdWRlIHBhZ2luYXRpb24gcGFyYW1ldGVyc1xuICAgKiBAcGFyYW0ge1Bvc3RncmVzUXVlcnl9IHJhd1N0YXRlbWVudCAtIFRoZSBvcmlnaW5hbCBQb3N0Z3JlU1FMIHF1ZXJ5XG4gICAqIEByZXR1cm4ge1Bvc3RncmVzUXVlcnl9IFRoZSBwcmVwYXJlZCBxdWVyeSB3aXRoIHBhZ2luYXRpb24gcGFyYW1ldGVyc1xuICAgKi9cbiAgcHJvdGVjdGVkIHByZXBhcmUocmF3U3RhdGVtZW50OiBQb3N0Z3Jlc1F1ZXJ5KTogUG9zdGdyZXNRdWVyeSB7XG4gICAgY29uc3QgcXVlcnk6IFBvc3RncmVzUXVlcnkgPSB7IC4uLnJhd1N0YXRlbWVudCB9O1xuICAgIHJldHVybiBxdWVyeTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gUmV0cmlldmVzIGEgc3BlY2lmaWMgcGFnZSBvZiByZXN1bHRzXG4gICAqIEBzdW1tYXJ5IEV4ZWN1dGVzIHRoZSBxdWVyeSB3aXRoIHBhZ2luYXRpb24gYW5kIHByb2Nlc3NlcyB0aGUgcmVzdWx0c1xuICAgKiBAcGFyYW0ge251bWJlcn0gW3BhZ2U9MV0gLSBUaGUgcGFnZSBudW1iZXIgdG8gcmV0cmlldmVcbiAgICogQHJldHVybiB7UHJvbWlzZTxSW10+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhbiBhcnJheSBvZiByZXN1bHRzXG4gICAqIEB0aHJvd3Mge1BhZ2luZ0Vycm9yfSBJZiB0cnlpbmcgdG8gYWNjZXNzIGFuIGludmFsaWQgcGFnZSBvciBpZiBubyBjbGFzcyBpcyBkZWZpbmVkXG4gICAqIEBtZXJtYWlkXG4gICAqIHNlcXVlbmNlRGlhZ3JhbVxuICAgKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICAgKiAgIHBhcnRpY2lwYW50IFBvc3RncmVTUUxQYWdpbmF0b3JcbiAgICogICBwYXJ0aWNpcGFudCBBZGFwdGVyXG4gICAqICAgcGFydGljaXBhbnQgUG9zdGdyZVNRTFxuICAgKlxuICAgKiAgIENsaWVudC0+PlBvc3RncmVTUUxQYWdpbmF0b3I6IHBhZ2UocGFnZU51bWJlcilcbiAgICogICBOb3RlIG92ZXIgUG9zdGdyZVNRTFBhZ2luYXRvcjogQ2xvbmUgc3RhdGVtZW50XG4gICAqXG4gICAqICAgYWx0IEZpcnN0IHRpbWUgb3IgbmVlZCBjb3VudFxuICAgKiAgICAgUG9zdGdyZVNRTFBhZ2luYXRvci0+PkFkYXB0ZXI6IEdldCB0b3RhbCBjb3VudFxuICAgKiAgICAgQWRhcHRlci0+PlBvc3RncmVTUUw6IEV4ZWN1dGUgQ09VTlQgcXVlcnlcbiAgICogICAgIFBvc3RncmVTUUwtLT4+QWRhcHRlcjogUmV0dXJuIGNvdW50XG4gICAqICAgICBBZGFwdGVyLS0+PlBvc3RncmVTUUxQYWdpbmF0b3I6IFJldHVybiBjb3VudFxuICAgKiAgICAgUG9zdGdyZVNRTFBhZ2luYXRvci0+PlBvc3RncmVTUUxQYWdpbmF0b3I6IENhbGN1bGF0ZSB0b3RhbCBwYWdlc1xuICAgKiAgIGVuZFxuICAgKlxuICAgKiAgIFBvc3RncmVTUUxQYWdpbmF0b3ItPj5Qb3N0Z3JlU1FMUGFnaW5hdG9yOiB2YWxpZGF0ZVBhZ2UocGFnZSlcbiAgICogICBQb3N0Z3JlU1FMUGFnaW5hdG9yLT4+UG9zdGdyZVNRTFBhZ2luYXRvcjogQ2FsY3VsYXRlIG9mZnNldFxuICAgKiAgIFBvc3RncmVTUUxQYWdpbmF0b3ItPj5Qb3N0Z3JlU1FMUGFnaW5hdG9yOiBBZGQgbGltaXQgYW5kIG9mZnNldCB0byBxdWVyeVxuICAgKlxuICAgKiAgIFBvc3RncmVTUUxQYWdpbmF0b3ItPj5BZGFwdGVyOiByYXcoc3RhdGVtZW50LCBmYWxzZSlcbiAgICogICBBZGFwdGVyLT4+UG9zdGdyZVNRTDogRXhlY3V0ZSBxdWVyeVxuICAgKiAgIFBvc3RncmVTUUwtLT4+QWRhcHRlcjogUmV0dXJuIHJlc3VsdHNcbiAgICogICBBZGFwdGVyLS0+PlBvc3RncmVTUUxQYWdpbmF0b3I6IFJldHVybiBQb3N0Z3JlU1FMUmVzcG9uc2VcbiAgICpcbiAgICogICBOb3RlIG92ZXIgUG9zdGdyZVNRTFBhZ2luYXRvcjogUHJvY2VzcyByZXN1bHRzXG4gICAqXG4gICAqICAgUG9zdGdyZVNRTFBhZ2luYXRvci0+PlBvc3RncmVTUUxQYWdpbmF0b3I6IENoZWNrIGZvciBjbGF6elxuICAgKlxuICAgKiAgIGFsdCBObyBjbGF6elxuICAgKiAgICAgUG9zdGdyZVNRTFBhZ2luYXRvci0tPj5DbGllbnQ6IFRocm93IFBhZ2luZ0Vycm9yXG4gICAqICAgZWxzZSBIYXMgY2xhenpcbiAgICogICAgIFBvc3RncmVTUUxQYWdpbmF0b3ItPj5Qb3N0Z3JlU1FMUGFnaW5hdG9yOiBGaW5kIHByaW1hcnkga2V5XG4gICAqXG4gICAqICAgICBhbHQgSGFzIGNvbHVtbnMgaW4gc3RhdGVtZW50XG4gICAqICAgICAgIFBvc3RncmVTUUxQYWdpbmF0b3ItPj5Qb3N0Z3JlU1FMUGFnaW5hdG9yOiBVc2Ugcm93cyBkaXJlY3RseVxuICAgKiAgICAgZWxzZSBObyBjb2x1bW5zXG4gICAqICAgICAgIFBvc3RncmVTUUxQYWdpbmF0b3ItPj5Qb3N0Z3JlU1FMUGFnaW5hdG9yOiBQcm9jZXNzIGVhY2ggcm93XG4gICAqICAgICAgIGxvb3AgRm9yIGVhY2ggcm93XG4gICAqICAgICAgICAgUG9zdGdyZVNRTFBhZ2luYXRvci0+PkFkYXB0ZXI6IHJldmVydChyb3csIGNsYXp6LCBwa0RlZi5pZCwgaWQpXG4gICAqICAgICAgIGVuZFxuICAgKiAgICAgZW5kXG4gICAqXG4gICAqICAgICBQb3N0Z3JlU1FMUGFnaW5hdG9yLT4+UG9zdGdyZVNRTFBhZ2luYXRvcjogVXBkYXRlIGN1cnJlbnRQYWdlXG4gICAqICAgICBQb3N0Z3JlU1FMUGFnaW5hdG9yLS0+PkNsaWVudDogUmV0dXJuIHJlc3VsdHNcbiAgICogICBlbmRcbiAgICovXG4gIGFzeW5jIHBhZ2UocGFnZTogbnVtYmVyID0gMSk6IFByb21pc2U8UltdPiB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBOb3QgaW1wbGVtZW50ZWQgeWV0YCk7XG4gICAgLy8gY29uc3Qgc3RhdGVtZW50ID0geyAuLi50aGlzLnN0YXRlbWVudCB9O1xuICAgIC8vXG4gICAgLy8gLy8gR2V0IHRvdGFsIGNvdW50IGlmIG5vdCBhbHJlYWR5IGNhbGN1bGF0ZWRcbiAgICAvLyBpZiAoIXRoaXMuX3JlY29yZENvdW50IHx8ICF0aGlzLl90b3RhbFBhZ2VzKSB7XG4gICAgLy8gICB0aGlzLl90b3RhbFBhZ2VzID0gdGhpcy5fcmVjb3JkQ291bnQgPSAwO1xuICAgIC8vXG4gICAgLy8gICAvLyBDcmVhdGUgYSBjb3VudCBxdWVyeSBiYXNlZCBvbiB0aGUgb3JpZ2luYWwgcXVlcnlcbiAgICAvLyAgIGNvbnN0IGNvdW50UXVlcnk6IFBvc3RncmVzUXVlcnkgPSB7XG4gICAgLy8gICAgIC4uLnN0YXRlbWVudCxcbiAgICAvLyAgICAgY291bnQ6IHRydWUsXG4gICAgLy8gICAgIGxpbWl0OiB1bmRlZmluZWQsXG4gICAgLy8gICAgIG9mZnNldDogdW5kZWZpbmVkLFxuICAgIC8vICAgfTtcbiAgICAvL1xuICAgIC8vICAgY29uc3QgY291bnRSZXN1bHQ6IFF1ZXJ5UmVzdWx0ID0gYXdhaXQgdGhpcy5hZGFwdGVyLnJhdyhcbiAgICAvLyAgICAgY291bnRRdWVyeSxcbiAgICAvLyAgICAgZmFsc2VcbiAgICAvLyAgICk7XG4gICAgLy8gICB0aGlzLl9yZWNvcmRDb3VudCA9IHBhcnNlSW50KGNvdW50UmVzdWx0LnJvd3NbMF0/LmNvdW50IHx8IFwiMFwiLCAxMCk7XG4gICAgLy9cbiAgICAvLyAgIGlmICh0aGlzLl9yZWNvcmRDb3VudCA+IDApIHtcbiAgICAvLyAgICAgY29uc3Qgc2l6ZSA9IHN0YXRlbWVudD8ubGltaXQgfHwgdGhpcy5zaXplO1xuICAgIC8vICAgICB0aGlzLl90b3RhbFBhZ2VzID0gTWF0aC5jZWlsKHRoaXMuX3JlY29yZENvdW50IC8gc2l6ZSk7XG4gICAgLy8gICB9XG4gICAgLy8gfVxuICAgIC8vXG4gICAgLy8gdGhpcy52YWxpZGF0ZVBhZ2UocGFnZSk7XG4gICAgLy9cbiAgICAvLyAvLyBDYWxjdWxhdGUgb2Zmc2V0IGJhc2VkIG9uIHBhZ2UgbnVtYmVyXG4gICAgLy8gY29uc3Qgb2Zmc2V0ID0gKHBhZ2UgLSAxKSAqIHRoaXMuc2l6ZTtcbiAgICAvLyBzdGF0ZW1lbnQubGltaXQgPSB0aGlzLnNpemU7XG4gICAgLy8gc3RhdGVtZW50Lm9mZnNldCA9IG9mZnNldDtcbiAgICAvL1xuICAgIC8vIGNvbnN0IHJlc3VsdDogUG9zdGdyZVNRTFJlc3BvbnNlPGFueT4gPSBhd2FpdCB0aGlzLmFkYXB0ZXIucmF3KFxuICAgIC8vICAgc3RhdGVtZW50LFxuICAgIC8vICAgZmFsc2VcbiAgICAvLyApO1xuICAgIC8vXG4gICAgLy8gaWYgKCF0aGlzLmNsYXp6KSB0aHJvdyBuZXcgUGFnaW5nRXJyb3IoXCJObyBzdGF0ZW1lbnQgdGFyZ2V0IGRlZmluZWRcIik7XG4gICAgLy9cbiAgICAvLyBjb25zdCBwa0RlZiA9IGZpbmRQcmltYXJ5S2V5KG5ldyB0aGlzLmNsYXp6KCkpO1xuICAgIC8vIGNvbnN0IHJvd3MgPSByZXN1bHQucm93cyB8fCBbXTtcbiAgICAvL1xuICAgIC8vIGNvbnN0IHJlc3VsdHMgPVxuICAgIC8vICAgc3RhdGVtZW50LmNvbHVtbnMgJiYgc3RhdGVtZW50LmNvbHVtbnMubGVuZ3RoXG4gICAgLy8gICAgID8gcm93cyAvLyBoYXMgY29sdW1ucyBtZWFucyBpdCdzIG5vdCBmdWxsIG1vZGVsXG4gICAgLy8gICAgIDogcm93cy5tYXAoKHJvdzogYW55KSA9PiB7XG4gICAgLy8gICAgICAgICByZXR1cm4gdGhpcy5hZGFwdGVyLnJldmVydChcbiAgICAvLyAgICAgICAgICAgcm93LFxuICAgIC8vICAgICAgICAgICB0aGlzLmNsYXp6LFxuICAgIC8vICAgICAgICAgICBwa0RlZi5pZCxcbiAgICAvLyAgICAgICAgICAgU2VxdWVuY2UucGFyc2VWYWx1ZShwa0RlZi5wcm9wcy50eXBlLCByb3dbUG9zdGdyZVNRTEtleXMuSURdKVxuICAgIC8vICAgICAgICAgKTtcbiAgICAvLyAgICAgICB9KTtcbiAgICAvL1xuICAgIC8vIHRoaXMuX2N1cnJlbnRQYWdlID0gcGFnZTtcbiAgICAvLyByZXR1cm4gcmVzdWx0cyBhcyBSW107XG4gIH1cbn1cbiJdfQ==