@decaf-ts/db-decorators
Version:
Agnostic database decorators and repository
133 lines • 19.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.hashOnCreateUpdate = hashOnCreateUpdate;
exports.hash = hash;
exports.composedFromCreateUpdate = composedFromCreateUpdate;
exports.composedFromKeys = composedFromKeys;
exports.composed = composed;
exports.versionCreateUpdate = versionCreateUpdate;
exports.version = version;
exports.transient = transient;
const constants_1 = require("./constants.cjs");
const reflection_1 = require("@decaf-ts/reflection");
const decorator_validation_1 = require("@decaf-ts/decorator-validation");
const decorators_1 = require("./../operations/decorators.cjs");
const errors_1 = require("./../repository/errors.cjs");
const Repository_1 = require("./../repository/Repository.cjs");
const operations_1 = require("./../operations/index.cjs");
/**
*
* @param {str} str
* @memberOf db-decorators.model
*/
function hashOnCreateUpdate(context, data, key, model, oldModel) {
if (typeof model[key] === "undefined")
return;
const hash = decorator_validation_1.Hashing.hash(model[key]);
if (oldModel && model[key] === hash)
return;
model[key] = hash;
}
function hash() {
return (0, reflection_1.apply)((0, decorators_1.onCreateUpdate)(hashOnCreateUpdate), (0, decorator_validation_1.propMetadata)(Repository_1.Repository.key(constants_1.DBKeys.HASH), {}));
}
function composedFromCreateUpdate(context, data, key, model) {
try {
const { args, type, prefix, suffix, separator } = data;
const composed = args.map((arg) => {
if (!(arg in model))
throw new errors_1.InternalError(`Property ${arg} not found to compose from`);
if (type === "keys")
return arg;
if (typeof model[arg] === "undefined")
throw new errors_1.InternalError(`Property ${args} does not contain a value to compose from`);
return model[arg].toString();
});
if (prefix)
composed.unshift(prefix);
if (suffix)
composed.push(suffix);
model[key] = composed.join(separator);
}
catch (e) {
throw new errors_1.InternalError(`Failed to compose value: ${e}`);
}
}
function composedFrom(args, hashResult = false, separator = constants_1.DefaultSeparator, type = "values", prefix = "", suffix = "") {
const data = {
args: args,
hashResult: hashResult,
separator: separator,
type: type,
prefix: prefix,
suffix: suffix,
};
const decorators = [
(0, decorators_1.onCreateUpdate)(composedFromCreateUpdate, data),
(0, decorator_validation_1.propMetadata)(Repository_1.Repository.key(constants_1.DBKeys.COMPOSED), data),
];
if (hashResult)
decorators.push(hash());
return (0, reflection_1.apply)(...decorators);
}
function composedFromKeys(args, separator = constants_1.DefaultSeparator, hash = false, prefix = "", suffix = "") {
return composedFrom(args, hash, separator, "keys", prefix, suffix);
}
function composed(args, separator = constants_1.DefaultSeparator, hash = false, prefix = "", suffix = "") {
return composedFrom(args, hash, separator, "values", prefix, suffix);
}
/**
* Creates a decorator function that updates the version of a model during create or update operations.
*
* @param {CrudOperations} operation - The type of operation being performed (CREATE or UPDATE).
* @returns {function} A function that updates the version of the model based on the operation type.
*
* @template M - Type extending Model
* @template V - Type extending IRepository<M>
*
* @this {V} - The repository instance
* @param {Context<M>} context - The context of the operation
* @param {unknown} data - Additional data for the operation (not used in this function)
* @param {string} key - The key of the version property in the model
* @param {M} model - The model being updated
* @throws {InternalError} If an invalid operation is provided or if version update fails
*/
function versionCreateUpdate(operation) {
return function versionCreateUpdate(context, data, key, model) {
try {
switch (operation) {
case operations_1.OperationKeys.CREATE:
model[key] = 1;
break;
case operations_1.OperationKeys.UPDATE:
model[key]++;
break;
default:
throw new errors_1.InternalError(`Invalid operation: ${operation}`);
}
}
catch (e) {
throw new errors_1.InternalError(`Failed to update version: ${e}`);
}
};
}
/**
* @description Creates a decorator for versioning a property in a model.
* @summary This decorator applies multiple sub-decorators to handle version management during create and update operations.
*
* @returns {Function} A composite decorator that:
* - Sets the type of the property to Number
* - Applies a version update on create operations
* - Applies a version update on update operations
* - Adds metadata indicating this property is used for versioning
*/
function version() {
return (0, reflection_1.apply)((0, decorator_validation_1.type)(Number.name), (0, decorators_1.onCreate)(versionCreateUpdate(operations_1.OperationKeys.CREATE)), (0, decorators_1.onUpdate)(versionCreateUpdate(operations_1.OperationKeys.UPDATE)), (0, decorator_validation_1.propMetadata)(Repository_1.Repository.key(constants_1.DBKeys.VERSION), true));
}
function transient() {
return function transient(model, attribute) {
(0, decorator_validation_1.propMetadata)(Repository_1.Repository.key(constants_1.DBKeys.TRANSIENT), true)(model, attribute);
(0, decorator_validation_1.propMetadata)(Repository_1.Repository.key(constants_1.DBKeys.TRANSIENT), true)(model.constructor);
};
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjb3JhdG9ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tb2RlbC9kZWNvcmF0b3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBc0JBLGdEQVdDO0FBRUQsb0JBS0M7QUFXRCw0REEyQkM7QUEyQkQsNENBUUM7QUFFRCw0QkFRQztBQWtCRCxrREF1QkM7QUFZRCwwQkFPQztBQUVELDhCQUtDO0FBOUxELCtDQUF1RDtBQUN2RCxxREFBNkM7QUFDN0MseUVBS3dDO0FBQ3hDLCtEQUE4RTtBQUU5RSx1REFBcUQ7QUFDckQsK0RBQXNEO0FBRXRELDBEQUE4RDtBQUc5RDs7OztHQUlHO0FBRUgsU0FBZ0Isa0JBQWtCLENBTXZCLE9BQVUsRUFBRSxJQUFPLEVBQUUsR0FBWSxFQUFFLEtBQVEsRUFBRSxRQUFZO0lBQ2xFLElBQUksT0FBTyxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssV0FBVztRQUFFLE9BQU87SUFDOUMsTUFBTSxJQUFJLEdBQUcsOEJBQU8sQ0FBQyxJQUFJLENBQUUsS0FBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDL0MsSUFBSSxRQUFRLElBQUssS0FBYSxDQUFDLEdBQUcsQ0FBQyxLQUFLLElBQUk7UUFBRSxPQUFPO0lBQ3JELEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUM7QUFDcEIsQ0FBQztBQUVELFNBQWdCLElBQUk7SUFDbEIsT0FBTyxJQUFBLGtCQUFLLEVBQ1YsSUFBQSwyQkFBYyxFQUFDLGtCQUFrQixDQUFDLEVBQ2xDLElBQUEsbUNBQVksRUFBQyx1QkFBVSxDQUFDLEdBQUcsQ0FBQyxrQkFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUM5QyxDQUFDO0FBQ0osQ0FBQztBQVdELFNBQWdCLHdCQUF3QixDQU03QixPQUFVLEVBQUUsSUFBTyxFQUFFLEdBQVksRUFBRSxLQUFRO0lBQ3BELElBQUksQ0FBQztRQUNILE1BQU0sRUFBRSxJQUFJLEVBQUUs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Q0FBQyxrQkFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUMxRSxDQUFDLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgREJLZXlzLCBEZWZhdWx0U2VwYXJhdG9yIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyBhcHBseSB9IGZyb20gXCJAZGVjYWYtdHMvcmVmbGVjdGlvblwiO1xuaW1wb3J0IHtcbiAgSGFzaGluZyxcbiAgTW9kZWwsXG4gIHByb3BNZXRhZGF0YSxcbiAgdHlwZSxcbn0gZnJvbSBcIkBkZWNhZi10cy9kZWNvcmF0b3ItdmFsaWRhdGlvblwiO1xuaW1wb3J0IHsgb25DcmVhdGUsIG9uQ3JlYXRlVXBkYXRlLCBvblVwZGF0ZSB9IGZyb20gXCIuLi9vcGVyYXRpb25zL2RlY29yYXRvcnNcIjtcbmltcG9ydCB7IElSZXBvc2l0b3J5IH0gZnJvbSBcIi4uL2ludGVyZmFjZXMvSVJlcG9zaXRvcnlcIjtcbmltcG9ydCB7IEludGVybmFsRXJyb3IgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS9lcnJvcnNcIjtcbmltcG9ydCB7IFJlcG9zaXRvcnkgfSBmcm9tIFwiLi4vcmVwb3NpdG9yeS9SZXBvc2l0b3J5XCI7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvQ29udGV4dFwiO1xuaW1wb3J0IHsgQ3J1ZE9wZXJhdGlvbnMsIE9wZXJhdGlvbktleXMgfSBmcm9tIFwiLi4vb3BlcmF0aW9uc1wiO1xuaW1wb3J0IHsgUmVwb3NpdG9yeUZsYWdzIH0gZnJvbSBcIi4uL3JlcG9zaXRvcnkvdHlwZXNcIjtcblxuLyoqXG4gKlxuICogQHBhcmFtIHtzdHJ9IHN0clxuICogQG1lbWJlck9mIGRiLWRlY29yYXRvcnMubW9kZWxcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gaGFzaE9uQ3JlYXRlVXBkYXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgViBleHRlbmRzIG9iamVjdCxcbiAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgQyBleHRlbmRzIENvbnRleHQ8Rj4gPSBDb250ZXh0PEY+LFxuPih0aGlzOiBSLCBjb250ZXh0OiBDLCBkYXRhOiBWLCBrZXk6IGtleW9mIE0sIG1vZGVsOiBNLCBvbGRNb2RlbD86IE0pOiB2b2lkIHtcbiAgaWYgKHR5cGVvZiBtb2RlbFtrZXldID09PSBcInVuZGVmaW5lZFwiKSByZXR1cm47XG4gIGNvbnN0IGhhc2ggPSBIYXNoaW5nLmhhc2goKG1vZGVsIGFzIGFueSlba2V5XSk7XG4gIGlmIChvbGRNb2RlbCAmJiAobW9kZWwgYXMgYW55KVtrZXldID09PSBoYXNoKSByZXR1cm47XG4gIG1vZGVsW2tleV0gPSBoYXNoO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFzaCgpIHtcbiAgcmV0dXJuIGFwcGx5KFxuICAgIG9uQ3JlYXRlVXBkYXRlKGhhc2hPbkNyZWF0ZVVwZGF0ZSksXG4gICAgcHJvcE1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5IQVNIKSwge30pXG4gICk7XG59XG5cbmV4cG9ydCB0eXBlIENvbXBvc2VkRnJvbU1ldGFkYXRhID0ge1xuICBhcmdzOiBzdHJpbmdbXTtcbiAgc2VwYXJhdG9yOiBzdHJpbmc7XG4gIGhhc2hSZXN1bHQ6IGJvb2xlYW47XG4gIHR5cGU6IFwia2V5c1wiIHwgXCJ2YWx1ZXNcIjtcbiAgcHJlZml4Pzogc3RyaW5nO1xuICBzdWZmaXg/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gY29tcG9zZWRGcm9tQ3JlYXRlVXBkYXRlPFxuICBNIGV4dGVuZHMgTW9kZWwsXG4gIFIgZXh0ZW5kcyBJUmVwb3NpdG9yeTxNLCBGLCBDPixcbiAgViBleHRlbmRzIENvbXBvc2VkRnJvbU1ldGFkYXRhLFxuICBGIGV4dGVuZHMgUmVwb3NpdG9yeUZsYWdzID0gUmVwb3NpdG9yeUZsYWdzLFxuICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4+KHRoaXM6IFIsIGNvbnRleHQ6IEMsIGRhdGE6IFYsIGtleToga2V5b2YgTSwgbW9kZWw6IE0pIHtcbiAgdHJ5IHtcbiAgICBjb25zdCB7IGFyZ3MsIHR5cGUsIHByZWZpeCwgc3VmZml4LCBzZXBhcmF0b3IgfSA9IGRhdGE7XG4gICAgY29uc3QgY29tcG9zZWQgPSBhcmdzLm1hcCgoYXJnOiBzdHJpbmcpID0+IHtcbiAgICAgIGlmICghKGFyZyBpbiBtb2RlbCkpXG4gICAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBQcm9wZXJ0eSAke2FyZ30gbm90IGZvdW5kIHRvIGNvbXBvc2UgZnJvbWApO1xuICAgICAgaWYgKHR5cGUgPT09IFwia2V5c1wiKSByZXR1cm4gYXJnO1xuICAgICAgaWYgKHR5cGVvZiAobW9kZWwgYXMgYW55KVthcmddID09PSBcInVuZGVmaW5lZFwiKVxuICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcbiAgICAgICAgICBgUHJvcGVydHkgJHthcmdzfSBkb2VzIG5vdCBjb250YWluIGEgdmFsdWUgdG8gY29tcG9zZSBmcm9tYFxuICAgICAgICApO1xuICAgICAgcmV0dXJuICgobW9kZWwgYXMgYW55KVthcmddIGFzIGFueSkudG9TdHJpbmcoKTtcbiAgICB9KTtcblxuICAgIGlmIChwcmVmaXgpIGNvbXBvc2VkLnVuc2hpZnQocHJlZml4KTtcbiAgICBpZiAoc3VmZml4KSBjb21wb3NlZC5wdXNoKHN1ZmZpeCk7XG5cbiAgICAobW9kZWwgYXMgYW55KVtrZXldID0gY29tcG9zZWQuam9pbihzZXBhcmF0b3IpO1xuICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgRmFpbGVkIHRvIGNvbXBvc2UgdmFsdWU6ICR7ZX1gKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjb21wb3NlZEZyb20oXG4gIGFyZ3M6IHN0cmluZ1tdLFxuICBoYXNoUmVzdWx0OiBib29sZWFuID0gZmFsc2UsXG4gIHNlcGFyYXRvcjogc3RyaW5nID0gRGVmYXVsdFNlcGFyYXRvcixcbiAgdHlwZTogXCJrZXlzXCIgfCBcInZhbHVlc1wiID0gXCJ2YWx1ZXNcIixcbiAgcHJlZml4ID0gXCJcIixcbiAgc3VmZml4ID0gXCJcIlxuKSB7XG4gIGNvbnN0IGRhdGE6IENvbXBvc2VkRnJvbU1ldGFkYXRhID0ge1xuICAgIGFyZ3M6IGFyZ3MsXG4gICAgaGFzaFJlc3VsdDogaGFzaFJlc3VsdCxcbiAgICBzZXBhcmF0b3I6IHNlcGFyYXRvcixcbiAgICB0eXBlOiB0eXBlLFxuICAgIHByZWZpeDogcHJlZml4LFxuICAgIHN1ZmZpeDogc3VmZml4LFxuICB9O1xuXG4gIGNvbnN0IGRlY29yYXRvcnMgPSBbXG4gICAgb25DcmVhdGVVcGRhdGUoY29tcG9zZWRGcm9tQ3JlYXRlVXBkYXRlLCBkYXRhKSxcbiAgICBwcm9wTWV0YWRhdGEoUmVwb3NpdG9yeS5rZXkoREJLZXlzLkNPTVBPU0VEKSwgZGF0YSksXG4gIF07XG4gIGlmIChoYXNoUmVzdWx0KSBkZWNvcmF0b3JzLnB1c2goaGFzaCgpKTtcbiAgcmV0dXJuIGFwcGx5KC4uLmRlY29yYXRvcnMpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29tcG9zZWRGcm9tS2V5cyhcbiAgYXJnczogc3RyaW5nW10sXG4gIHNlcGFyYXRvcjogc3RyaW5nID0gRGVmYXVsdFNlcGFyYXRvcixcbiAgaGFzaDogYm9vbGVhbiA9IGZhbHNlLFxuICBwcmVmaXggPSBcIlwiLFxuICBzdWZmaXggPSBcIlwiXG4pIHtcbiAgcmV0dXJuIGNvbXBvc2VkRnJvbShhcmdzLCBoYXNoLCBzZXBhcmF0b3IsIFwia2V5c1wiLCBwcmVmaXgsIHN1ZmZpeCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb21wb3NlZChcbiAgYXJnczogc3RyaW5nW10sXG4gIHNlcGFyYXRvcjogc3RyaW5nID0gRGVmYXVsdFNlcGFyYXRvcixcbiAgaGFzaDogYm9vbGVhbiA9IGZhbHNlLFxuICBwcmVmaXggPSBcIlwiLFxuICBzdWZmaXggPSBcIlwiXG4pIHtcbiAgcmV0dXJuIGNvbXBvc2VkRnJvbShhcmdzLCBoYXNoLCBzZXBhcmF0b3IsIFwidmFsdWVzXCIsIHByZWZpeCwgc3VmZml4KTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgZGVjb3JhdG9yIGZ1bmN0aW9uIHRoYXQgdXBkYXRlcyB0aGUgdmVyc2lvbiBvZiBhIG1vZGVsIGR1cmluZyBjcmVhdGUgb3IgdXBkYXRlIG9wZXJhdGlvbnMuXG4gKlxuICogQHBhcmFtIHtDcnVkT3BlcmF0aW9uc30gb3BlcmF0aW9uIC0gVGhlIHR5cGUgb2Ygb3BlcmF0aW9uIGJlaW5nIHBlcmZvcm1lZCAoQ1JFQVRFIG9yIFVQREFURSkuXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IEEgZnVuY3Rpb24gdGhhdCB1cGRhdGVzIHRoZSB2ZXJzaW9uIG9mIHRoZSBtb2RlbCBiYXNlZCBvbiB0aGUgb3BlcmF0aW9uIHR5cGUuXG4gKlxuICogQHRlbXBsYXRlIE0gLSBUeXBlIGV4dGVuZGluZyBNb2RlbFxuICogQHRlbXBsYXRlIFYgLSBUeXBlIGV4dGVuZGluZyBJUmVwb3NpdG9yeTxNPlxuICpcbiAqIEB0aGlzIHtWfSAtIFRoZSByZXBvc2l0b3J5IGluc3RhbmNlXG4gKiBAcGFyYW0ge0NvbnRleHQ8TT59IGNvbnRleHQgLSBUaGUgY29udGV4dCBvZiB0aGUgb3BlcmF0aW9uXG4gKiBAcGFyYW0ge3Vua25vd259IGRhdGEgLSBBZGRpdGlvbmFsIGRhdGEgZm9yIHRoZSBvcGVyYXRpb24gKG5vdCB1c2VkIGluIHRoaXMgZnVuY3Rpb24pXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IC0gVGhlIGtleSBvZiB0aGUgdmVyc2lvbiBwcm9wZXJ0eSBpbiB0aGUgbW9kZWxcbiAqIEBwYXJhbSB7TX0gbW9kZWwgLSBUaGUgbW9kZWwgYmVpbmcgdXBkYXRlZFxuICogQHRocm93cyB7SW50ZXJuYWxFcnJvcn0gSWYgYW4gaW52YWxpZCBvcGVyYXRpb24gaXMgcHJvdmlkZWQgb3IgaWYgdmVyc2lvbiB1cGRhdGUgZmFpbHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZlcnNpb25DcmVhdGVVcGRhdGUob3BlcmF0aW9uOiBDcnVkT3BlcmF0aW9ucykge1xuICByZXR1cm4gZnVuY3Rpb24gdmVyc2lvbkNyZWF0ZVVwZGF0ZTxcbiAgICBNIGV4dGVuZHMgTW9kZWwsXG4gICAgUiBleHRlbmRzIElSZXBvc2l0b3J5PE0sIEYsIEM+LFxuICAgIFYgZXh0ZW5kcyBvYmplY3QsXG4gICAgRiBleHRlbmRzIFJlcG9zaXRvcnlGbGFncyA9IFJlcG9zaXRvcnlGbGFncyxcbiAgICBDIGV4dGVuZHMgQ29udGV4dDxGPiA9IENvbnRleHQ8Rj4sXG4gID4odGhpczogUiwgY29udGV4dDogQywgZGF0YTogViwga2V5OiBrZXlvZiBNLCBtb2RlbDogTSkge1xuICAgIHRyeSB7XG4gICAgICBzd2l0Y2ggKG9wZXJhdGlvbikge1xuICAgICAgICBjYXNlIE9wZXJhdGlvbktleXMuQ1JFQVRFOlxuICAgICAgICAgIChtb2RlbCBhcyBhbnkpW2tleV0gPSAxO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIE9wZXJhdGlvbktleXMuVVBEQVRFOlxuICAgICAgICAgIChtb2RlbCBhcyBhbnkpW2tleV0rKztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgSW52YWxpZCBvcGVyYXRpb246ICR7b3BlcmF0aW9ufWApO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKGBGYWlsZWQgdG8gdXBkYXRlIHZlcnNpb246ICR7ZX1gKTtcbiAgICB9XG4gIH07XG59XG5cbi8qKlxuICogQGRlc2NyaXB0aW9uIENyZWF0ZXMgYSBkZWNvcmF0b3IgZm9yIHZlcnNpb25pbmcgYSBwcm9wZXJ0eSBpbiBhIG1vZGVsLlxuICogQHN1bW1hcnkgVGhpcyBkZWNvcmF0b3IgYXBwbGllcyBtdWx0aXBsZSBzdWItZGVjb3JhdG9ycyB0byBoYW5kbGUgdmVyc2lvbiBtYW5hZ2VtZW50IGR1cmluZyBjcmVhdGUgYW5kIHVwZGF0ZSBvcGVyYXRpb25zLlxuICpcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gQSBjb21wb3NpdGUgZGVjb3JhdG9yIHRoYXQ6XG4gKiAgIC0gU2V0cyB0aGUgdHlwZSBvZiB0aGUgcHJvcGVydHkgdG8gTnVtYmVyXG4gKiAgIC0gQXBwbGllcyBhIHZlcnNpb24gdXBkYXRlIG9uIGNyZWF0ZSBvcGVyYXRpb25zXG4gKiAgIC0gQXBwbGllcyBhIHZlcnNpb24gdXBkYXRlIG9uIHVwZGF0ZSBvcGVyYXRpb25zXG4gKiAgIC0gQWRkcyBtZXRhZGF0YSBpbmRpY2F0aW5nIHRoaXMgcHJvcGVydHkgaXMgdXNlZCBmb3IgdmVyc2lvbmluZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gdmVyc2lvbigpIHtcbiAgcmV0dXJuIGFwcGx5KFxuICAgIHR5cGUoTnVtYmVyLm5hbWUpLFxuICAgIG9uQ3JlYXRlKHZlcnNpb25DcmVhdGVVcGRhdGUoT3BlcmF0aW9uS2V5cy5DUkVBVEUpKSxcbiAgICBvblVwZGF0ZSh2ZXJzaW9uQ3JlYXRlVXBkYXRlKE9wZXJhdGlvbktleXMuVVBEQVRFKSksXG4gICAgcHJvcE1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5WRVJTSU9OKSwgdHJ1ZSlcbiAgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRyYW5zaWVudCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uIHRyYW5zaWVudChtb2RlbDogYW55LCBhdHRyaWJ1dGU6IHN0cmluZykge1xuICAgIHByb3BNZXRhZGF0YShSZXBvc2l0b3J5LmtleShEQktleXMuVFJBTlNJRU5UKSwgdHJ1ZSkobW9kZWwsIGF0dHJpYnV0ZSk7XG4gICAgcHJvcE1ldGFkYXRhKFJlcG9zaXRvcnkua2V5KERCS2V5cy5UUkFOU0lFTlQpLCB0cnVlKShtb2RlbC5jb25zdHJ1Y3Rvcik7XG4gIH07XG59XG4iXX0=