UNPKG

@decaf-ts/for-couchdb

Version:
176 lines 21.7 kB
import { PersistenceKeys } from "@decaf-ts/core"; import { CouchDBKeys } from "./constants.js"; import { DefaultSeparator } from "@decaf-ts/db-decorators"; import { CouchDBOperator } from "./query/constants.js"; /** * @description Re-authenticates a connection to CouchDB * @summary Refreshes the authentication for a CouchDB connection using the provided credentials * @param {any} con - The CouchDB connection object * @param {string} user - The username for authentication * @param {string} pass - The password for authentication * @return {Promise<any>} A promise that resolves to the authentication result * @function reAuth * @memberOf module:for-couchdb */ export async function reAuth(con, user, pass) { return con.auth(user, pass); } /** * @description Wraps a CouchDB database connection with automatic re-authentication * @summary Creates a proxy around a CouchDB database connection that automatically re-authenticates before each operation * @param {any} con - The CouchDB connection object * @param {string} dbName - The name of the database to use * @param {string} user - The username for authentication * @param {string} pass - The password for authentication * @return {any} The wrapped database connection object * @function wrapDocumentScope * @memberOf module:for-couchdb * @mermaid * sequenceDiagram * participant Client * participant wrapDocumentScope * participant DB * participant reAuth * * Client->>wrapDocumentScope: con, dbName, user, pass * wrapDocumentScope->>DB: con.use(dbName) * Note over wrapDocumentScope: Wrap DB methods with re-auth * * loop For each method (insert, get, put, destroy, find) * wrapDocumentScope->>wrapDocumentScope: Store original method * wrapDocumentScope->>wrapDocumentScope: Define new method with re-auth * end * * wrapDocumentScope->>wrapDocumentScope: Add NATIVE property with con value * wrapDocumentScope-->>Client: Return wrapped DB * * Note over Client: Later when client uses DB methods * Client->>DB: Any wrapped method call * DB->>reAuth: Authenticate before operation * reAuth-->>DB: Authentication complete * DB->>DB: Call original method * DB-->>Client: Return result */ export function wrapDocumentScope(con, dbName, user, pass) { const db = con.use(dbName); ["insert", "get", "put", "destroy", "find"].forEach((k) => { const original = db[k]; Object.defineProperty(db, k, { enumerable: false, configurable: true, value: async (...args) => { await reAuth(con, user, pass); return original.call(db, ...args); }, }); }); Object.defineProperty(db, CouchDBKeys.NATIVE, { enumerable: false, configurable: false, writable: false, value: con, }); return db; } /** * @description Tests if an attribute name is reserved in CouchDB * @summary Checks if an attribute name starts with an underscore, which indicates it's a reserved attribute in CouchDB * @param {string} attr - The attribute name to test * @return {RegExpMatchArray|null} The match result or null if no match * @function testReservedAttributes * @memberOf module:for-couchdb */ export function testReservedAttributes(attr) { const regexp = /^_.*$/g; return attr.match(regexp); } /** * @description Generates a name for a CouchDB index * @summary Creates a standardized name for a CouchDB index based on the table, attribute, compositions, and order * @param {string} attribute - The primary attribute for the index * @param {string} tableName - The name of the table * @param {string[]} [compositions] - Optional additional attributes to include in the index * @param {OrderDirection} [order] - Optional sort order for the index * @param {string} [separator=DefaultSeparator] - The separator to use between parts of the index name * @return {string} The generated index name * @function generateIndexName * @memberOf module:for-couchdb */ export function generateIndexName(attribute, tableName, compositions, order, separator = DefaultSeparator) { const attr = [PersistenceKeys.INDEX, tableName, attribute]; if (compositions) attr.push(...compositions); if (order) attr.push(order); return attr.join(separator); } /** * @description Generates a CouchDB index configuration * @summary Creates a complete CreateIndexRequest object for defining a CouchDB index based on specified parameters * @param {string} attribute - The primary attribute for the index * @param {string} tableName - The name of the table * @param {string[]} [compositions] - Optional additional attributes to include in the index * @param {OrderDirection} [order] - Optional sort order for the index * @param {string} [separator=DefaultSeparator] - The separator to use between parts of the index name * @return {CreateIndexRequest} The complete index configuration object * @function generateIndexDoc * @memberOf module:for-couchdb * @mermaid * sequenceDiagram * participant Caller * participant generateIndexDoc * participant generateIndexName * * Caller->>generateIndexDoc: attribute, tableName, compositions, order, separator * * Note over generateIndexDoc: Create partial filter selector * generateIndexDoc->>generateIndexDoc: Set up filter for tableName * * alt order is specified * Note over generateIndexDoc: Create ordered fields array * generateIndexDoc->>generateIndexDoc: Create orderProp for attribute * generateIndexDoc->>generateIndexDoc: Map compositions to ordered props * generateIndexDoc->>generateIndexDoc: Create sortedTable for table field * generateIndexDoc->>generateIndexDoc: Combine all ordered fields * else * Note over generateIndexDoc: Create simple fields array * generateIndexDoc->>generateIndexDoc: Use attribute, compositions, and table as strings * end * * generateIndexDoc->>generateIndexName: Generate index name * generateIndexName-->>generateIndexDoc: Return name * * Note over generateIndexDoc: Create final index request * generateIndexDoc-->>Caller: Return CreateIndexRequest */ export function generateIndexDoc(attribute, tableName, compositions, order, separator = DefaultSeparator) { const partialFilterSelector = {}; partialFilterSelector[CouchDBKeys.TABLE] = {}; partialFilterSelector[CouchDBKeys.TABLE][CouchDBOperator.EQUAL] = tableName; let fields; if (order) { const orderProp = {}; orderProp[attribute] = order; const sortedCompositions = (compositions || []).map((c) => { const r = {}; r[c] = order; return r; }); const sortedTable = {}; sortedTable[CouchDBKeys.TABLE] = order; fields = [orderProp, ...sortedCompositions, sortedTable]; } else { fields = [attribute, ...(compositions || []), CouchDBKeys.TABLE]; } const name = generateIndexName(attribute, tableName, compositions, order, separator); return { index: { fields: fields, // partial_filter_selector: partialFilterSelector, }, ddoc: [name, CouchDBKeys.DDOC].join(separator), name: name, }; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXRpbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFrQixlQUFlLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNqRSxPQUFPLEVBQUUsV0FBVyxFQUFFLHVCQUFvQjtBQUMxQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsZUFBZSxFQUFFLDZCQUEwQjtBQUdwRDs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLE1BQU0sQ0FBQyxHQUFRLEVBQUUsSUFBWSxFQUFFLElBQVk7SUFDL0QsT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztBQUM5QixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUNHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUMvQixHQUFRLEVBQ1IsTUFBYyxFQUNkLElBQVksRUFDWixJQUFZO0lBRVosTUFBTSxFQUFFLEdBQUcsR0FBRyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMzQixDQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtRQUN4RCxNQUFNLFFBQVEsR0FBSSxFQUEwQixDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2hELE1BQU0sQ0FBQyxjQUFjLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRTtZQUMzQixVQUFVLEVBQUUsS0FBSztZQUNqQixZQUFZLEVBQUUsSUFBSTtZQUNsQixLQUFLLEVBQUUsS0FBSyxFQUFFLEdBQUcsSUFBVyxFQUFFLEVBQUU7Z0JBQzlCLE1BQU0sTUFBTSxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7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TSxFQUFFLE1BQU07WUFDZCxrREFBa0Q7U0FDbkQ7UUFDRCxJQUFJLEVBQUUsQ0FBQyxJQUFJLEVBQUUsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7UUFDOUMsSUFBSSxFQUFFLElBQUk7S0FDWCxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9yZGVyRGlyZWN0aW9uLCBQZXJzaXN0ZW5jZUtleXMgfSBmcm9tIFwiQGRlY2FmLXRzL2NvcmVcIjtcbmltcG9ydCB7IENvdWNoREJLZXlzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBEZWZhdWx0U2VwYXJhdG9yIH0gZnJvbSBcIkBkZWNhZi10cy9kYi1kZWNvcmF0b3JzXCI7XG5pbXBvcnQgeyBDb3VjaERCT3BlcmF0b3IgfSBmcm9tIFwiLi9xdWVyeS9jb25zdGFudHNcIjtcbmltcG9ydCB7IENyZWF0ZUluZGV4UmVxdWVzdCwgTWFuZ29TZWxlY3RvciwgU29ydE9yZGVyIH0gZnJvbSBcIi4vdHlwZXNcIjtcblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gUmUtYXV0aGVudGljYXRlcyBhIGNvbm5lY3Rpb24gdG8gQ291Y2hEQlxuICogQHN1bW1hcnkgUmVmcmVzaGVzIHRoZSBhdXRoZW50aWNhdGlvbiBmb3IgYSBDb3VjaERCIGNvbm5lY3Rpb24gdXNpbmcgdGhlIHByb3ZpZGVkIGNyZWRlbnRpYWxzXG4gKiBAcGFyYW0ge2FueX0gY29uIC0gVGhlIENvdWNoREIgY29ubmVjdGlvbiBvYmplY3RcbiAqIEBwYXJhbSB7c3RyaW5nfSB1c2VyIC0gVGhlIHVzZXJuYW1lIGZvciBhdXRoZW50aWNhdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IHBhc3MgLSBUaGUgcGFzc3dvcmQgZm9yIGF1dGhlbnRpY2F0aW9uXG4gKiBAcmV0dXJuIHtQcm9taXNlPGFueT59IEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBhdXRoZW50aWNhdGlvbiByZXN1bHRcbiAqIEBmdW5jdGlvbiByZUF1dGhcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWNvdWNoZGJcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlQXV0aChjb246IGFueSwgdXNlcjogc3RyaW5nLCBwYXNzOiBzdHJpbmcpIHtcbiAgcmV0dXJuIGNvbi5hdXRoKHVzZXIsIHBhc3MpO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBXcmFwcyBhIENvdWNoREIgZGF0YWJhc2UgY29ubmVjdGlvbiB3aXRoIGF1dG9tYXRpYyByZS1hdXRoZW50aWNhdGlvblxuICogQHN1bW1hcnkgQ3JlYXRlcyBhIHByb3h5IGFyb3VuZCBhIENvdWNoREIgZGF0YWJhc2UgY29ubmVjdGlvbiB0aGF0IGF1dG9tYXRpY2FsbHkgcmUtYXV0aGVudGljYXRlcyBiZWZvcmUgZWFjaCBvcGVyYXRpb25cbiAqIEBwYXJhbSB7YW55fSBjb24gLSBUaGUgQ291Y2hEQiBjb25uZWN0aW9uIG9iamVjdFxuICogQHBhcmFtIHtzdHJpbmd9IGRiTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBkYXRhYmFzZSB0byB1c2VcbiAqIEBwYXJhbSB7c3RyaW5nfSB1c2VyIC0gVGhlIHVzZXJuYW1lIGZvciBhdXRoZW50aWNhdGlvblxuICogQHBhcmFtIHtzdHJpbmd9IHBhc3MgLSBUaGUgcGFzc3dvcmQgZm9yIGF1dGhlbnRpY2F0aW9uXG4gKiBAcmV0dXJuIHthbnl9IFRoZSB3cmFwcGVkIGRhdGFiYXNlIGNvbm5lY3Rpb24gb2JqZWN0XG4gKiBAZnVuY3Rpb24gd3JhcERvY3VtZW50U2NvcGVcbiAqIEBtZW1iZXJPZiBtb2R1bGU6Zm9yLWNvdWNoZGJcbiAqIEBtZXJtYWlkXG4gKiBzZXF1ZW5jZURpYWdyYW1cbiAqICAgcGFydGljaXBhbnQgQ2xpZW50XG4gKiAgIHBhcnRpY2lwYW50IHdyYXBEb2N1bWVudFNjb3BlXG4gKiAgIHBhcnRpY2lwYW50IERCXG4gKiAgIHBhcnRpY2lwYW50IHJlQXV0aFxuICogICBcbiAqICAgQ2xpZW50LT4+d3JhcERvY3VtZW50U2NvcGU6IGNvbiwgZGJOYW1lLCB1c2VyLCBwYXNzXG4gKiAgIHdyYXBEb2N1bWVudFNjb3BlLT4+REI6IGNvbi51c2UoZGJOYW1lKVxuICogICBOb3RlIG92ZXIgd3JhcERvY3VtZW50U2NvcGU6IFdyYXAgREIgbWV0aG9kcyB3aXRoIHJlLWF1dGhcbiAqICAgXG4gKiAgIGxvb3AgRm9yIGVhY2ggbWV0aG9kIChpbnNlcnQsIGdldCwgcHV0LCBkZXN0cm95LCBmaW5kKVxuICogICAgIHdyYXBEb2N1bWVudFNjb3BlLT4+d3JhcERvY3VtZW50U2NvcGU6IFN0b3JlIG9yaWdpbmFsIG1ldGhvZFxuICogICAgIHdyYXBEb2N1bWVudFNjb3BlLT4+d3JhcERvY3VtZW50U2NvcGU6IERlZmluZSBuZXcgbWV0aG9kIHdpdGggcmUtYXV0aFxuICogICBlbmRcbiAqICAgXG4gKiAgIHdyYXBEb2N1bWVudFNjb3BlLT4+d3JhcERvY3VtZW50U2NvcGU6IEFkZCBOQVRJVkUgcHJvcGVydHkgd2l0aCBjb24gdmFsdWVcbiAqICAgd3JhcERvY3VtZW50U2NvcGUtLT4+Q2xpZW50OiBSZXR1cm4gd3JhcHBlZCBEQlxuICogICBcbiAqICAgTm90ZSBvdmVyIENsaWVudDogTGF0ZXIgd2hlbiBjbGllbnQgdXNlcyBEQiBtZXRob2RzXG4gKiAgIENsaWVudC0+PkRCOiBBbnkgd3JhcHBlZCBtZXRob2QgY2FsbFxuICogICBEQi0+PnJlQXV0aDogQXV0aGVudGljYXRlIGJlZm9yZSBvcGVyYXRpb25cbiAqICAgcmVBdXRoLS0+PkRCOiBBdXRoZW50aWNhdGlvbiBjb21wbGV0ZVxuICogICBEQi0+PkRCOiBDYWxsIG9yaWdpbmFsIG1ldGhvZFxuICogICBEQi0tPj5DbGllbnQ6IFJldHVybiByZXN1bHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdyYXBEb2N1bWVudFNjb3BlKFxuICBjb246IGFueSxcbiAgZGJOYW1lOiBzdHJpbmcsXG4gIHVzZXI6IHN0cmluZyxcbiAgcGFzczogc3RyaW5nXG4pOiBhbnkge1xuICBjb25zdCBkYiA9IGNvbi51c2UoZGJOYW1lKTtcbiAgW1wiaW5zZXJ0XCIsIFwiZ2V0XCIsIFwicHV0XCIsIFwiZGVzdHJveVwiLCBcImZpbmRcIl0uZm9yRWFjaCgoaykgPT4ge1xuICAgIGNvbnN0IG9yaWdpbmFsID0gKGRiIGFzIFJlY29yZDxzdHJpbmcsIGFueT4pW2tdO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShkYiwgaywge1xuICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgICB2YWx1ZTogYXN5bmMgKC4uLmFyZ3M6IGFueVtdKSA9PiB7XG4gICAgICAgIGF3YWl0IHJlQXV0aChjb24sIHVzZXIsIHBhc3MpO1xuICAgICAgICByZXR1cm4gb3JpZ2luYWwuY2FsbChkYiwgLi4uYXJncyk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9KTtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRiLCBDb3VjaERCS2V5cy5OQVRJVkUsIHtcbiAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICB2YWx1ZTogY29uLFxuICB9KTtcbiAgcmV0dXJuIGRiO1xufVxuXG4vKipcbiAqIEBkZXNjcmlwdGlvbiBUZXN0cyBpZiBhbiBhdHRyaWJ1dGUgbmFtZSBpcyByZXNlcnZlZCBpbiBDb3VjaERCXG4gKiBAc3VtbWFyeSBDaGVja3MgaWYgYW4gYXR0cmlidXRlIG5hbWUgc3RhcnRzIHdpdGggYW4gdW5kZXJzY29yZSwgd2hpY2ggaW5kaWNhdGVzIGl0J3MgYSByZXNlcnZlZCBhdHRyaWJ1dGUgaW4gQ291Y2hEQlxuICogQHBhcmFtIHtzdHJpbmd9IGF0dHIgLSBUaGUgYXR0cmlidXRlIG5hbWUgdG8gdGVzdFxuICogQHJldHVybiB7UmVnRXhwTWF0Y2hBcnJheXxudWxsfSBUaGUgbWF0Y2ggcmVzdWx0IG9yIG51bGwgaWYgbm8gbWF0Y2hcbiAqIEBmdW5jdGlvbiB0ZXN0UmVzZXJ2ZWRBdHRyaWJ1dGVzXG4gKiBAbWVtYmVyT2YgbW9kdWxlOmZvci1jb3VjaGRiXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0ZXN0UmVzZXJ2ZWRBdHRyaWJ1dGVzKGF0dHI6IHN0cmluZykge1xuICBjb25zdCByZWdleHAgPSAvXl8uKiQvZztcbiAgcmV0dXJuIGF0dHIubWF0Y2gocmVnZXhwKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gR2VuZXJhdGVzIGEgbmFtZSBmb3IgYSBDb3VjaERCIGluZGV4XG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgc3RhbmRhcmRpemVkIG5hbWUgZm9yIGEgQ291Y2hEQiBpbmRleCBiYXNlZCBvbiB0aGUgdGFibGUsIGF0dHJpYnV0ZSwgY29tcG9zaXRpb25zLCBhbmQgb3JkZXJcbiAqIEBwYXJhbSB7c3RyaW5nfSBhdHRyaWJ1dGUgLSBUaGUgcHJpbWFyeSBhdHRyaWJ1dGUgZm9yIHRoZSBpbmRleFxuICogQHBhcmFtIHtzdHJpbmd9IHRhYmxlTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB0YWJsZVxuICogQHBhcmFtIHtzdHJpbmdbXX0gW2NvbXBvc2l0aW9uc10gLSBPcHRpb25hbCBhZGRpdGlvbmFsIGF0dHJpYnV0ZXMgdG8gaW5jbHVkZSBpbiB0aGUgaW5kZXhcbiAqIEBwYXJhbSB7T3JkZXJEaXJlY3Rpb259IFtvcmRlcl0gLSBPcHRpb25hbCBzb3J0IG9yZGVyIGZvciB0aGUgaW5kZXhcbiAqIEBwYXJhbSB7c3RyaW5nfSBbc2VwYXJhdG9yPURlZmF1bHRTZXBhcmF0b3JdIC0gVGhlIHNlcGFyYXRvciB0byB1c2UgYmV0d2VlbiBwYXJ0cyBvZiB0aGUgaW5kZXggbmFtZVxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgZ2VuZXJhdGVkIGluZGV4IG5hbWVcbiAqIEBmdW5jdGlvbiBnZW5lcmF0ZUluZGV4TmFtZVxuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItY291Y2hkYlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVJbmRleE5hbWUoXG4gIGF0dHJpYnV0ZTogc3RyaW5nLFxuICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgY29tcG9zaXRpb25zPzogc3RyaW5nW10sXG4gIG9yZGVyPzogT3JkZXJEaXJlY3Rpb24sXG4gIHNlcGFyYXRvciA9IERlZmF1bHRTZXBhcmF0b3Jcbik6IHN0cmluZyB7XG4gIGNvbnN0IGF0dHIgPSBbUGVyc2lzdGVuY2VLZXlzLklOREVYLCB0YWJsZU5hbWUsIGF0dHJpYnV0ZV07XG4gIGlmIChjb21wb3NpdGlvbnMpIGF0dHIucHVzaCguLi5jb21wb3NpdGlvbnMpO1xuICBpZiAob3JkZXIpIGF0dHIucHVzaChvcmRlcik7XG4gIHJldHVybiBhdHRyLmpvaW4oc2VwYXJhdG9yKTtcbn1cblxuLyoqXG4gKiBAZGVzY3JpcHRpb24gR2VuZXJhdGVzIGEgQ291Y2hEQiBpbmRleCBjb25maWd1cmF0aW9uXG4gKiBAc3VtbWFyeSBDcmVhdGVzIGEgY29tcGxldGUgQ3JlYXRlSW5kZXhSZXF1ZXN0IG9iamVjdCBmb3IgZGVmaW5pbmcgYSBDb3VjaERCIGluZGV4IGJhc2VkIG9uIHNwZWNpZmllZCBwYXJhbWV0ZXJzXG4gKiBAcGFyYW0ge3N0cmluZ30gYXR0cmlidXRlIC0gVGhlIHByaW1hcnkgYXR0cmlidXRlIGZvciB0aGUgaW5kZXhcbiAqIEBwYXJhbSB7c3RyaW5nfSB0YWJsZU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgdGFibGVcbiAqIEBwYXJhbSB7c3RyaW5nW119IFtjb21wb3NpdGlvbnNdIC0gT3B0aW9uYWwgYWRkaXRpb25hbCBhdHRyaWJ1dGVzIHRvIGluY2x1ZGUgaW4gdGhlIGluZGV4XG4gKiBAcGFyYW0ge09yZGVyRGlyZWN0aW9ufSBbb3JkZXJdIC0gT3B0aW9uYWwgc29ydCBvcmRlciBmb3IgdGhlIGluZGV4XG4gKiBAcGFyYW0ge3N0cmluZ30gW3NlcGFyYXRvcj1EZWZhdWx0U2VwYXJhdG9yXSAtIFRoZSBzZXBhcmF0b3IgdG8gdXNlIGJldHdlZW4gcGFydHMgb2YgdGhlIGluZGV4IG5hbWVcbiAqIEByZXR1cm4ge0NyZWF0ZUluZGV4UmVxdWVzdH0gVGhlIGNvbXBsZXRlIGluZGV4IGNvbmZpZ3VyYXRpb24gb2JqZWN0XG4gKiBAZnVuY3Rpb24gZ2VuZXJhdGVJbmRleERvY1xuICogQG1lbWJlck9mIG1vZHVsZTpmb3ItY291Y2hkYlxuICogQG1lcm1haWRcbiAqIHNlcXVlbmNlRGlhZ3JhbVxuICogICBwYXJ0aWNpcGFudCBDYWxsZXJcbiAqICAgcGFydGljaXBhbnQgZ2VuZXJhdGVJbmRleERvY1xuICogICBwYXJ0aWNpcGFudCBnZW5lcmF0ZUluZGV4TmFtZVxuICogICBcbiAqICAgQ2FsbGVyLT4+Z2VuZXJhdGVJbmRleERvYzogYXR0cmlidXRlLCB0YWJsZU5hbWUsIGNvbXBvc2l0aW9ucywgb3JkZXIsIHNlcGFyYXRvclxuICogICBcbiAqICAgTm90ZSBvdmVyIGdlbmVyYXRlSW5kZXhEb2M6IENyZWF0ZSBwYXJ0aWFsIGZpbHRlciBzZWxlY3RvclxuICogICBnZW5lcmF0ZUluZGV4RG9jLT4+Z2VuZXJhdGVJbmRleERvYzogU2V0IHVwIGZpbHRlciBmb3IgdGFibGVOYW1lXG4gKiAgIFxuICogICBhbHQgb3JkZXIgaXMgc3BlY2lmaWVkXG4gKiAgICAgTm90ZSBvdmVyIGdlbmVyYXRlSW5kZXhEb2M6IENyZWF0ZSBvcmRlcmVkIGZpZWxkcyBhcnJheVxuICogICAgIGdlbmVyYXRlSW5kZXhEb2MtPj5nZW5lcmF0ZUluZGV4RG9jOiBDcmVhdGUgb3JkZXJQcm9wIGZvciBhdHRyaWJ1dGVcbiAqICAgICBnZW5lcmF0ZUluZGV4RG9jLT4+Z2VuZXJhdGVJbmRleERvYzogTWFwIGNvbXBvc2l0aW9ucyB0byBvcmRlcmVkIHByb3BzXG4gKiAgICAgZ2VuZXJhdGVJbmRleERvYy0+PmdlbmVyYXRlSW5kZXhEb2M6IENyZWF0ZSBzb3J0ZWRUYWJsZSBmb3IgdGFibGUgZmllbGRcbiAqICAgICBnZW5lcmF0ZUluZGV4RG9jLT4+Z2VuZXJhdGVJbmRleERvYzogQ29tYmluZSBhbGwgb3JkZXJlZCBmaWVsZHNcbiAqICAgZWxzZVxuICogICAgIE5vdGUgb3ZlciBnZW5lcmF0ZUluZGV4RG9jOiBDcmVhdGUgc2ltcGxlIGZpZWxkcyBhcnJheVxuICogICAgIGdlbmVyYXRlSW5kZXhEb2MtPj5nZW5lcmF0ZUluZGV4RG9jOiBVc2UgYXR0cmlidXRlLCBjb21wb3NpdGlvbnMsIGFuZCB0YWJsZSBhcyBzdHJpbmdzXG4gKiAgIGVuZFxuICogICBcbiAqICAgZ2VuZXJhdGVJbmRleERvYy0+PmdlbmVyYXRlSW5kZXhOYW1lOiBHZW5lcmF0ZSBpbmRleCBuYW1lXG4gKiAgIGdlbmVyYXRlSW5kZXhOYW1lLS0+PmdlbmVyYXRlSW5kZXhEb2M6IFJldHVybiBuYW1lXG4gKiAgIFxuICogICBOb3RlIG92ZXIgZ2VuZXJhdGVJbmRleERvYzogQ3JlYXRlIGZpbmFsIGluZGV4IHJlcXVlc3RcbiAqICAgZ2VuZXJhdGVJbmRleERvYy0tPj5DYWxsZXI6IFJldHVybiBDcmVhdGVJbmRleFJlcXVlc3RcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlSW5kZXhEb2MoXG4gIGF0dHJpYnV0ZTogc3RyaW5nLFxuICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgY29tcG9zaXRpb25zPzogc3RyaW5nW10sXG4gIG9yZGVyPzogT3JkZXJEaXJlY3Rpb24sXG4gIHNlcGFyYXRvciA9IERlZmF1bHRTZXBhcmF0b3Jcbik6IENyZWF0ZUluZGV4UmVxdWVzdCB7XG4gIGNvbnN0IHBhcnRpYWxGaWx0ZXJTZWxlY3RvcjogTWFuZ29TZWxlY3RvciA9IHt9O1xuICBwYXJ0aWFsRmlsdGVyU2VsZWN0b3JbQ291Y2hEQktleXMuVEFCTEVdID0ge30gYXMgTWFuZ29TZWxlY3RvcjtcbiAgKHBhcnRpYWxGaWx0ZXJTZWxlY3RvcltDb3VjaERCS2V5cy5UQUJMRV0gYXMgTWFuZ29TZWxlY3RvcilbXG4gICAgQ291Y2hEQk9wZXJhdG9yLkVRVUFMXG4gIF0gPSB0YWJsZU5hbWU7XG4gIGxldCBmaWVsZHM6IFNvcnRPcmRlcltdO1xuICBpZiAob3JkZXIpIHtcbiAgICBjb25zdCBvcmRlclByb3A6IFNvcnRPcmRlciA9IHt9O1xuICAgIG9yZGVyUHJvcFthdHRyaWJ1dGVdID0gb3JkZXIgYXMgXCJhc2NcIiB8IFwiZGVzY1wiO1xuICAgIGNvbnN0IHNvcnRlZENvbXBvc2l0aW9uczogU29ydE9yZGVyW10gPSAoY29tcG9zaXRpb25zIHx8IFtdKS5tYXAoKGMpID0+IHtcbiAgICAgIGNvbnN0IHI6IFNvcnRPcmRlciA9IHt9O1xuICAgICAgcltjXSA9IG9yZGVyIGFzIFwiYXNjXCIgfCBcImRlc2NcIjtcbiAgICAgIHJldHVybiByO1xuICAgIH0pO1xuICAgIGNvbnN0IHNvcnRlZFRhYmxlOiBTb3J0T3JkZXIgPSB7fTtcbiAgICBzb3J0ZWRUYWJsZVtDb3VjaERCS2V5cy5UQUJMRV0gPSBvcmRlciBhcyBcImFzY1wiIHwgXCJkZXNjXCI7XG4gICAgZmllbGRzID0gW29yZGVyUHJvcCwgLi4uc29ydGVkQ29tcG9zaXRpb25zLCBzb3J0ZWRUYWJsZV07XG4gIH0gZWxzZSB7XG4gICAgZmllbGRzID0gW2F0dHJpYnV0ZSwgLi4uKGNvbXBvc2l0aW9ucyB8fCBbXSksIENvdWNoREJLZXlzLlRBQkxFXTtcbiAgfVxuICBjb25zdCBuYW1lID0gZ2VuZXJhdGVJbmRleE5hbWUoXG4gICAgYXR0cmlidXRlLFxuICAgIHRhYmxlTmFtZSxcbiAgICBjb21wb3NpdGlvbnMsXG4gICAgb3JkZXIsXG4gICAgc2VwYXJhdG9yXG4gICk7XG4gIHJldHVybiB7XG4gICAgaW5kZXg6IHtcbiAgICAgIGZpZWxkczogZmllbGRzLFxuICAgICAgLy8gcGFydGlhbF9maWx0ZXJfc2VsZWN0b3I6IHBhcnRpYWxGaWx0ZXJTZWxlY3RvcixcbiAgICB9LFxuICAgIGRkb2M6IFtuYW1lLCBDb3VjaERCS2V5cy5ERE9DXS5qb2luKHNlcGFyYXRvciksXG4gICAgbmFtZTogbmFtZSxcbiAgfTtcbn1cbiJdfQ==