@financialforcedev/orizuru
Version:
Streamlined communication between Heroku dynos / other worker processes
120 lines • 15.9 kB
JavaScript
;
/*
* Copyright (c) 2017-2019, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @module transport/transport
*/
const avsc_1 = require("avsc");
const fs_1 = __importDefault(require("fs"));
const path_1 = require("path");
/**
* Class used to encode and decode messages using the transport schema.
*/
class Transport {
/**
* Creates a new 'Transport' which can then be used to encode and decode messages.
*/
constructor() {
// Read jn the transport schema
const schemaPath = path_1.resolve(__dirname, './transport.avsc');
const schemaBuffer = fs_1.default.readFileSync(schemaPath);
const schema = schemaBuffer.toString();
const transport = JSON.parse(schema);
// Define the transport schema as a property.
this.compiledSchema = avsc_1.Type.forSchema(transport);
}
/**
* Decode a message using the transport schema.
*
* @param schema The [Apache Avro](https://avro.apache.org/docs/current/) schema.
* @param content The buffer from which to decode the message.
*/
decode(schema, content) {
const decompiledTransportObject = this.compiledSchema.fromBuffer(content);
const compiledContextSchema = avsc_1.Type.forSchema(JSON.parse(decompiledTransportObject.contextSchema));
const compiledWriterMessageSchema = avsc_1.Type.forSchema(JSON.parse(decompiledTransportObject.messageSchema));
const resolver = schema.createResolver(compiledWriterMessageSchema);
// Create plain objects from the AVSC types.
const context = Object.assign({}, compiledContextSchema.fromBuffer(decompiledTransportObject.contextBuffer));
const message = Object.assign({}, schema.fromBuffer(decompiledTransportObject.messageBuffer, resolver));
return { context, message };
}
/**
* Encode a message using the transport schema.
*
* @param schema The [Apache Avro](https://avro.apache.org/docs/current/) schema.
* @param context The Orizuru context for this message.
* @param message The message to send.
*/
encode(schema, { context, message }) {
const validatedContextSchema = this.getContextSchema(context);
const transport = {
contextBuffer: validatedContextSchema.toBuffer(context),
contextSchema: JSON.stringify(validatedContextSchema),
messageBuffer: schema.toBuffer(message),
messageSchema: JSON.stringify(schema)
};
return this.compiledSchema.toBuffer(transport);
}
/**
* Generates the context schema for the message.
*
* This makes sure that the schema has no anonymous types.
*
* @param context The context for which to generate the schema.
*/
getContextSchema(context) {
const compiledContextSchema = avsc_1.Type.forValue(context, {
typeHook: this.getTypeHook()
});
// Validate that the schema has no anonymous types
return avsc_1.Type.forSchema(compiledContextSchema, {
noAnonymousTypes: true
});
}
/**
* Generates type names for any anonymous types.
*
* @param schema The schema for which to generate the type names.
*/
getTypeHook() {
let i = 1;
return (schema) => {
if (schema.type && (schema.type === 'enum' || schema.type === 'fixed' || schema.type === 'record') && !schema.name) {
schema.namespace = 'com.financialforce.orizuru';
schema.name = `Context${i}`;
i++;
}
return avsc_1.Type.forSchema(schema);
};
}
}
exports.Transport = Transport;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNwb3J0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2luZGV4L3RyYW5zcG9ydC90cmFuc3BvcnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F3Qkc7Ozs7O0FBRUg7O0dBRUc7QUFFSCwrQkFBc0Q7QUFDdEQsNENBQW9CO0FBQ3BCLCtCQUErQjtBQUcvQjs7R0FFRztBQUNILE1BQWEsU0FBUztJQU9yQjs7T0FFRztJQUNIO1FBRUMsK0JBQStCO1FBQy9CLE1BQU0sVUFBVSxHQUFHLGNBQU8sQ0FBQyxTQUFTLEVBQUUsa0JBQWtCLENBQUMsQ0FBQztRQUMxRCxNQUFNLFlBQVksR0FBRyxZQUFFLENBQUMsWUFBWSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2pELE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUN2QyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRXJDLDZDQUE2QztRQUM3QyxJQUFJLENBQUMsY0FBYyxHQUFHLFdBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFakQsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ksTUFBTSxDQUF1RCxNQUFZLEVBQUUsT0FBZTtRQUVoRyxNQUFNLHlCQUF5QixHQUFRLElBQUksQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRS9FLE1BQU0scUJBQXFCLEdBQUcsV0FBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLHlCQUF5QixDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7UUFDbEcsTUFBTSwyQkFBMkIsR0FBRyxXQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMseUJBQXlCLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztRQUV4RyxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLDJCQUEyQixDQUFDLENBQUM7UUFFcEUsNENBQTRDO1FBQzVDLE1BQU0sT0FBTyxHQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLHFCQUFxQixDQUFDLFVBQVUsQ0FBQyx5QkFBeUIsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO1FBQ2hILE1BQU0sT0FBTyxHQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxVQUFVLENBQUMseUJBQXlCLENBQUMsYUFBYSxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFFM0csT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQztJQUU3QixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksTUFBTSxDQUF1RCxNQUFZLEVBQUUsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUF5QjtRQUU1SCxNQUFNLHNCQUFzQixHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUU5RCxNQUFNLFNBQVMsR0FBRztZQUNqQixhQUFhLEVBQUUsc0JBQXNCLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQztZQUN2RCxhQUFhLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxzQkFBc0IsQ0FBQztZQUNyRCxhQUFhLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7WUFDdkMsYUFBYSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDO1NBQ3JDLENBQUM7UUFFRixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBRWhELENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSyxnQkFBZ0IsQ0FBQyxPQUFZO1FBRXBDLE1BQU0scUJBQXFCLEdBQUcsV0FBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUU7WUFDcEQsUUFBUSxFQUFFLElBQUksQ0FBQyxXQUFXLEVBQUU7U0FDNUIsQ0FBQyxDQUFDO1FBRUgsa0RBQWtEO1FBQ2xELE9BQU8sV0FBSSxDQUFDLFNBQVMsQ0FBQyxxQkFBcUIsRUFBRTtZQUM1QyxnQkFBZ0IsRUFBRSxJQUFJO1NBQ3RCLENBQUMsQ0FBQztJQUVKLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssV0FBVztRQUVsQixJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDVixPQUFPLENBQUMsTUFBVyxFQUFFLEVBQUU7WUFDdEIsSUFBSSxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksS0FBSyxNQUFNLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxPQUFPLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUU7Z0JBQ25ILE1BQU0sQ0FBQyxTQUFTLEdBQUcsNEJBQTRCLENBQUM7Z0JBQ2hELE1BQU0sQ0FBQyxJQUFJLEdBQUcsVUFBVSxDQUFDLEVBQUUsQ0FBQztnQkFDNUIsQ0FBQyxFQUFFLENBQUM7YUFDSjtZQUNELE9BQU8sV0FBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUMvQixDQUFDLENBQUM7SUFDSCxDQUFDO0NBRUQ7QUExR0QsOEJBMEdDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxNy0yMDE5LCBGaW5hbmNpYWxGb3JjZS5jb20sIGluY1xuICogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqXG4gKiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuICogICBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG4gKlxuICogLSBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gKiAgICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gKiAtIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAqICAgICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvblxuICogICAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cbiAqIC0gTmVpdGhlciB0aGUgbmFtZSBvZiB0aGUgRmluYW5jaWFsRm9yY2UuY29tLCBpbmMgbm9yIHRoZSBuYW1lcyBvZiBpdHMgY29udHJpYnV0b3JzXG4gKiAgICAgIG1heSBiZSB1c2VkIHRvIGVuZG9yc2Ugb3IgcHJvbW90ZSBwcm9kdWN0cyBkZXJpdmVkIGZyb20gdGhpcyBzb2Z0d2FyZSB3aXRob3V0XG4gKiAgICAgIHNwZWNpZmljIHByaW9yIHdyaXR0ZW4gcGVybWlzc2lvbi5cbiAqXG4gKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbiAqICBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTXG4gKiAgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTExcbiAqICBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCxcbiAqICBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFNcbiAqICBPUiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUllcbiAqICBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQgKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSlcbiAqICBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cbiAqL1xuXG4vKipcbiAqIEBtb2R1bGUgdHJhbnNwb3J0L3RyYW5zcG9ydFxuICovXG5cbmltcG9ydCB7IEZvclNjaGVtYU9wdGlvbnMsIFNjaGVtYSwgVHlwZSB9IGZyb20gJ2F2c2MnO1xuaW1wb3J0IGZzIGZyb20gJ2ZzJztcbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tICdwYXRoJztcbmltcG9ydCB7IElPcml6dXJ1TWVzc2FnZSB9IGZyb20gJy4uLy4uJztcblxuLyoqXG4gKiBDbGFzcyB1c2VkIHRvIGVuY29kZSBhbmQgZGVjb2RlIG1lc3NhZ2VzIHVzaW5nIHRoZSB0cmFuc3BvcnQgc2NoZW1hLlxuICovXG5leHBvcnQgY2xhc3MgVHJhbnNwb3J0IHtcblxuXHQvKipcblx0ICogVGhlIGNvbXBpbGVkIHRyYW5zcG9ydCBbQXBhY2hlIEF2cm9dKGh0dHBzOi8vYXZyby5hcGFjaGUub3JnL2RvY3MvY3VycmVudC8pIHNjaGVtYS5cblx0ICovXG5cdHByaXZhdGUgcmVhZG9ubHkgY29tcGlsZWRTY2hlbWE6IFR5cGU7XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYSBuZXcgJ1RyYW5zcG9ydCcgd2hpY2ggY2FuIHRoZW4gYmUgdXNlZCB0byBlbmNvZGUgYW5kIGRlY29kZSBtZXNzYWdlcy5cblx0ICovXG5cdGNvbnN0cnVjdG9yKCkge1xuXG5cdFx0Ly8gUmVhZCBqbiB0aGUgdHJhbnNwb3J0IHNjaGVtYVxuXHRcdGNvbnN0IHNjaGVtYVBhdGggPSByZXNvbHZlKF9fZGlybmFtZSwgJy4vdHJhbnNwb3J0LmF2c2MnKTtcblx0XHRjb25zdCBzY2hlbWFCdWZmZXIgPSBmcy5yZWFkRmlsZVN5bmMoc2NoZW1hUGF0aCk7XG5cdFx0Y29uc3Qgc2NoZW1hID0gc2NoZW1hQnVmZmVyLnRvU3RyaW5nKCk7XG5cdFx0Y29uc3QgdHJhbnNwb3J0ID0gSlNPTi5wYXJzZShzY2hlbWEpO1xuXG5cdFx0Ly8gRGVmaW5lIHRoZSB0cmFuc3BvcnQgc2NoZW1hIGFzIGEgcHJvcGVydHkuXG5cdFx0dGhpcy5jb21waWxlZFNjaGVtYSA9IFR5cGUuZm9yU2NoZW1hKHRyYW5zcG9ydCk7XG5cblx0fVxuXG5cdC8qKlxuXHQgKiBEZWNvZGUgYSBtZXNzYWdlIHVzaW5nIHRoZSB0cmFuc3BvcnQgc2NoZW1hLlxuXHQgKlxuXHQgKiBAcGFyYW0gc2NoZW1hIFRoZSBbQXBhY2hlIEF2cm9dKGh0dHBzOi8vYXZyby5hcGFjaGUub3JnL2RvY3MvY3VycmVudC8pIHNjaGVtYS5cblx0ICogQHBhcmFtIGNvbnRlbnQgVGhlIGJ1ZmZlciBmcm9tIHdoaWNoIHRvIGRlY29kZSB0aGUgbWVzc2FnZS5cblx0ICovXG5cdHB1YmxpYyBkZWNvZGU8QyBleHRlbmRzIE9yaXp1cnUuQ29udGV4dCwgTSBleHRlbmRzIE9yaXp1cnUuTWVzc2FnZT4oc2NoZW1hOiBUeXBlLCBjb250ZW50OiBCdWZmZXIpOiBJT3JpenVydU1lc3NhZ2U8QywgTT4ge1xuXG5cdFx0Y29uc3QgZGVjb21waWxlZFRyYW5zcG9ydE9iamVjdDogYW55ID0gdGhpcy5jb21waWxlZFNjaGVtYS5mcm9tQnVmZmVyKGNvbnRlbnQpO1xuXG5cdFx0Y29uc3QgY29tcGlsZWRDb250ZXh0U2NoZW1hID0gVHlwZS5mb3JTY2hlbWEoSlNPTi5wYXJzZShkZWNvbXBpbGVkVHJhbnNwb3J0T2JqZWN0LmNvbnRleHRTY2hlbWEpKTtcblx0XHRjb25zdCBjb21waWxlZFdyaXRlck1lc3NhZ2VTY2hlbWEgPSBUeXBlLmZvclNjaGVtYShKU09OLnBhcnNlKGRlY29tcGlsZWRUcmFuc3BvcnRPYmplY3QubWVzc2FnZVNjaGVtYSkpO1xuXG5cdFx0Y29uc3QgcmVzb2x2ZXIgPSBzY2hlbWEuY3JlYXRlUmVzb2x2ZXIoY29tcGlsZWRXcml0ZXJNZXNzYWdlU2NoZW1hKTtcblxuXHRcdC8vIENyZWF0ZSBwbGFpbiBvYmplY3RzIGZyb20gdGhlIEFWU0MgdHlwZXMuXG5cdFx0Y29uc3QgY29udGV4dDogQyA9IE9iamVjdC5hc3NpZ24oe30sIGNvbXBpbGVkQ29udGV4dFNjaGVtYS5mcm9tQnVmZmVyKGRlY29tcGlsZWRUcmFuc3BvcnRPYmplY3QuY29udGV4dEJ1ZmZlcikpO1xuXHRcdGNvbnN0IG1lc3NhZ2U6IE0gPSBPYmplY3QuYXNzaWduKHt9LCBzY2hlbWEuZnJvbUJ1ZmZlcihkZWNvbXBpbGVkVHJhbnNwb3J0T2JqZWN0Lm1lc3NhZ2VCdWZmZXIsIHJlc29sdmVyKSk7XG5cblx0XHRyZXR1cm4geyBjb250ZXh0LCBtZXNzYWdlIH07XG5cblx0fVxuXG5cdC8qKlxuXHQgKiBFbmNvZGUgYSBtZXNzYWdlIHVzaW5nIHRoZSB0cmFuc3BvcnQgc2NoZW1hLlxuXHQgKlxuXHQgKiBAcGFyYW0gc2NoZW1hIFRoZSBbQXBhY2hlIEF2cm9dKGh0dHBzOi8vYXZyby5hcGFjaGUub3JnL2RvY3MvY3VycmVudC8pIHNjaGVtYS5cblx0ICogQHBhcmFtIGNvbnRleHQgVGhlIE9yaXp1cnUgY29udGV4dCBmb3IgdGhpcyBtZXNzYWdlLlxuXHQgKiBAcGFyYW0gbWVzc2FnZSBUaGUgbWVzc2FnZSB0byBzZW5kLlxuXHQgKi9cblx0cHVibGljIGVuY29kZTxDIGV4dGVuZHMgT3JpenVydS5Db250ZXh0LCBNIGV4dGVuZHMgT3JpenVydS5NZXNzYWdlPihzY2hlbWE6IFR5cGUsIHsgY29udGV4dCwgbWVzc2FnZSB9OiBJT3JpenVydU1lc3NhZ2U8QywgTT4pIHtcblxuXHRcdGNvbnN0IHZhbGlkYXRlZENvbnRleHRTY2hlbWEgPSB0aGlzLmdldENvbnRleHRTY2hlbWEoY29udGV4dCk7XG5cblx0XHRjb25zdCB0cmFuc3BvcnQgPSB7XG5cdFx0XHRjb250ZXh0QnVmZmVyOiB2YWxpZGF0ZWRDb250ZXh0U2NoZW1hLnRvQnVmZmVyKGNvbnRleHQpLFxuXHRcdFx0Y29udGV4dFNjaGVtYTogSlNPTi5zdHJpbmdpZnkodmFsaWRhdGVkQ29udGV4dFNjaGVtYSksXG5cdFx0XHRtZXNzYWdlQnVmZmVyOiBzY2hlbWEudG9CdWZmZXIobWVzc2FnZSksXG5cdFx0XHRtZXNzYWdlU2NoZW1hOiBKU09OLnN0cmluZ2lmeShzY2hlbWEpXG5cdFx0fTtcblxuXHRcdHJldHVybiB0aGlzLmNvbXBpbGVkU2NoZW1hLnRvQnVmZmVyKHRyYW5zcG9ydCk7XG5cblx0fVxuXG5cdC8qKlxuXHQgKiBHZW5lcmF0ZXMgdGhlIGNvbnRleHQgc2NoZW1hIGZvciB0aGUgbWVzc2FnZS5cblx0ICpcblx0ICogVGhpcyBtYWtlcyBzdXJlIHRoYXQgdGhlIHNjaGVtYSBoYXMgbm8gYW5vbnltb3VzIHR5cGVzLlxuXHQgKlxuXHQgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCBmb3Igd2hpY2ggdG8gZ2VuZXJhdGUgdGhlIHNjaGVtYS5cblx0ICovXG5cdHByaXZhdGUgZ2V0Q29udGV4dFNjaGVtYShjb250ZXh0OiBhbnkpIHtcblxuXHRcdGNvbnN0IGNvbXBpbGVkQ29udGV4dFNjaGVtYSA9IFR5cGUuZm9yVmFsdWUoY29udGV4dCwge1xuXHRcdFx0dHlwZUhvb2s6IHRoaXMuZ2V0VHlwZUhvb2soKVxuXHRcdH0pO1xuXG5cdFx0Ly8gVmFsaWRhdGUgdGhhdCB0aGUgc2NoZW1hIGhhcyBubyBhbm9ueW1vdXMgdHlwZXNcblx0XHRyZXR1cm4gVHlwZS5mb3JTY2hlbWEoY29tcGlsZWRDb250ZXh0U2NoZW1hLCB7XG5cdFx0XHRub0Fub255bW91c1R5cGVzOiB0cnVlXG5cdFx0fSk7XG5cblx0fVxuXG5cdC8qKlxuXHQgKiBHZW5lcmF0ZXMgdHlwZSBuYW1lcyBmb3IgYW55IGFub255bW91cyB0eXBlcy5cblx0ICpcblx0ICogQHBhcmFtIHNjaGVtYSBUaGUgc2NoZW1hIGZvciB3aGljaCB0byBnZW5lcmF0ZSB0aGUgdHlwZSBuYW1lcy5cblx0ICovXG5cdHByaXZhdGUgZ2V0VHlwZUhvb2soKTogKHNjaGVtYTogU2NoZW1hLCBvcHRzOiBGb3JTY2hlbWFPcHRpb25zKSA9PiBUeXBlIHtcblxuXHRcdGxldCBpID0gMTtcblx0XHRyZXR1cm4gKHNjaGVtYTogYW55KSA9PiB7XG5cdFx0XHRpZiAoc2NoZW1hLnR5cGUgJiYgKHNjaGVtYS50eXBlID09PSAnZW51bScgfHwgc2NoZW1hLnR5cGUgPT09ICdmaXhlZCcgfHwgc2NoZW1hLnR5cGUgPT09ICdyZWNvcmQnKSAmJiAhc2NoZW1hLm5hbWUpIHtcblx0XHRcdFx0c2NoZW1hLm5hbWVzcGFjZSA9ICdjb20uZmluYW5jaWFsZm9yY2Uub3JpenVydSc7XG5cdFx0XHRcdHNjaGVtYS5uYW1lID0gYENvbnRleHQke2l9YDtcblx0XHRcdFx0aSsrO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIFR5cGUuZm9yU2NoZW1hKHNjaGVtYSk7XG5cdFx0fTtcblx0fVxuXG59XG4iXX0=