@aws/pdk
Version:
All documentation is located at: https://aws.github.io/aws-pdk
194 lines • 28.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
/*! Copyright [Amazon.com](http://amazon.com/), Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0 */
const client_apigatewayv2_1 = require("@aws-sdk/client-apigatewayv2");
const client_s3_1 = require("@aws-sdk/client-s3");
const websocket_schema_1 = require("./websocket-schema");
const BATCH_SIZE = 10;
const s3 = new client_s3_1.S3({
customUserAgent: `aws-pdk/type-safe-api/ws-schema`,
});
const apiGw = new client_apigatewayv2_1.ApiGatewayV2({
customUserAgent: `aws-pdk/type-safe-api/ws-schema`,
});
/**
* Chunk an array into sub-arrays of the given size
*/
const chunk = (items, size = BATCH_SIZE) => {
const chunks = [];
for (let i = 0; i < items.length; i += size) {
chunks.push(items.slice(i, i + size));
}
return chunks;
};
/**
* Delete a batch of models
*/
const batchDeleteModels = async (apiId, routes, models) => {
for (const batch of chunk(models)) {
await Promise.all(batch.map(async (m) => {
// If there's a route for this model, and it's associated with this model, we need to first remove the association,
// since cloudformation will delete the route later, and we're not allowed to delete a model that's still referenced
// by a route
if (routes[m.Name] &&
routes[m.Name].RequestModels?.model === m.Name) {
await apiGw.updateRoute({
...routes[m.Name],
ApiId: apiId,
RouteId: routes[m.Name].RouteId,
RequestModels: {
model: "",
},
ModelSelectionExpression: undefined,
});
}
await apiGw.deleteModel({
ApiId: apiId,
ModelId: m.ModelId,
});
}));
}
};
/**
* Retrieve all models which already exist on the api
*/
const getAllModelsByRouteKey = async (apiId) => {
let nextToken = undefined;
const models = [];
do {
const res = await apiGw.getModels({
ApiId: apiId,
NextToken: nextToken,
});
nextToken = res.NextToken;
models.push(...(res.Items ?? []));
} while (nextToken);
// Models are named with the route key
return Object.fromEntries(models.map((m) => [m.Name, m]));
};
const getAllRoutesByRouteKey = async (apiId) => {
let nextToken = undefined;
const routes = [];
do {
const res = await apiGw.getRoutes({
ApiId: apiId,
NextToken: nextToken,
});
nextToken = res.NextToken;
routes.push(...(res.Items ?? []));
} while (nextToken);
return Object.fromEntries(routes.map((r) => [r.RouteKey, r]));
};
/**
* Wrap the schema from the spec in our protocol-specific schema
*/
const wrapSchema = (schema) => ({
type: "object",
properties: {
// All inputs must have a "route" which is our route selector
route: {
type: "string",
},
// Payload references the definition
payload: {
$ref: "#/definitions/Payload",
},
},
// When we don't have a schema, the payload can be anything, including not specified
required: ["route", ...(schema ? ["payload"] : [])],
definitions: {
...schema?.definitions,
// The payload is of the operation schema type, or {} which means "any"
Payload: schema?.schema ?? {},
},
});
/**
* Create a batch of models with the appropriate schema
*/
const batchCreateModels = async (apiId, routeKeys, schemas) => {
const results = [];
for (const batch of chunk(routeKeys)) {
results.push(...(await Promise.all(batch.map(async (routeKey) => apiGw.createModel({
ApiId: apiId,
Name: routeKey,
ContentType: "application/json",
Schema: JSON.stringify(wrapSchema(schemas[routeKey])),
})))));
}
return Object.fromEntries(results.map((r) => [r.Name, r.ModelId]));
};
/**
* Update a batch of models with the new schema
*/
const batchUpdateModels = async (apiId, models, schemas) => {
const results = [];
for (const batch of chunk(models)) {
results.push(...(await Promise.all(batch.map(async (model) => apiGw.updateModel({
ApiId: apiId,
ModelId: model.ModelId,
ContentType: "application/json",
Schema: JSON.stringify(wrapSchema(schemas[model.Name])),
})))));
}
return Object.fromEntries(results.map((r) => [r.Name, r.ModelId]));
};
/**
* Create or update the models
*/
const createOrUpdateModels = async (properties, routes) => {
const modelsByRouteKey = await getAllModelsByRouteKey(properties.apiId);
const existingRouteKeys = new Set(Object.keys(modelsByRouteKey));
const newRouteKeys = new Set(Object.keys(properties.serverOperationPaths));
const deletedRouteKeys = [...existingRouteKeys].filter((id) => !newRouteKeys.has(id));
console.log("Operations to delete", deletedRouteKeys);
const addedRouteKeys = [...newRouteKeys].filter((id) => !existingRouteKeys.has(id));
console.log("Operations to add", addedRouteKeys);
const updateRouteKeys = [...newRouteKeys].filter((id) => existingRouteKeys.has(id));
console.log("Operations to update", updateRouteKeys);
// Delete all the models to delete
await batchDeleteModels(properties.apiId, routes, deletedRouteKeys.map((id) => modelsByRouteKey[id]));
// Load the spec
const spec = JSON.parse(await (await s3.getObject({
Bucket: properties.inputSpecLocation.bucket,
Key: properties.inputSpecLocation.key,
})).Body.transformToString("utf-8"));
// Extract the schemas from the spec
const schemas = (0, websocket_schema_1.extractWebSocketSchemas)([...addedRouteKeys, ...updateRouteKeys], properties.serverOperationPaths, spec);
// Create/update the relevant models
return {
...(await batchCreateModels(properties.apiId, addedRouteKeys.filter((id) => schemas[id]), schemas)),
...(await batchUpdateModels(properties.apiId, updateRouteKeys
.filter((id) => schemas[id])
.map((id) => modelsByRouteKey[id]), schemas)),
};
};
/**
* Delete all models
*/
const deleteModels = async (properties, routes) => {
const modelsByRouteKey = await getAllModelsByRouteKey(properties.apiId);
await batchDeleteModels(properties.apiId, routes, Object.values(modelsByRouteKey));
};
/**
* Handler for creating websocket schemas
*/
exports.handler = async (event) => {
const PhysicalResourceId = event.PhysicalResourceId ?? `${event.ResourceProperties.apiId}-models`;
const routes = await getAllRoutesByRouteKey(event.ResourceProperties.apiId);
switch (event.RequestType) {
case "Create":
case "Update":
await createOrUpdateModels(event.ResourceProperties, routes);
break;
case "Delete":
await deleteModels(event.ResourceProperties, routes);
break;
default:
break;
}
return {
PhysicalResourceId,
};
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2Vic29ja2V0LXNjaGVtYS1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsid2Vic29ja2V0LXNjaGVtYS1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUE7c0NBQ3NDO0FBQ3RDLHNFQVFzQztBQUN0QyxrREFFNEI7QUFHNUIseURBRzRCO0FBdUM1QixNQUFNLFVBQVUsR0FBRyxFQUFFLENBQUM7QUFFdEIsTUFBTSxFQUFFLEdBQUcsSUFBSSxjQUFFLENBQUM7SUFDaEIsZUFBZSxFQUFFLGlDQUFpQztDQUNuRCxDQUFDLENBQUM7QUFDSCxNQUFNLEtBQUssR0FBRyxJQUFJLGtDQUFZLENBQUM7SUFDN0IsZUFBZSxFQUFFLGlDQUFpQztDQUNuRCxDQUFDLENBQUM7QUFFSDs7R0FFRztBQUNILE1BQU0sS0FBSyxHQUFHLENBQUksS0FBVSxFQUFFLE9BQWUsVUFBVSxFQUFTLEVBQUU7SUFDaEUsTUFBTSxNQUFNLEdBQVUsRUFBRSxDQUFDO0lBQ3pCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUM1QyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ3hDLENBQUM7SUFDRCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDLENBQUM7QUFFRjs7R0FFRztBQUNILE1BQU0saUJBQWlCLEdBQUcsS0FBSyxFQUM3QixLQUFhLEVBQ2IsTUFBcUMsRUFDckMsTUFBZSxFQUNmLEVBQUU7SUFDRixLQUFLLE1BQU0sS0FBSyxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQ2xDLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FDZixLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRTtZ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QU8sR0FBRyxLQUFLLEVBQUUsS0FBcUIsRUFBNEIsRUFBRTtJQUMxRSxNQUFNLGtCQUFrQixHQUN0QixLQUFLLENBQUMsa0JBQWtCLElBQUksR0FBRyxLQUFLLENBQUMsa0JBQWtCLENBQUMsS0FBSyxTQUFTLENBQUM7SUFDekUsTUFBTSxNQUFNLEdBQUcsTUFBTSxzQkFBc0IsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDNUUsUUFBUSxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDMUIsS0FBSyxRQUFRLENBQUM7UUFDZCxLQUFLLFFBQVE7WUFDWCxNQUFNLG9CQUFvQixDQUFDLEtBQUssQ0FBQyxrQkFBa0IsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUM3RCxNQUFNO1FBQ1IsS0FBSyxRQUFRO1lBQ1gsTUFBTSxZQUFZLENBQUMsS0FBSyxDQUFDLGtCQUFrQixFQUFFLE1BQU0sQ0FBQyxDQUFDO1lBQ3JELE1BQU07UUFDUjtZQUNFLE1BQU07SUFDVixDQUFDO0lBRUQsT0FBTztRQUNMLGtCQUFrQjtLQUNuQixDQUFDO0FBQ0osQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyohIENvcHlyaWdodCBbQW1hem9uLmNvbV0oaHR0cDovL2FtYXpvbi5jb20vKSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wICovXG5pbXBvcnQgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXG4gIEFwaUdhdGV3YXlWMixcbiAgQ3JlYXRlTW9kZWxDb21tYW5kT3V0cHV0LFxuICBHZXRNb2RlbHNDb21tYW5kT3V0cHV0LFxuICBHZXRSb3V0ZXNDb21tYW5kT3V0cHV0LFxuICBNb2RlbCxcbiAgUm91dGUsXG4gIFVwZGF0ZU1vZGVsQ29tbWFuZE91dHB1dCxcbn0gZnJvbSBcIkBhd3Mtc2RrL2NsaWVudC1hcGlnYXRld2F5djJcIjtcbmltcG9ydCB7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcbiAgUzMsXG59IGZyb20gXCJAYXdzLXNkay9jbGllbnQtczNcIjtcbmltcG9ydCB0eXBlIHsgT3BlbkFQSVYzIH0gZnJvbSBcIm9wZW5hcGktdHlwZXNcIjtcbmltcG9ydCB7IFMzTG9jYXRpb24gfSBmcm9tIFwiLlwiO1xuaW1wb3J0IHtcbiAgQXBpR2F0ZXdheVNjaGVtYVdpdGhSZWZzLFxuICBleHRyYWN0V2ViU29ja2V0U2NoZW1hcyxcbn0gZnJvbSBcIi4vd2Vic29ja2V0LXNjaGVtYVwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIFdlYlNvY2tldFNjaGVtYVJlc291cmNlUHJvcGVydGllcyB7XG4gIHJlYWRvbmx5IGFwaUlkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGlucHV0U3BlY0xvY2F0aW9uOiBTM0xvY2F0aW9uO1xuICByZWFkb25seSBzZXJ2ZXJPcGVyYXRpb25QYXRoczoge1xuICAgIFtyb3V0ZUtleTogc3RyaW5nXTogc3RyaW5nO1xuICB9O1xufVxuXG4vKipcbiAqIENsb3VkZm9ybWF0aW9uIGV2ZW50IHR5cGUgZm9yIGN1c3RvbSByZXNvdXJjZVxuICovXG5pbnRlcmZhY2UgT25FdmVudFJlcXVlc3Qge1xuICAvKipcbiAgICogVGhlIHR5cGUgb2YgY2xvdWRmb3JtYXRpb24gcmVxdWVzdFxuICAgKi9cbiAgcmVhZG9ubHkgUmVxdWVzdFR5cGU6IFwiQ3JlYXRlXCIgfCBcIlVwZGF0ZVwiIHwgXCJEZWxldGVcIjtcbiAgLyoqXG4gICAqIFBoeXNpY2FsIHJlc291cmNlIGlkIG9mIHRoZSBjdXN0b20gcmVzb3VyY2VcbiAgICovXG4gIHJlYWRvbmx5IFBoeXNpY2FsUmVzb3VyY2VJZD86IHN0cmluZztcbiAgLyoqXG4gICAqIFByb3BlcnRpZXMgZm9yIHByZXBhcmluZyB0aGUgd2Vic29ja2V0IGFwaSBtb2RlbHNcbiAgICovXG4gIHJlYWRvbmx5IFJlc291cmNlUHJvcGVydGllczogV2ViU29ja2V0U2NoZW1hUmVzb3VyY2VQcm9wZXJ0aWVzO1xufVxuXG5pbnRlcmZhY2UgT25FdmVudFJlc3BvbnNlIHtcbiAgLyoqXG4gICAqIFBoeXNpY2FsIHJlc291cmNlIGlkIG9mIHRoZSBjdXN0b20gcmVzb3VyY2VcbiAgICovXG4gIHJlYWRvbmx5IFBoeXNpY2FsUmVzb3VyY2VJZDogc3RyaW5nO1xuICAvKipcbiAgICogRGF0YSByZXR1cm5lZCBieSB0aGUgY3VzdG9tIHJlc291cmNlXG4gICAqL1xuICByZWFkb25seSBEYXRhPzoge307XG59XG5cbmNvbnN0IEJBVENIX1NJWkUgPSAxMDtcblxuY29uc3QgczMgPSBuZXcgUzMoe1xuICBjdXN0b21Vc2VyQWdlbnQ6IGBhd3MtcGRrL3R5cGUtc2FmZS1hcGkvd3Mtc2NoZW1hYCxcbn0pO1xuY29uc3QgYXBpR3cgPSBuZXcgQXBpR2F0ZXdheVYyKHtcbiAgY3VzdG9tVXNlckFnZW50OiBgYXdzLXBkay90eXBlLXNhZmUtYXBpL3dzLXNjaGVtYWAsXG59KTtcblxuLyoqXG4gKiBDaHVuayBhbiBhcnJheSBpbnRvIHN1Yi1hcnJheXMgb2YgdGhlIGdpdmVuIHNpemVcbiAqL1xuY29uc3QgY2h1bmsgPSA8VD4oaXRlbXM6IFRbXSwgc2l6ZTogbnVtYmVyID0gQkFUQ0hfU0laRSk6IFRbXVtdID0+IHtcbiAgY29uc3QgY2h1bmtzOiBUW11bXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGl0ZW1zLmxlbmd0aDsgaSArPSBzaXplKSB7XG4gICAgY2h1bmtzLnB1c2goaXRlbXMuc2xpY2UoaSwgaSArIHNpemUpKTtcbiAgfVxuICByZXR1cm4gY2h1bmtzO1xufTtcblxuLyoqXG4gKiBEZWxldGUgYSBiYXRjaCBvZiBtb2RlbHNcbiAqL1xuY29uc3QgYmF0Y2hEZWxldGVNb2RlbHMgPSBhc3luYyAoXG4gIGFwaUlkOiBzdHJpbmcsXG4gIHJvdXRlczogeyBbcm91dGVLZXk6IHN0cmluZ106IFJvdXRlIH0sXG4gIG1vZGVsczogTW9kZWxbXVxuKSA9PiB7XG4gIGZvciAoY29uc3QgYmF0Y2ggb2YgY2h1bmsobW9kZWxzKSkge1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgYmF0Y2gubWFwKGFzeW5jIChtKSA9PiB7XG4gICAgICAgIC8vIElmIHRoZXJlJ3MgYSByb3V0ZSBmb3IgdGhpcyBtb2RlbCwgYW5kIGl0J3MgYXNzb2NpYXRlZCB3aXRoIHRoaXMgbW9kZWwsIHdlIG5lZWQgdG8gZmlyc3QgcmVtb3ZlIHRoZSBhc3NvY2lhdGlvbixcbiAgICAgICAgLy8gc2luY2UgY2xvdWRmb3JtYXRpb24gd2lsbCBkZWxldGUgdGhlIHJvdXRlIGxhdGVyLCBhbmQgd2UncmUgbm90IGFsbG93ZWQgdG8gZGVsZXRlIGEgbW9kZWwgdGhhdCdzIHN0aWxsIHJlZmVyZW5jZWRcbiAgICAgICAgLy8gYnkgYSByb3V0ZVxuICAgICAgICBpZiAoXG4gICAgICAgICAgcm91dGVzW20uTmFtZSFdICYmXG4gICAgICAgICAgcm91dGVzW20uTmFtZSFdLlJlcXVlc3RNb2RlbHM/Lm1vZGVsID09PSBtLk5hbWUhXG4gICAgICAgICkge1xuICAgICAgICAgIGF3YWl0IGFwaUd3LnVwZGF0ZVJvdXRlKHtcbiAgICAgICAgICAgIC4uLnJvdXRlc1ttLk5hbWUhXSxcbiAgICAgICAgICAgIEFwaUlkOiBhcGlJZCxcbiAgICAgICAgICAgIFJvdXRlSWQ6IHJvdXRlc1ttLk5hbWUhXS5Sb3V0ZUlkISxcbiAgICAgICAgICAgIFJlcXVlc3RNb2RlbHM6IHtcbiAgICAgICAgICAgICAgbW9kZWw6IFwiXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgTW9kZWxTZWxlY3Rpb25FeHByZXNzaW9uOiB1bmRlZmluZWQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBhd2FpdCBhcGlHdy5kZWxldGVNb2RlbCh7XG4gICAgICAgICAgQXBpSWQ6IGFwaUlkLFxuICAgICAgICAgIE1vZGVsSWQ6IG0uTW9kZWxJZCEsXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICApO1xuICB9XG59O1xuXG4vKipcbiAqIFJldHJpZXZlIGFsbCBtb2RlbHMgd2hpY2ggYWxyZWFkeSBleGlzdCBvbiB0aGUgYXBpXG4gKi9cbmNvbnN0IGdldEFsbE1vZGVsc0J5Um91dGVLZXkgPSBhc3luYyAoXG4gIGFwaUlkOiBzdHJpbmdcbik6IFByb21pc2U8eyBbcm91dGVLZXk6IHN0cmluZ106IE1vZGVsIH0+ID0+IHtcbiAgbGV0IG5leHRUb2tlbjogc3RyaW5nIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICBjb25zdCBtb2RlbHM6IE1vZGVsW10gPSBbXTtcbiAgZG8ge1xuICAgIGNvbnN0IHJlczogR2V0TW9kZWxzQ29tbWFuZE91dHB1dCA9IGF3YWl0IGFwaUd3LmdldE1vZGVscyh7XG4gICAgICBBcGlJZDogYXBpSWQsXG4gICAgICBOZXh0VG9rZW46IG5leHRUb2tlbixcbiAgICB9KTtcbiAgICBuZXh0VG9rZW4gPSByZXMuTmV4dFRva2VuO1xuICAgIG1vZGVscy5wdXNoKC4uLihyZXMuSXRlbXMgPz8gW10pKTtcbiAgfSB3aGlsZSAobmV4dFRva2VuKTtcblxuICAvLyBNb2RlbHMgYXJlIG5hbWVkIHdpdGggdGhlIHJvdXRlIGtleVxuICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKG1vZGVscy5tYXAoKG0pID0+IFttLk5hbWUhLCBtXSkpO1xufTtcblxuY29uc3QgZ2V0QWxsUm91dGVzQnlSb3V0ZUtleSA9IGFzeW5jIChcbiAgYXBpSWQ6IHN0cmluZ1xuKTogUHJvbWlzZTx7IFtyb3V0ZUtleTogc3RyaW5nXTogUm91dGUgfT4gPT4ge1xuICBsZXQgbmV4dFRva2VuOiBzdHJpbmcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gIGNvbnN0IHJvdXRlczogUm91dGVbXSA9IFtdO1xuICBkbyB7XG4gICAgY29uc3QgcmVzOiBHZXRSb3V0ZXNDb21tYW5kT3V0cHV0ID0gYXdhaXQgYXBpR3cuZ2V0Um91dGVzKHtcbiAgICAgIEFwaUlkOiBhcGlJZCxcbiAgICAgIE5leHRUb2tlbjogbmV4dFRva2VuLFxuICAgIH0pO1xuICAgIG5leHRUb2tlbiA9IHJlcy5OZXh0VG9rZW47XG4gICAgcm91dGVzLnB1c2goLi4uKHJlcy5JdGVtcyA/PyBbXSkpO1xuICB9IHdoaWxlIChuZXh0VG9rZW4pO1xuXG4gIHJldHVybiBPYmplY3QuZnJvbUVudHJpZXMocm91dGVzLm1hcCgocikgPT4gW3IuUm91dGVLZXkhLCByXSkpO1xufTtcblxuLyoqXG4gKiBXcmFwIHRoZSBzY2hlbWEgZnJvbSB0aGUgc3BlYyBpbiBvdXIgcHJvdG9jb2wtc3BlY2lmaWMgc2NoZW1hXG4gKi9cbmNvbnN0IHdyYXBTY2hlbWEgPSAoc2NoZW1hOiBBcGlHYXRld2F5U2NoZW1hV2l0aFJlZnMpID0+ICh7XG4gIHR5cGU6IFwib2JqZWN0XCIsXG4gIHByb3BlcnRpZXM6IHtcbiAgICAvLyBBbGwgaW5wdXRzIG11c3QgaGF2ZSBhIFwicm91dGVcIiB3aGljaCBpcyBvdXIgcm91dGUgc2VsZWN0b3JcbiAgICByb3V0ZToge1xuICAgICAgdHlwZTogXCJzdHJpbmdcIixcbiAgICB9LFxuICAgIC8vIFBheWxvYWQgcmVmZXJlbmNlcyB0aGUgZGVmaW5pdGlvblxuICAgIHBheWxvYWQ6IHtcbiAgICAgICRyZWY6IFwiIy9kZWZpbml0aW9ucy9QYXlsb2FkXCIsXG4gICAgfSxcbiAgfSxcbiAgLy8gV2hlbiB3ZSBkb24ndCBoYXZlIGEgc2NoZW1hLCB0aGUgcGF5bG9hZCBjYW4gYmUgYW55dGhpbmcsIGluY2x1ZGluZyBub3Qgc3BlY2lmaWVkXG4gIHJlcXVpcmVkOiBbXCJyb3V0ZVwiLCAuLi4oc2NoZW1hID8gW1wicGF5bG9hZFwiXSA6IFtdKV0sXG4gIGRlZmluaXRpb25zOiB7XG4gICAgLi4uc2NoZW1hPy5kZWZpbml0aW9ucyxcbiAgICAvLyBUaGUgcGF5bG9hZCBpcyBvZiB0aGUgb3BlcmF0aW9uIHNjaGVtYSB0eXBlLCBvciB7fSB3aGljaCBtZWFucyBcImFueVwiXG4gICAgUGF5bG9hZDogc2NoZW1hPy5zY2hlbWEgPz8ge30sXG4gIH0sXG59KTtcblxuLyoqXG4gKiBDcmVhdGUgYSBiYXRjaCBvZiBtb2RlbHMgd2l0aCB0aGUgYXBwcm9wcmlhdGUgc2NoZW1hXG4gKi9cbmNvbnN0IGJhdGNoQ3JlYXRlTW9kZWxzID0gYXN5bmMgKFxuICBhcGlJZDogc3RyaW5nLFxuICByb3V0ZUtleXM6IHN0cmluZ1tdLFxuICBzY2hlbWFzOiB7IFtyb3V0ZUtleTogc3RyaW5nXTogQXBpR2F0ZXdheVNjaGVtYVdpdGhSZWZzIH1cbik6IFByb21pc2U8eyBbcm91dGVLZXk6IHN0cmluZ106IHN0cmluZyB9PiA9PiB7XG4gIGNvbnN0IHJlc3VsdHM6IENyZWF0ZU1vZGVsQ29tbWFuZE91dHB1dFtdID0gW107XG4gIGZvciAoY29uc3QgYmF0Y2ggb2YgY2h1bmsocm91dGVLZXlzKSkge1xuICAgIHJlc3VsdHMucHVzaChcbiAgICAgIC4uLihhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgYmF0Y2gubWFwKGFzeW5jIChyb3V0ZUtleSkgPT5cbiAgICAgICAgICBhcGlHdy5jcmVhdGVNb2RlbCh7XG4gICAgICAgICAgICBBcGlJZDogYXBpSWQsXG4gICAgICAgICAgICBOYW1lOiByb3V0ZUtleSxcbiAgICAgICAgICAgIENvbnRlbnRUeXBlOiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgICAgICAgIFNjaGVtYTogSlNPTi5zdHJpbmdpZnkod3JhcFNjaGVtYShzY2hlbWFzW3JvdXRlS2V5XSkpLFxuICAgICAgICAgIH0pXG4gICAgICAgIClcbiAgICAgICkpXG4gICAgKTtcbiAgfVxuICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKHJlc3VsdHMubWFwKChyKSA9PiBbci5OYW1lISwgci5Nb2RlbElkIV0pKTtcbn07XG5cbi8qKlxuICogVXBkYXRlIGEgYmF0Y2ggb2YgbW9kZWxzIHdpdGggdGhlIG5ldyBzY2hlbWFcbiAqL1xuY29uc3QgYmF0Y2hVcGRhdGVNb2RlbHMgPSBhc3luYyAoXG4gIGFwaUlkOiBzdHJpbmcsXG4gIG1vZGVsczogTW9kZWxbXSxcbiAgc2NoZW1hczogeyBbcm91dGVLZXk6IHN0cmluZ106IEFwaUdhdGV3YXlTY2hlbWFXaXRoUmVmcyB9XG4pOiBQcm9taXNlPHsgW3JvdXRlS2V5OiBzdHJpbmddOiBzdHJpbmcgfT4gPT4ge1xuICBjb25zdCByZXN1bHRzOiBVcGRhdGVNb2RlbENvbW1hbmRPdXRwdXRbXSA9IFtdO1xuICBmb3IgKGNvbnN0IGJhdGNoIG9mIGNodW5rKG1vZGVscykpIHtcbiAgICByZXN1bHRzLnB1c2goXG4gICAgICAuLi4oYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGJhdGNoLm1hcChhc3luYyAobW9kZWwpID0+XG4gICAgICAgICAgYXBpR3cudXBkYXRlTW9kZWwoe1xuICAgICAgICAgICAgQXBpSWQ6IGFwaUlkLFxuICAgICAgICAgICAgTW9kZWxJZDogbW9kZWwuTW9kZWxJZCEsXG4gICAgICAgICAgICBDb250ZW50VHlwZTogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgICAgICBTY2hlbWE6IEpTT04uc3RyaW5naWZ5KHdyYXBTY2hlbWEoc2NoZW1hc1ttb2RlbC5OYW1lIV0pKSxcbiAgICAgICAgICB9KVxuICAgICAgICApXG4gICAgICApKVxuICAgICk7XG4gIH1cbiAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhyZXN1bHRzLm1hcCgocikgPT4gW3IuTmFtZSEsIHIuTW9kZWxJZCFdKSk7XG59O1xuXG4vKipcbiAqIENyZWF0ZSBvciB1cGRhdGUgdGhlIG1vZGVsc1xuICovXG5jb25zdCBjcmVhdGVPclVwZGF0ZU1vZGVscyA9IGFzeW5jIChcbiAgcHJvcGVydGllczogV2ViU29ja2V0U2NoZW1hUmVzb3VyY2VQcm9wZXJ0aWVzLFxuICByb3V0ZXM6IHsgW3JvdXRlS2V5OiBzdHJpbmddOiBSb3V0ZSB9XG4pOiBQcm9taXNlPHsgW3JvdXRlS2V5OiBzdHJpbmddOiBzdHJpbmcgfT4gPT4ge1xuICBjb25zdCBtb2RlbHNCeVJvdXRlS2V5ID0gYXdhaXQgZ2V0QWxsTW9kZWxzQnlSb3V0ZUtleShwcm9wZXJ0aWVzLmFwaUlkKTtcbiAgY29uc3QgZXhpc3RpbmdSb3V0ZUtleXMgPSBuZXcgU2V0KE9iamVjdC5rZXlzKG1vZGVsc0J5Um91dGVLZXkpKTtcbiAgY29uc3QgbmV3Um91dGVLZXlzID0gbmV3IFNldChPYmplY3Qua2V5cyhwcm9wZXJ0aWVzLnNlcnZlck9wZXJhdGlvblBhdGhzKSk7XG5cbiAgY29uc3QgZGVsZXRlZFJvdXRlS2V5cyA9IFsuLi5leGlzdGluZ1JvdXRlS2V5c10uZmlsdGVyKFxuICAgIChpZCkgPT4gIW5ld1JvdXRlS2V5cy5oYXMoaWQpXG4gICk7XG4gIGNvbnNvbGUubG9nKFwiT3BlcmF0aW9ucyB0byBkZWxldGVcIiwgZGVsZXRlZFJvdXRlS2V5cyk7XG4gIGNvbnN0IGFkZGVkUm91dGVLZXlzID0gWy4uLm5ld1JvdXRlS2V5c10uZmlsdGVyKFxuICAgIChpZCkgPT4gIWV4aXN0aW5nUm91dGVLZXlzLmhhcyhpZClcbiAgKTtcbiAgY29uc29sZS5sb2coXCJPcGVyYXRpb25zIHRvIGFkZFwiLCBhZGRlZFJvdXRlS2V5cyk7XG4gIGNvbnN0IHVwZGF0ZVJvdXRlS2V5cyA9IFsuLi5uZXdSb3V0ZUtleXNdLmZpbHRlcigoaWQpID0+XG4gICAgZXhpc3RpbmdSb3V0ZUtleXMuaGFzKGlkKVxuICApO1xuICBjb25zb2xlLmxvZyhcIk9wZXJhdGlvbnMgdG8gdXBkYXRlXCIsIHVwZGF0ZVJvdXRlS2V5cyk7XG5cbiAgLy8gRGVsZXRlIGFsbCB0aGUgbW9kZWxzIHRvIGRlbGV0ZVxuICBhd2FpdCBiYXRjaERlbGV0ZU1vZGVscyhcbiAgICBwcm9wZXJ0aWVzLmFwaUlkLFxuICAgIHJvdXRlcyxcbiAgICBkZWxldGVkUm91dGVLZXlzLm1hcCgoaWQpID0+IG1vZGVsc0J5Um91dGVLZXlbaWRdKVxuICApO1xuXG4gIC8vIExvYWQgdGhlIHNwZWNcbiAgY29uc3Qgc3BlYyA9IEpTT04ucGFyc2UoXG4gICAgYXdhaXQgKFxuICAgICAgYXdhaXQgczMuZ2V0T2JqZWN0KHtcbiAgICAgICAgQnVja2V0OiBwcm9wZXJ0aWVzLmlucHV0U3BlY0xvY2F0aW9uLmJ1Y2tldCxcbiAgICAgICAgS2V5OiBwcm9wZXJ0aWVzLmlucHV0U3BlY0xvY2F0aW9uLmtleSxcbiAgICAgIH0pXG4gICAgKS5Cb2R5IS50cmFuc2Zvcm1Ub1N0cmluZyhcInV0Zi04XCIpXG4gICkgYXMgT3BlbkFQSVYzLkRvY3VtZW50O1xuXG4gIC8vIEV4dHJhY3QgdGhlIHNjaGVtYXMgZnJvbSB0aGUgc3BlY1xuICBjb25zdCBzY2hlbWFzID0gZXh0cmFjdFdlYlNvY2tldFNjaGVtYXMoXG4gICAgWy4uLmFkZGVkUm91dGVLZXlzLCAuLi51cGRhdGVSb3V0ZUtleXNdLFxuICAgIHByb3BlcnRpZXMuc2VydmVyT3BlcmF0aW9uUGF0aHMsXG4gICAgc3BlY1xuICApO1xuXG4gIC8vIENyZWF0ZS91cGRhdGUgdGhlIHJlbGV2YW50IG1vZGVsc1xuICByZXR1cm4ge1xuICAgIC4uLihhd2FpdCBiYXRjaENyZWF0ZU1vZGVscyhcbiAgICAgIHByb3BlcnRpZXMuYXBpSWQsXG4gICAgICBhZGRlZFJvdXRlS2V5cy5maWx0ZXIoKGlkKSA9PiBzY2hlbWFzW2lkXSksXG4gICAgICBzY2hlbWFzXG4gICAgKSksXG4gICAgLi4uKGF3YWl0IGJhdGNoVXBkYXRlTW9kZWxzKFxuICAgICAgcHJvcGVydGllcy5hcGlJZCxcbiAgICAgIHVwZGF0ZVJvdXRlS2V5c1xuICAgICAgICAuZmlsdGVyKChpZCkgPT4gc2NoZW1hc1tpZF0pXG4gICAgICAgIC5tYXAoKGlkKSA9PiBtb2RlbHNCeVJvdXRlS2V5W2lkXSksXG4gICAgICBzY2hlbWFzXG4gICAgKSksXG4gIH07XG59O1xuXG4vKipcbiAqIERlbGV0ZSBhbGwgbW9kZWxzXG4gKi9cbmNvbnN0IGRlbGV0ZU1vZGVscyA9IGFzeW5jIChcbiAgcHJvcGVydGllczogV2ViU29ja2V0U2NoZW1hUmVzb3VyY2VQcm9wZXJ0aWVzLFxuICByb3V0ZXM6IHsgW3JvdXRlS2V5OiBzdHJpbmddOiBSb3V0ZSB9XG4pID0+IHtcbiAgY29uc3QgbW9kZWxzQnlSb3V0ZUtleSA9IGF3YWl0IGdldEFsbE1vZGVsc0J5Um91dGVLZXkocHJvcGVydGllcy5hcGlJZCk7XG4gIGF3YWl0IGJhdGNoRGVsZXRlTW9kZWxzKFxuICAgIHByb3BlcnRpZXMuYXBpSWQsXG4gICAgcm91dGVzLFxuICAgIE9iamVjdC52YWx1ZXMobW9kZWxzQnlSb3V0ZUtleSlcbiAgKTtcbn07XG5cbi8qKlxuICogSGFuZGxlciBmb3IgY3JlYXRpbmcgd2Vic29ja2V0IHNjaGVtYXNcbiAqL1xuZXhwb3J0cy5oYW5kbGVyID0gYXN5bmMgKGV2ZW50OiBPbkV2ZW50UmVxdWVzdCk6IFByb21pc2U8T25FdmVudFJlc3BvbnNlPiA9PiB7XG4gIGNvbnN0IFBoeXNpY2FsUmVzb3VyY2VJZCA9XG4gICAgZXZlbnQuUGh5c2ljYWxSZXNvdXJjZUlkID8/IGAke2V2ZW50LlJlc291cmNlUHJvcGVydGllcy5hcGlJZH0tbW9kZWxzYDtcbiAgY29uc3Qgcm91dGVzID0gYXdhaXQgZ2V0QWxsUm91dGVzQnlSb3V0ZUtleShldmVudC5SZXNvdXJjZVByb3BlcnRpZXMuYXBpSWQpO1xuICBzd2l0Y2ggKGV2ZW50LlJlcXVlc3RUeXBlKSB7XG4gICAgY2FzZSBcIkNyZWF0ZVwiOlxuICAgIGNhc2UgXCJVcGRhdGVcIjpcbiAgICAgIGF3YWl0IGNyZWF0ZU9yVXBkYXRlTW9kZWxzKGV2ZW50LlJlc291cmNlUHJvcGVydGllcywgcm91dGVzKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgXCJEZWxldGVcIjpcbiAgICAgIGF3YWl0IGRlbGV0ZU1vZGVscyhldmVudC5SZXNvdXJjZVByb3BlcnRpZXMsIHJvdXRlcyk7XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgYnJlYWs7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIFBoeXNpY2FsUmVzb3VyY2VJZCxcbiAgfTtcbn07XG4iXX0=