@decaf-ts/core
Version:
Core persistence module for the decaf framework
215 lines • 20.6 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var _a, _b, _c, _d;
import { Model } from "@decaf-ts/decorator-validation";
import { Condition } from "./Condition.js";
import { findPrimaryKey, InternalError } from "@decaf-ts/db-decorators";
import { final } from "./../utils/decorators.js";
import { QueryError } from "./errors.js";
/**
* @description Base class for database query statements
* @summary Provides a foundation for building and executing database queries
*
* This abstract class implements the query builder pattern for constructing
* database queries. It supports various query operations like select, from,
* where, orderBy, groupBy, limit, and offset. It also provides methods for
* executing queries and handling pagination.
*
* @template Q - The query type specific to the database adapter
* @template M - The model type this statement operates on
* @template R - The return type of the query
* @param {Adapter<any, Q, any, any>} adapter - The database adapter to use for executing queries
* @class Statement
* @example
* // Create a statement to query users
* const statement = new SQLStatement(adapter);
* const users = await statement
* .select()
* .from(User)
* .where(Condition.attribute("status").eq("active"))
* .orderBy(["createdAt", "DESC"])
* .limit(10)
* .execute();
*
* // Use pagination
* const paginator = await statement
* .select()
* .from(User)
* .paginate(20); // 20 users per page
*
* @mermaid
* sequenceDiagram
* participant Client
* participant Statement
* participant Adapter
* participant Database
*
* Client->>Statement: select()
* Client->>Statement: from(Model)
* Client->>Statement: where(condition)
* Client->>Statement: orderBy([field, direction])
* Client->>Statement: limit(value)
* Client->>Statement: execute()
* Statement->>Statement: build()
* Statement->>Adapter: raw(query)
* Adapter->>Database: execute query
* Database-->>Adapter: return results
* Adapter-->>Statement: return processed results
* Statement-->>Client: return final results
*/
export class Statement {
constructor(adapter) {
this.adapter = adapter;
}
select(selector) {
Object.defineProperty(this, "selectSelector", {
value: selector,
writable: false,
});
return this;
}
distinct(selector) {
this.distinctSelector = selector;
return this;
}
max(selector) {
this.maxSelector = selector;
return this;
}
min(selector) {
this.minSelector = selector;
return this;
}
count(selector) {
this.countSelector = selector;
return this;
}
from(selector) {
this.fromSelector = (typeof selector === "string" ? Model.get(selector) : selector);
if (!this.fromSelector)
throw new QueryError(`Could not find selector model: ${selector}`);
return this;
}
where(condition) {
this.whereCondition = condition;
return this;
}
orderBy(selector) {
this.orderBySelector = selector;
return this;
}
groupBy(selector) {
this.groupBySelector = selector;
return this;
}
limit(value) {
this.limitSelector = value;
return this;
}
offset(value) {
this.offsetSelector = value;
return this;
}
async execute() {
try {
const query = this.build();
return (await this.raw(query));
}
catch (e) {
throw new InternalError(e);
}
}
async raw(rawInput) {
const results = await this.adapter.raw(rawInput);
if (!this.selectSelector)
return results;
const pkAttr = findPrimaryKey(new this.fromSelector()).id;
const processor = function recordProcessor(r) {
const id = r[pkAttr];
return this.adapter.revert(r, this.fromSelector, pkAttr, id);
}.bind(this);
if (Array.isArray(results))
return results.map(processor);
return processor(results);
}
}
__decorate([
final(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Array]),
__metadata("design:returntype", Object)
], Statement.prototype, "select", null);
__decorate([
final(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [typeof (_a = typeof S !== "undefined" && S) === "function" ? _a : Object]),
__metadata("design:returntype", Object)
], Statement.prototype, "distinct", null);
__decorate([
final(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [typeof (_b = typeof S !== "undefined" && S) === "function" ? _b : Object]),
__metadata("design:returntype", Object)
], Statement.prototype, "max", null);
__decorate([
final(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [typeof (_c = typeof S !== "undefined" && S) === "function" ? _c : Object]),
__metadata("design:returntype", Object)
], Statement.prototype, "min", null);
__decorate([
final(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [typeof (_d = typeof S !== "undefined" && S) === "function" ? _d : Object]),
__metadata("design:returntype", Object)
], Statement.prototype, "count", null);
__decorate([
final(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Object)
], Statement.prototype, "from", null);
__decorate([
final(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Condition]),
__metadata("design:returntype", Object)
], Statement.prototype, "where", null);
__decorate([
final(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Array]),
__metadata("design:returntype", Object)
], Statement.prototype, "orderBy", null);
__decorate([
final(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Object)
], Statement.prototype, "groupBy", null);
__decorate([
final(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number]),
__metadata("design:returntype", Object)
], Statement.prototype, "limit", null);
__decorate([
final(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number]),
__metadata("design:returntype", Object)
], Statement.prototype, "offset", null);
__decorate([
final(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], Statement.prototype, "execute", null);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3RhdGVtZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3F1ZXJ5L1N0YXRlbWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUEsT0FBTyxFQUFvQixLQUFLLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQVF6RSxPQUFPLEVBQUUsU0FBUyxFQUFFLHVCQUFvQjtBQUN4QyxPQUFPLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3hFLE9BQU8sRUFBRSxLQUFLLEVBQUUsaUNBQTRCO0FBZTVDLE9BQU8sRUFBRSxVQUFVLEVBQUUsb0JBQWlCO0FBRXRDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtERztBQUNILE1BQU0sT0FBZ0IsU0FBUztJQWU3QixZQUFnQyxPQUFrQztRQUFsQyxZQUFPLEdBQVAsT0FBTyxDQUEyQjtJQUFHLENBQUM7SUFXdEUsTUFBTSxDQUNKLFFBQTBCO1FBRTFCLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLGdCQUFnQixFQUFFO1lBQzVDLEtBQUssRUFBRSxRQUFRO1lBQ2YsUUFBUSxFQUFFLEtBQUs7U0FDaEIsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxJQUFvRSxDQUFDO0lBQzlFLENBQUM7SUFHRCxRQUFRLENBQ04sUUFBVztRQUVYLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxRQUFRLENBQUM7UUFDakMsT0FBTyxJQUFpQyxDQUFDO0lBQzNDLENBQUM7SUFHRCxHQUFHLENBQThCLFFBQVc7UUFDMUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxRQUFRLENBQUM7UUFDNUIsT0FBTyxJQUEwQixDQUFDO0lBQ3BDLENBQUM7SUFHRCxHQUFHLENBQThCLFFBQVc7UUFDMUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxRQUFRLENBQUM7UUFDNUIsT0FBTyxJQUEwQixDQUFDO0lBQ3BDLENBQUM7SUFHRCxLQUFL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QUczQztBQUdEO0lBREMsS0FBSyxFQUFFOzt5REFDc0MsQ0FBQyxvQkFBRCxDQUFDOztzQ0FHOUM7QUFHTTtJQUROLEtBQUssRUFBRTs7OztxQ0FRUDtBQUdNO0lBRE4sS0FBSyxFQUFFOztxQ0FDZ0IsU0FBUzs7c0NBR2hDO0FBR007SUFETixLQUFLLEVBQUU7Ozs7d0NBTVA7QUFHTTtJQUROLEtBQUssRUFBRTs7Ozt3Q0FJUDtBQUdNO0lBRE4sS0FBSyxFQUFFOzs7O3NDQUlQO0FBR007SUFETixLQUFLLEVBQUU7Ozs7dUNBSVA7QUFHSztJQURMLEtBQUssRUFBRTs7Ozt3Q0FRUCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IHR5cGUgQ29uc3RydWN0b3IsIE1vZGVsIH0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHR5cGUgeyBFeGVjdXRvciwgUmF3RXhlY3V0b3IgfSBmcm9tIFwiLi4vaW50ZXJmYWNlc1wiO1xuaW1wb3J0IHR5cGUge1xuICBGcm9tU2VsZWN0b3IsXG4gIEdyb3VwQnlTZWxlY3RvcixcbiAgT3JkZXJCeVNlbGVjdG9yLFxuICBTZWxlY3RTZWxlY3Rvcixcbn0gZnJvbSBcIi4vc2VsZWN0b3JzXCI7XG5pbXBvcnQgeyBDb25kaXRpb24gfSBmcm9tIFwiLi9Db25kaXRpb25cIjtcbmltcG9ydCB7IGZpbmRQcmltYXJ5S2V5LCBJbnRlcm5hbEVycm9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBmaW5hbCB9IGZyb20gXCIuLi91dGlscy9kZWNvcmF0b3JzXCI7XG5pbXBvcnQgdHlwZSB7XG4gIENvdW50T3B0aW9uLFxuICBEaXN0aW5jdE9wdGlvbixcbiAgTGltaXRPcHRpb24sXG4gIE1heE9wdGlvbixcbiAgTWluT3B0aW9uLFxuICBPZmZzZXRPcHRpb24sXG4gIE9yZGVyQW5kR3JvdXBPcHRpb24sXG4gIFNlbGVjdE9wdGlvbixcbiAgV2hlcmVPcHRpb24sXG59IGZyb20gXCIuL29wdGlvbnNcIjtcbmltcG9ydCB7IFBhZ2luYXRhYmxlIH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvUGFnaW5hdGFibGVcIjtcbmltcG9ydCB7IFBhZ2luYXRvciB9IGZyb20gXCIuL1BhZ2luYXRvclwiO1xuaW1wb3J0IHsgQWRhcHRlciB9IGZyb20gXCIuLi9wZXJzaXN0ZW5jZVwiO1xuaW1wb3J0IHsgUXVlcnlFcnJvciB9IGZyb20gXCIuL2Vycm9yc1wiO1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBCYXNlIGNsYXNzIGZvciBkYXRhYmFzZSBxdWVyeSBzdGF0ZW1lbnRzXG4gKiBAc3VtbWFyeSBQcm92aWRlcyBhIGZvdW5kYXRpb24gZm9yIGJ1aWxkaW5nIGFuZCBleGVjdXRpbmcgZGF0YWJhc2UgcXVlcmllc1xuICpcbiAqIFRoaXMgYWJzdHJhY3QgY2xhc3MgaW1wbGVtZW50cyB0aGUgcXVlcnkgYnVpbGRlciBwYXR0ZXJuIGZvciBjb25zdHJ1Y3RpbmdcbiAqIGRhdGFiYXNlIHF1ZXJpZXMuIEl0IHN1cHBvcnRzIHZhcmlvdXMgcXVlcnkgb3BlcmF0aW9ucyBsaWtlIHNlbGVjdCwgZnJvbSxcbiAqIHdoZXJlLCBvcmRlckJ5LCBncm91cEJ5LCBsaW1pdCwgYW5kIG9mZnNldC4gSXQgYWxzbyBwcm92aWRlcyBtZXRob2RzIGZvclxuICogZXhlY3V0aW5nIHF1ZXJpZXMgYW5kIGhhbmRsaW5nIHBhZ2luYXRpb24uXG4gKlxuICogQHRlbXBsYXRlIFEgLSBUaGUgcXVlcnkgdHlwZSBzcGVjaWZpYyB0byB0aGUgZGF0YWJhc2UgYWRhcHRlclxuICogQHRlbXBsYXRlIE0gLSBUaGUgbW9kZWwgdHlwZSB0aGlzIHN0YXRlbWVudCBvcGVyYXRlcyBvblxuICogQHRlbXBsYXRlIFIgLSBUaGUgcmV0dXJuIHR5cGUgb2YgdGhlIHF1ZXJ5XG4gKiBAcGFyYW0ge0FkYXB0ZXI8YW55LCBRLCBhbnksIGFueT59IGFkYXB0ZXIgLSBUaGUgZGF0YWJhc2UgYWRhcHRlciB0byB1c2UgZm9yIGV4ZWN1dGluZyBxdWVyaWVzXG4gKiBAY2xhc3MgU3RhdGVtZW50XG4gKiBAZXhhbXBsZVxuICogLy8gQ3JlYXRlIGEgc3RhdGVtZW50IHRvIHF1ZXJ5IHVzZXJzXG4gKiBjb25zdCBzdGF0ZW1lbnQgPSBuZXcgU1FMU3RhdGVtZW50KGFkYXB0ZXIpO1xuICogY29uc3QgdXNlcnMgPSBhd2FpdCBzdGF0ZW1lbnRcbiAqICAgLnNlbGVjdCgpXG4gKiAgIC5mcm9tKFVzZXIpXG4gKiAgIC53aGVyZShDb25kaXRpb24uYXR0cmlidXRlKFwic3RhdHVzXCIpLmVxKFwiYWN0aXZlXCIpKVxuICogICAub3JkZXJCeShbXCJjcmVhdGVkQXRcIiwgXCJERVNDXCJdKVxuICogICAubGltaXQoMTApXG4gKiAgIC5leGVjdXRlKCk7XG4gKlxuICogLy8gVXNlIHBhZ2luYXRpb25cbiAqIGNvbnN0IHBhZ2luYXRvciA9IGF3YWl0IHN0YXRlbWVudFxuICogICAuc2VsZWN0KClcbiAqICAgLmZyb20oVXNlcilcbiAqICAgLnBhZ2luYXRlKDIwKTsgLy8gMjAgdXNlcnMgcGVyIHBhZ2VcbiAqXG4gKiBAbWVybWFpZFxuICogc2VxdWVuY2VEaWFncmFtXG4gKiAgIHBhcnRpY2lwYW50IENsaWVudFxuICogICBwYXJ0aWNpcGFudCBTdGF0ZW1lbnRcbiAqICAgcGFydGljaXBhbnQgQWRhcHRlclxuICogICBwYXJ0aWNpcGFudCBEYXRhYmFzZVxuICpcbiAqICAgQ2xpZW50LT4+U3RhdGVtZW50OiBzZWxlY3QoKVxuICogICBDbGllbnQtPj5TdGF0ZW1lbnQ6IGZyb20oTW9kZWwpXG4gKiAgIENsaWVudC0+PlN0YXRlbWVudDogd2hlcmUoY29uZGl0aW9uKVxuICogICBDbGllbnQtPj5TdGF0ZW1lbnQ6IG9yZGVyQnkoW2ZpZWxkLCBkaXJlY3Rpb25dKVxuICogICBDbGllbnQtPj5TdGF0ZW1lbnQ6IGxpbWl0KHZhbHVlKVxuICogICBDbGllbnQtPj5TdGF0ZW1lbnQ6IGV4ZWN1dGUoKVxuICogICBTdGF0ZW1lbnQtPj5TdGF0ZW1lbnQ6IGJ1aWxkKClcbiAqICAgU3RhdGVtZW50LT4+QWRhcHRlcjogcmF3KHF1ZXJ5KVxuICogICBBZGFwdGVyLT4+RGF0YWJhc2U6IGV4ZWN1dGUgcXVlcnlcbiAqICAgRGF0YWJhc2UtLT4+QWRhcHRlcjogcmV0dXJuIHJlc3VsdHNcbiAqICAgQWRhcHRlci0tPj5TdGF0ZW1lbnQ6IHJldHVybiBwcm9jZXNzZWQgcmVzdWx0c1xuICogICBTdGF0ZW1lbnQtLT4+Q2xpZW50OiByZXR1cm4gZmluYWwgcmVzdWx0c1xuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgU3RhdGVtZW50PFEsIE0gZXh0ZW5kcyBNb2RlbCwgUj5cbiAgaW1wbGVtZW50cyBFeGVjdXRvcjxSPiwgUmF3RXhlY3V0b3I8UT4sIFBhZ2luYXRhYmxlPE0sIFIsIFE+XG57XG4gIHByb3RlY3RlZCByZWFkb25seSBzZWxlY3RTZWxlY3Rvcj86IFNlbGVjdFNlbGVjdG9yPE0+W107XG4gIHByb3RlY3RlZCBkaXN0aW5jdFNlbGVjdG9yPzogU2VsZWN0U2VsZWN0b3I8TT47XG4gIHByb3RlY3RlZCBtYXhTZWxlY3Rvcj86IFNlbGVjdFNlbGVjdG9yPE0+O1xuICBwcm90ZWN0ZWQgbWluU2VsZWN0b3I/OiBTZWxlY3RTZWxlY3RvcjxNPjtcbiAgcHJvdGVjdGVkIGNvdW50U2VsZWN0b3I/OiBTZWxlY3RTZWxlY3RvcjxNPjtcbiAgcHJvdGVjdGVkIGZyb21TZWxlY3RvciE6IENvbnN0cnVjdG9yPE0+O1xuICBwcm90ZWN0ZWQgd2hlcmVDb25kaXRpb24/OiBDb25kaXRpb248TT47XG4gIHByb3RlY3RlZCBvcmRlckJ5U2VsZWN0b3I/OiBPcmRlckJ5U2VsZWN0b3I8TT47XG4gIHByb3RlY3RlZCBncm91cEJ5U2VsZWN0b3I/OiBHcm91cEJ5U2VsZWN0b3I8TT47XG4gIHByb3RlY3RlZCBsaW1pdFNlbGVjdG9yPzogbnVtYmVyO1xuICBwcm90ZWN0ZWQgb2Zmc2V0U2VsZWN0b3I/OiBudW1iZXI7XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKHByb3RlY3RlZCBhZGFwdGVyOiBBZGFwdGVyPGFueSwgUSwgYW55LCBhbnk+KSB7fVxuXG4gIHNlbGVjdDxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgUyBleHRlbmRzIHJlYWRvbmx5IFNlbGVjdFNlbGVjdG9yPE0+W10sXG4gID4oKTogU2VsZWN0T3B0aW9uPE0sIE1bXT47XG4gIHNlbGVjdDxTIGV4dGVuZHMgcmVhZG9ubHkgU2VsZWN0U2VsZWN0b3I8TT5bXT4oXG4gICAgc2VsZWN0b3I6IHJlYWRvbmx5IFsuLi5TXVxuICApOiBTZWxlY3RPcHRpb248TSwgUGljazxNLCBTW251bWJlcl0+W10+O1xuXG4gIEBmaW5hbCgpXG4gIHNlbGVjdDxTIGV4dGVuZHMgcmVhZG9ubHkgU2VsZWN0U2VsZWN0b3I8TT5bXT4oXG4gICAgc2VsZWN0b3I/OiByZWFkb25seSBbLi4uU11cbiAgKTogU2VsZWN0T3B0aW9uPE0sIE1bXT4gfCBTZWxlY3RPcHRpb248TSwgUGljazxNLCBTW251bWJlcl0+W10+IHtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgXCJzZWxlY3RTZWxlY3RvclwiLCB7XG4gICAgICB2YWx1ZTogc2VsZWN0b3IsXG4gICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXMgYXMgU2VsZWN0T3B0aW9uPE0sIE1bXT4gfCBTZWxlY3RPcHRpb248TSwgUGljazxNLCBTW251bWJlcl0+W10+O1xuICB9XG5cbiAgQGZpbmFsKClcbiAgZGlzdGluY3Q8UyBleHRlbmRzIFNlbGVjdFNlbGVjdG9yPE0+PihcbiAgICBzZWxlY3RvcjogU1xuICApOiBEaXN0aW5jdE9wdGlvbjxNLCBNW1NdW10+IHtcbiAgICB0aGlzLmRpc3RpbmN0U2VsZWN0b3IgPSBzZWxlY3RvcjtcbiAgICByZXR1cm4gdGhpcyBhcyBEaXN0aW5jdE9wdGlvbjxNLCBNW1NdW10+O1xuICB9XG5cbiAgQGZpbmFsKClcbiAgbWF4PFMgZXh0ZW5kcyBTZWxlY3RTZWxlY3RvcjxNPj4oc2VsZWN0b3I6IFMpOiBNYXhPcHRpb248TSwgTVtTXT4ge1xuICAgIHRoaXMubWF4U2VsZWN0b3IgPSBzZWxlY3RvcjtcbiAgICByZXR1cm4gdGhpcyBhcyBNYXhPcHRpb248TSwgTVtTXT47XG4gIH1cblxuICBAZmluYWwoKVxuICBtaW48UyBleHRlbmRzIFNlbGVjdFNlbGVjdG9yPE0+PihzZWxlY3RvcjogUyk6IE1pbk9wdGlvbjxNLCBNW1NdPiB7XG4gICAgdGhpcy5taW5TZWxlY3RvciA9IHNlbGVjdG9yO1xuICAgIHJldHVybiB0aGlzIGFzIE1pbk9wdGlvbjxNLCBNW1NdPjtcbiAgfVxuXG4gIEBmaW5hbCgpXG4gIGNvdW50PFMgZXh0ZW5kcyBTZWxlY3RTZWxlY3RvcjxNPj4oc2VsZWN0b3I/OiBTKTogQ291bnRPcHRpb248TSwgbnVtYmVyPiB7XG4gICAgdGhpcy5jb3VudFNlbGVjdG9yID0gc2VsZWN0b3I7XG4gICAgcmV0dXJuIHRoaXMgYXMgQ291bnRPcHRpb248TSwgbnVtYmVyPjtcbiAgfVxuXG4gIEBmaW5hbCgpXG4gIHB1YmxpYyBmcm9tKHNlbGVjdG9yOiBGcm9tU2VsZWN0b3I8TT4pOiBXaGVyZU9wdGlvbjxNLCBSPiB7XG4gICAgdGhpcy5mcm9tU2VsZWN0b3IgPSAoXG4gICAgICB0eXBlb2Ygc2VsZWN0b3IgPT09IFwic3RyaW5nXCIgPyBNb2RlbC5nZXQoc2VsZWN0b3IpIDogc2VsZWN0b3JcbiAgICApIGFzIENvbnN0cnVjdG9yPE0+O1xuICAgIGlmICghdGhpcy5mcm9tU2VsZWN0b3IpXG4gICAgICB0aHJvdyBuZXcgUXVlcnlFcnJvcihgQ291bGQgbm90IGZpbmQgc2VsZWN0b3IgbW9kZWw6ICR7c2VsZWN0b3J9YCk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBAZmluYWwoKVxuICBwdWJsaWMgd2hlcmUoY29uZGl0aW9uOiBDb25kaXRpb248TT4pOiBPcmRlckFuZEdyb3VwT3B0aW9uPE0sIFI+IHtcbiAgICB0aGlzLndoZXJlQ29uZGl0aW9uID0gY29uZGl0aW9uO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgQGZpbmFsKClcbiAgcHVibGljIG9yZGVyQnkoXG4gICAgc2VsZWN0b3I6IE9yZGVyQnlTZWxlY3RvcjxNPlxuICApOiBMaW1pdE9wdGlvbjxNLCBSPiAmIE9mZnNldE9wdGlvbjxSPiB7XG4gICAgdGhpcy5vcmRlckJ5U2VsZWN0b3IgPSBzZWxlY3RvcjtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIEBmaW5hbCgpXG4gIHB1YmxpYyBncm91cEJ5KHNlbGVjdG9yOiBHcm91cEJ5U2VsZWN0b3I8TT4pOiBMaW1pdE9wdGlvbjxNLCBSPiB7XG4gICAgdGhpcy5ncm91cEJ5U2VsZWN0b3IgPSBzZWxlY3RvcjtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIEBmaW5hbCgpXG4gIHB1YmxpYyBsaW1pdCh2YWx1ZTogbnVtYmVyKTogT2Zmc2V0T3B0aW9uPFI+IHtcbiAgICB0aGlzLmxpbWl0U2VsZWN0b3IgPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIEBmaW5hbCgpXG4gIHB1YmxpYyBvZmZzZXQodmFsdWU6IG51bWJlcik6IEV4ZWN1dG9yPFI+IHtcbiAgICB0aGlzLm9mZnNldFNlbGVjdG9yID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBAZmluYWwoKVxuICBhc3luYyBleGVjdXRlKCk6IFByb21pc2U8Uj4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBxdWVyeTogUSA9IHRoaXMuYnVpbGQoKTtcbiAgICAgIHJldHVybiAoYXdhaXQgdGhpcy5yYXcocXVlcnkpKSBhcyBSO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGUgYXMgRXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHJhdzxSPihyYXdJbnB1dDogUSk6IFByb21pc2U8Uj4ge1xuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCB0aGlzLmFkYXB0ZXIucmF3PFI+KHJhd0lucHV0KTtcbiAgICBpZiAoIXRoaXMuc2VsZWN0U2VsZWN0b3IpIHJldHVybiByZXN1bHRzO1xuICAgIGNvbnN0IHBrQXR0ciA9IGZpbmRQcmltYXJ5S2V5KFxuICAgICAgbmV3ICh0aGlzLmZyb21TZWxlY3RvciBhcyBDb25zdHJ1Y3RvcjxNPikoKVxuICAgICkuaWQ7XG5cbiAgICBjb25zdCBwcm9jZXNzb3IgPSBmdW5jdGlvbiByZWNvcmRQcm9jZXNzb3IoXG4gICAgICB0aGlzOiBTdGF0ZW1lbnQ8USwgTSwgUj4sXG4gICAgICByOiBhbnlcbiAgICApIHtcbiAgICAgIGNvbnN0IGlkID0gcltwa0F0dHJdO1xuICAgICAgcmV0dXJuIHRoaXMuYWRhcHRlci5yZXZlcnQoXG4gICAgICAgIHIsXG4gICAgICAgIHRoaXMuZnJvbVNlbGVjdG9yIGFzIENvbnN0cnVjdG9yPGFueT4sXG4gICAgICAgIHBrQXR0cixcbiAgICAgICAgaWRcbiAgICAgICkgYXMgYW55O1xuICAgIH0uYmluZCh0aGlzIGFzIGFueSk7XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShyZXN1bHRzKSkgcmV0dXJuIHJlc3VsdHMubWFwKHByb2Nlc3NvcikgYXMgUjtcbiAgICByZXR1cm4gcHJvY2Vzc29yKHJlc3VsdHMpIGFzIFI7XG4gIH1cblxuICBwcm90ZWN0ZWQgYWJzdHJhY3QgYnVpbGQoKTogUTtcbiAgcHJvdGVjdGVkIGFic3RyYWN0IHBhcnNlQ29uZGl0aW9uKGNvbmRpdGlvbjogQ29uZGl0aW9uPE0+LCAuLi5hcmdzOiBhbnlbXSk6IFE7XG4gIGFic3RyYWN0IHBhZ2luYXRlKHNpemU6IG51bWJlcik6IFByb21pc2U8UGFnaW5hdG9yPE0sIFIsIFE+Pjtcbn1cbiJdfQ==