sq3-kv-data-store
Version:
Node.js key/value store for SQLITE3 that includes data search features
344 lines • 35.6 kB
JavaScript
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==