serverless-spy 2.3.19 → 2.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.jsii
CHANGED
|
@@ -4044,7 +4044,7 @@
|
|
|
4044
4044
|
},
|
|
4045
4045
|
"locationInModule": {
|
|
4046
4046
|
"filename": "src/ServerlessSpy.ts",
|
|
4047
|
-
"line":
|
|
4047
|
+
"line": 781
|
|
4048
4048
|
},
|
|
4049
4049
|
"name": "getConstructName",
|
|
4050
4050
|
"parameters": [
|
|
@@ -4346,6 +4346,6 @@
|
|
|
4346
4346
|
"symbolId": "src/ServerlessSpy:SpyFilter"
|
|
4347
4347
|
}
|
|
4348
4348
|
},
|
|
4349
|
-
"version": "2.3.
|
|
4350
|
-
"fingerprint": "
|
|
4349
|
+
"version": "2.3.21",
|
|
4350
|
+
"fingerprint": "QovkGOtZWZaf8/J4VXH8WLhnhUlqM8hcBZsd4PfE6vo="
|
|
4351
4351
|
}
|
package/dist/releasetag.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v2.3.
|
|
1
|
+
v2.3.21
|
package/lib/src/ServerlessSpy.js
CHANGED
|
@@ -415,11 +415,15 @@ class ServerlessSpy extends constructs_1.Construct {
|
|
|
415
415
|
table.node.defaultChild.streamSpecification = {
|
|
416
416
|
streamViewType: dynamoDb.StreamViewType.NEW_AND_OLD_IMAGES,
|
|
417
417
|
};
|
|
418
|
-
|
|
419
|
-
if (tableStreamArnDescriptor === undefined ||
|
|
420
|
-
tableStreamArnDescriptor.get === undefined) {
|
|
418
|
+
try {
|
|
421
419
|
table.tableStreamArn = table.node.defaultChild.attrStreamArn;
|
|
422
420
|
}
|
|
421
|
+
catch (e) {
|
|
422
|
+
// Property is read-only in newer CDK versions, skip the assignment
|
|
423
|
+
if (!(e instanceof TypeError && e.message.includes('only a getter'))) {
|
|
424
|
+
throw e; // Re-throw if it's a different error
|
|
425
|
+
}
|
|
426
|
+
}
|
|
423
427
|
this.lambdaSubscriptionMain.function.addEventSource(new dynamoDbStream.DynamoEventSource(table, {
|
|
424
428
|
startingPosition: lambda.StartingPosition.LATEST,
|
|
425
429
|
batchSize: 1,
|
|
@@ -626,5 +630,5 @@ class ServerlessSpy extends constructs_1.Construct {
|
|
|
626
630
|
}
|
|
627
631
|
exports.ServerlessSpy = ServerlessSpy;
|
|
628
632
|
_a = JSII_RTTI_SYMBOL_1;
|
|
629
|
-
ServerlessSpy[_a] = { fqn: "serverless-spy.ServerlessSpy", version: "2.3.
|
|
630
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2VydmVybGVzc1NweS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9TZXJ2ZXJsZXNzU3B5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3Qiw4RUFBc0U7QUFDdEUsNkNBUXFCO0FBQ3JCLHFEQUFxRDtBQUNyRCxpREFBaUQ7QUFDakQsMERBQTBEO0FBQzFELGlEQUE2QztBQUM3QyxpREFBaUQ7QUFDakQsdURBSWdDO0FBQ2hDLHVFQUF1RTtBQUN2RSxtRkFBc0U7QUFDdEUsNERBQTREO0FBQzVELHFFQUErRDtBQUMvRCx5Q0FBeUM7QUFDekMsNERBQTREO0FBQzVELDJDQUEyQztBQUMzQyw2REFBNkQ7QUFDN0QsMkNBQTJDO0FBQzNDLDJDQUFtRDtBQUNuRCxnRUFBNkQ7QUFtQjdELE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxJQUFnQixFQUEyQixFQUFFLENBQ3JFLGNBQWMsSUFBSSxJQUFJLElBQUksYUFBYSxJQUFJLElBQUksSUFBSSxTQUFTLElBQUksSUFBSSxDQUFDO0FBRXZFLE1BQU0sb0NBQW9DLEdBQUcsMEJBQTBCLENBQUM7QUFFeEUsTUFBYSxhQUFjLFNBQVEsc0JBQVM7SUFVMUMsWUFDRSxLQUFnQixFQUNoQixFQUFVLEVBQ0YsS0FBMEI7UUFFbEMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUZULFVBQUssR0FBTCxLQUFLLENBQXFCO1FBWjVCLDJCQUFzQixHQUFpQixFQUFFLENBQUM7UUFDMUMsMkJBQXNCLEdBQXlCLEVBQUUsQ0FBQztRQUVsRCxpQkFBWSxHQUFrQixFQUFFLENBQUM7UUFDbEMsZ0JBQVcsR0FBYSxFQUFFLENBQUM7UUFDMUIsZUFBVSxHQUFpQixFQUFFLENBQUM7UUFDOUIsYUFBUSxHQUEyQyxFQUFFLENBQUM7UUFVNUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FDOUIsSUFBSSxDQUFDLGFBQWEsQ0FB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RXZELElBQUksRUFBRSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3ZCLE9BQU8sR0FBRyxDQUFDO1FBQ2IsQ0FBQztRQUVELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFlBQVksR0FBRyxRQUFRLENBQUMsQ0FBQztRQUUzRCxJQUFJLEVBQUUsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUN4QixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLFlBQVksR0FBRyxRQUFRLElBQUksbUJBQW1CLENBQUMsQ0FBQztJQUNsRSxDQUFDOztBQXQwQkgsc0NBdTBCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBQeXRob25MYXllclZlcnNpb24gfSBmcm9tICdAYXdzLWNkay9hd3MtbGFtYmRhLXB5dGhvbi1hbHBoYSc7XG5pbXBvcnQge1xuICBhd3NfaWFtLFxuICBCdW5kbGluZ0ZpbGVBY2Nlc3MsXG4gIENmbk91dHB1dCxcbiAgY3VzdG9tX3Jlc291cmNlcyxcbiAgRHVyYXRpb24sXG4gIE5lc3RlZFN0YWNrLFxuICBTdGFjayxcbn0gZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0ICogYXMgZHluYW1vRGIgZnJvbSAnYXdzLWNkay1saWIvYXdzLWR5bmFtb2RiJztcbmltcG9ydCAqIGFzIGV2ZW50cyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZXZlbnRzJztcbmltcG9ydCAqIGFzIHRhcmdldHMgZnJvbSAnYXdzLWNkay1saWIvYXdzLWV2ZW50cy10YXJnZXRzJztcbmltcG9ydCB7IEVmZmVjdCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0IHtcbiAgQXJjaGl0ZWN0dXJlLFxuICBJTGF5ZXJWZXJzaW9uLFxuICBTaW5nbGV0b25GdW5jdGlvbixcbn0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQgKiBhcyBkeW5hbW9EYlN0cmVhbSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhLWV2ZW50LXNvdXJjZXMnO1xuaW1wb3J0IHsgU3FzRXZlbnRTb3VyY2UgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhLWV2ZW50LXNvdXJjZXMnO1xuaW1wb3J0ICogYXMgbGFtYmRhTm9kZSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhLW5vZGVqcyc7XG5pbXBvcnQgeyBOb2RlanNGdW5jdGlvbiB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEtbm9kZWpzJztcbmltcG9ydCAqIGFzIHMzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMyc7XG5pbXBvcnQgKiBhcyBzM25vdGlmIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zMy1ub3RpZmljYXRpb25zJztcbmltcG9ydCAqIGFzIHNucyBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc25zJztcbmltcG9ydCAqIGFzIHNuc1N1YnMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXNucy1zdWJzY3JpcHRpb25zJztcbmltcG9ydCAqIGFzIHNxcyBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc3FzJztcbmltcG9ydCB7IENvbnN0cnVjdCwgSUNvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgZW52VmFyaWFibGVOYW1lcyB9IGZyb20gJy4vY29tbW9uL2VudlZhcmlhYmxlTmFtZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZlcmxlc3NTcHlQcm9wcyB7XG4gIHJlYWRvbmx5IGdlbmVyYXRlU3B5RXZlbnRzRmlsZUxvY2F0aW9uPzogc3RyaW5nO1xuICByZWFkb25seSBzcHlTcXNXaXRoTm9TdWJzY3JpcHRpb25BbmREcm9wQWxsTWVzc2FnZXM/OiBib29sZWFuO1xuICByZWFkb25seSBkZWJ1Z01vZGU/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNweUZpbHRlciB7XG4gIHJlYWRvbmx5IHNweUxhbWJkYT86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHNweVNxcz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHNweVNuc1RvcGljPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3B5U25zU3Vic3JpcHRpb24/OiBib29sZWFuO1xuICByZWFkb25seSBzcHlFdmVudEJyaWRnZT86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHNweUV2ZW50QnJpZGdlUnVsZT86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHNweVMzPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3B5RHluYW1vREI/OiBib29sZWFuO1xufVxuXG5jb25zdCBpc0xhbWJkYUZ1bmN0aW9uID0gKG5vZGU6IElDb25zdHJ1Y3QpOiBub2RlIGlzIGxhbWJkYS5GdW5jdGlvbiA9PlxuICAnZnVuY3Rpb25OYW1lJyBpbiBub2RlICYmICdmdW5jdGlvbkFybicgaW4gbm9kZSAmJiAncnVudGltZScgaW4gbm9kZTtcblxuY29uc3Qgc2VydmVybGVzc1NweUlvdEVuZHBvaW50Q3JOYW1lUHJlZml4ID0gJ1NlcnZlcmxlc3NTcHlJb3RFbmRwb2ludCc7XG5cbmV4cG9ydCBjbGFzcyBTZXJ2ZXJsZXNzU3B5IGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgcHJpdmF0ZSBjcmVhdGVkUmVzb3VyY2VzQnlTU3B5OiBJQ29uc3RydWN0W10gPSBbXTtcbiAgcHJpdmF0ZSBsYW1iZGFTdWJzY3JpcHRpb25Qb29sOiBMYW1iZGFTdWJzY3JpcHRpb25bXSA9IFtdO1xuICBwcml2YXRlIGxhbWJkYVN1YnNjcmlwdGlvbk1haW46IExhbWJkYVN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSBsYW1iZGFzU3BpZWQ6IExhbWJkYVNwaWVkW10gPSBbXTtcbiAgcHVibGljIHNlcnZpY2VLZXlzOiBzdHJpbmdbXSA9IFtdO1xuICBwcml2YXRlIHNwaWVkTm9kZXM6IElDb25zdHJ1Y3RbXSA9IFtdO1xuICBwcml2YXRlIGxheWVyTWFwOiBQYXJ0aWFsPFJlY29yZDxzdHJpbmcsIElMYXllclZlcnNpb24+PiA9IHt9O1xuICBwcml2YXRlIHJlYWRvbmx5IGlvdEVuZHBvaW50OiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHByaXZhdGUgcHJvcHM/OiBTZXJ2ZXJsZXNzU3B5UHJvcHNcbiAgKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIGNvbnN0IHJvb3RTdGFjayA9IHRoaXMuY2xlYW5OYW1lKFxuICAgICAgdGhpcy5maW5kUm9vdFN0YWNrKFN0YWNrLm9mKHRoaXMpKS5ub2RlLmlkXG4gICAgKTtcblxuICAgIGNvbnN0IGdldElvVEVuZHBvaW50ID0gbmV3IGN1c3RvbV9yZXNvdXJjZXMuQXdzQ3VzdG9tUmVzb3VyY2UoXG4gICAgICB0aGlzLFxuICAgICAgc2VydmVybGVzc1NweUlvdEVuZHBvaW50Q3JOYW1lUHJlZml4LFxuICAgICAge1xuICAgICAgICBvbkNyZWF0ZToge1xuICAgICAgICAgIHNlcnZpY2U6ICdJb3QnLFxuICAgICAgICAgIGFjdGlvbjogJ2Rlc2NyaWJlRW5kcG9pbnQnLFxuICAgICAgICAgIHBoeXNpY2FsUmVzb3VyY2VJZDpcbiAgICAgICAgICAgIGN1c3RvbV9yZXNvdXJjZXMuUGh5c2ljYWxSZXNvdXJjZUlkLmZyb21SZXNwb25zZSgnZW5kcG9pbnRBZGRyZXNzJyksXG4gICAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgICAgZW5kcG9pbnRUeXBlOiAnaW90OkRhdGEtQVRTJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBvblVwZGF0ZToge1xuICAgICAgICAgIHNlcnZpY2U6ICdJb3QnLFxuICAgICAgICAgIGFjdGlvbjogJ2Rlc2NyaWJlRW5kcG9pbnQnLFxuICAgICAgICAgIHBoeXNpY2FsUmVzb3VyY2VJZDpcbiAgICAgICAgICAgIGN1c3RvbV9yZXNvdXJjZXMuUGh5c2ljYWxSZXNvdXJjZUlkLmZyb21SZXNwb25zZSgnZW5kcG9pbnRBZGRyZXNzJyksXG4gICAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgICAgZW5kcG9pbnRUeXBlOiAnaW90OkRhdGEtQVRTJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBpbnN0YWxsTGF0ZXN0QXdzU2RrOiBmYWxzZSxcbiAgICAgICAgcG9saWN5OiBjdXN0b21fcmVzb3VyY2VzLkF3c0N1c3RvbVJlc291cmNlUG9saWN5LmZyb21TZGtDYWxscyh7XG4gICAgICAgICAgcmVzb3VyY2VzOiBjdXN0b21fcmVzb3VyY2VzLkF3c0N1c3RvbVJlc291cmNlUG9saWN5LkFOWV9SRVNPVVJDRSxcbiAgICAgICAgfSksXG4gICAgICAgIGZ1bmN0aW9uTmFtZTogc2VydmVybGVzc1NweUlvdEVuZHBvaW50Q3JOYW1lUHJlZml4ICsgcm9vdFN0YWNrLFxuICAgICAgfVxuICAgICk7XG4gICAgdGhpcy5pb3RFbmRwb2ludCA9IGdldElvVEVuZHBvaW50LmdldFJlc3BvbnNlRmllbGQoJ2VuZHBvaW50QWRkcmVzcycpO1xuXG4gICAgdGhpcy5jcmVhdGVkUmVzb3VyY2VzQnlTU3B5LnB1c2goZ2V0SW9URW5kcG9pbnQpO1xuXG4gICAgbmV3IENmbk91dHB1dCh0aGlzLCAnU2VydmVybGVzc1NweUlvVEVuZHBvaW50Jywge1xuICAgICAga2V5OiAnU2VydmVybGVzc1NweVdzVXJsJyxcbiAgICAgIHZhbHVlOiBgJHt0aGlzLmlvdEVuZHBvaW50fS8ke3Jvb3RTdGFja31gLFxuICAgIH0pO1xuXG4gICAgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25NYWluID0gdGhpcy5wcm92aWRlRnVuY3Rpb25Gb3JTdWJzY3JpcHRpb24oKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RGVmYXVsdExhbWJkYUVudmlyb25tZW50VmFyaWFibGVzKCk6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0ge1xuICAgIHJldHVybiB7XG4gICAgICBOT0RFX09QVElPTlM6ICctLWVuYWJsZS1zb3VyY2UtbWFwcycsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0YWxpemUgc3B5aW5nIG9uIHJlc291cmNlcyBnaXZlbiBhcyBwYXJhbWV0ZXIuXG4gICAqIEBwYXJhbSBub2RlcyBXaGljaCByZW91cmNlcyBhbmQgdGhlaXIgY2hpbGRyZW4gdG8gc3B5IG9uLlxuICAgKi9cbiAgcHVibGljIHNweU5vZGVzKG5vZGVzOiBJQ29uc3RydWN0W10pIHtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2Ygbm9kZXMpIHtcbiAgICAgIGxldCBucyA9IHRoaXMuZ2V0QWxsTm9kZXMobm9kZSk7XG4gICAgICB0aGlzLmludGVybmFsU3B5Tm9kZXMobnMpO1xuICAgIH1cblxuICAgIHRoaXMuZmluYWxpemVTcHkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0YWxpemUgc3B5aW5nIG9uIHJlc291cmNlcy5cbiAgICogQHBhcmFtIGZpbHRlciBMaW1pdCB3aGljaCByZXNvdXJjZXMgdG8gc3B5IG9uLlxuICAgKi9cbiAgcHVibGljIHNweShmaWx0ZXI/OiBTcHlGaWx0ZXIpIHtcbiAgICBsZXQgbm9kZXMgPSB0aGlzLmdldEFsbE5vZGVzKFN0YWNrLm9mKHRoaXMpKTtcblxuICAgIGNvbnN0IGZpbHRlcldpdGhEZWZhdWx0czogUmVxdWlyZWQ8U3B5RmlsdGVyPiA9IHtcbiAgICAgIHNweUxhbWJkYTogdHJ1ZSxcbiAgICAgIHNweVNxczogdHJ1ZSxcbiAgICAgIHNweVNuc1RvcGljOiB0cnVlLFxuICAgICAgc3B5U25zU3Vic3JpcHRpb246IHRydWUsXG4gICAgICBzcHlFdmVudEJyaWRnZTogdHJ1ZSxcbiAgICAgIHNweUV2ZW50QnJpZGdlUnVsZTogdHJ1ZSxcbiAgICAgIHNweVMzOiB0cnVlLFxuICAgICAgc3B5RHluYW1vREI6IHRydWUsXG4gICAgICAuLi5maWx0ZXIsXG4gICAgfTtcblxuICAgIGNvbnN0IENSSUQgPVxuICAgICAgJ0FXUycgK1xuICAgICAgY3VzdG9tX3Jlc291cmNlcy5Bd3NDdXN0b21SZXNvdXJjZS5QUk9WSURFUl9GVU5DVElPTl9VVUlELnJlcGxhY2UoXG4gICAgICAgIC8tL2dpLFxuICAgICAgICAnJ1xuICAgICAgKS5zdWJzdHJpbmcoMCwgMTYpO1xuXG4gICAgbm9kZXMgPSBub2Rlcy5maWx0ZXIoKG5vZGUpID0+IHtcbiAgICAgIGlmIChcbiAgICAgICAgLy8gSWdub3JlIHRoZSBjdXN0b20gcmVzb3VyY2UgYW5kIHRoZSBQcm92aWRlciAoYXMgd2VsbCBhcyBhbnkgb3RoZXIgUHJvdmlkZXJzIHVzaW5nIHRoZSBzYW1lIHByb3ZpZGVyIGZ1bmN0aW9uKSwgb3RoZXJ3aXNlIHdlIGNhdXNlXG4gICAgICAgIC8vIGNpcmN1bGFyIGRlcGVuZGVuY2llc1xuICAgICAgICBub2RlLm5vZGUuaWQuc3RhcnRzV2l0aChDUklEKSB8fFxuICAgICAgICBub2RlLm5vZGUuaWQgPT09ICdQcm92aWRlcicgfHxcbiAgICAgICAgLy8gSWdub3JlIHNpbmdsZXRvbiBmdW5jdGlvbnMgYXMgdGhleSBjYW4gY2F1c2UgdmVyeSBvZGQgYmVoYXZpb3IgYW5kIGNyYXNoZXNcbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIFNpbmdsZXRvbkZ1bmN0aW9uXG4gICAgICApIHtcbiAgICAgICAgaWYgKHRoaXMucHJvcHM/LmRlYnVnTW9kZSkge1xuICAgICAgICAgIGNvbnNvbGUuaW5mbyhgU2tpcHBpbmcgJHtub2RlLm5vZGUuaWR9YCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZmlsdGVyV2l0aERlZmF1bHRzLnNweUxhbWJkYSAmJlxuICAgICAgICAobm9kZSBpbnN0YW5jZW9mIGxhbWJkYS5GdW5jdGlvbiB8fFxuICAgICAgICAgIG5vZGUgaW5zdGFuY2VvZiBOb2RlanNGdW5jdGlvbiB8fFxuICAgICAgICAgIGlzTGFtYmRhRnVuY3Rpb24obm9kZSkpXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKGZpbHRlcldpdGhEZWZhdWx0cy5zcHlTbnNUb3BpYyAmJiBub2RlIGluc3RhbmNlb2Ygc25zLlRvcGljKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZmlsdGVyV2l0aERlZmF1bHRzLnNweVNuc1N1YnNyaXB0aW9uICYmXG4gICAgICAgIG5vZGUgaW5zdGFuY2VvZiBzbnMuU3Vic2NyaXB0aW9uXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKGZpbHRlcldpdGhEZWZhdWx0cy5zcHlTMyAmJiBub2RlIGluc3RhbmNlb2YgczMuQnVja2V0KSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZmlsdGVyV2l0aERlZmF1bHRzLnNweUR5bmFtb0RCICYmXG4gICAgICAgIG5vZGUgaW5zdGFuY2VvZiBkeW5hbW9EYi5UYWJsZVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZmlsdGVyV2l0aERlZmF1bHRzLnNweUR5bmFtb0RCICYmXG4gICAgICAgIG5vZGUgaW5zdGFuY2VvZiBkeW5hbW9EYi5UYWJsZVYyXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5RXZlbnRCcmlkZ2UgJiZcbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIGV2ZW50cy5FdmVudEJ1c1xuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZmlsdGVyV2l0aERlZmF1bHRzLnNweUV2ZW50QnJpZGdlUnVsZSAmJlxuICAgICAgICBub2RlIGluc3RhbmNlb2YgZXZlbnRzLlJ1bGVcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGZpbHRlcldpdGhEZWZhdWx0cy5zcHlTcXMgJiZcbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIGxhbWJkYS5DZm5FdmVudFNvdXJjZU1hcHBpbmdcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGZpbHRlcldpdGhEZWZhdWx0cy5zcHlTcXMgJiZcbiAgICAgICAgdGhpcy5wcm9wcz8uc3B5U3FzV2l0aE5vU3Vic2NyaXB0aW9uQW5kRHJvcEFsbE1lc3NhZ2VzICYmXG4gICAgICAgIG5vZGUgaW5zdGFuY2VvZiBzcXMuUXVldWVcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0pO1xuXG4gICAgdGhpcy5pbnRlcm5hbFNweU5vZGVzKG5vZGVzKTtcbiAgICB0aGlzLmZpbmFsaXplU3B5KCk7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5Tm9kZXMobm9kZXM6IElDb25zdHJ1Y3RbXSkge1xuICAgIGZvciAoY29uc3Qgbm9kZSBvZiBub2Rlcykge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweU5vZGUobm9kZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBmaW5hbGl6ZVNweSgpIHtcbiAgICAvL3NldCBtYXBwaW5nIHByb3BlcnR5IGZvciBhbGwgZnVuY3Rpb25zIHdlIGNyZWF0ZWRcbiAgICBmb3IgKGNvbnN0IGZ1bmMgb2YgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25Qb29sKSB7XG4gICAgICBmdW5jLmZ1bmN0aW9uLmFkZEVudmlyb25tZW50KFxuICAgICAgICBlbnZWYXJpYWJsZU5hbWVzLlNTUFlfSU5GUkFfTUFQUElORyxcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoZnVuYy5tYXBwaW5nKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvL3NldCBtYXBwaW5nIHByb3BlcnR5IGZvciBhbGwgZnVuY3Rpb25zIHdlIHNweSBvblxuICAgIGZvciAoY29uc3QgZnVuYyBvZiB0aGlzLmxhbWJkYXNTcGllZCkge1xuICAgICAgZnVuYy5mdW5jdGlvbi5hZGRFbnZpcm9ubWVudChcbiAgICAgICAgZW52VmFyaWFibGVOYW1lcy5TU1BZX0lORlJBX01BUFBJTkcsXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KGZ1bmMubWFwcGluZylcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucHJvcHM/LmdlbmVyYXRlU3B5RXZlbnRzRmlsZUxvY2F0aW9uKSB7XG4gICAgICB0aGlzLndyaXRlU3B5RXZlbnRzQ2xhc3ModGhpcy5wcm9wcz8uZ2VuZXJhdGVTcHlFdmVudHNGaWxlTG9jYXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0RXh0ZW5zaW9uQXNzZXRMb2NhdGlvbigpIHtcbiAgICBsZXQgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbiA9IHBhdGguam9pbihcbiAgICAgIF9fZGlybmFtZSxcbiAgICAgICcuLi9leHRlbnNpb24vZGlzdC9sYXllcidcbiAgICApO1xuXG4gICAgY29uc3QgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkFsdCA9IHBhdGguam9pbihcbiAgICAgIF9fZGlybmFtZSxcbiAgICAgICcuLi9saWIvZXh0ZW5zaW9uL2Rpc3QvbGF5ZXInXG4gICAgKTtcblxuICAgIGlmICghZnMuZXhpc3RzU3luYyhleHRlbnNpb25Bc3NldExvY2F0aW9uKSkge1xuICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKGV4dGVuc2lvbkFzc2V0TG9jYXRpb25BbHQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgRm9sZGVyIHdpdGggYXNzZXRzIGZvciBleHRlbnNpb24gZG9lcyBub3QgZXhpc3RzIGF0ICR7ZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbn0gb3IgYXQgJHtleHRlbnNpb25Bc3NldExvY2F0aW9uQWx0fSBgXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBleHRlbnNpb25Bc3NldExvY2F0aW9uID0gZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkFsdDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBleHRlbnNpb25Bc3NldExvY2F0aW9uV3JhcHBlciA9IHBhdGguam9pbihcbiAgICAgIGV4dGVuc2lvbkFzc2V0TG9jYXRpb24sXG4gICAgICAnc3B5LXdyYXBwZXInXG4gICAgKTtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbldyYXBwZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBXcmFwcGVyIHNjcmlwdCBmb3IgZXh0ZW5zaW9uIGRvZXMgbm90IGV4aXN0cyAke2V4dGVuc2lvbkFzc2V0TG9jYXRpb259YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBleHRlbnNpb25Bc3NldExvY2F0aW9uQ29kZSA9IHBhdGguam9pbihcbiAgICAgIGV4dGVuc2lvbkFzc2V0TG9jYXRpb24sXG4gICAgICBgbm9kZWpzL25vZGVfbW9kdWxlcy9pbnRlcmNlcHRvci5qc2BcbiAgICApO1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhleHRlbnNpb25Bc3NldExvY2F0aW9uQ29kZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYENvZGUgZm9yIGV4dGVuc2lvbiBkb2VzIG5vdCBleGlzdHMgJHtleHRlbnNpb25Bc3NldExvY2F0aW9uQ29kZX1gXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbjtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0TGFuZ3VhZ2VFeHRlbnNpb25Bc3NldExvY2F0aW9uKGxhbmd1YWdlOiBzdHJpbmcpIHtcbiAgICBjb25zdCByb290RGlyID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uJyk7XG5cbiAgICBsZXQgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbiA9IHBhdGguam9pbihyb290RGlyLCBgZXh0ZW5zaW9ucy8ke2xhbmd1YWdlfWApO1xuXG4gICAgY29uc3QgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkFsdCA9IHBhdGguam9pbihcbiAgICAgIHJvb3REaXIsXG4gICAgICBgbGliL2V4dGVuc2lvbnMvJHtsYW5ndWFnZX1gXG4gICAgKTtcblxuICAgIGlmICghZnMuZXhpc3RzU3luYyhleHRlbnNpb25Bc3NldExvY2F0aW9uKSkge1xuICAgICAgaWYgKCFmcy5leGlzdHNTeW5jKGV4dGVuc2lvbkFzc2V0TG9jYXRpb25BbHQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgRm9sZGVyIHdpdGggYXNzZXRzIGZvciBleHRlbnNpb24gZm9yICR7bGFuZ3VhZ2V9IGRvZXMgbm90IGV4aXN0cyBhdCAke2V4dGVuc2lvbkFzc2V0TG9jYXRpb259IG9yIGF0ICR7ZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkFsdH0gYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbiA9IGV4dGVuc2lvbkFzc2V0TG9jYXRpb25BbHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbldyYXBwZXIgPSBwYXRoLmpvaW4oXG4gICAgICAvLyBleHRlbnNpb25Bc3NldExvY2F0aW9uLnN1YnN0cmluZyhcbiAgICAgIC8vICAgMCxcbiAgICAgIC8vICAgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbi5sYXN0SW5kZXhPZihwYXRoLnNlcClcbiAgICAgIC8vICksXG4gICAgICBleHRlbnNpb25Bc3NldExvY2F0aW9uLFxuICAgICAgJ3NweS13cmFwcGVyJ1xuICAgICk7XG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKGV4dGVuc2lvbkFzc2V0TG9jYXRpb25XcmFwcGVyKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgV3JhcHBlciBzY3JpcHQgZm9yIGV4dGVuc2lvbiBkb2VzIG5vdCBleGlzdHMgYXQgJHtleHRlbnNpb25Bc3NldExvY2F0aW9uV3JhcHBlcn1gXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBleHRlbnNpb25Bc3NldExvY2F0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFdyaXRlIFNweUV2ZW50cyBjbGFzcywgd2hpY2ggaGVscHMgd2l0aCB3cml0aW5nIHRoZSBjb2RlIGZvciB0ZXN0cy5cbiAgICogQHBhcmFtIGZpbGVMb2NhdGlvblxuICAgKi9cbiAgcHJpdmF0ZSB3cml0ZVNweUV2ZW50c0NsYXNzKGZpbGVMb2NhdGlvbjogc3RyaW5nKSB7XG4gICAgZnMubWtkaXJTeW5jKHBhdGguZGlybmFtZShmaWxlTG9jYXRpb24pLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcblxuICAgIGNvbnN0IHByb3BlcnRpZXMgPSB0aGlzLnNlcnZpY2VLZXlzXG4gICAgICAubWFwKChzaykgPT4gYCAgJHtzay5yZXBsYWNlKC8jL2csICcnKX06ICcke3NrfScgPSAnJHtza30nO1xcbmApXG4gICAgICAuam9pbignJyk7XG5cbiAgICBjb25zdCBjb2RlID0gYC8qIGVzbGludC1kaXNhYmxlICovXFxuZXhwb3J0IGNsYXNzIFNlcnZlcmxlc3NTcHlFdmVudHMge1xcbiR7cHJvcGVydGllc319XFxuYDtcblxuICAgIGZzLndyaXRlRmlsZVN5bmMoZmlsZUxvY2F0aW9uLCBjb2RlKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0QWxsTm9kZXMocGFyZW50OiBJQ29uc3RydWN0KSB7XG4gICAgY29uc3Qgbm9kZXM6IElDb25zdHJ1Y3RbXSA9IFtdO1xuICAgIG5vZGVzLnB1c2gocGFyZW50KTtcbiAgICB0aGlzLmdldEFsbE5vZGVzUmVjdXJzaXZlKHBhcmVudCwgbm9kZXMpO1xuICAgIHJldHVybiBub2RlcztcbiAgfVxuXG4gIHByaXZhdGUgZ2V0QWxsTm9kZXNSZWN1cnNpdmUocGFyZW50OiBJQ29uc3RydWN0LCBub2RlczogSUNvbnN0cnVjdFtdKSB7XG4gICAgZm9yIChjb25zdCBub2RlIG9mIHBhcmVudC5ub2RlLmNoaWxkcmVuKSB7XG4gICAgICBub2Rlcy5wdXNoKG5vZGUpO1xuICAgICAgdGhpcy5nZXRBbGxOb2Rlc1JlY3Vyc2l2ZShub2RlLCBub2Rlcyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweU5vZGUobm9kZTogSUNvbnN0cnVjdCkge1xuICAgIGlmICh0aGlzLnNwaWVkTm9kZXMuaW5jbHVkZXMobm9kZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnNwaWVkTm9kZXMucHVzaChub2RlKTtcblxuICAgIGlmICh0aGlzLmNyZWF0ZWRSZXNvdXJjZXNCeVNTcHkuaW5jbHVkZXMobm9kZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5sYW1iZGFTdWJzY3JpcHRpb25Qb29sLmZpbmQoKHMpID0+IHMuZnVuY3Rpb24gPT09IG5vZGUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucHJvcHM/LmRlYnVnTW9kZSkge1xuICAgICAgY29uc29sZS5pbmZvKCdTcHkgb24gbm9kZScsIHRoaXMuZ2V0Q29uc3RydWN0TmFtZShub2RlKSk7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgbm9kZSBpbnN0YW5jZW9mIGxhbWJkYS5GdW5jdGlvbiB8fFxuICAgICAgbm9kZSBpbnN0YW5jZW9mIE5vZGVqc0Z1bmN0aW9uIHx8XG4gICAgICBpc0xhbWJkYUZ1bmN0aW9uKG5vZGUpXG4gICAgKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5TGFtYmRhKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHNucy5Ub3BpYykge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweVNuc1RvcGljKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHNucy5TdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlTbnNTdWJzY3JpcHRpb24obm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgczMuQnVja2V0KSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5UzMobm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgZHluYW1vRGIuVGFibGUpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlEeW5hbW9kYihub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBkeW5hbW9EYi5UYWJsZVYyKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5RHluYW1vZGIobm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgZXZlbnRzLkV2ZW50QnVzKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5RXZlbnRCdXMobm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgZXZlbnRzLlJ1bGUpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlFdmVudEJ1c1J1bGUobm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgbGFtYmRhLkNmbkV2ZW50U291cmNlTWFwcGluZykge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweVNxcyhub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBzcXMuUXVldWUpIHtcbiAgICAgIGlmICh0aGlzLnByb3BzPy5zcHlTcXNXaXRoTm9TdWJzY3JpcHRpb25BbmREcm9wQWxsTWVzc2FnZXMpIHtcbiAgICAgICAgdGhpcy5pbnRlcm5hbFNweVNweVNxc1dpdGhOb1N1YnNjcmlwdGlvbihub2RlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldEV4dGVuc2lvbkZvclJ1bnRpbWUoXG4gICAgcnVudGltZTogbGFtYmRhLlJ1bnRpbWUsXG4gICAgYXJjaGl0ZWN0dXJlOiBsYW1iZGEuQXJjaGl0ZWN0dXJlXG4gICk6IHsgbGF5ZXI6IGxhbWJkYS5JTGF5ZXJWZXJzaW9uOyBzcHlXcmFwcGVyUGF0aDogc3RyaW5nIH0gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGxheWVyS2V5ID1cbiAgICAgIGBzc3B5X2V4dGVuc2lvbl8ke3J1bnRpbWUudG9TdHJpbmcoKX1fJHthcmNoaXRlY3R1cmUubmFtZS50b1N0cmluZygpfWAucmVwbGFjZShcbiAgICAgICAgL1xcLi9nLFxuICAgICAgICAnXydcbiAgICAgICk7XG5cbiAgICBsZXQgbGF5ZXIgPSB0aGlzLmxheWVyTWFwW2xheWVyS2V5XTtcbiAgICBsZXQgc3B5V3JhcHBlclBhdGggPSAnL29wdC9zcHktd3JhcHBlcic7XG5cbiAgICBzd2l0Y2ggKHJ1bnRpbWUubmFtZSkge1xuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5QWVRIT05fM184Lm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLlBZVEhPTl8zXzkubmFtZTpcbiAgICAgIGNhc2UgbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfMTAubmFtZTpcbiAgICAgIGNhc2UgbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfMTEubmFtZTpcbiAgICAgIGNhc2UgbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfMTIubmFtZTpcbiAgICAgICAgc3B5V3JhcHBlclBhdGggPSAnL29wdC9weXRob24vc3B5LXdyYXBwZXInO1xuICAgICAgICBsYXllciA9XG4gICAgICAgICAgbGF5ZXIgfHxcbiAgICAgICAgICBuZXcgUHl0aG9uTGF5ZXJWZXJzaW9uKHRoaXMsIGxheWVyS2V5LCB7XG4gICAgICAgICAgICBjb21wYXRpYmxlUnVudGltZXM6IFtydW50aW1lXSxcbiAgICAgICAgICAgIGNvbXBhdGlibGVBcmNoaXRlY3R1cmVzOiBbYXJjaGl0ZWN0dXJlXSxcbiAgICAgICAgICAgIGVudHJ5OiB0aGlzLmdldExhbmd1YWdlRXh0ZW5zaW9uQXNzZXRMb2NhdGlvbigncHl0aG9uJyksXG4gICAgICAgICAgICBidW5kbGluZzoge1xuICAgICAgICAgICAgICBidW5kbGluZ0ZpbGVBY2Nlc3M6IEJ1bmRsaW5nRmlsZUFjY2Vzcy5WT0xVTUVfQ09QWSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5OT0RFSlNfMTJfWC5uYW1lOlxuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5OT0RFSlNfMTRfWC5uYW1lOlxuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5OT0RFSlNfMTZfWC5uYW1lOlxuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5OT0RFSlNfMThfWC5uYW1lOlxuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5OT0RFSlNfMjBfWC5uYW1lOlxuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5OT0RFSlNfMjJfWC5uYW1lOlxuICAgICAgICBsYXllciA9XG4gICAgICAgICAgbGF5ZXIgfHxcbiAgICAgICAgICBuZXcgbGFtYmRhLkxheWVyVmVyc2lvbih0aGlzLCBsYXllcktleSwge1xuICAgICAgICAgICAgY29tcGF0aWJsZVJ1bnRpbWVzOiBbcnVudGltZV0sXG4gICAgICAgICAgICBjb21wYXRpYmxlQXJjaGl0ZWN0dXJlczogW2FyY2hpdGVjdHVyZV0sXG4gICAgICAgICAgICBjb2RlOiBsYW1iZGEuQ29kZS5mcm9tQXNzZXQodGhpcy5nZXRFeHRlbnNpb25Bc3NldExvY2F0aW9uKCkpLFxuICAgICAgICAgIH0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGNvbnNvbGUubG9nKGBObyBleHRlbnNpb25zIGF2YWlsYWJsZSBmb3IgJHtydW50aW1lLnRvU3RyaW5nKCl9YCk7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgdGhpcy5sYXllck1hcFtsYXllcktleV0gPSBsYXllcjtcbiAgICB0aGlzLmNyZWF0ZWRSZXNvdXJjZXNCeVNTcHkucHVzaChsYXllcik7XG4gICAgcmV0dXJuIHsgbGF5ZXIsIHNweVdyYXBwZXJQYXRoIH07XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5U3B5U3FzV2l0aE5vU3Vic2NyaXB0aW9uKHF1ZXVlOiBzcXMuUXVldWUpIHtcbiAgICBjb25zdCBzdWJzY3JpcHRpb24gPSB0aGlzLmZpbmRFbGVtZW50PGxhbWJkYS5DZm5FdmVudFNvdXJjZU1hcHBpbmc+KFxuICAgICAgKG46IElDb25zdHJ1Y3QpID0+XG4gICAgICAgIG4gaW5zdGFuY2VvZiBsYW1iZGEuQ2ZuRXZlbnRTb3VyY2VNYXBwaW5nICYmXG4gICAgICAgIChuIGFzIGxhbWJkYS5DZm5FdmVudFNvdXJjZU1hcHBpbmcpLmV2ZW50U291cmNlQXJuID09PSBxdWV1ZS5xdWV1ZUFyblxuICAgICk7XG5cbiAgICBpZiAoc3Vic2NyaXB0aW9uKSB7XG4gICAgICByZXR1cm47IC8vYWxyZWFkeSBoYXZlIHN1YnNjcmlwdGlvblxuICAgIH1cblxuICAgIGNvbnN0IHF1ZXVlTmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZShxdWV1ZSk7XG4gICAgY29uc3QgZnVuYyA9IG5ldyBOb2RlanNGdW5jdGlvbihcbiAgICAgIHRoaXMsXG4gICAgICBgJHtxdWV1ZU5hbWV9U3FzU3Vic2NyaXB0aW9uQW5kRHJvcEFsbE1lc3NhZ2VzYCxcbiAgICAgIHtcbiAgICAgICAgbWVtb3J5U2l6ZTogNTEyLFxuICAgICAgICB0aW1lb3V0OiBEdXJhdGlvbi5zZWNvbmRzKDUpLFxuICAgICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5OT0RFSlNfMjJfWCxcbiAgICAgICAgaGFuZGxlcjogJ2hhbmRsZXInLFxuICAgICAgICBlbnRyeTogdGhpcy5nZXRBc3NldExvY2F0aW9uKFxuICAgICAgICAgICdmdW5jdGlvbnMvc3FzU3Vic2NyaXB0aW9uQW5kRHJvcEFsbE1lc3NhZ2VzLmpzJ1xuICAgICAgICApLFxuICAgICAgICBlbnZpcm9ubWVudDogdGhpcy5nZXREZWZhdWx0TGFtYmRhRW52aXJvbm1lbnRWYXJpYWJsZXMoKSxcbiAgICAgIH1cbiAgICApO1xuICAgIGZ1bmMuYWRkRXZlbnRTb3VyY2UobmV3IFNxc0V2ZW50U291cmNlKHF1ZXVlKSk7XG4gICAgdGhpcy5zZXR1cEZvcklvVChmdW5jKTtcbiAgICBjb25zdCB7IGxheWVyLCBzcHlXcmFwcGVyUGF0aCB9ID0gdGhpcy5nZXRFeHRlbnNpb25Gb3JSdW50aW1lKFxuICAgICAgZnVuYy5ydW50aW1lLFxuICAgICAgZnVuYy5hcmNoaXRlY3R1cmVcbiAgICApITtcbiAgICBmdW5jLmFkZExheWVycyhsYXllcik7XG5cbiAgICBmdW5jLmFkZEVudmlyb25tZW50KCdBV1NfTEFNQkRBX0VYRUNfV1JBUFBFUicsIHNweVdyYXBwZXJQYXRoKTtcblxuICAgIGlmICh0aGlzLnByb3BzPy5kZWJ1Z01vZGUpIHtcbiAgICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoZW52VmFyaWFibGVOYW1lcy5TU1BZX0RFQlVHLCAndHJ1ZScpO1xuICAgIH1cblxuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKGZ1bmMpO1xuXG4gICAgY29uc3Qgc2VydmljZUtleSA9IGBTcXMjJHtxdWV1ZU5hbWV9YDtcblxuICAgIHRoaXMuYWRkTWFwcGluZ1RvRnVuY3Rpb24oZnVuYywge1xuICAgICAga2V5OiBxdWV1ZS5xdWV1ZUFybixcbiAgICAgIHZhbHVlOiBzZXJ2aWNlS2V5LFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoZW52VmFyaWFibGVOYW1lcy5TU1BZX1NVQlNDUklCRURfVE9fU1FTLCAndHJ1ZScpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweVNxcyhub2RlOiBsYW1iZGEuQ2ZuRXZlbnRTb3VyY2VNYXBwaW5nKSB7XG4gICAgY29uc3QgcXVldWUgPSB0aGlzLmZpbmRFbGVtZW50PHNxcy5RdWV1ZT4oXG4gICAgICAobjogSUNvbnN0cnVjdCkgPT5cbiAgICAgICAgbiBpbnN0YW5jZW9mIHNxcy5RdWV1ZSAmJlxuICAgICAgICAobiBhcyBzcXMuUXVldWUpLnF1ZXVlQXJuID09PSBub2RlLmV2ZW50U291cmNlQXJuXG4gICAgKTtcblxuICAgIGNvbnN0IGZ1bmMgPSB0aGlzLmZpbmRFbGVtZW50PGxhbWJkYS5GdW5jdGlvbj4oXG4gICAgICAobjogSUNvbnN0cnVjdCkgPT5cbiAgICAgICAgbiBpbnN0YW5jZW9mIGxhbWJkYS5GdW5jdGlvbiAmJlxuICAgICAgICAobiBhcyBsYW1iZGEuRnVuY3Rpb24pLmZ1bmN0aW9uTmFtZSA9PT0gbm9kZS5mdW5jdGlvbk5hbWVcbiAgICApO1xuXG4gICAgaWYgKHF1ZXVlICYmIGZ1bmMpIHtcbiAgICAgIGNvbnN0IHF1ZXVlTmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZShxdWV1ZSk7XG5cbiAgICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgU3FzIyR7cXVldWVOYW1lfWA7XG5cbiAgICAgIHRoaXMuYWRkTWFwcGluZ1RvRnVuY3Rpb24oZnVuYywge1xuICAgICAgICBrZXk6IHF1ZXVlLnF1ZXVlQXJuLFxuICAgICAgICB2YWx1ZTogc2VydmljZUtleSxcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goc2VydmljZUtleSk7XG4gICAgICBmdW5jLmFkZEVudmlyb25tZW50KGVudlZhcmlhYmxlTmFtZXMuU1NQWV9TVUJTQ1JJQkVEX1RPX1NRUywgJ3RydWUnKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZUZ1bmN0aW9uRm9yU3Vic2NyaXB0aW9uKGluZGV4OiBudW1iZXIpIHtcbiAgICBjb25zdCBmdW5jID0gbmV3IGxhbWJkYU5vZGUuTm9kZWpzRnVuY3Rpb24odGhpcywgYFN1YnNjcmlwdGlvbiR7aW5kZXh9YCwge1xuICAgICAgbWVtb3J5U2l6ZTogNTEyLFxuICAgICAgdGltZW91dDogRHVyYXRpb24uc2Vjb25kcyg1KSxcbiAgICAgIHJ1bnRpbWU6IGxhbWJkYS5SdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgaGFuZGxlcjogJ2hhbmRsZXInLFxuICAgICAgZW50cnk6IHRoaXMuZ2V0QXNzZXRMb2NhdGlvbignZnVuY3Rpb25zL3NlbmRNZXNzYWdlLmpzJyksXG4gICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICBOT0RFX09QVElPTlM6ICctLWVuYWJsZS1zb3VyY2UtbWFwcycsXG4gICAgICB9LFxuICAgIH0pO1xuICAgIHRoaXMuc2V0dXBGb3JJb1QoZnVuYyk7XG4gICAgcmV0dXJuIGZ1bmM7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5UzMoczNCdWNrZXQ6IHMzLkJ1Y2tldCkge1xuICAgIHMzQnVja2V0LmFkZEV2ZW50Tm90aWZpY2F0aW9uKFxuICAgICAgczMuRXZlbnRUeXBlLk9CSkVDVF9DUkVBVEVEX1BVVCxcbiAgICAgIG5ldyBzM25vdGlmLkxhbWJkYURlc3RpbmF0aW9uKHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uTWFpbi5mdW5jdGlvbilcbiAgICApO1xuXG4gICAgY29uc3QgbmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZShzM0J1Y2tldCk7XG5cbiAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYFMzIyR7bmFtZX1gO1xuICAgIHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uTWFpbi5tYXBwaW5nW3MzQnVja2V0LmJ1Y2tldEFybl0gPSBzZXJ2aWNlS2V5O1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlEeW5hbW9kYih0YWJsZTogZHluYW1vRGIuVGFibGUgfCBkeW5hbW9EYi5UYWJsZVYyKSB7XG4gICAgLy8gZW5hYmxlIER5bmFtb0RCIHN0cmVhbXMgd2l0aCBhIGhhY2tcbiAgICAodGFibGUubm9kZS5kZWZhdWx0Q2hpbGQgYXMgZHluYW1vRGIuQ2ZuVGFibGUpLnN0cmVhbVNwZWNpZmljYXRpb24gPSB7XG4gICAgICBzdHJlYW1WaWV3VHlwZTogZHluYW1vRGIuU3RyZWFtVmlld1R5cGUuTkVXX0FORF9PTERfSU1BR0VTLFxuICAgIH07XG4gICAgdmFyIHRhYmxlU3RyZWFtQXJuRGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoXG4gICAgICB0YWJsZSxcbiAgICAgICd0YWJsZVN0cmVhbUFybidcbiAgICApO1xuXG4gICAgaWYgKFxuICAgICAgdGFibGVTdHJlYW1Bcm5EZXNjcmlwdG9yID09PSB1bmRlZmluZWQgfHxcbiAgICAgIHRhYmxlU3RyZWFtQXJuRGVzY3JpcHRvci5nZXQgPT09IHVuZGVmaW5lZFxuICAgICkge1xuICAgICAgKHRhYmxlIGFzIGFueSkudGFibGVTdHJlYW1Bcm4gPSAoXG4gICAgICAgIHRhYmxlLm5vZGUuZGVmYXVsdENoaWxkIGFzIGR5bmFtb0RiLkNmblRhYmxlXG4gICAgICApLmF0dHJTdHJlYW1Bcm47XG4gICAgfVxuXG4gICAgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25NYWluLmZ1bmN0aW9uLmFkZEV2ZW50U291cmNlKFxuICAgICAgbmV3IGR5bmFtb0RiU3RyZWFtLkR5bmFtb0V2ZW50U291cmNlKHRhYmxlLCB7XG4gICAgICAgIHN0YXJ0aW5nUG9zaXRpb246IGxhbWJkYS5TdGFydGluZ1Bvc2l0aW9uLkxBVEVTVCxcbiAgICAgICAgYmF0Y2hTaXplOiAxLFxuICAgICAgICByZXRyeUF0dGVtcHRzOiAwLFxuICAgICAgfSlcbiAgICApO1xuXG4gICAgY29uc3QgbmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZSh0YWJsZSk7XG5cbiAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYER5bmFtb0RCIyR7bmFtZX1gO1xuICAgIHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uTWFpbi5tYXBwaW5nW3RhYmxlLnRhYmxlQXJuXSA9IHNlcnZpY2VLZXk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweUV2ZW50QnVzUnVsZShydWxlOiBldmVudHMuUnVsZSkge1xuICAgIGNvbnN0IHsgZXZlbnRCdXNOYW1lIH0gPSBydWxlLm5vZGUuZGVmYXVsdENoaWxkIGFzIGV2ZW50cy5DZm5SdWxlO1xuICAgIGxldCBicmlkZ2VOYW1lID0gJ0RlZmF1bHQnO1xuICAgIGlmICghIWV2ZW50QnVzTmFtZSkge1xuICAgICAgY29uc3QgZXZlbnRCcmlkZ2UgPSB0aGlzLmdldEV2ZW50QnJpZGdlKGV2ZW50QnVzTmFtZSk7XG5cbiAgICAgIGlmICghZXZlbnRCcmlkZ2UpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4gbm90IGZpbmQgRXZlbnRCcmlkZ2Ugd2l0aCBuYW1lIFwiJHtldmVudEJ1c05hbWV9XCJgKTtcbiAgICAgIH1cbiAgICAgIGJyaWRnZU5hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUoZXZlbnRCcmlkZ2UpO1xuICAgIH1cblxuICAgIGNvbnN0IGZ1bmN0aW9uU3Vic2NyaXB0aW9uID0gdGhpcy5wcm92aWRlRnVuY3Rpb25Gb3JTdWJzY3JpcHRpb24oXG4gICAgICAocykgPT4gIXMudXNlZEZvckV2ZW50QnJpZGdlXG4gICAgKTtcbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi51c2VkRm9yRXZlbnRCcmlkZ2UgPSB0cnVlO1xuXG4gICAgcnVsZS5hZGRUYXJnZXQobmV3IHRhcmdldHMuTGFtYmRhRnVuY3Rpb24oZnVuY3Rpb25TdWJzY3JpcHRpb24uZnVuY3Rpb24pKTtcblxuICAgIGNvbnN0IHJ1bGVOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHJ1bGUpO1xuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgRXZlbnRCcmlkZ2VSdWxlIyR7YnJpZGdlTmFtZX0jJHtydWxlTmFtZX1gO1xuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLm1hcHBpbmcuZXZlbnRCcmlkZ2UgPSBzZXJ2aWNlS2V5O1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlFdmVudEJ1cyhldmVudEJ1czogZXZlbnRzLkV2ZW50QnVzKSB7XG4gICAgY29uc3QgZnVuY3Rpb25TdWJzY3JpcHRpb24gPSB0aGlzLnByb3ZpZGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbihcbiAgICAgIChzKSA9PiAhcy51c2VkRm9yRXZlbnRCcmlkZ2VcbiAgICApO1xuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLnVzZWRGb3JFdmVudEJyaWRnZSA9IHRydWU7XG5cbiAgICBjb25zdCBicmlkZ2VOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKGV2ZW50QnVzKTtcbiAgICBjb25zdCBydWxlID0gbmV3IGV2ZW50cy5SdWxlKHRoaXMsIGBSdWxlQWxsJHticmlkZ2VOYW1lfWAsIHtcbiAgICAgIGV2ZW50QnVzLFxuICAgICAgZXZlbnRQYXR0ZXJuOiB7IHZlcnNpb246IFsnMCddIH0sXG4gICAgICB0YXJnZXRzOiBbbmV3IHRhcmdldHMuTGFtYmRhRnVuY3Rpb24oZnVuY3Rpb25TdWJzY3JpcHRpb24uZnVuY3Rpb24pXSxcbiAgICB9KTtcblxuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKHJ1bGUpO1xuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgRXZlbnRCcmlkZ2UjJHticmlkZ2VOYW1lfWA7XG4gICAgZnVuY3Rpb25TdWJzY3JpcHRpb24ubWFwcGluZy5ldmVudEJyaWRnZSA9IHNlcnZpY2VLZXk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweVNuc1RvcGljKHRvcGljOiBzbnMuVG9waWMpIHtcbiAgICBjb25zdCBmdW5jdGlvblN1YnNjcmlwdGlvbiA9IHRoaXMucHJvdmlkZUZ1bmN0aW9uRm9yU3Vic2NyaXB0aW9uKFxuICAgICAgKHMpID0+ICFzLnN1YnNyaWJlZFRvcGljcy5pbmNsdWRlcyh0b3BpYylcbiAgICApO1xuXG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gdG9waWMuYWRkU3Vic2NyaXB0aW9uKFxuICAgICAgbmV3IHNuc1N1YnMuTGFtYmRhU3Vic2NyaXB0aW9uKGZ1bmN0aW9uU3Vic2NyaXB0aW9uLmZ1bmN0aW9uKVxuICAgICk7XG4gICAgdGhpcy5jcmVhdGVkUmVzb3VyY2VzQnlTU3B5LnB1c2goc3Vic2NyaXB0aW9uKTtcbiAgICBjb25zdCB0b3BpY05hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUodG9waWMpO1xuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgU25zVG9waWMjJHt0b3BpY05hbWV9YDtcbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi5tYXBwaW5nW3RvcGljLnRvcGljQXJuXSA9IHNlcnZpY2VLZXk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLnN1YnNyaWJlZFRvcGljcy5wdXNoKHRvcGljKTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlTbnNTdWJzY3JpcHRpb24oc3Vic2NyaXB0aW9uOiBzbnMuU3Vic2NyaXB0aW9uKSB7XG4gICAgaWYgKCFzdWJzY3JpcHRpb24ubm9kZS5zY29wZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHRvcGljID0gdGhpcy5nZXRUb3BpYyhcbiAgICAgIChzdWJzY3JpcHRpb24ubm9kZS5kZWZhdWx0Q2hpbGQgYXMgc25zLkNmblN1YnNjcmlwdGlvbikudG9waWNBcm5cbiAgICApO1xuXG4gICAgaWYgKCF0b3BpYykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gbm90IGZpbmQgVG9waWMnKTtcbiAgICB9XG5cbiAgICBjb25zdCBmdW5jdGlvblN1YnNjcmlwdGlvbiA9IHRoaXMucHJvdmlkZUZ1bmN0aW9uRm9yU3Vic2NyaXB0aW9uKFxuICAgICAgKHMpID0+ICFzLnN1YnNyaWJlZFRvcGljcy5pbmNsdWRlcyh0b3BpYylcbiAgICApO1xuXG4gICAgY29uc3QgeyBmaWx0ZXJQb2xpY3kgfSA9IHN1YnNjcmlwdGlvbi5ub2RlXG4gICAgICAuZGVmYXVsdENoaWxkIGFzIHNucy5DZm5TdWJzY3JpcHRpb247XG5cbiAgICBjb25zdCBzdWJzY3JpcHRpb25DbG9uZSA9IHRvcGljLmFkZFN1YnNjcmlwdGlvbihcbiAgICAgIG5ldyBzbnNTdWJzLkxhbWJkYVN1YnNjcmlwdGlvbihmdW5jdGlvblN1YnNjcmlwdGlvbi5mdW5jdGlvbilcbiAgICApO1xuICAgIChzdWJzY3JpcHRpb25DbG9uZS5ub2RlLmRlZmF1bHRDaGlsZCBhcyBzbnMuQ2ZuU3Vic2NyaXB0aW9uKS5maWx0ZXJQb2xpY3kgPVxuICAgICAgZmlsdGVyUG9saWN5O1xuXG4gICAgdGhpcy5jcmVhdGVkUmVzb3VyY2VzQnlTU3B5LnB1c2goc3Vic2NyaXB0aW9uQ2xvbmUpO1xuXG4gICAgY29uc3QgdG9waWNOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHRvcGljKTtcbiAgICBjb25zdCB0YXJnZXROYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHN1YnNjcmlwdGlvbi5ub2RlLnNjb3BlKTtcblxuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLnN1YnNyaWJlZFRvcGljcy5wdXNoKHRvcGljKTtcbiAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYFNuc1N1YnNjcmlwdGlvbiMke3RvcGljTmFtZX0jJHt0YXJnZXROYW1lfWA7XG4gICAgZnVuY3Rpb25TdWJzY3JpcHRpb24ubWFwcGluZ1t0b3BpYy50b3BpY0Fybl0gPSBzZXJ2aWNlS2V5O1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgfVxuXG4gIHByaXZhdGUgcHJvdmlkZUZ1bmN0aW9uRm9yU3Vic2NyaXB0aW9uKFxuICAgIGZpbHRlckZ1bmN0aW9uPzogKHN1YnNjcmlwdGlvbjogTGFtYmRhU3Vic2NyaXB0aW9uKSA9PiBib29sZWFuXG4gICkge1xuICAgIGxldCBmdW5jdGlvblN1YnNjcmlwdGlvbjogTGFtYmRhU3Vic2NyaXB0aW9uIHwgdW5kZWZpbmVkO1xuXG4gICAgaWYgKGZpbHRlckZ1bmN0aW9uKSB7XG4gICAgICBmdW5jdGlvblN1YnNjcmlwdGlvbiA9IHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uUG9vbC5maW5kKGZpbHRlckZ1bmN0aW9uKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uUG9vbC5sZW5ndGggPiAwKSB7XG4gICAgICBmdW5jdGlvblN1YnNjcmlwdGlvbiA9IHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uUG9vbFswXTtcbiAgICB9XG5cbiAgICBpZiAoIWZ1bmN0aW9uU3Vic2NyaXB0aW9uKSB7XG4gICAgICBmdW5jdGlvblN1YnNjcmlwdGlvbiA9IHtcbiAgICAgICAgc3Vic3JpYmVkVG9waWNzOiBbXSxcbiAgICAgICAgdXNlZEZvckV2ZW50QnJpZGdlOiBmYWxzZSxcbiAgICAgICAgbWFwcGluZzoge30sXG4gICAgICAgIGZ1bmN0aW9uOiB0aGlzLmNyZWF0ZUZ1bmN0aW9uRm9yU3Vic2NyaXB0aW9uKFxuICAgICAgICAgIHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uUG9vbC5sZW5ndGhcbiAgICAgICAgKSxcbiAgICAgIH07XG4gICAgICB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2wucHVzaChmdW5jdGlvblN1YnNjcmlwdGlvbik7XG4gICAgfVxuICAgIHJldHVybiBmdW5jdGlvblN1YnNjcmlwdGlvbjtcbiAgfVxuXG4gIHByaXZhdGUgc2V0dXBGb3JJb1QoZnVuYzogbGFtYmRhLkZ1bmN0aW9uKSB7XG4gICAgZnVuYy5hZGRFbnZpcm9ubWVudChcbiAgICAgIGVudlZhcmlhYmxlTmFtZXMuU1NQWV9ST09UX1NUQUNLLFxuICAgICAgdGhpcy5jbGVhbk5hbWUodGhpcy5maW5kUm9vdFN0YWNrKFN0YWNrLm9mKHRoaXMpKS5ub2RlLmlkKVxuICAgICk7XG4gICAgZnVuYy5hZGRFbnZpcm9ubWVudChlbnZWYXJpYWJsZU5hbWVzLlNTUFlfSU9UX0VORFBPSU5ULCB0aGlzLmlvdEVuZHBvaW50KTtcblxuICAgIGZ1bmMuYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgbmV3IGF3c19pYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgYWN0aW9uczogWydpb3Q6KiddLFxuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlMYW1iZGEoZnVuYzogbGFtYmRhLkZ1bmN0aW9uKSB7XG4gICAgY29uc3QgeyBsYXllciwgc3B5V3JhcHBlclBhdGggfSA9IHRoaXMuZ2V0RXh0ZW5zaW9uRm9yUnVudGltZShcbiAgICAgIGZ1bmMucnVudGltZSxcbiAgICAgIGZ1bmMuYXJjaGl0ZWN0dXJlIHx8IEFyY2hpdGVjdHVyZS5YODZfNjRcbiAgICApITtcbiAgICBpZiAoIWxheWVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZ1bmMuYWRkTGF5ZXJzKGxheWVyKTtcblxuICAgIGNvbnN0IGZ1bmN0aW9uTmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZShmdW5jKTtcblxuICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoZW52VmFyaWFibGVOYW1lcy5TU1BZX0ZVTkNUSU9OX05BTUUsIGZ1bmN0aW9uTmFtZSk7XG4gICAgZnVuYy5hZGRFbnZpcm9ubWVudCgnQVdTX0xBTUJEQV9FWEVDX1dSQVBQRVInLCBzcHlXcmFwcGVyUGF0aCk7XG5cbiAgICBpZiAodGhpcy5wcm9wcz8uZGVidWdNb2RlKSB7XG4gICAgICBmdW5jLmFkZEVudmlyb25tZW50KGVudlZhcmlhYmxlTmFtZXMuU1NQWV9ERUJVRywgJ3RydWUnKTtcbiAgICB9XG5cbiAgICB0aGlzLnNldHVwRm9ySW9UKGZ1bmMpO1xuXG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKGBGdW5jdGlvbiMke2Z1bmN0aW9uTmFtZX0jUmVxdWVzdGApO1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChgRnVuY3Rpb24jJHtmdW5jdGlvbk5hbWV9I0Vycm9yYCk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKGBGdW5jdGlvbiMke2Z1bmN0aW9uTmFtZX0jQ29uc29sZWApO1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChgRnVuY3Rpb24jJHtmdW5jdGlvbk5hbWV9I1Jlc3BvbnNlYCk7XG5cbiAgICB0aGlzLmFkZE1hcHBpbmdUb0Z1bmN0aW9uKGZ1bmMpO1xuICB9XG5cbiAgcHVibGljIGdldENvbnN0cnVjdE5hbWUoY29uc3RydWN0OiBJQ29uc3RydWN0KSB7XG4gICAgbGV0IGNvbnN0cnVjdE5hbWUgPSBjb25zdHJ1Y3Qubm9kZS5wYXRoO1xuICAgIGNvbnN0IHsgbm9kZSB9ID0gU3RhY2sub2YodGhpcyk7XG5cbiAgICBpZiAoY29uc3RydWN0TmFtZS5zdGFydHNXaXRoKG5vZGUuaWQpKSB7XG4gICAgICBjb25zdHJ1Y3ROYW1lID0gY29uc3RydWN0TmFtZS5zdWJzdHJpbmcobm9kZS5pZC5sZW5ndGggKyAxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jbGVhbk5hbWUoY29uc3RydWN0TmFtZSk7XG4gIH1cblxuICBwcml2YXRlIGNsZWFuTmFtZShuYW1lOiBzdHJpbmcpIHtcbiAgICAvL3NuYWtlIGNhc2UgdG8gY2FtZWwgY2FzZSBpbmNsdWRpbmcgZGFzaCBhbmQgZmlyc3QgbGV0dGVyIHRvIHVwcGVyIGNhc2VcbiAgICByZXR1cm4gbmFtZVxuICAgICAgLnJlcGxhY2UoL1stX10rL2csICcgJylcbiAgICAgIC5yZXBsYWNlKC9bXlxcd1xcc10vZywgJycpXG4gICAgICAucmVwbGFjZSgvXFxzKC4pL2csICgkMSkgPT4gJDEudG9VcHBlckNhc2UoKSlcbiAgICAgIC5yZXBsYWNlKC9cXHMvZywgJycpXG4gICAgICAucmVwbGFjZSgvXiguKS8sICgkMSkgPT4gJDEudG9VcHBlckNhc2UoKSk7XG4gIH1cblxuICBwcml2YXRlIGdldFRvcGljKHRvcGljQXJuOiBzdHJpbmcpOiBzbnMuVG9waWMgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHRvcGljID0gdGhpcy5maW5kRWxlbWVudDxzbnMuVG9waWM+KFxuICAgICAgKG5vZGU6IElDb25zdHJ1Y3QpID0+XG4gICAgICAgIG5vZGUgaW5zdGFuY2VvZiBzbnMuVG9waWMgJiYgKG5vZGUgYXMgc25zLlRvcGljKS50b3BpY0FybiA9PT0gdG9waWNBcm5cbiAgICApO1xuXG4gICAgcmV0dXJuIHRvcGljO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRFdmVudEJyaWRnZShldmVudEJ1c05hbWU6IHN0cmluZyk6IGV2ZW50cy5JRXZlbnRCdXMgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGV2ZW50QnJpZGdlID0gdGhpcy5maW5kRWxlbWVudDxldmVudHMuSUV2ZW50QnVzPihcbiAgICAgIChub2RlOiBJQ29uc3RydWN0KSA9PlxuICAgICAgICAobm9kZSBpbnN0YW5jZW9mIGV2ZW50cy5FdmVudEJ1cyB8fFxuICAgICAgICAgIG5vZGUuY29uc3RydWN0b3IubmFtZSA9PT0gJ0ltcG9ydGVkRXZlbnRCdXMnKSAmJlxuICAgICAgICAobm9kZSBhcyBldmVudHMuSUV2ZW50QnVzKS5ldmVudEJ1c05hbWUgPT09IGV2ZW50QnVzTmFtZVxuICAgICk7XG5cbiAgICByZXR1cm4gZXZlbnRCcmlkZ2U7XG4gIH1cblxuICBwcml2YXRlIGZpbmRSb290U3RhY2soc3RhY2s6IFN0YWNrKTogU3RhY2sge1xuICAgIGlmIChzdGFjay5uZXN0ZWQpIHtcbiAgICAgIGNvbnN0IHBhcmVudFN0YWNrID0gKHN0YWNrIGFzIE5lc3RlZFN0YWNrKS5uZXN0ZWRTdGFja1BhcmVudDtcbiAgICAgIGlmIChwYXJlbnRTdGFjaykgcmV0dXJuIHRoaXMuZmluZFJvb3RTdGFjayhwYXJlbnRTdGFjayk7XG4gICAgICByZXR1cm4gc3RhY2s7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBzdGFjaztcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGZpbmRFbGVtZW50PFQgZXh0ZW5kcyBJQ29uc3RydWN0ID0gSUNvbnN0cnVjdD4oXG4gICAgZmlsdGVyRnVuYzogKG5vZGU6IElDb25zdHJ1Y3QpID0+IGJvb2xlYW4sXG4gICAgcGFyZW50PzogSUNvbnN0cnVjdFxuICApOiBUIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXBhcmVudCkge1xuICAgICAgcGFyZW50ID0gdGhpcy5maW5kUm9vdFN0YWNrKFN0YWNrLm9mKHRoaXMpKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgcGFyZW50Lm5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIGlmIChmaWx0ZXJGdW5jKG5vZGUpKSB7XG4gICAgICAgIHJldHVybiBub2RlIGFzIFQ7XG4gICAgICB9XG4gICAgICBjb25zdCBlbGVtZW50Rm91bmRJbkNoaWxkID0gdGhpcy5maW5kRWxlbWVudDxUPihmaWx0ZXJGdW5jLCBub2RlKTtcbiAgICAgIGlmIChlbGVtZW50Rm91bmRJbkNoaWxkKSB7XG4gICAgICAgIHJldHVybiBlbGVtZW50Rm91bmRJbkNoaWxkO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBwcml2YXRlIGFkZE1hcHBpbmdUb0Z1bmN0aW9uKFxuICAgIGZ1bmM6IGxhbWJkYS5GdW5jdGlvbixcbiAgICBrZXlWYWx1ZT86IHsga2V5OiBzdHJpbmc7IHZhbHVlOiBzdHJpbmcgfVxuICApIHtcbiAgICBmb3IgKGNvbnN0IGZzIG9mIHRoaXMubGFtYmRhc1NwaWVkKSB7XG4gICAgICBpZiAoZnMuZnVuY3Rpb24gPT09IGZ1bmMpIHtcbiAgICAgICAgaWYgKGtleVZhbHVlKSB7XG4gICAgICAgICAgZnMubWFwcGluZ1trZXlWYWx1ZS5rZXldID0ga2V5VmFsdWUudmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGZzOiBMYW1iZGFTcGllZCA9IHtcbiAgICAgIGZ1bmN0aW9uOiBmdW5jLFxuICAgICAgbWFwcGluZzoge30sXG4gICAgfTtcblxuICAgIGlmIChrZXlWYWx1ZSkge1xuICAgICAgZnMubWFwcGluZ1trZXlWYWx1ZS5rZXldID0ga2V5VmFsdWUudmFsdWU7XG4gICAgfVxuXG4gICAgdGhpcy5sYW1iZGFzU3BpZWQucHVzaChmcyk7XG4gIH1cblxuICBwcml2YXRlIGdldEFzc2V0TG9jYXRpb24obG9jYXRpb246IHN0cmluZykge1xuICAgIGNvbnN0IGxvYyA9IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi9saWIvJyArIGxvY2F0aW9uKTtcblxuICAgIGlmIChmcy5leGlzdHNTeW5jKGxvYykpIHtcbiAgICAgIHJldHVybiBsb2M7XG4gICAgfVxuXG4gICAgY29uc3QgbG9jMiA9IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi8uLi9saWIvJyArIGxvY2F0aW9uKTtcblxuICAgIGlmIChmcy5leGlzdHNTeW5jKGxvYzIpKSB7XG4gICAgICByZXR1cm4gbG9jMjtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYExvY2F0aW9uICR7bG9jfSBhbmQgJHtsb2MyfSBkb2VzIG5vdCBleGlzdHMuYCk7XG4gIH1cbn1cblxudHlwZSBMYW1iZGFTdWJzY3JpcHRpb24gPSB7XG4gIHN1YnNyaWJlZFRvcGljczogc25zLlRvcGljW107XG4gIHVzZWRGb3JFdmVudEJyaWRnZTogYm9vbGVhbjtcbiAgZnVuY3Rpb246IGxhbWJkYU5vZGUuTm9kZWpzRnVuY3Rpb247XG4gIG1hcHBpbmc6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59O1xuXG50eXBlIExhbWJkYVNwaWVkID0ge1xuICBmdW5jdGlvbjogbGFtYmRhLkZ1bmN0aW9uO1xuICBtYXBwaW5nOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xufTtcbiJdfQ==
|
|
633
|
+
ServerlessSpy[_a] = { fqn: "serverless-spy.ServerlessSpy", version: "2.3.21" };
|
|
634
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2VydmVybGVzc1NweS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9TZXJ2ZXJsZXNzU3B5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3Qiw4RUFBc0U7QUFDdEUsNkNBUXFCO0FBQ3JCLHFEQUFxRDtBQUNyRCxpREFBaUQ7QUFDakQsMERBQTBEO0FBQzFELGlEQUE2QztBQUM3QyxpREFBaUQ7QUFDakQsdURBSWdDO0FBQ2hDLHVFQUF1RTtBQUN2RSxtRkFBc0U7QUFDdEUsNERBQTREO0FBQzVELHFFQUErRDtBQUMvRCx5Q0FBeUM7QUFDekMsNERBQTREO0FBQzVELDJDQUEyQztBQUMzQyw2REFBNkQ7QUFDN0QsMkNBQTJDO0FBQzNDLDJDQUFtRDtBQUNuRCxnRUFBNkQ7QUFtQjdELE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxJQUFnQixFQUEyQixFQUFFLENBQ3JFLGNBQWMsSUFBSSxJQUFJLElBQUksYUFBYSxJQUFJLElBQUksSUFBSSxTQUFTLElBQUksSUFBSSxDQUFDO0FBRXZFLE1BQU0sb0NBQW9DLEdBQUcsMEJBQTBCLENBQUM7QUFFeEUsTUFBYSxhQUFjLFNBQVEsc0JBQVM7SUFVMUMsWUFDRSxLQUFnQixFQUNoQixFQUFVLEVBQ0YsS0FBMEI7UUFFbEMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUZULFVBQUssR0FBTCxLQUFLLENBQXFCO1FBWjVCLDJCQUFzQixHQUFpQixFQUFFLENBQUM7UUFDMUMsMkJBQXNCLEdBQXlCLEVBQUUsQ0FBQztRQUVsRCxpQkFBWSxHQUFrQixFQUFFLENBQUM7UUFDbEMsZ0JBQVcsR0FBYSxFQUFFLENBQUM7UUFDMUIsZUFBVSxHQUFpQixFQUFFLENBQUM7UUFDOUIsYUFBUSxHQUEyQyxFQUFFLENBQUM7UUFVNUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FDOUIsSUFBSSxDQUFDLGFBQWEsQ0FB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RyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxTQUFTLEdBQUcsUUFBUSxDQUFDLENBQUM7UUFFdkQsSUFBSSxFQUFFLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDdkIsT0FBTyxHQUFHLENBQUM7UUFDYixDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsWUFBWSxHQUFHLFFBQVEsQ0FBQyxDQUFDO1FBRTNELElBQUksRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3hCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsWUFBWSxHQUFHLFFBQVEsSUFBSSxtQkFBbUIsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7O0FBbjBCSCxzQ0FvMEJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IFB5dGhvbkxheWVyVmVyc2lvbiB9IGZyb20gJ0Bhd3MtY2RrL2F3cy1sYW1iZGEtcHl0aG9uLWFscGhhJztcbmltcG9ydCB7XG4gIGF3c19pYW0sXG4gIEJ1bmRsaW5nRmlsZUFjY2VzcyxcbiAgQ2ZuT3V0cHV0LFxuICBjdXN0b21fcmVzb3VyY2VzLFxuICBEdXJhdGlvbixcbiAgTmVzdGVkU3RhY2ssXG4gIFN0YWNrLFxufSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBkeW5hbW9EYiBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZHluYW1vZGInO1xuaW1wb3J0ICogYXMgZXZlbnRzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1ldmVudHMnO1xuaW1wb3J0ICogYXMgdGFyZ2V0cyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZXZlbnRzLXRhcmdldHMnO1xuaW1wb3J0IHsgRWZmZWN0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQge1xuICBBcmNoaXRlY3R1cmUsXG4gIElMYXllclZlcnNpb24sXG4gIFNpbmdsZXRvbkZ1bmN0aW9uLFxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCAqIGFzIGR5bmFtb0RiU3RyZWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEtZXZlbnQtc291cmNlcyc7XG5pbXBvcnQgeyBTcXNFdmVudFNvdXJjZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEtZXZlbnQtc291cmNlcyc7XG5pbXBvcnQgKiBhcyBsYW1iZGFOb2RlIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEtbm9kZWpzJztcbmltcG9ydCB7IE5vZGVqc0Z1bmN0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ub2RlanMnO1xuaW1wb3J0ICogYXMgczMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzJztcbmltcG9ydCAqIGFzIHMzbm90aWYgZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzLW5vdGlmaWNhdGlvbnMnO1xuaW1wb3J0ICogYXMgc25zIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zbnMnO1xuaW1wb3J0ICogYXMgc25zU3VicyBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc25zLXN1YnNjcmlwdGlvbnMnO1xuaW1wb3J0ICogYXMgc3FzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zcXMnO1xuaW1wb3J0IHsgQ29uc3RydWN0LCBJQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBlbnZWYXJpYWJsZU5hbWVzIH0gZnJvbSAnLi9jb21tb24vZW52VmFyaWFibGVOYW1lcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmVybGVzc1NweVByb3BzIHtcbiAgcmVhZG9ubHkgZ2VuZXJhdGVTcHlFdmVudHNGaWxlTG9jYXRpb24/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHNweVNxc1dpdGhOb1N1YnNjcmlwdGlvbkFuZERyb3BBbGxNZXNzYWdlcz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGRlYnVnTW9kZT86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3B5RmlsdGVyIHtcbiAgcmVhZG9ubHkgc3B5TGFtYmRhPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3B5U3FzPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3B5U25zVG9waWM/OiBib29sZWFuO1xuICByZWFkb25seSBzcHlTbnNTdWJzcmlwdGlvbj86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHNweUV2ZW50QnJpZGdlPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3B5RXZlbnRCcmlkZ2VSdWxlPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3B5UzM/OiBib29sZWFuO1xuICByZWFkb25seSBzcHlEeW5hbW9EQj86IGJvb2xlYW47XG59XG5cbmNvbnN0IGlzTGFtYmRhRnVuY3Rpb24gPSAobm9kZTogSUNvbnN0cnVjdCk6IG5vZGUgaXMgbGFtYmRhLkZ1bmN0aW9uID0+XG4gICdmdW5jdGlvbk5hbWUnIGluIG5vZGUgJiYgJ2Z1bmN0aW9uQXJuJyBpbiBub2RlICYmICdydW50aW1lJyBpbiBub2RlO1xuXG5jb25zdCBzZXJ2ZXJsZXNzU3B5SW90RW5kcG9pbnRDck5hbWVQcmVmaXggPSAnU2VydmVybGVzc1NweUlvdEVuZHBvaW50JztcblxuZXhwb3J0IGNsYXNzIFNlcnZlcmxlc3NTcHkgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBwcml2YXRlIGNyZWF0ZWRSZXNvdXJjZXNCeVNTcHk6IElDb25zdHJ1Y3RbXSA9IFtdO1xuICBwcml2YXRlIGxhbWJkYVN1YnNjcmlwdGlvblBvb2w6IExhbWJkYVN1YnNjcmlwdGlvbltdID0gW107XG4gIHByaXZhdGUgbGFtYmRhU3Vic2NyaXB0aW9uTWFpbjogTGFtYmRhU3Vic2NyaXB0aW9uO1xuICBwcml2YXRlIGxhbWJkYXNTcGllZDogTGFtYmRhU3BpZWRbXSA9IFtdO1xuICBwdWJsaWMgc2VydmljZUtleXM6IHN0cmluZ1tdID0gW107XG4gIHByaXZhdGUgc3BpZWROb2RlczogSUNvbnN0cnVjdFtdID0gW107XG4gIHByaXZhdGUgbGF5ZXJNYXA6IFBhcnRpYWw8UmVjb3JkPHN0cmluZywgSUxheWVyVmVyc2lvbj4+ID0ge307XG4gIHByaXZhdGUgcmVhZG9ubHkgaW90RW5kcG9pbnQ6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgcHJpdmF0ZSBwcm9wcz86IFNlcnZlcmxlc3NTcHlQcm9wc1xuICApIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3Qgcm9vdFN0YWNrID0gdGhpcy5jbGVhbk5hbWUoXG4gICAgICB0aGlzLmZpbmRSb290U3RhY2soU3RhY2sub2YodGhpcykpLm5vZGUuaWRcbiAgICApO1xuXG4gICAgY29uc3QgZ2V0SW9URW5kcG9pbnQgPSBuZXcgY3VzdG9tX3Jlc291cmNlcy5Bd3NDdXN0b21SZXNvdXJjZShcbiAgICAgIHRoaXMsXG4gICAgICBzZXJ2ZXJsZXNzU3B5SW90RW5kcG9pbnRDck5hbWVQcmVmaXgsXG4gICAgICB7XG4gICAgICAgIG9uQ3JlYXRlOiB7XG4gICAgICAgICAgc2VydmljZTogJ0lvdCcsXG4gICAgICAgICAgYWN0aW9uOiAnZGVzY3JpYmVFbmRwb2ludCcsXG4gICAgICAgICAgcGh5c2ljYWxSZXNvdXJjZUlkOlxuICAgICAgICAgICAgY3VzdG9tX3Jlc291cmNlcy5QaHlzaWNhbFJlc291cmNlSWQuZnJvbVJlc3BvbnNlKCdlbmRwb2ludEFkZHJlc3MnKSxcbiAgICAgICAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICAgICAgICBlbmRwb2ludFR5cGU6ICdpb3Q6RGF0YS1BVFMnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIG9uVXBkYXRlOiB7XG4gICAgICAgICAgc2VydmljZTogJ0lvdCcsXG4gICAgICAgICAgYWN0aW9uOiAnZGVzY3JpYmVFbmRwb2ludCcsXG4gICAgICAgICAgcGh5c2ljYWxSZXNvdXJjZUlkOlxuICAgICAgICAgICAgY3VzdG9tX3Jlc291cmNlcy5QaHlzaWNhbFJlc291cmNlSWQuZnJvbVJlc3BvbnNlKCdlbmRwb2ludEFkZHJlc3MnKSxcbiAgICAgICAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICAgICAgICBlbmRwb2ludFR5cGU6ICdpb3Q6RGF0YS1BVFMnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIGluc3RhbGxMYXRlc3RBd3NTZGs6IGZhbHNlLFxuICAgICAgICBwb2xpY3k6IGN1c3RvbV9yZXNvdXJjZXMuQXdzQ3VzdG9tUmVzb3VyY2VQb2xpY3kuZnJvbVNka0NhbGxzKHtcbiAgICAgICAgICByZXNvdXJjZXM6IGN1c3RvbV9yZXNvdXJjZXMuQXdzQ3VzdG9tUmVzb3VyY2VQb2xpY3kuQU5ZX1JFU09VUkNFLFxuICAgICAgICB9KSxcbiAgICAgICAgZnVuY3Rpb25OYW1lOiBzZXJ2ZXJsZXNzU3B5SW90RW5kcG9pbnRDck5hbWVQcmVmaXggKyByb290U3RhY2ssXG4gICAgICB9XG4gICAgKTtcbiAgICB0aGlzLmlvdEVuZHBvaW50ID0gZ2V0SW9URW5kcG9pbnQuZ2V0UmVzcG9uc2VGaWVsZCgnZW5kcG9pbnRBZGRyZXNzJyk7XG5cbiAgICB0aGlzLmNyZWF0ZWRSZXNvdXJjZXNCeVNTcHkucHVzaChnZXRJb1RFbmRwb2ludCk7XG5cbiAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsICdTZXJ2ZXJsZXNzU3B5SW9URW5kcG9pbnQnLCB7XG4gICAgICBrZXk6ICdTZXJ2ZXJsZXNzU3B5V3NVcmwnLFxuICAgICAgdmFsdWU6IGAke3RoaXMuaW90RW5kcG9pbnR9LyR7cm9vdFN0YWNrfWAsXG4gICAgfSk7XG5cbiAgICB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvbk1haW4gPSB0aGlzLnByb3ZpZGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbigpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREZWZhdWx0TGFtYmRhRW52aXJvbm1lbnRWYXJpYWJsZXMoKTogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIE5PREVfT1BUSU9OUzogJy0tZW5hYmxlLXNvdXJjZS1tYXBzJyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRhbGl6ZSBzcHlpbmcgb24gcmVzb3VyY2VzIGdpdmVuIGFzIHBhcmFtZXRlci5cbiAgICogQHBhcmFtIG5vZGVzIFdoaWNoIHJlb3VyY2VzIGFuZCB0aGVpciBjaGlsZHJlbiB0byBzcHkgb24uXG4gICAqL1xuICBwdWJsaWMgc3B5Tm9kZXMobm9kZXM6IElDb25zdHJ1Y3RbXSkge1xuICAgIGZvciAoY29uc3Qgbm9kZSBvZiBub2Rlcykge1xuICAgICAgbGV0IG5zID0gdGhpcy5nZXRBbGxOb2Rlcyhub2RlKTtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlOb2Rlcyhucyk7XG4gICAgfVxuXG4gICAgdGhpcy5maW5hbGl6ZVNweSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRhbGl6ZSBzcHlpbmcgb24gcmVzb3VyY2VzLlxuICAgKiBAcGFyYW0gZmlsdGVyIExpbWl0IHdoaWNoIHJlc291cmNlcyB0byBzcHkgb24uXG4gICAqL1xuICBwdWJsaWMgc3B5KGZpbHRlcj86IFNweUZpbHRlcikge1xuICAgIGxldCBub2RlcyA9IHRoaXMuZ2V0QWxsTm9kZXMoU3RhY2sub2YodGhpcykpO1xuXG4gICAgY29uc3QgZmlsdGVyV2l0aERlZmF1bHRzOiBSZXF1aXJlZDxTcHlGaWx0ZXI+ID0ge1xuICAgICAgc3B5TGFtYmRhOiB0cnVlLFxuICAgICAgc3B5U3FzOiB0cnVlLFxuICAgICAgc3B5U25zVG9waWM6IHRydWUsXG4gICAgICBzcHlTbnNTdWJzcmlwdGlvbjogdHJ1ZSxcbiAgICAgIHNweUV2ZW50QnJpZGdlOiB0cnVlLFxuICAgICAgc3B5RXZlbnRCcmlkZ2VSdWxlOiB0cnVlLFxuICAgICAgc3B5UzM6IHRydWUsXG4gICAgICBzcHlEeW5hbW9EQjogdHJ1ZSxcbiAgICAgIC4uLmZpbHRlcixcbiAgICB9O1xuXG4gICAgY29uc3QgQ1JJRCA9XG4gICAgICAnQVdTJyArXG4gICAgICBjdXN0b21fcmVzb3VyY2VzLkF3c0N1c3RvbVJlc291cmNlLlBST1ZJREVSX0ZVTkNUSU9OX1VVSUQucmVwbGFjZShcbiAgICAgICAgLy0vZ2ksXG4gICAgICAgICcnXG4gICAgICApLnN1YnN0cmluZygwLCAxNik7XG5cbiAgICBub2RlcyA9IG5vZGVzLmZpbHRlcigobm9kZSkgPT4ge1xuICAgICAgaWYgKFxuICAgICAgICAvLyBJZ25vcmUgdGhlIGN1c3RvbSByZXNvdXJjZSBhbmQgdGhlIFByb3ZpZGVyIChhcyB3ZWxsIGFzIGFueSBvdGhlciBQcm92aWRlcnMgdXNpbmcgdGhlIHNhbWUgcHJvdmlkZXIgZnVuY3Rpb24pLCBvdGhlcndpc2Ugd2UgY2F1c2VcbiAgICAgICAgLy8gY2lyY3VsYXIgZGVwZW5kZW5jaWVzXG4gICAgICAgIG5vZGUubm9kZS5pZC5zdGFydHNXaXRoKENSSUQpIHx8XG4gICAgICAgIG5vZGUubm9kZS5pZCA9PT0gJ1Byb3ZpZGVyJyB8fFxuICAgICAgICAvLyBJZ25vcmUgc2luZ2xldG9uIGZ1bmN0aW9ucyBhcyB0aGV5IGNhbiBjYXVzZSB2ZXJ5IG9kZCBiZWhhdmlvciBhbmQgY3Jhc2hlc1xuICAgICAgICBub2RlIGluc3RhbmNlb2YgU2luZ2xldG9uRnVuY3Rpb25cbiAgICAgICkge1xuICAgICAgICBpZiAodGhpcy5wcm9wcz8uZGVidWdNb2RlKSB7XG4gICAgICAgICAgY29uc29sZS5pbmZvKGBTa2lwcGluZyAke25vZGUubm9kZS5pZH1gKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5TGFtYmRhICYmXG4gICAgICAgIChub2RlIGluc3RhbmNlb2YgbGFtYmRhLkZ1bmN0aW9uIHx8XG4gICAgICAgICAgbm9kZSBpbnN0YW5jZW9mIE5vZGVqc0Z1bmN0aW9uIHx8XG4gICAgICAgICAgaXNMYW1iZGFGdW5jdGlvbihub2RlKSlcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoZmlsdGVyV2l0aERlZmF1bHRzLnNweVNuc1RvcGljICYmIG5vZGUgaW5zdGFuY2VvZiBzbnMuVG9waWMpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5U25zU3Vic3JpcHRpb24gJiZcbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIHNucy5TdWJzY3JpcHRpb25cbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoZmlsdGVyV2l0aERlZmF1bHRzLnNweVMzICYmIG5vZGUgaW5zdGFuY2VvZiBzMy5CdWNrZXQpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5RHluYW1vREIgJiZcbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIGR5bmFtb0RiLlRhYmxlXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5RHluYW1vREIgJiZcbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIGR5bmFtb0RiLlRhYmxlVjJcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGZpbHRlcldpdGhEZWZhdWx0cy5zcHlFdmVudEJyaWRnZSAmJlxuICAgICAgICBub2RlIGluc3RhbmNlb2YgZXZlbnRzLkV2ZW50QnVzXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5RXZlbnRCcmlkZ2VSdWxlICYmXG4gICAgICAgIG5vZGUgaW5zdGFuY2VvZiBldmVudHMuUnVsZVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZmlsdGVyV2l0aERlZmF1bHRzLnNweVNxcyAmJlxuICAgICAgICBub2RlIGluc3RhbmNlb2YgbGFtYmRhLkNmbkV2ZW50U291cmNlTWFwcGluZ1xuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZmlsdGVyV2l0aERlZmF1bHRzLnNweVNxcyAmJlxuICAgICAgICB0aGlzLnByb3BzPy5zcHlTcXNXaXRoTm9TdWJzY3JpcHRpb25BbmREcm9wQWxsTWVzc2FnZXMgJiZcbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIHNxcy5RdWV1ZVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSk7XG5cbiAgICB0aGlzLmludGVybmFsU3B5Tm9kZXMobm9kZXMpO1xuICAgIHRoaXMuZmluYWxpemVTcHkoKTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlOb2Rlcyhub2RlczogSUNvbnN0cnVjdFtdKSB7XG4gICAgZm9yIChjb25zdCBub2RlIG9mIG5vZGVzKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5Tm9kZShub2RlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGZpbmFsaXplU3B5KCkge1xuICAgIC8vc2V0IG1hcHBpbmcgcHJvcGVydHkgZm9yIGFsbCBmdW5jdGlvbnMgd2UgY3JlYXRlZFxuICAgIGZvciAoY29uc3QgZnVuYyBvZiB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2wpIHtcbiAgICAgIGZ1bmMuZnVuY3Rpb24uYWRkRW52aXJvbm1lbnQoXG4gICAgICAgIGVudlZhcmlhYmxlTmFtZXMuU1NQWV9JTkZSQV9NQVBQSU5HLFxuICAgICAgICBKU09OLnN0cmluZ2lmeShmdW5jLm1hcHBpbmcpXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vc2V0IG1hcHBpbmcgcHJvcGVydHkgZm9yIGFsbCBmdW5jdGlvbnMgd2Ugc3B5IG9uXG4gICAgZm9yIChjb25zdCBmdW5jIG9mIHRoaXMubGFtYmRhc1NwaWVkKSB7XG4gICAgICBmdW5jLmZ1bmN0aW9uLmFkZEVudmlyb25tZW50KFxuICAgICAgICBlbnZWYXJpYWJsZU5hbWVzLlNTUFlfSU5GUkFfTUFQUElORyxcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoZnVuYy5tYXBwaW5nKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wcm9wcz8uZ2VuZXJhdGVTcHlFdmVudHNGaWxlTG9jYXRpb24pIHtcbiAgICAgIHRoaXMud3JpdGVTcHlFdmVudHNDbGFzcyh0aGlzLnByb3BzPy5nZW5lcmF0ZVNweUV2ZW50c0ZpbGVMb2NhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRFeHRlbnNpb25Bc3NldExvY2F0aW9uKCkge1xuICAgIGxldCBleHRlbnNpb25Bc3NldExvY2F0aW9uID0gcGF0aC5qb2luKFxuICAgICAgX19kaXJuYW1lLFxuICAgICAgJy4uL2V4dGVuc2lvbi9kaXN0L2xheWVyJ1xuICAgICk7XG5cbiAgICBjb25zdCBleHRlbnNpb25Bc3NldExvY2F0aW9uQWx0ID0gcGF0aC5qb2luKFxuICAgICAgX19kaXJuYW1lLFxuICAgICAgJy4uL2xpYi9leHRlbnNpb24vZGlzdC9sYXllcidcbiAgICApO1xuXG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKGV4dGVuc2lvbkFzc2V0TG9jYXRpb24pKSB7XG4gICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkFsdCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBGb2xkZXIgd2l0aCBhc3NldHMgZm9yIGV4dGVuc2lvbiBkb2VzIG5vdCBleGlzdHMgYXQgJHtleHRlbnNpb25Bc3NldExvY2F0aW9ufSBvciBhdCAke2V4dGVuc2lvbkFzc2V0TG9jYXRpb25BbHR9IGBcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGV4dGVuc2lvbkFzc2V0TG9jYXRpb24gPSBleHRlbnNpb25Bc3NldExvY2F0aW9uQWx0O1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGV4dGVuc2lvbkFzc2V0TG9jYXRpb25XcmFwcGVyID0gcGF0aC5qb2luKFxuICAgICAgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbixcbiAgICAgICdzcHktd3JhcHBlcidcbiAgICApO1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhleHRlbnNpb25Bc3NldExvY2F0aW9uV3JhcHBlcikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFdyYXBwZXIgc2NyaXB0IGZvciBleHRlbnNpb24gZG9lcyBub3QgZXhpc3RzICR7ZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbn1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGV4dGVuc2lvbkFzc2V0TG9jYXRpb25Db2RlID0gcGF0aC5qb2luKFxuICAgICAgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbixcbiAgICAgIGBub2RlanMvbm9kZV9tb2R1bGVzL2ludGVyY2VwdG9yLmpzYFxuICAgICk7XG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKGV4dGVuc2lvbkFzc2V0TG9jYXRpb25Db2RlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ29kZSBmb3IgZXh0ZW5zaW9uIGRvZXMgbm90IGV4aXN0cyAke2V4dGVuc2lvbkFzc2V0TG9jYXRpb25Db2RlfWBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBleHRlbnNpb25Bc3NldExvY2F0aW9uO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRMYW5ndWFnZUV4dGVuc2lvbkFzc2V0TG9jYXRpb24obGFuZ3VhZ2U6IHN0cmluZykge1xuICAgIGNvbnN0IHJvb3REaXIgPSBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4nKTtcblxuICAgIGxldCBleHRlbnNpb25Bc3NldExvY2F0aW9uID0gcGF0aC5qb2luKHJvb3REaXIsIGBleHRlbnNpb25zLyR7bGFuZ3VhZ2V9YCk7XG5cbiAgICBjb25zdCBleHRlbnNpb25Bc3NldExvY2F0aW9uQWx0ID0gcGF0aC5qb2luKFxuICAgICAgcm9vdERpcixcbiAgICAgIGBsaWIvZXh0ZW5zaW9ucy8ke2xhbmd1YWdlfWBcbiAgICApO1xuXG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKGV4dGVuc2lvbkFzc2V0TG9jYXRpb24pKSB7XG4gICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkFsdCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBGb2xkZXIgd2l0aCBhc3NldHMgZm9yIGV4dGVuc2lvbiBmb3IgJHtsYW5ndWFnZX0gZG9lcyBub3QgZXhpc3RzIGF0ICR7ZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbn0gb3IgYXQgJHtleHRlbnNpb25Bc3NldExvY2F0aW9uQWx0fSBgXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBleHRlbnNpb25Bc3NldExvY2F0aW9uID0gZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkFsdDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBleHRlbnNpb25Bc3NldExvY2F0aW9uV3JhcHBlciA9IHBhdGguam9pbihcbiAgICAgIC8vIGV4dGVuc2lvbkFzc2V0TG9jYXRpb24uc3Vic3RyaW5nKFxuICAgICAgLy8gICAwLFxuICAgICAgLy8gICBleHRlbnNpb25Bc3NldExvY2F0aW9uLmxhc3RJbmRleE9mKHBhdGguc2VwKVxuICAgICAgLy8gKSxcbiAgICAgIGV4dGVuc2lvbkFzc2V0TG9jYXRpb24sXG4gICAgICAnc3B5LXdyYXBwZXInXG4gICAgKTtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbldyYXBwZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBXcmFwcGVyIHNjcmlwdCBmb3IgZXh0ZW5zaW9uIGRvZXMgbm90IGV4aXN0cyBhdCAke2V4dGVuc2lvbkFzc2V0TG9jYXRpb25XcmFwcGVyfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGV4dGVuc2lvbkFzc2V0TG9jYXRpb247XG4gIH1cblxuICAvKipcbiAgICogV3JpdGUgU3B5RXZlbnRzIGNsYXNzLCB3aGljaCBoZWxwcyB3aXRoIHdyaXRpbmcgdGhlIGNvZGUgZm9yIHRlc3RzLlxuICAgKiBAcGFyYW0gZmlsZUxvY2F0aW9uXG4gICAqL1xuICBwcml2YXRlIHdyaXRlU3B5RXZlbnRzQ2xhc3MoZmlsZUxvY2F0aW9uOiBzdHJpbmcpIHtcbiAgICBmcy5ta2RpclN5bmMocGF0aC5kaXJuYW1lKGZpbGVMb2NhdGlvbiksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gICAgY29uc3QgcHJvcGVydGllcyA9IHRoaXMuc2VydmljZUtleXNcbiAgICAgIC5tYXAoKHNrKSA9PiBgICAke3NrLnJlcGxhY2UoLyMvZywgJycpfTogJyR7c2t9JyA9ICcke3NrfSc7XFxuYClcbiAgICAgIC5qb2luKCcnKTtcblxuICAgIGNvbnN0IGNvZGUgPSBgLyogZXNsaW50LWRpc2FibGUgKi9cXG5leHBvcnQgY2xhc3MgU2VydmVybGVzc1NweUV2ZW50cyB7XFxuJHtwcm9wZXJ0aWVzfX1cXG5gO1xuXG4gICAgZnMud3JpdGVGaWxlU3luYyhmaWxlTG9jYXRpb24sIGNvZGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRBbGxOb2RlcyhwYXJlbnQ6IElDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBub2RlczogSUNvbnN0cnVjdFtdID0gW107XG4gICAgbm9kZXMucHVzaChwYXJlbnQpO1xuICAgIHRoaXMuZ2V0QWxsTm9kZXNSZWN1cnNpdmUocGFyZW50LCBub2Rlcyk7XG4gICAgcmV0dXJuIG5vZGVzO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRBbGxOb2Rlc1JlY3Vyc2l2ZShwYXJlbnQ6IElDb25zdHJ1Y3QsIG5vZGVzOiBJQ29uc3RydWN0W10pIHtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgcGFyZW50Lm5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIG5vZGVzLnB1c2gobm9kZSk7XG4gICAgICB0aGlzLmdldEFsbE5vZGVzUmVjdXJzaXZlKG5vZGUsIG5vZGVzKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5Tm9kZShub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgaWYgKHRoaXMuc3BpZWROb2Rlcy5pbmNsdWRlcyhub2RlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc3BpZWROb2Rlcy5wdXNoKG5vZGUpO1xuXG4gICAgaWYgKHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5pbmNsdWRlcyhub2RlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2wuZmluZCgocykgPT4gcy5mdW5jdGlvbiA9PT0gbm9kZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wcm9wcz8uZGVidWdNb2RlKSB7XG4gICAgICBjb25zb2xlLmluZm8oJ1NweSBvbiBub2RlJywgdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKG5vZGUpKTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBub2RlIGluc3RhbmNlb2YgbGFtYmRhLkZ1bmN0aW9uIHx8XG4gICAgICBub2RlIGluc3RhbmNlb2YgTm9kZWpzRnVuY3Rpb24gfHxcbiAgICAgIGlzTGFtYmRhRnVuY3Rpb24obm9kZSlcbiAgICApIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlMYW1iZGEobm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2Ygc25zLlRvcGljKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5U25zVG9waWMobm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2Ygc25zLlN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweVNuc1N1YnNjcmlwdGlvbihub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBzMy5CdWNrZXQpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlTMyhub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBkeW5hbW9EYi5UYWJsZSkge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweUR5bmFtb2RiKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIGR5bmFtb0RiLlRhYmxlVjIpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlEeW5hbW9kYihub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBldmVudHMuRXZlbnRCdXMpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlFdmVudEJ1cyhub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBldmVudHMuUnVsZSkge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweUV2ZW50QnVzUnVsZShub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBsYW1iZGEuQ2ZuRXZlbnRTb3VyY2VNYXBwaW5nKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5U3FzKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHNxcy5RdWV1ZSkge1xuICAgICAgaWYgKHRoaXMucHJvcHM/LnNweVNxc1dpdGhOb1N1YnNjcmlwdGlvbkFuZERyb3BBbGxNZXNzYWdlcykge1xuICAgICAgICB0aGlzLmludGVybmFsU3B5U3B5U3FzV2l0aE5vU3Vic2NyaXB0aW9uKG5vZGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0RXh0ZW5zaW9uRm9yUnVudGltZShcbiAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZSxcbiAgICBhcmNoaXRlY3R1cmU6IGxhbWJkYS5BcmNoaXRlY3R1cmVcbiAgKTogeyBsYXllcjogbGFtYmRhLklMYXllclZlcnNpb247IHNweVdyYXBwZXJQYXRoOiBzdHJpbmcgfSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgbGF5ZXJLZXkgPVxuICAgICAgYHNzcHlfZXh0ZW5zaW9uXyR7cnVudGltZS50b1N0cmluZygpfV8ke2FyY2hpdGVjdHVyZS5uYW1lLnRvU3RyaW5nKCl9YC5yZXBsYWNlKFxuICAgICAgICAvXFwuL2csXG4gICAgICAgICdfJ1xuICAgICAgKTtcblxuICAgIGxldCBsYXllciA9IHRoaXMubGF5ZXJNYXBbbGF5ZXJLZXldO1xuICAgIGxldCBzcHlXcmFwcGVyUGF0aCA9ICcvb3B0L3NweS13cmFwcGVyJztcblxuICAgIHN3aXRjaCAocnVudGltZS5uYW1lKSB7XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLlBZVEhPTl8zXzgubmFtZTpcbiAgICAgIGNhc2UgbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfOS5uYW1lOlxuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5QWVRIT05fM18xMC5uYW1lOlxuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5QWVRIT05fM18xMS5uYW1lOlxuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5QWVRIT05fM18xMi5uYW1lOlxuICAgICAgICBzcHlXcmFwcGVyUGF0aCA9ICcvb3B0L3B5dGhvbi9zcHktd3JhcHBlcic7XG4gICAgICAgIGxheWVyID1cbiAgICAgICAgICBsYXllciB8fFxuICAgICAgICAgIG5ldyBQeXRob25MYXllclZlcnNpb24odGhpcywgbGF5ZXJLZXksIHtcbiAgICAgICAgICAgIGNvbXBhdGlibGVSdW50aW1lczogW3J1bnRpbWVdLFxuICAgICAgICAgICAgY29tcGF0aWJsZUFyY2hpdGVjdHVyZXM6IFthcmNoaXRlY3R1cmVdLFxuICAgICAgICAgICAgZW50cnk6IHRoaXMuZ2V0TGFuZ3VhZ2VFeHRlbnNpb25Bc3NldExvY2F0aW9uKCdweXRob24nKSxcbiAgICAgICAgICAgIGJ1bmRsaW5nOiB7XG4gICAgICAgICAgICAgIGJ1bmRsaW5nRmlsZUFjY2VzczogQnVuZGxpbmdGaWxlQWNjZXNzLlZPTFVNRV9DT1BZLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLk5PREVKU18xMl9YLm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLk5PREVKU18xNF9YLm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLk5PREVKU18xNl9YLm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLk5PREVKU18xOF9YLm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLk5PREVKU18yMF9YLm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLk5PREVKU18yMl9YLm5hbWU6XG4gICAgICAgIGxheWVyID1cbiAgICAgICAgICBsYXllciB8fFxuICAgICAgICAgIG5ldyBsYW1iZGEuTGF5ZXJWZXJzaW9uKHRoaXMsIGxheWVyS2V5LCB7XG4gICAgICAgICAgICBjb21wYXRpYmxlUnVudGltZXM6IFtydW50aW1lXSxcbiAgICAgICAgICAgIGNvbXBhdGlibGVBcmNoaXRlY3R1cmVzOiBbYXJjaGl0ZWN0dXJlXSxcbiAgICAgICAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldCh0aGlzLmdldEV4dGVuc2lvbkFzc2V0TG9jYXRpb24oKSksXG4gICAgICAgICAgfSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS5sb2coYE5vIGV4dGVuc2lvbnMgYXZhaWxhYmxlIGZvciAke3J1bnRpbWUudG9TdHJpbmcoKX1gKTtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICB0aGlzLmxheWVyTWFwW2xheWVyS2V5XSA9IGxheWVyO1xuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKGxheWVyKTtcbiAgICByZXR1cm4geyBsYXllciwgc3B5V3JhcHBlclBhdGggfTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlTcHlTcXNXaXRoTm9TdWJzY3JpcHRpb24ocXVldWU6IHNxcy5RdWV1ZSkge1xuICAgIGNvbnN0IHN1YnNjcmlwdGlvbiA9IHRoaXMuZmluZEVsZW1lbnQ8bGFtYmRhLkNmbkV2ZW50U291cmNlTWFwcGluZz4oXG4gICAgICAobjogSUNvbnN0cnVjdCkgPT5cbiAgICAgICAgbiBpbnN0YW5jZW9mIGxhbWJkYS5DZm5FdmVudFNvdXJjZU1hcHBpbmcgJiZcbiAgICAgICAgKG4gYXMgbGFtYmRhLkNmbkV2ZW50U291cmNlTWFwcGluZykuZXZlbnRTb3VyY2VBcm4gPT09IHF1ZXVlLnF1ZXVlQXJuXG4gICAgKTtcblxuICAgIGlmIChzdWJzY3JpcHRpb24pIHtcbiAgICAgIHJldHVybjsgLy9hbHJlYWR5IGhhdmUgc3Vic2NyaXB0aW9uXG4gICAgfVxuXG4gICAgY29uc3QgcXVldWVOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHF1ZXVlKTtcbiAgICBjb25zdCBmdW5jID0gbmV3IE5vZGVqc0Z1bmN0aW9uKFxuICAgICAgdGhpcyxcbiAgICAgIGAke3F1ZXVlTmFtZX1TcXNTdWJzY3JpcHRpb25BbmREcm9wQWxsTWVzc2FnZXNgLFxuICAgICAge1xuICAgICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICAgIHRpbWVvdXQ6IER1cmF0aW9uLnNlY29uZHMoNSksXG4gICAgICAgIHJ1bnRpbWU6IGxhbWJkYS5SdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICBoYW5kbGVyOiAnaGFuZGxlcicsXG4gICAgICAgIGVudHJ5OiB0aGlzLmdldEFzc2V0TG9jYXRpb24oXG4gICAgICAgICAgJ2Z1bmN0aW9ucy9zcXNTdWJzY3JpcHRpb25BbmREcm9wQWxsTWVzc2FnZXMuanMnXG4gICAgICAgICksXG4gICAgICAgIGVudmlyb25tZW50OiB0aGlzLmdldERlZmF1bHRMYW1iZGFFbnZpcm9ubWVudFZhcmlhYmxlcygpLFxuICAgICAgfVxuICAgICk7XG4gICAgZnVuYy5hZGRFdmVudFNvdXJjZShuZXcgU3FzRXZlbnRTb3VyY2UocXVldWUpKTtcbiAgICB0aGlzLnNldHVwRm9ySW9UKGZ1bmMpO1xuICAgIGNvbnN0IHsgbGF5ZXIsIHNweVdyYXBwZXJQYXRoIH0gPSB0aGlzLmdldEV4dGVuc2lvbkZvclJ1bnRpbWUoXG4gICAgICBmdW5jLnJ1bnRpbWUsXG4gICAgICBmdW5jLmFyY2hpdGVjdHVyZVxuICAgICkhO1xuICAgIGZ1bmMuYWRkTGF5ZXJzKGxheWVyKTtcblxuICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoJ0FXU19MQU1CREFfRVhFQ19XUkFQUEVSJywgc3B5V3JhcHBlclBhdGgpO1xuXG4gICAgaWYgKHRoaXMucHJvcHM/LmRlYnVnTW9kZSkge1xuICAgICAgZnVuYy5hZGRFbnZpcm9ubWVudChlbnZWYXJpYWJsZU5hbWVzLlNTUFlfREVCVUcsICd0cnVlJyk7XG4gICAgfVxuXG4gICAgdGhpcy5jcmVhdGVkUmVzb3VyY2VzQnlTU3B5LnB1c2goZnVuYyk7XG5cbiAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYFNxcyMke3F1ZXVlTmFtZX1gO1xuXG4gICAgdGhpcy5hZGRNYXBwaW5nVG9GdW5jdGlvbihmdW5jLCB7XG4gICAgICBrZXk6IHF1ZXVlLnF1ZXVlQXJuLFxuICAgICAgdmFsdWU6IHNlcnZpY2VLZXksXG4gICAgfSk7XG5cbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goc2VydmljZUtleSk7XG4gICAgZnVuYy5hZGRFbnZpcm9ubWVudChlbnZWYXJpYWJsZU5hbWVzLlNTUFlfU1VCU0NSSUJFRF9UT19TUVMsICd0cnVlJyk7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5U3FzKG5vZGU6IGxhbWJkYS5DZm5FdmVudFNvdXJjZU1hcHBpbmcpIHtcbiAgICBjb25zdCBxdWV1ZSA9IHRoaXMuZmluZEVsZW1lbnQ8c3FzLlF1ZXVlPihcbiAgICAgIChuOiBJQ29uc3RydWN0KSA9PlxuICAgICAgICBuIGluc3RhbmNlb2Ygc3FzLlF1ZXVlICYmXG4gICAgICAgIChuIGFzIHNxcy5RdWV1ZSkucXVldWVBcm4gPT09IG5vZGUuZXZlbnRTb3VyY2VBcm5cbiAgICApO1xuXG4gICAgY29uc3QgZnVuYyA9IHRoaXMuZmluZEVsZW1lbnQ8bGFtYmRhLkZ1bmN0aW9uPihcbiAgICAgIChuOiBJQ29uc3RydWN0KSA9PlxuICAgICAgICBuIGluc3RhbmNlb2YgbGFtYmRhLkZ1bmN0aW9uICYmXG4gICAgICAgIChuIGFzIGxhbWJkYS5GdW5jdGlvbikuZnVuY3Rpb25OYW1lID09PSBub2RlLmZ1bmN0aW9uTmFtZVxuICAgICk7XG5cbiAgICBpZiAocXVldWUgJiYgZnVuYykge1xuICAgICAgY29uc3QgcXVldWVOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHF1ZXVlKTtcblxuICAgICAgY29uc3Qgc2VydmljZUtleSA9IGBTcXMjJHtxdWV1ZU5hbWV9YDtcblxuICAgICAgdGhpcy5hZGRNYXBwaW5nVG9GdW5jdGlvbihmdW5jLCB7XG4gICAgICAgIGtleTogcXVldWUucXVldWVBcm4sXG4gICAgICAgIHZhbHVlOiBzZXJ2aWNlS2V5LFxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoZW52VmFyaWFibGVOYW1lcy5TU1BZX1NVQlNDUklCRURfVE9fU1FTLCAndHJ1ZScpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlRnVuY3Rpb25Gb3JTdWJzY3JpcHRpb24oaW5kZXg6IG51bWJlcikge1xuICAgIGNvbnN0IGZ1bmMgPSBuZXcgbGFtYmRhTm9kZS5Ob2RlanNGdW5jdGlvbih0aGlzLCBgU3Vic2NyaXB0aW9uJHtpbmRleH1gLCB7XG4gICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICB0aW1lb3V0OiBEdXJhdGlvbi5zZWNvbmRzKDUpLFxuICAgICAgcnVudGltZTogbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICBoYW5kbGVyOiAnaGFuZGxlcicsXG4gICAgICBlbnRyeTogdGhpcy5nZXRBc3NldExvY2F0aW9uKCdmdW5jdGlvbnMvc2VuZE1lc3NhZ2UuanMnKSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIE5PREVfT1BUSU9OUzogJy0tZW5hYmxlLXNvdXJjZS1tYXBzJyxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgdGhpcy5zZXR1cEZvcklvVChmdW5jKTtcbiAgICByZXR1cm4gZnVuYztcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlTMyhzM0J1Y2tldDogczMuQnVja2V0KSB7XG4gICAgczNCdWNrZXQuYWRkRXZlbnROb3RpZmljYXRpb24oXG4gICAgICBzMy5FdmVudFR5cGUuT0JKRUNUX0NSRUFURURfUFVULFxuICAgICAgbmV3IHMzbm90aWYuTGFtYmRhRGVzdGluYXRpb24odGhpcy5sYW1iZGFTdWJzY3JpcHRpb25NYWluLmZ1bmN0aW9uKVxuICAgICk7XG5cbiAgICBjb25zdCBuYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHMzQnVja2V0KTtcblxuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgUzMjJHtuYW1lfWA7XG4gICAgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25NYWluLm1hcHBpbmdbczNCdWNrZXQuYnVja2V0QXJuXSA9IHNlcnZpY2VLZXk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweUR5bmFtb2RiKHRhYmxlOiBkeW5hbW9EYi5UYWJsZSB8IGR5bmFtb0RiLlRhYmxlVjIpIHtcbiAgICAvLyBlbmFibGUgRHluYW1vREIgc3RyZWFtcyB3aXRoIGEgaGFja1xuICAgICh0YWJsZS5ub2RlLmRlZmF1bHRDaGlsZCBhcyBkeW5hbW9EYi5DZm5UYWJsZSkuc3RyZWFtU3BlY2lmaWNhdGlvbiA9IHtcbiAgICAgIHN0cmVhbVZpZXdUeXBlOiBkeW5hbW9EYi5TdHJlYW1WaWV3VHlwZS5ORVdfQU5EX09MRF9JTUFHRVMsXG4gICAgfTtcbiAgICB0cnkge1xuICAgICAgKHRhYmxlIGFzIGFueSkudGFibGVTdHJlYW1Bcm4gPSAoXG4gICAgICAgIHRhYmxlLm5vZGUuZGVmYXVsdENoaWxkIGFzIGR5bmFtb0RiLkNmblRhYmxlXG4gICAgICApLmF0dHJTdHJlYW1Bcm47XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgLy8gUHJvcGVydHkgaXMgcmVhZC1vbmx5IGluIG5ld2VyIENESyB2ZXJzaW9ucywgc2tpcCB0aGUgYXNzaWdubWVudFxuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFR5cGVFcnJvciAmJiBlLm1lc3NhZ2UuaW5jbHVkZXMoJ29ubHkgYSBnZXR0ZXInKSkpIHtcbiAgICAgICAgdGhyb3cgZTsgLy8gUmUtdGhyb3cgaWYgaXQncyBhIGRpZmZlcmVudCBlcnJvclxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uTWFpbi5mdW5jdGlvbi5hZGRFdmVudFNvdXJjZShcbiAgICAgIG5ldyBkeW5hbW9EYlN0cmVhbS5EeW5hbW9FdmVudFNvdXJjZSh0YWJsZSwge1xuICAgICAgICBzdGFydGluZ1Bvc2l0aW9uOiBsYW1iZGEuU3RhcnRpbmdQb3NpdGlvbi5MQVRFU1QsXG4gICAgICAgIGJhdGNoU2l6ZTogMSxcbiAgICAgICAgcmV0cnlBdHRlbXB0czogMCxcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIGNvbnN0IG5hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUodGFibGUpO1xuXG4gICAgY29uc3Qgc2VydmljZUtleSA9IGBEeW5hbW9EQiMke25hbWV9YDtcbiAgICB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvbk1haW4ubWFwcGluZ1t0YWJsZS50YWJsZUFybl0gPSBzZXJ2aWNlS2V5O1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlFdmVudEJ1c1J1bGUocnVsZTogZXZlbnRzLlJ1bGUpIHtcbiAgICBjb25zdCB7IGV2ZW50QnVzTmFtZSB9ID0gcnVsZS5ub2RlLmRlZmF1bHRDaGlsZCBhcyBldmVudHMuQ2ZuUnVsZTtcbiAgICBsZXQgYnJpZGdlTmFtZSA9ICdEZWZhdWx0JztcbiAgICBpZiAoISFldmVudEJ1c05hbWUpIHtcbiAgICAgIGNvbnN0IGV2ZW50QnJpZGdlID0gdGhpcy5nZXRFdmVudEJyaWRnZShldmVudEJ1c05hbWUpO1xuXG4gICAgICBpZiAoIWV2ZW50QnJpZGdlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuIG5vdCBmaW5kIEV2ZW50QnJpZGdlIHdpdGggbmFtZSBcIiR7ZXZlbnRCdXNOYW1lfVwiYCk7XG4gICAgICB9XG4gICAgICBicmlkZ2VOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKGV2ZW50QnJpZGdlKTtcbiAgICB9XG5cbiAgICBjb25zdCBmdW5jdGlvblN1YnNjcmlwdGlvbiA9IHRoaXMucHJvdmlkZUZ1bmN0aW9uRm9yU3Vic2NyaXB0aW9uKFxuICAgICAgKHMpID0+ICFzLnVzZWRGb3JFdmVudEJyaWRnZVxuICAgICk7XG4gICAgZnVuY3Rpb25TdWJzY3JpcHRpb24udXNlZEZvckV2ZW50QnJpZGdlID0gdHJ1ZTtcblxuICAgIHJ1bGUuYWRkVGFyZ2V0KG5ldyB0YXJnZXRzLkxhbWJkYUZ1bmN0aW9uKGZ1bmN0aW9uU3Vic2NyaXB0aW9uLmZ1bmN0aW9uKSk7XG5cbiAgICBjb25zdCBydWxlTmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZShydWxlKTtcbiAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYEV2ZW50QnJpZGdlUnVsZSMke2JyaWRnZU5hbWV9IyR7cnVsZU5hbWV9YDtcbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi5tYXBwaW5nLmV2ZW50QnJpZGdlID0gc2VydmljZUtleTtcbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goc2VydmljZUtleSk7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5RXZlbnRCdXMoZXZlbnRCdXM6IGV2ZW50cy5FdmVudEJ1cykge1xuICAgIGNvbnN0IGZ1bmN0aW9uU3Vic2NyaXB0aW9uID0gdGhpcy5wcm92aWRlRnVuY3Rpb25Gb3JTdWJzY3JpcHRpb24oXG4gICAgICAocykgPT4gIXMudXNlZEZvckV2ZW50QnJpZGdlXG4gICAgKTtcbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi51c2VkRm9yRXZlbnRCcmlkZ2UgPSB0cnVlO1xuXG4gICAgY29uc3QgYnJpZGdlTmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZShldmVudEJ1cyk7XG4gICAgY29uc3QgcnVsZSA9IG5ldyBldmVudHMuUnVsZSh0aGlzLCBgUnVsZUFsbCR7YnJpZGdlTmFtZX1gLCB7XG4gICAgICBldmVudEJ1cyxcbiAgICAgIGV2ZW50UGF0dGVybjogeyB2ZXJzaW9uOiBbJzAnXSB9LFxuICAgICAgdGFyZ2V0czogW25ldyB0YXJnZXRzLkxhbWJkYUZ1bmN0aW9uKGZ1bmN0aW9uU3Vic2NyaXB0aW9uLmZ1bmN0aW9uKV0sXG4gICAgfSk7XG5cbiAgICB0aGlzLmNyZWF0ZWRSZXNvdXJjZXNCeVNTcHkucHVzaChydWxlKTtcbiAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYEV2ZW50QnJpZGdlIyR7YnJpZGdlTmFtZX1gO1xuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLm1hcHBpbmcuZXZlbnRCcmlkZ2UgPSBzZXJ2aWNlS2V5O1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlTbnNUb3BpYyh0b3BpYzogc25zLlRvcGljKSB7XG4gICAgY29uc3QgZnVuY3Rpb25TdWJzY3JpcHRpb24gPSB0aGlzLnByb3ZpZGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbihcbiAgICAgIChzKSA9PiAhcy5zdWJzcmliZWRUb3BpY3MuaW5jbHVkZXModG9waWMpXG4gICAgKTtcblxuICAgIGNvbnN0IHN1YnNjcmlwdGlvbiA9IHRvcGljLmFkZFN1YnNjcmlwdGlvbihcbiAgICAgIG5ldyBzbnNTdWJzLkxhbWJkYVN1YnNjcmlwdGlvbihmdW5jdGlvblN1YnNjcmlwdGlvbi5mdW5jdGlvbilcbiAgICApO1xuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKHN1YnNjcmlwdGlvbik7XG4gICAgY29uc3QgdG9waWNOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHRvcGljKTtcbiAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYFNuc1RvcGljIyR7dG9waWNOYW1lfWA7XG4gICAgZnVuY3Rpb25TdWJzY3JpcHRpb24ubWFwcGluZ1t0b3BpYy50b3BpY0Fybl0gPSBzZXJ2aWNlS2V5O1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi5zdWJzcmliZWRUb3BpY3MucHVzaCh0b3BpYyk7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5U25zU3Vic2NyaXB0aW9uKHN1YnNjcmlwdGlvbjogc25zLlN1YnNjcmlwdGlvbikge1xuICAgIGlmICghc3Vic2NyaXB0aW9uLm5vZGUuc2NvcGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB0b3BpYyA9IHRoaXMuZ2V0VG9waWMoXG4gICAgICAoc3Vic2NyaXB0aW9uLm5vZGUuZGVmYXVsdENoaWxkIGFzIHNucy5DZm5TdWJzY3JpcHRpb24pLnRvcGljQXJuXG4gICAgKTtcblxuICAgIGlmICghdG9waWMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBmaW5kIFRvcGljJyk7XG4gICAgfVxuXG4gICAgY29uc3QgZnVuY3Rpb25TdWJzY3JpcHRpb24gPSB0aGlzLnByb3ZpZGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbihcbiAgICAgIChzKSA9PiAhcy5zdWJzcmliZWRUb3BpY3MuaW5jbHVkZXModG9waWMpXG4gICAgKTtcblxuICAgIGNvbnN0IHsgZmlsdGVyUG9saWN5IH0gPSBzdWJzY3JpcHRpb24ubm9kZVxuICAgICAgLmRlZmF1bHRDaGlsZCBhcyBzbnMuQ2ZuU3Vic2NyaXB0aW9uO1xuXG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uQ2xvbmUgPSB0b3BpYy5hZGRTdWJzY3JpcHRpb24oXG4gICAgICBuZXcgc25zU3Vicy5MYW1iZGFTdWJzY3JpcHRpb24oZnVuY3Rpb25TdWJzY3JpcHRpb24uZnVuY3Rpb24pXG4gICAgKTtcbiAgICAoc3Vic2NyaXB0aW9uQ2xvbmUubm9kZS5kZWZhdWx0Q2hpbGQgYXMgc25zLkNmblN1YnNjcmlwdGlvbikuZmlsdGVyUG9saWN5ID1cbiAgICAgIGZpbHRlclBvbGljeTtcblxuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKHN1YnNjcmlwdGlvbkNsb25lKTtcblxuICAgIGNvbnN0IHRvcGljTmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZSh0b3BpYyk7XG4gICAgY29uc3QgdGFyZ2V0TmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZShzdWJzY3JpcHRpb24ubm9kZS5zY29wZSk7XG5cbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi5zdWJzcmliZWRUb3BpY3MucHVzaCh0b3BpYyk7XG4gICAgY29uc3Qgc2VydmljZUtleSA9IGBTbnNTdWJzY3JpcHRpb24jJHt0b3BpY05hbWV9IyR7dGFyZ2V0TmFtZX1gO1xuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLm1hcHBpbmdbdG9waWMudG9waWNBcm5dID0gc2VydmljZUtleTtcbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goc2VydmljZUtleSk7XG4gIH1cblxuICBwcml2YXRlIHByb3ZpZGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbihcbiAgICBmaWx0ZXJGdW5jdGlvbj86IChzdWJzY3JpcHRpb246IExhbWJkYVN1YnNjcmlwdGlvbikgPT4gYm9vbGVhblxuICApIHtcbiAgICBsZXQgZnVuY3Rpb25TdWJzY3JpcHRpb246IExhbWJkYVN1YnNjcmlwdGlvbiB8IHVuZGVmaW5lZDtcblxuICAgIGlmIChmaWx0ZXJGdW5jdGlvbikge1xuICAgICAgZnVuY3Rpb25TdWJzY3JpcHRpb24gPSB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2wuZmluZChmaWx0ZXJGdW5jdGlvbik7XG4gICAgfSBlbHNlIGlmICh0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2wubGVuZ3RoID4gMCkge1xuICAgICAgZnVuY3Rpb25TdWJzY3JpcHRpb24gPSB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2xbMF07XG4gICAgfVxuXG4gICAgaWYgKCFmdW5jdGlvblN1YnNjcmlwdGlvbikge1xuICAgICAgZnVuY3Rpb25TdWJzY3JpcHRpb24gPSB7XG4gICAgICAgIHN1YnNyaWJlZFRvcGljczogW10sXG4gICAgICAgIHVzZWRGb3JFdmVudEJyaWRnZTogZmFsc2UsXG4gICAgICAgIG1hcHBpbmc6IHt9LFxuICAgICAgICBmdW5jdGlvbjogdGhpcy5jcmVhdGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbihcbiAgICAgICAgICB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2wubGVuZ3RoXG4gICAgICAgICksXG4gICAgICB9O1xuICAgICAgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25Qb29sLnB1c2goZnVuY3Rpb25TdWJzY3JpcHRpb24pO1xuICAgIH1cbiAgICByZXR1cm4gZnVuY3Rpb25TdWJzY3JpcHRpb247XG4gIH1cblxuICBwcml2YXRlIHNldHVwRm9ySW9UKGZ1bmM6IGxhbWJkYS5GdW5jdGlvbikge1xuICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoXG4gICAgICBlbnZWYXJpYWJsZU5hbWVzLlNTUFlfUk9PVF9TVEFDSyxcbiAgICAgIHRoaXMuY2xlYW5OYW1lKHRoaXMuZmluZFJvb3RTdGFjayhTdGFjay5vZih0aGlzKSkubm9kZS5pZClcbiAgICApO1xuICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoZW52VmFyaWFibGVOYW1lcy5TU1BZX0lPVF9FTkRQT0lOVCwgdGhpcy5pb3RFbmRwb2ludCk7XG5cbiAgICBmdW5jLmFkZFRvUm9sZVBvbGljeShcbiAgICAgIG5ldyBhd3NfaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGFjdGlvbnM6IFsnaW90OionXSxcbiAgICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1csXG4gICAgICAgIHJlc291cmNlczogWycqJ10sXG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5TGFtYmRhKGZ1bmM6IGxhbWJkYS5GdW5jdGlvbikge1xuICAgIGNvbnN0IHsgbGF5ZXIsIHNweVdyYXBwZXJQYXRoIH0gPSB0aGlzLmdldEV4dGVuc2lvbkZvclJ1bnRpbWUoXG4gICAgICBmdW5jLnJ1bnRpbWUsXG4gICAgICBmdW5jLmFyY2hpdGVjdHVyZSB8fCBBcmNoaXRlY3R1cmUuWDg2XzY0XG4gICAgKSE7XG4gICAgaWYgKCFsYXllcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBmdW5jLmFkZExheWVycyhsYXllcik7XG5cbiAgICBjb25zdCBmdW5jdGlvbk5hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUoZnVuYyk7XG5cbiAgICBmdW5jLmFkZEVudmlyb25tZW50KGVudlZhcmlhYmxlTmFtZXMuU1NQWV9GVU5DVElPTl9OQU1FLCBmdW5jdGlvbk5hbWUpO1xuICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoJ0FXU19MQU1CREFfRVhFQ19XUkFQUEVSJywgc3B5V3JhcHBlclBhdGgpO1xuXG4gICAgaWYgKHRoaXMucHJvcHM/LmRlYnVnTW9kZSkge1xuICAgICAgZnVuYy5hZGRFbnZpcm9ubWVudChlbnZWYXJpYWJsZU5hbWVzLlNTUFlfREVCVUcsICd0cnVlJyk7XG4gICAgfVxuXG4gICAgdGhpcy5zZXR1cEZvcklvVChmdW5jKTtcblxuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChgRnVuY3Rpb24jJHtmdW5jdGlvbk5hbWV9I1JlcXVlc3RgKTtcbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goYEZ1bmN0aW9uIyR7ZnVuY3Rpb25OYW1lfSNFcnJvcmApO1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChgRnVuY3Rpb24jJHtmdW5jdGlvbk5hbWV9I0NvbnNvbGVgKTtcbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goYEZ1bmN0aW9uIyR7ZnVuY3Rpb25OYW1lfSNSZXNwb25zZWApO1xuXG4gICAgdGhpcy5hZGRNYXBwaW5nVG9GdW5jdGlvbihmdW5jKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRDb25zdHJ1Y3ROYW1lKGNvbnN0cnVjdDogSUNvbnN0cnVjdCkge1xuICAgIGxldCBjb25zdHJ1Y3ROYW1lID0gY29uc3RydWN0Lm5vZGUucGF0aDtcbiAgICBjb25zdCB7IG5vZGUgfSA9IFN0YWNrLm9mKHRoaXMpO1xuXG4gICAgaWYgKGNvbnN0cnVjdE5hbWUuc3RhcnRzV2l0aChub2RlLmlkKSkge1xuICAgICAgY29uc3RydWN0TmFtZSA9IGNvbnN0cnVjdE5hbWUuc3Vic3RyaW5nKG5vZGUuaWQubGVuZ3RoICsgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuY2xlYW5OYW1lKGNvbnN0cnVjdE5hbWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBjbGVhbk5hbWUobmFtZTogc3RyaW5nKSB7XG4gICAgLy9zbmFrZSBjYXNlIHRvIGNhbWVsIGNhc2UgaW5jbHVkaW5nIGRhc2ggYW5kIGZpcnN0IGxldHRlciB0byB1cHBlciBjYXNlXG4gICAgcmV0dXJuIG5hbWVcbiAgICAgIC5yZXBsYWNlKC9bLV9dKy9nLCAnICcpXG4gICAgICAucmVwbGFjZSgvW15cXHdcXHNdL2csICcnKVxuICAgICAgLnJlcGxhY2UoL1xccyguKS9nLCAoJDEpID0+ICQxLnRvVXBwZXJDYXNlKCkpXG4gICAgICAucmVwbGFjZSgvXFxzL2csICcnKVxuICAgICAgLnJlcGxhY2UoL14oLikvLCAoJDEpID0+ICQxLnRvVXBwZXJDYXNlKCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRUb3BpYyh0b3BpY0Fybjogc3RyaW5nKTogc25zLlRvcGljIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCB0b3BpYyA9IHRoaXMuZmluZEVsZW1lbnQ8c25zLlRvcGljPihcbiAgICAgIChub2RlOiBJQ29uc3RydWN0KSA9PlxuICAgICAgICBub2RlIGluc3RhbmNlb2Ygc25zLlRvcGljICYmIChub2RlIGFzIHNucy5Ub3BpYykudG9waWNBcm4gPT09IHRvcGljQXJuXG4gICAgKTtcblxuICAgIHJldHVybiB0b3BpYztcbiAgfVxuXG4gIHByaXZhdGUgZ2V0RXZlbnRCcmlkZ2UoZXZlbnRCdXNOYW1lOiBzdHJpbmcpOiBldmVudHMuSUV2ZW50QnVzIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBldmVudEJyaWRnZSA9IHRoaXMuZmluZEVsZW1lbnQ8ZXZlbnRzLklFdmVudEJ1cz4oXG4gICAgICAobm9kZTogSUNvbnN0cnVjdCkgPT5cbiAgICAgICAgKG5vZGUgaW5zdGFuY2VvZiBldmVudHMuRXZlbnRCdXMgfHxcbiAgICAgICAgICBub2RlLmNvbnN0cnVjdG9yLm5hbWUgPT09ICdJbXBvcnRlZEV2ZW50QnVzJykgJiZcbiAgICAgICAgKG5vZGUgYXMgZXZlbnRzLklFdmVudEJ1cykuZXZlbnRCdXNOYW1lID09PSBldmVudEJ1c05hbWVcbiAgICApO1xuXG4gICAgcmV0dXJuIGV2ZW50QnJpZGdlO1xuICB9XG5cbiAgcHJpdmF0ZSBmaW5kUm9vdFN0YWNrKHN0YWNrOiBTdGFjayk6IFN0YWNrIHtcbiAgICBpZiAoc3RhY2submVzdGVkKSB7XG4gICAgICBjb25zdCBwYXJlbnRTdGFjayA9IChzdGFjayBhcyBOZXN0ZWRTdGFjaykubmVzdGVkU3RhY2tQYXJlbnQ7XG4gICAgICBpZiAocGFyZW50U3RhY2spIHJldHVybiB0aGlzLmZpbmRSb290U3RhY2socGFyZW50U3RhY2spO1xuICAgICAgcmV0dXJuIHN0YWNrO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gc3RhY2s7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBmaW5kRWxlbWVudDxUIGV4dGVuZHMgSUNvbnN0cnVjdCA9IElDb25zdHJ1Y3Q+KFxuICAgIGZpbHRlckZ1bmM6IChub2RlOiBJQ29uc3RydWN0KSA9PiBib29sZWFuLFxuICAgIHBhcmVudD86IElDb25zdHJ1Y3RcbiAgKTogVCB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFwYXJlbnQpIHtcbiAgICAgIHBhcmVudCA9IHRoaXMuZmluZFJvb3RTdGFjayhTdGFjay5vZih0aGlzKSk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBub2RlIG9mIHBhcmVudC5ub2RlLmNoaWxkcmVuKSB7XG4gICAgICBpZiAoZmlsdGVyRnVuYyhub2RlKSkge1xuICAgICAgICByZXR1cm4gbm9kZSBhcyBUO1xuICAgICAgfVxuICAgICAgY29uc3QgZWxlbWVudEZvdW5kSW5DaGlsZCA9IHRoaXMuZmluZEVsZW1lbnQ8VD4oZmlsdGVyRnVuYywgbm9kZSk7XG4gICAgICBpZiAoZWxlbWVudEZvdW5kSW5DaGlsZCkge1xuICAgICAgICByZXR1cm4gZWxlbWVudEZvdW5kSW5DaGlsZDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRNYXBwaW5nVG9GdW5jdGlvbihcbiAgICBmdW5jOiBsYW1iZGEuRnVuY3Rpb24sXG4gICAga2V5VmFsdWU/OiB7IGtleTogc3RyaW5nOyB2YWx1ZTogc3RyaW5nIH1cbiAgKSB7XG4gICAgZm9yIChjb25zdCBmcyBvZiB0aGlzLmxhbWJkYXNTcGllZCkge1xuICAgICAgaWYgKGZzLmZ1bmN0aW9uID09PSBmdW5jKSB7XG4gICAgICAgIGlmIChrZXlWYWx1ZSkge1xuICAgICAgICAgIGZzLm1hcHBpbmdba2V5VmFsdWUua2V5XSA9IGtleVZhbHVlLnZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBmczogTGFtYmRhU3BpZWQgPSB7XG4gICAgICBmdW5jdGlvbjogZnVuYyxcbiAgICAgIG1hcHBpbmc6IHt9LFxuICAgIH07XG5cbiAgICBpZiAoa2V5VmFsdWUpIHtcbiAgICAgIGZzLm1hcHBpbmdba2V5VmFsdWUua2V5XSA9IGtleVZhbHVlLnZhbHVlO1xuICAgIH1cblxuICAgIHRoaXMubGFtYmRhc1NwaWVkLnB1c2goZnMpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRBc3NldExvY2F0aW9uKGxvY2F0aW9uOiBzdHJpbmcpIHtcbiAgICBjb25zdCBsb2MgPSBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vbGliLycgKyBsb2NhdGlvbik7XG5cbiAgICBpZiAoZnMuZXhpc3RzU3luYyhsb2MpKSB7XG4gICAgICByZXR1cm4gbG9jO1xuICAgIH1cblxuICAgIGNvbnN0IGxvYzIgPSBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vLi4vbGliLycgKyBsb2NhdGlvbik7XG5cbiAgICBpZiAoZnMuZXhpc3RzU3luYyhsb2MyKSkge1xuICAgICAgcmV0dXJuIGxvYzI7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKGBMb2NhdGlvbiAke2xvY30gYW5kICR7bG9jMn0gZG9lcyBub3QgZXhpc3RzLmApO1xuICB9XG59XG5cbnR5cGUgTGFtYmRhU3Vic2NyaXB0aW9uID0ge1xuICBzdWJzcmliZWRUb3BpY3M6IHNucy5Ub3BpY1tdO1xuICB1c2VkRm9yRXZlbnRCcmlkZ2U6IGJvb2xlYW47XG4gIGZ1bmN0aW9uOiBsYW1iZGFOb2RlLk5vZGVqc0Z1bmN0aW9uO1xuICBtYXBwaW5nOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xufTtcblxudHlwZSBMYW1iZGFTcGllZCA9IHtcbiAgZnVuY3Rpb246IGxhbWJkYS5GdW5jdGlvbjtcbiAgbWFwcGluZzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbn07XG4iXX0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerlessSpy.js","names":["Construct","props?: ServerlessSpyProps","Stack","custom_resources","CfnOutput","filterWithDefaults: Required<SpyFilter>","SingletonFunction","lambda","NodejsFunction","sns","s3","dynamoDb","events","sqs","envVariableNames","nodes: IConstruct[]","PythonLayerVersion","BundlingFileAccess","Duration","SqsEventSource","lambdaNode","s3notif","dynamoDbStream","targets","snsSubs","functionSubscription: LambdaSubscription | undefined","aws_iam","Effect","Architecture","fs","fs: LambdaSpied"],"sources":["../../src/ServerlessSpy.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { PythonLayerVersion } from '@aws-cdk/aws-lambda-python-alpha';\nimport {\n aws_iam,\n BundlingFileAccess,\n CfnOutput,\n custom_resources,\n Duration,\n NestedStack,\n Stack,\n} from 'aws-cdk-lib';\nimport * as dynamoDb from 'aws-cdk-lib/aws-dynamodb';\nimport * as events from 'aws-cdk-lib/aws-events';\nimport * as targets from 'aws-cdk-lib/aws-events-targets';\nimport { Effect } from 'aws-cdk-lib/aws-iam';\nimport * as lambda from 'aws-cdk-lib/aws-lambda';\nimport {\n Architecture,\n ILayerVersion,\n SingletonFunction,\n} from 'aws-cdk-lib/aws-lambda';\nimport * as dynamoDbStream from 'aws-cdk-lib/aws-lambda-event-sources';\nimport { SqsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';\nimport * as lambdaNode from 'aws-cdk-lib/aws-lambda-nodejs';\nimport { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';\nimport * as s3 from 'aws-cdk-lib/aws-s3';\nimport * as s3notif from 'aws-cdk-lib/aws-s3-notifications';\nimport * as sns from 'aws-cdk-lib/aws-sns';\nimport * as snsSubs from 'aws-cdk-lib/aws-sns-subscriptions';\nimport * as sqs from 'aws-cdk-lib/aws-sqs';\nimport { Construct, IConstruct } from 'constructs';\nimport { envVariableNames } from './common/envVariableNames';\n\nexport interface ServerlessSpyProps {\n readonly generateSpyEventsFileLocation?: string;\n readonly spySqsWithNoSubscriptionAndDropAllMessages?: boolean;\n readonly debugMode?: boolean;\n}\n\nexport interface SpyFilter {\n readonly spyLambda?: boolean;\n readonly spySqs?: boolean;\n readonly spySnsTopic?: boolean;\n readonly spySnsSubsription?: boolean;\n readonly spyEventBridge?: boolean;\n readonly spyEventBridgeRule?: boolean;\n readonly spyS3?: boolean;\n readonly spyDynamoDB?: boolean;\n}\n\nconst isLambdaFunction = (node: IConstruct): node is lambda.Function =>\n 'functionName' in node && 'functionArn' in node && 'runtime' in node;\n\nconst serverlessSpyIotEndpointCrNamePrefix = 'ServerlessSpyIotEndpoint';\n\nexport class ServerlessSpy extends Construct {\n private createdResourcesBySSpy: IConstruct[] = [];\n private lambdaSubscriptionPool: LambdaSubscription[] = [];\n private lambdaSubscriptionMain: LambdaSubscription;\n private lambdasSpied: LambdaSpied[] = [];\n public serviceKeys: string[] = [];\n private spiedNodes: IConstruct[] = [];\n private layerMap: Partial<Record<string, ILayerVersion>> = {};\n private readonly iotEndpoint: string;\n\n constructor(\n scope: Construct,\n id: string,\n private props?: ServerlessSpyProps\n ) {\n super(scope, id);\n\n const rootStack = this.cleanName(\n this.findRootStack(Stack.of(this)).node.id\n );\n\n const getIoTEndpoint = new custom_resources.AwsCustomResource(\n this,\n serverlessSpyIotEndpointCrNamePrefix,\n {\n onCreate: {\n service: 'Iot',\n action: 'describeEndpoint',\n physicalResourceId:\n custom_resources.PhysicalResourceId.fromResponse('endpointAddress'),\n parameters: {\n endpointType: 'iot:Data-ATS',\n },\n },\n onUpdate: {\n service: 'Iot',\n action: 'describeEndpoint',\n physicalResourceId:\n custom_resources.PhysicalResourceId.fromResponse('endpointAddress'),\n parameters: {\n endpointType: 'iot:Data-ATS',\n },\n },\n installLatestAwsSdk: false,\n policy: custom_resources.AwsCustomResourcePolicy.fromSdkCalls({\n resources: custom_resources.AwsCustomResourcePolicy.ANY_RESOURCE,\n }),\n functionName: serverlessSpyIotEndpointCrNamePrefix + rootStack,\n }\n );\n this.iotEndpoint = getIoTEndpoint.getResponseField('endpointAddress');\n\n this.createdResourcesBySSpy.push(getIoTEndpoint);\n\n new CfnOutput(this, 'ServerlessSpyIoTEndpoint', {\n key: 'ServerlessSpyWsUrl',\n value: `${this.iotEndpoint}/${rootStack}`,\n });\n\n this.lambdaSubscriptionMain = this.provideFunctionForSubscription();\n }\n\n private getDefaultLambdaEnvironmentVariables(): { [key: string]: string } {\n return {\n NODE_OPTIONS: '--enable-source-maps',\n };\n }\n\n /**\n * Initalize spying on resources given as parameter.\n * @param nodes Which reources and their children to spy on.\n */\n public spyNodes(nodes: IConstruct[]) {\n for (const node of nodes) {\n let ns = this.getAllNodes(node);\n this.internalSpyNodes(ns);\n }\n\n this.finalizeSpy();\n }\n\n /**\n * Initalize spying on resources.\n * @param filter Limit which resources to spy on.\n */\n public spy(filter?: SpyFilter) {\n let nodes = this.getAllNodes(Stack.of(this));\n\n const filterWithDefaults: Required<SpyFilter> = {\n spyLambda: true,\n spySqs: true,\n spySnsTopic: true,\n spySnsSubsription: true,\n spyEventBridge: true,\n spyEventBridgeRule: true,\n spyS3: true,\n spyDynamoDB: true,\n ...filter,\n };\n\n const CRID =\n 'AWS' +\n custom_resources.AwsCustomResource.PROVIDER_FUNCTION_UUID.replace(\n /-/gi,\n ''\n ).substring(0, 16);\n\n nodes = nodes.filter((node) => {\n if (\n // Ignore the custom resource and the Provider (as well as any other Providers using the same provider function), otherwise we cause\n // circular dependencies\n node.node.id.startsWith(CRID) ||\n node.node.id === 'Provider' ||\n // Ignore singleton functions as they can cause very odd behavior and crashes\n node instanceof SingletonFunction\n ) {\n if (this.props?.debugMode) {\n console.info(`Skipping ${node.node.id}`);\n }\n return false;\n } else if (\n filterWithDefaults.spyLambda &&\n (node instanceof lambda.Function ||\n node instanceof NodejsFunction ||\n isLambdaFunction(node))\n ) {\n return true;\n } else if (filterWithDefaults.spySnsTopic && node instanceof sns.Topic) {\n return true;\n } else if (\n filterWithDefaults.spySnsSubsription &&\n node instanceof sns.Subscription\n ) {\n return true;\n } else if (filterWithDefaults.spyS3 && node instanceof s3.Bucket) {\n return true;\n } else if (\n filterWithDefaults.spyDynamoDB &&\n node instanceof dynamoDb.Table\n ) {\n return true;\n } else if (\n filterWithDefaults.spyDynamoDB &&\n node instanceof dynamoDb.TableV2\n ) {\n return true;\n } else if (\n filterWithDefaults.spyEventBridge &&\n node instanceof events.EventBus\n ) {\n return true;\n } else if (\n filterWithDefaults.spyEventBridgeRule &&\n node instanceof events.Rule\n ) {\n return true;\n } else if (\n filterWithDefaults.spySqs &&\n node instanceof lambda.CfnEventSourceMapping\n ) {\n return true;\n } else if (\n filterWithDefaults.spySqs &&\n this.props?.spySqsWithNoSubscriptionAndDropAllMessages &&\n node instanceof sqs.Queue\n ) {\n return true;\n }\n\n return false;\n });\n\n this.internalSpyNodes(nodes);\n this.finalizeSpy();\n }\n\n private internalSpyNodes(nodes: IConstruct[]) {\n for (const node of nodes) {\n this.internalSpyNode(node);\n }\n }\n\n private finalizeSpy() {\n //set mapping property for all functions we created\n for (const func of this.lambdaSubscriptionPool) {\n func.function.addEnvironment(\n envVariableNames.SSPY_INFRA_MAPPING,\n JSON.stringify(func.mapping)\n );\n }\n\n //set mapping property for all functions we spy on\n for (const func of this.lambdasSpied) {\n func.function.addEnvironment(\n envVariableNames.SSPY_INFRA_MAPPING,\n JSON.stringify(func.mapping)\n );\n }\n\n if (this.props?.generateSpyEventsFileLocation) {\n this.writeSpyEventsClass(this.props?.generateSpyEventsFileLocation);\n }\n }\n\n private getExtensionAssetLocation() {\n let extensionAssetLocation = path.join(\n __dirname,\n '../extension/dist/layer'\n );\n\n const extensionAssetLocationAlt = path.join(\n __dirname,\n '../lib/extension/dist/layer'\n );\n\n if (!fs.existsSync(extensionAssetLocation)) {\n if (!fs.existsSync(extensionAssetLocationAlt)) {\n throw new Error(\n `Folder with assets for extension does not exists at ${extensionAssetLocation} or at ${extensionAssetLocationAlt} `\n );\n } else {\n extensionAssetLocation = extensionAssetLocationAlt;\n }\n }\n\n const extensionAssetLocationWrapper = path.join(\n extensionAssetLocation,\n 'spy-wrapper'\n );\n if (!fs.existsSync(extensionAssetLocationWrapper)) {\n throw new Error(\n `Wrapper script for extension does not exists ${extensionAssetLocation}`\n );\n }\n\n const extensionAssetLocationCode = path.join(\n extensionAssetLocation,\n `nodejs/node_modules/interceptor.js`\n );\n if (!fs.existsSync(extensionAssetLocationCode)) {\n throw new Error(\n `Code for extension does not exists ${extensionAssetLocationCode}`\n );\n }\n return extensionAssetLocation;\n }\n\n private getLanguageExtensionAssetLocation(language: string) {\n const rootDir = path.join(__dirname, '..');\n\n let extensionAssetLocation = path.join(rootDir, `extensions/${language}`);\n\n const extensionAssetLocationAlt = path.join(\n rootDir,\n `lib/extensions/${language}`\n );\n\n if (!fs.existsSync(extensionAssetLocation)) {\n if (!fs.existsSync(extensionAssetLocationAlt)) {\n throw new Error(\n `Folder with assets for extension for ${language} does not exists at ${extensionAssetLocation} or at ${extensionAssetLocationAlt} `\n );\n } else {\n extensionAssetLocation = extensionAssetLocationAlt;\n }\n }\n\n const extensionAssetLocationWrapper = path.join(\n // extensionAssetLocation.substring(\n // 0,\n // extensionAssetLocation.lastIndexOf(path.sep)\n // ),\n extensionAssetLocation,\n 'spy-wrapper'\n );\n if (!fs.existsSync(extensionAssetLocationWrapper)) {\n throw new Error(\n `Wrapper script for extension does not exists at ${extensionAssetLocationWrapper}`\n );\n }\n\n return extensionAssetLocation;\n }\n\n /**\n * Write SpyEvents class, which helps with writing the code for tests.\n * @param fileLocation\n */\n private writeSpyEventsClass(fileLocation: string) {\n fs.mkdirSync(path.dirname(fileLocation), { recursive: true });\n\n const properties = this.serviceKeys\n .map((sk) => ` ${sk.replace(/#/g, '')}: '${sk}' = '${sk}';\\n`)\n .join('');\n\n const code = `/* eslint-disable */\\nexport class ServerlessSpyEvents {\\n${properties}}\\n`;\n\n fs.writeFileSync(fileLocation, code);\n }\n\n private getAllNodes(parent: IConstruct) {\n const nodes: IConstruct[] = [];\n nodes.push(parent);\n this.getAllNodesRecursive(parent, nodes);\n return nodes;\n }\n\n private getAllNodesRecursive(parent: IConstruct, nodes: IConstruct[]) {\n for (const node of parent.node.children) {\n nodes.push(node);\n this.getAllNodesRecursive(node, nodes);\n }\n }\n\n private internalSpyNode(node: IConstruct) {\n if (this.spiedNodes.includes(node)) {\n return;\n }\n\n this.spiedNodes.push(node);\n\n if (this.createdResourcesBySSpy.includes(node)) {\n return;\n }\n\n if (this.lambdaSubscriptionPool.find((s) => s.function === node)) {\n return;\n }\n\n if (this.props?.debugMode) {\n console.info('Spy on node', this.getConstructName(node));\n }\n\n if (\n node instanceof lambda.Function ||\n node instanceof NodejsFunction ||\n isLambdaFunction(node)\n ) {\n this.internalSpyLambda(node);\n } else if (node instanceof sns.Topic) {\n this.internalSpySnsTopic(node);\n } else if (node instanceof sns.Subscription) {\n this.internalSpySnsSubscription(node);\n } else if (node instanceof s3.Bucket) {\n this.internalSpyS3(node);\n } else if (node instanceof dynamoDb.Table) {\n this.internalSpyDynamodb(node);\n } else if (node instanceof dynamoDb.TableV2) {\n this.internalSpyDynamodb(node);\n } else if (node instanceof events.EventBus) {\n this.internalSpyEventBus(node);\n } else if (node instanceof events.Rule) {\n this.internalSpyEventBusRule(node);\n } else if (node instanceof lambda.CfnEventSourceMapping) {\n this.internalSpySqs(node);\n } else if (node instanceof sqs.Queue) {\n if (this.props?.spySqsWithNoSubscriptionAndDropAllMessages) {\n this.internalSpySpySqsWithNoSubscription(node);\n }\n }\n }\n\n private getExtensionForRuntime(\n runtime: lambda.Runtime,\n architecture: lambda.Architecture\n ): { layer: lambda.ILayerVersion; spyWrapperPath: string } | undefined {\n const layerKey =\n `sspy_extension_${runtime.toString()}_${architecture.name.toString()}`.replace(\n /\\./g,\n '_'\n );\n\n let layer = this.layerMap[layerKey];\n let spyWrapperPath = '/opt/spy-wrapper';\n\n switch (runtime.name) {\n case lambda.Runtime.PYTHON_3_8.name:\n case lambda.Runtime.PYTHON_3_9.name:\n case lambda.Runtime.PYTHON_3_10.name:\n case lambda.Runtime.PYTHON_3_11.name:\n case lambda.Runtime.PYTHON_3_12.name:\n spyWrapperPath = '/opt/python/spy-wrapper';\n layer =\n layer ||\n new PythonLayerVersion(this, layerKey, {\n compatibleRuntimes: [runtime],\n compatibleArchitectures: [architecture],\n entry: this.getLanguageExtensionAssetLocation('python'),\n bundling: {\n bundlingFileAccess: BundlingFileAccess.VOLUME_COPY,\n },\n });\n break;\n case lambda.Runtime.NODEJS_12_X.name:\n case lambda.Runtime.NODEJS_14_X.name:\n case lambda.Runtime.NODEJS_16_X.name:\n case lambda.Runtime.NODEJS_18_X.name:\n case lambda.Runtime.NODEJS_20_X.name:\n case lambda.Runtime.NODEJS_22_X.name:\n layer =\n layer ||\n new lambda.LayerVersion(this, layerKey, {\n compatibleRuntimes: [runtime],\n compatibleArchitectures: [architecture],\n code: lambda.Code.fromAsset(this.getExtensionAssetLocation()),\n });\n break;\n default:\n console.log(`No extensions available for ${runtime.toString()}`);\n return undefined;\n }\n\n this.layerMap[layerKey] = layer;\n this.createdResourcesBySSpy.push(layer);\n return { layer, spyWrapperPath };\n }\n\n private internalSpySpySqsWithNoSubscription(queue: sqs.Queue) {\n const subscription = this.findElement<lambda.CfnEventSourceMapping>(\n (n: IConstruct) =>\n n instanceof lambda.CfnEventSourceMapping &&\n (n as lambda.CfnEventSourceMapping).eventSourceArn === queue.queueArn\n );\n\n if (subscription) {\n return; //already have subscription\n }\n\n const queueName = this.getConstructName(queue);\n const func = new NodejsFunction(\n this,\n `${queueName}SqsSubscriptionAndDropAllMessages`,\n {\n memorySize: 512,\n timeout: Duration.seconds(5),\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'handler',\n entry: this.getAssetLocation(\n 'functions/sqsSubscriptionAndDropAllMessages.js'\n ),\n environment: this.getDefaultLambdaEnvironmentVariables(),\n }\n );\n func.addEventSource(new SqsEventSource(queue));\n this.setupForIoT(func);\n const { layer, spyWrapperPath } = this.getExtensionForRuntime(\n func.runtime,\n func.architecture\n )!;\n func.addLayers(layer);\n\n func.addEnvironment('AWS_LAMBDA_EXEC_WRAPPER', spyWrapperPath);\n\n if (this.props?.debugMode) {\n func.addEnvironment(envVariableNames.SSPY_DEBUG, 'true');\n }\n\n this.createdResourcesBySSpy.push(func);\n\n const serviceKey = `Sqs#${queueName}`;\n\n this.addMappingToFunction(func, {\n key: queue.queueArn,\n value: serviceKey,\n });\n\n this.serviceKeys.push(serviceKey);\n func.addEnvironment(envVariableNames.SSPY_SUBSCRIBED_TO_SQS, 'true');\n }\n\n private internalSpySqs(node: lambda.CfnEventSourceMapping) {\n const queue = this.findElement<sqs.Queue>(\n (n: IConstruct) =>\n n instanceof sqs.Queue &&\n (n as sqs.Queue).queueArn === node.eventSourceArn\n );\n\n const func = this.findElement<lambda.Function>(\n (n: IConstruct) =>\n n instanceof lambda.Function &&\n (n as lambda.Function).functionName === node.functionName\n );\n\n if (queue && func) {\n const queueName = this.getConstructName(queue);\n\n const serviceKey = `Sqs#${queueName}`;\n\n this.addMappingToFunction(func, {\n key: queue.queueArn,\n value: serviceKey,\n });\n\n this.serviceKeys.push(serviceKey);\n func.addEnvironment(envVariableNames.SSPY_SUBSCRIBED_TO_SQS, 'true');\n }\n }\n\n private createFunctionForSubscription(index: number) {\n const func = new lambdaNode.NodejsFunction(this, `Subscription${index}`, {\n memorySize: 512,\n timeout: Duration.seconds(5),\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'handler',\n entry: this.getAssetLocation('functions/sendMessage.js'),\n environment: {\n NODE_OPTIONS: '--enable-source-maps',\n },\n });\n this.setupForIoT(func);\n return func;\n }\n\n private internalSpyS3(s3Bucket: s3.Bucket) {\n s3Bucket.addEventNotification(\n s3.EventType.OBJECT_CREATED_PUT,\n new s3notif.LambdaDestination(this.lambdaSubscriptionMain.function)\n );\n\n const name = this.getConstructName(s3Bucket);\n\n const serviceKey = `S3#${name}`;\n this.lambdaSubscriptionMain.mapping[s3Bucket.bucketArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyDynamodb(table: dynamoDb.Table | dynamoDb.TableV2) {\n // enable DynamoDB streams with a hack\n (table.node.defaultChild as dynamoDb.CfnTable).streamSpecification = {\n streamViewType: dynamoDb.StreamViewType.NEW_AND_OLD_IMAGES,\n };\n var tableStreamArnDescriptor = Object.getOwnPropertyDescriptor(\n table,\n 'tableStreamArn'\n );\n\n if (\n tableStreamArnDescriptor === undefined ||\n tableStreamArnDescriptor.get === undefined\n ) {\n (table as any).tableStreamArn = (\n table.node.defaultChild as dynamoDb.CfnTable\n ).attrStreamArn;\n }\n\n this.lambdaSubscriptionMain.function.addEventSource(\n new dynamoDbStream.DynamoEventSource(table, {\n startingPosition: lambda.StartingPosition.LATEST,\n batchSize: 1,\n retryAttempts: 0,\n })\n );\n\n const name = this.getConstructName(table);\n\n const serviceKey = `DynamoDB#${name}`;\n this.lambdaSubscriptionMain.mapping[table.tableArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyEventBusRule(rule: events.Rule) {\n const { eventBusName } = rule.node.defaultChild as events.CfnRule;\n let bridgeName = 'Default';\n if (!!eventBusName) {\n const eventBridge = this.getEventBridge(eventBusName);\n\n if (!eventBridge) {\n throw new Error(`Can not find EventBridge with name \"${eventBusName}\"`);\n }\n bridgeName = this.getConstructName(eventBridge);\n }\n\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.usedForEventBridge\n );\n functionSubscription.usedForEventBridge = true;\n\n rule.addTarget(new targets.LambdaFunction(functionSubscription.function));\n\n const ruleName = this.getConstructName(rule);\n const serviceKey = `EventBridgeRule#${bridgeName}#${ruleName}`;\n functionSubscription.mapping.eventBridge = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyEventBus(eventBus: events.EventBus) {\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.usedForEventBridge\n );\n functionSubscription.usedForEventBridge = true;\n\n const bridgeName = this.getConstructName(eventBus);\n const rule = new events.Rule(this, `RuleAll${bridgeName}`, {\n eventBus,\n eventPattern: { version: ['0'] },\n targets: [new targets.LambdaFunction(functionSubscription.function)],\n });\n\n this.createdResourcesBySSpy.push(rule);\n const serviceKey = `EventBridge#${bridgeName}`;\n functionSubscription.mapping.eventBridge = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpySnsTopic(topic: sns.Topic) {\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.subsribedTopics.includes(topic)\n );\n\n const subscription = topic.addSubscription(\n new snsSubs.LambdaSubscription(functionSubscription.function)\n );\n this.createdResourcesBySSpy.push(subscription);\n const topicName = this.getConstructName(topic);\n const serviceKey = `SnsTopic#${topicName}`;\n functionSubscription.mapping[topic.topicArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n functionSubscription.subsribedTopics.push(topic);\n }\n\n private internalSpySnsSubscription(subscription: sns.Subscription) {\n if (!subscription.node.scope) {\n return;\n }\n\n const topic = this.getTopic(\n (subscription.node.defaultChild as sns.CfnSubscription).topicArn\n );\n\n if (!topic) {\n throw new Error('Can not find Topic');\n }\n\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.subsribedTopics.includes(topic)\n );\n\n const { filterPolicy } = subscription.node\n .defaultChild as sns.CfnSubscription;\n\n const subscriptionClone = topic.addSubscription(\n new snsSubs.LambdaSubscription(functionSubscription.function)\n );\n (subscriptionClone.node.defaultChild as sns.CfnSubscription).filterPolicy =\n filterPolicy;\n\n this.createdResourcesBySSpy.push(subscriptionClone);\n\n const topicName = this.getConstructName(topic);\n const targetName = this.getConstructName(subscription.node.scope);\n\n functionSubscription.subsribedTopics.push(topic);\n const serviceKey = `SnsSubscription#${topicName}#${targetName}`;\n functionSubscription.mapping[topic.topicArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private provideFunctionForSubscription(\n filterFunction?: (subscription: LambdaSubscription) => boolean\n ) {\n let functionSubscription: LambdaSubscription | undefined;\n\n if (filterFunction) {\n functionSubscription = this.lambdaSubscriptionPool.find(filterFunction);\n } else if (this.lambdaSubscriptionPool.length > 0) {\n functionSubscription = this.lambdaSubscriptionPool[0];\n }\n\n if (!functionSubscription) {\n functionSubscription = {\n subsribedTopics: [],\n usedForEventBridge: false,\n mapping: {},\n function: this.createFunctionForSubscription(\n this.lambdaSubscriptionPool.length\n ),\n };\n this.lambdaSubscriptionPool.push(functionSubscription);\n }\n return functionSubscription;\n }\n\n private setupForIoT(func: lambda.Function) {\n func.addEnvironment(\n envVariableNames.SSPY_ROOT_STACK,\n this.cleanName(this.findRootStack(Stack.of(this)).node.id)\n );\n func.addEnvironment(envVariableNames.SSPY_IOT_ENDPOINT, this.iotEndpoint);\n\n func.addToRolePolicy(\n new aws_iam.PolicyStatement({\n actions: ['iot:*'],\n effect: Effect.ALLOW,\n resources: ['*'],\n })\n );\n }\n\n private internalSpyLambda(func: lambda.Function) {\n const { layer, spyWrapperPath } = this.getExtensionForRuntime(\n func.runtime,\n func.architecture || Architecture.X86_64\n )!;\n if (!layer) {\n return;\n }\n func.addLayers(layer);\n\n const functionName = this.getConstructName(func);\n\n func.addEnvironment(envVariableNames.SSPY_FUNCTION_NAME, functionName);\n func.addEnvironment('AWS_LAMBDA_EXEC_WRAPPER', spyWrapperPath);\n\n if (this.props?.debugMode) {\n func.addEnvironment(envVariableNames.SSPY_DEBUG, 'true');\n }\n\n this.setupForIoT(func);\n\n this.serviceKeys.push(`Function#${functionName}#Request`);\n this.serviceKeys.push(`Function#${functionName}#Error`);\n this.serviceKeys.push(`Function#${functionName}#Console`);\n this.serviceKeys.push(`Function#${functionName}#Response`);\n\n this.addMappingToFunction(func);\n }\n\n public getConstructName(construct: IConstruct) {\n let constructName = construct.node.path;\n const { node } = Stack.of(this);\n\n if (constructName.startsWith(node.id)) {\n constructName = constructName.substring(node.id.length + 1);\n }\n\n return this.cleanName(constructName);\n }\n\n private cleanName(name: string) {\n //snake case to camel case including dash and first letter to upper case\n return name\n .replace(/[-_]+/g, ' ')\n .replace(/[^\\w\\s]/g, '')\n .replace(/\\s(.)/g, ($1) => $1.toUpperCase())\n .replace(/\\s/g, '')\n .replace(/^(.)/, ($1) => $1.toUpperCase());\n }\n\n private getTopic(topicArn: string): sns.Topic | undefined {\n const topic = this.findElement<sns.Topic>(\n (node: IConstruct) =>\n node instanceof sns.Topic && (node as sns.Topic).topicArn === topicArn\n );\n\n return topic;\n }\n\n private getEventBridge(eventBusName: string): events.IEventBus | undefined {\n const eventBridge = this.findElement<events.IEventBus>(\n (node: IConstruct) =>\n (node instanceof events.EventBus ||\n node.constructor.name === 'ImportedEventBus') &&\n (node as events.IEventBus).eventBusName === eventBusName\n );\n\n return eventBridge;\n }\n\n private findRootStack(stack: Stack): Stack {\n if (stack.nested) {\n const parentStack = (stack as NestedStack).nestedStackParent;\n if (parentStack) return this.findRootStack(parentStack);\n return stack;\n } else {\n return stack;\n }\n }\n\n private findElement<T extends IConstruct = IConstruct>(\n filterFunc: (node: IConstruct) => boolean,\n parent?: IConstruct\n ): T | undefined {\n if (!parent) {\n parent = this.findRootStack(Stack.of(this));\n }\n\n for (const node of parent.node.children) {\n if (filterFunc(node)) {\n return node as T;\n }\n const elementFoundInChild = this.findElement<T>(filterFunc, node);\n if (elementFoundInChild) {\n return elementFoundInChild;\n }\n }\n\n return undefined;\n }\n\n private addMappingToFunction(\n func: lambda.Function,\n keyValue?: { key: string; value: string }\n ) {\n for (const fs of this.lambdasSpied) {\n if (fs.function === func) {\n if (keyValue) {\n fs.mapping[keyValue.key] = keyValue.value;\n }\n return;\n }\n }\n\n const fs: LambdaSpied = {\n function: func,\n mapping: {},\n };\n\n if (keyValue) {\n fs.mapping[keyValue.key] = keyValue.value;\n }\n\n this.lambdasSpied.push(fs);\n }\n\n private getAssetLocation(location: string) {\n const loc = path.join(__dirname, '../lib/' + location);\n\n if (fs.existsSync(loc)) {\n return loc;\n }\n\n const loc2 = path.join(__dirname, '../../lib/' + location);\n\n if (fs.existsSync(loc2)) {\n return loc2;\n }\n\n throw new Error(`Location ${loc} and ${loc2} does not exists.`);\n }\n}\n\ntype LambdaSubscription = {\n subsribedTopics: sns.Topic[];\n usedForEventBridge: boolean;\n function: lambdaNode.NodejsFunction;\n mapping: Record<string, string>;\n};\n\ntype LambdaSpied = {\n function: lambda.Function;\n mapping: Record<string, string>;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ServerlessSpy.js","names":["Construct","props?: ServerlessSpyProps","Stack","custom_resources","CfnOutput","filterWithDefaults: Required<SpyFilter>","SingletonFunction","lambda","NodejsFunction","sns","s3","dynamoDb","events","sqs","envVariableNames","nodes: IConstruct[]","PythonLayerVersion","BundlingFileAccess","Duration","SqsEventSource","lambdaNode","s3notif","dynamoDbStream","targets","snsSubs","functionSubscription: LambdaSubscription | undefined","aws_iam","Effect","Architecture","fs","fs: LambdaSpied"],"sources":["../../src/ServerlessSpy.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { PythonLayerVersion } from '@aws-cdk/aws-lambda-python-alpha';\nimport {\n aws_iam,\n BundlingFileAccess,\n CfnOutput,\n custom_resources,\n Duration,\n NestedStack,\n Stack,\n} from 'aws-cdk-lib';\nimport * as dynamoDb from 'aws-cdk-lib/aws-dynamodb';\nimport * as events from 'aws-cdk-lib/aws-events';\nimport * as targets from 'aws-cdk-lib/aws-events-targets';\nimport { Effect } from 'aws-cdk-lib/aws-iam';\nimport * as lambda from 'aws-cdk-lib/aws-lambda';\nimport {\n Architecture,\n ILayerVersion,\n SingletonFunction,\n} from 'aws-cdk-lib/aws-lambda';\nimport * as dynamoDbStream from 'aws-cdk-lib/aws-lambda-event-sources';\nimport { SqsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';\nimport * as lambdaNode from 'aws-cdk-lib/aws-lambda-nodejs';\nimport { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';\nimport * as s3 from 'aws-cdk-lib/aws-s3';\nimport * as s3notif from 'aws-cdk-lib/aws-s3-notifications';\nimport * as sns from 'aws-cdk-lib/aws-sns';\nimport * as snsSubs from 'aws-cdk-lib/aws-sns-subscriptions';\nimport * as sqs from 'aws-cdk-lib/aws-sqs';\nimport { Construct, IConstruct } from 'constructs';\nimport { envVariableNames } from './common/envVariableNames';\n\nexport interface ServerlessSpyProps {\n readonly generateSpyEventsFileLocation?: string;\n readonly spySqsWithNoSubscriptionAndDropAllMessages?: boolean;\n readonly debugMode?: boolean;\n}\n\nexport interface SpyFilter {\n readonly spyLambda?: boolean;\n readonly spySqs?: boolean;\n readonly spySnsTopic?: boolean;\n readonly spySnsSubsription?: boolean;\n readonly spyEventBridge?: boolean;\n readonly spyEventBridgeRule?: boolean;\n readonly spyS3?: boolean;\n readonly spyDynamoDB?: boolean;\n}\n\nconst isLambdaFunction = (node: IConstruct): node is lambda.Function =>\n 'functionName' in node && 'functionArn' in node && 'runtime' in node;\n\nconst serverlessSpyIotEndpointCrNamePrefix = 'ServerlessSpyIotEndpoint';\n\nexport class ServerlessSpy extends Construct {\n private createdResourcesBySSpy: IConstruct[] = [];\n private lambdaSubscriptionPool: LambdaSubscription[] = [];\n private lambdaSubscriptionMain: LambdaSubscription;\n private lambdasSpied: LambdaSpied[] = [];\n public serviceKeys: string[] = [];\n private spiedNodes: IConstruct[] = [];\n private layerMap: Partial<Record<string, ILayerVersion>> = {};\n private readonly iotEndpoint: string;\n\n constructor(\n scope: Construct,\n id: string,\n private props?: ServerlessSpyProps\n ) {\n super(scope, id);\n\n const rootStack = this.cleanName(\n this.findRootStack(Stack.of(this)).node.id\n );\n\n const getIoTEndpoint = new custom_resources.AwsCustomResource(\n this,\n serverlessSpyIotEndpointCrNamePrefix,\n {\n onCreate: {\n service: 'Iot',\n action: 'describeEndpoint',\n physicalResourceId:\n custom_resources.PhysicalResourceId.fromResponse('endpointAddress'),\n parameters: {\n endpointType: 'iot:Data-ATS',\n },\n },\n onUpdate: {\n service: 'Iot',\n action: 'describeEndpoint',\n physicalResourceId:\n custom_resources.PhysicalResourceId.fromResponse('endpointAddress'),\n parameters: {\n endpointType: 'iot:Data-ATS',\n },\n },\n installLatestAwsSdk: false,\n policy: custom_resources.AwsCustomResourcePolicy.fromSdkCalls({\n resources: custom_resources.AwsCustomResourcePolicy.ANY_RESOURCE,\n }),\n functionName: serverlessSpyIotEndpointCrNamePrefix + rootStack,\n }\n );\n this.iotEndpoint = getIoTEndpoint.getResponseField('endpointAddress');\n\n this.createdResourcesBySSpy.push(getIoTEndpoint);\n\n new CfnOutput(this, 'ServerlessSpyIoTEndpoint', {\n key: 'ServerlessSpyWsUrl',\n value: `${this.iotEndpoint}/${rootStack}`,\n });\n\n this.lambdaSubscriptionMain = this.provideFunctionForSubscription();\n }\n\n private getDefaultLambdaEnvironmentVariables(): { [key: string]: string } {\n return {\n NODE_OPTIONS: '--enable-source-maps',\n };\n }\n\n /**\n * Initalize spying on resources given as parameter.\n * @param nodes Which reources and their children to spy on.\n */\n public spyNodes(nodes: IConstruct[]) {\n for (const node of nodes) {\n let ns = this.getAllNodes(node);\n this.internalSpyNodes(ns);\n }\n\n this.finalizeSpy();\n }\n\n /**\n * Initalize spying on resources.\n * @param filter Limit which resources to spy on.\n */\n public spy(filter?: SpyFilter) {\n let nodes = this.getAllNodes(Stack.of(this));\n\n const filterWithDefaults: Required<SpyFilter> = {\n spyLambda: true,\n spySqs: true,\n spySnsTopic: true,\n spySnsSubsription: true,\n spyEventBridge: true,\n spyEventBridgeRule: true,\n spyS3: true,\n spyDynamoDB: true,\n ...filter,\n };\n\n const CRID =\n 'AWS' +\n custom_resources.AwsCustomResource.PROVIDER_FUNCTION_UUID.replace(\n /-/gi,\n ''\n ).substring(0, 16);\n\n nodes = nodes.filter((node) => {\n if (\n // Ignore the custom resource and the Provider (as well as any other Providers using the same provider function), otherwise we cause\n // circular dependencies\n node.node.id.startsWith(CRID) ||\n node.node.id === 'Provider' ||\n // Ignore singleton functions as they can cause very odd behavior and crashes\n node instanceof SingletonFunction\n ) {\n if (this.props?.debugMode) {\n console.info(`Skipping ${node.node.id}`);\n }\n return false;\n } else if (\n filterWithDefaults.spyLambda &&\n (node instanceof lambda.Function ||\n node instanceof NodejsFunction ||\n isLambdaFunction(node))\n ) {\n return true;\n } else if (filterWithDefaults.spySnsTopic && node instanceof sns.Topic) {\n return true;\n } else if (\n filterWithDefaults.spySnsSubsription &&\n node instanceof sns.Subscription\n ) {\n return true;\n } else if (filterWithDefaults.spyS3 && node instanceof s3.Bucket) {\n return true;\n } else if (\n filterWithDefaults.spyDynamoDB &&\n node instanceof dynamoDb.Table\n ) {\n return true;\n } else if (\n filterWithDefaults.spyDynamoDB &&\n node instanceof dynamoDb.TableV2\n ) {\n return true;\n } else if (\n filterWithDefaults.spyEventBridge &&\n node instanceof events.EventBus\n ) {\n return true;\n } else if (\n filterWithDefaults.spyEventBridgeRule &&\n node instanceof events.Rule\n ) {\n return true;\n } else if (\n filterWithDefaults.spySqs &&\n node instanceof lambda.CfnEventSourceMapping\n ) {\n return true;\n } else if (\n filterWithDefaults.spySqs &&\n this.props?.spySqsWithNoSubscriptionAndDropAllMessages &&\n node instanceof sqs.Queue\n ) {\n return true;\n }\n\n return false;\n });\n\n this.internalSpyNodes(nodes);\n this.finalizeSpy();\n }\n\n private internalSpyNodes(nodes: IConstruct[]) {\n for (const node of nodes) {\n this.internalSpyNode(node);\n }\n }\n\n private finalizeSpy() {\n //set mapping property for all functions we created\n for (const func of this.lambdaSubscriptionPool) {\n func.function.addEnvironment(\n envVariableNames.SSPY_INFRA_MAPPING,\n JSON.stringify(func.mapping)\n );\n }\n\n //set mapping property for all functions we spy on\n for (const func of this.lambdasSpied) {\n func.function.addEnvironment(\n envVariableNames.SSPY_INFRA_MAPPING,\n JSON.stringify(func.mapping)\n );\n }\n\n if (this.props?.generateSpyEventsFileLocation) {\n this.writeSpyEventsClass(this.props?.generateSpyEventsFileLocation);\n }\n }\n\n private getExtensionAssetLocation() {\n let extensionAssetLocation = path.join(\n __dirname,\n '../extension/dist/layer'\n );\n\n const extensionAssetLocationAlt = path.join(\n __dirname,\n '../lib/extension/dist/layer'\n );\n\n if (!fs.existsSync(extensionAssetLocation)) {\n if (!fs.existsSync(extensionAssetLocationAlt)) {\n throw new Error(\n `Folder with assets for extension does not exists at ${extensionAssetLocation} or at ${extensionAssetLocationAlt} `\n );\n } else {\n extensionAssetLocation = extensionAssetLocationAlt;\n }\n }\n\n const extensionAssetLocationWrapper = path.join(\n extensionAssetLocation,\n 'spy-wrapper'\n );\n if (!fs.existsSync(extensionAssetLocationWrapper)) {\n throw new Error(\n `Wrapper script for extension does not exists ${extensionAssetLocation}`\n );\n }\n\n const extensionAssetLocationCode = path.join(\n extensionAssetLocation,\n `nodejs/node_modules/interceptor.js`\n );\n if (!fs.existsSync(extensionAssetLocationCode)) {\n throw new Error(\n `Code for extension does not exists ${extensionAssetLocationCode}`\n );\n }\n return extensionAssetLocation;\n }\n\n private getLanguageExtensionAssetLocation(language: string) {\n const rootDir = path.join(__dirname, '..');\n\n let extensionAssetLocation = path.join(rootDir, `extensions/${language}`);\n\n const extensionAssetLocationAlt = path.join(\n rootDir,\n `lib/extensions/${language}`\n );\n\n if (!fs.existsSync(extensionAssetLocation)) {\n if (!fs.existsSync(extensionAssetLocationAlt)) {\n throw new Error(\n `Folder with assets for extension for ${language} does not exists at ${extensionAssetLocation} or at ${extensionAssetLocationAlt} `\n );\n } else {\n extensionAssetLocation = extensionAssetLocationAlt;\n }\n }\n\n const extensionAssetLocationWrapper = path.join(\n // extensionAssetLocation.substring(\n // 0,\n // extensionAssetLocation.lastIndexOf(path.sep)\n // ),\n extensionAssetLocation,\n 'spy-wrapper'\n );\n if (!fs.existsSync(extensionAssetLocationWrapper)) {\n throw new Error(\n `Wrapper script for extension does not exists at ${extensionAssetLocationWrapper}`\n );\n }\n\n return extensionAssetLocation;\n }\n\n /**\n * Write SpyEvents class, which helps with writing the code for tests.\n * @param fileLocation\n */\n private writeSpyEventsClass(fileLocation: string) {\n fs.mkdirSync(path.dirname(fileLocation), { recursive: true });\n\n const properties = this.serviceKeys\n .map((sk) => ` ${sk.replace(/#/g, '')}: '${sk}' = '${sk}';\\n`)\n .join('');\n\n const code = `/* eslint-disable */\\nexport class ServerlessSpyEvents {\\n${properties}}\\n`;\n\n fs.writeFileSync(fileLocation, code);\n }\n\n private getAllNodes(parent: IConstruct) {\n const nodes: IConstruct[] = [];\n nodes.push(parent);\n this.getAllNodesRecursive(parent, nodes);\n return nodes;\n }\n\n private getAllNodesRecursive(parent: IConstruct, nodes: IConstruct[]) {\n for (const node of parent.node.children) {\n nodes.push(node);\n this.getAllNodesRecursive(node, nodes);\n }\n }\n\n private internalSpyNode(node: IConstruct) {\n if (this.spiedNodes.includes(node)) {\n return;\n }\n\n this.spiedNodes.push(node);\n\n if (this.createdResourcesBySSpy.includes(node)) {\n return;\n }\n\n if (this.lambdaSubscriptionPool.find((s) => s.function === node)) {\n return;\n }\n\n if (this.props?.debugMode) {\n console.info('Spy on node', this.getConstructName(node));\n }\n\n if (\n node instanceof lambda.Function ||\n node instanceof NodejsFunction ||\n isLambdaFunction(node)\n ) {\n this.internalSpyLambda(node);\n } else if (node instanceof sns.Topic) {\n this.internalSpySnsTopic(node);\n } else if (node instanceof sns.Subscription) {\n this.internalSpySnsSubscription(node);\n } else if (node instanceof s3.Bucket) {\n this.internalSpyS3(node);\n } else if (node instanceof dynamoDb.Table) {\n this.internalSpyDynamodb(node);\n } else if (node instanceof dynamoDb.TableV2) {\n this.internalSpyDynamodb(node);\n } else if (node instanceof events.EventBus) {\n this.internalSpyEventBus(node);\n } else if (node instanceof events.Rule) {\n this.internalSpyEventBusRule(node);\n } else if (node instanceof lambda.CfnEventSourceMapping) {\n this.internalSpySqs(node);\n } else if (node instanceof sqs.Queue) {\n if (this.props?.spySqsWithNoSubscriptionAndDropAllMessages) {\n this.internalSpySpySqsWithNoSubscription(node);\n }\n }\n }\n\n private getExtensionForRuntime(\n runtime: lambda.Runtime,\n architecture: lambda.Architecture\n ): { layer: lambda.ILayerVersion; spyWrapperPath: string } | undefined {\n const layerKey =\n `sspy_extension_${runtime.toString()}_${architecture.name.toString()}`.replace(\n /\\./g,\n '_'\n );\n\n let layer = this.layerMap[layerKey];\n let spyWrapperPath = '/opt/spy-wrapper';\n\n switch (runtime.name) {\n case lambda.Runtime.PYTHON_3_8.name:\n case lambda.Runtime.PYTHON_3_9.name:\n case lambda.Runtime.PYTHON_3_10.name:\n case lambda.Runtime.PYTHON_3_11.name:\n case lambda.Runtime.PYTHON_3_12.name:\n spyWrapperPath = '/opt/python/spy-wrapper';\n layer =\n layer ||\n new PythonLayerVersion(this, layerKey, {\n compatibleRuntimes: [runtime],\n compatibleArchitectures: [architecture],\n entry: this.getLanguageExtensionAssetLocation('python'),\n bundling: {\n bundlingFileAccess: BundlingFileAccess.VOLUME_COPY,\n },\n });\n break;\n case lambda.Runtime.NODEJS_12_X.name:\n case lambda.Runtime.NODEJS_14_X.name:\n case lambda.Runtime.NODEJS_16_X.name:\n case lambda.Runtime.NODEJS_18_X.name:\n case lambda.Runtime.NODEJS_20_X.name:\n case lambda.Runtime.NODEJS_22_X.name:\n layer =\n layer ||\n new lambda.LayerVersion(this, layerKey, {\n compatibleRuntimes: [runtime],\n compatibleArchitectures: [architecture],\n code: lambda.Code.fromAsset(this.getExtensionAssetLocation()),\n });\n break;\n default:\n console.log(`No extensions available for ${runtime.toString()}`);\n return undefined;\n }\n\n this.layerMap[layerKey] = layer;\n this.createdResourcesBySSpy.push(layer);\n return { layer, spyWrapperPath };\n }\n\n private internalSpySpySqsWithNoSubscription(queue: sqs.Queue) {\n const subscription = this.findElement<lambda.CfnEventSourceMapping>(\n (n: IConstruct) =>\n n instanceof lambda.CfnEventSourceMapping &&\n (n as lambda.CfnEventSourceMapping).eventSourceArn === queue.queueArn\n );\n\n if (subscription) {\n return; //already have subscription\n }\n\n const queueName = this.getConstructName(queue);\n const func = new NodejsFunction(\n this,\n `${queueName}SqsSubscriptionAndDropAllMessages`,\n {\n memorySize: 512,\n timeout: Duration.seconds(5),\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'handler',\n entry: this.getAssetLocation(\n 'functions/sqsSubscriptionAndDropAllMessages.js'\n ),\n environment: this.getDefaultLambdaEnvironmentVariables(),\n }\n );\n func.addEventSource(new SqsEventSource(queue));\n this.setupForIoT(func);\n const { layer, spyWrapperPath } = this.getExtensionForRuntime(\n func.runtime,\n func.architecture\n )!;\n func.addLayers(layer);\n\n func.addEnvironment('AWS_LAMBDA_EXEC_WRAPPER', spyWrapperPath);\n\n if (this.props?.debugMode) {\n func.addEnvironment(envVariableNames.SSPY_DEBUG, 'true');\n }\n\n this.createdResourcesBySSpy.push(func);\n\n const serviceKey = `Sqs#${queueName}`;\n\n this.addMappingToFunction(func, {\n key: queue.queueArn,\n value: serviceKey,\n });\n\n this.serviceKeys.push(serviceKey);\n func.addEnvironment(envVariableNames.SSPY_SUBSCRIBED_TO_SQS, 'true');\n }\n\n private internalSpySqs(node: lambda.CfnEventSourceMapping) {\n const queue = this.findElement<sqs.Queue>(\n (n: IConstruct) =>\n n instanceof sqs.Queue &&\n (n as sqs.Queue).queueArn === node.eventSourceArn\n );\n\n const func = this.findElement<lambda.Function>(\n (n: IConstruct) =>\n n instanceof lambda.Function &&\n (n as lambda.Function).functionName === node.functionName\n );\n\n if (queue && func) {\n const queueName = this.getConstructName(queue);\n\n const serviceKey = `Sqs#${queueName}`;\n\n this.addMappingToFunction(func, {\n key: queue.queueArn,\n value: serviceKey,\n });\n\n this.serviceKeys.push(serviceKey);\n func.addEnvironment(envVariableNames.SSPY_SUBSCRIBED_TO_SQS, 'true');\n }\n }\n\n private createFunctionForSubscription(index: number) {\n const func = new lambdaNode.NodejsFunction(this, `Subscription${index}`, {\n memorySize: 512,\n timeout: Duration.seconds(5),\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'handler',\n entry: this.getAssetLocation('functions/sendMessage.js'),\n environment: {\n NODE_OPTIONS: '--enable-source-maps',\n },\n });\n this.setupForIoT(func);\n return func;\n }\n\n private internalSpyS3(s3Bucket: s3.Bucket) {\n s3Bucket.addEventNotification(\n s3.EventType.OBJECT_CREATED_PUT,\n new s3notif.LambdaDestination(this.lambdaSubscriptionMain.function)\n );\n\n const name = this.getConstructName(s3Bucket);\n\n const serviceKey = `S3#${name}`;\n this.lambdaSubscriptionMain.mapping[s3Bucket.bucketArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyDynamodb(table: dynamoDb.Table | dynamoDb.TableV2) {\n // enable DynamoDB streams with a hack\n (table.node.defaultChild as dynamoDb.CfnTable).streamSpecification = {\n streamViewType: dynamoDb.StreamViewType.NEW_AND_OLD_IMAGES,\n };\n try {\n (table as any).tableStreamArn = (\n table.node.defaultChild as dynamoDb.CfnTable\n ).attrStreamArn;\n } catch (e) {\n // Property is read-only in newer CDK versions, skip the assignment\n if (!(e instanceof TypeError && e.message.includes('only a getter'))) {\n throw e; // Re-throw if it's a different error\n }\n }\n\n this.lambdaSubscriptionMain.function.addEventSource(\n new dynamoDbStream.DynamoEventSource(table, {\n startingPosition: lambda.StartingPosition.LATEST,\n batchSize: 1,\n retryAttempts: 0,\n })\n );\n\n const name = this.getConstructName(table);\n\n const serviceKey = `DynamoDB#${name}`;\n this.lambdaSubscriptionMain.mapping[table.tableArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyEventBusRule(rule: events.Rule) {\n const { eventBusName } = rule.node.defaultChild as events.CfnRule;\n let bridgeName = 'Default';\n if (!!eventBusName) {\n const eventBridge = this.getEventBridge(eventBusName);\n\n if (!eventBridge) {\n throw new Error(`Can not find EventBridge with name \"${eventBusName}\"`);\n }\n bridgeName = this.getConstructName(eventBridge);\n }\n\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.usedForEventBridge\n );\n functionSubscription.usedForEventBridge = true;\n\n rule.addTarget(new targets.LambdaFunction(functionSubscription.function));\n\n const ruleName = this.getConstructName(rule);\n const serviceKey = `EventBridgeRule#${bridgeName}#${ruleName}`;\n functionSubscription.mapping.eventBridge = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyEventBus(eventBus: events.EventBus) {\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.usedForEventBridge\n );\n functionSubscription.usedForEventBridge = true;\n\n const bridgeName = this.getConstructName(eventBus);\n const rule = new events.Rule(this, `RuleAll${bridgeName}`, {\n eventBus,\n eventPattern: { version: ['0'] },\n targets: [new targets.LambdaFunction(functionSubscription.function)],\n });\n\n this.createdResourcesBySSpy.push(rule);\n const serviceKey = `EventBridge#${bridgeName}`;\n functionSubscription.mapping.eventBridge = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpySnsTopic(topic: sns.Topic) {\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.subsribedTopics.includes(topic)\n );\n\n const subscription = topic.addSubscription(\n new snsSubs.LambdaSubscription(functionSubscription.function)\n );\n this.createdResourcesBySSpy.push(subscription);\n const topicName = this.getConstructName(topic);\n const serviceKey = `SnsTopic#${topicName}`;\n functionSubscription.mapping[topic.topicArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n functionSubscription.subsribedTopics.push(topic);\n }\n\n private internalSpySnsSubscription(subscription: sns.Subscription) {\n if (!subscription.node.scope) {\n return;\n }\n\n const topic = this.getTopic(\n (subscription.node.defaultChild as sns.CfnSubscription).topicArn\n );\n\n if (!topic) {\n throw new Error('Can not find Topic');\n }\n\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.subsribedTopics.includes(topic)\n );\n\n const { filterPolicy } = subscription.node\n .defaultChild as sns.CfnSubscription;\n\n const subscriptionClone = topic.addSubscription(\n new snsSubs.LambdaSubscription(functionSubscription.function)\n );\n (subscriptionClone.node.defaultChild as sns.CfnSubscription).filterPolicy =\n filterPolicy;\n\n this.createdResourcesBySSpy.push(subscriptionClone);\n\n const topicName = this.getConstructName(topic);\n const targetName = this.getConstructName(subscription.node.scope);\n\n functionSubscription.subsribedTopics.push(topic);\n const serviceKey = `SnsSubscription#${topicName}#${targetName}`;\n functionSubscription.mapping[topic.topicArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private provideFunctionForSubscription(\n filterFunction?: (subscription: LambdaSubscription) => boolean\n ) {\n let functionSubscription: LambdaSubscription | undefined;\n\n if (filterFunction) {\n functionSubscription = this.lambdaSubscriptionPool.find(filterFunction);\n } else if (this.lambdaSubscriptionPool.length > 0) {\n functionSubscription = this.lambdaSubscriptionPool[0];\n }\n\n if (!functionSubscription) {\n functionSubscription = {\n subsribedTopics: [],\n usedForEventBridge: false,\n mapping: {},\n function: this.createFunctionForSubscription(\n this.lambdaSubscriptionPool.length\n ),\n };\n this.lambdaSubscriptionPool.push(functionSubscription);\n }\n return functionSubscription;\n }\n\n private setupForIoT(func: lambda.Function) {\n func.addEnvironment(\n envVariableNames.SSPY_ROOT_STACK,\n this.cleanName(this.findRootStack(Stack.of(this)).node.id)\n );\n func.addEnvironment(envVariableNames.SSPY_IOT_ENDPOINT, this.iotEndpoint);\n\n func.addToRolePolicy(\n new aws_iam.PolicyStatement({\n actions: ['iot:*'],\n effect: Effect.ALLOW,\n resources: ['*'],\n })\n );\n }\n\n private internalSpyLambda(func: lambda.Function) {\n const { layer, spyWrapperPath } = this.getExtensionForRuntime(\n func.runtime,\n func.architecture || Architecture.X86_64\n )!;\n if (!layer) {\n return;\n }\n func.addLayers(layer);\n\n const functionName = this.getConstructName(func);\n\n func.addEnvironment(envVariableNames.SSPY_FUNCTION_NAME, functionName);\n func.addEnvironment('AWS_LAMBDA_EXEC_WRAPPER', spyWrapperPath);\n\n if (this.props?.debugMode) {\n func.addEnvironment(envVariableNames.SSPY_DEBUG, 'true');\n }\n\n this.setupForIoT(func);\n\n this.serviceKeys.push(`Function#${functionName}#Request`);\n this.serviceKeys.push(`Function#${functionName}#Error`);\n this.serviceKeys.push(`Function#${functionName}#Console`);\n this.serviceKeys.push(`Function#${functionName}#Response`);\n\n this.addMappingToFunction(func);\n }\n\n public getConstructName(construct: IConstruct) {\n let constructName = construct.node.path;\n const { node } = Stack.of(this);\n\n if (constructName.startsWith(node.id)) {\n constructName = constructName.substring(node.id.length + 1);\n }\n\n return this.cleanName(constructName);\n }\n\n private cleanName(name: string) {\n //snake case to camel case including dash and first letter to upper case\n return name\n .replace(/[-_]+/g, ' ')\n .replace(/[^\\w\\s]/g, '')\n .replace(/\\s(.)/g, ($1) => $1.toUpperCase())\n .replace(/\\s/g, '')\n .replace(/^(.)/, ($1) => $1.toUpperCase());\n }\n\n private getTopic(topicArn: string): sns.Topic | undefined {\n const topic = this.findElement<sns.Topic>(\n (node: IConstruct) =>\n node instanceof sns.Topic && (node as sns.Topic).topicArn === topicArn\n );\n\n return topic;\n }\n\n private getEventBridge(eventBusName: string): events.IEventBus | undefined {\n const eventBridge = this.findElement<events.IEventBus>(\n (node: IConstruct) =>\n (node instanceof events.EventBus ||\n node.constructor.name === 'ImportedEventBus') &&\n (node as events.IEventBus).eventBusName === eventBusName\n );\n\n return eventBridge;\n }\n\n private findRootStack(stack: Stack): Stack {\n if (stack.nested) {\n const parentStack = (stack as NestedStack).nestedStackParent;\n if (parentStack) return this.findRootStack(parentStack);\n return stack;\n } else {\n return stack;\n }\n }\n\n private findElement<T extends IConstruct = IConstruct>(\n filterFunc: (node: IConstruct) => boolean,\n parent?: IConstruct\n ): T | undefined {\n if (!parent) {\n parent = this.findRootStack(Stack.of(this));\n }\n\n for (const node of parent.node.children) {\n if (filterFunc(node)) {\n return node as T;\n }\n const elementFoundInChild = this.findElement<T>(filterFunc, node);\n if (elementFoundInChild) {\n return elementFoundInChild;\n }\n }\n\n return undefined;\n }\n\n private addMappingToFunction(\n func: lambda.Function,\n keyValue?: { key: string; value: string }\n ) {\n for (const fs of this.lambdasSpied) {\n if (fs.function === func) {\n if (keyValue) {\n fs.mapping[keyValue.key] = keyValue.value;\n }\n return;\n }\n }\n\n const fs: LambdaSpied = {\n function: func,\n mapping: {},\n };\n\n if (keyValue) {\n fs.mapping[keyValue.key] = keyValue.value;\n }\n\n this.lambdasSpied.push(fs);\n }\n\n private getAssetLocation(location: string) {\n const loc = path.join(__dirname, '../lib/' + location);\n\n if (fs.existsSync(loc)) {\n return loc;\n }\n\n const loc2 = path.join(__dirname, '../../lib/' + location);\n\n if (fs.existsSync(loc2)) {\n return loc2;\n }\n\n throw new Error(`Location ${loc} and ${loc2} does not exists.`);\n }\n}\n\ntype LambdaSubscription = {\n subsribedTopics: sns.Topic[];\n usedForEventBridge: boolean;\n function: lambdaNode.NodejsFunction;\n mapping: Record<string, string>;\n};\n\ntype LambdaSpied = {\n function: lambda.Function;\n mapping: Record<string, string>;\n};\n"],"mappings":"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"}
|
|
@@ -281,8 +281,11 @@ var ServerlessSpy = class extends Construct {
|
|
|
281
281
|
}
|
|
282
282
|
internalSpyDynamodb(table) {
|
|
283
283
|
table.node.defaultChild.streamSpecification = { streamViewType: dynamoDb.StreamViewType.NEW_AND_OLD_IMAGES };
|
|
284
|
-
|
|
285
|
-
|
|
284
|
+
try {
|
|
285
|
+
table.tableStreamArn = table.node.defaultChild.attrStreamArn;
|
|
286
|
+
} catch (e) {
|
|
287
|
+
if (!(e instanceof TypeError && e.message.includes("only a getter"))) throw e;
|
|
288
|
+
}
|
|
286
289
|
this.lambdaSubscriptionMain.function.addEventSource(new dynamoDbStream.DynamoEventSource(table, {
|
|
287
290
|
startingPosition: lambda.StartingPosition.LATEST,
|
|
288
291
|
batchSize: 1,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServerlessSpy.mjs","names":["props?: ServerlessSpyProps","filterWithDefaults: Required<SpyFilter>","nodes: IConstruct[]","functionSubscription: LambdaSubscription | undefined","fs","fs: LambdaSpied"],"sources":["../../src/ServerlessSpy.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { PythonLayerVersion } from '@aws-cdk/aws-lambda-python-alpha';\nimport {\n aws_iam,\n BundlingFileAccess,\n CfnOutput,\n custom_resources,\n Duration,\n NestedStack,\n Stack,\n} from 'aws-cdk-lib';\nimport * as dynamoDb from 'aws-cdk-lib/aws-dynamodb';\nimport * as events from 'aws-cdk-lib/aws-events';\nimport * as targets from 'aws-cdk-lib/aws-events-targets';\nimport { Effect } from 'aws-cdk-lib/aws-iam';\nimport * as lambda from 'aws-cdk-lib/aws-lambda';\nimport {\n Architecture,\n ILayerVersion,\n SingletonFunction,\n} from 'aws-cdk-lib/aws-lambda';\nimport * as dynamoDbStream from 'aws-cdk-lib/aws-lambda-event-sources';\nimport { SqsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';\nimport * as lambdaNode from 'aws-cdk-lib/aws-lambda-nodejs';\nimport { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';\nimport * as s3 from 'aws-cdk-lib/aws-s3';\nimport * as s3notif from 'aws-cdk-lib/aws-s3-notifications';\nimport * as sns from 'aws-cdk-lib/aws-sns';\nimport * as snsSubs from 'aws-cdk-lib/aws-sns-subscriptions';\nimport * as sqs from 'aws-cdk-lib/aws-sqs';\nimport { Construct, IConstruct } from 'constructs';\nimport { envVariableNames } from './common/envVariableNames';\n\nexport interface ServerlessSpyProps {\n readonly generateSpyEventsFileLocation?: string;\n readonly spySqsWithNoSubscriptionAndDropAllMessages?: boolean;\n readonly debugMode?: boolean;\n}\n\nexport interface SpyFilter {\n readonly spyLambda?: boolean;\n readonly spySqs?: boolean;\n readonly spySnsTopic?: boolean;\n readonly spySnsSubsription?: boolean;\n readonly spyEventBridge?: boolean;\n readonly spyEventBridgeRule?: boolean;\n readonly spyS3?: boolean;\n readonly spyDynamoDB?: boolean;\n}\n\nconst isLambdaFunction = (node: IConstruct): node is lambda.Function =>\n 'functionName' in node && 'functionArn' in node && 'runtime' in node;\n\nconst serverlessSpyIotEndpointCrNamePrefix = 'ServerlessSpyIotEndpoint';\n\nexport class ServerlessSpy extends Construct {\n private createdResourcesBySSpy: IConstruct[] = [];\n private lambdaSubscriptionPool: LambdaSubscription[] = [];\n private lambdaSubscriptionMain: LambdaSubscription;\n private lambdasSpied: LambdaSpied[] = [];\n public serviceKeys: string[] = [];\n private spiedNodes: IConstruct[] = [];\n private layerMap: Partial<Record<string, ILayerVersion>> = {};\n private readonly iotEndpoint: string;\n\n constructor(\n scope: Construct,\n id: string,\n private props?: ServerlessSpyProps\n ) {\n super(scope, id);\n\n const rootStack = this.cleanName(\n this.findRootStack(Stack.of(this)).node.id\n );\n\n const getIoTEndpoint = new custom_resources.AwsCustomResource(\n this,\n serverlessSpyIotEndpointCrNamePrefix,\n {\n onCreate: {\n service: 'Iot',\n action: 'describeEndpoint',\n physicalResourceId:\n custom_resources.PhysicalResourceId.fromResponse('endpointAddress'),\n parameters: {\n endpointType: 'iot:Data-ATS',\n },\n },\n onUpdate: {\n service: 'Iot',\n action: 'describeEndpoint',\n physicalResourceId:\n custom_resources.PhysicalResourceId.fromResponse('endpointAddress'),\n parameters: {\n endpointType: 'iot:Data-ATS',\n },\n },\n installLatestAwsSdk: false,\n policy: custom_resources.AwsCustomResourcePolicy.fromSdkCalls({\n resources: custom_resources.AwsCustomResourcePolicy.ANY_RESOURCE,\n }),\n functionName: serverlessSpyIotEndpointCrNamePrefix + rootStack,\n }\n );\n this.iotEndpoint = getIoTEndpoint.getResponseField('endpointAddress');\n\n this.createdResourcesBySSpy.push(getIoTEndpoint);\n\n new CfnOutput(this, 'ServerlessSpyIoTEndpoint', {\n key: 'ServerlessSpyWsUrl',\n value: `${this.iotEndpoint}/${rootStack}`,\n });\n\n this.lambdaSubscriptionMain = this.provideFunctionForSubscription();\n }\n\n private getDefaultLambdaEnvironmentVariables(): { [key: string]: string } {\n return {\n NODE_OPTIONS: '--enable-source-maps',\n };\n }\n\n /**\n * Initalize spying on resources given as parameter.\n * @param nodes Which reources and their children to spy on.\n */\n public spyNodes(nodes: IConstruct[]) {\n for (const node of nodes) {\n let ns = this.getAllNodes(node);\n this.internalSpyNodes(ns);\n }\n\n this.finalizeSpy();\n }\n\n /**\n * Initalize spying on resources.\n * @param filter Limit which resources to spy on.\n */\n public spy(filter?: SpyFilter) {\n let nodes = this.getAllNodes(Stack.of(this));\n\n const filterWithDefaults: Required<SpyFilter> = {\n spyLambda: true,\n spySqs: true,\n spySnsTopic: true,\n spySnsSubsription: true,\n spyEventBridge: true,\n spyEventBridgeRule: true,\n spyS3: true,\n spyDynamoDB: true,\n ...filter,\n };\n\n const CRID =\n 'AWS' +\n custom_resources.AwsCustomResource.PROVIDER_FUNCTION_UUID.replace(\n /-/gi,\n ''\n ).substring(0, 16);\n\n nodes = nodes.filter((node) => {\n if (\n // Ignore the custom resource and the Provider (as well as any other Providers using the same provider function), otherwise we cause\n // circular dependencies\n node.node.id.startsWith(CRID) ||\n node.node.id === 'Provider' ||\n // Ignore singleton functions as they can cause very odd behavior and crashes\n node instanceof SingletonFunction\n ) {\n if (this.props?.debugMode) {\n console.info(`Skipping ${node.node.id}`);\n }\n return false;\n } else if (\n filterWithDefaults.spyLambda &&\n (node instanceof lambda.Function ||\n node instanceof NodejsFunction ||\n isLambdaFunction(node))\n ) {\n return true;\n } else if (filterWithDefaults.spySnsTopic && node instanceof sns.Topic) {\n return true;\n } else if (\n filterWithDefaults.spySnsSubsription &&\n node instanceof sns.Subscription\n ) {\n return true;\n } else if (filterWithDefaults.spyS3 && node instanceof s3.Bucket) {\n return true;\n } else if (\n filterWithDefaults.spyDynamoDB &&\n node instanceof dynamoDb.Table\n ) {\n return true;\n } else if (\n filterWithDefaults.spyDynamoDB &&\n node instanceof dynamoDb.TableV2\n ) {\n return true;\n } else if (\n filterWithDefaults.spyEventBridge &&\n node instanceof events.EventBus\n ) {\n return true;\n } else if (\n filterWithDefaults.spyEventBridgeRule &&\n node instanceof events.Rule\n ) {\n return true;\n } else if (\n filterWithDefaults.spySqs &&\n node instanceof lambda.CfnEventSourceMapping\n ) {\n return true;\n } else if (\n filterWithDefaults.spySqs &&\n this.props?.spySqsWithNoSubscriptionAndDropAllMessages &&\n node instanceof sqs.Queue\n ) {\n return true;\n }\n\n return false;\n });\n\n this.internalSpyNodes(nodes);\n this.finalizeSpy();\n }\n\n private internalSpyNodes(nodes: IConstruct[]) {\n for (const node of nodes) {\n this.internalSpyNode(node);\n }\n }\n\n private finalizeSpy() {\n //set mapping property for all functions we created\n for (const func of this.lambdaSubscriptionPool) {\n func.function.addEnvironment(\n envVariableNames.SSPY_INFRA_MAPPING,\n JSON.stringify(func.mapping)\n );\n }\n\n //set mapping property for all functions we spy on\n for (const func of this.lambdasSpied) {\n func.function.addEnvironment(\n envVariableNames.SSPY_INFRA_MAPPING,\n JSON.stringify(func.mapping)\n );\n }\n\n if (this.props?.generateSpyEventsFileLocation) {\n this.writeSpyEventsClass(this.props?.generateSpyEventsFileLocation);\n }\n }\n\n private getExtensionAssetLocation() {\n let extensionAssetLocation = path.join(\n __dirname,\n '../extension/dist/layer'\n );\n\n const extensionAssetLocationAlt = path.join(\n __dirname,\n '../lib/extension/dist/layer'\n );\n\n if (!fs.existsSync(extensionAssetLocation)) {\n if (!fs.existsSync(extensionAssetLocationAlt)) {\n throw new Error(\n `Folder with assets for extension does not exists at ${extensionAssetLocation} or at ${extensionAssetLocationAlt} `\n );\n } else {\n extensionAssetLocation = extensionAssetLocationAlt;\n }\n }\n\n const extensionAssetLocationWrapper = path.join(\n extensionAssetLocation,\n 'spy-wrapper'\n );\n if (!fs.existsSync(extensionAssetLocationWrapper)) {\n throw new Error(\n `Wrapper script for extension does not exists ${extensionAssetLocation}`\n );\n }\n\n const extensionAssetLocationCode = path.join(\n extensionAssetLocation,\n `nodejs/node_modules/interceptor.js`\n );\n if (!fs.existsSync(extensionAssetLocationCode)) {\n throw new Error(\n `Code for extension does not exists ${extensionAssetLocationCode}`\n );\n }\n return extensionAssetLocation;\n }\n\n private getLanguageExtensionAssetLocation(language: string) {\n const rootDir = path.join(__dirname, '..');\n\n let extensionAssetLocation = path.join(rootDir, `extensions/${language}`);\n\n const extensionAssetLocationAlt = path.join(\n rootDir,\n `lib/extensions/${language}`\n );\n\n if (!fs.existsSync(extensionAssetLocation)) {\n if (!fs.existsSync(extensionAssetLocationAlt)) {\n throw new Error(\n `Folder with assets for extension for ${language} does not exists at ${extensionAssetLocation} or at ${extensionAssetLocationAlt} `\n );\n } else {\n extensionAssetLocation = extensionAssetLocationAlt;\n }\n }\n\n const extensionAssetLocationWrapper = path.join(\n // extensionAssetLocation.substring(\n // 0,\n // extensionAssetLocation.lastIndexOf(path.sep)\n // ),\n extensionAssetLocation,\n 'spy-wrapper'\n );\n if (!fs.existsSync(extensionAssetLocationWrapper)) {\n throw new Error(\n `Wrapper script for extension does not exists at ${extensionAssetLocationWrapper}`\n );\n }\n\n return extensionAssetLocation;\n }\n\n /**\n * Write SpyEvents class, which helps with writing the code for tests.\n * @param fileLocation\n */\n private writeSpyEventsClass(fileLocation: string) {\n fs.mkdirSync(path.dirname(fileLocation), { recursive: true });\n\n const properties = this.serviceKeys\n .map((sk) => ` ${sk.replace(/#/g, '')}: '${sk}' = '${sk}';\\n`)\n .join('');\n\n const code = `/* eslint-disable */\\nexport class ServerlessSpyEvents {\\n${properties}}\\n`;\n\n fs.writeFileSync(fileLocation, code);\n }\n\n private getAllNodes(parent: IConstruct) {\n const nodes: IConstruct[] = [];\n nodes.push(parent);\n this.getAllNodesRecursive(parent, nodes);\n return nodes;\n }\n\n private getAllNodesRecursive(parent: IConstruct, nodes: IConstruct[]) {\n for (const node of parent.node.children) {\n nodes.push(node);\n this.getAllNodesRecursive(node, nodes);\n }\n }\n\n private internalSpyNode(node: IConstruct) {\n if (this.spiedNodes.includes(node)) {\n return;\n }\n\n this.spiedNodes.push(node);\n\n if (this.createdResourcesBySSpy.includes(node)) {\n return;\n }\n\n if (this.lambdaSubscriptionPool.find((s) => s.function === node)) {\n return;\n }\n\n if (this.props?.debugMode) {\n console.info('Spy on node', this.getConstructName(node));\n }\n\n if (\n node instanceof lambda.Function ||\n node instanceof NodejsFunction ||\n isLambdaFunction(node)\n ) {\n this.internalSpyLambda(node);\n } else if (node instanceof sns.Topic) {\n this.internalSpySnsTopic(node);\n } else if (node instanceof sns.Subscription) {\n this.internalSpySnsSubscription(node);\n } else if (node instanceof s3.Bucket) {\n this.internalSpyS3(node);\n } else if (node instanceof dynamoDb.Table) {\n this.internalSpyDynamodb(node);\n } else if (node instanceof dynamoDb.TableV2) {\n this.internalSpyDynamodb(node);\n } else if (node instanceof events.EventBus) {\n this.internalSpyEventBus(node);\n } else if (node instanceof events.Rule) {\n this.internalSpyEventBusRule(node);\n } else if (node instanceof lambda.CfnEventSourceMapping) {\n this.internalSpySqs(node);\n } else if (node instanceof sqs.Queue) {\n if (this.props?.spySqsWithNoSubscriptionAndDropAllMessages) {\n this.internalSpySpySqsWithNoSubscription(node);\n }\n }\n }\n\n private getExtensionForRuntime(\n runtime: lambda.Runtime,\n architecture: lambda.Architecture\n ): { layer: lambda.ILayerVersion; spyWrapperPath: string } | undefined {\n const layerKey =\n `sspy_extension_${runtime.toString()}_${architecture.name.toString()}`.replace(\n /\\./g,\n '_'\n );\n\n let layer = this.layerMap[layerKey];\n let spyWrapperPath = '/opt/spy-wrapper';\n\n switch (runtime.name) {\n case lambda.Runtime.PYTHON_3_8.name:\n case lambda.Runtime.PYTHON_3_9.name:\n case lambda.Runtime.PYTHON_3_10.name:\n case lambda.Runtime.PYTHON_3_11.name:\n case lambda.Runtime.PYTHON_3_12.name:\n spyWrapperPath = '/opt/python/spy-wrapper';\n layer =\n layer ||\n new PythonLayerVersion(this, layerKey, {\n compatibleRuntimes: [runtime],\n compatibleArchitectures: [architecture],\n entry: this.getLanguageExtensionAssetLocation('python'),\n bundling: {\n bundlingFileAccess: BundlingFileAccess.VOLUME_COPY,\n },\n });\n break;\n case lambda.Runtime.NODEJS_12_X.name:\n case lambda.Runtime.NODEJS_14_X.name:\n case lambda.Runtime.NODEJS_16_X.name:\n case lambda.Runtime.NODEJS_18_X.name:\n case lambda.Runtime.NODEJS_20_X.name:\n case lambda.Runtime.NODEJS_22_X.name:\n layer =\n layer ||\n new lambda.LayerVersion(this, layerKey, {\n compatibleRuntimes: [runtime],\n compatibleArchitectures: [architecture],\n code: lambda.Code.fromAsset(this.getExtensionAssetLocation()),\n });\n break;\n default:\n console.log(`No extensions available for ${runtime.toString()}`);\n return undefined;\n }\n\n this.layerMap[layerKey] = layer;\n this.createdResourcesBySSpy.push(layer);\n return { layer, spyWrapperPath };\n }\n\n private internalSpySpySqsWithNoSubscription(queue: sqs.Queue) {\n const subscription = this.findElement<lambda.CfnEventSourceMapping>(\n (n: IConstruct) =>\n n instanceof lambda.CfnEventSourceMapping &&\n (n as lambda.CfnEventSourceMapping).eventSourceArn === queue.queueArn\n );\n\n if (subscription) {\n return; //already have subscription\n }\n\n const queueName = this.getConstructName(queue);\n const func = new NodejsFunction(\n this,\n `${queueName}SqsSubscriptionAndDropAllMessages`,\n {\n memorySize: 512,\n timeout: Duration.seconds(5),\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'handler',\n entry: this.getAssetLocation(\n 'functions/sqsSubscriptionAndDropAllMessages.js'\n ),\n environment: this.getDefaultLambdaEnvironmentVariables(),\n }\n );\n func.addEventSource(new SqsEventSource(queue));\n this.setupForIoT(func);\n const { layer, spyWrapperPath } = this.getExtensionForRuntime(\n func.runtime,\n func.architecture\n )!;\n func.addLayers(layer);\n\n func.addEnvironment('AWS_LAMBDA_EXEC_WRAPPER', spyWrapperPath);\n\n if (this.props?.debugMode) {\n func.addEnvironment(envVariableNames.SSPY_DEBUG, 'true');\n }\n\n this.createdResourcesBySSpy.push(func);\n\n const serviceKey = `Sqs#${queueName}`;\n\n this.addMappingToFunction(func, {\n key: queue.queueArn,\n value: serviceKey,\n });\n\n this.serviceKeys.push(serviceKey);\n func.addEnvironment(envVariableNames.SSPY_SUBSCRIBED_TO_SQS, 'true');\n }\n\n private internalSpySqs(node: lambda.CfnEventSourceMapping) {\n const queue = this.findElement<sqs.Queue>(\n (n: IConstruct) =>\n n instanceof sqs.Queue &&\n (n as sqs.Queue).queueArn === node.eventSourceArn\n );\n\n const func = this.findElement<lambda.Function>(\n (n: IConstruct) =>\n n instanceof lambda.Function &&\n (n as lambda.Function).functionName === node.functionName\n );\n\n if (queue && func) {\n const queueName = this.getConstructName(queue);\n\n const serviceKey = `Sqs#${queueName}`;\n\n this.addMappingToFunction(func, {\n key: queue.queueArn,\n value: serviceKey,\n });\n\n this.serviceKeys.push(serviceKey);\n func.addEnvironment(envVariableNames.SSPY_SUBSCRIBED_TO_SQS, 'true');\n }\n }\n\n private createFunctionForSubscription(index: number) {\n const func = new lambdaNode.NodejsFunction(this, `Subscription${index}`, {\n memorySize: 512,\n timeout: Duration.seconds(5),\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'handler',\n entry: this.getAssetLocation('functions/sendMessage.js'),\n environment: {\n NODE_OPTIONS: '--enable-source-maps',\n },\n });\n this.setupForIoT(func);\n return func;\n }\n\n private internalSpyS3(s3Bucket: s3.Bucket) {\n s3Bucket.addEventNotification(\n s3.EventType.OBJECT_CREATED_PUT,\n new s3notif.LambdaDestination(this.lambdaSubscriptionMain.function)\n );\n\n const name = this.getConstructName(s3Bucket);\n\n const serviceKey = `S3#${name}`;\n this.lambdaSubscriptionMain.mapping[s3Bucket.bucketArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyDynamodb(table: dynamoDb.Table | dynamoDb.TableV2) {\n // enable DynamoDB streams with a hack\n (table.node.defaultChild as dynamoDb.CfnTable).streamSpecification = {\n streamViewType: dynamoDb.StreamViewType.NEW_AND_OLD_IMAGES,\n };\n var tableStreamArnDescriptor = Object.getOwnPropertyDescriptor(\n table,\n 'tableStreamArn'\n );\n\n if (\n tableStreamArnDescriptor === undefined ||\n tableStreamArnDescriptor.get === undefined\n ) {\n (table as any).tableStreamArn = (\n table.node.defaultChild as dynamoDb.CfnTable\n ).attrStreamArn;\n }\n\n this.lambdaSubscriptionMain.function.addEventSource(\n new dynamoDbStream.DynamoEventSource(table, {\n startingPosition: lambda.StartingPosition.LATEST,\n batchSize: 1,\n retryAttempts: 0,\n })\n );\n\n const name = this.getConstructName(table);\n\n const serviceKey = `DynamoDB#${name}`;\n this.lambdaSubscriptionMain.mapping[table.tableArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyEventBusRule(rule: events.Rule) {\n const { eventBusName } = rule.node.defaultChild as events.CfnRule;\n let bridgeName = 'Default';\n if (!!eventBusName) {\n const eventBridge = this.getEventBridge(eventBusName);\n\n if (!eventBridge) {\n throw new Error(`Can not find EventBridge with name \"${eventBusName}\"`);\n }\n bridgeName = this.getConstructName(eventBridge);\n }\n\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.usedForEventBridge\n );\n functionSubscription.usedForEventBridge = true;\n\n rule.addTarget(new targets.LambdaFunction(functionSubscription.function));\n\n const ruleName = this.getConstructName(rule);\n const serviceKey = `EventBridgeRule#${bridgeName}#${ruleName}`;\n functionSubscription.mapping.eventBridge = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyEventBus(eventBus: events.EventBus) {\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.usedForEventBridge\n );\n functionSubscription.usedForEventBridge = true;\n\n const bridgeName = this.getConstructName(eventBus);\n const rule = new events.Rule(this, `RuleAll${bridgeName}`, {\n eventBus,\n eventPattern: { version: ['0'] },\n targets: [new targets.LambdaFunction(functionSubscription.function)],\n });\n\n this.createdResourcesBySSpy.push(rule);\n const serviceKey = `EventBridge#${bridgeName}`;\n functionSubscription.mapping.eventBridge = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpySnsTopic(topic: sns.Topic) {\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.subsribedTopics.includes(topic)\n );\n\n const subscription = topic.addSubscription(\n new snsSubs.LambdaSubscription(functionSubscription.function)\n );\n this.createdResourcesBySSpy.push(subscription);\n const topicName = this.getConstructName(topic);\n const serviceKey = `SnsTopic#${topicName}`;\n functionSubscription.mapping[topic.topicArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n functionSubscription.subsribedTopics.push(topic);\n }\n\n private internalSpySnsSubscription(subscription: sns.Subscription) {\n if (!subscription.node.scope) {\n return;\n }\n\n const topic = this.getTopic(\n (subscription.node.defaultChild as sns.CfnSubscription).topicArn\n );\n\n if (!topic) {\n throw new Error('Can not find Topic');\n }\n\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.subsribedTopics.includes(topic)\n );\n\n const { filterPolicy } = subscription.node\n .defaultChild as sns.CfnSubscription;\n\n const subscriptionClone = topic.addSubscription(\n new snsSubs.LambdaSubscription(functionSubscription.function)\n );\n (subscriptionClone.node.defaultChild as sns.CfnSubscription).filterPolicy =\n filterPolicy;\n\n this.createdResourcesBySSpy.push(subscriptionClone);\n\n const topicName = this.getConstructName(topic);\n const targetName = this.getConstructName(subscription.node.scope);\n\n functionSubscription.subsribedTopics.push(topic);\n const serviceKey = `SnsSubscription#${topicName}#${targetName}`;\n functionSubscription.mapping[topic.topicArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private provideFunctionForSubscription(\n filterFunction?: (subscription: LambdaSubscription) => boolean\n ) {\n let functionSubscription: LambdaSubscription | undefined;\n\n if (filterFunction) {\n functionSubscription = this.lambdaSubscriptionPool.find(filterFunction);\n } else if (this.lambdaSubscriptionPool.length > 0) {\n functionSubscription = this.lambdaSubscriptionPool[0];\n }\n\n if (!functionSubscription) {\n functionSubscription = {\n subsribedTopics: [],\n usedForEventBridge: false,\n mapping: {},\n function: this.createFunctionForSubscription(\n this.lambdaSubscriptionPool.length\n ),\n };\n this.lambdaSubscriptionPool.push(functionSubscription);\n }\n return functionSubscription;\n }\n\n private setupForIoT(func: lambda.Function) {\n func.addEnvironment(\n envVariableNames.SSPY_ROOT_STACK,\n this.cleanName(this.findRootStack(Stack.of(this)).node.id)\n );\n func.addEnvironment(envVariableNames.SSPY_IOT_ENDPOINT, this.iotEndpoint);\n\n func.addToRolePolicy(\n new aws_iam.PolicyStatement({\n actions: ['iot:*'],\n effect: Effect.ALLOW,\n resources: ['*'],\n })\n );\n }\n\n private internalSpyLambda(func: lambda.Function) {\n const { layer, spyWrapperPath } = this.getExtensionForRuntime(\n func.runtime,\n func.architecture || Architecture.X86_64\n )!;\n if (!layer) {\n return;\n }\n func.addLayers(layer);\n\n const functionName = this.getConstructName(func);\n\n func.addEnvironment(envVariableNames.SSPY_FUNCTION_NAME, functionName);\n func.addEnvironment('AWS_LAMBDA_EXEC_WRAPPER', spyWrapperPath);\n\n if (this.props?.debugMode) {\n func.addEnvironment(envVariableNames.SSPY_DEBUG, 'true');\n }\n\n this.setupForIoT(func);\n\n this.serviceKeys.push(`Function#${functionName}#Request`);\n this.serviceKeys.push(`Function#${functionName}#Error`);\n this.serviceKeys.push(`Function#${functionName}#Console`);\n this.serviceKeys.push(`Function#${functionName}#Response`);\n\n this.addMappingToFunction(func);\n }\n\n public getConstructName(construct: IConstruct) {\n let constructName = construct.node.path;\n const { node } = Stack.of(this);\n\n if (constructName.startsWith(node.id)) {\n constructName = constructName.substring(node.id.length + 1);\n }\n\n return this.cleanName(constructName);\n }\n\n private cleanName(name: string) {\n //snake case to camel case including dash and first letter to upper case\n return name\n .replace(/[-_]+/g, ' ')\n .replace(/[^\\w\\s]/g, '')\n .replace(/\\s(.)/g, ($1) => $1.toUpperCase())\n .replace(/\\s/g, '')\n .replace(/^(.)/, ($1) => $1.toUpperCase());\n }\n\n private getTopic(topicArn: string): sns.Topic | undefined {\n const topic = this.findElement<sns.Topic>(\n (node: IConstruct) =>\n node instanceof sns.Topic && (node as sns.Topic).topicArn === topicArn\n );\n\n return topic;\n }\n\n private getEventBridge(eventBusName: string): events.IEventBus | undefined {\n const eventBridge = this.findElement<events.IEventBus>(\n (node: IConstruct) =>\n (node instanceof events.EventBus ||\n node.constructor.name === 'ImportedEventBus') &&\n (node as events.IEventBus).eventBusName === eventBusName\n );\n\n return eventBridge;\n }\n\n private findRootStack(stack: Stack): Stack {\n if (stack.nested) {\n const parentStack = (stack as NestedStack).nestedStackParent;\n if (parentStack) return this.findRootStack(parentStack);\n return stack;\n } else {\n return stack;\n }\n }\n\n private findElement<T extends IConstruct = IConstruct>(\n filterFunc: (node: IConstruct) => boolean,\n parent?: IConstruct\n ): T | undefined {\n if (!parent) {\n parent = this.findRootStack(Stack.of(this));\n }\n\n for (const node of parent.node.children) {\n if (filterFunc(node)) {\n return node as T;\n }\n const elementFoundInChild = this.findElement<T>(filterFunc, node);\n if (elementFoundInChild) {\n return elementFoundInChild;\n }\n }\n\n return undefined;\n }\n\n private addMappingToFunction(\n func: lambda.Function,\n keyValue?: { key: string; value: string }\n ) {\n for (const fs of this.lambdasSpied) {\n if (fs.function === func) {\n if (keyValue) {\n fs.mapping[keyValue.key] = keyValue.value;\n }\n return;\n }\n }\n\n const fs: LambdaSpied = {\n function: func,\n mapping: {},\n };\n\n if (keyValue) {\n fs.mapping[keyValue.key] = keyValue.value;\n }\n\n this.lambdasSpied.push(fs);\n }\n\n private getAssetLocation(location: string) {\n const loc = path.join(__dirname, '../lib/' + location);\n\n if (fs.existsSync(loc)) {\n return loc;\n }\n\n const loc2 = path.join(__dirname, '../../lib/' + location);\n\n if (fs.existsSync(loc2)) {\n return loc2;\n }\n\n throw new Error(`Location ${loc} and ${loc2} does not exists.`);\n }\n}\n\ntype LambdaSubscription = {\n subsribedTopics: sns.Topic[];\n usedForEventBridge: boolean;\n function: lambdaNode.NodejsFunction;\n mapping: Record<string, string>;\n};\n\ntype LambdaSpied = {\n function: lambda.Function;\n mapping: Record<string, string>;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ServerlessSpy.mjs","names":["props?: ServerlessSpyProps","filterWithDefaults: Required<SpyFilter>","nodes: IConstruct[]","functionSubscription: LambdaSubscription | undefined","fs","fs: LambdaSpied"],"sources":["../../src/ServerlessSpy.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { PythonLayerVersion } from '@aws-cdk/aws-lambda-python-alpha';\nimport {\n aws_iam,\n BundlingFileAccess,\n CfnOutput,\n custom_resources,\n Duration,\n NestedStack,\n Stack,\n} from 'aws-cdk-lib';\nimport * as dynamoDb from 'aws-cdk-lib/aws-dynamodb';\nimport * as events from 'aws-cdk-lib/aws-events';\nimport * as targets from 'aws-cdk-lib/aws-events-targets';\nimport { Effect } from 'aws-cdk-lib/aws-iam';\nimport * as lambda from 'aws-cdk-lib/aws-lambda';\nimport {\n Architecture,\n ILayerVersion,\n SingletonFunction,\n} from 'aws-cdk-lib/aws-lambda';\nimport * as dynamoDbStream from 'aws-cdk-lib/aws-lambda-event-sources';\nimport { SqsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';\nimport * as lambdaNode from 'aws-cdk-lib/aws-lambda-nodejs';\nimport { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';\nimport * as s3 from 'aws-cdk-lib/aws-s3';\nimport * as s3notif from 'aws-cdk-lib/aws-s3-notifications';\nimport * as sns from 'aws-cdk-lib/aws-sns';\nimport * as snsSubs from 'aws-cdk-lib/aws-sns-subscriptions';\nimport * as sqs from 'aws-cdk-lib/aws-sqs';\nimport { Construct, IConstruct } from 'constructs';\nimport { envVariableNames } from './common/envVariableNames';\n\nexport interface ServerlessSpyProps {\n readonly generateSpyEventsFileLocation?: string;\n readonly spySqsWithNoSubscriptionAndDropAllMessages?: boolean;\n readonly debugMode?: boolean;\n}\n\nexport interface SpyFilter {\n readonly spyLambda?: boolean;\n readonly spySqs?: boolean;\n readonly spySnsTopic?: boolean;\n readonly spySnsSubsription?: boolean;\n readonly spyEventBridge?: boolean;\n readonly spyEventBridgeRule?: boolean;\n readonly spyS3?: boolean;\n readonly spyDynamoDB?: boolean;\n}\n\nconst isLambdaFunction = (node: IConstruct): node is lambda.Function =>\n 'functionName' in node && 'functionArn' in node && 'runtime' in node;\n\nconst serverlessSpyIotEndpointCrNamePrefix = 'ServerlessSpyIotEndpoint';\n\nexport class ServerlessSpy extends Construct {\n private createdResourcesBySSpy: IConstruct[] = [];\n private lambdaSubscriptionPool: LambdaSubscription[] = [];\n private lambdaSubscriptionMain: LambdaSubscription;\n private lambdasSpied: LambdaSpied[] = [];\n public serviceKeys: string[] = [];\n private spiedNodes: IConstruct[] = [];\n private layerMap: Partial<Record<string, ILayerVersion>> = {};\n private readonly iotEndpoint: string;\n\n constructor(\n scope: Construct,\n id: string,\n private props?: ServerlessSpyProps\n ) {\n super(scope, id);\n\n const rootStack = this.cleanName(\n this.findRootStack(Stack.of(this)).node.id\n );\n\n const getIoTEndpoint = new custom_resources.AwsCustomResource(\n this,\n serverlessSpyIotEndpointCrNamePrefix,\n {\n onCreate: {\n service: 'Iot',\n action: 'describeEndpoint',\n physicalResourceId:\n custom_resources.PhysicalResourceId.fromResponse('endpointAddress'),\n parameters: {\n endpointType: 'iot:Data-ATS',\n },\n },\n onUpdate: {\n service: 'Iot',\n action: 'describeEndpoint',\n physicalResourceId:\n custom_resources.PhysicalResourceId.fromResponse('endpointAddress'),\n parameters: {\n endpointType: 'iot:Data-ATS',\n },\n },\n installLatestAwsSdk: false,\n policy: custom_resources.AwsCustomResourcePolicy.fromSdkCalls({\n resources: custom_resources.AwsCustomResourcePolicy.ANY_RESOURCE,\n }),\n functionName: serverlessSpyIotEndpointCrNamePrefix + rootStack,\n }\n );\n this.iotEndpoint = getIoTEndpoint.getResponseField('endpointAddress');\n\n this.createdResourcesBySSpy.push(getIoTEndpoint);\n\n new CfnOutput(this, 'ServerlessSpyIoTEndpoint', {\n key: 'ServerlessSpyWsUrl',\n value: `${this.iotEndpoint}/${rootStack}`,\n });\n\n this.lambdaSubscriptionMain = this.provideFunctionForSubscription();\n }\n\n private getDefaultLambdaEnvironmentVariables(): { [key: string]: string } {\n return {\n NODE_OPTIONS: '--enable-source-maps',\n };\n }\n\n /**\n * Initalize spying on resources given as parameter.\n * @param nodes Which reources and their children to spy on.\n */\n public spyNodes(nodes: IConstruct[]) {\n for (const node of nodes) {\n let ns = this.getAllNodes(node);\n this.internalSpyNodes(ns);\n }\n\n this.finalizeSpy();\n }\n\n /**\n * Initalize spying on resources.\n * @param filter Limit which resources to spy on.\n */\n public spy(filter?: SpyFilter) {\n let nodes = this.getAllNodes(Stack.of(this));\n\n const filterWithDefaults: Required<SpyFilter> = {\n spyLambda: true,\n spySqs: true,\n spySnsTopic: true,\n spySnsSubsription: true,\n spyEventBridge: true,\n spyEventBridgeRule: true,\n spyS3: true,\n spyDynamoDB: true,\n ...filter,\n };\n\n const CRID =\n 'AWS' +\n custom_resources.AwsCustomResource.PROVIDER_FUNCTION_UUID.replace(\n /-/gi,\n ''\n ).substring(0, 16);\n\n nodes = nodes.filter((node) => {\n if (\n // Ignore the custom resource and the Provider (as well as any other Providers using the same provider function), otherwise we cause\n // circular dependencies\n node.node.id.startsWith(CRID) ||\n node.node.id === 'Provider' ||\n // Ignore singleton functions as they can cause very odd behavior and crashes\n node instanceof SingletonFunction\n ) {\n if (this.props?.debugMode) {\n console.info(`Skipping ${node.node.id}`);\n }\n return false;\n } else if (\n filterWithDefaults.spyLambda &&\n (node instanceof lambda.Function ||\n node instanceof NodejsFunction ||\n isLambdaFunction(node))\n ) {\n return true;\n } else if (filterWithDefaults.spySnsTopic && node instanceof sns.Topic) {\n return true;\n } else if (\n filterWithDefaults.spySnsSubsription &&\n node instanceof sns.Subscription\n ) {\n return true;\n } else if (filterWithDefaults.spyS3 && node instanceof s3.Bucket) {\n return true;\n } else if (\n filterWithDefaults.spyDynamoDB &&\n node instanceof dynamoDb.Table\n ) {\n return true;\n } else if (\n filterWithDefaults.spyDynamoDB &&\n node instanceof dynamoDb.TableV2\n ) {\n return true;\n } else if (\n filterWithDefaults.spyEventBridge &&\n node instanceof events.EventBus\n ) {\n return true;\n } else if (\n filterWithDefaults.spyEventBridgeRule &&\n node instanceof events.Rule\n ) {\n return true;\n } else if (\n filterWithDefaults.spySqs &&\n node instanceof lambda.CfnEventSourceMapping\n ) {\n return true;\n } else if (\n filterWithDefaults.spySqs &&\n this.props?.spySqsWithNoSubscriptionAndDropAllMessages &&\n node instanceof sqs.Queue\n ) {\n return true;\n }\n\n return false;\n });\n\n this.internalSpyNodes(nodes);\n this.finalizeSpy();\n }\n\n private internalSpyNodes(nodes: IConstruct[]) {\n for (const node of nodes) {\n this.internalSpyNode(node);\n }\n }\n\n private finalizeSpy() {\n //set mapping property for all functions we created\n for (const func of this.lambdaSubscriptionPool) {\n func.function.addEnvironment(\n envVariableNames.SSPY_INFRA_MAPPING,\n JSON.stringify(func.mapping)\n );\n }\n\n //set mapping property for all functions we spy on\n for (const func of this.lambdasSpied) {\n func.function.addEnvironment(\n envVariableNames.SSPY_INFRA_MAPPING,\n JSON.stringify(func.mapping)\n );\n }\n\n if (this.props?.generateSpyEventsFileLocation) {\n this.writeSpyEventsClass(this.props?.generateSpyEventsFileLocation);\n }\n }\n\n private getExtensionAssetLocation() {\n let extensionAssetLocation = path.join(\n __dirname,\n '../extension/dist/layer'\n );\n\n const extensionAssetLocationAlt = path.join(\n __dirname,\n '../lib/extension/dist/layer'\n );\n\n if (!fs.existsSync(extensionAssetLocation)) {\n if (!fs.existsSync(extensionAssetLocationAlt)) {\n throw new Error(\n `Folder with assets for extension does not exists at ${extensionAssetLocation} or at ${extensionAssetLocationAlt} `\n );\n } else {\n extensionAssetLocation = extensionAssetLocationAlt;\n }\n }\n\n const extensionAssetLocationWrapper = path.join(\n extensionAssetLocation,\n 'spy-wrapper'\n );\n if (!fs.existsSync(extensionAssetLocationWrapper)) {\n throw new Error(\n `Wrapper script for extension does not exists ${extensionAssetLocation}`\n );\n }\n\n const extensionAssetLocationCode = path.join(\n extensionAssetLocation,\n `nodejs/node_modules/interceptor.js`\n );\n if (!fs.existsSync(extensionAssetLocationCode)) {\n throw new Error(\n `Code for extension does not exists ${extensionAssetLocationCode}`\n );\n }\n return extensionAssetLocation;\n }\n\n private getLanguageExtensionAssetLocation(language: string) {\n const rootDir = path.join(__dirname, '..');\n\n let extensionAssetLocation = path.join(rootDir, `extensions/${language}`);\n\n const extensionAssetLocationAlt = path.join(\n rootDir,\n `lib/extensions/${language}`\n );\n\n if (!fs.existsSync(extensionAssetLocation)) {\n if (!fs.existsSync(extensionAssetLocationAlt)) {\n throw new Error(\n `Folder with assets for extension for ${language} does not exists at ${extensionAssetLocation} or at ${extensionAssetLocationAlt} `\n );\n } else {\n extensionAssetLocation = extensionAssetLocationAlt;\n }\n }\n\n const extensionAssetLocationWrapper = path.join(\n // extensionAssetLocation.substring(\n // 0,\n // extensionAssetLocation.lastIndexOf(path.sep)\n // ),\n extensionAssetLocation,\n 'spy-wrapper'\n );\n if (!fs.existsSync(extensionAssetLocationWrapper)) {\n throw new Error(\n `Wrapper script for extension does not exists at ${extensionAssetLocationWrapper}`\n );\n }\n\n return extensionAssetLocation;\n }\n\n /**\n * Write SpyEvents class, which helps with writing the code for tests.\n * @param fileLocation\n */\n private writeSpyEventsClass(fileLocation: string) {\n fs.mkdirSync(path.dirname(fileLocation), { recursive: true });\n\n const properties = this.serviceKeys\n .map((sk) => ` ${sk.replace(/#/g, '')}: '${sk}' = '${sk}';\\n`)\n .join('');\n\n const code = `/* eslint-disable */\\nexport class ServerlessSpyEvents {\\n${properties}}\\n`;\n\n fs.writeFileSync(fileLocation, code);\n }\n\n private getAllNodes(parent: IConstruct) {\n const nodes: IConstruct[] = [];\n nodes.push(parent);\n this.getAllNodesRecursive(parent, nodes);\n return nodes;\n }\n\n private getAllNodesRecursive(parent: IConstruct, nodes: IConstruct[]) {\n for (const node of parent.node.children) {\n nodes.push(node);\n this.getAllNodesRecursive(node, nodes);\n }\n }\n\n private internalSpyNode(node: IConstruct) {\n if (this.spiedNodes.includes(node)) {\n return;\n }\n\n this.spiedNodes.push(node);\n\n if (this.createdResourcesBySSpy.includes(node)) {\n return;\n }\n\n if (this.lambdaSubscriptionPool.find((s) => s.function === node)) {\n return;\n }\n\n if (this.props?.debugMode) {\n console.info('Spy on node', this.getConstructName(node));\n }\n\n if (\n node instanceof lambda.Function ||\n node instanceof NodejsFunction ||\n isLambdaFunction(node)\n ) {\n this.internalSpyLambda(node);\n } else if (node instanceof sns.Topic) {\n this.internalSpySnsTopic(node);\n } else if (node instanceof sns.Subscription) {\n this.internalSpySnsSubscription(node);\n } else if (node instanceof s3.Bucket) {\n this.internalSpyS3(node);\n } else if (node instanceof dynamoDb.Table) {\n this.internalSpyDynamodb(node);\n } else if (node instanceof dynamoDb.TableV2) {\n this.internalSpyDynamodb(node);\n } else if (node instanceof events.EventBus) {\n this.internalSpyEventBus(node);\n } else if (node instanceof events.Rule) {\n this.internalSpyEventBusRule(node);\n } else if (node instanceof lambda.CfnEventSourceMapping) {\n this.internalSpySqs(node);\n } else if (node instanceof sqs.Queue) {\n if (this.props?.spySqsWithNoSubscriptionAndDropAllMessages) {\n this.internalSpySpySqsWithNoSubscription(node);\n }\n }\n }\n\n private getExtensionForRuntime(\n runtime: lambda.Runtime,\n architecture: lambda.Architecture\n ): { layer: lambda.ILayerVersion; spyWrapperPath: string } | undefined {\n const layerKey =\n `sspy_extension_${runtime.toString()}_${architecture.name.toString()}`.replace(\n /\\./g,\n '_'\n );\n\n let layer = this.layerMap[layerKey];\n let spyWrapperPath = '/opt/spy-wrapper';\n\n switch (runtime.name) {\n case lambda.Runtime.PYTHON_3_8.name:\n case lambda.Runtime.PYTHON_3_9.name:\n case lambda.Runtime.PYTHON_3_10.name:\n case lambda.Runtime.PYTHON_3_11.name:\n case lambda.Runtime.PYTHON_3_12.name:\n spyWrapperPath = '/opt/python/spy-wrapper';\n layer =\n layer ||\n new PythonLayerVersion(this, layerKey, {\n compatibleRuntimes: [runtime],\n compatibleArchitectures: [architecture],\n entry: this.getLanguageExtensionAssetLocation('python'),\n bundling: {\n bundlingFileAccess: BundlingFileAccess.VOLUME_COPY,\n },\n });\n break;\n case lambda.Runtime.NODEJS_12_X.name:\n case lambda.Runtime.NODEJS_14_X.name:\n case lambda.Runtime.NODEJS_16_X.name:\n case lambda.Runtime.NODEJS_18_X.name:\n case lambda.Runtime.NODEJS_20_X.name:\n case lambda.Runtime.NODEJS_22_X.name:\n layer =\n layer ||\n new lambda.LayerVersion(this, layerKey, {\n compatibleRuntimes: [runtime],\n compatibleArchitectures: [architecture],\n code: lambda.Code.fromAsset(this.getExtensionAssetLocation()),\n });\n break;\n default:\n console.log(`No extensions available for ${runtime.toString()}`);\n return undefined;\n }\n\n this.layerMap[layerKey] = layer;\n this.createdResourcesBySSpy.push(layer);\n return { layer, spyWrapperPath };\n }\n\n private internalSpySpySqsWithNoSubscription(queue: sqs.Queue) {\n const subscription = this.findElement<lambda.CfnEventSourceMapping>(\n (n: IConstruct) =>\n n instanceof lambda.CfnEventSourceMapping &&\n (n as lambda.CfnEventSourceMapping).eventSourceArn === queue.queueArn\n );\n\n if (subscription) {\n return; //already have subscription\n }\n\n const queueName = this.getConstructName(queue);\n const func = new NodejsFunction(\n this,\n `${queueName}SqsSubscriptionAndDropAllMessages`,\n {\n memorySize: 512,\n timeout: Duration.seconds(5),\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'handler',\n entry: this.getAssetLocation(\n 'functions/sqsSubscriptionAndDropAllMessages.js'\n ),\n environment: this.getDefaultLambdaEnvironmentVariables(),\n }\n );\n func.addEventSource(new SqsEventSource(queue));\n this.setupForIoT(func);\n const { layer, spyWrapperPath } = this.getExtensionForRuntime(\n func.runtime,\n func.architecture\n )!;\n func.addLayers(layer);\n\n func.addEnvironment('AWS_LAMBDA_EXEC_WRAPPER', spyWrapperPath);\n\n if (this.props?.debugMode) {\n func.addEnvironment(envVariableNames.SSPY_DEBUG, 'true');\n }\n\n this.createdResourcesBySSpy.push(func);\n\n const serviceKey = `Sqs#${queueName}`;\n\n this.addMappingToFunction(func, {\n key: queue.queueArn,\n value: serviceKey,\n });\n\n this.serviceKeys.push(serviceKey);\n func.addEnvironment(envVariableNames.SSPY_SUBSCRIBED_TO_SQS, 'true');\n }\n\n private internalSpySqs(node: lambda.CfnEventSourceMapping) {\n const queue = this.findElement<sqs.Queue>(\n (n: IConstruct) =>\n n instanceof sqs.Queue &&\n (n as sqs.Queue).queueArn === node.eventSourceArn\n );\n\n const func = this.findElement<lambda.Function>(\n (n: IConstruct) =>\n n instanceof lambda.Function &&\n (n as lambda.Function).functionName === node.functionName\n );\n\n if (queue && func) {\n const queueName = this.getConstructName(queue);\n\n const serviceKey = `Sqs#${queueName}`;\n\n this.addMappingToFunction(func, {\n key: queue.queueArn,\n value: serviceKey,\n });\n\n this.serviceKeys.push(serviceKey);\n func.addEnvironment(envVariableNames.SSPY_SUBSCRIBED_TO_SQS, 'true');\n }\n }\n\n private createFunctionForSubscription(index: number) {\n const func = new lambdaNode.NodejsFunction(this, `Subscription${index}`, {\n memorySize: 512,\n timeout: Duration.seconds(5),\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'handler',\n entry: this.getAssetLocation('functions/sendMessage.js'),\n environment: {\n NODE_OPTIONS: '--enable-source-maps',\n },\n });\n this.setupForIoT(func);\n return func;\n }\n\n private internalSpyS3(s3Bucket: s3.Bucket) {\n s3Bucket.addEventNotification(\n s3.EventType.OBJECT_CREATED_PUT,\n new s3notif.LambdaDestination(this.lambdaSubscriptionMain.function)\n );\n\n const name = this.getConstructName(s3Bucket);\n\n const serviceKey = `S3#${name}`;\n this.lambdaSubscriptionMain.mapping[s3Bucket.bucketArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyDynamodb(table: dynamoDb.Table | dynamoDb.TableV2) {\n // enable DynamoDB streams with a hack\n (table.node.defaultChild as dynamoDb.CfnTable).streamSpecification = {\n streamViewType: dynamoDb.StreamViewType.NEW_AND_OLD_IMAGES,\n };\n try {\n (table as any).tableStreamArn = (\n table.node.defaultChild as dynamoDb.CfnTable\n ).attrStreamArn;\n } catch (e) {\n // Property is read-only in newer CDK versions, skip the assignment\n if (!(e instanceof TypeError && e.message.includes('only a getter'))) {\n throw e; // Re-throw if it's a different error\n }\n }\n\n this.lambdaSubscriptionMain.function.addEventSource(\n new dynamoDbStream.DynamoEventSource(table, {\n startingPosition: lambda.StartingPosition.LATEST,\n batchSize: 1,\n retryAttempts: 0,\n })\n );\n\n const name = this.getConstructName(table);\n\n const serviceKey = `DynamoDB#${name}`;\n this.lambdaSubscriptionMain.mapping[table.tableArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyEventBusRule(rule: events.Rule) {\n const { eventBusName } = rule.node.defaultChild as events.CfnRule;\n let bridgeName = 'Default';\n if (!!eventBusName) {\n const eventBridge = this.getEventBridge(eventBusName);\n\n if (!eventBridge) {\n throw new Error(`Can not find EventBridge with name \"${eventBusName}\"`);\n }\n bridgeName = this.getConstructName(eventBridge);\n }\n\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.usedForEventBridge\n );\n functionSubscription.usedForEventBridge = true;\n\n rule.addTarget(new targets.LambdaFunction(functionSubscription.function));\n\n const ruleName = this.getConstructName(rule);\n const serviceKey = `EventBridgeRule#${bridgeName}#${ruleName}`;\n functionSubscription.mapping.eventBridge = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyEventBus(eventBus: events.EventBus) {\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.usedForEventBridge\n );\n functionSubscription.usedForEventBridge = true;\n\n const bridgeName = this.getConstructName(eventBus);\n const rule = new events.Rule(this, `RuleAll${bridgeName}`, {\n eventBus,\n eventPattern: { version: ['0'] },\n targets: [new targets.LambdaFunction(functionSubscription.function)],\n });\n\n this.createdResourcesBySSpy.push(rule);\n const serviceKey = `EventBridge#${bridgeName}`;\n functionSubscription.mapping.eventBridge = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpySnsTopic(topic: sns.Topic) {\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.subsribedTopics.includes(topic)\n );\n\n const subscription = topic.addSubscription(\n new snsSubs.LambdaSubscription(functionSubscription.function)\n );\n this.createdResourcesBySSpy.push(subscription);\n const topicName = this.getConstructName(topic);\n const serviceKey = `SnsTopic#${topicName}`;\n functionSubscription.mapping[topic.topicArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n functionSubscription.subsribedTopics.push(topic);\n }\n\n private internalSpySnsSubscription(subscription: sns.Subscription) {\n if (!subscription.node.scope) {\n return;\n }\n\n const topic = this.getTopic(\n (subscription.node.defaultChild as sns.CfnSubscription).topicArn\n );\n\n if (!topic) {\n throw new Error('Can not find Topic');\n }\n\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.subsribedTopics.includes(topic)\n );\n\n const { filterPolicy } = subscription.node\n .defaultChild as sns.CfnSubscription;\n\n const subscriptionClone = topic.addSubscription(\n new snsSubs.LambdaSubscription(functionSubscription.function)\n );\n (subscriptionClone.node.defaultChild as sns.CfnSubscription).filterPolicy =\n filterPolicy;\n\n this.createdResourcesBySSpy.push(subscriptionClone);\n\n const topicName = this.getConstructName(topic);\n const targetName = this.getConstructName(subscription.node.scope);\n\n functionSubscription.subsribedTopics.push(topic);\n const serviceKey = `SnsSubscription#${topicName}#${targetName}`;\n functionSubscription.mapping[topic.topicArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private provideFunctionForSubscription(\n filterFunction?: (subscription: LambdaSubscription) => boolean\n ) {\n let functionSubscription: LambdaSubscription | undefined;\n\n if (filterFunction) {\n functionSubscription = this.lambdaSubscriptionPool.find(filterFunction);\n } else if (this.lambdaSubscriptionPool.length > 0) {\n functionSubscription = this.lambdaSubscriptionPool[0];\n }\n\n if (!functionSubscription) {\n functionSubscription = {\n subsribedTopics: [],\n usedForEventBridge: false,\n mapping: {},\n function: this.createFunctionForSubscription(\n this.lambdaSubscriptionPool.length\n ),\n };\n this.lambdaSubscriptionPool.push(functionSubscription);\n }\n return functionSubscription;\n }\n\n private setupForIoT(func: lambda.Function) {\n func.addEnvironment(\n envVariableNames.SSPY_ROOT_STACK,\n this.cleanName(this.findRootStack(Stack.of(this)).node.id)\n );\n func.addEnvironment(envVariableNames.SSPY_IOT_ENDPOINT, this.iotEndpoint);\n\n func.addToRolePolicy(\n new aws_iam.PolicyStatement({\n actions: ['iot:*'],\n effect: Effect.ALLOW,\n resources: ['*'],\n })\n );\n }\n\n private internalSpyLambda(func: lambda.Function) {\n const { layer, spyWrapperPath } = this.getExtensionForRuntime(\n func.runtime,\n func.architecture || Architecture.X86_64\n )!;\n if (!layer) {\n return;\n }\n func.addLayers(layer);\n\n const functionName = this.getConstructName(func);\n\n func.addEnvironment(envVariableNames.SSPY_FUNCTION_NAME, functionName);\n func.addEnvironment('AWS_LAMBDA_EXEC_WRAPPER', spyWrapperPath);\n\n if (this.props?.debugMode) {\n func.addEnvironment(envVariableNames.SSPY_DEBUG, 'true');\n }\n\n this.setupForIoT(func);\n\n this.serviceKeys.push(`Function#${functionName}#Request`);\n this.serviceKeys.push(`Function#${functionName}#Error`);\n this.serviceKeys.push(`Function#${functionName}#Console`);\n this.serviceKeys.push(`Function#${functionName}#Response`);\n\n this.addMappingToFunction(func);\n }\n\n public getConstructName(construct: IConstruct) {\n let constructName = construct.node.path;\n const { node } = Stack.of(this);\n\n if (constructName.startsWith(node.id)) {\n constructName = constructName.substring(node.id.length + 1);\n }\n\n return this.cleanName(constructName);\n }\n\n private cleanName(name: string) {\n //snake case to camel case including dash and first letter to upper case\n return name\n .replace(/[-_]+/g, ' ')\n .replace(/[^\\w\\s]/g, '')\n .replace(/\\s(.)/g, ($1) => $1.toUpperCase())\n .replace(/\\s/g, '')\n .replace(/^(.)/, ($1) => $1.toUpperCase());\n }\n\n private getTopic(topicArn: string): sns.Topic | undefined {\n const topic = this.findElement<sns.Topic>(\n (node: IConstruct) =>\n node instanceof sns.Topic && (node as sns.Topic).topicArn === topicArn\n );\n\n return topic;\n }\n\n private getEventBridge(eventBusName: string): events.IEventBus | undefined {\n const eventBridge = this.findElement<events.IEventBus>(\n (node: IConstruct) =>\n (node instanceof events.EventBus ||\n node.constructor.name === 'ImportedEventBus') &&\n (node as events.IEventBus).eventBusName === eventBusName\n );\n\n return eventBridge;\n }\n\n private findRootStack(stack: Stack): Stack {\n if (stack.nested) {\n const parentStack = (stack as NestedStack).nestedStackParent;\n if (parentStack) return this.findRootStack(parentStack);\n return stack;\n } else {\n return stack;\n }\n }\n\n private findElement<T extends IConstruct = IConstruct>(\n filterFunc: (node: IConstruct) => boolean,\n parent?: IConstruct\n ): T | undefined {\n if (!parent) {\n parent = this.findRootStack(Stack.of(this));\n }\n\n for (const node of parent.node.children) {\n if (filterFunc(node)) {\n return node as T;\n }\n const elementFoundInChild = this.findElement<T>(filterFunc, node);\n if (elementFoundInChild) {\n return elementFoundInChild;\n }\n }\n\n return undefined;\n }\n\n private addMappingToFunction(\n func: lambda.Function,\n keyValue?: { key: string; value: string }\n ) {\n for (const fs of this.lambdasSpied) {\n if (fs.function === func) {\n if (keyValue) {\n fs.mapping[keyValue.key] = keyValue.value;\n }\n return;\n }\n }\n\n const fs: LambdaSpied = {\n function: func,\n mapping: {},\n };\n\n if (keyValue) {\n fs.mapping[keyValue.key] = keyValue.value;\n }\n\n this.lambdasSpied.push(fs);\n }\n\n private getAssetLocation(location: string) {\n const loc = path.join(__dirname, '../lib/' + location);\n\n if (fs.existsSync(loc)) {\n return loc;\n }\n\n const loc2 = path.join(__dirname, '../../lib/' + location);\n\n if (fs.existsSync(loc2)) {\n return loc2;\n }\n\n throw new Error(`Location ${loc} and ${loc2} does not exists.`);\n }\n}\n\ntype LambdaSubscription = {\n subsribedTopics: sns.Topic[];\n usedForEventBridge: boolean;\n function: lambdaNode.NodejsFunction;\n mapping: Record<string, string>;\n};\n\ntype LambdaSpied = {\n function: lambda.Function;\n mapping: Record<string, string>;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;uBAgC6D;AAmB7D,MAAM,oBAAoB,SACxB,kBAAkB,QAAQ,iBAAiB,QAAQ,aAAa;AAElE,MAAM,uCAAuC;AAE7C,IAAa,gBAAb,cAAmC,UAAU;CAU3C,YACE,OACA,IACA,AAAQA,OACR;AACA,QAAM,OAAO,GAAG;EAFR;gCAZqC,EAAE;gCACM,EAAE;sBAEnB,EAAE;qBACT,EAAE;oBACE,EAAE;kBACsB,EAAE;EAU3D,MAAM,YAAY,KAAK,UACrB,KAAK,cAAc,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,GACzC;EAED,MAAM,iBAAiB,IAAI,iBAAiB,kBAC1C,MACA,sCACA;GACE,UAAU;IACR,SAAS;IACT,QAAQ;IACR,oBACE,iBAAiB,mBAAmB,aAAa,kBAAkB;IACrE,YAAY,EACV,cAAc,gBACf;IACF;GACD,UAAU;IACR,SAAS;IACT,QAAQ;IACR,oBACE,iBAAiB,mBAAmB,aAAa,kBAAkB;IACrE,YAAY,EACV,cAAc,gBACf;IACF;GACD,qBAAqB;GACrB,QAAQ,iBAAiB,wBAAwB,aAAa,EAC5D,WAAW,iBAAiB,wBAAwB,cACrD,CAAC;GACF,cAAc,uCAAuC;GACtD,CACF;AACD,OAAK,cAAc,eAAe,iBAAiB,kBAAkB;AAErE,OAAK,uBAAuB,KAAK,eAAe;AAEhD,MAAI,UAAU,MAAM,4BAA4B;GAC9C,KAAK;GACL,OAAO,GAAG,KAAK,YAAY,GAAG;GAC/B,CAAC;AAEF,OAAK,yBAAyB,KAAK,gCAAgC;;CAGrE,AAAQ,uCAAkE;AACxE,SAAO,EACL,cAAc,wBACf;;;;;;CAOH,AAAO,SAAS,OAAqB;AACnC,OAAK,MAAM,QAAQ,OAAO;GACxB,IAAI,KAAK,KAAK,YAAY,KAAK;AAC/B,QAAK,iBAAiB,GAAG;;AAG3B,OAAK,aAAa;;;;;;CAOpB,AAAO,IAAI,QAAoB;EAC7B,IAAI,QAAQ,KAAK,YAAY,MAAM,GAAG,KAAK,CAAC;EAE5C,MAAMC,qBAA0C;GAC9C,WAAW;GACX,QAAQ;GACR,aAAa;GACb,mBAAmB;GACnB,gBAAgB;GAChB,oBAAoB;GACpB,OAAO;GACP,aAAa;GACb,GAAG;GACJ;EAED,MAAM,OACJ,QACA,iBAAiB,kBAAkB,uBAAuB,QACxD,OACA,GACD,CAAC,UAAU,GAAG,GAAG;AAEpB,UAAQ,MAAM,QAAQ,SAAS;AAC7B,OAGE,KAAK,KAAK,GAAG,WAAW,KAAK,IAC7B,KAAK,KAAK,OAAO,cAEjB,gBAAgB,mBAChB;AACA,QAAI,KAAK,OAAO,UACd,SAAQ,KAAK,YAAY,KAAK,KAAK,KAAK;AAE1C,WAAO;cAEP,mBAAmB,cAClB,gBAAgB,OAAO,YACtB,gBAAgB,kBAChB,iBAAiB,KAAK,EAExB,QAAO;YACE,mBAAmB,eAAe,gBAAgB,IAAI,MAC/D,QAAO;YAEP,mBAAmB,qBACnB,gBAAgB,IAAI,aAEpB,QAAO;YACE,mBAAmB,SAAS,gBAAgB,GAAG,OACxD,QAAO;YAEP,mBAAmB,eACnB,gBAAgB,SAAS,MAEzB,QAAO;YAEP,mBAAmB,eACnB,gBAAgB,SAAS,QAEzB,QAAO;YAEP,mBAAmB,kBACnB,gBAAgB,OAAO,SAEvB,QAAO;YAEP,mBAAmB,sBACnB,gBAAgB,OAAO,KAEvB,QAAO;YAEP,mBAAmB,UACnB,gBAAgB,OAAO,sBAEvB,QAAO;YAEP,mBAAmB,UACnB,KAAK,OAAO,8CACZ,gBAAgB,IAAI,MAEpB,QAAO;AAGT,UAAO;IACP;AAEF,OAAK,iBAAiB,MAAM;AAC5B,OAAK,aAAa;;CAGpB,AAAQ,iBAAiB,OAAqB;AAC5C,OAAK,MAAM,QAAQ,MACjB,MAAK,gBAAgB,KAAK;;CAI9B,AAAQ,cAAc;AAEpB,OAAK,MAAM,QAAQ,KAAK,uBACtB,MAAK,SAAS,eACZ,iBAAiB,oBACjB,KAAK,UAAU,KAAK,QAAQ,CAC7B;AAIH,OAAK,MAAM,QAAQ,KAAK,aACtB,MAAK,SAAS,eACZ,iBAAiB,oBACjB,KAAK,UAAU,KAAK,QAAQ,CAC7B;AAGH,MAAI,KAAK,OAAO,8BACd,MAAK,oBAAoB,KAAK,OAAO,8BAA8B;;CAIvE,AAAQ,4BAA4B;EAClC,IAAI,yBAAyB,KAAK,KAChC,WACA,0BACD;EAED,MAAM,4BAA4B,KAAK,KACrC,WACA,8BACD;AAED,MAAI,CAAC,GAAG,WAAW,uBAAuB,CACxC,KAAI,CAAC,GAAG,WAAW,0BAA0B,CAC3C,OAAM,IAAI,MACR,uDAAuD,uBAAuB,SAAS,0BAA0B,GAClH;MAED,0BAAyB;EAI7B,MAAM,gCAAgC,KAAK,KACzC,wBACA,cACD;AACD,MAAI,CAAC,GAAG,WAAW,8BAA8B,CAC/C,OAAM,IAAI,MACR,gDAAgD,yBACjD;EAGH,MAAM,6BAA6B,KAAK,KACtC,wBACA,qCACD;AACD,MAAI,CAAC,GAAG,WAAW,2BAA2B,CAC5C,OAAM,IAAI,MACR,sCAAsC,6BACvC;AAEH,SAAO;;CAGT,AAAQ,kCAAkC,UAAkB;EAC1D,MAAM,UAAU,KAAK,KAAK,WAAW,KAAK;EAE1C,IAAI,yBAAyB,KAAK,KAAK,SAAS,cAAc,WAAW;EAEzE,MAAM,4BAA4B,KAAK,KACrC,SACA,kBAAkB,WACnB;AAED,MAAI,CAAC,GAAG,WAAW,uBAAuB,CACxC,KAAI,CAAC,GAAG,WAAW,0BAA0B,CAC3C,OAAM,IAAI,MACR,wCAAwC,SAAS,sBAAsB,uBAAuB,SAAS,0BAA0B,GAClI;MAED,0BAAyB;EAI7B,MAAM,gCAAgC,KAAK,KAKzC,wBACA,cACD;AACD,MAAI,CAAC,GAAG,WAAW,8BAA8B,CAC/C,OAAM,IAAI,MACR,mDAAmD,gCACpD;AAGH,SAAO;;;;;;CAOT,AAAQ,oBAAoB,cAAsB;AAChD,KAAG,UAAU,KAAK,QAAQ,aAAa,EAAE,EAAE,WAAW,MAAM,CAAC;EAM7D,MAAM,OAAO,6DAJM,KAAK,YACrB,KAAK,OAAO,KAAK,GAAG,QAAQ,MAAM,GAAG,CAAC,KAAK,GAAG,OAAO,GAAG,MAAM,CAC9D,KAAK,GAAG,CAE0E;AAErF,KAAG,cAAc,cAAc,KAAK;;CAGtC,AAAQ,YAAY,QAAoB;EACtC,MAAMC,QAAsB,EAAE;AAC9B,QAAM,KAAK,OAAO;AAClB,OAAK,qBAAqB,QAAQ,MAAM;AACxC,SAAO;;CAGT,AAAQ,qBAAqB,QAAoB,OAAqB;AACpE,OAAK,MAAM,QAAQ,OAAO,KAAK,UAAU;AACvC,SAAM,KAAK,KAAK;AAChB,QAAK,qBAAqB,MAAM,MAAM;;;CAI1C,AAAQ,gBAAgB,MAAkB;AACxC,MAAI,KAAK,WAAW,SAAS,KAAK,CAChC;AAGF,OAAK,WAAW,KAAK,KAAK;AAE1B,MAAI,KAAK,uBAAuB,SAAS,KAAK,CAC5C;AAGF,MAAI,KAAK,uBAAuB,MAAM,MAAM,EAAE,aAAa,KAAK,CAC9D;AAGF,MAAI,KAAK,OAAO,UACd,SAAQ,KAAK,eAAe,KAAK,iBAAiB,KAAK,CAAC;AAG1D,MACE,gBAAgB,OAAO,YACvB,gBAAgB,kBAChB,iBAAiB,KAAK,CAEtB,MAAK,kBAAkB,KAAK;WACnB,gBAAgB,IAAI,MAC7B,MAAK,oBAAoB,KAAK;WACrB,gBAAgB,IAAI,aAC7B,MAAK,2BAA2B,KAAK;WAC5B,gBAAgB,GAAG,OAC5B,MAAK,cAAc,KAAK;WACf,gBAAgB,SAAS,MAClC,MAAK,oBAAoB,KAAK;WACrB,gBAAgB,SAAS,QAClC,MAAK,oBAAoB,KAAK;WACrB,gBAAgB,OAAO,SAChC,MAAK,oBAAoB,KAAK;WACrB,gBAAgB,OAAO,KAChC,MAAK,wBAAwB,KAAK;WACzB,gBAAgB,OAAO,sBAChC,MAAK,eAAe,KAAK;WAChB,gBAAgB,IAAI,OAC7B;OAAI,KAAK,OAAO,2CACd,MAAK,oCAAoC,KAAK;;;CAKpD,AAAQ,uBACN,SACA,cACqE;EACrE,MAAM,WACJ,kBAAkB,QAAQ,UAAU,CAAC,GAAG,aAAa,KAAK,UAAU,GAAG,QACrE,OACA,IACD;EAEH,IAAI,QAAQ,KAAK,SAAS;EAC1B,IAAI,iBAAiB;AAErB,UAAQ,QAAQ,MAAhB;GACE,KAAK,OAAO,QAAQ,WAAW;GAC/B,KAAK,OAAO,QAAQ,WAAW;GAC/B,KAAK,OAAO,QAAQ,YAAY;GAChC,KAAK,OAAO,QAAQ,YAAY;GAChC,KAAK,OAAO,QAAQ,YAAY;AAC9B,qBAAiB;AACjB,YACE,SACA,IAAI,mBAAmB,MAAM,UAAU;KACrC,oBAAoB,CAAC,QAAQ;KAC7B,yBAAyB,CAAC,aAAa;KACvC,OAAO,KAAK,kCAAkC,SAAS;KACvD,UAAU,EACR,oBAAoB,mBAAmB,aACxC;KACF,CAAC;AACJ;GACF,KAAK,OAAO,QAAQ,YAAY;GAChC,KAAK,OAAO,QAAQ,YAAY;GAChC,KAAK,OAAO,QAAQ,YAAY;GAChC,KAAK,OAAO,QAAQ,YAAY;GAChC,KAAK,OAAO,QAAQ,YAAY;GAChC,KAAK,OAAO,QAAQ,YAAY;AAC9B,YACE,SACA,IAAI,OAAO,aAAa,MAAM,UAAU;KACtC,oBAAoB,CAAC,QAAQ;KAC7B,yBAAyB,CAAC,aAAa;KACvC,MAAM,OAAO,KAAK,UAAU,KAAK,2BAA2B,CAAC;KAC9D,CAAC;AACJ;GACF;AACE,YAAQ,IAAI,+BAA+B,QAAQ,UAAU,GAAG;AAChE;;AAGJ,OAAK,SAAS,YAAY;AAC1B,OAAK,uBAAuB,KAAK,MAAM;AACvC,SAAO;GAAE;GAAO;GAAgB;;CAGlC,AAAQ,oCAAoC,OAAkB;AAO5D,MANqB,KAAK,aACvB,MACC,aAAa,OAAO,yBACnB,EAAmC,mBAAmB,MAAM,SAChE,CAGC;EAGF,MAAM,YAAY,KAAK,iBAAiB,MAAM;EAC9C,MAAM,OAAO,IAAI,eACf,MACA,GAAG,UAAU,oCACb;GACE,YAAY;GACZ,SAAS,SAAS,QAAQ,EAAE;GAC5B,SAAS,OAAO,QAAQ;GACxB,SAAS;GACT,OAAO,KAAK,iBACV,iDACD;GACD,aAAa,KAAK,sCAAsC;GACzD,CACF;AACD,OAAK,eAAe,IAAI,eAAe,MAAM,CAAC;AAC9C,OAAK,YAAY,KAAK;EACtB,MAAM,EAAE,OAAO,mBAAmB,KAAK,uBACrC,KAAK,SACL,KAAK,aACN;AACD,OAAK,UAAU,MAAM;AAErB,OAAK,eAAe,2BAA2B,eAAe;AAE9D,MAAI,KAAK,OAAO,UACd,MAAK,eAAe,iBAAiB,YAAY,OAAO;AAG1D,OAAK,uBAAuB,KAAK,KAAK;EAEtC,MAAM,aAAa,OAAO;AAE1B,OAAK,qBAAqB,MAAM;GAC9B,KAAK,MAAM;GACX,OAAO;GACR,CAAC;AAEF,OAAK,YAAY,KAAK,WAAW;AACjC,OAAK,eAAe,iBAAiB,wBAAwB,OAAO;;CAGtE,AAAQ,eAAe,MAAoC;EACzD,MAAM,QAAQ,KAAK,aAChB,MACC,aAAa,IAAI,SAChB,EAAgB,aAAa,KAAK,eACtC;EAED,MAAM,OAAO,KAAK,aACf,MACC,aAAa,OAAO,YACnB,EAAsB,iBAAiB,KAAK,aAChD;AAED,MAAI,SAAS,MAAM;GAGjB,MAAM,aAAa,OAFD,KAAK,iBAAiB,MAAM;AAI9C,QAAK,qBAAqB,MAAM;IAC9B,KAAK,MAAM;IACX,OAAO;IACR,CAAC;AAEF,QAAK,YAAY,KAAK,WAAW;AACjC,QAAK,eAAe,iBAAiB,wBAAwB,OAAO;;;CAIxE,AAAQ,8BAA8B,OAAe;EACnD,MAAM,OAAO,IAAI,WAAW,eAAe,MAAM,eAAe,SAAS;GACvE,YAAY;GACZ,SAAS,SAAS,QAAQ,EAAE;GAC5B,SAAS,OAAO,QAAQ;GACxB,SAAS;GACT,OAAO,KAAK,iBAAiB,2BAA2B;GACxD,aAAa,EACX,cAAc,wBACf;GACF,CAAC;AACF,OAAK,YAAY,KAAK;AACtB,SAAO;;CAGT,AAAQ,cAAc,UAAqB;AACzC,WAAS,qBACP,GAAG,UAAU,oBACb,IAAI,QAAQ,kBAAkB,KAAK,uBAAuB,SAAS,CACpE;EAID,MAAM,aAAa,MAFN,KAAK,iBAAiB,SAAS;AAG5C,OAAK,uBAAuB,QAAQ,SAAS,aAAa;AAC1D,OAAK,YAAY,KAAK,WAAW;;CAGnC,AAAQ,oBAAoB,OAA0C;AAEpE,EAAC,MAAM,KAAK,aAAmC,sBAAsB,EACnE,gBAAgB,SAAS,eAAe,oBACzC;AACD,MAAI;AACF,GAAC,MAAc,iBACb,MAAM,KAAK,aACX;WACK,GAAG;AAEV,OAAI,EAAE,aAAa,aAAa,EAAE,QAAQ,SAAS,gBAAgB,EACjE,OAAM;;AAIV,OAAK,uBAAuB,SAAS,eACnC,IAAI,eAAe,kBAAkB,OAAO;GAC1C,kBAAkB,OAAO,iBAAiB;GAC1C,WAAW;GACX,eAAe;GAChB,CAAC,CACH;EAID,MAAM,aAAa,YAFN,KAAK,iBAAiB,MAAM;AAGzC,OAAK,uBAAuB,QAAQ,MAAM,YAAY;AACtD,OAAK,YAAY,KAAK,WAAW;;CAGnC,AAAQ,wBAAwB,MAAmB;EACjD,MAAM,EAAE,iBAAiB,KAAK,KAAK;EACnC,IAAI,aAAa;AACjB,MAAI,CAAC,CAAC,cAAc;GAClB,MAAM,cAAc,KAAK,eAAe,aAAa;AAErD,OAAI,CAAC,YACH,OAAM,IAAI,MAAM,uCAAuC,aAAa,GAAG;AAEzE,gBAAa,KAAK,iBAAiB,YAAY;;EAGjD,MAAM,uBAAuB,KAAK,gCAC/B,MAAM,CAAC,EAAE,mBACX;AACD,uBAAqB,qBAAqB;AAE1C,OAAK,UAAU,IAAI,QAAQ,eAAe,qBAAqB,SAAS,CAAC;EAEzE,MAAM,WAAW,KAAK,iBAAiB,KAAK;EAC5C,MAAM,aAAa,mBAAmB,WAAW,GAAG;AACpD,uBAAqB,QAAQ,cAAc;AAC3C,OAAK,YAAY,KAAK,WAAW;;CAGnC,AAAQ,oBAAoB,UAA2B;EACrD,MAAM,uBAAuB,KAAK,gCAC/B,MAAM,CAAC,EAAE,mBACX;AACD,uBAAqB,qBAAqB;EAE1C,MAAM,aAAa,KAAK,iBAAiB,SAAS;EAClD,MAAM,OAAO,IAAI,OAAO,KAAK,MAAM,UAAU,cAAc;GACzD;GACA,cAAc,EAAE,SAAS,CAAC,IAAI,EAAE;GAChC,SAAS,CAAC,IAAI,QAAQ,eAAe,qBAAqB,SAAS,CAAC;GACrE,CAAC;AAEF,OAAK,uBAAuB,KAAK,KAAK;EACtC,MAAM,aAAa,eAAe;AAClC,uBAAqB,QAAQ,cAAc;AAC3C,OAAK,YAAY,KAAK,WAAW;;CAGnC,AAAQ,oBAAoB,OAAkB;EAC5C,MAAM,uBAAuB,KAAK,gCAC/B,MAAM,CAAC,EAAE,gBAAgB,SAAS,MAAM,CAC1C;EAED,MAAM,eAAe,MAAM,gBACzB,IAAI,QAAQ,mBAAmB,qBAAqB,SAAS,CAC9D;AACD,OAAK,uBAAuB,KAAK,aAAa;EAE9C,MAAM,aAAa,YADD,KAAK,iBAAiB,MAAM;AAE9C,uBAAqB,QAAQ,MAAM,YAAY;AAC/C,OAAK,YAAY,KAAK,WAAW;AACjC,uBAAqB,gBAAgB,KAAK,MAAM;;CAGlD,AAAQ,2BAA2B,cAAgC;AACjE,MAAI,CAAC,aAAa,KAAK,MACrB;EAGF,MAAM,QAAQ,KAAK,SAChB,aAAa,KAAK,aAAqC,SACzD;AAED,MAAI,CAAC,MACH,OAAM,IAAI,MAAM,qBAAqB;EAGvC,MAAM,uBAAuB,KAAK,gCAC/B,MAAM,CAAC,EAAE,gBAAgB,SAAS,MAAM,CAC1C;EAED,MAAM,EAAE,iBAAiB,aAAa,KACnC;EAEH,MAAM,oBAAoB,MAAM,gBAC9B,IAAI,QAAQ,mBAAmB,qBAAqB,SAAS,CAC9D;AACD,EAAC,kBAAkB,KAAK,aAAqC,eAC3D;AAEF,OAAK,uBAAuB,KAAK,kBAAkB;EAEnD,MAAM,YAAY,KAAK,iBAAiB,MAAM;EAC9C,MAAM,aAAa,KAAK,iBAAiB,aAAa,KAAK,MAAM;AAEjE,uBAAqB,gBAAgB,KAAK,MAAM;EAChD,MAAM,aAAa,mBAAmB,UAAU,GAAG;AACnD,uBAAqB,QAAQ,MAAM,YAAY;AAC/C,OAAK,YAAY,KAAK,WAAW;;CAGnC,AAAQ,+BACN,gBACA;EACA,IAAIC;AAEJ,MAAI,eACF,wBAAuB,KAAK,uBAAuB,KAAK,eAAe;WAC9D,KAAK,uBAAuB,SAAS,EAC9C,wBAAuB,KAAK,uBAAuB;AAGrD,MAAI,CAAC,sBAAsB;AACzB,0BAAuB;IACrB,iBAAiB,EAAE;IACnB,oBAAoB;IACpB,SAAS,EAAE;IACX,UAAU,KAAK,8BACb,KAAK,uBAAuB,OAC7B;IACF;AACD,QAAK,uBAAuB,KAAK,qBAAqB;;AAExD,SAAO;;CAGT,AAAQ,YAAY,MAAuB;AACzC,OAAK,eACH,iBAAiB,iBACjB,KAAK,UAAU,KAAK,cAAc,MAAM,GAAG,KAAK,CAAC,CAAC,KAAK,GAAG,CAC3D;AACD,OAAK,eAAe,iBAAiB,mBAAmB,KAAK,YAAY;AAEzE,OAAK,gBACH,IAAI,QAAQ,gBAAgB;GAC1B,SAAS,CAAC,QAAQ;GAClB,QAAQ,OAAO;GACf,WAAW,CAAC,IAAI;GACjB,CAAC,CACH;;CAGH,AAAQ,kBAAkB,MAAuB;EAC/C,MAAM,EAAE,OAAO,mBAAmB,KAAK,uBACrC,KAAK,SACL,KAAK,gBAAgB,aAAa,OACnC;AACD,MAAI,CAAC,MACH;AAEF,OAAK,UAAU,MAAM;EAErB,MAAM,eAAe,KAAK,iBAAiB,KAAK;AAEhD,OAAK,eAAe,iBAAiB,oBAAoB,aAAa;AACtE,OAAK,eAAe,2BAA2B,eAAe;AAE9D,MAAI,KAAK,OAAO,UACd,MAAK,eAAe,iBAAiB,YAAY,OAAO;AAG1D,OAAK,YAAY,KAAK;AAEtB,OAAK,YAAY,KAAK,YAAY,aAAa,UAAU;AACzD,OAAK,YAAY,KAAK,YAAY,aAAa,QAAQ;AACvD,OAAK,YAAY,KAAK,YAAY,aAAa,UAAU;AACzD,OAAK,YAAY,KAAK,YAAY,aAAa,WAAW;AAE1D,OAAK,qBAAqB,KAAK;;CAGjC,AAAO,iBAAiB,WAAuB;EAC7C,IAAI,gBAAgB,UAAU,KAAK;EACnC,MAAM,EAAE,SAAS,MAAM,GAAG,KAAK;AAE/B,MAAI,cAAc,WAAW,KAAK,GAAG,CACnC,iBAAgB,cAAc,UAAU,KAAK,GAAG,SAAS,EAAE;AAG7D,SAAO,KAAK,UAAU,cAAc;;CAGtC,AAAQ,UAAU,MAAc;AAE9B,SAAO,KACJ,QAAQ,UAAU,IAAI,CACtB,QAAQ,YAAY,GAAG,CACvB,QAAQ,WAAW,OAAO,GAAG,aAAa,CAAC,CAC3C,QAAQ,OAAO,GAAG,CAClB,QAAQ,SAAS,OAAO,GAAG,aAAa,CAAC;;CAG9C,AAAQ,SAAS,UAAyC;AAMxD,SALc,KAAK,aAChB,SACC,gBAAgB,IAAI,SAAU,KAAmB,aAAa,SACjE;;CAKH,AAAQ,eAAe,cAAoD;AAQzE,SAPoB,KAAK,aACtB,UACE,gBAAgB,OAAO,YACtB,KAAK,YAAY,SAAS,uBAC3B,KAA0B,iBAAiB,aAC/C;;CAKH,AAAQ,cAAc,OAAqB;AACzC,MAAI,MAAM,QAAQ;GAChB,MAAM,cAAe,MAAsB;AAC3C,OAAI,YAAa,QAAO,KAAK,cAAc,YAAY;AACvD,UAAO;QAEP,QAAO;;CAIX,AAAQ,YACN,YACA,QACe;AACf,MAAI,CAAC,OACH,UAAS,KAAK,cAAc,MAAM,GAAG,KAAK,CAAC;AAG7C,OAAK,MAAM,QAAQ,OAAO,KAAK,UAAU;AACvC,OAAI,WAAW,KAAK,CAClB,QAAO;GAET,MAAM,sBAAsB,KAAK,YAAe,YAAY,KAAK;AACjE,OAAI,oBACF,QAAO;;;CAOb,AAAQ,qBACN,MACA,UACA;AACA,OAAK,MAAMC,QAAM,KAAK,aACpB,KAAIA,KAAG,aAAa,MAAM;AACxB,OAAI,SACF,MAAG,QAAQ,SAAS,OAAO,SAAS;AAEtC;;EAIJ,MAAMC,OAAkB;GACtB,UAAU;GACV,SAAS,EAAE;GACZ;AAED,MAAI,SACF,MAAG,QAAQ,SAAS,OAAO,SAAS;AAGtC,OAAK,aAAa,KAAKD,KAAG;;CAG5B,AAAQ,iBAAiB,UAAkB;EACzC,MAAM,MAAM,KAAK,KAAK,WAAW,YAAY,SAAS;AAEtD,MAAI,GAAG,WAAW,IAAI,CACpB,QAAO;EAGT,MAAM,OAAO,KAAK,KAAK,WAAW,eAAe,SAAS;AAE1D,MAAI,GAAG,WAAW,KAAK,CACrB,QAAO;AAGT,QAAM,IAAI,MAAM,YAAY,IAAI,OAAO,KAAK,mBAAmB"}
|