UNPKG

nukak

Version:

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

245 lines 37.6 kB
import { getMeta } from '../entity/decorator/index.js'; import { clone, getKeys, filterRelationKeys, filterPersistableRelationKeys, augmentWhere } from '../util/index.js'; import { GenericRepository } from '../repository/index.js'; export class AbstractQuerier { findOneById(entity, id, q = {}) { const meta = getMeta(entity); q.$where = augmentWhere(meta, q.$where, id); return this.findOne(entity, q); } async findOne(entity, q) { const rows = await this.findMany(entity, { ...q, $limit: 1 }); return rows[0]; } findManyAndCount(entity, q) { const qCount = { ...q, }; delete qCount.$sort; delete qCount.$limit; delete qCount.$skip; return Promise.all([this.findMany(entity, q), this.count(entity, qCount)]); } async insertOne(entity, payload) { const [id] = await this.insertMany(entity, [payload]); return id; } updateOneById(entity, id, payload) { return this.updateMany(entity, { $where: id }, payload); } deleteOneById(entity, id, opts) { return this.deleteMany(entity, { $where: id }, opts); } async saveOne(entity, payload) { const [id] = await this.saveMany(entity, [payload]); return id; } async saveMany(entity, payload) { const meta = getMeta(entity); const ids = []; const updates = []; const inserts = []; for (const it of payload) { if (it[meta.id]) { if (getKeys(it).length === 1) { ids.push(it[meta.id]); } else { updates.push(it); } } else { inserts.push(it); } } return Promise.all([ ...ids, ...(inserts.length ? await this.insertMany(entity, inserts) : []), ...updates.map(async (it) => { const { [meta.id]: id, ...data } = it; await this.updateOneById(entity, id, data); return id; }), ]); } async fillToManyRelations(entity, payload, select) { if (!payload.length) { return; } const meta = getMeta(entity); const relKeys = filterRelationKeys(meta, select); for (const relKey of relKeys) { const relOpts = meta.relations[relKey]; const relEntity = relOpts.entity(); const relSelect = clone(select[relKey]); const relQuery = relSelect === true || relSelect === undefined ? {} : Array.isArray(relSelect) ? { $select: relSelect } : relSelect; const ids = payload.map((it) => it[meta.id]); if (relOpts.through) { const localField = relOpts.references[0].local; const throughEntity = relOpts.through(); const throughMeta = getMeta(throughEntity); const targetRelKey = Object.keys(throughMeta.relations).find((key) => throughMeta.relations[key].references.some(({ local }) => local === relOpts.references[1].local)); const throughFounds = await this.findMany(throughEntity, { ...relQuery, $select: { [localField]: true, [targetRelKey]: { ...relQuery, $required: true, }, }, $where: { ...relQuery.$where, [localField]: ids, }, }); const founds = throughFounds.map((it) => ({ ...it[targetRelKey], [localField]: it[localField] })); this.putChildrenInParents(payload, founds, meta.id, localField, relKey); } else if (relOpts.cardinality === '1m') { const foreignField = relOpts.references[0].foreign; if (relQuery.$select) { if (Array.isArray(relQuery.$select)) { if (!relQuery.$select.includes(foreignField)) { relQuery.$select.push(foreignField); } } else if (!relQuery.$select[foreignField]) { relQuery.$select[foreignField] = true; } } relQuery.$where = { ...relQuery.$where, [foreignField]: ids }; const founds = await this.findMany(relEntity, relQuery); this.putChildrenInParents(payload, founds, meta.id, foreignField, relKey); } } } putChildrenInParents(parents, children, parentIdKey, referenceKey, relKey) { const childrenByParentMap = children.reduce((acc, child) => { const parenId = child[referenceKey]; if (!acc[parenId]) { acc[parenId] = []; } acc[parenId].push(child); return acc; }, {}); for (const parent of parents) { const parentId = parent[parentIdKey]; parent[relKey] = childrenByParentMap[parentId]; } } async insertRelations(entity, payload) { const meta = getMeta(entity); await Promise.all(payload.map((it) => { const relKeys = filterPersistableRelationKeys(meta, it, 'persist'); if (!relKeys.length) { return; } return Promise.all(relKeys.map((relKey) => this.saveRelation(entity, it, relKey))); })); } async updateRelations(entity, q, payload) { const meta = getMeta(entity); const relKeys = filterPersistableRelationKeys(meta, payload, 'persist'); if (!relKeys.length) { return; } const founds = await this.findMany(entity, { ...q, $select: [meta.id] }); const ids = founds.map((found) => found[meta.id]); await Promise.all(ids.map((id) => Promise.all(relKeys.map((relKey) => this.saveRelation(entity, { ...payload, [meta.id]: id }, relKey, true))))); } async deleteRelations(entity, ids, opts) { const meta = getMeta(entity); const relKeys = filterPersistableRelationKeys(meta, meta.relations, 'delete'); for (const relKey of relKeys) { const relOpts = meta.relations[relKey]; const relEntity = relOpts.entity(); const localField = relOpts.references[0].local; if (relOpts.through) { const throughEntity = relOpts.through(); await this.deleteMany(throughEntity, { $where: { [localField]: ids } }, opts); return; } await this.deleteMany(relEntity, { [localField]: ids }, opts); } } async saveRelation(entity, payload, relKey, isUpdate) { const meta = getMeta(entity); const id = payload[meta.id]; const { entity: entityGetter, cardinality, references, through } = meta.relations[relKey]; const relEntity = entityGetter(); const relPayload = payload[relKey]; if (cardinality === '1m' || cardinality === 'mm') { if (through) { const localField = references[0].local; const throughEntity = through(); if (isUpdate) { await this.deleteMany(throughEntity, { $where: { [localField]: id } }); } if (relPayload) { const savedIds = await this.saveMany(relEntity, relPayload); const throughBodies = savedIds.map((relId) => ({ [references[0].local]: id, [references[1].local]: relId, })); await this.insertMany(throughEntity, throughBodies); } return; } const foreignField = references[0].foreign; if (isUpdate) { await this.deleteMany(relEntity, { $where: { [foreignField]: id } }); } if (relPayload) { for (const it of relPayload) { it[foreignField] = id; } await this.saveMany(relEntity, relPayload); } return; } if (cardinality === '11') { const foreignField = references[0].foreign; if (relPayload === null) { await this.deleteMany(relEntity, { $where: { [foreignField]: id } }); return; } await this.saveOne(relEntity, { ...relPayload, [foreignField]: id }); return; } if (cardinality === 'm1' && relPayload) { const localField = references[0].local; const referenceId = await this.insertOne(relEntity, relPayload); await this.updateOneById(entity, id, { [localField]: referenceId }); return; } } getRepository(entity) { return new GenericRepository(entity, this); } async transaction(callback) { try { await this.beginTransaction(); const res = await callback(); await this.commitTransaction(); return res; } catch (err) { await this.rollbackTransaction(); throw err; } finally { await this.release(); } } async releaseIfFree() { if (!this.hasOpenTransaction) { await this.release(); } } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWJzdHJhY3RRdWVyaWVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3F1ZXJpZXIvYWJzdHJhY3RRdWVyaWVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQWVBLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSw2QkFBNkIsRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNuSCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUUzRCxNQUFNLE9BQWdCLGVBQWU7SUFDbkMsV0FBVyxDQUFJLE1BQWUsRUFBRSxFQUFjLEVBQUUsSUFBaUIsRUFBRTtRQUNqRSxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDN0IsQ0FBQyxDQUFDLE1BQU0sR0FBRyxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDNUMsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQsS0FBSyxDQUFDLE9BQU8sQ0FBSSxNQUFlLEVBQUUsQ0FBYztRQUM5QyxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLEVBQUUsR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDOUQsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDakIsQ0FBQztJQUlELGdCQUFnQixDQUFJLE1BQWUsRUFBRSxDQUFXO1FBQzlDLE1BQU0sTUFBTSxHQUFHO1lBQ2IsR0FBRyxDQUFDO1NBQ29CLENBQUM7UUFDM0IsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDO1FBQ3BCLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FB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O0lBQzdDLENBQUM7SUFJRCxLQUFLLENBQUMsV0FBVyxDQUFJLFFBQTBCO1FBQzdDLElBQUksQ0FBQztZQUNILE1BQU0sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDOUIsTUFBTSxHQUFHLEdBQUcsTUFBTSxRQUFRLEVBQUUsQ0FBQztZQUM3QixNQUFNLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQy9CLE9BQU8sR0FBRyxDQUFDO1FBQ2IsQ0FBQztRQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7WUFDYixNQUFNLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBQ2pDLE1BQU0sR0FBRyxDQUFDO1FBQ1osQ0FBQztnQkFBUyxDQUFDO1lBQ1QsTUFBTSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDdkIsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsYUFBYTtRQUNqQixJQUFJLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDN0IsTUFBTSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDdkIsQ0FBQztJQUNILENBQUM7Q0FTRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHtcbiAgSWRWYWx1ZSxcbiAgUXVlcmllcixcbiAgUXVlcnksXG4gIFF1ZXJ5T3B0aW9ucyxcbiAgUXVlcnlTZWxlY3QsXG4gIFF1ZXJ5U2VhcmNoLFxuICBSZWxhdGlvbktleSxcbiAgUmVsYXRpb25WYWx1ZSxcbiAgUmVwb3NpdG9yeSxcbiAgVHlwZSxcbiAgUXVlcnlPbmUsXG4gIFF1ZXJ5Q29uZmxpY3RQYXRocyxcbiAgUXVlcnlVcGRhdGVSZXN1bHQsXG59IGZyb20gJy4uL3R5cGUvaW5kZXguanMnO1xuaW1wb3J0IHsgZ2V0TWV0YSB9IGZyb20gJy4uL2VudGl0eS9kZWNvcmF0b3IvaW5kZXguanMnO1xuaW1wb3J0IHsgY2xvbmUsIGdldEtleXMsIGZpbHRlclJlbGF0aW9uS2V5cywgZmlsdGVyUGVyc2lzdGFibGVSZWxhdGlvbktleXMsIGF1Z21lbnRXaGVyZSB9IGZyb20gJy4uL3V0aWwvaW5kZXguanMnO1xuaW1wb3J0IHsgR2VuZXJpY1JlcG9zaXRvcnkgfSBmcm9tICcuLi9yZXBvc2l0b3J5L2luZGV4LmpzJztcblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEFic3RyYWN0UXVlcmllciBpbXBsZW1lbnRzIFF1ZXJpZXIge1xuICBmaW5kT25lQnlJZDxFPihlbnRpdHk6IFR5cGU8RT4sIGlkOiBJZFZhbHVlPEU+LCBxOiBRdWVyeU9uZTxFPiA9IHt9KSB7XG4gICAgY29uc3QgbWV0YSA9IGdldE1ldGEoZW50aXR5KTtcbiAgICBxLiR3aGVyZSA9IGF1Z21lbnRXaGVyZShtZXRhLCBxLiR3aGVyZSwgaWQpO1xuICAgIHJldHVybiB0aGlzLmZpbmRPbmUoZW50aXR5LCBxKTtcbiAgfVxuXG4gIGFzeW5jIGZpbmRPbmU8RT4oZW50aXR5OiBUeXBlPEU+LCBxOiBRdWVyeU9uZTxFPikge1xuICAgIGNvbnN0IHJvd3MgPSBhd2FpdCB0aGlzLmZpbmRNYW55KGVudGl0eSwgeyAuLi5xLCAkbGltaXQ6IDEgfSk7XG4gICAgcmV0dXJuIHJvd3NbMF07XG4gIH1cblxuICBhYnN0cmFjdCBmaW5kTWFueTxFPihlbnRpdHk6IFR5cGU8RT4sIHE6IFF1ZXJ5PEU+KTogUHJvbWlzZTxFW10+O1xuXG4gIGZpbmRNYW55QW5kQ291bnQ8RT4oZW50aXR5OiBUeXBlPEU+LCBxOiBRdWVyeTxFPikge1xuICAgIGNvbnN0IHFDb3VudCA9IHtcbiAgICAgIC4uLnEsXG4gICAgfSBzYXRpc2ZpZXMgUXVlcnlTZWFyY2g8RT47XG4gICAgZGVsZXRlIHFDb3VudC4kc29ydDtcbiAgICBkZWxldGUgcUNvdW50LiRsaW1pdDtcbiAgICBkZWxldGUgcUNvdW50LiRza2lwO1xuICAgIHJldHVybiBQcm9taXNlLmFsbChbdGhpcy5maW5kTWFueShlbnRpdHksIHEpLCB0aGlzLmNvdW50KGVudGl0eSwgcUNvdW50KV0pO1xuICB9XG5cbiAgYWJzdHJhY3QgY291bnQ8RT4oZW50aXR5OiBUeXBlPEU+LCBxOiBRdWVyeVNlYXJjaDxFPik6IFByb21pc2U8bnVtYmVyPjtcblxuICBhc3luYyBpbnNlcnRPbmU8RT4oZW50aXR5OiBUeXBlPEU+LCBwYXlsb2FkOiBFKSB7XG4gICAgY29uc3QgW2lkXSA9IGF3YWl0IHRoaXMuaW5zZXJ0TWFueShlbnRpdHksIFtwYXlsb2FkXSk7XG4gICAgcmV0dXJuIGlkO1xuICB9XG5cbiAgYWJzdHJhY3QgaW5zZXJ0TWFueTxFPihlbnRpdHk6IFR5cGU8RT4sIHBheWxvYWQ6IEVbXSk6IFByb21pc2U8SWRWYWx1ZTxFPltdPjtcblxuICB1cGRhdGVPbmVCeUlkPEU+KGVudGl0eTogVHlwZTxFPiwgaWQ6IElkVmFsdWU8RT4sIHBheWxvYWQ6IEUpIHtcbiAgICByZXR1cm4gdGhpcy51cGRhdGVNYW55KGVudGl0eSwgeyAkd2hlcmU6IGlkIH0sIHBheWxvYWQpO1xuICB9XG5cbiAgYWJzdHJhY3QgdXBkYXRlTWFueTxFPihlbnRpdHk6IFR5cGU8RT4sIHE6IFF1ZXJ5U2VhcmNoPEU+LCBwYXlsb2FkOiBFKTogUHJvbWlzZTxudW1iZXI+O1xuXG4gIGFic3RyYWN0IHVwc2VydE9uZTxFPihlbnRpdHk6IFR5cGU8RT4sIGNvbmZsaWN0UGF0aHM6IFF1ZXJ5Q29uZmxpY3RQYXRoczxFPiwgcGF5bG9hZDogRSk6IFByb21pc2U8UXVlcnlVcGRhdGVSZXN1bHQ+O1xuXG4gIGRlbGV0ZU9uZUJ5SWQ8RT4oZW50aXR5OiBUeXBlPEU+LCBpZDogSWRWYWx1ZTxFPiwgb3B0cz86IFF1ZXJ5T3B0aW9ucykge1xuICAgIHJldHVybiB0aGlzLmRlbGV0ZU1hbnkoZW50aXR5LCB7ICR3aGVyZTogaWQgfSwgb3B0cyk7XG4gIH1cblxuICBhYnN0cmFjdCBkZWxldGVNYW55PEU+KGVudGl0eTogVHlwZTxFPiwgcTogUXVlcnlTZWFyY2g8RT4sIG9wdHM/OiBRdWVyeU9wdGlvbnMpOiBQcm9taXNlPG51bWJlcj47XG5cbiAgYXN5bmMgc2F2ZU9uZTxFPihlbnRpdHk6IFR5cGU8RT4sIHBheWxvYWQ6IEUpIHtcbiAgICBjb25zdCBbaWRdID0gYXdhaXQgdGhpcy5zYXZlTWFueShlbnRpdHksIFtwYXlsb2FkXSk7XG4gICAgcmV0dXJuIGlkO1xuICB9XG5cbiAgYXN5bmMgc2F2ZU1hbnk8RT4oZW50aXR5OiBUeXBlPEU+LCBwYXlsb2FkOiBFW10pIHtcbiAgICBjb25zdCBtZXRhID0gZ2V0TWV0YShlbnRpdHkpO1xuICAgIGNvbnN0IGlkczogSWRWYWx1ZTxFPltdID0gW107XG4gICAgY29uc3QgdXBkYXRlczogRVtdID0gW107XG4gICAgY29uc3QgaW5zZXJ0czogRVtdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IGl0IG9mIHBheWxvYWQpIHtcbiAgICAgIGlmIChpdFttZXRhLmlkXSkge1xuICAgICAgICBpZiAoZ2V0S2V5cyhpdCkubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgaWRzLnB1c2goaXRbbWV0YS5pZF0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHVwZGF0ZXMucHVzaChpdCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGluc2VydHMucHVzaChpdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFByb21pc2UuYWxsKFtcbiAgICAgIC4uLmlkcyxcbiAgICAgIC4uLihpbnNlcnRzLmxlbmd0aCA/IGF3YWl0IHRoaXMuaW5zZXJ0TWFueShlbnRpdHksIGluc2VydHMpIDogW10pLFxuICAgICAgLi4udXBkYXRlcy5tYXAoYXN5bmMgKGl0KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgW21ldGEuaWRdOiBpZCwgLi4uZGF0YSB9ID0gaXQ7XG4gICAgICAgIGF3YWl0IHRoaXMudXBkYXRlT25lQnlJZChlbnRpdHksIGlkLCBkYXRhIGFzIEUpO1xuICAgICAgICByZXR1cm4gaWQ7XG4gICAgICB9KSxcbiAgICBdKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBmaWxsVG9NYW55UmVsYXRpb25zPEU+KGVudGl0eTogVHlwZTxFPiwgcGF5bG9hZDogRVtdLCBzZWxlY3Q6IFF1ZXJ5U2VsZWN0PEU+KSB7XG4gICAgaWYgKCFwYXlsb2FkLmxlbmd0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IG1ldGEgPSBnZXRNZXRhKGVudGl0eSk7XG4gICAgY29uc3QgcmVsS2V5cyA9IGZpbHRlclJlbGF0aW9uS2V5cyhtZXRhLCBzZWxlY3QpO1xuXG4gICAgZm9yIChjb25zdCByZWxLZXkgb2YgcmVsS2V5cykge1xuICAgICAgY29uc3QgcmVsT3B0cyA9IG1ldGEucmVsYXRpb25zW3JlbEtleV07XG4gICAgICBjb25zdCByZWxFbnRpdHkgPSByZWxPcHRzLmVudGl0eSgpO1xuICAgICAgY29uc3QgcmVsU2VsZWN0ID0gY2xvbmUoc2VsZWN0W3JlbEtleSBhcyBzdHJpbmddKTtcbiAgICAgIGNvbnN0IHJlbFF1ZXJ5OiBRdWVyeTx1bmtub3duPiA9XG4gICAgICAgIHJlbFNlbGVjdCA9PT0gdHJ1ZSB8fCByZWxTZWxlY3QgPT09IHVuZGVmaW5lZFxuICAgICAgICAgID8ge31cbiAgICAgICAgICA6IEFycmF5LmlzQXJyYXkocmVsU2VsZWN0KVxuICAgICAgICAgICAgPyB7ICRzZWxlY3Q6IHJlbFNlbGVjdCB9XG4gICAgICAgICAgICA6IHJlbFNlbGVjdDtcbiAgICAgIGNvbnN0IGlkcyA9IHBheWxvYWQubWFwKChpdCkgPT4gaXRbbWV0YS5pZF0pO1xuXG4gICAgICBpZiAocmVsT3B0cy50aHJvdWdoKSB7XG4gICAgICAgIGNvbnN0IGxvY2FsRmllbGQgPSByZWxPcHRzLnJlZmVyZW5jZXNbMF0ubG9jYWw7XG4gICAgICAgIGNvbnN0IHRocm91Z2hFbnRpdHkgPSByZWxPcHRzLnRocm91Z2goKTtcbiAgICAgICAgY29uc3QgdGhyb3VnaE1ldGEgPSBnZXRNZXRhKHRocm91Z2hFbnRpdHkpO1xuICAgICAgICBjb25zdCB0YXJnZXRSZWxLZXkgPSBPYmplY3Qua2V5cyh0aHJvdWdoTWV0YS5yZWxhdGlvbnMpLmZpbmQoKGtleSkgPT5cbiAgICAgICAgICB0aHJvdWdoTWV0YS5yZWxhdGlvbnNba2V5XS5yZWZlcmVuY2VzLnNvbWUoKHsgbG9jYWwgfSkgPT4gbG9jYWwgPT09IHJlbE9wdHMucmVmZXJlbmNlc1sxXS5sb2NhbCksXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IHRocm91Z2hGb3VuZHMgPSBhd2FpdCB0aGlzLmZpbmRNYW55KHRocm91Z2hFbnRpdHksIHtcbiAgICAgICAgICAuLi5yZWxRdWVyeSxcbiAgICAgICAgICAkc2VsZWN0OiB7XG4gICAgICAgICAgICBbbG9jYWxGaWVsZF06IHRydWUsXG4gICAgICAgICAgICBbdGFyZ2V0UmVsS2V5XToge1xuICAgICAgICAgICAgICAuLi5yZWxRdWVyeSxcbiAgICAgICAgICAgICAgJHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgICR3aGVyZToge1xuICAgICAgICAgICAgLi4ucmVsUXVlcnkuJHdoZXJlLFxuICAgICAgICAgICAgW2xvY2FsRmllbGRdOiBpZHMsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IGZvdW5kcyA9IHRocm91Z2hGb3VuZHMubWFwKChpdCkgPT4gKHsgLi4uaXRbdGFyZ2V0UmVsS2V5XSwgW2xvY2FsRmllbGRdOiBpdFtsb2NhbEZpZWxkXSB9KSk7XG4gICAgICAgIHRoaXMucHV0Q2hpbGRyZW5JblBhcmVudHMocGF5bG9hZCwgZm91bmRzLCBtZXRhLmlkLCBsb2NhbEZpZWxkLCByZWxLZXkpO1xuICAgICAgfSBlbHNlIGlmIChyZWxPcHRzLmNhcmRpbmFsaXR5ID09PSAnMW0nKSB7XG4gICAgICAgIGNvbnN0IGZvcmVpZ25GaWVsZCA9IHJlbE9wdHMucmVmZXJlbmNlc1swXS5mb3JlaWduO1xuICAgICAgICBpZiAocmVsUXVlcnkuJHNlbGVjdCkge1xuICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KHJlbFF1ZXJ5LiRzZWxlY3QpKSB7XG4gICAgICAgICAgICBpZiAoIXJlbFF1ZXJ5LiRzZWxlY3QuaW5jbHVkZXMoZm9yZWlnbkZpZWxkKSkge1xuICAgICAgICAgICAgICByZWxRdWVyeS4kc2VsZWN0LnB1c2goZm9yZWlnbkZpZWxkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKCFyZWxRdWVyeS4kc2VsZWN0W2ZvcmVpZ25GaWVsZF0pIHtcbiAgICAgICAgICAgIHJlbFF1ZXJ5LiRzZWxlY3RbZm9yZWlnbkZpZWxkXSA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJlbFF1ZXJ5LiR3aGVyZSA9IHsgLi4ucmVsUXVlcnkuJHdoZXJlLCBbZm9yZWlnbkZpZWxkXTogaWRzIH07XG4gICAgICAgIGNvbnN0IGZvdW5kcyA9IGF3YWl0IHRoaXMuZmluZE1hbnkocmVsRW50aXR5LCByZWxRdWVyeSk7XG4gICAgICAgIHRoaXMucHV0Q2hpbGRyZW5JblBhcmVudHMocGF5bG9hZCwgZm91bmRzLCBtZXRhLmlkLCBmb3JlaWduRmllbGQsIHJlbEtleSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIHB1dENoaWxkcmVuSW5QYXJlbnRzPEU+KFxuICAgIHBhcmVudHM6IEVbXSxcbiAgICBjaGlsZHJlbjogRVtdLFxuICAgIHBhcmVudElkS2V5OiBzdHJpbmcsXG4gICAgcmVmZXJlbmNlS2V5OiBzdHJpbmcsXG4gICAgcmVsS2V5OiBzdHJpbmcsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGNoaWxkcmVuQnlQYXJlbnRNYXAgPSBjaGlsZHJlbi5yZWR1Y2UoKGFjYywgY2hpbGQpID0+IHtcbiAgICAgIGNvbnN0IHBhcmVuSWQgPSBjaGlsZFtyZWZlcmVuY2VLZXldO1xuICAgICAgaWYgKCFhY2NbcGFyZW5JZF0pIHtcbiAgICAgICAgYWNjW3BhcmVuSWRdID0gW107XG4gICAgICB9XG4gICAgICBhY2NbcGFyZW5JZF0ucHVzaChjaGlsZCk7XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sIHt9KTtcblxuICAgIGZvciAoY29uc3QgcGFyZW50IG9mIHBhcmVudHMpIHtcbiAgICAgIGNvbnN0IHBhcmVudElkID0gcGFyZW50W3BhcmVudElkS2V5XTtcbiAgICAgIHBhcmVudFtyZWxLZXldID0gY2hpbGRyZW5CeVBhcmVudE1hcFtwYXJlbnRJZF07XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIGluc2VydFJlbGF0aW9uczxFPihlbnRpdHk6IFR5cGU8RT4sIHBheWxvYWQ6IEVbXSkge1xuICAgIGNvbnN0IG1ldGEgPSBnZXRNZXRhKGVudGl0eSk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBwYXlsb2FkLm1hcCgoaXQpID0+IHtcbiAgICAgICAgY29uc3QgcmVsS2V5cyA9IGZpbHRlclBlcnNpc3RhYmxlUmVsYXRpb25LZXlzKG1ldGEsIGl0LCAncGVyc2lzdCcpO1xuICAgICAgICBpZiAoIXJlbEtleXMubGVuZ3RoKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChyZWxLZXlzLm1hcCgocmVsS2V5KSA9PiB0aGlzLnNhdmVSZWxhdGlvbihlbnRpdHksIGl0LCByZWxLZXkpKSk7XG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHVwZGF0ZVJlbGF0aW9uczxFPihlbnRpdHk6IFR5cGU8RT4sIHE6IFF1ZXJ5U2VhcmNoPEU+LCBwYXlsb2FkOiBFKSB7XG4gICAgY29uc3QgbWV0YSA9IGdldE1ldGEoZW50aXR5KTtcbiAgICBjb25zdCByZWxLZXlzID0gZmlsdGVyUGVyc2lzdGFibGVSZWxhdGlvbktleXMobWV0YSwgcGF5bG9hZCwgJ3BlcnNpc3QnKTtcblxuICAgIGlmICghcmVsS2V5cy5sZW5ndGgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBmb3VuZHMgPSBhd2FpdCB0aGlzLmZpbmRNYW55KGVudGl0eSwgeyAuLi5xLCAkc2VsZWN0OiBbbWV0YS5pZF0gfSk7XG4gICAgY29uc3QgaWRzID0gZm91bmRzLm1hcCgoZm91bmQpID0+IGZvdW5kW21ldGEuaWRdKTtcblxuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgaWRzLm1hcCgoaWQpID0+XG4gICAgICAgIFByb21pc2UuYWxsKHJlbEtleXMubWFwKChyZWxLZXkpID0+IHRoaXMuc2F2ZVJlbGF0aW9uKGVudGl0eSwgeyAuLi5wYXlsb2FkLCBbbWV0YS5pZF06IGlkIH0sIHJlbEtleSwgdHJ1ZSkpKSxcbiAgICAgICksXG4gICAgKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBkZWxldGVSZWxhdGlvbnM8RT4oZW50aXR5OiBUeXBlPEU+LCBpZHM6IElkVmFsdWU8RT5bXSwgb3B0cz86IFF1ZXJ5T3B0aW9ucykge1xuICAgIGNvbnN0IG1ldGEgPSBnZXRNZXRhKGVudGl0eSk7XG4gICAgY29uc3QgcmVsS2V5cyA9IGZpbHRlclBlcnNpc3RhYmxlUmVsYXRpb25LZXlzKG1ldGEsIG1ldGEucmVsYXRpb25zIGFzIEUsICdkZWxldGUnKTtcblxuICAgIGZvciAoY29uc3QgcmVsS2V5IG9mIHJlbEtleXMpIHtcbiAgICAgIGNvbnN0IHJlbE9wdHMgPSBtZXRhLnJlbGF0aW9uc1tyZWxLZXldO1xuICAgICAgY29uc3QgcmVsRW50aXR5ID0gcmVsT3B0cy5lbnRpdHkoKTtcbiAgICAgIGNvbnN0IGxvY2FsRmllbGQgPSByZWxPcHRzLnJlZmVyZW5jZXNbMF0ubG9jYWw7XG4gICAgICBpZiAocmVsT3B0cy50aHJvdWdoKSB7XG4gICAgICAgIGNvbnN0IHRocm91Z2hFbnRpdHkgPSByZWxPcHRzLnRocm91Z2goKTtcbiAgICAgICAgYXdhaXQgdGhpcy5kZWxldGVNYW55KHRocm91Z2hFbnRpdHksIHsgJHdoZXJlOiB7IFtsb2NhbEZpZWxkXTogaWRzIH0gfSwgb3B0cyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGF3YWl0IHRoaXMuZGVsZXRlTWFueShyZWxFbnRpdHksIHsgW2xvY2FsRmllbGRdOiBpZHMgfSwgb3B0cyk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGFzeW5jIHNhdmVSZWxhdGlvbjxFPihlbnRpdHk6IFR5cGU8RT4sIHBheWxvYWQ6IEUsIHJlbEtleTogUmVsYXRpb25LZXk8RT4sIGlzVXBkYXRlPzogYm9vbGVhbikge1xuICAgIGNvbnN0IG1ldGEgPSBnZXRNZXRhKGVudGl0eSk7XG4gICAgY29uc3QgaWQgPSBwYXlsb2FkW21ldGEuaWRdO1xuICAgIGNvbnN0IHsgZW50aXR5OiBlbnRpdHlHZXR0ZXIsIGNhcmRpbmFsaXR5LCByZWZlcmVuY2VzLCB0aHJvdWdoIH0gPSBtZXRhLnJlbGF0aW9uc1tyZWxLZXldO1xuICAgIGNvbnN0IHJlbEVudGl0eSA9IGVudGl0eUdldHRlcigpO1xuICAgIGNvbnN0IHJlbFBheWxvYWQgPSBwYXlsb2FkW3JlbEtleV0gYXMgdW5rbm93biBhcyBSZWxhdGlvblZhbHVlPEU+W107XG5cbiAgICBpZiAoY2FyZGluYWxpdHkgPT09ICcxbScgfHwgY2FyZGluYWxpdHkgPT09ICdtbScpIHtcbiAgICAgIGlmICh0aHJvdWdoKSB7XG4gICAgICAgIGNvbnN0IGxvY2FsRmllbGQgPSByZWZlcmVuY2VzWzBdLmxvY2FsO1xuXG4gICAgICAgIGNvbnN0IHRocm91Z2hFbnRpdHkgPSB0aHJvdWdoKCk7XG4gICAgICAgIGlmIChpc1VwZGF0ZSkge1xuICAgICAgICAgIGF3YWl0IHRoaXMuZGVsZXRlTWFueSh0aHJvdWdoRW50aXR5LCB7ICR3aGVyZTogeyBbbG9jYWxGaWVsZF06IGlkIH0gfSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlbFBheWxvYWQpIHtcbiAgICAgICAgICBjb25zdCBzYXZlZElkcyA9IGF3YWl0IHRoaXMuc2F2ZU1hbnkocmVsRW50aXR5LCByZWxQYXlsb2FkKTtcbiAgICAgICAgICBjb25zdCB0aHJvdWdoQm9kaWVzID0gc2F2ZWRJZHMubWFwKChyZWxJZCkgPT4gKHtcbiAgICAgICAgICAgIFtyZWZlcmVuY2VzWzBdLmxvY2FsXTogaWQsXG4gICAgICAgICAgICBbcmVmZXJlbmNlc1sxXS5sb2NhbF06IHJlbElkLFxuICAgICAgICAgIH0pKTtcbiAgICAgICAgICBhd2FpdCB0aGlzLmluc2VydE1hbnkodGhyb3VnaEVudGl0eSwgdGhyb3VnaEJvZGllcyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3QgZm9yZWlnbkZpZWxkID0gcmVmZXJlbmNlc1swXS5mb3JlaWduO1xuICAgICAgaWYgKGlzVXBkYXRlKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuZGVsZXRlTWFueShyZWxFbnRpdHksIHsgJHdoZXJlOiB7IFtmb3JlaWduRmllbGRdOiBpZCB9IH0pO1xuICAgICAgfVxuICAgICAgaWYgKHJlbFBheWxvYWQpIHtcbiAgICAgICAgZm9yIChjb25zdCBpdCBvZiByZWxQYXlsb2FkKSB7XG4gICAgICAgICAgaXRbZm9yZWlnbkZpZWxkXSA9IGlkO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHRoaXMuc2F2ZU1hbnkocmVsRW50aXR5LCByZWxQYXlsb2FkKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoY2FyZGluYWxpdHkgPT09ICcxMScpIHtcbiAgICAgIGNvbnN0IGZvcmVpZ25GaWVsZCA9IHJlZmVyZW5jZXNbMF0uZm9yZWlnbjtcbiAgICAgIGlmIChyZWxQYXlsb2FkID09PSBudWxsKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuZGVsZXRlTWFueShyZWxFbnRpdHksIHsgJHdoZXJlOiB7IFtmb3JlaWduRmllbGRdOiBpZCB9IH0pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLnNhdmVPbmUocmVsRW50aXR5LCB7IC4uLnJlbFBheWxvYWQsIFtmb3JlaWduRmllbGRdOiBpZCB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoY2FyZGluYWxpdHkgPT09ICdtMScgJiYgcmVsUGF5bG9hZCkge1xuICAgICAgY29uc3QgbG9jYWxGaWVsZCA9IHJlZmVyZW5jZXNbMF0ubG9jYWw7XG4gICAgICBjb25zdCByZWZlcmVuY2VJZCA9IGF3YWl0IHRoaXMuaW5zZXJ0T25lKHJlbEVudGl0eSwgcmVsUGF5bG9hZCk7XG4gICAgICBhd2FpdCB0aGlzLnVwZGF0ZU9uZUJ5SWQoZW50aXR5LCBpZCwgeyBbbG9jYWxGaWVsZF06IHJlZmVyZW5jZUlkIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuXG4gIGdldFJlcG9zaXRvcnk8RT4oZW50aXR5OiBUeXBlPEU+KTogUmVwb3NpdG9yeTxFPiB7XG4gICAgcmV0dXJuIG5ldyBHZW5lcmljUmVwb3NpdG9yeShlbnRpdHksIHRoaXMpO1xuICB9XG5cbiAgYWJzdHJhY3QgcmVhZG9ubHkgaGFzT3BlblRyYW5zYWN0aW9uOiBib29sZWFuO1xuXG4gIGFzeW5jIHRyYW5zYWN0aW9uPFQ+KGNhbGxiYWNrOiAoKSA9PiBQcm9taXNlPFQ+KSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuYmVnaW5UcmFuc2FjdGlvbigpO1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgY2FsbGJhY2soKTtcbiAgICAgIGF3YWl0IHRoaXMuY29tbWl0VHJhbnNhY3Rpb24oKTtcbiAgICAgIHJldHVybiByZXM7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBhd2FpdCB0aGlzLnJvbGxiYWNrVHJhbnNhY3Rpb24oKTtcbiAgICAgIHRocm93IGVycjtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgdGhpcy5yZWxlYXNlKCk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgcmVsZWFzZUlmRnJlZSgpIHtcbiAgICBpZiAoIXRoaXMuaGFzT3BlblRyYW5zYWN0aW9uKSB7XG4gICAgICBhd2FpdCB0aGlzLnJlbGVhc2UoKTtcbiAgICB9XG4gIH1cblxuICBhYnN0cmFjdCBiZWdpblRyYW5zYWN0aW9uKCk6IFByb21pc2U8dm9pZD47XG5cbiAgYWJzdHJhY3QgY29tbWl0VHJhbnNhY3Rpb24oKTogUHJvbWlzZTx2b2lkPjtcblxuICBhYnN0cmFjdCByb2xsYmFja1RyYW5zYWN0aW9uKCk6IFByb21pc2U8dm9pZD47XG5cbiAgYWJzdHJhY3QgcmVsZWFzZSgpOiBQcm9taXNlPHZvaWQ+O1xufVxuIl19