UNPKG

nukak

Version:

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

214 lines 29.1 kB
import 'reflect-metadata'; import { getKeys, hasKeys, lowerFirst, upperFirst } from '../../util/index.js'; const holder = globalThis; const metaKey = 'nukak/entity/decorator'; const metas = holder[metaKey] ?? new Map(); holder[metaKey] = metas; export function defineField(entity, key, opts = {}) { const meta = ensureMeta(entity); if (!opts.type) { const type = inferType(entity, key); opts = { ...opts, type }; } meta.fields[key] = { ...meta.fields[key], ...{ name: key, ...opts } }; return meta; } export function defineId(entity, key, opts) { const meta = ensureMeta(entity); const id = getIdKey(meta); if (id) { console.info(`Overriding ID property for '${entity.name}' from '${id}' to '${key}'`); delete meta.fields[id]; } return defineField(entity, key, { ...opts, isId: true }); } export function defineRelation(entity, key, opts) { if (!opts.entity) { const inferredType = inferEntityType(entity, key); opts.entity = () => inferredType; } const meta = ensureMeta(entity); meta.relations[key] = { ...meta.relations[key], ...opts }; return meta; } export function defineEntity(entity, opts = {}) { const meta = ensureMeta(entity); if (!hasKeys(meta.fields)) { throw TypeError(`'${entity.name}' must have fields`); } const onDeleteKeys = getKeys(meta.fields).filter((key) => meta.fields[key].onDelete); if (onDeleteKeys.length > 1) { throw TypeError(`'${entity.name}' must have one field with 'onDelete' as maximum`); } if (opts.softDelete) { if (!onDeleteKeys.length) { throw TypeError(`'${entity.name}' must have one field with 'onDelete' to enable 'softDelete'`); } meta.softDelete = onDeleteKeys[0]; } meta.name = opts.name ?? entity.name; let proto = Object.getPrototypeOf(entity.prototype); while (proto.constructor !== Object) { const parentMeta = ensureMeta(proto.constructor); extendMeta(meta, parentMeta); proto = Object.getPrototypeOf(proto); } const id = getIdKey(meta); if (!id) { throw TypeError(`'${entity.name}' must have one field decorated with @Id`); } meta.id = id; return meta; } export function getEntities() { return [...metas.entries()].reduce((acc, [key, val]) => { if (val.id) { acc.push(key); } return acc; }, []); } function ensureMeta(entity) { let meta = metas.get(entity); if (meta) { return meta; } meta = { entity, fields: {}, relations: {} }; metas.set(entity, meta); return meta; } export function getMeta(entity) { const meta = metas.get(entity); if (!meta) { throw TypeError(`'${entity.name}' is not an entity`); } if (meta.processed) { return meta; } meta.processed = true; return fillRelations(meta); } function fillRelations(meta) { for (const relKey in meta.relations) { const relOpts = meta.relations[relKey]; if (relOpts.references) { // references were manually specified continue; } if (relOpts.mappedBy) { fillInverseSideRelations(relOpts); continue; } const relEntity = relOpts.entity(); const relMeta = ensureMeta(relEntity); if (relOpts.cardinality === 'mm') { const idName = meta.fields[meta.id].name; const relIdName = relMeta.fields[relMeta.id].name; const source = lowerFirst(meta.name) + upperFirst(idName); const target = lowerFirst(relMeta.name) + upperFirst(relIdName); relOpts.references = [ { local: source, foreign: meta.id }, { local: target, foreign: relMeta.id }, ]; } else { relOpts.references = [{ local: `${relKey}Id`, foreign: relMeta.id }]; } if (relOpts.through) { fillThroughRelations(relOpts.through()); } } return meta; } function fillInverseSideRelations(relOpts) { const relEntity = relOpts.entity(); const relMeta = getMeta(relEntity); relOpts.mappedBy = getMappedByRelationKey(relOpts); if (relMeta.fields[relOpts.mappedBy]) { relOpts.references = [{ local: relMeta.id, foreign: relOpts.mappedBy }]; return; } const mappedByRelation = relMeta.relations[relOpts.mappedBy]; if (relOpts.cardinality === 'm1' || relOpts.cardinality === 'mm') { relOpts.references = mappedByRelation.references.slice().reverse(); relOpts.through = mappedByRelation.through; return; } relOpts.references = mappedByRelation.references.map(({ local, foreign }) => ({ local: foreign, foreign: local, })); } function fillThroughRelations(entity) { const meta = ensureMeta(entity); meta.relations = getKeys(meta.fields).reduce((relations, key) => { const { reference } = meta.fields[key]; if (reference) { const relEntity = reference(); const relMeta = ensureMeta(relEntity); const relKey = key.slice(0, -relMeta.id.length); const relOpts = { entity: reference, cardinality: 'm1', references: [{ local: key, foreign: relMeta.id }], }; relations[relKey] = relOpts; } return relations; }, {}); } function getMappedByRelationKey(relOpts) { if (typeof relOpts.mappedBy === 'function') { const relEntity = relOpts.entity(); const relMeta = ensureMeta(relEntity); const keyMap = getRelationKeyMap(relMeta); return relOpts.mappedBy(keyMap); } return relOpts.mappedBy; } function getRelationKeyMap(meta) { return getKeys(meta.fields) .concat(getKeys(meta.relations)) .reduce((acc, key) => { acc[key] = key; return acc; }, {}); } function getIdKey(meta) { const id = getKeys(meta.fields).find((key) => meta.fields[key]?.isId); return id; } function extendMeta(target, source) { const sourceFields = { ...source.fields }; const targetId = getIdKey(target); if (targetId) { const sourceId = getIdKey(source); if (sourceId) { delete sourceFields[sourceId]; } } target.fields = { ...sourceFields, ...target.fields }; target.relations = { ...source.relations, ...target.relations }; } function inferType(entity, key) { return Reflect.getMetadata('design:type', entity.prototype, key); } function inferEntityType(entity, key) { const inferredType = inferType(entity, key); const isValidType = isValidEntityType(inferredType); if (!isValidType) { console.log('****', entity, key, inferredType); throw TypeError(`'${entity.name}.${key}' type was auto-inferred with invalid type '${inferredType?.name}'`); } return inferredType; } export function isValidEntityType(type) { return (typeof type === 'function' && type !== Boolean && type !== String && type !== Number && type !== BigInt && type !== Date && type !== Symbol); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVmaW5pdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9lbnRpdHkvZGVjb3JhdG9yL2RlZmluaXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxrQkFBa0IsQ0FBQztBQWExQixPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFL0UsTUFBTSxNQUFNLEdBQUcsVUFBVSxDQUFDO0FBQzFCLE1BQU0sT0FBTyxHQUFHLHdCQUF3QixDQUFDO0FBQ3pDLE1BQU0sS0FBSyxHQUF3QyxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQztBQUNoRixNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsS0FBSyxDQUFDO0FBRXhCLE1BQU0sVUFBVSxXQUFXLENBQUksTUFBZSxFQUFFLEdBQVcsRUFBRSxPQUFxQixFQUFFO0lBQ2xGLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNoQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2YsTUFBTSxJQUFJLEdBQUcsU0FBUyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNwQyxJQUFJLEdBQUcsRUFBRSxHQUFHLElBQUksRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksRUFBRSxFQUFFLENBQUM7SUFDdEUsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQsTUFBTSxVQUFVLFFBQVEsQ0FBSSxNQUFlLEVBQUUsR0FBVyxFQUFFLElBQWtCO0lBQzFFLE1BQU0sSUFBSSxH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TSxTQUFTLENBQUMsSUFBSSxNQUFNLENBQUMsSUFBSSxJQUFJLEdBQUcsK0NBQStDLFlBQVksRUFBRSxJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBQzlHLENBQUM7SUFDRCxPQUFPLFlBQVksQ0FBQztBQUN0QixDQUFDO0FBRUQsTUFBTSxVQUFVLGlCQUFpQixDQUFDLElBQWE7SUFDN0MsT0FBTyxDQUNMLE9BQU8sSUFBSSxLQUFLLFVBQVU7UUFDMUIsSUFBSSxLQUFLLE9BQU87UUFDaEIsSUFBSSxLQUFLLE1BQU07UUFDZixJQUFJLEtBQUssTUFBTTtRQUNmLElBQUksS0FBSyxNQUFNO1FBQ2YsSUFBSSxLQUFLLElBQUk7UUFDYixJQUFJLEtBQUssTUFBTSxDQUNoQixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAncmVmbGVjdC1tZXRhZGF0YSc7XG5pbXBvcnQgdHlwZSB7XG4gIEVudGl0eU1ldGEsXG4gIEVudGl0eU9wdGlvbnMsXG4gIEZpZWxkS2V5LFxuICBGaWVsZE9wdGlvbnMsXG4gIElkS2V5LFxuICBLZXksXG4gIFJlbGF0aW9uS2V5LFxuICBSZWxhdGlvbktleU1hcCxcbiAgUmVsYXRpb25PcHRpb25zLFxuICBUeXBlLFxufSBmcm9tICcuLi8uLi90eXBlL2luZGV4LmpzJztcbmltcG9ydCB7IGdldEtleXMsIGhhc0tleXMsIGxvd2VyRmlyc3QsIHVwcGVyRmlyc3QgfSBmcm9tICcuLi8uLi91dGlsL2luZGV4LmpzJztcblxuY29uc3QgaG9sZGVyID0gZ2xvYmFsVGhpcztcbmNvbnN0IG1ldGFLZXkgPSAnbnVrYWsvZW50aXR5L2RlY29yYXRvcic7XG5jb25zdCBtZXRhczogTWFwPFR5cGU8dW5rbm93bj4sIEVudGl0eU1ldGE8YW55Pj4gPSBob2xkZXJbbWV0YUtleV0gPz8gbmV3IE1hcCgpO1xuaG9sZGVyW21ldGFLZXldID0gbWV0YXM7XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWZpbmVGaWVsZDxFPihlbnRpdHk6IFR5cGU8RT4sIGtleTogc3RyaW5nLCBvcHRzOiBGaWVsZE9wdGlvbnMgPSB7fSk6IEVudGl0eU1ldGE8RT4ge1xuICBjb25zdCBtZXRhID0gZW5zdXJlTWV0YShlbnRpdHkpO1xuICBpZiAoIW9wdHMudHlwZSkge1xuICAgIGNvbnN0IHR5cGUgPSBpbmZlclR5cGUoZW50aXR5LCBrZXkpO1xuICAgIG9wdHMgPSB7IC4uLm9wdHMsIHR5cGUgfTtcbiAgfVxuICBtZXRhLmZpZWxkc1trZXldID0geyAuLi5tZXRhLmZpZWxkc1trZXldLCAuLi57IG5hbWU6IGtleSwgLi4ub3B0cyB9IH07XG4gIHJldHVybiBtZXRhO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmaW5lSWQ8RT4oZW50aXR5OiBUeXBlPEU+LCBrZXk6IHN0cmluZywgb3B0czogRmllbGRPcHRpb25zKTogRW50aXR5TWV0YTxFPiB7XG4gIGNvbnN0IG1ldGEgPSBlbnN1cmVNZXRhKGVudGl0eSk7XG4gIGNvbnN0IGlkID0gZ2V0SWRLZXkobWV0YSk7XG4gIGlmIChpZCkge1xuICAgIGNvbnNvbGUuaW5mbyhgT3ZlcnJpZGluZyBJRCBwcm9wZXJ0eSBmb3IgJyR7ZW50aXR5Lm5hbWV9JyBmcm9tICcke2lkfScgdG8gJyR7a2V5fSdgKTtcbiAgICBkZWxldGUgbWV0YS5maWVsZHNbaWRdO1xuICB9XG4gIHJldHVybiBkZWZpbmVGaWVsZChlbnRpdHksIGtleSwgeyAuLi5vcHRzLCBpc0lkOiB0cnVlIH0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmaW5lUmVsYXRpb248RT4oZW50aXR5OiBUeXBlPEU+LCBrZXk6IHN0cmluZywgb3B0czogUmVsYXRpb25PcHRpb25zPEU+KTogRW50aXR5TWV0YTxFPiB7XG4gIGlmICghb3B0cy5lbnRpdHkpIHtcbiAgICBjb25zdCBpbmZlcnJlZFR5cGUgPSBpbmZlckVudGl0eVR5cGUoZW50aXR5LCBrZXkpO1xuICAgIG9wdHMuZW50aXR5ID0gKCkgPT4gaW5mZXJyZWRUeXBlO1xuICB9XG4gIGNvbnN0IG1ldGEgPSBlbnN1cmVNZXRhKGVudGl0eSk7XG4gIG1ldGEucmVsYXRpb25zW2tleV0gPSB7IC4uLm1ldGEucmVsYXRpb25zW2tleV0sIC4uLm9wdHMgfTtcbiAgcmV0dXJuIG1ldGE7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWZpbmVFbnRpdHk8RT4oZW50aXR5OiBUeXBlPEU+LCBvcHRzOiBFbnRpdHlPcHRpb25zID0ge30pOiBFbnRpdHlNZXRhPEU+IHtcbiAgY29uc3QgbWV0YSA9IGVuc3VyZU1ldGEoZW50aXR5KTtcblxuICBpZiAoIWhhc0tleXMobWV0YS5maWVsZHMpKSB7XG4gICAgdGhyb3cgVHlwZUVycm9yKGAnJHtlbnRpdHkubmFtZX0nIG11c3QgaGF2ZSBmaWVsZHNgKTtcbiAgfVxuXG4gIGNvbnN0IG9uRGVsZXRlS2V5cyA9IGdldEtleXMobWV0YS5maWVsZHMpLmZpbHRlcigoa2V5KSA9PiBtZXRhLmZpZWxkc1trZXldLm9uRGVsZXRlKSBhcyBGaWVsZEtleTxFPltdO1xuXG4gIGlmIChvbkRlbGV0ZUtleXMubGVuZ3RoID4gMSkge1xuICAgIHRocm93IFR5cGVFcnJvcihgJyR7ZW50aXR5Lm5hbWV9JyBtdXN0IGhhdmUgb25lIGZpZWxkIHdpdGggJ29uRGVsZXRlJyBhcyBtYXhpbXVtYCk7XG4gIH1cblxuICBpZiAob3B0cy5zb2Z0RGVsZXRlKSB7XG4gICAgaWYgKCFvbkRlbGV0ZUtleXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBUeXBlRXJyb3IoYCcke2VudGl0eS5uYW1lfScgbXVzdCBoYXZlIG9uZSBmaWVsZCB3aXRoICdvbkRlbGV0ZScgdG8gZW5hYmxlICdzb2Z0RGVsZXRlJ2ApO1xuICAgIH1cbiAgICBtZXRhLnNvZnREZWxldGUgPSBvbkRlbGV0ZUtleXNbMF07XG4gIH1cblxuICBtZXRhLm5hbWUgPSBvcHRzLm5hbWUgPz8gZW50aXR5Lm5hbWU7XG4gIGxldCBwcm90bzogRnVuY3Rpb25Db25zdHJ1Y3RvciA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihlbnRpdHkucHJvdG90eXBlKTtcblxuICB3aGlsZSAocHJvdG8uY29uc3RydWN0b3IgIT09IE9iamVjdCkge1xuICAgIGNvbnN0IHBhcmVudE1ldGEgPSBlbnN1cmVNZXRhKHByb3RvLmNvbnN0cnVjdG9yIGFzIFR5cGU8RT4pO1xuICAgIGV4dGVuZE1ldGEobWV0YSwgcGFyZW50TWV0YSk7XG4gICAgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YocHJvdG8pO1xuICB9XG5cbiAgY29uc3QgaWQgPSBnZXRJZEtleShtZXRhKTtcbiAgaWYgKCFpZCkge1xuICAgIHRocm93IFR5cGVFcnJvcihgJyR7ZW50aXR5Lm5hbWV9JyBtdXN0IGhhdmUgb25lIGZpZWxkIGRlY29yYXRlZCB3aXRoIEBJZGApO1xuICB9XG4gIG1ldGEuaWQgPSBpZDtcblxuICByZXR1cm4gbWV0YTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEVudGl0aWVzKCk6IFR5cGU8dW5rbm93bj5bXSB7XG4gIHJldHVybiBbLi4ubWV0YXMuZW50cmllcygpXS5yZWR1Y2UoKGFjYywgW2tleSwgdmFsXSkgPT4ge1xuICAgIGlmICh2YWwuaWQpIHtcbiAgICAgIGFjYy5wdXNoKGtleSk7XG4gICAgfVxuICAgIHJldHVybiBhY2M7XG4gIH0sIFtdKTtcbn1cblxuZnVuY3Rpb24gZW5zdXJlTWV0YTxFPihlbnRpdHk6IFR5cGU8RT4pOiBFbnRpdHlNZXRhPEU+IHtcbiAgbGV0IG1ldGEgPSBtZXRhcy5nZXQoZW50aXR5KTtcbiAgaWYgKG1ldGEpIHtcbiAgICByZXR1cm4gbWV0YTtcbiAgfVxuICBtZXRhID0geyBlbnRpdHksIGZpZWxkczoge30sIHJlbGF0aW9uczoge30gfTtcbiAgbWV0YXMuc2V0KGVudGl0eSwgbWV0YSk7XG4gIHJldHVybiBtZXRhO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TWV0YTxFPihlbnRpdHk6IFR5cGU8RT4pOiBFbnRpdHlNZXRhPEU+IHtcbiAgY29uc3QgbWV0YSA9IG1ldGFzLmdldChlbnRpdHkpO1xuICBpZiAoIW1ldGEpIHtcbiAgICB0aHJvdyBUeXBlRXJyb3IoYCcke2VudGl0eS5uYW1lfScgaXMgbm90IGFuIGVudGl0eWApO1xuICB9XG4gIGlmIChtZXRhLnByb2Nlc3NlZCkge1xuICAgIHJldHVybiBtZXRhO1xuICB9XG4gIG1ldGEucHJvY2Vzc2VkID0gdHJ1ZTtcbiAgcmV0dXJuIGZpbGxSZWxhdGlvbnMobWV0YSk7XG59XG5cbmZ1bmN0aW9uIGZpbGxSZWxhdGlvbnM8RT4obWV0YTogRW50aXR5TWV0YTxFPik6IEVudGl0eU1ldGE8RT4ge1xuICBmb3IgKGNvbnN0IHJlbEtleSBpbiBtZXRhLnJlbGF0aW9ucykge1xuICAgIGNvbnN0IHJlbE9wdHMgPSBtZXRhLnJlbGF0aW9uc1tyZWxLZXkgYXMgUmVsYXRpb25LZXk8RT5dO1xuXG4gICAgaWYgKHJlbE9wdHMucmVmZXJlbmNlcykge1xuICAgICAgLy8gcmVmZXJlbmNlcyB3ZXJlIG1hbnVhbGx5IHNwZWNpZmllZFxuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgaWYgKHJlbE9wdHMubWFwcGVkQnkpIHtcbiAgICAgIGZpbGxJbnZlcnNlU2lkZVJlbGF0aW9ucyhyZWxPcHRzKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIGNvbnN0IHJlbEVudGl0eSA9IHJlbE9wdHMuZW50aXR5KCk7XG4gICAgY29uc3QgcmVsTWV0YSA9IGVuc3VyZU1ldGEocmVsRW50aXR5KTtcblxuICAgIGlmIChyZWxPcHRzLmNhcmRpbmFsaXR5ID09PSAnbW0nKSB7XG4gICAgICBjb25zdCBpZE5hbWUgPSBtZXRhLmZpZWxkc1ttZXRhLmlkXS5uYW1lO1xuICAgICAgY29uc3QgcmVsSWROYW1lID0gcmVsTWV0YS5maWVsZHNbcmVsTWV0YS5pZF0ubmFtZTtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IGxvd2VyRmlyc3QobWV0YS5uYW1lKSArIHVwcGVyRmlyc3QoaWROYW1lKTtcbiAgICAgIGNvbnN0IHRhcmdldCA9IGxvd2VyRmlyc3QocmVsTWV0YS5uYW1lKSArIHVwcGVyRmlyc3QocmVsSWROYW1lKTtcbiAgICAgIHJlbE9wdHMucmVmZXJlbmNlcyA9IFtcbiAgICAgICAgeyBsb2NhbDogc291cmNlLCBmb3JlaWduOiBtZXRhLmlkIH0sXG4gICAgICAgIHsgbG9jYWw6IHRhcmdldCwgZm9yZWlnbjogcmVsTWV0YS5pZCB9LFxuICAgICAgXTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVsT3B0cy5yZWZlcmVuY2VzID0gW3sgbG9jYWw6IGAke3JlbEtleX1JZGAsIGZvcmVpZ246IHJlbE1ldGEuaWQgfV07XG4gICAgfVxuXG4gICAgaWYgKHJlbE9wdHMudGhyb3VnaCkge1xuICAgICAgZmlsbFRocm91Z2hSZWxhdGlvbnMocmVsT3B0cy50aHJvdWdoKCkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtZXRhO1xufVxuXG5mdW5jdGlvbiBmaWxsSW52ZXJzZVNpZGVSZWxhdGlvbnM8RT4ocmVsT3B0czogUmVsYXRpb25PcHRpb25zPEU+KTogdm9pZCB7XG4gIGNvbnN0IHJlbEVudGl0eSA9IHJlbE9wdHMuZW50aXR5KCk7XG4gIGNvbnN0IHJlbE1ldGEgPSBnZXRNZXRhKHJlbEVudGl0eSk7XG4gIHJlbE9wdHMubWFwcGVkQnkgPSBnZXRNYXBwZWRCeVJlbGF0aW9uS2V5KHJlbE9wdHMpO1xuXG4gIGlmIChyZWxNZXRhLmZpZWxkc1tyZWxPcHRzLm1hcHBlZEJ5IGFzIEZpZWxkS2V5PEU+XSkge1xuICAgIHJlbE9wdHMucmVmZXJlbmNlcyA9IFt7IGxvY2FsOiByZWxNZXRhLmlkLCBmb3JlaWduOiByZWxPcHRzLm1hcHBlZEJ5IH1dO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IG1hcHBlZEJ5UmVsYXRpb24gPSByZWxNZXRhLnJlbGF0aW9uc1tyZWxPcHRzLm1hcHBlZEJ5IGFzIFJlbGF0aW9uS2V5PEU+XTtcblxuICBpZiAocmVsT3B0cy5jYXJkaW5hbGl0eSA9PT0gJ20xJyB8fCByZWxPcHRzLmNhcmRpbmFsaXR5ID09PSAnbW0nKSB7XG4gICAgcmVsT3B0cy5yZWZlcmVuY2VzID0gbWFwcGVkQnlSZWxhdGlvbi5yZWZlcmVuY2VzLnNsaWNlKCkucmV2ZXJzZSgpO1xuICAgIHJlbE9wdHMudGhyb3VnaCA9IG1hcHBlZEJ5UmVsYXRpb24udGhyb3VnaDtcbiAgICByZXR1cm47XG4gIH1cblxuICByZWxPcHRzLnJlZmVyZW5jZXMgPSBtYXBwZWRCeVJlbGF0aW9uLnJlZmVyZW5jZXMubWFwKCh7IGxvY2FsLCBmb3JlaWduIH0pID0+ICh7XG4gICAgbG9jYWw6IGZvcmVpZ24sXG4gICAgZm9yZWlnbjogbG9jYWwsXG4gIH0pKTtcbn1cblxuZnVuY3Rpb24gZmlsbFRocm91Z2hSZWxhdGlvbnM8RT4oZW50aXR5OiBUeXBlPEU+KTogdm9pZCB7XG4gIGNvbnN0IG1ldGEgPSBlbnN1cmVNZXRhKGVudGl0eSk7XG4gIG1ldGEucmVsYXRpb25zID0gZ2V0S2V5cyhtZXRhLmZpZWxkcykucmVkdWNlKChyZWxhdGlvbnMsIGtleSkgPT4ge1xuICAgIGNvbnN0IHsgcmVmZXJlbmNlIH0gPSBtZXRhLmZpZWxkc1trZXkgYXMgRmllbGRLZXk8RT5dO1xuICAgIGlmIChyZWZlcmVuY2UpIHtcbiAgICAgIGNvbnN0IHJlbEVudGl0eSA9IHJlZmVyZW5jZSgpO1xuICAgICAgY29uc3QgcmVsTWV0YSA9IGVuc3VyZU1ldGEocmVsRW50aXR5KTtcbiAgICAgIGNvbnN0IHJlbEtleSA9IGtleS5zbGljZSgwLCAtcmVsTWV0YS5pZC5sZW5ndGgpO1xuICAgICAgY29uc3QgcmVsT3B0czogUmVsYXRpb25PcHRpb25zID0ge1xuICAgICAgICBlbnRpdHk6IHJlZmVyZW5jZSxcbiAgICAgICAgY2FyZGluYWxpdHk6ICdtMScsXG4gICAgICAgIHJlZmVyZW5jZXM6IFt7IGxvY2FsOiBrZXksIGZvcmVpZ246IHJlbE1ldGEuaWQgfV0sXG4gICAgICB9O1xuICAgICAgcmVsYXRpb25zW3JlbEtleV0gPSByZWxPcHRzO1xuICAgIH1cbiAgICByZXR1cm4gcmVsYXRpb25zO1xuICB9LCB7fSk7XG59XG5cbmZ1bmN0aW9uIGdldE1hcHBlZEJ5UmVsYXRpb25LZXk8RT4ocmVsT3B0czogUmVsYXRpb25PcHRpb25zPEU+KTogS2V5PEU+IHtcbiAgaWYgKHR5cGVvZiByZWxPcHRzLm1hcHBlZEJ5ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgY29uc3QgcmVsRW50aXR5ID0gcmVsT3B0cy5lbnRpdHkoKTtcbiAgICBjb25zdCByZWxNZXRhID0gZW5zdXJlTWV0YShyZWxFbnRpdHkpO1xuICAgIGNvbnN0IGtleU1hcCA9IGdldFJlbGF0aW9uS2V5TWFwKHJlbE1ldGEpO1xuICAgIHJldHVybiByZWxPcHRzLm1hcHBlZEJ5KGtleU1hcCk7XG4gIH1cbiAgcmV0dXJuIHJlbE9wdHMubWFwcGVkQnk7XG59XG5cbmZ1bmN0aW9uIGdldFJlbGF0aW9uS2V5TWFwPEU+KG1ldGE6IEVudGl0eU1ldGE8RT4pOiBSZWxhdGlvbktleU1hcDxFPiB7XG4gIHJldHVybiBnZXRLZXlzKG1ldGEuZmllbGRzKVxuICAgIC5jb25jYXQoZ2V0S2V5cyhtZXRhLnJlbGF0aW9ucykpXG4gICAgLnJlZHVjZShcbiAgICAgIChhY2MsIGtleSkgPT4ge1xuICAgICAgICBhY2Nba2V5XSA9IGtleTtcbiAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgIH0sXG4gICAgICB7fSBhcyBSZWxhdGlvbktleU1hcDxFPixcbiAgICApO1xufVxuXG5mdW5jdGlvbiBnZXRJZEtleTxFPihtZXRhOiBFbnRpdHlNZXRhPEU+KTogSWRLZXk8RT4ge1xuICBjb25zdCBpZCA9IGdldEtleXMobWV0YS5maWVsZHMpLmZpbmQoKGtleSkgPT4gbWV0YS5maWVsZHNba2V5XT8uaXNJZCk7XG4gIHJldHVybiBpZCBhcyBJZEtleTxFPjtcbn1cblxuZnVuY3Rpb24gZXh0ZW5kTWV0YTxFPih0YXJnZXQ6IEVudGl0eU1ldGE8RT4sIHNvdXJjZTogRW50aXR5TWV0YTxFPik6IHZvaWQge1xuICBjb25zdCBzb3VyY2VGaWVsZHMgPSB7IC4uLnNvdXJjZS5maWVsZHMgfTtcbiAgY29uc3QgdGFyZ2V0SWQgPSBnZXRJZEtleSh0YXJnZXQpO1xuICBpZiAodGFyZ2V0SWQpIHtcbiAgICBjb25zdCBzb3VyY2VJZCA9IGdldElkS2V5KHNvdXJjZSk7XG4gICAgaWYgKHNvdXJjZUlkKSB7XG4gICAgICBkZWxldGUgc291cmNlRmllbGRzW3NvdXJjZUlkXTtcbiAgICB9XG4gIH1cbiAgdGFyZ2V0LmZpZWxkcyA9IHsgLi4uc291cmNlRmllbGRzLCAuLi50YXJnZXQuZmllbGRzIH07XG4gIHRhcmdldC5yZWxhdGlvbnMgPSB7IC4uLnNvdXJjZS5yZWxhdGlvbnMsIC4uLnRhcmdldC5yZWxhdGlvbnMgfTtcbn1cblxuZnVuY3Rpb24gaW5mZXJUeXBlPEU+KGVudGl0eTogVHlwZTxFPiwga2V5OiBzdHJpbmcpOiBhbnkge1xuICByZXR1cm4gUmVmbGVjdC5nZXRNZXRhZGF0YSgnZGVzaWduOnR5cGUnLCBlbnRpdHkucHJvdG90eXBlLCBrZXkpO1xufVxuXG5mdW5jdGlvbiBpbmZlckVudGl0eVR5cGU8RT4oZW50aXR5OiBUeXBlPEU+LCBrZXk6IHN0cmluZyk6IFR5cGU8YW55PiB7XG4gIGNvbnN0IGluZmVycmVkVHlwZSA9IGluZmVyVHlwZShlbnRpdHksIGtleSk7XG4gIGNvbnN0IGlzVmFsaWRUeXBlID0gaXNWYWxpZEVudGl0eVR5cGUoaW5mZXJyZWRUeXBlKTtcbiAgaWYgKCFpc1ZhbGlkVHlwZSkge1xuICAgIGNvbnNvbGUubG9nKCcqKioqJywgZW50aXR5LCBrZXksIGluZmVycmVkVHlwZSk7XG4gICAgdGhyb3cgVHlwZUVycm9yKGAnJHtlbnRpdHkubmFtZX0uJHtrZXl9JyB0eXBlIHdhcyBhdXRvLWluZmVycmVkIHdpdGggaW52YWxpZCB0eXBlICcke2luZmVycmVkVHlwZT8ubmFtZX0nYCk7XG4gIH1cbiAgcmV0dXJuIGluZmVycmVkVHlwZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRFbnRpdHlUeXBlKHR5cGU6IHVua25vd24pOiB0eXBlIGlzIFR5cGU8dW5rbm93bj4ge1xuICByZXR1cm4gKFxuICAgIHR5cGVvZiB0eXBlID09PSAnZnVuY3Rpb24nICYmXG4gICAgdHlwZSAhPT0gQm9vbGVhbiAmJlxuICAgIHR5cGUgIT09IFN0cmluZyAmJlxuICAgIHR5cGUgIT09IE51bWJlciAmJlxuICAgIHR5cGUgIT09IEJpZ0ludCAmJlxuICAgIHR5cGUgIT09IERhdGUgJiZcbiAgICB0eXBlICE9PSBTeW1ib2xcbiAgKTtcbn1cbiJdfQ==