UNPKG

@financialforcedev/orizuru

Version:

Streamlined communication between Heroku dynos / other worker processes

168 lines 22.4 kB
"use strict"; /* * 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