@financialforcedev/orizuru
Version:
Streamlined communication between Heroku dynos / other worker processes
168 lines • 22.4 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 __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const http_status_codes_1 = require("http-status-codes");
const lodash_1 = require("lodash");
const RouteMethod = __importStar(require("../server/routeMethod"));
const schema_1 = require("./shared/schema");
/**
* The default response writer.
*
* @param server The Orizuru server instance.
*/
function defaultResponseWriter(server) {
return (error, request, response) => {
if (error) {
server.error(error);
response.status(http_status_codes_1.BAD_REQUEST).send({
error: error.message
});
}
else {
response.sendStatus(http_status_codes_1.OK);
}
};
}
/**
* Generates the default path for the route.
*
* @param namespace The schema namespace.
*/
function defaultPathMapper(namespace) {
return namespace.replace(/\./g, '/').replace('_', '.');
}
/**
* Generates the endpoint for the route.
*
* @param [endpoint] Optional endpoint to validate.
*/
function getEndpoint(endpoint) {
if (!endpoint) {
return '/';
}
if (endpoint.startsWith('/')) {
return endpoint;
}
return '/' + endpoint;
}
/**
* Gets the schema name from the [Apache Avro](https://avro.apache.org/docs/current/) schema.
*
* @param avroSchema The [Apache Avro](https://avro.apache.org/docs/current/) schema.
*/
function getSchemaName(avroSchema) {
const schemaNameParts = avroSchema.name.split('.');
return schemaNameParts.pop();
}
/**
* Calculates the full API endpoint for this route.
*
* @param schema The [Apache Avro](https://avro.apache.org/docs/current/) schema.
* @param endpoint The endpoint for the route.
* @param pathMapper The path mapper.
*/
function calculateApiEndpoint(schema, endpoint, pathMapper) {
const schemaName = getSchemaName(schema);
const schemaNameParts = schema.name.split('.');
schemaNameParts.pop();
const schemaNamespace = schemaNameParts.join('.');
return endpoint + pathMapper(schemaNamespace) + '/' + schemaName;
}
/**
* Validates the {@link Route} configuration.
*/
class RouteValidator {
/**
* Validate the route configuration options.
* @param options The route configuration options to validate.
*/
validate(options) {
if (!options) {
throw new Error('Missing required object parameter.');
}
if (!lodash_1.isPlainObject(options)) {
throw new Error(`Invalid parameter: ${options} is not an object.`);
}
if (options.endpoint && !lodash_1.isString(options.endpoint)) {
throw new Error('Invalid parameter: endpoint is not a string.');
}
if (options.method && !lodash_1.isString(options.method)) {
throw new Error('Invalid parameter: method is not a string.');
}
if (options.method && !Object.values(RouteMethod).find((value) => value === options.method)) {
throw new Error(`Invalid parameter: method must be one of the following options: ${Object.values(RouteMethod)}. Got ${options.method}.`);
}
if (options.middleware) {
if (!lodash_1.isArray(options.middleware)) {
throw new Error('Invalid parameter: middleware is not an array.');
}
options.middleware.forEach(((middleware, index) => {
if (!lodash_1.isFunction(middleware)) {
throw new Error(`Invalid parameter: middleware[${index}] is not a function.`);
}
}));
}
if (options.responseWriter && !lodash_1.isFunction(options.responseWriter)) {
throw new Error('Invalid parameter: responseWriter is not a function.');
}
if (options.pathMapper && !lodash_1.isFunction(options.pathMapper)) {
throw new Error('Invalid parameter: pathMapper is not a function.');
}
if (options.synchronous !== undefined && !lodash_1.isBoolean(options.synchronous)) {
throw new Error('Invalid parameter: synchronous is not a boolean.');
}
// Validate the schema
const avroSchema = new schema_1.SchemaValidator().validate(options.schema);
const endpoint = getEndpoint(options.endpoint);
const pathMapper = options.pathMapper || defaultPathMapper;
const apiEndpoint = calculateApiEndpoint(avroSchema, endpoint, pathMapper);
const validatedOptions = {
apiEndpoint,
fullSchemaName: avroSchema.name,
method: options.method || RouteMethod.POST,
middleware: options.middleware || [],
pathMapper: options.pathMapper || defaultPathMapper,
publishOptions: options.publishOptions || {
eventName: avroSchema.name
},
responseWriter: options.responseWriter || defaultResponseWriter,
schema: avroSchema,
schemaName: getSchemaName(avroSchema),
synchronous: options.synchronous || false
};
return validatedOptions;
}
}
exports.RouteValidator = RouteValidator;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaW5kZXgvdmFsaWRhdG9yL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHOzs7Ozs7Ozs7QUFPSCx5REFBb0Q7QUFDcEQsbUNBQWlGO0FBR2pGLG1FQUFxRDtBQUNyRCw0Q0FBa0Q7QUF5RGxEOzs7O0dBSUc7QUFDSCxTQUFTLHFCQUFxQixDQUFDLE1BQXVCO0lBRXJELE9BQU8sQ0FBQyxLQUF3QixFQUFFLE9BQWdCLEVBQUUsUUFBa0IsRUFBRSxFQUFFO1FBQ3pFLElBQUksS0FBSyxFQUFFO1lBQ1YsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNwQixRQUFRLENBQUMsTUFBTSxDQUFDLCtCQUFXLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQ2pDLEtBQUssRUFBRSxLQUFLLENBQUMsT0FBTzthQUNwQixDQUFDLENBQUM7U0FDSDthQUFNO1lBQ04sUUFBUSxDQUFDLFVBQVUsQ0FBQyxzQkFBRSxDQUFDLENBQUM7U0FDeEI7SUFDRixDQUFDLENBQUM7QUFFSCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsaUJBQWlCLENBQUMsU0FBaUI7SUFDM0MsT0FBTyxTQUFTLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBQ3hELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxXQUFXLENBQUMsUUFBaUI7SUFFckMsSUFBSSxDQUFDLFFBQVEsRUFBRTtRQUNkLE9BQU8sR0FBRyxDQUFDO0tBQ1g7SUFFRCxJQUFJLFFBQVEsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUU7UUFDN0IsT0FBTyxRQUFRLENBQUM7S0FDaEI7SUFFRCxPQUFPLEdBQUcsR0FBRyxRQUFRLENBQUM7QUFFdkIs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aWdodCAoYykgMjAxNy0yMDE5LCBGaW5hbmNpYWxGb3JjZS5jb20sIGluY1xuICogQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqXG4gKiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXQgbW9kaWZpY2F0aW9uLFxuICogICBhcmUgcGVybWl0dGVkIHByb3ZpZGVkIHRoYXQgdGhlIGZvbGxvd2luZyBjb25kaXRpb25zIGFyZSBtZXQ6XG4gKlxuICogLSBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gKiAgICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG4gKiAtIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSxcbiAqICAgICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvblxuICogICAgICBhbmQvb3Igb3RoZXIgbWF0ZXJpYWxzIHByb3ZpZGVkIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi5cbiAqIC0gTmVpdGhlciB0aGUgbmFtZSBvZiB0aGUgRmluYW5jaWFsRm9yY2UuY29tLCBpbmMgbm9yIHRoZSBuYW1lcyBvZiBpdHMgY29udHJpYnV0b3JzXG4gKiAgICAgIG1heSBiZSB1c2VkIHRvIGVuZG9yc2Ugb3IgcHJvbW90ZSBwcm9kdWN0cyBkZXJpdmVkIGZyb20gdGhpcyBzb2Z0d2FyZSB3aXRob3V0XG4gKiAgICAgIHNwZWNpZmljIHByaW9yIHdyaXR0ZW4gcGVybWlzc2lvbi5cbiAqXG4gKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbiAqICBBTlkgRVhQUkVTUyBPUiBJTVBMSUVEIFdBUlJBTlRJRVMsIElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBUSEUgSU1QTElFRCBXQVJSQU5USUVTXG4gKiAgT0YgTUVSQ0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBUkUgRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTExcbiAqICBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCxcbiAqICBFWEVNUExBUlksIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFNcbiAqICBPUiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUllcbiAqICBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlQgKElOQ0xVRElORyBORUdMSUdFTkNFIE9SIE9USEVSV0lTRSlcbiAqICBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0UgT0YgVEhJUyBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cbiAqL1xuXG4vKipcbiAqIEBtb2R1bGUgdmFsaWRhdG9yL3JvdXRlXG4gKi9cblxuaW1wb3J0IHsgRXJyb3JSZXF1ZXN0SGFuZGxlciwgUmVxdWVzdEhhbmRsZXIgfSBmcm9tICdleHByZXNzLXNlcnZlLXN0YXRpYy1jb3JlJztcbmltcG9ydCB7IEJBRF9SRVFVRVNULCBPSyB9IGZyb20gJ2h0dHAtc3RhdHVzLWNvZGVzJztcbmltcG9ydCB7IGlzQXJyYXksIGlzQm9vbGVhbiwgaXNGdW5jdGlvbiwgaXNQbGFpbk9iamVjdCwgaXNTdHJpbmcgfSBmcm9tICdsb2Rhc2gnO1xuXG5pbXBvcnQgeyBBdnJvU2NoZW1hLCBPcHRpb25zLCBSZXF1ZXN0LCBSZXNwb25zZSwgUmVzcG9uc2VXcml0ZXJGdW5jdGlvbiB9IGZyb20gJy4uLy4uJztcbmltcG9ydCAqIGFzIFJvdXRlTWV0aG9kIGZyb20gJy4uL3NlcnZlci9yb3V0ZU1ldGhvZCc7XG5pbXBvcnQgeyBTY2hlbWFWYWxpZGF0b3IgfSBmcm9tICcuL3NoYXJlZC9zY2hlbWEnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFJvdXRlQ29uZmlndXJhdGlvbiB7XG5cblx0LyoqXG5cdCAqIFRoZSBBUEkgZW5kcG9pbnQgZm9yIHRoaXMgcm91dGUuXG5cdCAqL1xuXHRhcGlFbmRwb2ludDogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBUaGUgZnVsbCBuYW1lIGZvciB0aGUgc2NoZW1hLlxuXHQgKi9cblx0ZnVsbFNjaGVtYU5hbWU6IHN0cmluZztcblxuXHQvKipcblx0ICogVGhlIEhUVFAgbWV0aG9kIGZvciB0aGlzIHJvdXRlLlxuXHQgKi9cblx0bWV0aG9kOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFRoZSBtaWRkbGV3YXJlIGZvciB0aGlzIHJvdXRlLlxuXHQgKi9cblx0bWlkZGxld2FyZTogQXJyYXk8RXJyb3JSZXF1ZXN0SGFuZGxlciB8IFJlcXVlc3RIYW5kbGVyPjtcblxuXHQvKipcblx0ICogQSBmdW5jdGlvbiB0aGF0IG1hcHMgdGhlIHNjaGVtYSBuYW1lc3BhY2UgdG8gdGhlIHJlcXVpcmVkIGZvcm1hdC5cblx0ICovXG5cdHBhdGhNYXBwZXI6IChzY2hlbWFOYW1lc3BhY2U6IHN0cmluZykgPT4gc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBUaGUgcHVibGlzaCBvcHRpb25zIHJlcXVpcmVkIGZvciB0aGUgdHJhbnNwb3J0IGxheWVyLlxuXHQgKi9cblx0cHVibGlzaE9wdGlvbnM6IE9wdGlvbnMuVHJhbnNwb3J0LklQdWJsaXNoO1xuXG5cdC8qKlxuXHQgKiBXcml0ZXMgdGhlIHJlc3BvbnNlIHRvIHRoZSBpbmNvbWluZyByZXF1ZXN0LlxuXHQgKi9cblx0cmVzcG9uc2VXcml0ZXI6IFJlc3BvbnNlV3JpdGVyRnVuY3Rpb247XG5cblx0LyoqXG5cdCAqIFRoZSBbQXBhY2hlIEF2cm9dKGh0dHBzOi8vYXZyby5hcGFjaGUub3JnL2RvY3MvY3VycmVudC8pIHNjaGVtYSB0aGF0IG1lc3NhZ2VzIGZvciB0aGlzIHJvdXRlIHNob3VsZCBiZSB2YWxpZGF0ZWQgYWdhaW5zdC5cblx0ICovXG5cdHNjaGVtYTogQXZyb1NjaGVtYTtcblxuXHQvKipcblx0ICogVGhlIHNjaGVtYSBuYW1lLlxuXHQgKi9cblx0c2NoZW1hTmFtZTogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBEZXRlcm1pbmVzIHdoZXRoZXIgdGhpcyBwcm9jZXNzIGlzIGRlYWx0IHdpdGggc3luY2hyb25vdXNseS5cblx0ICogQnkgZGVmYXVsdCwgZmFsc2UuXG5cdCAqL1xuXHRzeW5jaHJvbm91cz86IGJvb2xlYW47XG5cbn1cblxuLyoqXG4gKiBUaGUgZGVmYXVsdCByZXNwb25zZSB3cml0ZXIuXG4gKlxuICogQHBhcmFtIHNlcnZlciBUaGUgT3JpenVydSBzZXJ2ZXIgaW5zdGFuY2UuXG4gKi9cbmZ1bmN0aW9uIGRlZmF1bHRSZXNwb25zZVdyaXRlcihzZXJ2ZXI6IE9yaXp1cnUuSVNlcnZlcikge1xuXG5cdHJldHVybiAoZXJyb3I6IEVycm9yIHwgdW5kZWZpbmVkLCByZXF1ZXN0OiBSZXF1ZXN0LCByZXNwb25zZTogUmVzcG9uc2UpID0+IHtcblx0XHRpZiAoZXJyb3IpIHtcblx0XHRcdHNlcnZlci5lcnJvcihlcnJvcik7XG5cdFx0XHRyZXNwb25zZS5zdGF0dXMoQkFEX1JFUVVFU1QpLnNlbmQoe1xuXHRcdFx0XHRlcnJvcjogZXJyb3IubWVzc2FnZVxuXHRcdFx0fSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJlc3BvbnNlLnNlbmRTdGF0dXMoT0spO1xuXHRcdH1cblx0fTtcblxufVxuXG4vKipcbiAqIEdlbmVyYXRlcyB0aGUgZGVmYXVsdCBwYXRoIGZvciB0aGUgcm91dGUuXG4gKlxuICogQHBhcmFtIG5hbWVzcGFjZSBUaGUgc2NoZW1hIG5hbWVzcGFjZS5cbiAqL1xuZnVuY3Rpb24gZGVmYXVsdFBhdGhNYXBwZXIobmFtZXNwYWNlOiBzdHJpbmcpIHtcblx0cmV0dXJuIG5hbWVzcGFjZS5yZXBsYWNlKC9cXC4vZywgJy8nKS5yZXBsYWNlKCdfJywgJy4nKTtcbn1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgdGhlIGVuZHBvaW50IGZvciB0aGUgcm91dGUuXG4gKlxuICogQHBhcmFtIFtlbmRwb2ludF0gT3B0aW9uYWwgZW5kcG9pbnQgdG8gdmFsaWRhdGUuXG4gKi9cbmZ1bmN0aW9uIGdldEVuZHBvaW50KGVuZHBvaW50Pzogc3RyaW5nKSB7XG5cblx0aWYgKCFlbmRwb2ludCkge1xuXHRcdHJldHVybiAnLyc7XG5cdH1cblxuXHRpZiAoZW5kcG9pbnQuc3RhcnRzV2l0aCgnLycpKSB7XG5cdFx0cmV0dXJuIGVuZHBvaW50O1xuXHR9XG5cblx0cmV0dXJuICcvJyArIGVuZHBvaW50O1xuXG59XG5cbi8qKlxuICogR2V0cyB0aGUgc2NoZW1hIG5hbWUgZnJvbSB0aGUgW0FwYWNoZSBBdnJvXShodHRwczovL2F2cm8uYXBhY2hlLm9yZy9kb2NzL2N1cnJlbnQvKSBzY2hlbWEuXG4gKlxuICogQHBhcmFtIGF2cm9TY2hlbWEgVGhlIFtBcGFjaGUgQXZyb10oaHR0cHM6Ly9hdnJvLmFwYWNoZS5vcmcvZG9jcy9jdXJyZW50Lykgc2NoZW1hLlxuICovXG5mdW5jdGlvbiBnZXRTY2hlbWFOYW1lKGF2cm9TY2hlbWE6IEF2cm9TY2hlbWEpIHtcblx0Y29uc3Qgc2NoZW1hTmFtZVBhcnRzID0gYXZyb1NjaGVtYS5uYW1lLnNwbGl0KCcuJyk7XG5cdHJldHVybiBzY2hlbWFOYW1lUGFydHMucG9wKCkgYXMgc3RyaW5nO1xufVxuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGZ1bGwgQVBJIGVuZHBvaW50IGZvciB0aGlzIHJvdXRlLlxuICpcbiAqIEBwYXJhbSBzY2hlbWEgVGhlIFtBcGFjaGUgQXZyb10oaHR0cHM6Ly9hdnJvLmFwYWNoZS5vcmcvZG9jcy9jdXJyZW50Lykgc2NoZW1hLlxuICogQHBhcmFtIGVuZHBvaW50IFRoZSBlbmRwb2ludCBmb3IgdGhlIHJvdXRlLlxuICogQHBhcmFtIHBhdGhNYXBwZXIgVGhlIHBhdGggbWFwcGVyLlxuICovXG5mdW5jdGlvbiBjYWxjdWxhdGVBcGlFbmRwb2ludChzY2hlbWE6IEF2cm9TY2hlbWEsIGVuZHBvaW50OiBzdHJpbmcsIHBhdGhNYXBwZXI6IChzY2hlbWFOYW1lc3BhY2U6IHN0cmluZykgPT4gc3RyaW5nKSB7XG5cdGNvbnN0IHNjaGVtYU5hbWUgPSBnZXRTY2hlbWFOYW1lKHNjaGVtYSk7XG5cdGNvbnN0IHNjaGVtYU5hbWVQYXJ0cyA9IHNjaGVtYS5uYW1lLnNwbGl0KCcuJyk7XG5cdHNjaGVtYU5hbWVQYXJ0cy5wb3AoKTtcblx0Y29uc3Qgc2NoZW1hTmFtZXNwYWNlID0gc2NoZW1hTmFtZVBhcnRzLmpvaW4oJy4nKTtcblx0cmV0dXJuIGVuZHBvaW50ICsgcGF0aE1hcHBlcihzY2hlbWFOYW1lc3BhY2UpICsgJy8nICsgc2NoZW1hTmFtZTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgdGhlIHtAbGluayBSb3V0ZX0gY29uZmlndXJhdGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIFJvdXRlVmFsaWRhdG9yIHtcblxuXHQvKipcblx0ICogVmFsaWRhdGUgdGhlIHJvdXRlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucy5cblx0ICogQHBhcmFtIG9wdGlvbnMgVGhlIHJvdXRlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyB0byB2YWxpZGF0ZS5cblx0ICovXG5cdHB1YmxpYyB2YWxpZGF0ZShvcHRpb25zOiBPcHRpb25zLklSb3V0ZUNvbmZpZ3VyYXRpb24pOiBSb3V0ZUNvbmZpZ3VyYXRpb24ge1xuXG5cdFx0aWYgKCFvcHRpb25zKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgb2JqZWN0IHBhcmFtZXRlci4nKTtcblx0XHR9XG5cblx0XHRpZiAoIWlzUGxhaW5PYmplY3Qob3B0aW9ucykpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBwYXJhbWV0ZXI6ICR7b3B0aW9uc30gaXMgbm90IGFuIG9iamVjdC5gKTtcblx0XHR9XG5cblx0XHRpZiAob3B0aW9ucy5lbmRwb2ludCAmJiAhaXNTdHJpbmcob3B0aW9ucy5lbmRwb2ludCkpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignSW52YWxpZCBwYXJhbWV0ZXI6IGVuZHBvaW50IGlzIG5vdCBhIHN0cmluZy4nKTtcblx0XHR9XG5cblx0XHRpZiAob3B0aW9ucy5tZXRob2QgJiYgIWlzU3RyaW5nKG9wdGlvbnMubWV0aG9kKSkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHBhcmFtZXRlcjogbWV0aG9kIGlzIG5vdCBhIHN0cmluZy4nKTtcblx0XHR9XG5cblx0XHRpZiAob3B0aW9ucy5tZXRob2QgJiYgIU9iamVjdC52YWx1ZXMoUm91dGVNZXRob2QpLmZpbmQoKHZhbHVlKSA9PiB2YWx1ZSA9PT0gb3B0aW9ucy5tZXRob2QpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcGFyYW1ldGVyOiBtZXRob2QgbXVzdCBiZSBvbmUgb2YgdGhlIGZvbGxvd2luZyBvcHRpb25zOiAke09iamVjdC52YWx1ZXMoUm91dGVNZXRob2QpfS4gR290ICR7b3B0aW9ucy5tZXRob2R9LmApO1xuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zLm1pZGRsZXdhcmUpIHtcblxuXHRcdFx0aWYgKCFpc0FycmF5KG9wdGlvbnMubWlkZGxld2FyZSkpIHtcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHBhcmFtZXRlcjogbWlkZGxld2FyZSBpcyBub3QgYW4gYXJyYXkuJyk7XG5cdFx0XHR9XG5cblx0XHRcdG9wdGlvbnMubWlkZGxld2FyZS5mb3JFYWNoKCgobWlkZGxld2FyZSwgaW5kZXgpID0+IHtcblx0XHRcdFx0aWYgKCFpc0Z1bmN0aW9uKG1pZGRsZXdhcmUpKSB7XG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHBhcmFtZXRlcjogbWlkZGxld2FyZVske2luZGV4fV0gaXMgbm90IGEgZnVuY3Rpb24uYCk7XG5cdFx0XHRcdH1cblx0XHRcdH0pKTtcblxuXHRcdH1cblxuXHRcdGlmIChvcHRpb25zLnJlc3BvbnNlV3JpdGVyICYmICFpc0Z1bmN0aW9uKG9wdGlvbnMucmVzcG9uc2VXcml0ZXIpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgcGFyYW1ldGVyOiByZXNwb25zZVdyaXRlciBpcyBub3QgYSBmdW5jdGlvbi4nKTtcblx0XHR9XG5cblx0XHRpZiAob3B0aW9ucy5wYXRoTWFwcGVyICYmICFpc0Z1bmN0aW9uKG9wdGlvbnMucGF0aE1hcHBlcikpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignSW52YWxpZCBwYXJhbWV0ZXI6IHBhdGhNYXBwZXIgaXMgbm90IGEgZnVuY3Rpb24uJyk7XG5cdFx0fVxuXG5cdFx0aWYgKG9wdGlvbnMuc3luY2hyb25vdXMgIT09IHVuZGVmaW5lZCAmJiAhaXNCb29sZWFuKG9wdGlvbnMuc3luY2hyb25vdXMpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgcGFyYW1ldGVyOiBzeW5jaHJvbm91cyBpcyBub3QgYSBib29sZWFuLicpO1xuXHRcdH1cblxuXHRcdC8vIFZhbGlkYXRlIHRoZSBzY2hlbWFcblx0XHRjb25zdCBhdnJvU2NoZW1hID0gbmV3IFNjaGVtYVZhbGlkYXRvcigpLnZhbGlkYXRlKG9wdGlvbnMuc2NoZW1hKTtcblxuXHRcdGNvbnN0IGVuZHBvaW50ID0gZ2V0RW5kcG9pbnQob3B0aW9ucy5lbmRwb2ludCk7XG5cdFx0Y29uc3QgcGF0aE1hcHBlciA9IG9wdGlvbnMucGF0aE1hcHBlciB8fCBkZWZhdWx0UGF0aE1hcHBlcjtcblx0XHRjb25zdCBhcGlFbmRwb2ludCA9IGNhbGN1bGF0ZUFwaUVuZHBvaW50KGF2cm9TY2hlbWEsIGVuZHBvaW50LCBwYXRoTWFwcGVyKTtcblxuXHRcdGNvbnN0IHZhbGlkYXRlZE9wdGlvbnM6IFJvdXRlQ29uZmlndXJhdGlvbiA9IHtcblx0XHRcdGFwaUVuZHBvaW50LFxuXHRcdFx0ZnVsbFNjaGVtYU5hbWU6IGF2cm9TY2hlbWEubmFtZSxcblx0XHRcdG1ldGhvZDogb3B0aW9ucy5tZXRob2QgfHwgUm91dGVNZXRob2QuUE9TVCxcblx0XHRcdG1pZGRsZXdhcmU6IG9wdGlvbnMubWlkZGxld2FyZSB8fCBbXSxcblx0XHRcdHBhdGhNYXBwZXI6IG9wdGlvbnMucGF0aE1hcHBlciB8fCBkZWZhdWx0UGF0aE1hcHBlcixcblx0XHRcdHB1Ymxpc2hPcHRpb25zOiBvcHRpb25zLnB1Ymxpc2hPcHRpb25zIHx8IHtcblx0XHRcdFx0ZXZlbnROYW1lOiBhdnJvU2NoZW1hLm5hbWVcblx0XHRcdH0sXG5cdFx0XHRyZXNwb25zZVdyaXRlcjogb3B0aW9ucy5yZXNwb25zZVdyaXRlciB8fCBkZWZhdWx0UmVzcG9uc2VXcml0ZXIsXG5cdFx0XHRzY2hlbWE6IGF2cm9TY2hlbWEsXG5cdFx0XHRzY2hlbWFOYW1lOiBnZXRTY2hlbWFOYW1lKGF2cm9TY2hlbWEpLFxuXHRcdFx0c3luY2hyb25vdXM6IG9wdGlvbnMuc3luY2hyb25vdXMgfHwgZmFsc2Vcblx0XHR9O1xuXG5cdFx0cmV0dXJuIHZhbGlkYXRlZE9wdGlvbnM7XG5cdH1cblxufVxuIl19