UNPKG

nukak

Version:

flexible and efficient ORM, with declarative JSON syntax and smart type-safety

392 lines 67.1 kB
import { QueryRaw, } from '../type/index.js'; import { filterRelationKeys, isSelectingRelations, getKeys, hasKeys, buildSortMap, flatObject, raw, buldQueryWhereAsMap, getFieldCallbackValue, getFieldKeys, fillOnFields, filterFieldKeys, } from '../util/index.js'; import { getMeta } from '../entity/index.js'; export class AbstractSqlDialect { escapeIdChar; beginTransactionCommand; escapeIdRegex; constructor(escapeIdChar = '`', beginTransactionCommand = 'START TRANSACTION') { this.escapeIdChar = escapeIdChar; this.beginTransactionCommand = beginTransactionCommand; this.escapeIdRegex = RegExp(escapeIdChar, 'g'); } returningId(entity) { const meta = getMeta(entity); const idName = meta.fields[meta.id].name; return `RETURNING ${this.escapeId(idName)} ${this.escapeId('id')}`; } search(entity, q = {}, opts = {}) { const meta = getMeta(entity); const prefix = (opts.prefix ?? (opts.autoPrefix || isSelectingRelations(meta, q.$select))) ? meta.name : undefined; opts = { ...opts, prefix }; const where = this.where(entity, q.$where, opts); const sort = this.sort(entity, q.$sort, opts); const pager = this.pager(q); return where + sort + pager; } selectFields(entity, select, opts) { const meta = getMeta(entity); const prefix = opts.prefix ? opts.prefix + '.' : ''; const escapedPrefix = this.escapeId(opts.prefix, true, true); let selectArr; if (select) { if (Array.isArray(select)) { selectArr = select; } else { const selectPositive = getKeys(select).filter((it) => select[it]); selectArr = selectPositive.length ? selectPositive : getFieldKeys(meta.fields).filter((it) => !(it in select)); } selectArr = selectArr.filter((it) => it instanceof QueryRaw || it in meta.fields); if (opts.prefix && !selectArr.includes(meta.id)) { selectArr = [meta.id, ...selectArr]; } } else { selectArr = getFieldKeys(meta.fields); } return selectArr .map((key) => { if (key instanceof QueryRaw) { return this.getRawValue({ value: key, prefix, escapedPrefix, autoPrefixAlias: opts.autoPrefixAlias, }); } const field = meta.fields[key]; if (field.virtual) { return this.getRawValue({ value: raw(field.virtual.value, key), prefix, escapedPrefix, autoPrefixAlias: opts.autoPrefixAlias, }); } const fieldPath = `${escapedPrefix}${this.escapeId(field.name)}`; return !opts.autoPrefixAlias && field.name === key ? fieldPath : `${fieldPath} ${this.escapeId((prefix + key), true)}`; }) .join(', '); } selectRelations(entity, select = {}, { prefix } = {}) { const meta = getMeta(entity); const relKeys = filterRelationKeys(meta, select); const isSelectArray = Array.isArray(select); let fields = ''; let tables = ''; for (const relKey of relKeys) { const relOpts = meta.relations[relKey]; if (relOpts.cardinality === '1m' || relOpts.cardinality === 'mm') { // '1m' and 'mm' should be resolved in a higher layer because they will need multiple queries continue; } const joinRelAlias = prefix ? prefix + '.' + relKey : relKey; const relEntity = relOpts.entity(); const relSelect = select[relKey]; const relQuery = isSelectArray ? {} : Array.isArray(relSelect) ? { $select: relSelect } : relSelect; const relColumns = this.selectFields(relEntity, relQuery.$select, { prefix: joinRelAlias, autoPrefixAlias: true, }); fields += ', ' + relColumns; const { fields: subColumns, tables: subTables } = this.selectRelations(relEntity, relQuery.$select, { prefix: joinRelAlias, }); fields += subColumns; const relMeta = getMeta(relEntity); const relEntityName = this.escapeId(relMeta.name); const relPath = prefix ? this.escapeId(prefix, true) : this.escapeId(meta.name); const joinType = relQuery.$required ? 'INNER' : 'LEFT'; const joinAlias = this.escapeId(joinRelAlias, true); tables += ` ${joinType} JOIN ${relEntityName} ${joinAlias} ON `; tables += relOpts.references .map((it) => `${joinAlias}.${this.escapeId(it.foreign)} = ${relPath}.${this.escapeId(it.local)}`) .join(' AND '); if (relQuery.$where) { const where = this.where(relEntity, relQuery.$where, { prefix: relKey, clause: false }); tables += ` AND ${where}`; } tables += subTables; } return { fields, tables }; } select(entity, select, opts = {}) { const meta = getMeta(entity); const prefix = (opts.prefix ?? (opts.autoPrefix || isSelectingRelations(meta, select))) ? meta.name : undefined; const fields = this.selectFields(entity, select, { prefix }); const { fields: relationFields, tables } = this.selectRelations(entity, select); return `SELECT ${fields}${relationFields} FROM ${this.escapeId(meta.name)}${tables}`; } where(entity, where = {}, opts) { const meta = getMeta(entity); const { usePrecedence, clause = 'WHERE', softDelete } = opts; where = buldQueryWhereAsMap(meta, where); if (meta.softDelete && (softDelete || softDelete === undefined) && !where[meta.softDelete]) { where[meta.softDelete] = null; } const entries = Object.entries(where); if (!entries.length) { return ''; } const options = { ...opts, usePrecedence: entries.length > 1 }; let sql = entries .map(([key, val]) => this.compare(entity, key, val, options)) .join(` AND `); if (usePrecedence) { sql = `(${sql})`; } return clause ? ` ${clause} ${sql}` : sql; } compare(entity, key, val, opts = {}) { const meta = getMeta(entity); if (val instanceof QueryRaw) { if (key === '$exists' || key === '$nexists') { const value = val; const query = this.getRawValue({ value, prefix: meta.name, escapedPrefix: this.escapeId(meta.name, false, true), }); return `${key === '$exists' ? 'EXISTS' : 'NOT EXISTS'} (${query})`; } const comparisonKey = this.getComparisonKey(entity, key, opts); return `${comparisonKey} = ${val.value}`; } if (key === '$text') { const search = val; const fields = search.$fields.map((field) => this.escapeId(meta.fields[field].name)); return `MATCH(${fields.join(', ')}) AGAINST(${this.escape(search.$value)})`; } if (key === '$and' || key === '$or' || key === '$not' || key === '$nor') { const negateOperatorMap = { $not: '$and', $nor: '$or', }; const op = negateOperatorMap[key] ?? key; const negate = key in negateOperatorMap ? 'NOT ' : ''; const values = val; const hasManyItems = values.length > 1; const logicalComparison = values .map((whereEntry) => { if (whereEntry instanceof QueryRaw) { return this.getRawValue({ value: whereEntry, prefix: opts.prefix, escapedPrefix: this.escapeId(opts.prefix, true, true), }); } return this.where(entity, whereEntry, { prefix: opts.prefix, usePrecedence: hasManyItems && !Array.isArray(whereEntry) && getKeys(whereEntry).length > 1, clause: false, }); }) .join(op === '$or' ? ' OR ' : ' AND '); return (opts.usePrecedence || negate) && hasManyItems ? `${negate}(${logicalComparison})` : `${negate}${logicalComparison}`; } const value = Array.isArray(val) ? { $in: val } : typeof val === 'object' && val !== null ? val : { $eq: val }; const operators = getKeys(value); const comparisons = operators .map((op) => this.compareFieldOperator(entity, key, op, value[op], opts)) .join(' AND '); return operators.length > 1 ? `(${comparisons})` : comparisons; } compareFieldOperator(entity, key, op, val, opts = {}) { const comparisonKey = this.getComparisonKey(entity, key, opts); switch (op) { case '$eq': return val === null ? `${comparisonKey} IS NULL` : `${comparisonKey} = ${this.escape(val)}`; case '$ne': return val === null ? `${comparisonKey} IS NOT NULL` : `${comparisonKey} <> ${this.escape(val)}`; case '$not': return this.compare(entity, '$not', [{ [key]: val }], opts); case '$gt': return `${comparisonKey} > ${this.escape(val)}`; case '$gte': return `${comparisonKey} >= ${this.escape(val)}`; case '$lt': return `${comparisonKey} < ${this.escape(val)}`; case '$lte': return `${comparisonKey} <= ${this.escape(val)}`; case '$startsWith': return `${comparisonKey} LIKE ${this.escape(`${val}%`)}`; case '$istartsWith': return `LOWER(${comparisonKey}) LIKE ${this.escape(val.toLowerCase() + '%')}`; case '$endsWith': return `${comparisonKey} LIKE ${this.escape(`%${val}`)}`; case '$iendsWith': return `LOWER(${comparisonKey}) LIKE ${this.escape('%' + val.toLowerCase())}`; case '$includes': return `${comparisonKey} LIKE ${this.escape(`%${val}%`)}`; case '$iincludes': return `LOWER(${comparisonKey}) LIKE ${this.escape('%' + val.toLowerCase() + '%')}`; case '$ilike': return `LOWER(${comparisonKey}) LIKE ${this.escape(val.toLowerCase())}`; case '$like': return `${comparisonKey} LIKE ${this.escape(val)}`; case '$in': return `${comparisonKey} IN (${this.escape(val)})`; case '$nin': return `${comparisonKey} NOT IN (${this.escape(val)})`; case '$regex': return `${comparisonKey} REGEXP ${this.escape(val)}`; default: throw TypeError(`unknown operator: ${op}`); } } getComparisonKey(entity, key, { prefix } = {}) { const meta = getMeta(entity); const escapedPrefix = this.escapeId(prefix, true, true); const field = meta.fields[key]; if (field?.virtual) { return this.getRawValue({ value: field.virtual, prefix, escapedPrefix, }); } return escapedPrefix + this.escapeId(field?.name ?? key); } sort(entity, sort, { prefix }) { const sortMap = buildSortMap(sort); if (!hasKeys(sortMap)) { return ''; } const meta = getMeta(entity); const flattenedSort = flatObject(sortMap, prefix); const directionMap = { 1: '', asc: '', '-1': ' DESC', desc: ' DESC' }; const order = Object.entries(flattenedSort) .map(([key, sort]) => { const name = meta.fields[key]?.name ?? key; const direction = directionMap[sort]; return this.escapeId(name) + direction; }) .join(', '); return ` ORDER BY ${order}`; } pager(opts) { let sql = ''; if (opts.$limit) { sql += ` LIMIT ${Number(opts.$limit)}`; } if (opts.$skip !== undefined) { sql += ` OFFSET ${Number(opts.$skip)}`; } return sql; } count(entity, q, opts) { const search = { ...q, }; delete search.$sort; const select = this.select(entity, [raw('COUNT(*)', 'count')]); const criteria = this.search(entity, search, opts); return select + criteria; } find(entity, q, opts) { const select = this.select(entity, q.$select, opts); const criteria = this.search(entity, q, opts); return select + criteria; } insert(entity, payload) { const meta = getMeta(entity); const records = this.getPersistables(meta, payload, 'onInsert'); const keys = getKeys(records[0]); const columns = keys.map((key) => this.escapeId(meta.fields[key].name)); const values = records.map((record) => keys.map((key) => record[key]).join(', ')).join('), ('); return `INSERT INTO ${this.escapeId(meta.name)} (${columns.join(', ')}) VALUES (${values})`; } update(entity, q, payload, opts) { const meta = getMeta(entity); const record = this.getPersistable(meta, payload, 'onUpdate'); const keys = getKeys(record); const entries = keys.map((key) => `${this.escapeId(meta.fields[key].name)} = ${record[key]}`).join(', '); const criteria = this.search(entity, q, opts); return `UPDATE ${this.escapeId(meta.name)} SET ${entries}${criteria}`; } upsert(entity, conflictPaths, payload) { const meta = getMeta(entity); const insert = this.insert(entity, payload); const fields = filterFieldKeys(meta, payload, 'onInsert'); const update = fields .filter((col) => !conflictPaths[col]) .map((col) => `${this.escapeId(col)} = VALUES(${this.escapeId(col)})`) .join(', '); return `${insert} ON DUPLICATE KEY UPDATE ${update}`; } delete(entity, q, opts = {}) { const meta = getMeta(entity); if (opts.softDelete || opts.softDelete === undefined) { if (meta.softDelete) { const criteria = this.search(entity, q, opts); const value = getFieldCallbackValue(meta.fields[meta.softDelete].onDelete); return `UPDATE ${this.escapeId(meta.name)} SET ${this.escapeId(meta.softDelete)} = ${this.escape(value)}${criteria}`; } else if (opts.softDelete) { throw TypeError(`'${meta.name}' has not enabled 'softDelete'`); } } const criteria = this.search(entity, q, opts); return `DELETE FROM ${this.escapeId(meta.name)}${criteria}`; } escapeId(val, forbidQualified, addDot) { if (!val) { return ''; } if (!forbidQualified && val.includes('.')) { return val .split('.') .map((it) => this.escapeId(it)) .join('.'); } // sourced from 'escapeId' function here https://github.com/mysqljs/sqlstring/blob/master/lib/SqlString.js const escaped = this.escapeIdChar + val.replace(this.escapeIdRegex, this.escapeIdChar + this.escapeIdChar) + this.escapeIdChar; const suffix = addDot ? '.' : ''; return escaped + suffix; } getPersistable(meta, payload, callbackKey) { return this.getPersistables(meta, payload, callbackKey)[0]; } getPersistables(meta, payload, callbackKey) { const payloads = fillOnFields(meta, payload, callbackKey); const fieldKeys = filterFieldKeys(meta, payloads[0], callbackKey); return payloads.map((it) => fieldKeys.reduce((acc, key) => { const { type } = meta.fields[key]; let value = it[key]; if (value instanceof QueryRaw) { value = this.getRawValue({ value }); } else if (type === 'json' || type === 'jsonb') { value = (this.escape(JSON.stringify(value)) + `::${type}`); } else if (type === 'vector') { value = value.map((num) => +num).join(','); value = `'[${value}]'`; } else { value = this.escape(value); } acc[key] = value; return acc; }, {})); } getRawValue(opts) { const { value, prefix = '', autoPrefixAlias } = opts; const val = typeof value.value === 'function' ? value.value({ ...opts, dialect: this }) : prefix + value.value; const alias = value.alias; if (alias) { const fullAlias = autoPrefixAlias ? prefix + alias : alias; const escapedFullAlias = this.escapeId(fullAlias, true); return `${val} ${escapedFullAlias}`; } return val; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJzdHJhY3RTcWxEaWFsZWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2RpYWxlY3QvYWJzdHJhY3RTcWxEaWFsZWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFtQkwsUUFBUSxHQU1ULE1BQU0sa0JBQWtCLENBQUM7QUFDMUIsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixvQkFBb0IsRUFDcEIsT0FBTyxFQUNQLE9BQU8sRUFDUCxZQUFZLEVBQ1osVUFBVSxFQUNWLEdBQUcsRUFDSCxtQkFBbUIsRUFDbkIscUJBQXFCLEVBQ3JCLFlBQVksRUFDWixZQUFZLEVBQ1osZUFBZSxHQUVoQixNQUFNLGtCQUFrQixDQUFDO0FBRTFCLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUU3QyxNQUFNLE9BQWdCLGtCQUFrQjtJQUkzQjtJQUNBO0lBSkYsYUFBYSxDQUFTO0lBRS9CLFlBQ1csZUFBMEIsR0FBRyxFQUM3QiwwQkFBa0MsbUJBQW1CO1FBRHJELGlCQUFZLEdBQVosWUFBWSxDQUFpQjtRQUM3Qiw0QkFBdUIsR0FBdkIsdUJBQXVCLENBQThCO1FBRTlELElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDLFlBQVksRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQsV0FBVyxDQUFJLE1BQWU7UUFDNUIsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzdCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUN6QyxPQUFPLGFBQWEsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7SUFDckUsQ0FBQztJQUVELE1BQU0sQ0FBSSxNQUFlLEVBQUUsSUFBYyxFQUFFLEVBQUUsT0FB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biAgUXVlcnlXaGVyZUZpZWxkT3BlcmF0b3JNYXAsXG4gIFF1ZXJ5U29ydCxcbiAgUXVlcnlQYWdlcixcbiAgUXVlcnlUZXh0U2VhcmNoT3B0aW9ucyxcbiAgRmllbGRLZXksXG4gIFF1ZXJ5U2VsZWN0LFxuICBUeXBlLFxuICBRdWVyeVNlbGVjdEFycmF5LFxuICBRdWVyeU9wdGlvbnMsXG4gIFF1ZXJ5RGlhbGVjdCxcbiAgUXVlcnlXaGVyZU9wdGlvbnMsXG4gIFF1ZXJ5Q29tcGFyaXNvbk9wdGlvbnMsXG4gIFF1ZXJ5V2hlcmVNYXAsXG4gIFF1ZXJ5U2VsZWN0T3B0aW9ucyxcbiAgUXVlcnlTb3J0RGlyZWN0aW9uLFxuICBRdWVyeVdoZXJlQXJyYXksXG4gIFF1ZXJ5UmF3LFxuICBRdWVyeVNlYXJjaCxcbiAgUXVlcnksXG4gIFF1ZXJ5Q29uZmxpY3RQYXRocyxcbiAgRW50aXR5TWV0YSxcbiAgUXVlcnlSYXdGbk9wdGlvbnMsXG59IGZyb20gJy4uL3R5cGUvaW5kZXguanMnO1xuaW1wb3J0IHtcbiAgZmlsdGVyUmVsYXRpb25LZXlzLFxuICBpc1NlbGVjdGluZ1JlbGF0aW9ucyxcbiAgZ2V0S2V5cyxcbiAgaGFzS2V5cyxcbiAgYnVpbGRTb3J0TWFwLFxuICBmbGF0T2JqZWN0LFxuICByYXcsXG4gIGJ1bGRRdWVyeVdoZXJlQXNNYXAsXG4gIGdldEZpZWxkQ2FsbGJhY2tWYWx1ZSxcbiAgZ2V0RmllbGRLZXlzLFxuICBmaWxsT25GaWVsZHMsXG4gIGZpbHRlckZpZWxkS2V5cyxcbiAgQ2FsbGJhY2tLZXksXG59IGZyb20gJy4uL3V0aWwvaW5kZXguanMnO1xuXG5pbXBvcnQgeyBnZXRNZXRhIH0gZnJvbSAnLi4vZW50aXR5L2luZGV4LmpzJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEFic3RyYWN0U3FsRGlhbGVjdCBpbXBsZW1lbnRzIFF1ZXJ5RGlhbGVjdCB7XG4gIHJlYWRvbmx5IGVzY2FwZUlkUmVnZXg6IFJlZ0V4cDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICByZWFkb25seSBlc2NhcGVJZENoYXI6ICdgJyB8ICdcIicgPSAnYCcsXG4gICAgcmVhZG9ubHkgYmVnaW5UcmFuc2FjdGlvbkNvbW1hbmQ6IHN0cmluZyA9ICdTVEFSVCBUUkFOU0FDVElPTicsXG4gICkge1xuICAgIHRoaXMuZXNjYXBlSWRSZWdleCA9IFJlZ0V4cChlc2NhcGVJZENoYXIsICdnJyk7XG4gIH1cblxuICByZXR1cm5pbmdJZDxFPihlbnRpdHk6IFR5cGU8RT4pOiBzdHJpbmcge1xuICAgIGNvbnN0IG1ldGEgPSBnZXRNZXRhKGVudGl0eSk7XG4gICAgY29uc3QgaWROYW1lID0gbWV0YS5maWVsZHNbbWV0YS5pZF0ubmFtZTtcbiAgICByZXR1cm4gYFJFVFVSTklORyAke3RoaXMuZXNjYXBlSWQoaWROYW1lKX0gJHt0aGlzLmVzY2FwZUlkKCdpZCcpfWA7XG4gIH1cblxuICBzZWFyY2g8RT4oZW50aXR5OiBUeXBlPEU+LCBxOiBRdWVyeTxFPiA9IHt9LCBvcHRzOiBRdWVyeU9wdGlvbnMgPSB7fSk6IHN0cmluZyB7XG4gICAgY29uc3QgbWV0YSA9IGdldE1ldGEoZW50aXR5KTtcbiAgICBjb25zdCBwcmVmaXggPSAob3B0cy5wcmVmaXggPz8gKG9wdHMuYXV0b1ByZWZpeCB8fCBpc1NlbGVjdGluZ1JlbGF0aW9ucyhtZXRhLCBxLiRzZWxlY3QpKSkgPyBtZXRhLm5hbWUgOiB1bmRlZmluZWQ7XG4gICAgb3B0cyA9IHsgLi4ub3B0cywgcHJlZml4IH07XG4gICAgY29uc3Qgd2hlcmUgPSB0aGlzLndoZXJlPEU+KGVudGl0eSwgcS4kd2hlcmUsIG9wdHMpO1xuICAgIGNvbnN0IHNvcnQgPSB0aGlzLnNvcnQ8RT4oZW50aXR5LCBxLiRzb3J0LCBvcHRzKTtcbiAgICBjb25zdCBwYWdlciA9IHRoaXMucGFnZXIocSk7XG4gICAgcmV0dXJuIHdoZXJlICsgc29ydCArIHBhZ2VyO1xuICB9XG5cbiAgc2VsZWN0RmllbGRzPEU+KGVudGl0eTogVHlwZTxFPiwgc2VsZWN0OiBRdWVyeVNlbGVjdDxFPiwgb3B0czogUXVlcnlTZWxlY3RPcHRpb25zKTogc3RyaW5nIHtcbiAgICBjb25zdCBtZXRhID0gZ2V0TWV0YShlbnRpdHkpO1xuICAgIGNvbnN0IHByZWZpeCA9IG9wdHMucHJlZml4ID8gb3B0cy5wcmVmaXggKyAnLicgOiAnJztcbiAgICBjb25zdCBlc2NhcGVkUHJlZml4ID0gdGhpcy5lc2NhcGVJZChvcHRzLnByZWZpeCwgdHJ1ZSwgdHJ1ZSk7XG5cbiAgICBsZXQgc2VsZWN0QXJyOiBRdWVyeVNlbGVjdEFycmF5PEU+O1xuXG4gICAgaWYgKHNlbGVjdCkge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoc2VsZWN0KSkge1xuICAgICAgICBzZWxlY3RBcnIgPSBzZWxlY3Q7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBzZWxlY3RQb3NpdGl2ZSA9IGdldEtleXMoc2VsZWN0KS5maWx0ZXIoKGl0KSA9PiBzZWxlY3RbaXRdKSBhcyBGaWVsZEtleTxFPltdO1xuICAgICAgICBzZWxlY3RBcnIgPSBzZWxlY3RQb3NpdGl2ZS5sZW5ndGhcbiAgICAgICAgICA/IHNlbGVjdFBvc2l0aXZlXG4gICAgICAgICAgOiAoZ2V0RmllbGRLZXlzKG1ldGEuZmllbGRzKS5maWx0ZXIoKGl0KSA9PiAhKGl0IGluIHNlbGVjdCkpIGFzIEZpZWxkS2V5PEU+W10pO1xuICAgICAgfVxuICAgICAgc2VsZWN0QXJyID0gc2VsZWN0QXJyLmZpbHRlcigoaXQpID0+IGl0IGluc3RhbmNlb2YgUXVlcnlSYXcgfHwgaXQgaW4gbWV0YS5maWVsZHMpO1xuICAgICAgaWYgKG9wdHMucHJlZml4ICYmICFzZWxlY3RBcnIuaW5jbHVkZXMobWV0YS5pZCkpIHtcbiAgICAgICAgc2VsZWN0QXJyID0gW21ldGEuaWQsIC4uLnNlbGVjdEFycl07XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHNlbGVjdEFyciA9IGdldEZpZWxkS2V5cyhtZXRhLmZpZWxkcykgYXMgRmllbGRLZXk8RT5bXTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZWN0QXJyXG4gICAgICAubWFwKChrZXkpID0+IHtcbiAgICAgICAgaWYgKGtleSBpbnN0YW5jZW9mIFF1ZXJ5UmF3KSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmF3VmFsdWUoe1xuICAgICAgICAgICAgdmFsdWU6IGtleSxcbiAgICAgICAgICAgIHByZWZpeCxcbiAgICAgICAgICAgIGVzY2FwZWRQcmVmaXgsXG4gICAgICAgICAgICBhdXRvUHJlZml4QWxpYXM6IG9wdHMuYXV0b1ByZWZpeEFsaWFzLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZmllbGQgPSBtZXRhLmZpZWxkc1trZXkgYXMgRmllbGRLZXk8RT5dO1xuXG4gICAgICAgIGlmIChmaWVsZC52aXJ0dWFsKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmF3VmFsdWUoe1xuICAgICAgICAgICAgdmFsdWU6IHJhdyhmaWVsZC52aXJ0dWFsLnZhbHVlLCBrZXkpLFxuICAgICAgICAgICAgcHJlZml4LFxuICAgICAgICAgICAgZXNjYXBlZFByZWZpeCxcbiAgICAgICAgICAgIGF1dG9QcmVmaXhBbGlhczogb3B0cy5hdXRvUHJlZml4QWxpYXMsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBmaWVsZFBhdGggPSBgJHtlc2NhcGVkUHJlZml4fSR7dGhpcy5lc2NhcGVJZChmaWVsZC5uYW1lKX1gO1xuXG4gICAgICAgIHJldHVybiAhb3B0cy5hdXRvUHJlZml4QWxpYXMgJiYgZmllbGQubmFtZSA9PT0ga2V5XG4gICAgICAgICAgPyBmaWVsZFBhdGhcbiAgICAgICAgICA6IGAke2ZpZWxkUGF0aH0gJHt0aGlzLmVzY2FwZUlkKChwcmVmaXggKyBrZXkpIGFzIEZpZWxkS2V5PEU+LCB0cnVlKX1gO1xuICAgICAgfSlcbiAgICAgIC5qb2luKCcsICcpO1xuICB9XG5cbiAgc2VsZWN0UmVsYXRpb25zPEU+KFxuICAgIGVudGl0eTogVHlwZTxFPixcbiAgICBzZWxlY3Q6IFF1ZXJ5U2VsZWN0PEU+ID0ge30sXG4gICAgeyBwcmVmaXggfTogeyBwcmVmaXg/OiBzdHJpbmcgfSA9IHt9LFxuICApOiB7IGZpZWxkczogc3RyaW5nOyB0YWJsZXM6IHN0cmluZyB9IHtcbiAgICBjb25zdCBtZXRhID0gZ2V0TWV0YShlbnRpdHkpO1xuICAgIGNvbnN0IHJlbEtleXMgPSBmaWx0ZXJSZWxhdGlvbktleXMobWV0YSwgc2VsZWN0KTtcbiAgICBjb25zdCBpc1NlbGVjdEFycmF5ID0gQXJyYXkuaXNBcnJheShzZWxlY3QpO1xuICAgIGxldCBmaWVsZHMgPSAnJztcbiAgICBsZXQgdGFibGVzID0gJyc7XG5cbiAgICBmb3IgKGNvbnN0IHJlbEtleSBvZiByZWxLZXlzKSB7XG4gICAgICBjb25zdCByZWxPcHRzID0gbWV0YS5yZWxhdGlvbnNbcmVsS2V5XTtcblxuICAgICAgaWYgKHJlbE9wdHMuY2FyZGluYWxpdHkgPT09ICcxbScgfHwgcmVsT3B0cy5jYXJkaW5hbGl0eSA9PT0gJ21tJykge1xuICAgICAgICAvLyAnMW0nIGFuZCAnbW0nIHNob3VsZCBiZSByZXNvbHZlZCBpbiBhIGhpZ2hlciBsYXllciBiZWNhdXNlIHRoZXkgd2lsbCBuZWVkIG11bHRpcGxlIHF1ZXJpZXNcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGpvaW5SZWxBbGlhcyA9IHByZWZpeCA/IHByZWZpeCArICcuJyArIHJlbEtleSA6IHJlbEtleTtcbiAgICAgIGNvbnN0IHJlbEVudGl0eSA9IHJlbE9wdHMuZW50aXR5KCk7XG4gICAgICBjb25zdCByZWxTZWxlY3QgPSBzZWxlY3RbcmVsS2V5IGFzIHN0cmluZ107XG4gICAgICBjb25zdCByZWxRdWVyeSA9IGlzU2VsZWN0QXJyYXkgPyB7fSA6IEFycmF5LmlzQXJyYXkocmVsU2VsZWN0KSA/IHsgJHNlbGVjdDogcmVsU2VsZWN0IH0gOiByZWxTZWxlY3Q7XG5cbiAgICAgIGNvbnN0IHJlbENvbHVtbnMgPSB0aGlzLnNlbGVjdEZpZWxkcyhyZWxFbnRpdHksIHJlbFF1ZXJ5LiRzZWxlY3QsIHtcbiAgICAgICAgcHJlZml4OiBqb2luUmVsQWxpYXMsXG4gICAgICAgIGF1dG9QcmVmaXhBbGlhczogdHJ1ZSxcbiAgICAgIH0pO1xuXG4gICAgICBmaWVsZHMgKz0gJywgJyArIHJlbENvbHVtbnM7XG5cbiAgICAgIGNvbnN0IHsgZmllbGRzOiBzdWJDb2x1bW5zLCB0YWJsZXM6IHN1YlRhYmxlcyB9ID0gdGhpcy5zZWxlY3RSZWxhdGlvbnMocmVsRW50aXR5LCByZWxRdWVyeS4kc2VsZWN0LCB7XG4gICAgICAgIHByZWZpeDogam9pblJlbEFsaWFzLFxuICAgICAgfSk7XG5cbiAgICAgIGZpZWxkcyArPSBzdWJDb2x1bW5zO1xuXG4gICAgICBjb25zdCByZWxNZXRhID0gZ2V0TWV0YShyZWxFbnRpdHkpO1xuICAgICAgY29uc3QgcmVsRW50aXR5TmFtZSA9IHRoaXMuZXNjYXBlSWQocmVsTWV0YS5uYW1lKTtcbiAgICAgIGNvbnN0IHJlbFBhdGggPSBwcmVmaXggPyB0aGlzLmVzY2FwZUlkKHByZWZpeCwgdHJ1ZSkgOiB0aGlzLmVzY2FwZUlkKG1ldGEubmFtZSk7XG4gICAgICBjb25zdCBqb2luVHlwZSA9IHJlbFF1ZXJ5LiRyZXF1aXJlZCA/ICdJTk5FUicgOiAnTEVGVCc7XG4gICAgICBjb25zdCBqb2luQWxpYXMgPSB0aGlzLmVzY2FwZUlkKGpvaW5SZWxBbGlhcywgdHJ1ZSk7XG5cbiAgICAgIHRhYmxlcyArPSBgICR7am9pblR5cGV9IEpPSU4gJHtyZWxFbnRpdHlOYW1lfSAke2pvaW5BbGlhc30gT04gYDtcbiAgICAgIHRhYmxlcyArPSByZWxPcHRzLnJlZmVyZW5jZXNcbiAgICAgICAgLm1hcCgoaXQpID0+IGAke2pvaW5BbGlhc30uJHt0aGlzLmVzY2FwZUlkKGl0LmZvcmVpZ24pfSA9ICR7cmVsUGF0aH0uJHt0aGlzLmVzY2FwZUlkKGl0LmxvY2FsKX1gKVxuICAgICAgICAuam9pbignIEFORCAnKTtcblxuICAgICAgaWYgKHJlbFF1ZXJ5LiR3aGVyZSkge1xuICAgICAgICBjb25zdCB3aGVyZSA9IHRoaXMud2h