@synerty/vortexjs
Version:
Custom observable data serialisation and routing based on Angular 2+
144 lines • 21.3 kB
JavaScript
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FwLXNxbC1hcGkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvdm9ydGV4L3N0b3JhZ2UtYXBpL2NhcC1zcWwtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM1QyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFM0MsT0FBTyxFQUNILGVBQWUsRUFFZixnQkFBZ0IsR0FDbkIsTUFBTSw2QkFBNkIsQ0FBQztBQUNyQyxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBa0IsTUFBTSxlQUFlLENBQUM7QUFDbEUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFHdkMsV0FBTSxTQUFTLEdBQWYsTUFBTSxTQUFVLFNBQVEsU0FBUztJQUM1QixnQkFBZ0IsR0FBZSxJQUFJLENBQUM7SUFDcEMsaUJBQWlCLEdBQTRCLElBQUksQ0FBQztJQUUxRCxZQUF3QixNQUFjLEVBQWMsUUFBa0I7UUFDbEUsS0FBSyxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRUQsSUFBWSxTQUFTO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUNuQixDQUFDO0lBRUQsSUFBWSxTQUFTLENBQUMsR0FBdUI7UUFDekMsSUFBSSxDQUFDLEVBQUUsR0FBRyxHQUFHLENBQUM7SUFDbEIsQ0FBQztJQUVELEtBQUssQ0FBQyxNQUFNO1FBQ1IsT0FBTyxJQUFJLENBQUMsRUFBRSxJQUFJLElBQUksQ0FBQztJQUMzQixDQUFDO0lBRUQsS0FBSyxDQUFDLEtBQUs7UUFDUCxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1FBQ25ELElBQUksQ0FBQyxFQUFFLEdB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LENBQUMsQ0FBQTtJQUFrQixXQUFBLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQTtHQUoxQyxTQUFTLENBNk1yQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdCB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBDYXBhY2l0b3IgfSBmcm9tIFwiQGNhcGFjaXRvci9jb3JlXCI7XG5pbXBvcnQgeyBEZXZpY2UgfSBmcm9tIFwiQGNhcGFjaXRvci9kZXZpY2VcIjtcblxuaW1wb3J0IHtcbiAgICBDYXBhY2l0b3JTUUxpdGUsXG4gICAgY2FwU1FMaXRlU2V0LFxuICAgIFNRTGl0ZUNvbm5lY3Rpb24sXG59IGZyb20gXCJAY2FwYWNpdG9yLWNvbW11bml0eS9zcWxpdGVcIjtcbmltcG9ydCB7IHJhbmRvbSwgU3FsQXBpQUJDLCBTcWxFeGVjdXRlRGF0YSB9IGZyb20gXCIuL3NxbC1hcGktYWJjXCI7XG5pbXBvcnQgeyBhc3NlcnQsIGRhdGVTdHIgfSBmcm9tIFwiLi4vVXRpbE1pc2NcIjtcbmltcG9ydCB7IFNRTGl0ZURCQ29ubmVjdGlvbiB9IGZyb20gXCJAY2FwYWNpdG9yLWNvbW11bml0eS9zcWxpdGVcIjtcblxuZXhwb3J0IGNsYXNzIENhcFNxbEFwaSBleHRlbmRzIFNxbEFwaUFCQyB7XG4gICAgcHJpdmF0ZSBfQ2FwYWNpdG9yU1FMaXRlOiBhbnkgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIF9zcWxpdGVDb25uZWN0aW9uOiBTUUxpdGVDb25uZWN0aW9uIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdHJ1Y3RvcihASW5qZWN0KFwiXCIpIGRiTmFtZTogc3RyaW5nLCBASW5qZWN0KFtdKSBkYlNjaGVtYTogc3RyaW5nW10pIHtcbiAgICAgICAgc3VwZXIoZGJOYW1lLCBkYlNjaGVtYSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXQgY2FwRGJDb25uKCk6IFNRTGl0ZURCQ29ubmVjdGlvbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmRiO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2V0IGNhcERiQ29ubih2YWw6IFNRTGl0ZURCQ29ubmVjdGlvbikge1xuICAgICAgICB0aGlzLmRiID0gdmFsO1xuICAgIH1cblxuICAgIGFzeW5jIGlzT3BlbigpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGIgIT0gbnVsbDtcbiAgICB9XG5cbiAgICBhc3luYyBjbG9zZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXdhaXQgdGhpcy5fc3FsaXRlQ29ubmVjdGlvbi5jbG9zZUFsbENvbm5lY3Rpb25zKCk7XG4gICAgICAgIHRoaXMuZGIgPSBudWxsO1xuICAgICAgICB0aGlzLl9DYXBhY2l0b3JTUUxpdGUgPSBudWxsO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBhc3luYyBfb3BlbkRiKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBpZiAoYXdhaXQgdGhpcy5pc09wZW4oKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIC8vIFdhaXQgZm9yIHRoZSBwbGF0Zm9ybSB0byBpbml0aWFsaXNlXG4gICAgICAgIGNvbnN0IGluZm8gPSBhd2FpdCBEZXZpY2UuZ2V0SW5mbygpO1xuXG4gICAgICAgIC8vIEdldCB0aGUgcGx1Z2luXG4gICAgICAgIGNvbnNvbGUubG9nKGAke2RhdGVTdHIoKX0gKioqIHBsYXRmb3JtICR7aW5mby5wbGF0Zm9ybX1gKTtcbiAgICAgICAgdGhpcy5fQ2FwYWNpdG9yU1FMaXRlID0gQ2FwYWNpdG9yU1FMaXRlO1xuXG4gICAgICAgIGlmIChDYXBhY2l0b3IuZ2V0UGxhdGZvcm0oKSA9PT0gXCJhbmRyb2lkXCIpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5fQ2FwYWNpdG9yU1FMaXRlLnJlcXVlc3RQZXJtaXNzaW9ucygpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRoaXMgYXBwIGNhbid0IHdvcmsgd2l0aG91dCBEYXRhYmFzZSBhY2Nlc3MuXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fc3FsaXRlQ29ubmVjdGlvbiA9IG5ldyBTUUxpdGVDb25uZWN0aW9uKHRoaXMuX0NhcGFjaXRvclNRTGl0ZSk7XG5cbiAgICAgICAgLy8gVGhlIHBsdWdpbiBrZWVwcyBhIHNpbmdsZXRvbiBjb25uZWN0aW9uIHBlciBEQiBuYW1lIGFjcm9zcyBhbGxcbiAgICAgICAgLy8gQ2FwU3FsQXBpIGluc3RhbmNlcy4gV2l0aG91dCBpc29sYXRpb24sIHR3byBjYWxsZXJzIGNhbiBib3RoIHNlZVxuICAgICAgICAvLyBpc0Nvbm5lY3Rpb249ZmFsc2UgYW5kIGJvdGggY2FsbCBjcmVhdGVDb25uZWN0aW9uIOKAlCB0aGUgc2Vjb25kXG4gICAgICAgIC8vIHRocm93cyBcIkNvbm5lY3Rpb24gPGRiTmFtZT4gYWxyZWFkeSBleGlzdHNcIi4gRmFsbCBiYWNrIHRvXG4gICAgICAgIC8vIHJldHJpZXZlQ29ubmVjdGlvbiBpbiB0aGF0IGNhc2UuXG4gICAgICAgIGF3YWl0IHRoaXMuX2FjcXVpcmVDb25uZWN0aW9uKHRoaXMuZGJOYW1lKTtcblxuICAgICAgICBjb25zdCBkYk9wZW4gPSBhd2FpdCB0aGlzLmNhcERiQ29ubi5pc0RCT3BlbigpO1xuICAgICAgICBpZiAoZGJPcGVuPy5yZXN1bHQgIT09IHRydWUpIHtcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuY2FwRGJDb25uLm9wZW4oKTtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB0aGlzLmluc3RhbGxTY2hlbWEoKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9hY3F1aXJlQ29ubmVjdGlvbihkYk5hbWU6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBleGlzdGluZyA9IGF3YWl0IHRoaXMuX3NxbGl0ZUNvbm5lY3Rpb24uaXNDb25uZWN0aW9uKFxuICAgICAgICAgICAgZGJOYW1lLFxuICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICk7XG4gICAgICAgIGlmIChleGlzdGluZz8ucmVzdWx0ID09PSB0cnVlKSB7XG4gICAgICAgICAgICB0aGlzLmNhcERiQ29ubiA9IGF3YWl0IHRoaXMuX3NxbGl0ZUNvbm5lY3Rpb24ucmV0cmlldmVDb25uZWN0aW9uKFxuICAgICAgICAgICAgICAgIGRiTmFtZSxcbiAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMuY2FwRGJDb25uID0gYXdhaXQgdGhpcy5fc3FsaXRlQ29ubmVjdGlvbi5jcmVhdGVDb25uZWN0aW9uKFxuICAgICAgICAgICAgICAgIGRiTmFtZSxcbiAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgICBcIm5vLWVuY3J5cHRpb25cIixcbiAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gRGVmZW5jZS1pbi1kZXB0aDogaWYgY3JlYXRlQ29ubmVjdGlvbiBzdGlsbCByYWNlcyBwYXN0IHRoZVxuICAgICAgICAgICAgLy8gbG9jayAoZS5nLiBhbm90aGVyIGNvZGUgcGF0aCBieXBhc3NlZCBDYXBTcWxBcGkpLCBmYWxsIGJhY2tcbiAgICAgICAgICAgIC8vIHRvIHJldHJpZXZpbmcgdGhlIGV4aXN0aW5nIGNvbm5lY3Rpb24uXG4gICAgICAgICAgICBjb25zdCBtc2cgPSB0eXBlb2YgZSA9PT0gXCJzdHJpbmdcIiA/IGUgOiAoZSBhcyBFcnJvcik/Lm1lc3NhZ2U7XG4gICAgICAgICAgICBpZiAobXNnICYmIG1zZy5pbmRleE9mKFwiYWxyZWFkeSBleGlzdHNcIikgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jYXBEYkNvbm4gPVxuICAgICAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLl9zcWxpdGVDb25uZWN0aW9uLnJldHJpZXZlQ29ubmVjdGlvbihcbiAgICAgICAgICAgICAgICAgICAgICAgIGRiTmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBhc3luYyB0cmFuc2FjdGlvbihcbiAgICAgICAgZXhlY3V0ZURhdGE6IFNxbEV4ZWN1dGVEYXRhW10sXG4gICAgICAgIGlzUXVlcnk6IGJvb2xlYW5cbiAgICApOiBQcm9taXNlPGFueVtdIHwgbnVsbD4ge1xuICAgICAgICBpZiAoIShhd2FpdCB0aGlzLmlzT3BlbigpKSkgYXdhaXQgdGhpcy5vcGVuKCk7XG5cbiAgICAgICAgbGV0IHJldHJpZXMgPSA1O1xuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5fdHJhbnNhY3Rpb25Jbm5lcihleGVjdXRlRGF0YSwgaXNRdWVyeSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICByZXRyaWVzID49IDBcbiAgICAgICAgICAgICAgICAgICAgLyogJiZcbiAgICAgICAgICAgICAgICAgICAgIChDYXBTcWxBcGkuY2hlY2tSZXRyeU1lc3NhZ2UoZSkgfHxcbiAgICAgICAgICAgICAgICAgICAgIENhcFNxbEFwaS5pc0xvY2tlZE1zZyhlKSkgKi9cbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0cmllcy0tO1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocikgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gcigpLCAxMDAgKyByYW5kb20oKSlcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBfdHJhbnNhY3Rpb25Jbm5lcihcbiAgICAgICAgZXhlY3V0ZURhdGE6IFNxbEV4ZWN1dGVEYXRhW10sXG4gICAgICAgIGlzUXVlcnk6IGJvb2xlYW5cbiAgICApOiBQcm9taXNlPGFueVtdIHwgbnVsbD4ge1xuICAgICAgICBpZiAoaXNRdWVyeSkgcmV0dXJuIGF3YWl0IHRoaXMuX3RyYW5zYWN0aW9uSW5uZXJRdWVyeShleGVjdXRlRGF0YSk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5fdHJhbnNhY3Rpb25Jbm5lckV4ZWN1dGUoZXhlY3V0ZURhdGEpO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3RyYW5zYWN0aW9uSW5uZXJRdWVyeShcbiAgICAgICAgZXhlY3V0ZURhdGE6IFNxbEV4ZWN1dGVEYXRhW11cbiAgICApOiBQcm9taXNlPGFueVtdIHwgbnVsbD4ge1xuICAgICAgICBhc3NlcnQoXG4gICAgICAgICAgICBleGVjdXRlRGF0YS5sZW5ndGggPT09IDEsXG4gICAgICAgICAgICBcIldlIGV4cGVjdCBleGVjdXRlRGF0YS5sZW5ndGggPT09IDEgZm9yIGEgcXVlcnlcIlxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IGRhdGEgPSAoXG4gICAgICAgICAgICBhd2FpdCB0aGlzLmNhcERiQ29ubi5xdWVyeShcbiAgICAgICAgICAgICAgICBleGVjdXRlRGF0YVswXS5zcWwsXG4gICAgICAgICAgICAgICAgZXhlY3V0ZURhdGFbMF0uYmluZFBhcmFtc1xuICAgICAgICAgICAgKVxuICAgICAgICApPy52YWx1ZXM7XG5cbiAgICAgICAgcmV0dXJuIGRhdGE/Lmxlbmd0aCA/IGRhdGEgOiBudWxsO1xuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX3RyYW5zYWN0aW9uSW5uZXJFeGVjdXRlKFxuICAgICAgICBleGVjdXRlRGF0YTogU3FsRXhlY3V0ZURhdGFbXVxuICAgICk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBjYXBEYXRhOiBBcnJheTxjYXBTUUxpdGVTZXQ+ID0gW107XG4gICAgICAgIGNvbnN0IHNxbE9ubHlMaXN0OiBzdHJpbmdbXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IGRhdGEgb2YgZXhlY3V0ZURhdGEpIHtcbiAgICAgICAgICAgIGlmICghZGF0YS5iaW5kUGFyYW1zPy5sZW5ndGggLyogbnVsbCBvciAwICovKSB7XG4gICAgICAgICAgICAgICAgc3FsT25seUxpc3QucHVzaChkYXRhLnNxbCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNhcERhdGEucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIHN0YXRlbWVudDogZGF0YS5zcWwsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlczogZGF0YS5iaW5kUGFyYW1zLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChjb25zdCBzcWwgb2Ygc3FsT25seUxpc3QpIHtcbiAgICAgICAgICAgIC8vIEp1c3QgZXhlY3V0ZSBpdCwgdXN1YWxseSBpZiB3ZSB3YW50IGEgdHJhbnNhY3Rpb24gd2UncmVcbiAgICAgICAgICAgIC8vIG9ubHkgaW5zZXJ0aW5nIGxvdHMgb2YgZGF0YS5cbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuY2FwRGJDb25uLnJ1bihzcWwpO1xuICAgICAgICAgICAgaWYgKHJlc3VsdC5jaGFuZ2VzLmNoYW5nZXMgPT09IC0xKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkFuIGVycm9yIG9jY3VycmVkIGluIHRoZSBTUUxcIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2FwRGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuY2FwRGJDb25uLmV4ZWN1dGVTZXQoY2FwRGF0YSk7XG4gICAgICAgICAgICBpZiAocmVzdWx0LmNoYW5nZXMuY2hhbmdlcyA9PT0gLTEpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQW4gZXJyb3Igb2NjdXJyZWQgaW4gdGhlIFNRTFwiKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIHByaXZhdGUgc3RhdGljIGNoZWNrUmV0cnlNZXNzYWdlKG1lc3NhZ2U6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIC8vICAgICBpZiAobWVzc2FnZS5pbmRleE9mKFJFVFJZX05PX1NQQUNFKSAhPT0gLTEpIHJldHVybiB0cnVlO1xuICAgIC8vXG4gICAgLy8gICAgIHJldHVybiBtZXNzYWdlLmluZGV4T2YoUkVUUllfRElTS19FUlJPUikgIT09IC0xO1xuICAgIC8vIH1cbiAgICAvL1xuICAgIC8vIHByaXZhdGUgc3RhdGljIGlzTG9ja2VkTXNnKGVycjogYW55KTogYm9vbGVhbiB7XG4gICAgLy8gICAgIGNvbnN0IG1zZyA9IGVyci50b1N0cmluZygpO1xuICAgIC8vXG4gICAgLy8gICAgIGNvbnN0IGhhc05zU3FsRXJyb3IgPVxuICAgIC8vICAgICAgICAgbXNnLmluZGV4T2YoXCJTUUxJVEUuQUxMIC0gRGF0YWJhc2UgRXJyb3I1XCIpICE9PSAtMTtcbiAgICAvL1xuICAgIC8vICAgICAvLyB1bmFibGUgdG8gYmVnaW4gdHJhbnNhY3Rpb24gKDUgZGF0YWJhc2UgaXMgbG9ja2VkKVxuICAgIC8vICAgICBjb25zdCBoYXNDYXBTcWxFcnJvciA9IG1zZy5pbmRleE9mKFwiNSBkYXRhYmFzZSBpcyBsb2NrZWRcIikgIT09IC0xO1xuICAgIC8vXG4gICAgLy8gICAgIGlmIChoYXNOc1NxbEVycm9yIHx8IGhhc0NhcFNxbEVycm9yKSByZXR1cm4gdHJ1ZTtcbiAgICAvL1xuICAgIC8vICAgICBjb25zb2xlLmxvZyhgV2ViU1FMOiBGb3VuZCBlcnJvciBtZXNzYWdlIHRoYXQgaXNuJ3QgYSBsb2NrIDogJHttc2d9YCk7XG4gICAgLy8gICAgIHJldHVybiBmYWxzZTtcbiAgICAvLyB9XG59XG4iXX0=