@aws/pdk
Version:
All documentation is located at: https://aws.github.io/aws-pdk
144 lines • 21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractWebSocketSchemas = exports.extractWebSocketSchema = void 0;
const constants_1 = require("./constants");
const prepare_spec_1 = require("./prepare-spec");
const _get = (object, paths) => {
if (typeof object === "undefined") {
return undefined;
}
if (paths.length === 0) {
return object;
}
return _get(object[paths[0]], paths.slice(1));
};
/**
* Return whether or not the given OpenAPI object is a reference
*/
const isRef = (obj) => !!obj && typeof obj === "object" && "$ref" in obj;
/**
* Return whether a given OpenAPI object is a schema object
*/
const isSchemaObj = (obj) => !!obj &&
typeof obj === "object" &&
("type" in obj ||
"allOf" in obj ||
"oneOf" in obj ||
"anyOf" in obj ||
"not" in obj);
/**
* Split a reference into its component parts
* eg: #/components/schemas/Foo -> ["components", "schemas", "Foo"]
*/
const splitRef = (ref) => ref
.slice(2)
.split("/")
.map((p) => p.replace(/~0/g, "~").replace(/~1/g, "/"));
/**
* Resolve the given reference in the spec
*/
const resolveRef = (spec, ref) => {
const refParts = splitRef(ref);
const resolved = _get(spec, refParts);
if (!resolved) {
throw new Error(`Unable to resolve ref ${ref} in spec`);
}
return resolved;
};
/**
* Get the id of a reference to be used in the "definitions" section
*/
const getRefId = (ref) => splitRef(ref).join("_");
/**
* Rewrite a reference to an API gateway model supported format
* eg #/components/schemas/Foo -> #/definitions/components_schemas_Foo
*/
const rewriteRef = (ref) => `#/definitions/${getRefId(ref)}`;
/**
* Map the given function over all refs in an OpenAPI object
*/
const mapRefs = (obj, fn) => {
// Use JSON.stringify's replacement function to simplify traversing a spec
return JSON.parse(JSON.stringify(obj, (key, value) => {
if (key === "$ref") {
return fn(value);
}
return value;
}));
};
/**
* Find all references recursively starting at the given schema
*/
const findAllReferences = (schema, spec, seenRefs = new Set()) => {
const newRefs = new Set();
mapRefs(schema, (ref) => newRefs.add(ref));
const refsToSearch = [...newRefs].filter((ref) => !seenRefs.has(ref));
const newSeenRefs = new Set([...newRefs, ...seenRefs]);
return new Set([
...newSeenRefs,
...refsToSearch.flatMap((ref) => [
...findAllReferences(resolveRef(spec, ref), spec, newSeenRefs),
]),
]);
};
/**
* Rewrite all references in the schema to instead reference #/definitions/xxx, and collect any other schemas recursively referenced by the schema
*
* @see https://docs.aws.amazon.com/apigateway/latest/developerguide/models-mappings-models.html#api-gateway-request-validation-model-more-complex
*/
const rewriteSchemaReferences = (schema, spec) => {
// Rewrite the schema and spec, replacing references with #/definitions/xxx as per the API Gateway model format
const rewrittenSchema = mapRefs(schema, rewriteRef);
const rewrittenSpec = mapRefs(spec, rewriteRef);
// Set of definitions that must be included for the given schema
const definitions = {};
// Find all recursive references from the schema, and add their (rewritten) schema to definitions
[...findAllReferences(schema, spec)].forEach((ref) => {
definitions[getRefId(ref)] = resolveRef(rewrittenSpec, ref);
});
return { schema: rewrittenSchema, definitions };
};
const extractWebSocketSchema = (operationId, requestBody, spec) => {
// Resolve the body reference, if any
const body = isRef(requestBody)
? resolveRef(spec, requestBody.$ref)
: requestBody;
const candidateSchema = body?.content?.["application/json"]?.schema;
if (!candidateSchema) {
// No schema found
return undefined;
}
// Resolve the top level schema reference, if any
const rawSchema = isRef(candidateSchema)
? resolveRef(spec, candidateSchema.$ref)
: candidateSchema;
if (!isSchemaObj(rawSchema)) {
throw new Error(`Invalid OpenAPI specification: request body for operation ${operationId} is not a valid schema`);
}
// Rewrite schema references to a format accepted by API Gateway
return rewriteSchemaReferences(rawSchema, spec);
};
exports.extractWebSocketSchema = extractWebSocketSchema;
const extractWebSocketSchemas = (operationIds, serverOperationPaths, spec) => {
const schemasByOperationId = {};
for (const operationId of operationIds) {
const path = serverOperationPaths[operationId];
const pathItem = spec.paths[path];
(0, prepare_spec_1.validatePathItem)(path, pathItem);
// Exactly 1 operation must be defined for each path in a websocket OpenAPI spec
const operations = Object.values(constants_1.HttpMethods).flatMap((method) => pathItem[method] ? [{ ...pathItem[method], method }] : []);
if (operations.length !== 1) {
throw new Error(`Each path must have a single method for websocket apis. Found ${operations.map((o) => o.method).join(", ") || "no methods"}`);
}
// Extract the schema for the websocket input validation model
if (operations[0]?.requestBody) {
const schema = (0, exports.extractWebSocketSchema)(operationId, operations[0].requestBody, spec);
if (schema) {
schemasByOperationId[operationId] = schema;
}
}
}
return schemasByOperationId;
};
exports.extractWebSocketSchemas = extractWebSocketSchemas;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2Vic29ja2V0LXNjaGVtYS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIndlYnNvY2tldC1zY2hlbWEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBR0EsMkNBQTBDO0FBQzFDLGlEQUFrRDtBQVFsRCxNQUFNLElBQUksR0FBRyxDQUFDLE1BQXVCLEVBQUUsS0FBZSxFQUFPLEVBQUU7SUFDN0QsSUFBSSxPQUFPLE1BQU0sS0FBSyxXQUFXLEVBQUUsQ0FBQztRQUNsQyxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBQ0QsSUFBSSxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3ZCLE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2hELENBQUMsQ0FBQztBQUVGOztHQUVHO0FBQ0gsTUFBTSxLQUFLLEdBQUcsQ0FBQyxHQUFZLEVBQW9DLEVBQUUsQ0FDL0QsQ0FBQyxDQUFDLEdBQUcsSUFBSSxPQUFPLEdBQUcsS0FBSyxRQUFRLElBQUksTUFBTSxJQUFJLEdBQUcsQ0FBQztBQUVwRDs7R0FFRztBQUNILE1BQU0sV0FBVyxHQUFHLENBQUMsR0FBWSxFQUFpQyxFQUFFLENBQ2xFLENBQUMsQ0FBQyxHQUFHO0lBQ0wsT0FBTyxHQUFHLEtBQUssUUFBUTtJQUN2QixDQUFDLE1BQU0sSUFBSSxHQUFHO1FBQ1osT0FBTyxJQUFJLEdBQUc7UUFDZCxPQUFPLElBQUksR0FBRztRQUNkLE9BQU8sSUFBSSxHQUFHO1FBQ2QsS0FBSyxJQUFJLEdBQUcsQ0FBQyxDQUFDO0FBRWxCOzs7R0FHRztBQUNILE1BQU0sUUFBUSxHQUFHLENBQUMsR0FBVyxFQUFZLEVBQUUsQ0FDekMsR0FBRztLQUNBLEtBQUssQ0FBQyxDQUFDLENBQUM7S0FDUixLQUFLLENBQUMsR0FBRyxDQUFDO0tBQ1YsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7QUFFM0Q7O0dBRUc7QUFDSCxNQUFNLFVBQVUsR0FBRyxDQUFDLElBQXdCLEVBQUUsR0FBVyxFQUFPLEVBQUU7SUFDaEUsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQy9CLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDdEMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2QsTUFBTSxJQUFJLEtBQUssQ0FBQyx5QkFBeUIsR0FBRyxVQUFVLENBQUMsQ0FBQztJQUMxRCxDQUFDO0lBQ0QsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQyxDQUFDO0FBRUY7O0dBRUc7QUFDSCxNQUFNLFFBQVEsR0FBRyxDQUFDLEdBQVcsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUUxRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsR0FBRyxDQUFDLEdBQVcsRUFBRSxFQUFFLENBQUMsaUJBQWlCLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO0FBRXJFOztHQUVHO0FBQ0gsTUFBTSxPQUFPLEdBQUcsQ0FBSSxHQUFXLEVBQUUsRUFBc0IsRUFBVSxFQUFFO0lBQ2pFLDBFQUEwRTtJQUMxRSxPQUFPLElBQUksQ0FBQyxLQUFLLENBQ2YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEVBQUU7UUFDakMsSUFBSSxHQUFHLEtBQUssTUFBTSxFQUFFLENBQUM7WUFDbkIsT0FBTyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDbkIsQ0FBQztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQyxDQUFDLENBQ0gsQ0FBQztBQUNKLENBQUMsQ0FBQztBQUVGOztHQUVHO0FBQ0gsTUFBTSxpQkFBaUIsR0FBRyxDQUN4QixNQUE4QixFQUM5QixJQUF3QixFQUN4QixXQUF3QixJQUFJLEdBQUcsRUFBRSxFQUNwQixFQUFFO0lBQ2YsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUNsQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDM0MsTUFBTSxZQUFZLEdBQUcsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDdEUsTUFBTSxXQUFXLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLE9BQU8sRUFBRSxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDdkQsT0FBTyxJQUFJLEdBQUcsQ0FBQztRQUNiLEdBQUcsV0FBVztRQUNkLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUM7WUFDL0IsR0FBRyxpQkFBaUIsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLElBQUksRUFBRSxXQUFXLENBQUM7U0FDL0QsQ0FBQztLQUNILENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCxNQUFNLHVCQUF1QixHQUFHLENBQzlCLE1BQThCLEVBQzlCLElBQXdCLEVBQ0UsRUFBRTtJQUM1QiwrR0FBK0c7SUFDL0csTUFBTSxlQUFlLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQTJCLENBQUM7SUFDOUUsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLElBQUksRUFBRSxVQUFVLENBQXVCLENBQUM7SUFFdEUsZ0VBQWdFO0lBQ2hFLE1BQU0sV0FBVyxHQUFzQixFQUFFLENBQUM7SUFFMUMsaUdBQWlHO0lBQ2pHLENBQUMsR0FBRyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtRQUNuRCxXQUFXLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsVUFBVSxDQUFDLGFBQWEsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUM5RCxDQUFDLENBQUMsQ0FBQztJQUVILE9BQU8sRUFBRSxNQUFNLEVBQUUsZUFBZSxFQUFFLFdBQVcsRUFBRSxDQUFDO0FBQ2xELENBQUMsQ0FBQztBQUVLLE1BQU0sc0JBQXNCLEdBQUcsQ0FDcEMsV0FBbUIsRUFDbkIsV0FBb0UsRUFDcEUsSUFBd0IsRUFDYyxFQUFFO0lBQ3hDLHFDQUFxQztJQUNyQyxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDO1FBQzdCLENBQUMsQ0FBRSxVQUFVLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxJQUFJLENBQWlDO1FBQ3JFLENBQUMsQ0FBQyxXQUFXLENBQUM7SUFDaEIsTUFBTSxlQUFlLEdBQUcsSUFBSSxFQUFFLE9BQU8sRUFBRSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsTUFBTSxDQUFDO0lBQ3BFLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUNyQixrQkFBa0I7UUFDbEIsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELGlEQUFpRDtJQUNqRCxNQUFNLFNBQVMsR0FBRyxLQUFLLENBQUMsZUFBZSxDQUFDO1FBQ3RDLENBQUMsQ0FBRSxVQUFVLENBQUMsSUFBSSxFQUFFLGVBQWUsQ0FBQyxJQUFJLENBQTRCO1FBQ3BFLENBQUMsQ0FBQyxlQUFlLENBQUM7SUFFcEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1FBQzVCLE1BQU0sSUFBSSxLQUFLLENBQ2IsNkRBQTZELFdBQVcsd0JBQXdCLENBQ2pHLENBQUM7SUFDSixDQUFDO0lBRUQsZ0VBQWdFO0lBQ2hFLE9BQU8sdUJBQXVCLENBQUMsU0FBUyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQ2xELENBQUMsQ0FBQztBQTVCVyxRQUFBLHNCQUFzQiwwQkE0QmpDO0FBRUssTUFBTSx1QkFBdUIsR0FBRyxDQUNyQyxZQUFzQixFQUN0QixvQkFBdUQsRUFDdkQsSUFBd0IsRUFDNkIsRUFBRTtJQUN2RCxNQUFNLG9CQUFvQixHQUV0QixFQUFFLENBQUM7SUFDUCxLQUFLLE1BQU0sV0FBVyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sSUFBSSxHQUFHLG9CQUFvQixDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQy9DLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFFLENBQUM7UUFDbkMsSUFBQSwrQkFBZ0IsRUFBQyxJQUFJLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFFakMsZ0ZBQWdGO1FBQ2hGLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsdUJBQVcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQy9ELFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FDMUQsQ0FBQztRQUVGLElBQUksVUFBVSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUM1QixNQUFNLElBQUksS0FBSyxDQUNiLGlFQUNFLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksWUFDaEQsRUFBRSxDQUNILENBQUM7UUFDSixDQUFDO1FBRUQsOERBQThEO1FBQzlELElBQUksVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxDQUFDO1lBQy9CLE1BQU0sTUFBTSxHQUFHLElBQUEsOEJBQXNCLEVBQ25DLFdBQVcsRUFDWCxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUN6QixJQUFJLENBQ0wsQ0FBQztZQUNGLElBQUksTUFBTSxFQUFFLENBQUM7Z0JBQ1gsb0JBQW9CLENBQUMsV0FBVyxDQUFDLEdBQUcsTUFBTSxDQUFDO1lBQzdDLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sb0JBQW9CLENBQUM7QUFDOUIsQ0FBQyxDQUFDO0FBdkNXLFFBQUEsdUJBQXVCLDJCQXVDbEMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiEgQ29weXJpZ2h0IFtBbWF6b24uY29tXShodHRwOi8vYW1hem9uLmNvbS8pLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjAgKi9cbmltcG9ydCB0eXBlIHsgT3BlbkFQSVYzIH0gZnJvbSBcIm9wZW5hcGktdHlwZXNcIjtcbmltcG9ydCB7IEh0dHBNZXRob2RzIH0gZnJvbSBcIi4vY29uc3RhbnRzXCI7XG5pbXBvcnQgeyB2YWxpZGF0ZVBhdGhJdGVtIH0gZnJvbSBcIi4vcHJlcGFyZS1zcGVjXCI7XG5cbnR5cGUgU2NoZW1hRGVmaW5pdGlvbnMgPSB7IFtrZXk6IHN0cmluZ106IE9wZW5BUElWMy5TY2hlbWFPYmplY3QgfTtcbmV4cG9ydCB0eXBlIEFwaUdhdGV3YXlTY2hlbWFXaXRoUmVmcyA9IHtcbiAgc2NoZW1hOiBPcGVuQVBJVjMuU2NoZW1hT2JqZWN0O1xuICBkZWZpbml0aW9uczogU2NoZW1hRGVmaW5pdGlvbnM7XG59O1xuXG5jb25zdCBfZ2V0ID0gKG9iamVjdDogYW55IHwgdW5kZWZpbmVkLCBwYXRoczogc3RyaW5nW10pOiBhbnkgPT4ge1xuICBpZiAodHlwZW9mIG9iamVjdCA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgaWYgKHBhdGhzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBvYmplY3Q7XG4gIH1cbiAgcmV0dXJuIF9nZXQob2JqZWN0W3BhdGhzWzBdXSwgcGF0aHMuc2xpY2UoMSkpO1xufTtcblxuLyoqXG4gKiBSZXR1cm4gd2hldGhlciBvciBub3QgdGhlIGdpdmVuIE9wZW5BUEkgb2JqZWN0IGlzIGEgcmVmZXJlbmNlXG4gKi9cbmNvbnN0IGlzUmVmID0gKG9iajogdW5rbm93bik6IG9iaiBpcyBPcGVuQVBJVjMuUmVmZXJlbmNlT2JqZWN0ID0+XG4gICEhb2JqICYmIHR5cGVvZiBvYmogPT09IFwib2JqZWN0XCIgJiYgXCIkcmVmXCIgaW4gb2JqO1xuXG4vKipcbiAqIFJldHVybiB3aGV0aGVyIGEgZ2l2ZW4gT3BlbkFQSSBvYmplY3QgaXMgYSBzY2hlbWEgb2JqZWN0XG4gKi9cbmNvbnN0IGlzU2NoZW1hT2JqID0gKG9iajogdW5rbm93bik6IG9iaiBpcyBPcGVuQVBJVjMuU2NoZW1hT2JqZWN0ID0+XG4gICEhb2JqICYmXG4gIHR5cGVvZiBvYmogPT09IFwib2JqZWN0XCIgJiZcbiAgKFwidHlwZVwiIGluIG9iaiB8fFxuICAgIFwiYWxsT2ZcIiBpbiBvYmogfHxcbiAgICBcIm9uZU9mXCIgaW4gb2JqIHx8XG4gICAgXCJhbnlPZlwiIGluIG9iaiB8fFxuICAgIFwibm90XCIgaW4gb2JqKTtcblxuLyoqXG4gKiBTcGxpdCBhIHJlZmVyZW5jZSBpbnRvIGl0cyBjb21wb25lbnQgcGFydHNcbiAqIGVnOiAjL2NvbXBvbmVudHMvc2NoZW1hcy9Gb28gLT4gW1wiY29tcG9uZW50c1wiLCBcInNjaGVtYXNcIiwgXCJGb29cIl1cbiAqL1xuY29uc3Qgc3BsaXRSZWYgPSAocmVmOiBzdHJpbmcpOiBzdHJpbmdbXSA9PlxuICByZWZcbiAgICAuc2xpY2UoMilcbiAgICAuc3BsaXQoXCIvXCIpXG4gICAgLm1hcCgocCkgPT4gcC5yZXBsYWNlKC9+MC9nLCBcIn5cIikucmVwbGFjZSgvfjEvZywgXCIvXCIpKTtcblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBnaXZlbiByZWZlcmVuY2UgaW4gdGhlIHNwZWNcbiAqL1xuY29uc3QgcmVzb2x2ZVJlZiA9IChzcGVjOiBPcGVuQVBJVjMuRG9jdW1lbnQsIHJlZjogc3RyaW5nKTogYW55ID0+IHtcbiAgY29uc3QgcmVmUGFydHMgPSBzcGxpdFJlZihyZWYpO1xuICBjb25zdCByZXNvbHZlZCA9IF9nZXQoc3BlYywgcmVmUGFydHMpO1xuICBpZiAoIXJlc29sdmVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbmFibGUgdG8gcmVzb2x2ZSByZWYgJHtyZWZ9IGluIHNwZWNgKTtcbiAgfVxuICByZXR1cm4gcmVzb2x2ZWQ7XG59O1xuXG4vKipcbiAqIEdldCB0aGUgaWQgb2YgYSByZWZlcmVuY2UgdG8gYmUgdXNlZCBpbiB0aGUgXCJkZWZpbml0aW9uc1wiIHNlY3Rpb25cbiAqL1xuY29uc3QgZ2V0UmVmSWQgPSAocmVmOiBzdHJpbmcpID0+IHNwbGl0UmVmKHJlZikuam9pbihcIl9cIik7XG5cbi8qKlxuICogUmV3cml0ZSBhIHJlZmVyZW5jZSB0byBhbiBBUEkgZ2F0ZXdheSBtb2RlbCBzdXBwb3J0ZWQgZm9ybWF0XG4gKiBlZyAjL2NvbXBvbmVudHMvc2NoZW1hcy9Gb28gLT4gIy9kZWZpbml0aW9ucy9jb21wb25lbnRzX3NjaGVtYXNfRm9vXG4gKi9cbmNvbnN0IHJld3JpdGVSZWYgPSAocmVmOiBzdHJpbmcpID0+IGAjL2RlZmluaXRpb25zLyR7Z2V0UmVmSWQocmVmKX1gO1xuXG4vKipcbiAqIE1hcCB0aGUgZ2l2ZW4gZnVuY3Rpb24gb3ZlciBhbGwgcmVmcyBpbiBhbiBPcGVuQVBJIG9iamVjdFxuICovXG5jb25zdCBtYXBSZWZzID0gPFQ+KG9iajogb2JqZWN0LCBmbjogKHJlZjogc3RyaW5nKSA9PiBUKTogb2JqZWN0ID0+IHtcbiAgLy8gVXNlIEpTT04uc3RyaW5naWZ5J3MgcmVwbGFjZW1lbnQgZnVuY3Rpb24gdG8gc2ltcGxpZnkgdHJhdmVyc2luZyBhIHNwZWNcbiAgcmV0dXJuIEpTT04ucGFyc2UoXG4gICAgSlNPTi5zdHJpbmdpZnkob2JqLCAoa2V5LCB2YWx1ZSkgPT4ge1xuICAgICAgaWYgKGtleSA9PT0gXCIkcmVmXCIpIHtcbiAgICAgICAgcmV0dXJuIGZuKHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9KVxuICApO1xufTtcblxuLyoqXG4gKiBGaW5kIGFsbCByZWZlcmVuY2VzIHJlY3Vyc2l2ZWx5IHN0YXJ0aW5nIGF0IHRoZSBnaXZlbiBzY2hlbWFcbiAqL1xuY29uc3QgZmluZEFsbFJlZmVyZW5jZXMgPSAoXG4gIHNjaGVtYTogT3BlbkFQSVYzLlNjaGVtYU9iamVjdCxcbiAgc3BlYzogT3BlbkFQSVYzLkRvY3VtZW50LFxuICBzZWVuUmVmczogU2V0PHN0cmluZz4gPSBuZXcgU2V0KClcbik6IFNldDxzdHJpbmc+ID0+IHtcbiAgY29uc3QgbmV3UmVmcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBtYXBSZWZzKHNjaGVtYSwgKHJlZikgPT4gbmV3UmVmcy5hZGQocmVmKSk7XG4gIGNvbnN0IHJlZnNUb1NlYXJjaCA9IFsuLi5uZXdSZWZzXS5maWx0ZXIoKHJlZikgPT4gIXNlZW5SZWZzLmhhcyhyZWYpKTtcbiAgY29uc3QgbmV3U2VlblJlZnMgPSBuZXcgU2V0KFsuLi5uZXdSZWZzLCAuLi5zZWVuUmVmc10pO1xuICByZXR1cm4gbmV3IFNldChbXG4gICAgLi4ubmV3U2VlblJlZnMsXG4gICAgLi4ucmVmc1RvU2VhcmNoLmZsYXRNYXAoKHJlZikgPT4gW1xuICAgICAgLi4uZmluZEFsbFJlZmVyZW5jZXMocmVzb2x2ZVJlZihzcGVjLCByZWYpLCBzcGVjLCBuZXdTZWVuUmVmcyksXG4gICAgXSksXG4gIF0pO1xufTtcblxuLyoqXG4gKiBSZXdyaXRlIGFsbCByZWZlcmVuY2VzIGluIHRoZSBzY2hlbWEgdG8gaW5zdGVhZCByZWZlcmVuY2UgIy9kZWZpbml0aW9ucy94eHgsIGFuZCBjb2xsZWN0IGFueSBvdGhlciBzY2hlbWFzIHJlY3Vyc2l2ZWx5IHJlZmVyZW5jZWQgYnkgdGhlIHNjaGVtYVxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwaWdhdGV3YXkvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL21vZGVscy1tYXBwaW5ncy1tb2RlbHMuaHRtbCNhcGktZ2F0ZXdheS1yZXF1ZXN0LXZhbGlkYXRpb24tbW9kZWwtbW9yZS1jb21wbGV4XG4gKi9cbmNvbnN0IHJld3JpdGVTY2hlbWFSZWZlcmVuY2VzID0gKFxuICBzY2hlbWE6IE9wZW5BUElWMy5TY2hlbWFPYmplY3QsXG4gIHNwZWM6IE9wZW5BUElWMy5Eb2N1bWVudFxuKTogQXBpR2F0ZXdheVNjaGVtYVdpdGhSZWZzID0+IHtcbiAgLy8gUmV3cml0ZSB0aGUgc2NoZW1hIGFuZCBzcGVjLCByZXBsYWNpbmcgcmVmZXJlbmNlcyB3aXRoICMvZGVmaW5pdGlvbnMveHh4IGFzIHBlciB0aGUgQVBJIEdhdGV3YXkgbW9kZWwgZm9ybWF0XG4gIGNvbnN0IHJld3JpdHRlblNjaGVtYSA9IG1hcFJlZnMoc2NoZW1hLCByZXdyaXRlUmVmKSBhcyBPcGVuQVBJVjMuU2NoZW1hT2JqZWN0O1xuICBjb25zdCByZXdyaXR0ZW5TcGVjID0gbWFwUmVmcyhzcGVjLCByZXdyaXRlUmVmKSBhcyBPcGVuQVBJVjMuRG9jdW1lbnQ7XG5cbiAgLy8gU2V0IG9mIGRlZmluaXRpb25zIHRoYXQgbXVzdCBiZSBpbmNsdWRlZCBmb3IgdGhlIGdpdmVuIHNjaGVtYVxuICBjb25zdCBkZWZpbml0aW9uczogU2NoZW1hRGVmaW5pdGlvbnMgPSB7fTtcblxuICAvLyBGaW5kIGFsbCByZWN1cnNpdmUgcmVmZXJlbmNlcyBmcm9tIHRoZSBzY2hlbWEsIGFuZCBhZGQgdGhlaXIgKHJld3JpdHRlbikgc2NoZW1hIHRvIGRlZmluaXRpb25zXG4gIFsuLi5maW5kQWxsUmVmZXJlbmNlcyhzY2hlbWEsIHNwZWMpXS5mb3JFYWNoKChyZWYpID0+IHtcbiAgICBkZWZpbml0aW9uc1tnZXRSZWZJZChyZWYpXSA9IHJlc29sdmVSZWYocmV3cml0dGVuU3BlYywgcmVmKTtcbiAgfSk7XG5cbiAgcmV0dXJuIHsgc2NoZW1hOiByZXdyaXR0ZW5TY2hlbWEsIGRlZmluaXRpb25zIH07XG59O1xuXG5leHBvcnQgY29uc3QgZXh0cmFjdFdlYlNvY2tldFNjaGVtYSA9IChcbiAgb3BlcmF0aW9uSWQ6IHN0cmluZyxcbiAgcmVxdWVzdEJvZHk6IE9wZW5BUElWMy5SZXF1ZXN0Qm9keU9iamVjdCB8IE9wZW5BUElWMy5SZWZlcmVuY2VPYmplY3QsXG4gIHNwZWM6IE9wZW5BUElWMy5Eb2N1bWVudFxuKTogQXBpR2F0ZXdheVNjaGVtYVdpdGhSZWZzIHwgdW5kZWZpbmVkID0+IHtcbiAgLy8gUmVzb2x2ZSB0aGUgYm9keSByZWZlcmVuY2UsIGlmIGFueVxuICBjb25zdCBib2R5ID0gaXNSZWYocmVxdWVzdEJvZHkpXG4gICAgPyAocmVzb2x2ZVJlZihzcGVjLCByZXF1ZXN0Qm9keS4kcmVmKSBhcyBPcGVuQVBJVjMuUmVxdWVzdEJvZHlPYmplY3QpXG4gICAgOiByZXF1ZXN0Qm9keTtcbiAgY29uc3QgY2FuZGlkYXRlU2NoZW1hID0gYm9keT8uY29udGVudD8uW1wiYXBwbGljYXRpb24vanNvblwiXT8uc2NoZW1hO1xuICBpZiAoIWNhbmRpZGF0ZVNjaGVtYSkge1xuICAgIC8vIE5vIHNjaGVtYSBmb3VuZFxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvLyBSZXNvbHZlIHRoZSB0b3AgbGV2ZWwgc2NoZW1hIHJlZmVyZW5jZSwgaWYgYW55XG4gIGNvbnN0IHJhd1NjaGVtYSA9IGlzUmVmKGNhbmRpZGF0ZVNjaGVtYSlcbiAgICA/IChyZXNvbHZlUmVmKHNwZWMsIGNhbmRpZGF0ZVNjaGVtYS4kcmVmKSBhcyBPcGVuQVBJVjMuU2NoZW1hT2JqZWN0KVxuICAgIDogY2FuZGlkYXRlU2NoZW1hO1xuXG4gIGlmICghaXNTY2hlbWFPYmoocmF3U2NoZW1hKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBJbnZhbGlkIE9wZW5BUEkgc3BlY2lmaWNhdGlvbjogcmVxdWVzdCBib2R5IGZvciBvcGVyYXRpb24gJHtvcGVyYXRpb25JZH0gaXMgbm90IGEgdmFsaWQgc2NoZW1hYFxuICAgICk7XG4gIH1cblxuICAvLyBSZXdyaXRlIHNjaGVtYSByZWZlcmVuY2VzIHRvIGEgZm9ybWF0IGFjY2VwdGVkIGJ5IEFQSSBHYXRld2F5XG4gIHJldHVybiByZXdyaXRlU2NoZW1hUmVmZXJlbmNlcyhyYXdTY2hlbWEsIHNwZWMpO1xufTtcblxuZXhwb3J0IGNvbnN0IGV4dHJhY3RXZWJTb2NrZXRTY2hlbWFzID0gKFxuICBvcGVyYXRpb25JZHM6IHN0cmluZ1tdLFxuICBzZXJ2ZXJPcGVyYXRpb25QYXRoczogeyBbb3BlcmF0aW9uSWQ6IHN0cmluZ106IHN0cmluZyB9LFxuICBzcGVjOiBPcGVuQVBJVjMuRG9jdW1lbnRcbik6IHsgW29wZXJhdGlvbklkOiBzdHJpbmddOiBBcGlHYXRld2F5U2NoZW1hV2l0aFJlZnMgfSA9PiB7XG4gIGNvbnN0IHNjaGVtYXNCeU9wZXJhdGlvbklkOiB7XG4gICAgW29wZXJhdGlvbklkOiBzdHJpbmddOiBBcGlHYXRld2F5U2NoZW1hV2l0aFJlZnM7XG4gIH0gPSB7fTtcbiAgZm9yIChjb25zdCBvcGVyYXRpb25JZCBvZiBvcGVyYXRpb25JZHMpIHtcbiAgICBjb25zdCBwYXRoID0gc2VydmVyT3BlcmF0aW9uUGF0aHNbb3BlcmF0aW9uSWRdO1xuICAgIGNvbnN0IHBhdGhJdGVtID0gc3BlYy5wYXRoc1twYXRoXSE7XG4gICAgdmFsaWRhdGVQYXRoSXRlbShwYXRoLCBwYXRoSXRlbSk7XG5cbiAgICAvLyBFeGFjdGx5IDEgb3BlcmF0aW9uIG11c3QgYmUgZGVmaW5lZCBmb3IgZWFjaCBwYXRoIGluIGEgd2Vic29ja2V0IE9wZW5BUEkgc3BlY1xuICAgIGNvbnN0IG9wZXJhdGlvbnMgPSBPYmplY3QudmFsdWVzKEh0dHBNZXRob2RzKS5mbGF0TWFwKChtZXRob2QpID0+XG4gICAgICBwYXRoSXRlbVttZXRob2RdID8gW3sgLi4ucGF0aEl0ZW1bbWV0aG9kXSwgbWV0aG9kIH1dIDogW11cbiAgICApO1xuXG4gICAgaWYgKG9wZXJhdGlvbnMubGVuZ3RoICE9PSAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBFYWNoIHBhdGggbXVzdCBoYXZlIGEgc2luZ2xlIG1ldGhvZCBmb3Igd2Vic29ja2V0IGFwaXMuIEZvdW5kICR7XG4gICAgICAgICAgb3BlcmF0aW9ucy5tYXAoKG8pID0+IG8ubWV0aG9kKS5qb2luKFwiLCBcIikgfHwgXCJubyBtZXRob2RzXCJcbiAgICAgICAgfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gRXh0cmFjdCB0aGUgc2NoZW1hIGZvciB0aGUgd2Vic29ja2V0IGlucHV0IHZhbGlkYXRpb24gbW9kZWxcbiAgICBpZiAob3BlcmF0aW9uc1swXT8ucmVxdWVzdEJvZHkpIHtcbiAgICAgIGNvbnN0IHNjaGVtYSA9IGV4dHJhY3RXZWJTb2NrZXRTY2hlbWEoXG4gICAgICAgIG9wZXJhdGlvbklkLFxuICAgICAgICBvcGVyYXRpb25zWzBdLnJlcXVlc3RCb2R5LFxuICAgICAgICBzcGVjXG4gICAgICApO1xuICAgICAgaWYgKHNjaGVtYSkge1xuICAgICAgICBzY2hlbWFzQnlPcGVyYXRpb25JZFtvcGVyYXRpb25JZF0gPSBzY2hlbWE7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBzY2hlbWFzQnlPcGVyYXRpb25JZDtcbn07XG4iXX0=