UNPKG

@synerty/vortexjs

Version:

Custom observable data serialisation and routing based on Angular 2+

144 lines 21.3 kB
import { __decorate, __param } from "tslib"; import { Inject } from "@angular/core"; import { Capacitor } from "@capacitor/core"; import { Device } from "@capacitor/device"; import { CapacitorSQLite, SQLiteConnection, } from "@capacitor-community/sqlite"; import { random, SqlApiABC } from "./sql-api-abc"; import { assert, dateStr } from "../UtilMisc"; export let CapSqlApi = class CapSqlApi extends SqlApiABC { _CapacitorSQLite = null; _sqliteConnection = null; constructor(dbName, dbSchema) { super(dbName, dbSchema); } get capDbConn() { return this.db; } set capDbConn(val) { this.db = val; } async isOpen() { return this.db != null; } async close() { await this._sqliteConnection.closeAllConnections(); this.db = null; this._CapacitorSQLite = null; } async _openDb() { if (await this.isOpen()) { return; } // Wait for the platform to initialise const info = await Device.getInfo(); // Get the plugin console.log(`${dateStr()} *** platform ${info.platform}`); this._CapacitorSQLite = CapacitorSQLite; if (Capacitor.getPlatform() === "android") { try { await this._CapacitorSQLite.requestPermissions(); } catch (e) { throw new Error("This app can't work without Database access."); } } this._sqliteConnection = new SQLiteConnection(this._CapacitorSQLite); // The plugin keeps a singleton connection per DB name across all // CapSqlApi instances. Without isolation, two callers can both see // isConnection=false and both call createConnection — the second // throws "Connection <dbName> already exists". Fall back to // retrieveConnection in that case. await this._acquireConnection(this.dbName); const dbOpen = await this.capDbConn.isDBOpen(); if (dbOpen?.result !== true) { await this.capDbConn.open(); } await this.installSchema(); } async _acquireConnection(dbName) { const existing = await this._sqliteConnection.isConnection(dbName, false); if (existing?.result === true) { this.capDbConn = await this._sqliteConnection.retrieveConnection(dbName, false); return; } try { this.capDbConn = await this._sqliteConnection.createConnection(dbName, false, "no-encryption", 1, false); } catch (e) { // Defence-in-depth: if createConnection still races past the // lock (e.g. another code path bypassed CapSqlApi), fall back // to retrieving the existing connection. const msg = typeof e === "string" ? e : e?.message; if (msg && msg.indexOf("already exists") !== -1) { this.capDbConn = await this._sqliteConnection.retrieveConnection(dbName, false); return; } throw e; } } async transaction(executeData, isQuery) { if (!(await this.isOpen())) await this.open(); let retries = 5; while (true) { try { return await this._transactionInner(executeData, isQuery); } catch (e) { if (retries >= 0 /* && (CapSqlApi.checkRetryMessage(e) || CapSqlApi.isLockedMsg(e)) */ ) { retries--; await new Promise((r) => setTimeout(() => r(), 100 + random())); continue; } throw new Error(e); } } } async _transactionInner(executeData, isQuery) { if (isQuery) return await this._transactionInnerQuery(executeData); await this._transactionInnerExecute(executeData); } async _transactionInnerQuery(executeData) { assert(executeData.length === 1, "We expect executeData.length === 1 for a query"); const data = (await this.capDbConn.query(executeData[0].sql, executeData[0].bindParams))?.values; return data?.length ? data : null; } async _transactionInnerExecute(executeData) { const capData = []; const sqlOnlyList = []; for (const data of executeData) { if (!data.bindParams?.length /* null or 0 */) { sqlOnlyList.push(data.sql); } else { capData.push({ statement: data.sql, values: data.bindParams, }); } } for (const sql of sqlOnlyList) { // Just execute it, usually if we want a transaction we're // only inserting lots of data. const result = await this.capDbConn.run(sql); if (result.changes.changes === -1) throw new Error("An error occurred in the SQL"); } if (capData.length) { const result = await this.capDbConn.executeSet(capData); if (result.changes.changes === -1) throw new Error("An error occurred in the SQL"); } } }; CapSqlApi = __decorate([ __param(0, Inject("")), __param(1, Inject([])) ], CapSqlApi); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FwLXNxbC1hcGkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvdm9ydGV4L3N0b3JhZ2UtYXBpL2NhcC1zcWwtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM1QyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFM0MsT0FBTyxFQUNILGVBQWUsRUFFZixnQkFBZ0IsR0FDbkIsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBa0IsTUFBTSxlQUFlLENBQUM7QUFDbEUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFHdkMsV0FBTSxTQUFTLEdBQWYsTUFBTSxTQUFVLFNBQVEsU0FBUztJQUM1QixnQkFBZ0IsR0FBZSxJQUFJLENBQUM7SUFDcEMsaUJBQWlCLEdBQTRCLElBQUksQ0FBQztJQUUxRCxZQUF3QixNQUFjLEVBQWMsUUFBa0I7UUFDbEUsS0FBSyxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRUQsSUFBWSxTQUFTO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUNuQixDQUFDO0lBRUQsSUFBWSxTQUFTLENBQUMsR0FBdUI7UUFDekMsSUFBSSxDQUFDLEVBQUUsR0FBRyxHQUFHLENBQUM7SUFDbEIsQ0FBQztJQUVELEtBQUssQ0FBQyxNQUFNO1FBQ1IsT0FBTyxJQUFJLENBQUMsRUFBRSxJQUFJLElBQUksQ0FBQztJQUMzQixDQUFDO0lBRUQsS0FBSyxDQUFDLEtBQUs7UUFDUCxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBQ25ELElBQUksQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDO1FBQ2YsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksQ0FBQztJQUNqQyxDQUFDO0lBRVMsS0FBSyxDQUFDLE9BQU87UUFDbkIsSUFBSSxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRTtZQUNyQixPQUFPO1NBQ1Y7UUFDRCxzQ0FBc0M7UUFDdEMsTUFBTSxJQUFJLEdBQUcsTUFBTSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFcEMsaUJBQWlCO1FBQ2pCLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxPQUFPLEVBQUUsaUJBQWlCLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQzFELElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxlQUFlLENBQUM7UUFFeEMsSUFBSSxTQUFTLENBQUMsV0FBVyxFQUFFLEtBQUssU0FBUyxFQUFFO1lBQ3ZDLElBQUk7Z0JBQ0EsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsa0JBQWtCLEVBQUUsQ0FBQzthQUNwRDtZQUFDLE9BQU8sQ0FBQyxFQUFFO2dCQUNSLE1BQU0sSUFBSSxLQUFLLENBQUMsOENBQThDLENBQUMsQ0FBQzthQUNuRTtTQUNKO1FBRUQsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksZ0JBQWdCLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFFckUsaUVBQWlFO1FBQ2pFLG1FQUFtRTtRQUNuRSxpRUFBaUU7UUFDakUsNERBQTREO1FBQzVELG1DQUFtQztRQUNuQyxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFM0MsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQy9DLElBQUksTUFBTSxFQUFFLE1BQU0sS0FBSyxJQUFJLEVBQUU7WUFDekIsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDO1NBQy9CO1FBQ0QsTUFBTSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDL0IsQ0FBQztJQUVPLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxNQUFjO1FBQzNDLE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FDdEQsTUFBTSxFQUNOLEtBQUssQ0FDUixDQUFDO1FBQ0YsSUFBSSxRQUFRLEVBQUUsTUFBTSxLQUFLLElBQUksRUFBRTtZQUMzQixJQUFJLENBQUMsU0FBUyxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLGtCQUFrQixDQUM1RCxNQUFNLEVBQ04sS0FBSyxDQUNSLENBQUM7WUFDRixPQUFPO1NBQ1Y7UUFDRCxJQUFJO1lBQ0EsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FDMUQsTUFBTSxFQUNOLEtBQUssRUFDTCxlQUFlLEVBQ2YsQ0FBQyxFQUNELEtBQUssQ0FDUixDQUFDO1NBQ0w7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNSLDZEQUE2RDtZQUM3RCw4REFBOEQ7WUFDOUQseUNBQXlDO1lBQ3pDLE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBRSxDQUFXLEVBQUUsT0FBTyxDQUFDO1lBQzlELElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRTtnQkFDN0MsSUFBSSxDQUFDLFNBQVM7b0JBQ1YsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsa0JBQWtCLENBQzNDLE1BQU0sRUFDTixLQUFLLENBQ1IsQ0FBQztnQkFDTixPQUFPO2FBQ1Y7WUFDRCxNQUFNLENBQUMsQ0FBQztTQUNYO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxXQUFXLENBQ2IsV0FBNkIsRUFDN0IsT0FBZ0I7UUFFaEIsSUFBSSxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFBRSxNQUFNLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUU5QyxJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUM7UUFDaEIsT0FBTyxJQUFJLEVBQUU7WUFDVCxJQUFJO2dCQUNBLE9BQU8sTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2FBQzdEO1lBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ1IsSUFDSSxPQUFPLElBQUksQ0FBQztnQkFDWjs7NkNBRTZCO2tCQUMvQjtvQkFDRSxPQUFPLEVBQUUsQ0FBQztvQkFDVixNQUFNLElBQUksT0FBTyxDQUFPLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FDMUIsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEdBQUcsR0FBRyxNQUFNLEVBQUUsQ0FBQyxDQUN4QyxDQUFDO29CQUNGLFNBQVM7aUJBQ1o7Z0JBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUN0QjtTQUNKO0lBQ0wsQ0FBQztJQUVPLEtBQUssQ0FBQyxpQkFBaUIsQ0FDM0IsV0FBNkIsRUFDN0IsT0FBZ0I7UUFFaEIsSUFBSSxPQUFPO1lBQUUsT0FBTyxNQUFNLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUVuRSxNQUFNLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNyRCxDQUFDO0lBRU8sS0FBSyxDQUFDLHNCQUFzQixDQUNoQyxXQUE2QjtRQUU3QixNQUFNLENBQ0YsV0FBVyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQ3hCLGdEQUFnRCxDQUNuRCxDQUFDO1FBRUYsTUFBTSxJQUFJLEdBQUcsQ0FDVCxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUN0QixXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUNsQixXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUM1QixDQUNKLEVBQUUsTUFBTSxDQUFDO1FBRVYsT0FBTyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUN0QyxDQUFDO0lBRU8sS0FBSyxDQUFDLHdCQUF3QixDQUNsQyxXQUE2QjtRQUU3QixNQUFNLE9BQU8sR0FBd0IsRUFBRSxDQUFDO1FBQ3hDLE1BQU0sV0FBVyxHQUFhLEVBQUUsQ0FBQztRQUNqQyxLQUFLLE1BQU0sSUFBSSxJQUFJLFdBQVcsRUFBRTtZQUM1QixJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsZUFBZSxFQUFFO2dCQUMxQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQzthQUM5QjtpQkFBTTtnQkFDSCxPQUFPLENBQUMsSUFBSSxDQUFDO29CQUNULFNBQVMsRUFBRSxJQUFJLENBQUMsR0FBRztvQkFDbkIsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVO2lCQUMxQixDQUFDLENBQUM7YUFDTjtTQUNKO1FBRUQsS0FBSyxNQUFNLEdBQUcsSUFBSSxXQUFXLEVBQUU7WUFDM0IsMERBQTBEO1lBQzFELCtCQUErQjtZQUMvQixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQzdDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEtBQUssQ0FBQyxDQUFDO2dCQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLDhCQUE4QixDQUFDLENBQUM7U0FDdkQ7UUFFRCxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUU7WUFDaEIsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN4RCxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxLQUFLLENBQUMsQ0FBQztnQkFDN0IsTUFBTSxJQUFJLEtBQUssQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO1NBQ3ZEO0lBQ0wsQ0FBQztDQXNCSixDQUFBO0FBN01ZLFNBQVM7SUFJTCxXQUFBLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUFrQixXQUFBLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQTtHQUoxQyxTQUFTLENBNk1yQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdCB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBDYXBhY2l0b3IgfSBmcm9tIFwiQGNhcGFjaXRvci9jb3JlXCI7XG5pbXBvcnQgeyBEZXZpY2UgfSBmcm9tIFwiQGNhcGFjaXRvci9kZXZpY2VcIjtcblxuaW1wb3J0IHtcbiAgICBDYXBhY2l0b3JTUUxpdGUsXG4gICAgY2FwU1FMaXRlU2V0LFxuICAgIFNRTGl0ZUNvbm5lY3Rpb24sXG59IGZyb20gXCJAY2FwYWNpdG9yLWNvbW11bml0eS9zcWxpdGVcIjtcbmltcG9ydCB7IHJhbmRvbSwgU3FsQXBpQUJDLCBTcWxFeGVjdXRlRGF0YSB9IGZyb20gXCIuL3NxbC1hcGktYWJjXCI7XG5pbXBvcnQgeyBhc3NlcnQsIGRhdGVTdHIgfSBmcm9tIFwiLi4vVXRpbE1pc2NcIjtcbmltcG9ydCB7IFNRTGl0ZURCQ29ubmVjdGlvbiB9IGZyb20gXCJAY2FwYWNpdG9yLWNvbW11bml0eS9zcWxpdGVcIjtcblxuZXhwb3J0IGNsYXNzIENhcFNxbEFwaSBleHRlbmRzIFNxbEFwaUFCQyB7XG4gICAgcHJpdmF0ZSBfQ2FwYWNpdG9yU1FMaXRlOiBhbnkgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIF9zcWxpdGVDb25uZWN0aW9uOiBTUUxpdGVDb25uZWN0aW9uIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdHJ1Y3RvcihASW5qZWN0KFwiXCIpIGRiTmFtZTogc3RyaW5nLCBASW5qZWN0KFtdKSBkYlNjaGVtYTogc3RyaW5nW10pIHtcbiAgICAgICAgc3VwZXIoZGJOYW1lLCBkYlNjaGVtYSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXQgY2FwRGJDb25uKCk6IFNRTGl0ZURCQ29ubmVjdGlvbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmRiO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2V0IGNhcERiQ29ubih2YWw6IFNRTGl0ZURCQ29ubmVjdGlvbikge1xuICAgICAgICB0aGlzLmRiID0gdmFsO1xuICAgIH1cblxuICAgIGFzeW5jIGlzT3BlbigpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGIgIT0gbnVsbDtcbiAgICB9XG5cbiAgICBhc3luYyBjbG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5fc3FsaXRlQ29ubmVjdGlvbi5jbG9zZUFsbENvbm5lY3Rpb25zKCk7XG4gICAgICAgIHRoaXMuZGIgPSBudWxsO1xuICAgICAgICB0aGlzLl9DYXBhY2l0b3JTUUxpdGUgPSBudWxsO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhc3luYyBfb3BlbkRiKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoYXdhaXQgdGhpcy5pc09wZW4oKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdhaXQgZm9yIHRoZSBwbGF0Zm9ybSB0byBpbml0aWFsaXNlXG4gICAgICAgIGNvbnN0IGluZm8gPSBhd2FpdCBEZXZpY2UuZ2V0SW5mbygpO1xuXG4gICAgICAgIC8vIEdldCB0aGUgcGx1Z2luXG4gICAgICAgIGNvbnNvbGUubG9nKGAke2RhdGVTdHIoKX0gKioqIHBsYXRmb3JtICR7aW5mby5wbGF0Zm9ybX1gKTtcbiAgICAgICAgdGhpcy5fQ2FwYWNpdG9yU1FMaXRlID0gQ2FwYWNpdG9yU1FMaXRlO1xuXG4gICAgICAgIGlmIChDYXBhY2l0b3IuZ2V0UGxhdGZvcm0oKSA9PT0gXCJhbmRyb2lkXCIpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5fQ2FwYWNpdG9yU1FMaXRlLnJlcXVlc3RQZXJtaXNzaW9ucygpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoaXMgYXBwIGNhbid0IHdvcmsgd2l0aG91dCBEYXRhYmFzZSBhY2Nlc3MuXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fc3FsaXRlQ29ubmVjdGlvbiA9IG5ldyBTUUxpdGVDb25uZWN0aW9uKHRoaXMuX0NhcGFjaXRvclNRTGl0ZSk7XG5cbiAgICAgICAgLy8gVGhlIHBsdWdpbiBrZWVwcyBhIHNpbmdsZXRvbiBjb25uZWN0aW9uIHBlciBEQiBuYW1lIGFjcm9zcyBhbGxcbiAgICAgICAgLy8gQ2FwU3FsQXBpIGluc3RhbmNlcy4gV2l0aG91dCBpc29sYXRpb24sIHR3byBjYWxsZXJzIGNhbiBib3RoIHNlZVxuICAgICAgICAvLyBpc0Nvbm5lY3Rpb249ZmFsc2UgYW5kIGJvdGggY2FsbCBjcmVhdGVDb25uZWN0aW9uIOKAlCB0aGUgc2Vjb25kXG4gICAgICAgIC8vIHRocm93cyBcIkNvbm5lY3Rpb24gPGRiTmFtZT4gYWxyZWFkeSBleGlzdHNcIi4gRmFsbCBiYWNrIHRvXG4gICAgICAgIC8vIHJldHJpZXZlQ29ubmVjdGlvbiBpbiB0aGF0IGNhc2UuXG4gICAgICAgIGF3YWl0IHRoaXMuX2FjcXVpcmVDb25uZWN0aW9uKHRoaXMuZGJOYW1lKTtcblxuICAgICAgICBjb25zdCBkYk9wZW4gPSBhd2FpdCB0aGlzLmNhcERiQ29ubi5pc0RCT3BlbigpO1xuICAgICAgICBpZiAoZGJPcGVuPy5yZXN1bHQgIT09IHRydWUpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2FwRGJDb25uLm9wZW4oKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB0aGlzLmluc3RhbGxTY2hlbWEoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9hY3F1aXJlQ29ubmVjdGlvbihkYk5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHRoaXMuX3NxbGl0ZUNvbm5lY3Rpb24uaXNDb25uZWN0aW9uKFxuICAgICAgICAgICAgZGJOYW1lLFxuICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChleGlzdGluZz8ucmVzdWx0ID09PSB0cnVlKSB7XG4gICAgICAgICAgICB0aGlzLmNhcERiQ29ubiA9IGF3YWl0IHRoaXMuX3NxbGl0ZUNvbm5lY3Rpb24ucmV0cmlldmVDb25uZWN0aW9uKFxuICAgICAgICAgICAgICAgIGRiTmFtZSxcbiAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMuY2FwRGJDb25uID0gYXdhaXQgdGhpcy5fc3FsaXRlQ29ubmVjdGlvbi5jcmVhdGVDb25uZWN0aW9uKFxuICAgICAgICAgICAgICAgIGRiTmFtZSxcbiAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgICBcIm5vLWVuY3J5cHRpb25cIixcbiAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gRGVmZW5jZS1pbi1kZXB0aDogaWYgY3JlYXRlQ29ubmVjdGlvbiBzdGlsbCByYWNlcyBwYXN0IHRoZVxuICAgICAgICAgICAgLy8gbG9jayAoZS5nLiBhbm90aGVyIGNvZGUgcGF0aCBieXBhc3NlZCBDYXBTcWxBcGkpLCBmYWxsIGJhY2tcbiAgICAgICAgICAgIC8vIHRvIHJldHJpZXZpbmcgdGhlIGV4aXN0aW5nIGNvbm5lY3Rpb24uXG4gICAgICAgICAgICBjb25zdCBtc2cgPSB0eXBlb2YgZSA9PT0gXCJzdHJpbmdcIiA/IGUgOiAoZSBhcyBFcnJvcik/Lm1lc3NhZ2U7XG4gICAgICAgICAgICBpZiAobXNnICYmIG1zZy5pbmRleE9mKFwiYWxyZWFkeSBleGlzdHNcIikgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jYXBEYkNvbm4gPVxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl9zcWxpdGVDb25uZWN0aW9uLnJldHJpZXZlQ29ubmVjdGlvbihcbiAgICAgICAgICAgICAgICAgICAgICAgIGRiTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyB0cmFuc2FjdGlvbihcbiAgICAgICAgZXhlY3V0ZURhdGE6IFNxbEV4ZWN1dGVEYXRhW10sXG4gICAgICAgIGlzUXVlcnk6IGJvb2xlYW5cbiAgICApOiBQcm9taXNlPGFueVtdIHwgbnVsbD4ge1xuICAgICAgICBpZiAoIShhd2FpdCB0aGlzLmlzT3BlbigpKSkgYXdhaXQgdGhpcy5vcGVuKCk7XG5cbiAgICAgICAgbGV0IHJldHJpZXMgPSA1O1xuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5fdHJhbnNhY3Rpb25Jbm5lcihleGVjdXRlRGF0YSwgaXNRdWVyeSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICByZXRyaWVzID49IDBcbiAgICAgICAgICAgICAgICAgICAgLyogJiZcbiAgICAgICAgICAgICAgICAgICAgIChDYXBTcWxBcGkuY2hlY2tSZXRyeU1lc3NhZ2UoZSkgfHxcbiAgICAgICAgICAgICAgICAgICAgIENhcFNxbEFwaS5pc0xvY2tlZE1zZyhlKSkgKi9cbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0cmllcy0tO1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocikgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gcigpLCAxMDAgKyByYW5kb20oKSlcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfdHJhbnNhY3Rpb25Jbm5lcihcbiAgICAgICAgZXhlY3V0ZURhdGE6IFNxbEV4ZWN1dGVEYXRhW10sXG4gICAgICAgIGlzUXVlcnk6IGJvb2xlYW5cbiAgICApOiBQcm9taXNlPGFueVtdIHwgbnVsbD4ge1xuICAgICAgICBpZiAoaXNRdWVyeSkgcmV0dXJuIGF3YWl0IHRoaXMuX3RyYW5zYWN0aW9uSW5uZXJRdWVyeShleGVjdXRlRGF0YSk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5fdHJhbnNhY3Rpb25Jbm5lckV4ZWN1dGUoZXhlY3V0ZURhdGEpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3RyYW5zYWN0aW9uSW5uZXJRdWVyeShcbiAgICAgICAgZXhlY3V0ZURhdGE6IFNxbEV4ZWN1dGVEYXRhW11cbiAgICApOiBQcm9taXNlPGFueVtdIHwgbnVsbD4ge1xuICAgICAgICBhc3NlcnQoXG4gICAgICAgICAgICBleGVjdXRlRGF0YS5sZW5ndGggPT09IDEsXG4gICAgICAgICAgICBcIldlIGV4cGVjdCBleGVjdXRlRGF0YS5sZW5ndGggPT09IDEgZm9yIGEgcXVlcnlcIlxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IGRhdGEgPSAoXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmNhcERiQ29ubi5xdWVyeShcbiAgICAgICAgICAgICAgICBleGVjdXRlRGF0YVswXS5zcWwsXG4gICAgICAgICAgICAgICAgZXhlY3V0ZURhdGFbMF0uYmluZFBhcmFtc1xuICAgICAgICAgICAgKVxuICAgICAgICApPy52YWx1ZXM7XG5cbiAgICAgICAgcmV0dXJuIGRhdGE/Lmxlbmd0aCA/IGRhdGEgOiBudWxsO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3RyYW5zYWN0aW9uSW5uZXJFeGVjdXRlKFxuICAgICAgICBleGVjdXRlRGF0YTogU3FsRXhlY3V0ZURhdGFbXVxuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBjYXBEYXRhOiBBcnJheTxjYXBTUUxpdGVTZXQ+ID0gW107XG4gICAgICAgIGNvbnN0IHNxbE9ubHlMaXN0OiBzdHJpbmdbXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGRhdGEgb2YgZXhlY3V0ZURhdGEpIHtcbiAgICAgICAgICAgIGlmICghZGF0YS5iaW5kUGFyYW1zPy5sZW5ndGggLyogbnVsbCBvciAwICovKSB7XG4gICAgICAgICAgICAgICAgc3FsT25seUxpc3QucHVzaChkYXRhLnNxbCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhcERhdGEucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHN0YXRlbWVudDogZGF0YS5zcWwsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlczogZGF0YS5iaW5kUGFyYW1zLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChjb25zdCBzcWwgb2Ygc3FsT25seUxpc3QpIHtcbiAgICAgICAgICAgIC8vIEp1c3QgZXhlY3V0ZSBpdCwgdXN1YWxseSBpZiB3ZSB3YW50IGEgdHJhbnNhY3Rpb24gd2UncmVcbiAgICAgICAgICAgIC8vIG9ubHkgaW5zZXJ0aW5nIGxvdHMgb2YgZGF0YS5cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuY2FwRGJDb25uLnJ1bihzcWwpO1xuICAgICAgICAgICAgaWYgKHJlc3VsdC5jaGFuZ2VzLmNoYW5nZXMgPT09IC0xKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkFuIGVycm9yIG9jY3VycmVkIGluIHRoZSBTUUxcIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2FwRGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuY2FwRGJDb25uLmV4ZWN1dGVTZXQoY2FwRGF0YSk7XG4gICAgICAgICAgICBpZiAocmVzdWx0LmNoYW5nZXMuY2hhbmdlcyA9PT0gLTEpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQW4gZXJyb3Igb2NjdXJyZWQgaW4gdGhlIFNRTFwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHByaXZhdGUgc3RhdGljIGNoZWNrUmV0cnlNZXNzYWdlKG1lc3NhZ2U6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIC8vICAgICBpZiAobWVzc2FnZS5pbmRleE9mKFJFVFJZX05PX1NQQUNFKSAhPT0gLTEpIHJldHVybiB0cnVlO1xuICAgIC8vXG4gICAgLy8gICAgIHJldHVybiBtZXNzYWdlLmluZGV4T2YoUkVUUllfRElTS19FUlJPUikgIT09IC0xO1xuICAgIC8vIH1cbiAgICAvL1xuICAgIC8vIHByaXZhdGUgc3RhdGljIGlzTG9ja2VkTXNnKGVycjogYW55KTogYm9vbGVhbiB7XG4gICAgLy8gICAgIGNvbnN0IG1zZyA9IGVyci50b1N0cmluZygpO1xuICAgIC8vXG4gICAgLy8gICAgIGNvbnN0IGhhc05zU3FsRXJyb3IgPVxuICAgIC8vICAgICAgICAgbXNnLmluZGV4T2YoXCJTUUxJVEUuQUxMIC0gRGF0YWJhc2UgRXJyb3I1XCIpICE9PSAtMTtcbiAgICAvL1xuICAgIC8vICAgICAvLyB1bmFibGUgdG8gYmVnaW4gdHJhbnNhY3Rpb24gKDUgZGF0YWJhc2UgaXMgbG9ja2VkKVxuICAgIC8vICAgICBjb25zdCBoYXNDYXBTcWxFcnJvciA9IG1zZy5pbmRleE9mKFwiNSBkYXRhYmFzZSBpcyBsb2NrZWRcIikgIT09IC0xO1xuICAgIC8vXG4gICAgLy8gICAgIGlmIChoYXNOc1NxbEVycm9yIHx8IGhhc0NhcFNxbEVycm9yKSByZXR1cm4gdHJ1ZTtcbiAgICAvL1xuICAgIC8vICAgICBjb25zb2xlLmxvZyhgV2ViU1FMOiBGb3VuZCBlcnJvciBtZXNzYWdlIHRoYXQgaXNuJ3QgYSBsb2NrIDogJHttc2d9YCk7XG4gICAgLy8gICAgIHJldHVybiBmYWxzZTtcbiAgICAvLyB9XG59XG4iXX0=