UNPKG

@decaf-ts/core

Version:

Core persistence module for the decaf framework

219 lines 21 kB
"use strict"; 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; Object.defineProperty(exports, "__esModule", { value: true }); exports.Statement = void 0; const decorator_validation_1 = require("@decaf-ts/decorator-validation"); const Condition_1 = require("./Condition.cjs"); const db_decorators_1 = require("@decaf-ts/db-decorators"); const decorators_1 = require("./../utils/decorators.cjs"); const errors_1 = require("./errors.cjs"); /** * @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 */ 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" ? decorator_validation_1.Model.get(selector) : selector); if (!this.fromSelector) throw new errors_1.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 db_decorators_1.InternalError(e); } } async raw(rawInput) { const results = await this.adapter.raw(rawInput); if (!this.selectSelector) return results; const pkAttr = (0, db_decorators_1.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); } } exports.Statement = Statement; __decorate([ (0, decorators_1.final)(), __metadata("design:type", Function), __metadata("design:paramtypes", [Array]), __metadata("design:returntype", Object) ], Statement.prototype, "select", null); __decorate([ (0, decorators_1.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([ (0, decorators_1.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([ (0, decorators_1.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([ (0, decorators_1.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([ (0, decorators_1.final)(), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Object) ], Statement.prototype, "from", null); __decorate([ (0, decorators_1.final)(), __metadata("design:type", Function), __metadata("design:paramtypes", [Condition_1.Condition]), __metadata("design:returntype", Object) ], Statement.prototype, "where", null); __decorate([ (0, decorators_1.final)(), __metadata("design:type", Function), __metadata("design:paramtypes", [Array]), __metadata("design:returntype", Object) ], Statement.prototype, "orderBy", null); __decorate([ (0, decorators_1.final)(), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", Object) ], Statement.prototype, "groupBy", null); __decorate([ (0, decorators_1.final)(), __metadata("design:type", Function), __metadata("design:paramtypes", [Number]), __metadata("design:returntype", Object) ], Statement.prototype, "limit", null); __decorate([ (0, decorators_1.final)(), __metadata("design:type", Function), __metadata("design:paramtypes", [Number]), __metadata("design:returntype", Object) ], Statement.prototype, "offset", null); __decorate([ (0, decorators_1.final)(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", Promise) ], Statement.prototype, "execute", null); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3RhdGVtZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3F1ZXJ5L1N0YXRlbWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7O0FBQUEseUVBQXlFO0FBUXpFLCtDQUF3QztBQUN4QywyREFBd0U7QUFDeEUsMERBQTRDO0FBZTVDLHlDQUFzQztBQUV0Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrREc7QUFDSCxNQUFzQixTQUFTO0lBZTdCLFlBQWdDLE9BQWtDO1FBQWxDLFlBQU8sR0FBUCxPQUFPLENBQTJCO0lBQUcsQ0FBQztJQVd0RSxNQUFNLENBQ0osUUFBMEI7UUFFMUIsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUU7WUFDNUMsS0FBSyxFQUFFLFFBQVE7WUFDZixRQUFRLEVBQUUsS0FBSztTQUNoQixDQUFDLENBQUM7UUFDSCxPQUFPLElBQW9FLENBQUM7SUFDOUUsQ0FBQztJQUdELFFBQVEsQ0FDTixRQUFXO1FBRVgsSUFBSSxDQUFDLGdCQUFnQixHQUFHLFFBQVEsQ0FBQztRQUNqQyxPQUFPLElBQWlDLENBQUM7SUFDM0MsQ0FBQztJQUdELEdBQUcsQ0FBOEIsUUFBVztRQUMxQyxJQUFJLENBQUMsV0FBVyxHQUFHLFFBQVEsQ0FBQztRQUM1QixPQUFPLElBQTBCLENBQUM7SUFDcEMsQ0FBQztJQUdELEdBQUcsQ0FBOEIsUUFBVztRQUMxQyxJQUFJLENBQUMsV0FBVyxHQUFHLFFBQVEsQ0FBQztRQUM1QixPQUFPLElBQTBCLENBQUM7SUFDcEMsQ0FBQztJQUdELEtBQUssQ0FBOEIsUUFBWTtRQUM3QyxJQUFJLENBQUMsYUFBYSxHQUFHLFFBQVEsQ0FBQztRQUM5QixPQUFPLElBQThCLENBQUM7SUFDeEMsQ0FBQztJQUdNLElBQUksQ0FBQyxRQUF5QjtRQUNuQyxJQUFJLENBQUMsWUFBWSxHQUFHLENBQ2xCLE9B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OztxQ0FRUDtBQUdNO0lBRE4sSUFBQSxrQkFBSyxHQUFFOztxQ0FDZ0IscUJBQVM7O3NDQUdoQztBQUdNO0lBRE4sSUFBQSxrQkFBSyxHQUFFOzs7O3dDQU1QO0FBR007SUFETixJQUFBLGtCQUFLLEdBQUU7Ozs7d0NBSVA7QUFHTTtJQUROLElBQUEsa0JBQUssR0FBRTs7OztzQ0FJUDtBQUdNO0lBRE4sSUFBQSxrQkFBSyxHQUFFOzs7O3VDQUlQO0FBR0s7SUFETCxJQUFBLGtCQUFLLEdBQUU7Ozs7d0NBUVAiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB0eXBlIENvbnN0cnVjdG9yLCBNb2RlbCB9IGZyb20gXCJAZGVjYWYtdHMvZGVjb3JhdG9yLXZhbGlkYXRpb25cIjtcbmltcG9ydCB0eXBlIHsgRXhlY3V0b3IsIFJhd0V4ZWN1dG9yIH0gZnJvbSBcIi4uL2ludGVyZmFjZXNcIjtcbmltcG9ydCB0eXBlIHtcbiAgRnJvbVNlbGVjdG9yLFxuICBHcm91cEJ5U2VsZWN0b3IsXG4gIE9yZGVyQnlTZWxlY3RvcixcbiAgU2VsZWN0U2VsZWN0b3IsXG59IGZyb20gXCIuL3NlbGVjdG9yc1wiO1xuaW1wb3J0IHsgQ29uZGl0aW9uIH0gZnJvbSBcIi4vQ29uZGl0aW9uXCI7XG5pbXBvcnQgeyBmaW5kUHJpbWFyeUtleSwgSW50ZXJuYWxFcnJvciB9IGZyb20gXCJAZGVjYWYtdHMvZGItZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHsgZmluYWwgfSBmcm9tIFwiLi4vdXRpbHMvZGVjb3JhdG9yc1wiO1xuaW1wb3J0IHR5cGUge1xuICBDb3VudE9wdGlvbixcbiAgRGlzdGluY3RPcHRpb24sXG4gIExpbWl0T3B0aW9uLFxuICBNYXhPcHRpb24sXG4gIE1pbk9wdGlvbixcbiAgT2Zmc2V0T3B0aW9uLFxuICBPcmRlckFuZEdyb3VwT3B0aW9uLFxuICBTZWxlY3RPcHRpb24sXG4gIFdoZXJlT3B0aW9uLFxufSBmcm9tIFwiLi9vcHRpb25zXCI7XG5pbXBvcnQgeyBQYWdpbmF0YWJsZSB9IGZyb20gXCIuLi9pbnRlcmZhY2VzL1BhZ2luYXRhYmxlXCI7XG5pbXBvcnQgeyBQYWdpbmF0b3IgfSBmcm9tIFwiLi9QYWdpbmF0b3JcIjtcbmltcG9ydCB7IEFkYXB0ZXIgfSBmcm9tIFwiLi4vcGVyc2lzdGVuY2VcIjtcbmltcG9ydCB7IFF1ZXJ5RXJyb3IgfSBmcm9tIFwiLi9lcnJvcnNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gQmFzZSBjbGFzcyBmb3IgZGF0YWJhc2UgcXVlcnkgc3RhdGVtZW50c1xuICogQHN1bW1hcnkgUHJvdmlkZXMgYSBmb3VuZGF0aW9uIGZvciBidWlsZGluZyBhbmQgZXhlY3V0aW5nIGRhdGFiYXNlIHF1ZXJpZXNcbiAqXG4gKiBUaGlzIGFic3RyYWN0IGNsYXNzIGltcGxlbWVudHMgdGhlIHF1ZXJ5IGJ1aWxkZXIgcGF0dGVybiBmb3IgY29uc3RydWN0aW5nXG4gKiBkYXRhYmFzZSBxdWVyaWVzLiBJdCBzdXBwb3J0cyB2YXJpb3VzIHF1ZXJ5IG9wZXJhdGlvbnMgbGlrZSBzZWxlY3QsIGZyb20sXG4gKiB3aGVyZSwgb3JkZXJCeSwgZ3JvdXBCeSwgbGltaXQsIGFuZCBvZmZzZXQuIEl0IGFsc28gcHJvdmlkZXMgbWV0aG9kcyBmb3JcbiAqIGV4ZWN1dGluZyBxdWVyaWVzIGFuZCBoYW5kbGluZyBwYWdpbmF0aW9uLlxuICpcbiAqIEB0ZW1wbGF0ZSBRIC0gVGhlIHF1ZXJ5IHR5cGUgc3BlY2lmaWMgdG8gdGhlIGRhdGFiYXNlIGFkYXB0ZXJcbiAqIEB0ZW1wbGF0ZSBNIC0gVGhlIG1vZGVsIHR5cGUgdGhpcyBzdGF0ZW1lbnQgb3BlcmF0ZXMgb25cbiAqIEB0ZW1wbGF0ZSBSIC0gVGhlIHJldHVybiB0eXBlIG9mIHRoZSBxdWVyeVxuICogQHBhcmFtIHtBZGFwdGVyPGFueSwgUSwgYW55LCBhbnk+fSBhZGFwdGVyIC0gVGhlIGRhdGFiYXNlIGFkYXB0ZXIgdG8gdXNlIGZvciBleGVjdXRpbmcgcXVlcmllc1xuICogQGNsYXNzIFN0YXRlbWVudFxuICogQGV4YW1wbGVcbiAqIC8vIENyZWF0ZSBhIHN0YXRlbWVudCB0byBxdWVyeSB1c2Vyc1xuICogY29uc3Qgc3RhdGVtZW50ID0gbmV3IFNRTFN0YXRlbWVudChhZGFwdGVyKTtcbiAqIGNvbnN0IHVzZXJzID0gYXdhaXQgc3RhdGVtZW50XG4gKiAgIC5zZWxlY3QoKVxuICogICAuZnJvbShVc2VyKVxuICogICAud2hlcmUoQ29uZGl0aW9uLmF0dHJpYnV0ZShcInN0YXR1c1wiKS5lcShcImFjdGl2ZVwiKSlcbiAqICAgLm9yZGVyQnkoW1wiY3JlYXRlZEF0XCIsIFwiREVTQ1wiXSlcbiAqICAgLmxpbWl0KDEwKVxuICogICAuZXhlY3V0ZSgpO1xuICpcbiAqIC8vIFVzZSBwYWdpbmF0aW9uXG4gKiBjb25zdCBwYWdpbmF0b3IgPSBhd2FpdCBzdGF0ZW1lbnRcbiAqICAgLnNlbGVjdCgpXG4gKiAgIC5mcm9tKFVzZXIpXG4gKiAgIC5wYWdpbmF0ZSgyMCk7IC8vIDIwIHVzZXJzIHBlciBwYWdlXG4gKlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDbGllbnRcbiAqICAgcGFydGljaXBhbnQgU3RhdGVtZW50XG4gKiAgIHBhcnRpY2lwYW50IEFkYXB0ZXJcbiAqICAgcGFydGljaXBhbnQgRGF0YWJhc2VcbiAqXG4gKiAgIENsaWVudC0+PlN0YXRlbWVudDogc2VsZWN0KClcbiAqICAgQ2xpZW50LT4+U3RhdGVtZW50OiBmcm9tKE1vZGVsKVxuICogICBDbGllbnQtPj5TdGF0ZW1lbnQ6IHdoZXJlKGNvbmRpdGlvbilcbiAqICAgQ2xpZW50LT4+U3RhdGVtZW50OiBvcmRlckJ5KFtmaWVsZCwgZGlyZWN0aW9uXSlcbiAqICAgQ2xpZW50LT4+U3RhdGVtZW50OiBsaW1pdCh2YWx1ZSlcbiAqICAgQ2xpZW50LT4+U3RhdGVtZW50OiBleGVjdXRlKClcbiAqICAgU3RhdGVtZW50LT4+U3RhdGVtZW50OiBidWlsZCgpXG4gKiAgIFN0YXRlbWVudC0+PkFkYXB0ZXI6IHJhdyhxdWVyeSlcbiAqICAgQWRhcHRlci0+PkRhdGFiYXNlOiBleGVjdXRlIHF1ZXJ5XG4gKiAgIERhdGFiYXNlLS0+PkFkYXB0ZXI6IHJldHVybiByZXN1bHRzXG4gKiAgIEFkYXB0ZXItLT4+U3RhdGVtZW50OiByZXR1cm4gcHJvY2Vzc2VkIHJlc3VsdHNcbiAqICAgU3RhdGVtZW50LS0+PkNsaWVudDogcmV0dXJuIGZpbmFsIHJlc3VsdHNcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFN0YXRlbWVudDxRLCBNIGV4dGVuZHMgTW9kZWwsIFI+XG4gIGltcGxlbWVudHMgRXhlY3V0b3I8Uj4sIFJhd0V4ZWN1dG9yPFE+LCBQYWdpbmF0YWJsZTxNLCBSLCBRPlxue1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgc2VsZWN0U2VsZWN0b3I/OiBTZWxlY3RTZWxlY3RvcjxNPltdO1xuICBwcm90ZWN0ZWQgZGlzdGluY3RTZWxlY3Rvcj86IFNlbGVjdFNlbGVjdG9yPE0+O1xuICBwcm90ZWN0ZWQgbWF4U2VsZWN0b3I/OiBTZWxlY3RTZWxlY3RvcjxNPjtcbiAgcHJvdGVjdGVkIG1pblNlbGVjdG9yPzogU2VsZWN0U2VsZWN0b3I8TT47XG4gIHByb3RlY3RlZCBjb3VudFNlbGVjdG9yPzogU2VsZWN0U2VsZWN0b3I8TT47XG4gIHByb3RlY3RlZCBmcm9tU2VsZWN0b3IhOiBDb25zdHJ1Y3RvcjxNPjtcbiAgcHJvdGVjdGVkIHdoZXJlQ29uZGl0aW9uPzogQ29uZGl0aW9uPE0+O1xuICBwcm90ZWN0ZWQgb3JkZXJCeVNlbGVjdG9yPzogT3JkZXJCeVNlbGVjdG9yPE0+O1xuICBwcm90ZWN0ZWQgZ3JvdXBCeVNlbGVjdG9yPzogR3JvdXBCeVNlbGVjdG9yPE0+O1xuICBwcm90ZWN0ZWQgbGltaXRTZWxlY3Rvcj86IG51bWJlcjtcbiAgcHJvdGVjdGVkIG9mZnNldFNlbGVjdG9yPzogbnVtYmVyO1xuXG4gIHByb3RlY3RlZCBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgYWRhcHRlcjogQWRhcHRlcjxhbnksIFEsIGFueSwgYW55Pikge31cblxuICBzZWxlY3Q8XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIFMgZXh0ZW5kcyByZWFkb25seSBTZWxlY3RTZWxlY3RvcjxNPltdLFxuICA+KCk6IFNlbGVjdE9wdGlvbjxNLCBNW10+O1xuICBzZWxlY3Q8UyBleHRlbmRzIHJlYWRvbmx5IFNlbGVjdFNlbGVjdG9yPE0+W10+KFxuICAgIHNlbGVjdG9yOiByZWFkb25seSBbLi4uU11cbiAgKTogU2VsZWN0T3B0aW9uPE0sIFBpY2s8TSwgU1tudW1iZXJdPltdPjtcblxuICBAZmluYWwoKVxuICBzZWxlY3Q8UyBleHRlbmRzIHJlYWRvbmx5IFNlbGVjdFNlbGVjdG9yPE0+W10+KFxuICAgIHNlbGVjdG9yPzogcmVhZG9ubHkgWy4uLlNdXG4gICk6IFNlbGVjdE9wdGlvbjxNLCBNW10+IHwgU2VsZWN0T3B0aW9uPE0sIFBpY2s8TSwgU1tudW1iZXJdPltdPiB7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIFwic2VsZWN0U2VsZWN0b3JcIiwge1xuICAgICAgdmFsdWU6IHNlbGVjdG9yLFxuICAgICAgd3JpdGFibGU6IGZhbHNlLFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzIGFzIFNlbGVjdE9wdGlvbjxNLCBNW10+IHwgU2VsZWN0T3B0aW9uPE0sIFBpY2s8TSwgU1tudW1iZXJdPltdPjtcbiAgfVxuXG4gIEBmaW5hbCgpXG4gIGRpc3RpbmN0PFMgZXh0ZW5kcyBTZWxlY3RTZWxlY3RvcjxNPj4oXG4gICAgc2VsZWN0b3I6IFNcbiAgKTogRGlzdGluY3RPcHRpb248TSwgTVtTXVtdPiB7XG4gICAgdGhpcy5kaXN0aW5jdFNlbGVjdG9yID0gc2VsZWN0b3I7XG4gICAgcmV0dXJuIHRoaXMgYXMgRGlzdGluY3RPcHRpb248TSwgTVtTXVtdPjtcbiAgfVxuXG4gIEBmaW5hbCgpXG4gIG1heDxTIGV4dGVuZHMgU2VsZWN0U2VsZWN0b3I8TT4+KHNlbGVjdG9yOiBTKTogTWF4T3B0aW9uPE0sIE1bU10+IHtcbiAgICB0aGlzLm1heFNlbGVjdG9yID0gc2VsZWN0b3I7XG4gICAgcmV0dXJuIHRoaXMgYXMgTWF4T3B0aW9uPE0sIE1bU10+O1xuICB9XG5cbiAgQGZpbmFsKClcbiAgbWluPFMgZXh0ZW5kcyBTZWxlY3RTZWxlY3RvcjxNPj4oc2VsZWN0b3I6IFMpOiBNaW5PcHRpb248TSwgTVtTXT4ge1xuICAgIHRoaXMubWluU2VsZWN0b3IgPSBzZWxlY3RvcjtcbiAgICByZXR1cm4gdGhpcyBhcyBNaW5PcHRpb248TSwgTVtTXT47XG4gIH1cblxuICBAZmluYWwoKVxuICBjb3VudDxTIGV4dGVuZHMgU2VsZWN0U2VsZWN0b3I8TT4+KHNlbGVjdG9yPzogUyk6IENvdW50T3B0aW9uPE0sIG51bWJlcj4ge1xuICAgIHRoaXMuY291bnRTZWxlY3RvciA9IHNlbGVjdG9yO1xuICAgIHJldHVybiB0aGlzIGFzIENvdW50T3B0aW9uPE0sIG51bWJlcj47XG4gIH1cblxuICBAZmluYWwoKVxuICBwdWJsaWMgZnJvbShzZWxlY3RvcjogRnJvbVNlbGVjdG9yPE0+KTogV2hlcmVPcHRpb248TSwgUj4ge1xuICAgIHRoaXMuZnJvbVNlbGVjdG9yID0gKFxuICAgICAgdHlwZW9mIHNlbGVjdG9yID09PSBcInN0cmluZ1wiID8gTW9kZWwuZ2V0KHNlbGVjdG9yKSA6IHNlbGVjdG9yXG4gICAgKSBhcyBDb25zdHJ1Y3RvcjxNPjtcbiAgICBpZiAoIXRoaXMuZnJvbVNlbGVjdG9yKVxuICAgICAgdGhyb3cgbmV3IFF1ZXJ5RXJyb3IoYENvdWxkIG5vdCBmaW5kIHNlbGVjdG9yIG1vZGVsOiAke3NlbGVjdG9yfWApO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgQGZpbmFsKClcbiAgcHVibGljIHdoZXJlKGNvbmRpdGlvbjogQ29uZGl0aW9uPE0+KTogT3JkZXJBbmRHcm91cE9wdGlvbjxNLCBSPiB7XG4gICAgdGhpcy53aGVyZUNvbmRpdGlvbiA9IGNvbmRpdGlvbjtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIEBmaW5hbCgpXG4gIHB1YmxpYyBvcmRlckJ5KFxuICAgIHNlbGVjdG9yOiBPcmRlckJ5U2VsZWN0b3I8TT5cbiAgKTogTGltaXRPcHRpb248TSwgUj4gJiBPZmZzZXRPcHRpb248Uj4ge1xuICAgIHRoaXMub3JkZXJCeVNlbGVjdG9yID0gc2VsZWN0b3I7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBAZmluYWwoKVxuICBwdWJsaWMgZ3JvdXBCeShzZWxlY3RvcjogR3JvdXBCeVNlbGVjdG9yPE0+KTogTGltaXRPcHRpb248TSwgUj4ge1xuICAgIHRoaXMuZ3JvdXBCeVNlbGVjdG9yID0gc2VsZWN0b3I7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBAZmluYWwoKVxuICBwdWJsaWMgbGltaXQodmFsdWU6IG51bWJlcik6IE9mZnNldE9wdGlvbjxSPiB7XG4gICAgdGhpcy5saW1pdFNlbGVjdG9yID0gdmFsdWU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBAZmluYWwoKVxuICBwdWJsaWMgb2Zmc2V0KHZhbHVlOiBudW1iZXIpOiBFeGVjdXRvcjxSPiB7XG4gICAgdGhpcy5vZmZzZXRTZWxlY3RvciA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgQGZpbmFsKClcbiAgYXN5bmMgZXhlY3V0ZSgpOiBQcm9taXNlPFI+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcXVlcnk6IFEgPSB0aGlzLmJ1aWxkKCk7XG4gICAgICByZXR1cm4gKGF3YWl0IHRoaXMucmF3KHF1ZXJ5KSkgYXMgUjtcbiAgICB9IGNhdGNoIChlOiB1bmtub3duKSB7XG4gICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihlIGFzIEVycm9yKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyByYXc8Uj4ocmF3SW5wdXQ6IFEpOiBQcm9taXNlPFI+IHtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgdGhpcy5hZGFwdGVyLnJhdzxSPihyYXdJbnB1dCk7XG4gICAgaWYgKCF0aGlzLnNlbGVjdFNlbGVjdG9yKSByZXR1cm4gcmVzdWx0cztcbiAgICBjb25zdCBwa0F0dHIgPSBmaW5kUHJpbWFyeUtleShcbiAgICAgIG5ldyAodGhpcy5mcm9tU2VsZWN0b3IgYXMgQ29uc3RydWN0b3I8TT4pKClcbiAgICApLmlkO1xuXG4gICAgY29uc3QgcHJvY2Vzc29yID0gZnVuY3Rpb24gcmVjb3JkUHJvY2Vzc29yKFxuICAgICAgdGhpczogU3RhdGVtZW50PFEsIE0sIFI+LFxuICAgICAgcjogYW55XG4gICAgKSB7XG4gICAgICBjb25zdCBpZCA9IHJbcGtBdHRyXTtcbiAgICAgIHJldHVybiB0aGlzLmFkYXB0ZXIucmV2ZXJ0KFxuICAgICAgICByLFxuICAgICAgICB0aGlzLmZyb21TZWxlY3RvciBhcyBDb25zdHJ1Y3Rvcjxhbnk+LFxuICAgICAgICBwa0F0dHIsXG4gICAgICAgIGlkXG4gICAgICApIGFzIGFueTtcbiAgICB9LmJpbmQodGhpcyBhcyBhbnkpO1xuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkocmVzdWx0cykpIHJldHVybiByZXN1bHRzLm1hcChwcm9jZXNzb3IpIGFzIFI7XG4gICAgcmV0dXJuIHByb2Nlc3NvcihyZXN1bHRzKSBhcyBSO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGJ1aWxkKCk6IFE7XG4gIHByb3RlY3RlZCBhYnN0cmFjdCBwYXJzZUNvbmRpdGlvbihjb25kaXRpb246IENvbmRpdGlvbjxNPiwgLi4uYXJnczogYW55W10pOiBRO1xuICBhYnN0cmFjdCBwYWdpbmF0ZShzaXplOiBudW1iZXIpOiBQcm9taXNlPFBhZ2luYXRvcjxNLCBSLCBRPj47XG59XG4iXX0=