@decaf-ts/for-typeorm 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +93 -0
- package/dist/for-typeorm.cjs +2553 -0
- package/dist/for-typeorm.esm.cjs +2538 -0
- package/lib/TypeORMAdapter.cjs +1129 -0
- package/lib/TypeORMAdapter.d.ts +221 -0
- package/lib/TypeORMDispatch.cjs +134 -0
- package/lib/TypeORMDispatch.d.ts +87 -0
- package/lib/TypeORMEventSubscriber.cjs +96 -0
- package/lib/TypeORMEventSubscriber.d.ts +56 -0
- package/lib/TypeORMRepository.cjs +209 -0
- package/lib/TypeORMRepository.d.ts +125 -0
- package/lib/constants.cjs +43 -0
- package/lib/constants.d.ts +39 -0
- package/lib/errors.cjs +28 -0
- package/lib/errors.d.ts +21 -0
- package/lib/esm/TypeORMAdapter.d.ts +221 -0
- package/lib/esm/TypeORMAdapter.js +1124 -0
- package/lib/esm/TypeORMDispatch.d.ts +87 -0
- package/lib/esm/TypeORMDispatch.js +130 -0
- package/lib/esm/TypeORMEventSubscriber.d.ts +56 -0
- package/lib/esm/TypeORMEventSubscriber.js +93 -0
- package/lib/esm/TypeORMRepository.d.ts +125 -0
- package/lib/esm/TypeORMRepository.js +206 -0
- package/lib/esm/constants.d.ts +39 -0
- package/lib/esm/constants.js +40 -0
- package/lib/esm/errors.d.ts +21 -0
- package/lib/esm/errors.js +24 -0
- package/lib/esm/index.d.ts +22 -0
- package/lib/esm/index.js +25 -0
- package/lib/esm/indexes/generator.d.ts +50 -0
- package/lib/esm/indexes/generator.js +95 -0
- package/lib/esm/indexes/index.d.ts +1 -0
- package/lib/esm/indexes/index.js +2 -0
- package/lib/esm/overrides/Column.d.ts +74 -0
- package/lib/esm/overrides/Column.js +70 -0
- package/lib/esm/overrides/CreateDateColumn.d.ts +2 -0
- package/lib/esm/overrides/CreateDateColumn.js +9 -0
- package/lib/esm/overrides/Entity.d.ts +11 -0
- package/lib/esm/overrides/Entity.js +28 -0
- package/lib/esm/overrides/PrimaryColumn.d.ts +20 -0
- package/lib/esm/overrides/PrimaryColumn.js +53 -0
- package/lib/esm/overrides/PrimaryGeneratedColumn.d.ts +24 -0
- package/lib/esm/overrides/PrimaryGeneratedColumn.js +51 -0
- package/lib/esm/overrides/UpdateDateColumn.d.ts +2 -0
- package/lib/esm/overrides/UpdateDateColumn.js +9 -0
- package/lib/esm/overrides/utils.d.ts +2 -0
- package/lib/esm/overrides/utils.js +29 -0
- package/lib/esm/query/Paginator.d.ts +86 -0
- package/lib/esm/query/Paginator.js +124 -0
- package/lib/esm/query/Statement.d.ts +131 -0
- package/lib/esm/query/Statement.js +242 -0
- package/lib/esm/query/constants.d.ts +52 -0
- package/lib/esm/query/constants.js +74 -0
- package/lib/esm/query/index.d.ts +4 -0
- package/lib/esm/query/index.js +5 -0
- package/lib/esm/query/translate.d.ts +34 -0
- package/lib/esm/query/translate.js +42 -0
- package/lib/esm/raw/postgres.d.ts +36 -0
- package/lib/esm/raw/postgres.js +2 -0
- package/lib/esm/sequences/Sequence.d.ts +67 -0
- package/lib/esm/sequences/Sequence.js +117 -0
- package/lib/esm/sequences/index.d.ts +1 -0
- package/lib/esm/sequences/index.js +2 -0
- package/lib/esm/types.d.ts +67 -0
- package/lib/esm/types.js +28 -0
- package/lib/esm/utils.d.ts +16 -0
- package/lib/esm/utils.js +29 -0
- package/lib/index.cjs +42 -0
- package/lib/index.d.ts +22 -0
- package/lib/indexes/generator.cjs +98 -0
- package/lib/indexes/generator.d.ts +50 -0
- package/lib/indexes/index.cjs +18 -0
- package/lib/indexes/index.d.ts +1 -0
- package/lib/overrides/Column.cjs +73 -0
- package/lib/overrides/Column.d.ts +74 -0
- package/lib/overrides/CreateDateColumn.cjs +12 -0
- package/lib/overrides/CreateDateColumn.d.ts +2 -0
- package/lib/overrides/Entity.cjs +31 -0
- package/lib/overrides/Entity.d.ts +11 -0
- package/lib/overrides/PrimaryColumn.cjs +56 -0
- package/lib/overrides/PrimaryColumn.d.ts +20 -0
- package/lib/overrides/PrimaryGeneratedColumn.cjs +54 -0
- package/lib/overrides/PrimaryGeneratedColumn.d.ts +24 -0
- package/lib/overrides/UpdateDateColumn.cjs +12 -0
- package/lib/overrides/UpdateDateColumn.d.ts +2 -0
- package/lib/overrides/utils.cjs +32 -0
- package/lib/overrides/utils.d.ts +2 -0
- package/lib/query/Paginator.cjs +128 -0
- package/lib/query/Paginator.d.ts +86 -0
- package/lib/query/Statement.cjs +246 -0
- package/lib/query/Statement.d.ts +131 -0
- package/lib/query/constants.cjs +77 -0
- package/lib/query/constants.d.ts +52 -0
- package/lib/query/index.cjs +21 -0
- package/lib/query/index.d.ts +4 -0
- package/lib/query/translate.cjs +45 -0
- package/lib/query/translate.d.ts +34 -0
- package/lib/raw/postgres.cjs +3 -0
- package/lib/raw/postgres.d.ts +36 -0
- package/lib/sequences/Sequence.cjs +121 -0
- package/lib/sequences/Sequence.d.ts +67 -0
- package/lib/sequences/index.cjs +18 -0
- package/lib/sequences/index.d.ts +1 -0
- package/lib/types.cjs +31 -0
- package/lib/types.d.ts +67 -0
- package/lib/utils.cjs +32 -0
- package/lib/utils.d.ts +16 -0
- package/package.json +128 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { PrimaryGeneratedColumnNumericOptions } from "typeorm/decorator/options/PrimaryGeneratedColumnNumericOptions";
|
|
2
|
+
import { PrimaryGeneratedColumnUUIDOptions } from "typeorm/decorator/options/PrimaryGeneratedColumnUUIDOptions";
|
|
3
|
+
import { PrimaryGeneratedColumnIdentityOptions } from "typeorm/decorator/options/PrimaryGeneratedColumnIdentityOptions";
|
|
4
|
+
/**
|
|
5
|
+
* Column decorator is used to mark a specific class property as a table column.
|
|
6
|
+
*/
|
|
7
|
+
export declare function PrimaryGeneratedColumn(): PropertyDecorator;
|
|
8
|
+
/**
|
|
9
|
+
* Column decorator is used to mark a specific class property as a table column.
|
|
10
|
+
*/
|
|
11
|
+
export declare function PrimaryGeneratedColumn(options: PrimaryGeneratedColumnNumericOptions): PropertyDecorator;
|
|
12
|
+
/**
|
|
13
|
+
* Column decorator is used to mark a specific class property as a table column.
|
|
14
|
+
*/
|
|
15
|
+
export declare function PrimaryGeneratedColumn(strategy: "increment", options?: PrimaryGeneratedColumnNumericOptions): PropertyDecorator;
|
|
16
|
+
/**
|
|
17
|
+
* Column decorator is used to mark a specific class property as a table column.
|
|
18
|
+
*/
|
|
19
|
+
export declare function PrimaryGeneratedColumn(strategy: "uuid", options?: PrimaryGeneratedColumnUUIDOptions): PropertyDecorator;
|
|
20
|
+
/**
|
|
21
|
+
* Column decorator is used to mark a specific class property as a table column.
|
|
22
|
+
*/
|
|
23
|
+
export declare function PrimaryGeneratedColumn(strategy: "rowid", options?: PrimaryGeneratedColumnUUIDOptions): PropertyDecorator;
|
|
24
|
+
export declare function PrimaryGeneratedColumn(strategy: "identity", options?: PrimaryGeneratedColumnIdentityOptions): PropertyDecorator;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UpdateDateColumn = UpdateDateColumn;
|
|
4
|
+
const typeorm_1 = require("typeorm");
|
|
5
|
+
const utils_1 = require("./utils.cjs");
|
|
6
|
+
function UpdateDateColumn(options) {
|
|
7
|
+
return function (object, propertyName) {
|
|
8
|
+
const columns = (0, typeorm_1.getMetadataArgsStorage)().columns;
|
|
9
|
+
(0, utils_1.aggregateOrNewColumn)(object.constructor, propertyName, columns, options || {}, "updateDate");
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVXBkYXRlRGF0ZUNvbHVtbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9vdmVycmlkZXMvVXBkYXRlRGF0ZUNvbHVtbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUdBLDRDQVdDO0FBZEQscUNBQWdFO0FBQ2hFLHVDQUErQztBQUUvQyxTQUFnQixnQkFBZ0IsQ0FBQyxPQUF1QjtJQUN0RCxPQUFPLFVBQVUsTUFBVyxFQUFFLFlBQWlCO1FBQzdDLE1BQU0sT0FBTyxHQUFHLElBQUEsZ0NBQXNCLEdBQUUsQ0FBQyxPQUFPLENBQUM7UUFDakQsSUFBQSw0QkFBb0IsRUFDbEIsTUFBTSxDQUFDLFdBQVcsRUFDbEIsWUFBWSxFQUNaLE9BQU8sRUFDUCxPQUFPLElBQUksRUFBRSxFQUNiLFlBQVksQ0FDYixDQUFDO0lBQ0osQ0FBQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbHVtbk9wdGlvbnMsIGdldE1ldGFkYXRhQXJnc1N0b3JhZ2UgfSBmcm9tIFwidHlwZW9ybVwiO1xuaW1wb3J0IHsgYWdncmVnYXRlT3JOZXdDb2x1bW4gfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5leHBvcnQgZnVuY3Rpb24gVXBkYXRlRGF0ZUNvbHVtbihvcHRpb25zPzogQ29sdW1uT3B0aW9ucyk6IFByb3BlcnR5RGVjb3JhdG9yIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIChvYmplY3Q6IGFueSwgcHJvcGVydHlOYW1lOiBhbnkpIHtcbiAgICBjb25zdCBjb2x1bW5zID0gZ2V0TWV0YWRhdGFBcmdzU3RvcmFnZSgpLmNvbHVtbnM7XG4gICAgYWdncmVnYXRlT3JOZXdDb2x1bW4oXG4gICAgICBvYmplY3QuY29uc3RydWN0b3IsXG4gICAgICBwcm9wZXJ0eU5hbWUsXG4gICAgICBjb2x1bW5zLFxuICAgICAgb3B0aW9ucyB8fCB7fSxcbiAgICAgIFwidXBkYXRlRGF0ZVwiXG4gICAgKTtcbiAgfTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.aggregateOrNewColumn = aggregateOrNewColumn;
|
|
4
|
+
function aggregateOrNewColumn(target, property, columns, options = {}, mode = "regular") {
|
|
5
|
+
const cols = columns.filter((c) => c.target === target && c.propertyName === property);
|
|
6
|
+
if (cols.length > 1)
|
|
7
|
+
throw new Error(`Multiple columns for ${property} found for given target: ${columns.map((c) => c.propertyName).join(", ")}`);
|
|
8
|
+
if (cols.length === 0) {
|
|
9
|
+
columns.push({
|
|
10
|
+
target: target,
|
|
11
|
+
propertyName: property,
|
|
12
|
+
mode: mode,
|
|
13
|
+
options: options,
|
|
14
|
+
});
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const column = cols[0];
|
|
18
|
+
Object.defineProperty(column, "options", {
|
|
19
|
+
value: { ...column.options, ...options },
|
|
20
|
+
writable: true,
|
|
21
|
+
enumerable: true,
|
|
22
|
+
configurable: true,
|
|
23
|
+
});
|
|
24
|
+
if (mode !== "regular")
|
|
25
|
+
Object.defineProperty(column, "mode", {
|
|
26
|
+
value: mode,
|
|
27
|
+
writable: true,
|
|
28
|
+
enumerable: true,
|
|
29
|
+
configurable: true,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvb3ZlcnJpZGVzL3V0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBRUEsb0RBMENDO0FBMUNELFNBQWdCLG9CQUFvQixDQUNsQyxNQUFXLEVBQ1gsUUFBZ0IsRUFDaEIsT0FBNkIsRUFDN0IsVUFBZSxFQUFFLEVBQ2pCLE9BQWUsU0FBUztJQUV4QixNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUN6QixDQUFDLENBQXFCLEVBQUUsRUFBRSxDQUN4QixDQUFDLENBQUMsTUFBTSxLQUFLLE1BQU0sSUFBSSxDQUFDLENBQUMsWUFBWSxLQUFLLFFBQVEsQ0FDckQsQ0FBQztJQUVGLElBQUksSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDO1FBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQ2Isd0JBQXdCLFFBQVEsNEJBQTRCLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FDNUcsQ0FBQztJQUVKLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUN0QixPQUFPLENBQUMsSUFBSSxDQUFDO1lBQ1gsTUFBTSxFQUFFLE1BQU07WUFDZCxZQUFZLEVBQUUsUUFBUTtZQUN0QixJQUFJLEVBQUUsSUFBSTtZQUNWLE9BQU8sRUFBRSxPQUFPO1NBQ0ssQ0FBQyxDQUFDO1FBQ3pCLE9BQU87SUFDVCxDQUFDO0lBRUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZCLE1BQU0sQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRTtRQUN2QyxLQUFLLEVBQUUsRUFBRSxHQUFHLE1BQU0sQ0FBQyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUU7UUFDeEMsUUFBUSxFQUFFLElBQUk7UUFDZCxVQUFVLEVBQUUsSUFBSTtRQUNoQixZQUFZLEVBQUUsSUFBSTtLQUNuQixDQUFDLENBQUM7SUFFSCxJQUFJLElBQUksS0FBSyxTQUFTO1FBQ3BCLE1BQU0sQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRTtZQUNwQyxLQUFLLEVBQUUsSUFBSTtZQUNYLFFBQVEsRUFBRSxJQUFJO1lBQ2QsVUFBVSxFQUFFLElBQUk7WUFDaEIsWUFBWSxFQUFFLElBQUk7U0FDbkIsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbHVtbk1ldGFkYXRhQXJncyB9IGZyb20gXCJ0eXBlb3JtL21ldGFkYXRhLWFyZ3MvQ29sdW1uTWV0YWRhdGFBcmdzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBhZ2dyZWdhdGVPck5ld0NvbHVtbihcbiAgdGFyZ2V0OiBhbnksXG4gIHByb3BlcnR5OiBzdHJpbmcsXG4gIGNvbHVtbnM6IENvbHVtbk1ldGFkYXRhQXJnc1tdLFxuICBvcHRpb25zOiBhbnkgPSB7fSxcbiAgbW9kZTogc3RyaW5nID0gXCJyZWd1bGFyXCJcbikge1xuICBjb25zdCBjb2xzID0gY29sdW1ucy5maWx0ZXIoXG4gICAgKGM6IENvbHVtbk1ldGFkYXRhQXJncykgPT5cbiAgICAgIGMudGFyZ2V0ID09PSB0YXJnZXQgJiYgYy5wcm9wZXJ0eU5hbWUgPT09IHByb3BlcnR5XG4gICk7XG5cbiAgaWYgKGNvbHMubGVuZ3RoID4gMSlcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgTXVsdGlwbGUgY29sdW1ucyBmb3IgJHtwcm9wZXJ0eX0gZm91bmQgZm9yIGdpdmVuIHRhcmdldDogJHtjb2x1bW5zLm1hcCgoYykgPT4gYy5wcm9wZXJ0eU5hbWUpLmpvaW4oXCIsIFwiKX1gXG4gICAgKTtcblxuICBpZiAoY29scy5sZW5ndGggPT09IDApIHtcbiAgICBjb2x1bW5zLnB1c2goe1xuICAgICAgdGFyZ2V0OiB0YXJnZXQsXG4gICAgICBwcm9wZXJ0eU5hbWU6IHByb3BlcnR5LFxuICAgICAgbW9kZTogbW9kZSxcbiAgICAgIG9wdGlvbnM6IG9wdGlvbnMsXG4gICAgfSBhcyBDb2x1bW5NZXRhZGF0YUFyZ3MpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGNvbHVtbiA9IGNvbHNbMF07XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb2x1bW4sIFwib3B0aW9uc1wiLCB7XG4gICAgdmFsdWU6IHsgLi4uY29sdW1uLm9wdGlvbnMsIC4uLm9wdGlvbnMgfSxcbiAgICB3cml0YWJsZTogdHJ1ZSxcbiAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgfSk7XG5cbiAgaWYgKG1vZGUgIT09IFwicmVndWxhclwiKVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb2x1bW4sIFwibW9kZVwiLCB7XG4gICAgICB2YWx1ZTogbW9kZSxcbiAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICB9KTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TypeORMPaginator = void 0;
|
|
4
|
+
const core_1 = require("@decaf-ts/core");
|
|
5
|
+
const decorator_validation_1 = require("@decaf-ts/decorator-validation");
|
|
6
|
+
const db_decorators_1 = require("@decaf-ts/db-decorators");
|
|
7
|
+
/**
|
|
8
|
+
* @description Paginator for TypeORM query results.
|
|
9
|
+
* @summary Implements pagination for TypeORM-built queries using take/skip for efficient navigation through result sets.
|
|
10
|
+
* @template M The model type that extends Model.
|
|
11
|
+
* @template R The result type.
|
|
12
|
+
* @param {TypeORMAdapter} adapter The TypeORM adapter.
|
|
13
|
+
* @param {TypeORMQuery} query The query container to paginate.
|
|
14
|
+
* @param {number} size The page size.
|
|
15
|
+
* @param {Constructor<M>} clazz The model constructor.
|
|
16
|
+
* @class TypeORMPaginator
|
|
17
|
+
* @example
|
|
18
|
+
* // Example of using TypeORMPaginator
|
|
19
|
+
* const paginator = new TypeORMPaginator(adapter, { query: qb }, 10, User);
|
|
20
|
+
* const page1 = await paginator.page(1);
|
|
21
|
+
* const page2 = await paginator.page(2);
|
|
22
|
+
*/
|
|
23
|
+
class TypeORMPaginator extends core_1.Paginator {
|
|
24
|
+
/**
|
|
25
|
+
* @description Gets the total number of pages
|
|
26
|
+
* @summary Returns the total number of pages based on the record count and page size
|
|
27
|
+
* @return {number} The total number of pages
|
|
28
|
+
*/
|
|
29
|
+
get total() {
|
|
30
|
+
return this._totalPages;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* @description Gets the total record count
|
|
34
|
+
* @summary Returns the total number of records matching the query
|
|
35
|
+
* @return {number} The total record count
|
|
36
|
+
*/
|
|
37
|
+
get count() {
|
|
38
|
+
return this._recordCount;
|
|
39
|
+
}
|
|
40
|
+
get repo() {
|
|
41
|
+
if (!this.__repo) {
|
|
42
|
+
this.__repo = this.adapter.dataSource.getRepository(this.clazz[decorator_validation_1.ModelKeys.ANCHOR]);
|
|
43
|
+
}
|
|
44
|
+
return this.__repo;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* @description Creates a new TypeORMPaginator instance.
|
|
48
|
+
* @summary Initializes a paginator for TypeORM query results.
|
|
49
|
+
* @param {TypeORMAdapter} adapter The TypeORM adapter.
|
|
50
|
+
* @param {TypeORMQuery} query The TypeORM query container to paginate.
|
|
51
|
+
* @param {number} size The page size.
|
|
52
|
+
* @param {Constructor<M>} clazz The model constructor.
|
|
53
|
+
*/
|
|
54
|
+
constructor(adapter, query, size, clazz) {
|
|
55
|
+
super(adapter, query, size, clazz);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* @description Prepares a query for pagination
|
|
59
|
+
* @summary Modifies the raw query to include pagination parameters
|
|
60
|
+
* @param {TypeORMQuery} rawStatement - The original PostgreSQL query
|
|
61
|
+
* @return {TypeORMQuery} The prepared query with pagination parameters
|
|
62
|
+
*/
|
|
63
|
+
prepare(rawStatement) {
|
|
64
|
+
const query = { ...rawStatement };
|
|
65
|
+
return query;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* @description Retrieves a specific page of results.
|
|
69
|
+
* @summary Executes the query with pagination and processes the results.
|
|
70
|
+
* @param {number} [page=1] The page number to retrieve.
|
|
71
|
+
* @return {Promise<R[]>} A promise that resolves to an array of results.
|
|
72
|
+
* @throws {PagingError} If trying to access an invalid page or if no class is defined.
|
|
73
|
+
* @mermaid
|
|
74
|
+
* sequenceDiagram
|
|
75
|
+
* participant Client
|
|
76
|
+
* participant Paginator as TypeORMPaginator
|
|
77
|
+
* participant Adapter
|
|
78
|
+
* participant DB as Database
|
|
79
|
+
*
|
|
80
|
+
* Client->>Paginator: page(pageNumber)
|
|
81
|
+
* Note over Paginator: Prepare options (skip/take)
|
|
82
|
+
*
|
|
83
|
+
* alt First time or need count
|
|
84
|
+
* Paginator->>Adapter: Get count
|
|
85
|
+
* Adapter->>DB: Execute COUNT
|
|
86
|
+
* DB-->>Adapter: count
|
|
87
|
+
* Adapter-->>Paginator: count
|
|
88
|
+
* Paginator->>Paginator: Calculate total pages
|
|
89
|
+
* end
|
|
90
|
+
*
|
|
91
|
+
* Paginator->>Adapter: Execute query
|
|
92
|
+
* Adapter->>DB: findAndCount(options)
|
|
93
|
+
* DB-->>Adapter: rows, count
|
|
94
|
+
* Adapter-->>Paginator: rows, count
|
|
95
|
+
*
|
|
96
|
+
* Paginator->>Paginator: Map rows to models
|
|
97
|
+
* Paginator-->>Client: results
|
|
98
|
+
*/
|
|
99
|
+
async page(page = 1) {
|
|
100
|
+
const statement = { ...this.statement };
|
|
101
|
+
// Get total count if not already calculated
|
|
102
|
+
if (!this._recordCount || !this._totalPages) {
|
|
103
|
+
this._totalPages = this._recordCount = 0;
|
|
104
|
+
}
|
|
105
|
+
const opts = Object.assign(statement, {
|
|
106
|
+
skip: (this.current || 0) * this.size,
|
|
107
|
+
take: this.size,
|
|
108
|
+
});
|
|
109
|
+
// this.validatePage(page);
|
|
110
|
+
const result = await this.repo.findAndCount(opts);
|
|
111
|
+
this._recordCount = result[1];
|
|
112
|
+
this._totalPages = Math.ceil(this._recordCount / this.size);
|
|
113
|
+
if (!this.clazz)
|
|
114
|
+
throw new core_1.PagingError("No statement target defined");
|
|
115
|
+
const pkDef = (0, db_decorators_1.findPrimaryKey)(new this.clazz());
|
|
116
|
+
const rows = result[0] || [];
|
|
117
|
+
const results =
|
|
118
|
+
// statement.columns && statement.columns.length
|
|
119
|
+
// ? rows // has columns means it's not full model
|
|
120
|
+
rows.map((row) => {
|
|
121
|
+
return this.adapter.revert(row, this.clazz, pkDef.id, row[pkDef.id]);
|
|
122
|
+
});
|
|
123
|
+
this._currentPage = page;
|
|
124
|
+
return results;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
exports.TypeORMPaginator = TypeORMPaginator;
|
|
128
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUGFnaW5hdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3F1ZXJ5L1BhZ2luYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5Q0FBd0Q7QUFFeEQseUVBQStFO0FBRy9FLDJEQUF5RDtBQUV6RDs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxNQUFhLGdCQUFxQyxTQUFRLGdCQUl6RDtJQUNDOzs7O09BSUc7SUFDSCxJQUFhLEtBQUs7UUFDaEIsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDO0lBQzFCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsSUFBYSxLQUFLO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztJQUMzQixDQUFDO0lBSUQsSUFBYyxJQUFJO1FBQ2hCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDakIsSUFBSSxDQUFDLE1BQU0sR0FBSSxJQUFJLENBQUMsT0FBMEIsQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUNyRSxJQUFJLENBQUMsS0FBSyxDQUFDLGdDQUFTLENBQUMsTUFBaUMsQ0FBQyxDQUN4RCxDQUFDO1FBQ0osQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILFlBQ0UsT0FBdUIsRUFDdkIsS0FBbUIsRUFDbkIsSUFBWSxFQUNaLEtBQXFCO1FBRXJCLEtBQUssQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDTyxPQUFPLENBQUMsWUFBMEI7UUFDMUMsTUFBTSxLQUFLLEdBQWlCLEVBQUUsR0FBRyxZQUFZLEVBQUUsQ0FBQztRQUNoRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQStCRztJQUVILEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBZSxDQUFDO1FBQ3pCLE1BQU0sU0FBUyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFFeEMsNENBQTRDO1FBQzVDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzVDLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFlBQVksR0FBRyxDQUFDLENBQUM7UUFDM0MsQ0FBQztRQUVELE1BQU0sSUFBSSxHQUF1QixNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRTtZQUN4RCxJQUFJLEVBQUUsQ0FBQyxJQUFJLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJO1lBQ3JDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTtTQUNoQixDQUFDLENBQUM7UUFFSCwyQkFBMkI7UUFFM0IsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVsRCxJQUFJLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5QixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFNUQsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLO1lBQUUsTUFBTSxJQUFJLGtCQUFXLENBQUMsNkJBQTZCLENBQUMsQ0FBQztRQUV0RSxNQUFNLEtBQUssR0FBRyxJQUFBLDhCQUFjLEVBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUMvQyxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBRTdCLE1BQU0sT0FBTztRQUNYLGdEQUFnRDtRQUNoRCxvREFBb0Q7UUFDcEQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQVEsRUFBRSxFQUFFO1lBQ3BCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLEVBQUUsRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDdkUsQ0FBQyxDQUFDLENBQUM7UUFFTCxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztRQUN6QixPQUFPLE9BQXlCLENBQUM7SUFDbkMsQ0FBQztDQUNGO0FBbElELDRDQWtJQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBhZ2luYXRvciwgUGFnaW5nRXJyb3IgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IFR5cGVPUk1RdWVyeSB9IGZyb20gXCIuLi90eXBlc1wiO1xuaW1wb3J0IHsgQ29uc3RydWN0b3IsIE1vZGVsLCBNb2RlbEtleXMgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBUeXBlT1JNQWRhcHRlciB9IGZyb20gXCIuLi9UeXBlT1JNQWRhcHRlclwiO1xuaW1wb3J0IHsgRmluZE1hbnlPcHRpb25zLCBSZXBvc2l0b3J5IGFzIFJlcG8gfSBmcm9tIFwidHlwZW9ybVwiO1xuaW1wb3J0IHsgZmluZFByaW1hcnlLZXkgfSBmcm9tIFwiQGRlY2FmLXRzL2RiLWRlY29yYXRvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUGFnaW5hdG9yIGZvciBUeXBlT1JNIHF1ZXJ5IHJlc3VsdHMuXG4gKiBAc3VtbWFyeSBJbXBsZW1lbnRzIHBhZ2luYXRpb24gZm9yIFR5cGVPUk0tYnVpbHQgcXVlcmllcyB1c2luZyB0YWtlL3NraXAgZm9yIGVmZmljaWVudCBuYXZpZ2F0aW9uIHRocm91Z2ggcmVzdWx0IHNldHMuXG4gKiBAdGVtcGxhdGUgTSBUaGUgbW9kZWwgdHlwZSB0aGF0IGV4dGVuZHMgTW9kZWwuXG4gKiBAdGVtcGxhdGUgUiBUaGUgcmVzdWx0IHR5cGUuXG4gKiBAcGFyYW0ge1R5cGVPUk1BZGFwdGVyfSBhZGFwdGVyIFRoZSBUeXBlT1JNIGFkYXB0ZXIuXG4gKiBAcGFyYW0ge1R5cGVPUk1RdWVyeX0gcXVlcnkgVGhlIHF1ZXJ5IGNvbnRhaW5lciB0byBwYWdpbmF0ZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIFRoZSBwYWdlIHNpemUuXG4gKiBAcGFyYW0ge0NvbnN0cnVjdG9yPE0+fSBjbGF6eiBUaGUgbW9kZWwgY29uc3RydWN0b3IuXG4gKiBAY2xhc3MgVHlwZU9STVBhZ2luYXRvclxuICogQGV4YW1wbGVcbiAqIC8vIEV4YW1wbGUgb2YgdXNpbmcgVHlwZU9STVBhZ2luYXRvclxuICogY29uc3QgcGFnaW5hdG9yID0gbmV3IFR5cGVPUk1QYWdpbmF0b3IoYWRhcHRlciwgeyBxdWVyeTogcWIgfSwgMTAsIFVzZXIpO1xuICogY29uc3QgcGFnZTEgPSBhd2FpdCBwYWdpbmF0b3IucGFnZSgxKTtcbiAqIGNvbnN0IHBhZ2UyID0gYXdhaXQgcGFnaW5hdG9yLnBhZ2UoMik7XG4gKi9cbmV4cG9ydCBjbGFzcyBUeXBlT1JNUGFnaW5hdG9yPE0gZXh0ZW5kcyBNb2RlbCwgUj4gZXh0ZW5kcyBQYWdpbmF0b3I8XG4gIE0sXG4gIFIsXG4gIFR5cGVPUk1RdWVyeVxuPiB7XG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgdG90YWwgbnVtYmVyIG9mIHBhZ2VzXG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIHRvdGFsIG51bWJlciBvZiBwYWdlcyBiYXNlZCBvbiB0aGUgcmVjb3JkIGNvdW50IGFuZCBwYWdlIHNpemVcbiAgICogQHJldHVybiB7bnVtYmVyfSBUaGUgdG90YWwgbnVtYmVyIG9mIHBhZ2VzXG4gICAqL1xuICBvdmVycmlkZSBnZXQgdG90YWwoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fdG90YWxQYWdlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gR2V0cyB0aGUgdG90YWwgcmVjb3JkIGNvdW50XG4gICAqIEBzdW1tYXJ5IFJldHVybnMgdGhlIHRvdGFsIG51bWJlciBvZiByZWNvcmRzIG1hdGNoaW5nIHRoZSBxdWVyeVxuICAgKiBAcmV0dXJuIHtudW1iZXJ9IFRoZSB0b3RhbCByZWNvcmQgY291bnRcbiAgICovXG4gIG92ZXJyaWRlIGdldCBjb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9yZWNvcmRDb3VudDtcbiAgfVxuXG4gIHByaXZhdGUgX19yZXBvPzogUmVwbzxhbnk+O1xuXG4gIHByb3RlY3RlZCBnZXQgcmVwbygpIHtcbiAgICBpZiAoIXRoaXMuX19yZXBvKSB7XG4gICAgICB0aGlzLl9fcmVwbyA9ICh0aGlzLmFkYXB0ZXIgYXMgVHlwZU9STUFkYXB0ZXIpLmRhdGFTb3VyY2UuZ2V0UmVwb3NpdG9yeShcbiAgICAgICAgdGhpcy5jbGF6eltNb2RlbEtleXMuQU5DSE9SIGFzIGtleW9mIHR5cGVvZiB0aGlzLmNsYXp6XVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX19yZXBvO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgbmV3IFR5cGVPUk1QYWdpbmF0b3IgaW5zdGFuY2UuXG4gICAqIEBzdW1tYXJ5IEluaXRpYWxpemVzIGEgcGFnaW5hdG9yIGZvciBUeXBlT1JNIHF1ZXJ5IHJlc3VsdHMuXG4gICAqIEBwYXJhbSB7VHlwZU9STUFkYXB0ZXJ9IGFkYXB0ZXIgVGhlIFR5cGVPUk0gYWRhcHRlci5cbiAgICogQHBhcmFtIHtUeXBlT1JNUXVlcnl9IHF1ZXJ5IFRoZSBUeXBlT1JNIHF1ZXJ5IGNvbnRhaW5lciB0byBwYWdpbmF0ZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHNpemUgVGhlIHBhZ2Ugc2l6ZS5cbiAgICogQHBhcmFtIHtDb25zdHJ1Y3RvcjxNPn0gY2xhenogVGhlIG1vZGVsIGNvbnN0cnVjdG9yLlxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgYWRhcHRlcjogVHlwZU9STUFkYXB0ZXIsXG4gICAgcXVlcnk6IFR5cGVPUk1RdWVyeSxcbiAgICBzaXplOiBudW1iZXIsXG4gICAgY2xheno6IENvbnN0cnVjdG9yPE0+XG4gICkge1xuICAgIHN1cGVyKGFkYXB0ZXIsIHF1ZXJ5LCBzaXplLCBjbGF6eik7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFByZXBhcmVzIGEgcXVlcnkgZm9yIHBhZ2luYXRpb25cbiAgICogQHN1bW1hcnkgTW9kaWZpZXMgdGhlIHJhdyBxdWVyeSB0byBpbmNsdWRlIHBhZ2luYXRpb24gcGFyYW1ldGVyc1xuICAgKiBAcGFyYW0ge1R5cGVPUk1RdWVyeX0gcmF3U3RhdGVtZW50IC0gVGhlIG9yaWdpbmFsIFBvc3RncmVTUUwgcXVlcnlcbiAgICogQHJldHVybiB7VHlwZU9STVF1ZXJ5fSBUaGUgcHJlcGFyZWQgcXVlcnkgd2l0aCBwYWdpbmF0aW9uIHBhcmFtZXRlcnNcbiAgICovXG4gIHByb3RlY3RlZCBwcmVwYXJlKHJhd1N0YXRlbWVudDogVHlwZU9STVF1ZXJ5KTogVHlwZU9STVF1ZXJ5IHtcbiAgICBjb25zdCBxdWVyeTogVHlwZU9STVF1ZXJ5ID0geyAuLi5yYXdTdGF0ZW1lbnQgfTtcbiAgICByZXR1cm4gcXVlcnk7XG4gIH1cblxuICAvKipcbiAgICogQGRlc2NyaXB0aW9uIFJldHJpZXZlcyBhIHNwZWNpZmljIHBhZ2Ugb2YgcmVzdWx0cy5cbiAgICogQHN1bW1hcnkgRXhlY3V0ZXMgdGhlIHF1ZXJ5IHdpdGggcGFnaW5hdGlvbiBhbmQgcHJvY2Vzc2VzIHRoZSByZXN1bHRzLlxuICAgKiBAcGFyYW0ge251bWJlcn0gW3BhZ2U9MV0gVGhlIHBhZ2UgbnVtYmVyIHRvIHJldHJpZXZlLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPFJbXT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIGFycmF5IG9mIHJlc3VsdHMuXG4gICAqIEB0aHJvd3Mge1BhZ2luZ0Vycm9yfSBJZiB0cnlpbmcgdG8gYWNjZXNzIGFuIGludmFsaWQgcGFnZSBvciBpZiBubyBjbGFzcyBpcyBkZWZpbmVkLlxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAgICogICBwYXJ0aWNpcGFudCBQYWdpbmF0b3IgYXMgVHlwZU9STVBhZ2luYXRvclxuICAgKiAgIHBhcnRpY2lwYW50IEFkYXB0ZXJcbiAgICogICBwYXJ0aWNpcGFudCBEQiBhcyBEYXRhYmFzZVxuICAgKlxuICAgKiAgIENsaWVudC0+PlBhZ2luYXRvcjogcGFnZShwYWdlTnVtYmVyKVxuICAgKiAgIE5vdGUgb3ZlciBQYWdpbmF0b3I6IFByZXBhcmUgb3B0aW9ucyAoc2tpcC90YWtlKVxuICAgKlxuICAgKiAgIGFsdCBGaXJzdCB0aW1lIG9yIG5lZWQgY291bnRcbiAgICogICAgIFBhZ2luYXRvci0+PkFkYXB0ZXI6IEdldCBjb3VudFxuICAgKiAgICAgQWRhcHRlci0+PkRCOiBFeGVjdXRlIENPVU5UXG4gICAqICAgICBEQi0tPj5BZGFwdGVyOiBjb3VudFxuICAgKiAgICAgQWRhcHRlci0tPj5QYWdpbmF0b3I6IGNvdW50XG4gICAqICAgICBQYWdpbmF0b3ItPj5QYWdpbmF0b3I6IENhbGN1bGF0ZSB0b3RhbCBwYWdlc1xuICAgKiAgIGVuZFxuICAgKlxuICAgKiAgIFBhZ2luYXRvci0+PkFkYXB0ZXI6IEV4ZWN1dGUgcXVlcnlcbiAgICogICBBZGFwdGVyLT4+REI6IGZpbmRBbmRDb3VudChvcHRpb25zKVxuICAgKiAgIERCLS0+PkFkYXB0ZXI6IHJvd3MsIGNvdW50XG4gICAqICAgQWRhcHRlci0tPj5QYWdpbmF0b3I6IHJvd3MsIGNvdW50XG4gICAqXG4gICAqICAgUGFnaW5hdG9yLT4+UGFnaW5hdG9yOiBNYXAgcm93cyB0byBtb2RlbHNcbiAgICogICBQYWdpbmF0b3ItLT4+Q2xpZW50OiByZXN1bHRzXG4gICAqL1xuXG4gIGFzeW5jIHBhZ2UocGFnZTogbnVtYmVyID0gMSk6IFByb21pc2U8UltdPiB7XG4gICAgY29uc3Qgc3RhdGVtZW50ID0geyAuLi50aGlzLnN0YXRlbWVudCB9O1xuXG4gICAgLy8gR2V0IHRvdGFsIGNvdW50IGlmIG5vdCBhbHJlYWR5IGNhbGN1bGF0ZWRcbiAgICBpZiAoIXRoaXMuX3JlY29yZENvdW50IHx8ICF0aGlzLl90b3RhbFBhZ2VzKSB7XG4gICAgICB0aGlzLl90b3RhbFBhZ2VzID0gdGhpcy5fcmVjb3JkQ291bnQgPSAwO1xuICAgIH1cblxuICAgIGNvbnN0IG9wdHM6IEZpbmRNYW55T3B0aW9uczxNPiA9IE9iamVjdC5hc3NpZ24oc3RhdGVtZW50LCB7XG4gICAgICBza2lwOiAodGhpcy5jdXJyZW50IHx8IDApICogdGhpcy5zaXplLFxuICAgICAgdGFrZTogdGhpcy5zaXplLFxuICAgIH0pO1xuXG4gICAgLy8gdGhpcy52YWxpZGF0ZVBhZ2UocGFnZSk7XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnJlcG8uZmluZEFuZENvdW50KG9wdHMpO1xuXG4gICAgdGhpcy5fcmVjb3JkQ291bnQgPSByZXN1bHRbMV07XG4gICAgdGhpcy5fdG90YWxQYWdlcyA9IE1hdGguY2VpbCh0aGlzLl9yZWNvcmRDb3VudCAvIHRoaXMuc2l6ZSk7XG5cbiAgICBpZiAoIXRoaXMuY2xhenopIHRocm93IG5ldyBQYWdpbmdFcnJvcihcIk5vIHN0YXRlbWVudCB0YXJnZXQgZGVmaW5lZFwiKTtcblxuICAgIGNvbnN0IHBrRGVmID0gZmluZFByaW1hcnlLZXkobmV3IHRoaXMuY2xhenooKSk7XG4gICAgY29uc3Qgcm93cyA9IHJlc3VsdFswXSB8fCBbXTtcblxuICAgIGNvbnN0IHJlc3VsdHMgPVxuICAgICAgLy8gc3RhdGVtZW50LmNvbHVtbnMgJiYgc3RhdGVtZW50LmNvbHVtbnMubGVuZ3RoXG4gICAgICAvLyAgID8gcm93cyAvLyBoYXMgY29sdW1ucyBtZWFucyBpdCdzIG5vdCBmdWxsIG1vZGVsXG4gICAgICByb3dzLm1hcCgocm93OiBhbnkpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yZXZlcnQocm93LCB0aGlzLmNsYXp6LCBwa0RlZi5pZCwgcm93W3BrRGVmLmlkXSk7XG4gICAgICB9KTtcblxuICAgIHRoaXMuX2N1cnJlbnRQYWdlID0gcGFnZTtcbiAgICByZXR1cm4gcmVzdWx0cyBhcyB1bmtub3duIGFzIFJbXTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Paginator } from "@decaf-ts/core";
|
|
2
|
+
import { TypeORMQuery } from "../types";
|
|
3
|
+
import { Constructor, Model } from "@decaf-ts/decorator-validation";
|
|
4
|
+
import { TypeORMAdapter } from "../TypeORMAdapter";
|
|
5
|
+
import { Repository as Repo } from "typeorm";
|
|
6
|
+
/**
|
|
7
|
+
* @description Paginator for TypeORM query results.
|
|
8
|
+
* @summary Implements pagination for TypeORM-built queries using take/skip for efficient navigation through result sets.
|
|
9
|
+
* @template M The model type that extends Model.
|
|
10
|
+
* @template R The result type.
|
|
11
|
+
* @param {TypeORMAdapter} adapter The TypeORM adapter.
|
|
12
|
+
* @param {TypeORMQuery} query The query container to paginate.
|
|
13
|
+
* @param {number} size The page size.
|
|
14
|
+
* @param {Constructor<M>} clazz The model constructor.
|
|
15
|
+
* @class TypeORMPaginator
|
|
16
|
+
* @example
|
|
17
|
+
* // Example of using TypeORMPaginator
|
|
18
|
+
* const paginator = new TypeORMPaginator(adapter, { query: qb }, 10, User);
|
|
19
|
+
* const page1 = await paginator.page(1);
|
|
20
|
+
* const page2 = await paginator.page(2);
|
|
21
|
+
*/
|
|
22
|
+
export declare class TypeORMPaginator<M extends Model, R> extends Paginator<M, R, TypeORMQuery> {
|
|
23
|
+
/**
|
|
24
|
+
* @description Gets the total number of pages
|
|
25
|
+
* @summary Returns the total number of pages based on the record count and page size
|
|
26
|
+
* @return {number} The total number of pages
|
|
27
|
+
*/
|
|
28
|
+
get total(): number;
|
|
29
|
+
/**
|
|
30
|
+
* @description Gets the total record count
|
|
31
|
+
* @summary Returns the total number of records matching the query
|
|
32
|
+
* @return {number} The total record count
|
|
33
|
+
*/
|
|
34
|
+
get count(): number;
|
|
35
|
+
private __repo?;
|
|
36
|
+
protected get repo(): Repo<any>;
|
|
37
|
+
/**
|
|
38
|
+
* @description Creates a new TypeORMPaginator instance.
|
|
39
|
+
* @summary Initializes a paginator for TypeORM query results.
|
|
40
|
+
* @param {TypeORMAdapter} adapter The TypeORM adapter.
|
|
41
|
+
* @param {TypeORMQuery} query The TypeORM query container to paginate.
|
|
42
|
+
* @param {number} size The page size.
|
|
43
|
+
* @param {Constructor<M>} clazz The model constructor.
|
|
44
|
+
*/
|
|
45
|
+
constructor(adapter: TypeORMAdapter, query: TypeORMQuery, size: number, clazz: Constructor<M>);
|
|
46
|
+
/**
|
|
47
|
+
* @description Prepares a query for pagination
|
|
48
|
+
* @summary Modifies the raw query to include pagination parameters
|
|
49
|
+
* @param {TypeORMQuery} rawStatement - The original PostgreSQL query
|
|
50
|
+
* @return {TypeORMQuery} The prepared query with pagination parameters
|
|
51
|
+
*/
|
|
52
|
+
protected prepare(rawStatement: TypeORMQuery): TypeORMQuery;
|
|
53
|
+
/**
|
|
54
|
+
* @description Retrieves a specific page of results.
|
|
55
|
+
* @summary Executes the query with pagination and processes the results.
|
|
56
|
+
* @param {number} [page=1] The page number to retrieve.
|
|
57
|
+
* @return {Promise<R[]>} A promise that resolves to an array of results.
|
|
58
|
+
* @throws {PagingError} If trying to access an invalid page or if no class is defined.
|
|
59
|
+
* @mermaid
|
|
60
|
+
* sequenceDiagram
|
|
61
|
+
* participant Client
|
|
62
|
+
* participant Paginator as TypeORMPaginator
|
|
63
|
+
* participant Adapter
|
|
64
|
+
* participant DB as Database
|
|
65
|
+
*
|
|
66
|
+
* Client->>Paginator: page(pageNumber)
|
|
67
|
+
* Note over Paginator: Prepare options (skip/take)
|
|
68
|
+
*
|
|
69
|
+
* alt First time or need count
|
|
70
|
+
* Paginator->>Adapter: Get count
|
|
71
|
+
* Adapter->>DB: Execute COUNT
|
|
72
|
+
* DB-->>Adapter: count
|
|
73
|
+
* Adapter-->>Paginator: count
|
|
74
|
+
* Paginator->>Paginator: Calculate total pages
|
|
75
|
+
* end
|
|
76
|
+
*
|
|
77
|
+
* Paginator->>Adapter: Execute query
|
|
78
|
+
* Adapter->>DB: findAndCount(options)
|
|
79
|
+
* DB-->>Adapter: rows, count
|
|
80
|
+
* Adapter-->>Paginator: rows, count
|
|
81
|
+
*
|
|
82
|
+
* Paginator->>Paginator: Map rows to models
|
|
83
|
+
* Paginator-->>Client: results
|
|
84
|
+
*/
|
|
85
|
+
page(page?: number): Promise<R[]>;
|
|
86
|
+
}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TypeORMStatement = void 0;
|
|
4
|
+
const core_1 = require("@decaf-ts/core");
|
|
5
|
+
const decorator_validation_1 = require("@decaf-ts/decorator-validation");
|
|
6
|
+
const translate_1 = require("./translate.cjs");
|
|
7
|
+
const constants_1 = require("./constants.cjs");
|
|
8
|
+
const Paginator_1 = require("./Paginator.cjs");
|
|
9
|
+
const db_decorators_1 = require("@decaf-ts/db-decorators");
|
|
10
|
+
/**
|
|
11
|
+
* @description Statement builder for TypeORM-backed queries.
|
|
12
|
+
* @summary Provides a fluent interface for building SQL queries via TypeORM's SelectQueryBuilder with type safety and Decaf.ts abstractions.
|
|
13
|
+
* @template M The model type that extends Model.
|
|
14
|
+
* @template R The result type returned from execution.
|
|
15
|
+
* @param {TypeORMAdapter} adapter The TypeORM adapter.
|
|
16
|
+
* @class TypeORMStatement
|
|
17
|
+
* @example
|
|
18
|
+
* // Example using TypeORMStatement
|
|
19
|
+
* const statement = new TypeORMStatement<User, User[]>(adapter);
|
|
20
|
+
* const users = await statement
|
|
21
|
+
* .from(User)
|
|
22
|
+
* .where(Condition.attribute<User>('age').gt(18))
|
|
23
|
+
* .orderBy('lastName', 'asc')
|
|
24
|
+
* .limit(10)
|
|
25
|
+
* .execute();
|
|
26
|
+
*/
|
|
27
|
+
class TypeORMStatement extends core_1.Statement {
|
|
28
|
+
constructor(adapter) {
|
|
29
|
+
super(adapter);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* @description Builds a TypeORM SelectQueryBuilder from the statement.
|
|
33
|
+
* @summary Converts the statement's conditions, selectors, and options into a TypeORM-backed query object.
|
|
34
|
+
* @return {TypeORMQuery} The built TypeORM query container.
|
|
35
|
+
* @throws {Error} If there are invalid query conditions.
|
|
36
|
+
* @mermaid
|
|
37
|
+
* sequenceDiagram
|
|
38
|
+
* participant Statement
|
|
39
|
+
* participant Repository
|
|
40
|
+
* participant parseCondition
|
|
41
|
+
*
|
|
42
|
+
* Statement->>Statement: build()
|
|
43
|
+
* Note over Statement: Initialize query
|
|
44
|
+
* Statement->>Repository: Get table name
|
|
45
|
+
* Repository-->>Statement: Return table name
|
|
46
|
+
* Statement->>Statement: Create base query
|
|
47
|
+
*
|
|
48
|
+
* alt Has selectSelector
|
|
49
|
+
* Statement->>Statement: Add columns to query
|
|
50
|
+
* end
|
|
51
|
+
*
|
|
52
|
+
* alt Has whereCondition
|
|
53
|
+
* Statement->>Statement: Create combined condition with table
|
|
54
|
+
* Statement->>parseCondition: Parse condition
|
|
55
|
+
* parseCondition-->>Statement: Return parsed conditions
|
|
56
|
+
* Statement->>Statement: Add conditions to query
|
|
57
|
+
* end
|
|
58
|
+
*
|
|
59
|
+
* alt Has orderBySelector
|
|
60
|
+
* Statement->>Statement: Add orderBy to query
|
|
61
|
+
* end
|
|
62
|
+
*
|
|
63
|
+
* alt Has limitSelector
|
|
64
|
+
* Statement->>Statement: Set limit
|
|
65
|
+
* else
|
|
66
|
+
* Statement->>Statement: Use default limit
|
|
67
|
+
* end
|
|
68
|
+
*
|
|
69
|
+
* alt Has offsetSelector
|
|
70
|
+
* Statement->>Statement: Set offset
|
|
71
|
+
* end
|
|
72
|
+
*
|
|
73
|
+
* Statement-->>Statement: Return query
|
|
74
|
+
*/
|
|
75
|
+
build() {
|
|
76
|
+
const log = this.log.for(this.build);
|
|
77
|
+
const tableName = core_1.Repository.table(this.fromSelector);
|
|
78
|
+
const m = new this.fromSelector();
|
|
79
|
+
const q = {
|
|
80
|
+
query: this.adapter.dataSource
|
|
81
|
+
.getRepository(this.fromSelector[decorator_validation_1.ModelKeys.ANCHOR])
|
|
82
|
+
.createQueryBuilder(tableName),
|
|
83
|
+
};
|
|
84
|
+
if (this.selectSelector)
|
|
85
|
+
q.query = q.query.select(this.selectSelector.map((s) => `${tableName}.${s}`));
|
|
86
|
+
else
|
|
87
|
+
q.query = q.query.select();
|
|
88
|
+
//
|
|
89
|
+
// q.query = (q.query as SelectQueryBuilder<any>).from(
|
|
90
|
+
// this.fromSelector[ModelKeys.ANCHOR as keyof typeof this.fromSelector],
|
|
91
|
+
// tableName
|
|
92
|
+
// );
|
|
93
|
+
if (this.whereCondition)
|
|
94
|
+
q.query = this.parseCondition(this.whereCondition, tableName, q.query).query;
|
|
95
|
+
let orderByArgs;
|
|
96
|
+
if (!this.orderBySelector)
|
|
97
|
+
orderByArgs = [
|
|
98
|
+
`${tableName}.${(0, db_decorators_1.findPrimaryKey)(m).id}`,
|
|
99
|
+
core_1.OrderDirection.ASC.toUpperCase(),
|
|
100
|
+
];
|
|
101
|
+
else
|
|
102
|
+
orderByArgs = [
|
|
103
|
+
`${tableName}.${this.orderBySelector[0]}`,
|
|
104
|
+
this.orderBySelector[1].toUpperCase(),
|
|
105
|
+
];
|
|
106
|
+
q.query = q.query.orderBy(...orderByArgs);
|
|
107
|
+
if (this.limitSelector) {
|
|
108
|
+
q.query = q.query.limit(this.limitSelector);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
log.debug(`No limit selector defined. Using default limit of ${constants_1.TypeORMQueryLimit}`);
|
|
112
|
+
q.query = q.query.limit(constants_1.TypeORMQueryLimit);
|
|
113
|
+
}
|
|
114
|
+
// Add offset
|
|
115
|
+
if (this.offsetSelector)
|
|
116
|
+
q.query = q.query.skip(this.offsetSelector);
|
|
117
|
+
return q;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* @description Creates a paginator for the statement.
|
|
121
|
+
* @summary Builds the query and returns a TypeORMPaginator for paginated results.
|
|
122
|
+
* @template R The result type.
|
|
123
|
+
* @param {number} size The page size.
|
|
124
|
+
* @return {Promise<Paginator<M, R, TypeORMQuery>>} A promise that resolves to a paginator.
|
|
125
|
+
* @throws {InternalError} If there's an error building the query.
|
|
126
|
+
*/
|
|
127
|
+
async paginate(size) {
|
|
128
|
+
try {
|
|
129
|
+
const query = this.build();
|
|
130
|
+
const transformedQuery = {};
|
|
131
|
+
const a = query.query;
|
|
132
|
+
if (this.whereCondition)
|
|
133
|
+
transformedQuery.where = this.parseConditionForPagination(this.whereCondition, core_1.Repository.table(this.fromSelector));
|
|
134
|
+
if (this.orderBySelector)
|
|
135
|
+
transformedQuery.order = {
|
|
136
|
+
[this.orderBySelector[0]]: this.orderBySelector[1].toString(),
|
|
137
|
+
};
|
|
138
|
+
return new Paginator_1.TypeORMPaginator(this.adapter, transformedQuery, size, this.fromSelector);
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
throw new db_decorators_1.InternalError(e);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* @description Processes a record.
|
|
146
|
+
* @summary Converts a raw result row to a model instance using the adapter.
|
|
147
|
+
* @param {any} r The raw record.
|
|
148
|
+
* @param {keyof M} pkAttr The primary key attribute of the model.
|
|
149
|
+
* @param {"Number" | "BigInt" | undefined} sequenceType The type of the sequence.
|
|
150
|
+
* @return {any} The processed record.
|
|
151
|
+
*/
|
|
152
|
+
processRecord(r, pkAttr) {
|
|
153
|
+
if (typeof r[pkAttr] !== "undefined") {
|
|
154
|
+
return this.adapter.revert(r, this.fromSelector, pkAttr, r[pkAttr]);
|
|
155
|
+
}
|
|
156
|
+
return r;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* @description Executes a raw TypeORM query builder.
|
|
160
|
+
* @summary Sends the built SelectQueryBuilder to the database via TypeORM and returns the results.
|
|
161
|
+
* @template R The result type.
|
|
162
|
+
* @param {TypeORMQuery} rawInput The query container to execute.
|
|
163
|
+
* @return {Promise<R>} A promise that resolves to the query results.
|
|
164
|
+
*/
|
|
165
|
+
async raw(rawInput) {
|
|
166
|
+
const log = this.log.for(this.raw);
|
|
167
|
+
log.debug(`Executing raw query: ${rawInput.query.getSql()}`);
|
|
168
|
+
return (await rawInput.query.getMany());
|
|
169
|
+
}
|
|
170
|
+
parseConditionForPagination(condition, tableName, counter = 0, conditionalOp) {
|
|
171
|
+
throw new db_decorators_1.InternalError("Not implemented");
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* @description Parses a condition into PostgreSQL conditions
|
|
175
|
+
* @summary Converts a Condition object into PostgreSQL condition structures
|
|
176
|
+
* @param {Condition<M>} condition - The condition to parse
|
|
177
|
+
* @param {string} [tableName] - the positional index of the arguments
|
|
178
|
+
* @return {TypeORMQuery} The PostgresSQL condition
|
|
179
|
+
* @mermaid
|
|
180
|
+
* sequenceDiagram
|
|
181
|
+
* participant Statement
|
|
182
|
+
* participant translateOperators
|
|
183
|
+
* participant parseCondition
|
|
184
|
+
*
|
|
185
|
+
* Statement->>Statement: parseCondition(condition)
|
|
186
|
+
*
|
|
187
|
+
* Note over Statement: Extract condition parts
|
|
188
|
+
*
|
|
189
|
+
* alt Simple comparison operator
|
|
190
|
+
* Statement->>translateOperators: translateOperators(operator)
|
|
191
|
+
* translateOperators-->>Statement: Return PostgreSQL operator
|
|
192
|
+
* Statement->>Statement: Create condition with column, operator, and value
|
|
193
|
+
* else NOT operator
|
|
194
|
+
* Statement->>Statement: parseCondition(attr1)
|
|
195
|
+
* Statement->>Statement: Add NOT to conditions
|
|
196
|
+
* else AND/OR operator
|
|
197
|
+
* Statement->>Statement: parseCondition(attr1)
|
|
198
|
+
* Statement->>Statement: parseCondition(comparison)
|
|
199
|
+
* Statement->>Statement: Combine conditions with AND/OR
|
|
200
|
+
* end
|
|
201
|
+
*
|
|
202
|
+
* Statement-->>Statement: Return conditions array
|
|
203
|
+
*/
|
|
204
|
+
parseCondition(condition, tableName, qb, counter = 0, conditionalOp) {
|
|
205
|
+
const { attr1, operator, comparison } = condition;
|
|
206
|
+
function parse() {
|
|
207
|
+
const sqlOperator = (0, translate_1.translateOperators)(operator);
|
|
208
|
+
const attrRef = `${attr1}${counter}`;
|
|
209
|
+
const queryStr = `${tableName}.${attr1} ${sqlOperator} :${attrRef}`;
|
|
210
|
+
const values = {
|
|
211
|
+
[attrRef]: comparison,
|
|
212
|
+
};
|
|
213
|
+
switch (conditionalOp) {
|
|
214
|
+
case core_1.GroupOperator.AND:
|
|
215
|
+
return {
|
|
216
|
+
query: qb.andWhere(queryStr, values),
|
|
217
|
+
};
|
|
218
|
+
case core_1.GroupOperator.OR:
|
|
219
|
+
return {
|
|
220
|
+
query: qb.orWhere(queryStr, values),
|
|
221
|
+
};
|
|
222
|
+
case core_1.Operator.NOT:
|
|
223
|
+
throw new Error("NOT operator not implemented");
|
|
224
|
+
default:
|
|
225
|
+
return {
|
|
226
|
+
query: qb.where(queryStr, values),
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if ([core_1.GroupOperator.AND, core_1.GroupOperator.OR, core_1.Operator.NOT].indexOf(operator) === -1) {
|
|
231
|
+
return parse();
|
|
232
|
+
}
|
|
233
|
+
// For NOT operator
|
|
234
|
+
else if (operator === core_1.Operator.NOT) {
|
|
235
|
+
throw new Error("NOT operator not implemented");
|
|
236
|
+
}
|
|
237
|
+
// For AND/OR operators
|
|
238
|
+
else {
|
|
239
|
+
qb = this.parseCondition(attr1, tableName, qb, ++counter)
|
|
240
|
+
.query;
|
|
241
|
+
return this.parseCondition(comparison, tableName, qb, ++counter, operator);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
exports.TypeORMStatement = TypeORMStatement;
|
|
246
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3RhdGVtZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3F1ZXJ5L1N0YXRlbWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5Q0FRd0I7QUFDeEIseUVBQWtFO0FBQ2xFLCtDQUFpRDtBQUNqRCwrQ0FBZ0Q7QUFDaEQsK0NBQStDO0FBQy9DLDJEQUF3RTtBQU94RTs7Ozs7Ozs7Ozs7Ozs7OztHQWdCRztBQUNILE1BQWEsZ0JBQXFDLFNBQVEsZ0JBSXpEO0lBR0MsWUFBWSxPQUF1QjtRQUNqQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDakIsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O09BMkNHO0lBQ08sS0FBSztRQUNiLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNyQyxNQUFNLFNBQVMsR0FBRyxpQkFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDdEQsTUFBTSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFFbEMsTUFBTSxDQUFDLEdBQTJDO1lBQ2hELEtBQUssRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVU7aUJBQzNCLGFBQWEsQ0FDWixJQUFJLENBQUMsWUFBWSxDQUFDLGdDQUFTLENBQUMsTUFBd0MsQ0FBQyxDQUN0RTtpQkFDQSxrQkFBa0IsQ0FBQyxTQUFTLENBQTBCO1NBQzFELENBQUM7UUFFRixJQUFJLElBQUksQ0FBQyxjQUFjO1lBQ3JCLENBQUMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQ3RCLElBQUksQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLFNBQVMsSUFBSSxDQUFXLEVBQUUsQ0FB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SSxDQUFDLGNBQWMsQ0FBQyxLQUFxQixFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsRUFBRSxPQUFPLENBQUM7aUJBQ3RFLEtBQXlDLENBQUM7WUFDN0MsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUN4QixVQUFVLEVBQ1YsU0FBUyxFQUNULEVBQUUsRUFDRixFQUFFLE9BQU8sRUFDVCxRQUFRLENBQ1QsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUE1UkQsNENBNFJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29uZGl0aW9uLFxuICBHcm91cE9wZXJhdG9yLFxuICBPcGVyYXRvcixcbiAgT3JkZXJEaXJlY3Rpb24sXG4gIFBhZ2luYXRvcixcbiAgUmVwb3NpdG9yeSxcbiAgU3RhdGVtZW50LFxufSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IE1vZGVsLCBNb2RlbEtleXMgfSBmcm9tIFwiQGRlY2FmLXRzL2RlY29yYXRvci12YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyB0cmFuc2xhdGVPcGVyYXRvcnMgfSBmcm9tIFwiLi90cmFuc2xhdGVcIjtcbmltcG9ydCB7IFR5cGVPUk1RdWVyeUxpbWl0IH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBUeXBlT1JNUGFnaW5hdG9yIH0gZnJvbSBcIi4vUGFnaW5hdG9yXCI7XG5pbXBvcnQgeyBmaW5kUHJpbWFyeUtleSwgSW50ZXJuYWxFcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgVHlwZU9STVF1ZXJ5IH0gZnJvbSBcIi4uL3R5cGVzXCI7XG5pbXBvcnQgeyBUeXBlT1JNQWRhcHRlciB9IGZyb20gXCIuLi9UeXBlT1JNQWRhcHRlclwiO1xuaW1wb3J0IHsgRmluZE1hbnlPcHRpb25zLCBTZWxlY3RRdWVyeUJ1aWxkZXIgfSBmcm9tIFwidHlwZW9ybVwiO1xuaW1wb3J0IHsgRmluZE9wdGlvbnNXaGVyZSB9IGZyb20gXCJ0eXBlb3JtL2ZpbmQtb3B0aW9ucy9GaW5kT3B0aW9uc1doZXJlXCI7XG5pbXBvcnQgeyBGaW5kT3B0aW9uc09yZGVyIH0gZnJvbSBcInR5cGVvcm0vZmluZC1vcHRpb25zL0ZpbmRPcHRpb25zT3JkZXJcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gU3RhdGVtZW50IGJ1aWxkZXIgZm9yIFR5cGVPUk0tYmFja2VkIHF1ZXJpZXMuXG4gKiBAc3VtbWFyeSBQcm92aWRlcyBhIGZsdWVudCBpbnRlcmZhY2UgZm9yIGJ1aWxkaW5nIFNRTCBxdWVyaWVzIHZpYSBUeXBlT1JNJ3MgU2VsZWN0UXVlcnlCdWlsZGVyIHdpdGggdHlwZSBzYWZldHkgYW5kIERlY2FmLnRzIGFic3RyYWN0aW9ucy5cbiAqIEB0ZW1wbGF0ZSBNIFRoZSBtb2RlbCB0eXBlIHRoYXQgZXh0ZW5kcyBNb2RlbC5cbiAqIEB0ZW1wbGF0ZSBSIFRoZSByZXN1bHQgdHlwZSByZXR1cm5lZCBmcm9tIGV4ZWN1dGlvbi5cbiAqIEBwYXJhbSB7VHlwZU9STUFkYXB0ZXJ9IGFkYXB0ZXIgVGhlIFR5cGVPUk0gYWRhcHRlci5cbiAqIEBjbGFzcyBUeXBlT1JNU3RhdGVtZW50XG4gKiBAZXhhbXBsZVxuICogLy8gRXhhbXBsZSB1c2luZyBUeXBlT1JNU3RhdGVtZW50XG4gKiBjb25zdCBzdGF0ZW1lbnQgPSBuZXcgVHlwZU9STVN0YXRlbWVudDxVc2VyLCBVc2VyW10+KGFkYXB0ZXIpO1xuICogY29uc3QgdXNlcnMgPSBhd2FpdCBzdGF0ZW1lbnRcbiAqICAgLmZyb20oVXNlcilcbiAqICAgLndoZXJlKENvbmRpdGlvbi5hdHRyaWJ1dGU8VXNlcj4oJ2FnZScpLmd0KDE4KSlcbiAqICAgLm9yZGVyQnkoJ2xhc3ROYW1lJywgJ2FzYycpXG4gKiAgIC5saW1pdCgxMClcbiAqICAgLmV4ZWN1dGUoKTtcbiAqL1xuZXhwb3J0IGNsYXNzIFR5cGVPUk1TdGF0ZW1lbnQ8TSBleHRlbmRzIE1vZGVsLCBSPiBleHRlbmRzIFN0YXRlbWVudDxcbiAgVHlwZU9STVF1ZXJ5PE0+LFxuICBNLFxuICBSXG4+IHtcbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGFkYXB0ZXIhOiBUeXBlT1JNQWRhcHRlcjtcblxuICBjb25zdHJ1Y3RvcihhZGFwdGVyOiBUeXBlT1JNQWRhcHRlcikge1xuICAgIHN1cGVyKGFkYXB0ZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBCdWlsZHMgYSBUeXBlT1JNIFNlbGVjdFF1ZXJ5QnVpbGRlciBmcm9tIHRoZSBzdGF0ZW1lbnQuXG4gICAqIEBzdW1tYXJ5IENvbnZlcnRzIHRoZSBzdGF0ZW1lbnQncyBjb25kaXRpb25zLCBzZWxlY3RvcnMsIGFuZCBvcHRpb25zIGludG8gYSBUeXBlT1JNLWJhY2tlZCBxdWVyeSBvYmplY3QuXG4gICAqIEByZXR1cm4ge1R5cGVPUk1RdWVyeX0gVGhlIGJ1aWx0IFR5cGVPUk0gcXVlcnkgY29udGFpbmVyLlxuICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlcmUgYXJlIGludmFsaWQgcXVlcnkgY29uZGl0aW9ucy5cbiAgICogQG1lcm1haWRcbiAgICogc2VxdWVuY2VEaWFncmFtXG4gICAqICAgcGFydGljaXBhbnQgU3RhdGVtZW50XG4gICAqICAgcGFydGljaXBhbnQgUmVwb3NpdG9yeVxuICAgKiAgIHBhcnRpY2lwYW50IHBhcnNlQ29uZGl0aW9uXG4gICAqXG4gICAqICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBidWlsZCgpXG4gICAqICAgTm90ZSBvdmVyIFN0YXRlbWVudDogSW5pdGlhbGl6ZSBxdWVyeVxuICAgKiAgIFN0YXRlbWVudC0+PlJlcG9zaXRvcnk6IEdldCB0YWJsZSBuYW1lXG4gICAqICAgUmVwb3NpdG9yeS0tPj5TdGF0ZW1lbnQ6IFJldHVybiB0YWJsZSBuYW1lXG4gICAqICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBDcmVhdGUgYmFzZSBxdWVyeVxuICAgKlxuICAgKiAgIGFsdCBIYXMgc2VsZWN0U2VsZWN0b3JcbiAgICogICAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogQWRkIGNvbHVtbnMgdG8gcXVlcnlcbiAgICogICBlbmRcbiAgICpcbiAgICogICBhbHQgSGFzIHdoZXJlQ29uZGl0aW9uXG4gICAqICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IENyZWF0ZSBjb21iaW5lZCBjb25kaXRpb24gd2l0aCB0YWJsZVxuICAgKiAgICAgU3RhdGVtZW50LT4+cGFyc2VDb25kaXRpb246IFBhcnNlIGNvbmRpdGlvblxuICAgKiAgICAgcGFyc2VDb25kaXRpb24tLT4+U3RhdGVtZW50OiBSZXR1cm4gcGFyc2VkIGNvbmRpdGlvbnNcbiAgICogICAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogQWRkIGNvbmRpdGlvbnMgdG8gcXVlcnlcbiAgICogICBlbmRcbiAgICpcbiAgICogICBhbHQgSGFzIG9yZGVyQnlTZWxlY3RvclxuICAgKiAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBBZGQgb3JkZXJCeSB0byBxdWVyeVxuICAgKiAgIGVuZFxuICAgKlxuICAgKiAgIGFsdCBIYXMgbGltaXRTZWxlY3RvclxuICAgKiAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBTZXQgbGltaXRcbiAgICogICBlbHNlXG4gICAqICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IFVzZSBkZWZhdWx0IGxpbWl0XG4gICAqICAgZW5kXG4gICAqXG4gICAqICAgYWx0IEhhcyBvZmZzZXRTZWxlY3RvclxuICAgKiAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBTZXQgb2Zmc2V0XG4gICAqICAgZW5kXG4gICAqXG4gICAqICAgU3RhdGVtZW50LS0+PlN0YXRlbWVudDogUmV0dXJuIHF1ZXJ5XG4gICAqL1xuICBwcm90ZWN0ZWQgYnVpbGQoKTogVHlwZU9STVF1ZXJ5PE0+IHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5idWlsZCk7XG4gICAgY29uc3QgdGFibGVOYW1lID0gUmVwb3NpdG9yeS50YWJsZSh0aGlzLmZyb21TZWxlY3Rvcik7XG4gICAgY29uc3QgbSA9IG5ldyB0aGlzLmZyb21TZWxlY3RvcigpO1xuXG4gICAgY29uc3QgcTogVHlwZU9STVF1ZXJ5PE0sIFNlbGVjdFF1ZXJ5QnVpbGRlcjxNPj4gPSB7XG4gICAgICBxdWVyeTogdGhpcy5hZGFwdGVyLmRhdGFTb3VyY2VcbiAgICAgICAgLmdldFJlcG9zaXRvcnkoXG4gICAgICAgICAgdGhpcy5mcm9tU2VsZWN0b3JbTW9kZWxLZXlzLkFOQ0hPUiBhcyBrZXlvZiB0eXBlb2YgdGhpcy5mcm9tU2VsZWN0b3JdXG4gICAgICAgIClcbiAgICAgICAgLmNyZWF0ZVF1ZXJ5QnVpbGRlcih0YWJsZU5hbWUpIGFzIFNlbGVjdFF1ZXJ5QnVpbGRlcjxNPixcbiAgICB9O1xuXG4gICAgaWYgKHRoaXMuc2VsZWN0U2VsZWN0b3IpXG4gICAgICBxLnF1ZXJ5ID0gcS5xdWVyeS5zZWxlY3QoXG4gICAgICAgIHRoaXMuc2VsZWN0U2VsZWN0b3IubWFwKChzKSA9PiBgJHt0YWJsZU5hbWV9LiR7cyBhcyBzdHJpbmd9YClcbiAgICAgICk7XG4gICAgZWxzZSBxLnF1ZXJ5ID0gcS5xdWVyeS5zZWxlY3QoKTtcbiAgICAvL1xuICAgIC8vIHEucXVlcnkgPSAocS5xdWVyeSBhcyBTZWxlY3RRdWVyeUJ1aWxkZXI8YW55PikuZnJvbShcbiAgICAvLyAgIHRoaXMuZnJvbVNlbGVjdG9yW01vZGVsS2V5cy5BTkNIT1IgYXMga2V5b2YgdHlwZW9mIHRoaXMuZnJvbVNlbGVjdG9yXSxcbiAgICAvLyAgIHRhYmxlTmFtZVxuICAgIC8vICk7XG5cbiAgICBpZiAodGhpcy53aGVyZUNvbmRpdGlvbilcbiAgICAgIHEucXVlcnkgPSB0aGlzLnBhcnNlQ29uZGl0aW9uKFxuICAgICAgICB0aGlzLndoZXJlQ29uZGl0aW9uLFxuICAgICAgICB0YWJsZU5hbWUsXG4gICAgICAgIHEucXVlcnkgYXMgU2VsZWN0UXVlcnlCdWlsZGVyPGFueT5cbiAgICAgICkucXVlcnkgYXMgdW5rbm93biBhcyBTZWxlY3RRdWVyeUJ1aWxkZXI8TT47XG5cbiAgICBsZXQgb3JkZXJCeUFyZ3M6IFtzdHJpbmcsIFwiREVTQ1wiIHwgXCJBU0NcIl07XG4gICAgaWYgKCF0aGlzLm9yZGVyQnlTZWxlY3RvcilcbiAgICAgIG9yZGVyQnlBcmdzID0gW1xuICAgICAgICBgJHt0YWJsZU5hbWV9LiR7ZmluZFByaW1hcnlLZXkobSkuaWQgYXMgc3RyaW5nfWAsXG4gICAgICAgIE9yZGVyRGlyZWN0aW9uLkFTQy50b1VwcGVyQ2FzZSgpIGFzIFwiQVNDXCIsXG4gICAgICBdO1xuICAgIGVsc2VcbiAgICAgIG9yZGVyQnlBcmdzID0gW1xuICAgICAgICBgJHt0YWJsZU5hbWV9LiR7dGhpcy5vcmRlckJ5U2VsZWN0b3JbMF0gYXMgc3RyaW5nfWAsXG4gICAgICAgIHRoaXMub3JkZXJCeVNlbGVjdG9yWzFdLnRvVXBwZXJDYXNlKCkgYXMgXCJERVNDXCIgfCBcIkFTQ1wiLFxuICAgICAgXTtcblxuICAgIHEucXVlcnkgPSAocS5xdWVyeSBhcyBTZWxlY3RRdWVyeUJ1aWxkZXI8YW55Pikub3JkZXJCeSguLi5vcmRlckJ5QXJncyk7XG4gICAgaWYgKHRoaXMubGltaXRTZWxlY3Rvcikge1xuICAgICAgcS5xdWVyeSA9IChxLnF1ZXJ5IGFzIFNlbGVjdFF1ZXJ5QnVpbGRlcjxhbnk+KS5saW1pdCh0aGlzLmxpbWl0U2VsZWN0b3IpO1xuICAgIH0gZWxzZSB7XG4gICAgICBsb2cuZGVidWcoXG4gICAgICAgIGBObyBsaW1pdCBzZWxlY3RvciBkZWZpbmVkLiBVc2luZyBkZWZhdWx0IGxpbWl0IG9mICR7VHlwZU9STVF1ZXJ5TGltaXR9YFxuICAgICAgKTtcbiAgICAgIHEucXVlcnkgPSAocS5xdWVyeSBhcyBTZWxlY3RRdWVyeUJ1aWxkZXI8YW55PikubGltaXQoVHlwZU9STVF1ZXJ5TGltaXQpO1xuICAgIH1cblxuICAgIC8vIEFkZCBvZmZzZXRcbiAgICBpZiAodGhpcy5vZmZzZXRTZWxlY3RvcilcbiAgICAgIHEucXVlcnkgPSAocS5xdWVyeSBhcyBTZWxlY3RRdWVyeUJ1aWxkZXI8YW55Pikuc2tpcCh0aGlzLm9mZnNldFNlbGVjdG9yKTtcblxuICAgIHJldHVybiBxIGFzIGFueTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAZGVzY3JpcHRpb24gQ3JlYXRlcyBhIHBhZ2luYXRvciBmb3IgdGhlIHN0YXRlbWVudC5cbiAgICogQHN1bW1hcnkgQnVpbGRzIHRoZSBxdWVyeSBhbmQgcmV0dXJucyBhIFR5cGVPUk1QYWdpbmF0b3IgZm9yIHBhZ2luYXRlZCByZXN1bHRzLlxuICAgKiBAdGVtcGxhdGUgUiBUaGUgcmVzdWx0IHR5cGUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIFRoZSBwYWdlIHNpemUuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8UGFnaW5hdG9yPE0sIFIsIFR5cGVPUk1RdWVyeT4+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBhIHBhZ2luYXRvci5cbiAgICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gSWYgdGhlcmUncyBhbiBlcnJvciBidWlsZGluZyB0aGUgcXVlcnkuXG4gICAqL1xuICBhc3luYyBwYWdpbmF0ZTxSPihzaXplOiBudW1iZXIpOiBQcm9taXNlPFBhZ2luYXRvcjxNLCBSLCBUeXBlT1JNUXVlcnk+PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHF1ZXJ5OiBUeXBlT1JNUXVlcnkgPSB0aGlzLmJ1aWxkKCk7XG4gICAgICBjb25zdCB0cmFuc2Zvcm1lZFF1ZXJ5OiBGaW5kTWFueU9wdGlvbnM8TT4gPSB7fTtcbiAgICAgIGNvbnN0IGEgPSBxdWVyeS5xdWVyeSBhcyB1bmtub3duIGFzIFNlbGVjdFF1ZXJ5QnVpbGRlcjxNPjtcbiAgICAgIGlmICh0aGlzLndoZXJlQ29uZGl0aW9uKVxuICAgICAgICB0cmFuc2Zvcm1lZFF1ZXJ5LndoZXJlID0gdGhpcy5wYXJzZUNvbmRpdGlvbkZvclBhZ2luYXRpb24oXG4gICAgICAgICAgdGhpcy53aGVyZUNvbmRpdGlvbixcbiAgICAgICAgICBSZXBvc2l0b3J5LnRhYmxlKHRoaXMuZnJvbVNlbGVjdG9yKVxuICAgICAgICApO1xuXG4gICAgICBpZiAodGhpcy5vcmRlckJ5U2VsZWN0b3IpXG4gICAgICAgIHRyYW5zZm9ybWVkUXVlcnkub3JkZXIgPSB7XG4gICAgICAgICAgW3RoaXMub3JkZXJCeVNlbGVjdG9yWzBdXTogdGhpcy5vcmRlckJ5U2VsZWN0b3JbMV0udG9TdHJpbmcoKSxcbiAgICAgICAgfSBhcyBhbnk7XG5cbiAgICAgIHJldHVybiBuZXcgVHlwZU9STVBhZ2luYXRvcihcbiAgICAgICAgdGhpcy5hZGFwdGVyIGFzIGFueSxcbiAgICAgICAgdHJhbnNmb3JtZWRRdWVyeSBhcyBhbnksXG4gICAgICAgIHNpemUsXG4gICAgICAgIHRoaXMuZnJvbVNlbGVjdG9yXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQcm9jZXNzZXMgYSByZWNvcmQuXG4gICAqIEBzdW1tYXJ5IENvbnZlcnRzIGEgcmF3IHJlc3VsdCByb3cgdG8gYSBtb2RlbCBpbnN0YW5jZSB1c2luZyB0aGUgYWRhcHRlci5cbiAgICogQHBhcmFtIHthbnl9IHIgVGhlIHJhdyByZWNvcmQuXG4gICAqIEBwYXJhbSB7a2V5b2YgTX0gcGtBdHRyIFRoZSBwcmltYXJ5IGtleSBhdHRyaWJ1dGUgb2YgdGhlIG1vZGVsLlxuICAgKiBAcGFyYW0ge1wiTnVtYmVyXCIgfCBcIkJpZ0ludFwiIHwgdW5kZWZpbmVkfSBzZXF1ZW5jZVR5cGUgVGhlIHR5cGUgb2YgdGhlIHNlcXVlbmNlLlxuICAgKiBAcmV0dXJuIHthbnl9IFRoZSBwcm9jZXNzZWQgcmVjb3JkLlxuICAgKi9cbiAgcHJpdmF0ZSBwcm9jZXNzUmVjb3JkKHI6IGFueSwgcGtBdHRyOiBrZXlvZiBNKSB7XG4gICAgaWYgKHR5cGVvZiByW3BrQXR0cl0gIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KHIsIHRoaXMuZnJvbVNlbGVjdG9yLCBwa0F0dHIsIHJbcGtBdHRyXSk7XG4gICAgfVxuICAgIHJldHVybiByO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBFeGVjdXRlcyBhIHJhdyBUeXBlT1JNIHF1ZXJ5IGJ1aWxkZXIuXG4gICAqIEBzdW1tYXJ5IFNlbmRzIHRoZSBidWlsdCBTZWxlY3RRdWVyeUJ1aWxkZXIgdG8gdGhlIGRhdGFiYXNlIHZpYSBUeXBlT1JNIGFuZCByZXR1cm5zIHRoZSByZXN1bHRzLlxuICAgKiBAdGVtcGxhdGUgUiBUaGUgcmVzdWx0IHR5cGUuXG4gICAqIEBwYXJhbSB7VHlwZU9STVF1ZXJ5fSByYXdJbnB1dCBUaGUgcXVlcnkgY29udGFpbmVyIHRvIGV4ZWN1dGUuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8Uj59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBxdWVyeSByZXN1bHRzLlxuICAgKi9cbiAgb3ZlcnJpZGUgYXN5bmMgcmF3PFI+KHJhd0lucHV0OiBUeXBlT1JNUXVlcnk8TT4pOiBQcm9taXNlPFI+IHtcbiAgICBjb25zdCBsb2cgPSB0aGlzLmxvZy5mb3IodGhpcy5yYXcpO1xuICAgIGxvZy5kZWJ1ZyhcbiAgICAgIGBFeGVjdXRpbmcgcmF3IHF1ZXJ5OiAkeyhyYXdJbnB1dC5xdWVyeSBhcyB1bmtub3duIGFzIFNlbGVjdFF1ZXJ5QnVpbGRlcjxNPikuZ2V0U3FsKCl9YFxuICAgICk7XG4gICAgcmV0dXJuIChhd2FpdCAoXG4gICAgICByYXdJbnB1dC5xdWVyeSBhcyB1bmtub3duIGFzIFNlbGVjdFF1ZXJ5QnVpbGRlcjxNPlxuICAgICkuZ2V0TWFueSgpKSBhcyBSO1xuICB9XG5cbiAgcHJvdGVjdGVkIHBhcnNlQ29uZGl0aW9uRm9yUGFnaW5hdGlvbihcbiAgICBjb25kaXRpb246IENvbmRpdGlvbjxNPixcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgICBjb3VudGVyID0gMCxcbiAgICBjb25kaXRpb25hbE9wPzogR3JvdXBPcGVyYXRvciB8IE9wZXJhdG9yXG4gICk6IEZpbmRPcHRpb25zV2hlcmU8TT5bXSB8IEZpbmRPcHRpb25zV2hlcmU8TT4ge1xuICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiTm90IGltcGxlbWVudGVkXCIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXNjcmlwdGlvbiBQYXJzZXMgYSBjb25kaXRpb24gaW50byBQb3N0Z3JlU1FMIGNvbmRpdGlvbnNcbiAgICogQHN1bW1hcnkgQ29udmVydHMgYSBDb25kaXRpb24gb2JqZWN0IGludG8gUG9zdGdyZVNRTCBjb25kaXRpb24gc3RydWN0dXJlc1xuICAgKiBAcGFyYW0ge0NvbmRpdGlvbjxNPn0gY29uZGl0aW9uIC0gVGhlIGNvbmRpdGlvbiB0byBwYXJzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW3RhYmxlTmFtZV0gLSB0aGUgcG9zaXRpb25hbCBpbmRleCBvZiB0aGUgYXJndW1lbnRzXG4gICAqIEByZXR1cm4ge1R5cGVPUk1RdWVyeX0gVGhlIFBvc3RncmVzU1FMIGNvbmRpdGlvblxuICAgKiBAbWVybWFpZFxuICAgKiBzZXF1ZW5jZURpYWdyYW1cbiAgICogICBwYXJ0aWNpcGFudCBTdGF0ZW1lbnRcbiAgICogICBwYXJ0aWNpcGFudCB0cmFuc2xhdGVPcGVyYXRvcnNcbiAgICogICBwYXJ0aWNpcGFudCBwYXJzZUNvbmRpdGlvblxuICAgKlxuICAgKiAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogcGFyc2VDb25kaXRpb24oY29uZGl0aW9uKVxuICAgKlxuICAgKiAgIE5vdGUgb3ZlciBTdGF0ZW1lbnQ6IEV4dHJhY3QgY29uZGl0aW9uIHBhcnRzXG4gICAqXG4gICAqICAgYWx0IFNpbXBsZSBjb21wYXJpc29uIG9wZXJhdG9yXG4gICAqICAgICBTdGF0ZW1lbnQtPj50cmFuc2xhdGVPcGVyYXRvcnM6IHRyYW5zbGF0ZU9wZXJhdG9ycyhvcGVyYXRvcilcbiAgICogICAgIHRyYW5zbGF0ZU9wZXJhdG9ycy0tPj5TdGF0ZW1lbnQ6IFJldHVybiBQb3N0Z3JlU1FMIG9wZXJhdG9yXG4gICAqICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IENyZWF0ZSBjb25kaXRpb24gd2l0aCBjb2x1bW4sIG9wZXJhdG9yLCBhbmQgdmFsdWVcbiAgICogICBlbHNlIE5PVCBvcGVyYXRvclxuICAgKiAgICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBwYXJzZUNvbmRpdGlvbihhdHRyMSlcbiAgICogICAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogQWRkIE5PVCB0byBjb25kaXRpb25zXG4gICAqICAgZWxzZSBBTkQvT1Igb3BlcmF0b3JcbiAgICogICAgIFN0YXRlbWVudC0+PlN0YXRlbWVudDogcGFyc2VDb25kaXRpb24oYXR0cjEpXG4gICAqICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IHBhcnNlQ29uZGl0aW9uKGNvbXBhcmlzb24pXG4gICAqICAgICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IENvbWJpbmUgY29uZGl0aW9ucyB3aXRoIEFORC9PUlxuICAgKiAgIGVuZFxuICAgKlxuICAgKiAgIFN0YXRlbWVudC0tPj5TdGF0ZW1lbnQ6IFJldHVybiBjb25kaXRpb25zIGFycmF5XG4gICAqL1xuICBwcm90ZWN0ZWQgcGFyc2VDb25kaXRpb24oXG4gICAgY29uZGl0aW9uOiBDb25kaXRpb248TT4sXG4gICAgdGFibGVOYW1lOiBzdHJpbmcsXG4gICAgcWI6IFNlbGVjdFF1ZXJ5QnVpbGRlcjxhbnk+LFxuICAgIGNvdW50ZXIgPSAwLFxuICAgIGNvbmRpdGlvbmFsT3A/OiBHcm91cE9wZXJhdG9yIHwgT3BlcmF0b3JcbiAgKTogVHlwZU9STVF1ZXJ5PE0+IHtcbiAgICBjb25zdCB7IGF0dHIxLCBvcGVyYXRvciwgY29tcGFyaXNvbiB9ID0gY29uZGl0aW9uIGFzIHVua25vd24gYXMge1xuICAgICAgYXR0cjE6IHN0cmluZyB8IENvbmRpdGlvbjxNPjtcbiAgICAgIG9wZXJhdG9yOiBPcGVyYXRvciB8IEdyb3VwT3BlcmF0b3I7XG4gICAgICBjb21wYXJpc29uOiBhbnk7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIHBhcnNlKCk6IFR5cGVPUk1RdWVyeTxNPiB7XG4gICAgICBjb25zdCBzcWxPcGVyYXRvciA9IHRyYW5zbGF0ZU9wZXJhdG9ycyhvcGVyYXRvcik7XG4gICAgICBjb25zdCBhdHRyUmVmID0gYCR7YXR0cjF9JHtjb3VudGVyfWA7XG4gICAgICBjb25zdCBxdWVyeVN0ciA9IGAke3RhYmxlTmFtZX0uJHthdHRyMX0gJHtzcWxPcGVyYXRvcn0gOiR7YXR0clJlZn1gO1xuICAgICAgY29uc3QgdmFsdWVzID0ge1xuICAgICAgICBbYXR0clJlZl06IGNvbXBhcmlzb24sXG4gICAgICB9O1xuICAgICAgc3dpdGNoIChjb25kaXRpb25hbE9wKSB7XG4gICAgICAgIGNhc2UgR3JvdXBPcGVyYXRvci5BTkQ6XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHF1ZXJ5OiBxYi5hbmRXaGVyZShxdWVyeVN0ciwgdmFsdWVzKSBhcyBhbnksXG4gICAgICAgICAgfTtcbiAgICAgICAgY2FzZSBHcm91cE9wZXJhdG9yLk9SOlxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBxdWVyeTogcWIub3JXaGVyZShxdWVyeVN0ciwgdmFsdWVzKSBhcyBhbnksXG4gICAgICAgICAgfTtcbiAgICAgICAgY2FzZSBPcGVyYXRvci5OT1Q6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTk9UIG9wZXJhdG9yIG5vdCBpbXBsZW1lbnRlZFwiKTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgcXVlcnk6IHFiLndoZXJlKHF1ZXJ5U3RyLCB2YWx1ZXMpIGFzIGFueSxcbiAgICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChcbiAgICAgIFtHcm91cE9wZXJhdG9yLkFORCwgR3JvdXBPcGVyYXRvci5PUiwgT3BlcmF0b3IuTk9UXS5pbmRleE9mKFxuICAgICAgICBvcGVyYXRvciBhcyBHcm91cE9wZXJhdG9yXG4gICAgICApID09PSAtMVxuICAgICkge1xuICAgICAgcmV0dXJuIHBhcnNlKCk7XG4gICAgfVxuICAgIC8vIEZvciBOT1Qgb3BlcmF0b3JcbiAgICBlbHNlIGlmIChvcGVyYXRvciA9PT0gT3BlcmF0b3IuTk9UKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOT1Qgb3BlcmF0b3Igbm90IGltcGxlbWVudGVkXCIpO1xuICAgIH1cbiAgICAvLyBGb3IgQU5EL09SIG9wZXJhdG9yc1xuICAgIGVsc2Uge1xuICAgICAgcWIgPSB0aGlzLnBhcnNlQ29uZGl0aW9uKGF0dHIxIGFzIENvbmRpdGlvbjxNPiwgdGFibGVOYW1lLCBxYiwgKytjb3VudGVyKVxuICAgICAgICAucXVlcnkgYXMgdW5rbm93biBhcyBTZWxlY3RRdWVyeUJ1aWxkZXI8TT47XG4gICAgICByZXR1cm4gdGhpcy5wYXJzZUNvbmRpdGlvbihcbiAgICAgICAgY29tcGFyaXNvbixcbiAgICAgICAgdGFibGVOYW1lLFxuICAgICAgICBxYixcbiAgICAgICAgKytjb3VudGVyLFxuICAgICAgICBvcGVyYXRvclxuICAgICAgKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==
|