UNPKG

sq3-kv-data-store

Version:

Node.js key/value store for SQLITE3 that includes data search features

344 lines 35.6 kB
import util from 'node:util'; import sqlite3 from 'sqlite3'; import { selectors2where } from './finder.js'; ///////////////////// Create a table export class SQ3DataStore { #DB; #tablenm; #indexnm; constructor(DB, tablenm) { if (typeof DB === 'object' && DB instanceof sqlite3.Database) { this.#DB = DB; } else if (typeof DB === 'string') { this.#DB = new sqlite3.Database(DB); } else { this.#DB = new sqlite3.Database(':memory:'); } // this.#DB.on('trace', (sql) => { // console.log(`TRACE: ${sql}`); // }); this.#tablenm = tablenm; this.#indexnm = `kv_index_${this.#tablenm}`; this.#DB.exec(` CREATE TABLE ${this.#tablenm} ( key TEXT PRIMARY KEY, value TEXT ) WITHOUT ROWID; CREATE UNIQUE INDEX ${this.#indexnm} ON ${this.#tablenm} (key); `, (err) => { if (err) { console.error(`******** Could not create database ${this.#tablenm}`); } }); } get DB() { return this.#DB; } // This can be useful for debugging. // This SQLITE query retrieves the table listing // all the existing tables. // async tables() { // const rows = await new Promise((resolve, reject) => { // this.#DB.all(` // SELECT * FROM sqlite_master; // `, {}, // (err, rows) => { // if (err) { // console.error(`put ERROR `, err.stack); // reject(err); // } else { // resolve(rows); // } // }); // }); // return rows; // } async put(key, value) { // insert into ... // console.log(`before get ${key}`); const update = await this.get(key); // console.log(`put ${key} got value ${util.inspect(update)}`); if (update) { return this.update(key, value); } // console.log(`to put ${key}`, value); await new Promise((resolve, reject) => { this.#DB.run(` INSERT INTO "${this.#tablenm}" ( key, value ) VALUES ( $key, $value ) `, { $key: key, $value: JSON.stringify(value) }, (err) => { if (err) { console.error(`put ERROR `, err.stack); reject(err); } else { resolve(undefined); } }); }); // console.log(`did put ${key}`); } async update(key, value) { // console.log(`to update ${key}`, value); const that = this; const result = await new Promise((resolve, reject) => { that.#DB.run(` UPDATE ${this.#tablenm} SET value = $value WHERE key = $key `, { $key: key, $value: JSON.stringify(value) }, (err) => { if (err) { console.error(`update ERROR`, err.stack); reject(err); } else resolve(undefined); }); }); // console.log(`updated ${key}`); } async get(key) { // ... get item from table // console.log(`get ${key}`); const that = this; const result = await new Promise((resolve, reject) => { that.#DB.all(` SELECT value FROM ${this.#tablenm} WHERE key = $key `, { // $tablenm: this.#tablenm, $key: key }, (err, rows) => { if (err) reject(err); else resolve(rows); }); }); // console.log(`got ${key}`, result); if (Array.isArray(result) && result.length === 1) { const v1 = result[0]; if (typeof v1 === 'object' && 'value' in v1 && typeof v1['value'] === 'string') { return JSON.parse(v1['value']); } else { throw new Error(`Database had incorrect value field for ${key} ${util.inspect(v1)}`); } } else if (Array.isArray(result) && result.length > 1) { throw new Error(`Got more than one item for ${key} -- ${util.inspect(result)}`); } return undefined; } /** * Determines whether the database contains an item * with the given key. * * @param key * @returns true if an item exists, false otherwise */ async exists(key) { if (!this.#DB) { throw new Error("Database not initialized"); } const that = this; const result = await new Promise((resolve, reject) => { that.#DB.all(` SELECT 1 FROM ${this.#tablenm} WHERE key = $key `, { $key: key }, (err, rows) => { if (err) reject(err); else resolve(rows); }); }); if (Array.isArray(result) && result.length === 1) { return true; } else if (Array.isArray(result) && result.length > 1) { return false; } return false; } /** * Fetch the keys used in the table. Optionally the * pattern parameter is the type of pattern used * in an SQL LIKE clause. * @param pattern An SQL LIKE pattern specifier * @returns Either all keys, or the ones matching the pattern */ async keys(pattern) { if (!this.#DB) { throw new Error("Database not initialized"); } const that = this; const result = await new Promise((resolve, reject) => { // This is a big funky - BUT - // We can either query where "pattern" is a LIKE pattern // or we query for all keys. // That means we have two choices of query string // and two choices of the values object. that.#DB.all(typeof pattern === 'string' ? ` SELECT DISTINCT key FROM ${this.#tablenm} WHERE key LIKE $pattern ` : ` SELECT DISTINCT key FROM ${this.#tablenm} `, typeof pattern === 'string' ? { $pattern: pattern } : {}, (err, rows) => { if (err) reject(err); else resolve(rows.map((item) => { return item.key; })); }); }); if (Array.isArray(result)) { return result; } else { return []; } } /** * * [ * { '$.foo.bar': 'value' }, * { '$.foo.bar1': 'value1' }, * { '$OR': [ * { '$.foo.zab': { gt: 'value } } * ] } * ] * * * { * '$.foo.bar': 'value', * '$.foo.bar1': 'value1' * '$.foo.bar2': { lt: 'value' }, * '$OR': [ * ] * } * * @param selector */ async find(selectors) { let where = selectors2where(selectors); // An empty selector should return all items if (!(where && typeof where === 'string' && where.length >= 1)) { return this.findAll(); } // console.log(`${util.inspect(selectors)} ==> ${where}`); const query = ` SELECT key, value FROM ${this.#tablenm} WHERE ${where} `; // console.log(query); try { const that = this; const rows = await new Promise((resolve, reject) => { that.#DB.all(query, {}, (err, rows) => { if (err) reject(err); else resolve(rows); }); }); // console.log(`find ${util.inspect(rows)}`); return rows.map(row => { return JSON.parse(row.value); }); } catch (err) { console.log(`find ERROR `, err.stack); throw err; } } async findAll() { const query = ` SELECT key, value FROM ${this.#tablenm} `; const that = this; const rows = await new Promise((resolve, reject) => { that.#DB.all(query, {}, (err, rows) => { if (err) reject(err); else resolve(rows); }); }); return rows.map(row => { return JSON.parse(row.value); }); } async delete(key) { // .. delete item from table await new Promise((resolve, reject) => { this.#DB.run(` DELETE FROM ${this.#tablenm} WHERE key = $key `, { // $tablenm: this.#tablenm, $key: key }, (err) => { if (err) { console.error(`delete ERROR`, err.stack); reject(err); } else { resolve(undefined); } }); }); } async drop() { // ... DROP TABLE await new Promise((resolve, reject) => { this.#DB.run(` DROP TABLE ${this.#tablenm} `, {}, (err) => { if (err) { console.error(`delete ERROR`, err.stack); reject(err); } else { resolve(undefined); } }); }); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQzdCLE9BQU8sT0FBTyxNQUFNLFNBQVMsQ0FBQztBQUM5QixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRTlDLG9DQUFvQztBQUVwQyxNQUFNLE9BQU8sWUFBWTtJQUVyQixHQUFHLENBQW1CO0lBQ3RCLFFBQVEsQ0FBUztJQUNqQixRQUFRLENBQVM7SUFFakIsWUFDSSxFQUE2QixFQUM3QixPQUFlO1FBR2YsSUFBSSxPQUFPLEVBQUUsS0FBSyxRQUFRO2VBQ3RCLEVBQUUsWUFBWSxPQUFPLENBQUMsUUFBUSxFQUNoQyxDQUFDO1lBQ0MsSUFBSSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUM7UUFDbEIsQ0FBQzthQUFNLElBQUksT0FBTyxFQUFFLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDaEMsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDeEMsQ0FBQzthQUFNLENBQUM7WUFDSixJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNoRCxDQUFDO1FBRUQsa0NBQWtDO1FBQ2xDLG9DQUFvQztRQUNwQyxNQUFNO1FBRU4sSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUM7UUFDeEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxZQUFZLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUU1QyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQzsyQkFDSyxJQUFJLENBQUMsUUFBUTs7OztrQ0FJTixJQUFJLENBQUMsUUFBUTtxQkFDMUIsSUFBSSxDQUFDLFFBQVE7U0FDekIsRUFDRCxDQUFDLEdBQUcsRUFBRSxFQUFFO1lBQ0os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QUN2QixDQUFDO1lBQ0wsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxLQUFLLENBQUMsSUFBSTtRQUdOLGlCQUFpQjtRQUNqQixNQUFNLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ2xDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDOzZCQUNJLElBQUksQ0FBQyxRQUFRO2FBQzdCLEVBQUUsRUFBRyxFQUNOLENBQUMsR0FBRyxFQUFFLEVBQUU7Z0JBQ0osSUFBSSxHQUFHLEVBQUUsQ0FBQztvQkFDTixPQUFPLENBQUMsS0FBSyxDQUFDLGNBQWMsRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQ3pDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDaEIsQ0FBQztxQkFBTSxDQUFDO29CQUNKLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDdkIsQ0FBQztZQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ1AsQ0FBQyxDQUFDLENBQUM7SUFDUCxDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyJcbmltcG9ydCB1dGlsIGZyb20gJ25vZGU6dXRpbCc7XG5pbXBvcnQgc3FsaXRlMyBmcm9tICdzcWxpdGUzJztcbmltcG9ydCB7IHNlbGVjdG9yczJ3aGVyZSB9IGZyb20gJy4vZmluZGVyLmpzJztcblxuLy8vLy8vLy8vLy8vLy8vLy8vLy8vIENyZWF0ZSBhIHRhYmxlXG5cbmV4cG9ydCBjbGFzcyBTUTNEYXRhU3RvcmUge1xuXG4gICAgI0RCOiBzcWxpdGUzLkRhdGFiYXNlO1xuICAgICN0YWJsZW5tOiBzdHJpbmc7XG4gICAgI2luZGV4bm06IHN0cmluZztcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBEQjogc3FsaXRlMy5EYXRhYmFzZSB8IHN0cmluZyxcbiAgICAgICAgdGFibGVubTogc3RyaW5nXG4gICAgKSB7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBEQiA9PT0gJ29iamVjdCdcbiAgICAgICAgICYmIERCIGluc3RhbmNlb2Ygc3FsaXRlMy5EYXRhYmFzZVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHRoaXMuI0RCID0gREI7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIERCID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhpcy4jREIgPSBuZXcgc3FsaXRlMy5EYXRhYmFzZShEQik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLiNEQiA9IG5ldyBzcWxpdGUzLkRhdGFiYXNlKCc6bWVtb3J5OicpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gdGhpcy4jREIub24oJ3RyYWNlJywgKHNxbCkgPT4ge1xuICAgICAgICAvLyAgICAgY29uc29sZS5sb2coYFRSQUNFOiAke3NxbH1gKTtcbiAgICAgICAgLy8gfSk7XG5cbiAgICAgICAgdGhpcy4jdGFibGVubSA9IHRhYmxlbm07XG4gICAgICAgIHRoaXMuI2luZGV4bm0gPSBga3ZfaW5kZXhfJHt0aGlzLiN0YWJsZW5tfWA7XG5cbiAgICAgICAgdGhpcy4jREIuZXhlYyhgXG4gICAgICAgICAgICBDUkVBVEUgVEFCTEUgJHt0aGlzLiN0YWJsZW5tfSAoXG4gICAgICAgICAgICAgICAga2V5IFRFWFQgUFJJTUFSWSBLRVksXG4gICAgICAgICAgICAgICAgdmFsdWUgVEVYVFxuICAgICAgICAgICAgKSBXSVRIT1VUIFJPV0lEO1xuICAgICAgICAgICAgQ1JFQVRFIFVOSVFVRSBJTkRFWCAke3RoaXMuI2luZGV4bm19XG4gICAgICAgICAgICAgICAgT04gJHt0aGlzLiN0YWJsZW5tfSAoa2V5KTtcbiAgICAgICAgYCxcbiAgICAgICAgKGVycikgPT4ge1xuICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYCoqKioqKioqIENvdWxkIG5vdCBjcmVhdGUgZGF0YWJhc2UgJHt0aGlzLiN0YWJsZW5tfWApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIH1cblxuICAgIGdldCBEQigpOiBzcWxpdGUzLkRhdGFiYXNlIHsgcmV0dXJuIHRoaXMuI0RCOyB9XG5cbiAgICAvLyBUaGlzIGNhbiBiZSB1c2VmdWwgZm9yIGRlYnVnZ2luZy5cbiAgICAvLyBUaGlzIFNRTElURSBxdWVyeSByZXRyaWV2ZXMgdGhlIHRhYmxlIGxpc3RpbmdcbiAgICAvLyBhbGwgdGhlIGV4aXN0aW5nIHRhYmxlcy5cblxuICAgIC8vIGFzeW5jIHRhYmxlcygpIHtcbiAgICAvLyAgICAgY29uc3Qgcm93cyA9IGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAvLyAgICAgICAgIHRoaXMuI0RCLmFsbChgXG4gICAgLy8gICAgICAgICAgICAgU0VMRUNUICogRlJPTSBzcWxpdGVfbWFzdGVyO1xuICAgIC8vICAgICAgICAgYCwge30sXG4gICAgLy8gICAgICAgICAoZXJyLCByb3dzKSA9PiB7XG4gICAgLy8gICAgICAgICAgICAgaWYgKGVycikge1xuICAgIC8vICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBwdXQgRVJST1IgYCwgZXJyLnN0YWNrKTtcbiAgICAvLyAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgLy8gICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAvLyAgICAgICAgICAgICAgICAgcmVzb2x2ZShyb3dzKTtcbiAgICAvLyAgICAgICAgICAgICB9XG4gICAgLy8gICAgICAgICB9KTtcbiAgICAvLyAgICAgfSk7XG4gICAgLy8gICAgIHJldHVybiByb3dzO1xuICAgIC8vIH1cblxuICAgIGFzeW5jIHB1dChrZXk6IHN0cmluZywgdmFsdWU6IGFueSlcbiAgICAgICAgOiBQcm9taXNlPHZvaWQ+XG4gICAge1xuICAgICAgICAvLyBpbnNlcnQgaW50byAuLi5cbiAgICAgICAgLy8gY29uc29sZS5sb2coYGJlZm9yZSBnZXQgJHtrZXl9YCk7XG4gICAgICAgIGNvbnN0IHVwZGF0ZSA9IGF3YWl0IHRoaXMuZ2V0KGtleSk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGBwdXQgJHtrZXl9IGdvdCB2YWx1ZSAke3V0aWwuaW5zcGVjdCh1cGRhdGUpfWApO1xuICAgICAgICBpZiAodXBkYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy51cGRhdGUoa2V5LCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gY29uc29sZS5sb2coYHRvIHB1dCAke2tleX1gLCB2YWx1ZSk7XG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuI0RCLnJ1bihgXG4gICAgICAgICAgICAgICAgSU5TRVJUIElOVE8gXCIke3RoaXMuI3RhYmxlbm19XCJcbiAgICAgICAgICAgICAgICAoIGtleSwgdmFsdWUgKVxuICAgICAgICAgICAgICAgIFZBTFVFUyAoXG4gICAgICAgICAgICAgICAgICAgICRrZXksICR2YWx1ZVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgIGAsIHtcbiAgICAgICAgICAgICAgICAka2V5OiBrZXksXG4gICAgICAgICAgICAgICAgJHZhbHVlOiBKU09OLnN0cmluZ2lmeSh2YWx1ZSlcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAoZXJyKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBwdXQgRVJST1IgYCwgZXJyLnN0YWNrKTtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KSBcbiAgICAgICAgLy8gY29uc29sZS5sb2coYGRpZCBwdXQgJHtrZXl9YCk7XG4gICAgfVxuXG4gICAgYXN5bmMgdXBkYXRlKGtleTogc3RyaW5nLCB2YWx1ZTogYW55KVxuICAgICAgICA6IFByb21pc2U8dm9pZD5cbiAgICB7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGB0byB1cGRhdGUgJHtrZXl9YCwgdmFsdWUpO1xuICAgICAgICBjb25zdCB0aGF0ID0gdGhpcztcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhhdC4jREIucnVuKGBcbiAgICAgICAgICAgICAgICBVUERBVEUgJHt0aGlzLiN0YWJsZW5tfVxuICAgICAgICAgICAgICAgICAgIFNFVCB2YWx1ZSA9ICR2YWx1ZVxuICAgICAgICAgICAgICAgICBXSEVSRSBrZXkgPSAka2V5XG4gICAgICAgICAgICBgLCB7XG4gICAgICAgICAgICAgICAgJGtleToga2V5LFxuICAgICAgICAgICAgICAgICR2YWx1ZTogSlNPTi5zdHJpbmdpZnkodmFsdWUpXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgdXBkYXRlIEVSUk9SYCwgZXJyLnN0YWNrKTtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHJlc29sdmUodW5kZWZpbmVkKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgLy8gY29uc29sZS5sb2coYHVwZGF0ZWQgJHtrZXl9YCk7XG4gICAgfVxuXG4gICAgYXN5bmMgZ2V0KGtleTogc3RyaW5nKVxuICAgICAgICA6IFByb21pc2U8YW55IHwgdW5kZWZpbmVkPlxuICAgIHtcbiAgICAgICAgLy8gLi4uIGdldCBpdGVtIGZyb20gdGFibGVcbiAgICAgICAgLy8gY29uc29sZS5sb2coYGdldCAke2tleX1gKTtcbiAgICAgICAgY29uc3QgdGhhdCA9IHRoaXM7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoYXQuI0RCLmFsbChgXG4gICAgICAgICAgICAgICAgU0VMRUNUIHZhbHVlXG4gICAgICAgICAgICAgICAgICBGUk9NICR7dGhpcy4jdGFibGVubX1cbiAgICAgICAgICAgICAgICAgV0hFUkUga2V5ID0gJGtleVxuICAgICAgICAgICAgYCwge1xuICAgICAgICAgICAgICAgIC8vICR0YWJsZW5tOiB0aGlzLiN0YWJsZW5tLFxuICAgICAgICAgICAgICAgICRrZXk6IGtleVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIChlcnIsIHJvd3MpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyKSByZWplY3QoZXJyKTtcbiAgICAgICAgICAgICAgICBlbHNlIHJlc29sdmUocm93cyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIGNvbnNvbGUubG9nKGBnb3QgJHtrZXl9YCwgcmVzdWx0KTtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVzdWx0KVxuICAgICAgICAgJiYgcmVzdWx0Lmxlbmd0aCA9PT0gMVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGNvbnN0IHYxID0gcmVzdWx0WzBdO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB2MSA9PT0gJ29iamVjdCdcbiAgICAgICAgICAgICAmJiAndmFsdWUnIGluIHYxXG4gICAgICAgICAgICAgJiYgdHlwZW9mIHYxWyd2YWx1ZSddID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEpTT04ucGFyc2UodjFbJ3ZhbHVlJ10pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERhdGFiYXNlIGhhZCBpbmNvcnJlY3QgdmFsdWUgZmllbGQgZm9yICR7a2V5fSAke3V0aWwuaW5zcGVjdCh2MSl9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShyZXN1bHQpXG4gICAgICAgICAgICAmJiByZXN1bHQubGVuZ3RoID4gMVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgR290IG1vcmUgdGhhbiBvbmUgaXRlbSBmb3IgJHtrZXl9IC0tICR7dXRpbC5pbnNwZWN0KHJlc3VsdCl9YCk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGV0ZXJtaW5lcyB3aGV0aGVyIHRoZSBkYXRhYmFzZSBjb250YWlucyBhbiBpdGVtXG4gICAgICogd2l0aCB0aGUgZ2l2ZW4ga2V5LlxuICAgICAqXG4gICAgICogQHBhcmFtIGtleSBcbiAgICAgKiBAcmV0dXJucyB0cnVlIGlmIGFuIGl0ZW0gZXhpc3RzLCBmYWxzZSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBhc3luYyBleGlzdHMoa2V5OiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgaWYgKCF0aGlzLiNEQikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRGF0YWJhc2Ugbm90IGluaXRpYWxpemVkXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0aGF0LiNEQi5hbGwoYFxuICAgICAgICAgICAgICAgIFNFTEVDVCAxXG4gICAgICAgICAgICAgICAgICBGUk9NICR7dGhpcy4jdGFibGVubX1cbiAgICAgICAgICAgICAgICAgV0hFUkUga2V5ID0gJGtleVxuICAgICAgICAgICAgICAgIGAsIHtcbiAgICAgICAgICAgICAgICAgICAgJGtleToga2V5XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAoZXJyLCByb3dzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIHJlc29sdmUocm93cyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShyZXN1bHQpXG4gICAgICAgICAmJiByZXN1bHQubGVuZ3RoID09PSAxXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShyZXN1bHQpXG4gICAgICAgICAgICAmJiByZXN1bHQubGVuZ3RoID4gMVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmV0Y2ggdGhlIGtleXMgdXNlZCBpbiB0aGUgdGFibGUuICBPcHRpb25hbGx5IHRoZVxuICAgICAqIHBhdHRlcm4gcGFyYW1ldGVyIGlzIHRoZSB0eXBlIG9mIHBhdHRlcm4gdXNlZFxuICAgICAqIGluIGFuIFNRTCBMSUtFIGNsYXVzZS5cbiAgICAgKiBAcGFyYW0gcGF0dGVybiBBbiBTUUwgTElLRSBwYXR0ZXJuIHNwZWNpZmllclxuICAgICAqIEByZXR1cm5zIEVpdGhlciBhbGwga2V5cywgb3IgdGhlIG9uZXMgbWF0Y2hpbmcgdGhlIHBhdHRlcm5cbiAgICAgKi9cbiAgICBhc3luYyBrZXlzKHBhdHRlcm4/OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgICAgIGlmICghdGhpcy4jREIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkRhdGFiYXNlIG5vdCBpbml0aWFsaXplZFwiKTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB0aGF0ID0gdGhpcztcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgLy8gVGhpcyBpcyBhIGJpZyBmdW5reSAtIEJVVCAtXG4gICAgICAgICAgICAvLyBXZSBjYW4gZWl0aGVyIHF1ZXJ5IHdoZXJlIFwicGF0dGVyblwiIGlzIGEgTElLRSBwYXR0ZXJuXG4gICAgICAgICAgICAvLyBvciB3ZSBxdWVyeSBmb3IgYWxsIGtleXMuXG4gICAgICAgICAgICAvLyBUaGF0IG1lYW5zIHdlIGhhdmUgdHdvIGNob2ljZXMgb2YgcXVlcnkgc3RyaW5nXG4gICAgICAgICAgICAvLyBhbmQgdHdvIGNob2ljZXMgb2YgdGhlIHZhbHVlcyBvYmplY3QuXG4gICAgICAgICAgICB0aGF0LiNEQi5hbGwoXG4gICAgICAgICAgICAgICAgdHlwZW9mIHBhdHRlcm4gPT09ICdzdHJpbmcnXG4gICAgICAgICAgICAgICAgPyBgXG4gICAgICAgICAgICAgICAgU0VMRUNUIERJU1RJTkNUIGtleVxuICAgICAgICAgICAgICAgICAgRlJPTSAke3RoaXMuI3RhYmxlbm19XG4gICAgICAgICAgICAgICAgIFdIRVJFIGtleSBMSUtFICRwYXR0ZXJuXG4gICAgICAgICAgICAgICAgYFxuICAgICAgICAgICAgICAgIDogYFxuICAgICAgICAgICAgICAgIFNFTEVDVCBESVNUSU5DVCBrZXlcbiAgICAgICAgICAgICAgICAgIEZST00gJHt0aGlzLiN0YWJsZW5tfVxuICAgICAgICAgICAgICAgIGAsXG4gICAgICAgICAgICAgICAgdHlwZW9mIHBhdHRlcm4gPT09ICdzdHJpbmcnXG4gICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgICRwYXR0ZXJuOiBwYXR0ZXJuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDogeyB9LFxuICAgICAgICAgICAgICAgIChlcnIsIHJvd3MpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycikgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgcmVzb2x2ZShyb3dzLm1hcCgoaXRlbTogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXRlbS5rZXlcbiAgICAgICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVzdWx0KSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFxuICAgICAqIFtcbiAgICAgKiAgeyAnJC5mb28uYmFyJzogJ3ZhbHVlJyB9LFxuICAgICAqICB7ICckLmZvby5iYXIxJzogJ3ZhbHVlMScgfSxcbiAgICAgKiAgeyAnJE9SJzogW1xuICAgICAqICAgICB7ICckLmZvby56YWInOiB7IGd0OiAndmFsdWUgfSB9XG4gICAgICogIF0gfVxuICAgICAqIF1cbiAgICAgKiBcbiAgICAgKiBcbiAgICAgKiB7XG4gICAgICogICckLmZvby5iYXInOiAndmFsdWUnLFxuICAgICAqICAnJC5mb28uYmFyMSc6ICd2YWx1ZTEnXG4gICAgICogICckLmZvby5iYXIyJzogeyBsdDogJ3ZhbHVlJyB9LFxuICAgICAqICAnJE9SJzogW1xuICAgICAqICBdXG4gICAgICogfVxuICAgICAqIFxuICAgICAqIEBwYXJhbSBzZWxlY3RvciBcbiAgICAgKi9cbiAgICBhc3luYyBmaW5kKHNlbGVjdG9yczogYW55KVxuICAgICAgICA6IFByb21pc2U8QXJyYXk8YW55PiB8IHVuZGVmaW5lZD5cbiAgICB7XG4gICAgICAgIGxldCB3aGVyZSA9IHNlbGVjdG9yczJ3aGVyZShzZWxlY3RvcnMpO1xuXG4gICAgICAgIC8vIEFuIGVtcHR5IHNlbGVjdG9yIHNob3VsZCByZXR1cm4gYWxsIGl0ZW1zXG4gICAgICAgIGlmICghKHdoZXJlXG4gICAgICAgICAgICAmJiB0eXBlb2Ygd2hlcmUgPT09ICdzdHJpbmcnXG4gICAgICAgICAgICAmJiB3aGVyZS5sZW5ndGggPj0gMSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZpbmRBbGwoKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBjb25zb2xlLmxvZyhgJHt1dGlsLmluc3BlY3Qoc2VsZWN0b3JzKX0gPT0+ICR7d2hlcmV9YCk7XG5cbiAgICAgICAgY29uc3QgcXVlcnkgPWBcbiAgICAgICAgICAgICAgICBTRUxFQ1Qga2V5LCB2YWx1ZVxuICAgICAgICAgICAgICAgICAgRlJPTSAke3RoaXMuI3RhYmxlbm19XG4gICAgICAgICAgICAgICAgIFdIRVJFICR7d2hlcmV9XG4gICAgICAgICAgICBgO1xuICAgICAgICAvLyBjb25zb2xlLmxvZyhxdWVyeSk7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuICAgICAgICAgICAgY29uc3Qgcm93cyA9IGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICB0aGF0LiNEQi5hbGwocXVlcnksIHsgfSxcbiAgICAgICAgICAgICAgICAoZXJyLCByb3dzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIHJlc29sdmUocm93cyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KSBhcyBhbnlbXTtcblxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coYGZpbmQgJHt1dGlsLmluc3BlY3Qocm93cyl9YCk7XG4gICAgICAgICAgICByZXR1cm4gcm93cy5tYXAocm93ID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShyb3cudmFsdWUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycjogYW55KSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgZmluZCBFUlJPUiBgLCBlcnIuc3RhY2spO1xuICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgYXN5bmMgZmluZEFsbCgpXG4gICAgICAgIDogUHJvbWlzZTxBcnJheTxhbnk+PlxuICAgIHtcblxuICAgICAgICBjb25zdCBxdWVyeSA9IGBcbiAgICAgICAgICAgICAgICBTRUxFQ1Qga2V5LCB2YWx1ZVxuICAgICAgICAgICAgICAgICAgRlJPTSAke3RoaXMuI3RhYmxlbm19XG4gICAgICAgICAgICBgO1xuICAgICAgICBjb25zdCB0aGF0ID0gdGhpcztcbiAgICAgICAgY29uc3Qgcm93cyA9IGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoYXQuI0RCLmFsbChxdWVyeSwgeyB9LFxuICAgICAgICAgICAgKGVyciwgcm93cykgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgIGVsc2UgcmVzb2x2ZShyb3dzKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KSBhcyBhbnlbXTtcblxuICAgICAgICByZXR1cm4gcm93cy5tYXAocm93ID0+IHtcbiAgICAgICAgICAgIHJldHVybiBKU09OLnBhcnNlKHJvdy52YWx1ZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGFzeW5jIGRlbGV0ZShrZXk6IHN0cmluZylcbiAgICAgICAgOiBQcm9taXNlPHZvaWQ+XG4gICAge1xuICAgICAgICAvLyAuLiBkZWxldGUgaXRlbSBmcm9tIHRhYmxlXG4gICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRoaXMuI0RCLnJ1bihgXG4gICAgICAgICAgICAgICAgREVMRVRFXG4gICAgICAgICAgICAgICAgICBGUk9NICR7dGhpcy4jdGFibGVubX1cbiAgICAgICAgICAgICAgICAgV0hFUkUga2V5ID0gJGtleVxuICAgICAgICAgICAgYCwge1xuICAgICAgICAgICAgICAgIC8vICR0YWJsZW5tOiB0aGlzLiN0YWJsZW5tLFxuICAgICAgICAgICAgICAgICRrZXk6IGtleVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYGRlbGV0ZSBFUlJPUmAsIGVyci5zdGFjayk7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgYXN5bmMgZHJvcCgpXG4gICAgICAgIDogUHJvbWlzZTx2b2lkPlxuICAgIHtcbiAgICAgICAgLy8gLi4uIERST1AgVEFCTEVcbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdGhpcy4jREIucnVuKGBcbiAgICAgICAgICAgICAgICBEUk9QIFRBQkxFICR7dGhpcy4jdGFibGVubX1cbiAgICAgICAgICAgIGAsIHsgfSxcbiAgICAgICAgICAgIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYGRlbGV0ZSBFUlJPUmAsIGVyci5zdGFjayk7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUodW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxufSJdfQ==