serverless-spy 2.3.17 → 2.3.18

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": 774
4047
+ "line": 776
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.17",
4350
- "fingerprint": "An7Y7/sDcjaiN8HqVqUGK5rhBPZfnOra8u0KqR/j2tg="
4349
+ "version": "2.3.18",
4350
+ "fingerprint": "1+VyOSSBMc/uINp5FeAgnRMs4NrJi9RHmEjhq0BUN/g="
4351
4351
  }
@@ -1 +1 @@
1
- v2.3.17
1
+ v2.3.18
@@ -415,7 +415,10 @@ class ServerlessSpy extends constructs_1.Construct {
415
415
  table.node.defaultChild.streamSpecification = {
416
416
  streamViewType: dynamoDb.StreamViewType.NEW_AND_OLD_IMAGES,
417
417
  };
418
- table.tableStreamArn = table.node.defaultChild.attrStreamArn;
418
+ Object.assign(table, {
419
+ tableStreamArn: table.node.defaultChild
420
+ .attrStreamArn,
421
+ });
419
422
  this.lambdaSubscriptionMain.function.addEventSource(new dynamoDbStream.DynamoEventSource(table, {
420
423
  startingPosition: lambda.StartingPosition.LATEST,
421
424
  batchSize: 1,
@@ -622,5 +625,5 @@ class ServerlessSpy extends constructs_1.Construct {
622
625
  }
623
626
  exports.ServerlessSpy = ServerlessSpy;
624
627
  _a = JSII_RTTI_SYMBOL_1;
625
- ServerlessSpy[_a] = { fqn: "serverless-spy.ServerlessSpy", version: "2.3.17" };
626
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2VydmVybGVzc1NweS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9TZXJ2ZXJsZXNzU3B5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3Qiw4RUFBc0U7QUFDdEUsNkNBUXFCO0FBQ3JCLHFEQUFxRDtBQUNyRCxpREFBaUQ7QUFDakQsMERBQTBEO0FBQzFELGlEQUE2QztBQUM3QyxpREFBaUQ7QUFDakQsdURBSWdDO0FBQ2hDLHVFQUF1RTtBQUN2RSxtRkFBc0U7QUFDdEUsNERBQTREO0FBQzVELHFFQUErRDtBQUMvRCx5Q0FBeUM7QUFDekMsNERBQTREO0FBQzVELDJDQUEyQztBQUMzQyw2REFBNkQ7QUFDN0QsMkNBQTJDO0FBQzNDLDJDQUFtRDtBQUNuRCxnRUFBNkQ7QUFtQjdELE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxJQUFnQixFQUEyQixFQUFFLENBQ3JFLGNBQWMsSUFBSSxJQUFJLElBQUksYUFBYSxJQUFJLElBQUksSUFBSSxTQUFTLElBQUksSUFBSSxDQUFDO0FBRXZFLE1BQU0sb0NBQW9DLEdBQUcsMEJBQTBCLENBQUM7QUFFeEUsTUFBYSxhQUFjLFNBQVEsc0JBQVM7SUFVMUMsWUFDRSxLQUFnQixFQUNoQixFQUFVLEVBQ0YsS0FBMEI7UUFFbEMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUZULFVBQUssR0FBTCxLQUFLLENBQXFCO1FBWjVCLDJCQUFzQixHQUFpQixFQUFFLENBQUM7UUFDMUMsMkJBQXNCLEdBQXlCLEVBQUUsQ0FBQztRQUVsRCxpQkFBWSxHQUFrQixFQUFFLENBQUM7UUFDbEMsZ0JBQVcsR0FBYSxFQUFFLENBQUM7UUFDMUIsZUFBVSxHQUFpQixFQUFFLENBQUM7UUFDOUIsYUFBUSxHQUEyQyxFQUFFLENBQUM7UUFVNUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FDOUIsSUFBSSxDQUFDLGFBQWEsQ0FB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O1FBRTNELElBQUksRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3hCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsWUFBWSxHQUFHLFFBQVEsSUFBSSxtQkFBbUIsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7O0FBNXpCSCxzQ0E2ekJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IFB5dGhvbkxheWVyVmVyc2lvbiB9IGZyb20gJ0Bhd3MtY2RrL2F3cy1sYW1iZGEtcHl0aG9uLWFscGhhJztcbmltcG9ydCB7XG4gIGF3c19pYW0sXG4gIEJ1bmRsaW5nRmlsZUFjY2VzcyxcbiAgQ2ZuT3V0cHV0LFxuICBjdXN0b21fcmVzb3VyY2VzLFxuICBEdXJhdGlvbixcbiAgTmVzdGVkU3RhY2ssXG4gIFN0YWNrLFxufSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBkeW5hbW9EYiBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZHluYW1vZGInO1xuaW1wb3J0ICogYXMgZXZlbnRzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1ldmVudHMnO1xuaW1wb3J0ICogYXMgdGFyZ2V0cyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZXZlbnRzLXRhcmdldHMnO1xuaW1wb3J0IHsgRWZmZWN0IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBsYW1iZGEgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYSc7XG5pbXBvcnQge1xuICBBcmNoaXRlY3R1cmUsXG4gIElMYXllclZlcnNpb24sXG4gIFNpbmdsZXRvbkZ1bmN0aW9uLFxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCAqIGFzIGR5bmFtb0RiU3RyZWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEtZXZlbnQtc291cmNlcyc7XG5pbXBvcnQgeyBTcXNFdmVudFNvdXJjZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEtZXZlbnQtc291cmNlcyc7XG5pbXBvcnQgKiBhcyBsYW1iZGFOb2RlIGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEtbm9kZWpzJztcbmltcG9ydCB7IE5vZGVqc0Z1bmN0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ub2RlanMnO1xuaW1wb3J0ICogYXMgczMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzJztcbmltcG9ydCAqIGFzIHMzbm90aWYgZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzLW5vdGlmaWNhdGlvbnMnO1xuaW1wb3J0ICogYXMgc25zIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zbnMnO1xuaW1wb3J0ICogYXMgc25zU3VicyBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc25zLXN1YnNjcmlwdGlvbnMnO1xuaW1wb3J0ICogYXMgc3FzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zcXMnO1xuaW1wb3J0IHsgQ29uc3RydWN0LCBJQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBlbnZWYXJpYWJsZU5hbWVzIH0gZnJvbSAnLi9jb21tb24vZW52VmFyaWFibGVOYW1lcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmVybGVzc1NweVByb3BzIHtcbiAgcmVhZG9ubHkgZ2VuZXJhdGVTcHlFdmVudHNGaWxlTG9jYXRpb24/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHNweVNxc1dpdGhOb1N1YnNjcmlwdGlvbkFuZERyb3BBbGxNZXNzYWdlcz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGRlYnVnTW9kZT86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3B5RmlsdGVyIHtcbiAgcmVhZG9ubHkgc3B5TGFtYmRhPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3B5U3FzPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3B5U25zVG9waWM/OiBib29sZWFuO1xuICByZWFkb25seSBzcHlTbnNTdWJzcmlwdGlvbj86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHNweUV2ZW50QnJpZGdlPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3B5RXZlbnRCcmlkZ2VSdWxlPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3B5UzM/OiBib29sZWFuO1xuICByZWFkb25seSBzcHlEeW5hbW9EQj86IGJvb2xlYW47XG59XG5cbmNvbnN0IGlzTGFtYmRhRnVuY3Rpb24gPSAobm9kZTogSUNvbnN0cnVjdCk6IG5vZGUgaXMgbGFtYmRhLkZ1bmN0aW9uID0+XG4gICdmdW5jdGlvbk5hbWUnIGluIG5vZGUgJiYgJ2Z1bmN0aW9uQXJuJyBpbiBub2RlICYmICdydW50aW1lJyBpbiBub2RlO1xuXG5jb25zdCBzZXJ2ZXJsZXNzU3B5SW90RW5kcG9pbnRDck5hbWVQcmVmaXggPSAnU2VydmVybGVzc1NweUlvdEVuZHBvaW50JztcblxuZXhwb3J0IGNsYXNzIFNlcnZlcmxlc3NTcHkgZXh0ZW5kcyBDb25zdHJ1Y3Qge1xuICBwcml2YXRlIGNyZWF0ZWRSZXNvdXJjZXNCeVNTcHk6IElDb25zdHJ1Y3RbXSA9IFtdO1xuICBwcml2YXRlIGxhbWJkYVN1YnNjcmlwdGlvblBvb2w6IExhbWJkYVN1YnNjcmlwdGlvbltdID0gW107XG4gIHByaXZhdGUgbGFtYmRhU3Vic2NyaXB0aW9uTWFpbjogTGFtYmRhU3Vic2NyaXB0aW9uO1xuICBwcml2YXRlIGxhbWJkYXNTcGllZDogTGFtYmRhU3BpZWRbXSA9IFtdO1xuICBwdWJsaWMgc2VydmljZUtleXM6IHN0cmluZ1tdID0gW107XG4gIHByaXZhdGUgc3BpZWROb2RlczogSUNvbnN0cnVjdFtdID0gW107XG4gIHByaXZhdGUgbGF5ZXJNYXA6IFBhcnRpYWw8UmVjb3JkPHN0cmluZywgSUxheWVyVmVyc2lvbj4+ID0ge307XG4gIHByaXZhdGUgcmVhZG9ubHkgaW90RW5kcG9pbnQ6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgcHJpdmF0ZSBwcm9wcz86IFNlcnZlcmxlc3NTcHlQcm9wc1xuICApIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgY29uc3Qgcm9vdFN0YWNrID0gdGhpcy5jbGVhbk5hbWUoXG4gICAgICB0aGlzLmZpbmRSb290U3RhY2soU3RhY2sub2YodGhpcykpLm5vZGUuaWRcbiAgICApO1xuXG4gICAgY29uc3QgZ2V0SW9URW5kcG9pbnQgPSBuZXcgY3VzdG9tX3Jlc291cmNlcy5Bd3NDdXN0b21SZXNvdXJjZShcbiAgICAgIHRoaXMsXG4gICAgICBzZXJ2ZXJsZXNzU3B5SW90RW5kcG9pbnRDck5hbWVQcmVmaXgsXG4gICAgICB7XG4gICAgICAgIG9uQ3JlYXRlOiB7XG4gICAgICAgICAgc2VydmljZTogJ0lvdCcsXG4gICAgICAgICAgYWN0aW9uOiAnZGVzY3JpYmVFbmRwb2ludCcsXG4gICAgICAgICAgcGh5c2ljYWxSZXNvdXJjZUlkOlxuICAgICAgICAgICAgY3VzdG9tX3Jlc291cmNlcy5QaHlzaWNhbFJlc291cmNlSWQuZnJvbVJlc3BvbnNlKCdlbmRwb2ludEFkZHJlc3MnKSxcbiAgICAgICAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICAgICAgICBlbmRwb2ludFR5cGU6ICdpb3Q6RGF0YS1BVFMnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIG9uVXBkYXRlOiB7XG4gICAgICAgICAgc2VydmljZTogJ0lvdCcsXG4gICAgICAgICAgYWN0aW9uOiAnZGVzY3JpYmVFbmRwb2ludCcsXG4gICAgICAgICAgcGh5c2ljYWxSZXNvdXJjZUlkOlxuICAgICAgICAgICAgY3VzdG9tX3Jlc291cmNlcy5QaHlzaWNhbFJlc291cmNlSWQuZnJvbVJlc3BvbnNlKCdlbmRwb2ludEFkZHJlc3MnKSxcbiAgICAgICAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICAgICAgICBlbmRwb2ludFR5cGU6ICdpb3Q6RGF0YS1BVFMnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIGluc3RhbGxMYXRlc3RBd3NTZGs6IGZhbHNlLFxuICAgICAgICBwb2xpY3k6IGN1c3RvbV9yZXNvdXJjZXMuQXdzQ3VzdG9tUmVzb3VyY2VQb2xpY3kuZnJvbVNka0NhbGxzKHtcbiAgICAgICAgICByZXNvdXJjZXM6IGN1c3RvbV9yZXNvdXJjZXMuQXdzQ3VzdG9tUmVzb3VyY2VQb2xpY3kuQU5ZX1JFU09VUkNFLFxuICAgICAgICB9KSxcbiAgICAgICAgZnVuY3Rpb25OYW1lOiBzZXJ2ZXJsZXNzU3B5SW90RW5kcG9pbnRDck5hbWVQcmVmaXggKyByb290U3RhY2ssXG4gICAgICB9XG4gICAgKTtcbiAgICB0aGlzLmlvdEVuZHBvaW50ID0gZ2V0SW9URW5kcG9pbnQuZ2V0UmVzcG9uc2VGaWVsZCgnZW5kcG9pbnRBZGRyZXNzJyk7XG5cbiAgICB0aGlzLmNyZWF0ZWRSZXNvdXJjZXNCeVNTcHkucHVzaChnZXRJb1RFbmRwb2ludCk7XG5cbiAgICBuZXcgQ2ZuT3V0cHV0KHRoaXMsICdTZXJ2ZXJsZXNzU3B5SW9URW5kcG9pbnQnLCB7XG4gICAgICBrZXk6ICdTZXJ2ZXJsZXNzU3B5V3NVcmwnLFxuICAgICAgdmFsdWU6IGAke3RoaXMuaW90RW5kcG9pbnR9LyR7cm9vdFN0YWNrfWAsXG4gICAgfSk7XG5cbiAgICB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvbk1haW4gPSB0aGlzLnByb3ZpZGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbigpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXREZWZhdWx0TGFtYmRhRW52aXJvbm1lbnRWYXJpYWJsZXMoKTogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIE5PREVfT1BUSU9OUzogJy0tZW5hYmxlLXNvdXJjZS1tYXBzJyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRhbGl6ZSBzcHlpbmcgb24gcmVzb3VyY2VzIGdpdmVuIGFzIHBhcmFtZXRlci5cbiAgICogQHBhcmFtIG5vZGVzIFdoaWNoIHJlb3VyY2VzIGFuZCB0aGVpciBjaGlsZHJlbiB0byBzcHkgb24uXG4gICAqL1xuICBwdWJsaWMgc3B5Tm9kZXMobm9kZXM6IElDb25zdHJ1Y3RbXSkge1xuICAgIGZvciAoY29uc3Qgbm9kZSBvZiBub2Rlcykge1xuICAgICAgbGV0IG5zID0gdGhpcy5nZXRBbGxOb2Rlcyhub2RlKTtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlOb2Rlcyhucyk7XG4gICAgfVxuXG4gICAgdGhpcy5maW5hbGl6ZVNweSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEluaXRhbGl6ZSBzcHlpbmcgb24gcmVzb3VyY2VzLlxuICAgKiBAcGFyYW0gZmlsdGVyIExpbWl0IHdoaWNoIHJlc291cmNlcyB0byBzcHkgb24uXG4gICAqL1xuICBwdWJsaWMgc3B5KGZpbHRlcj86IFNweUZpbHRlcikge1xuICAgIGxldCBub2RlcyA9IHRoaXMuZ2V0QWxsTm9kZXMoU3RhY2sub2YodGhpcykpO1xuXG4gICAgY29uc3QgZmlsdGVyV2l0aERlZmF1bHRzOiBSZXF1aXJlZDxTcHlGaWx0ZXI+ID0ge1xuICAgICAgc3B5TGFtYmRhOiB0cnVlLFxuICAgICAgc3B5U3FzOiB0cnVlLFxuICAgICAgc3B5U25zVG9waWM6IHRydWUsXG4gICAgICBzcHlTbnNTdWJzcmlwdGlvbjogdHJ1ZSxcbiAgICAgIHNweUV2ZW50QnJpZGdlOiB0cnVlLFxuICAgICAgc3B5RXZlbnRCcmlkZ2VSdWxlOiB0cnVlLFxuICAgICAgc3B5UzM6IHRydWUsXG4gICAgICBzcHlEeW5hbW9EQjogdHJ1ZSxcbiAgICAgIC4uLmZpbHRlcixcbiAgICB9O1xuXG4gICAgY29uc3QgQ1JJRCA9XG4gICAgICAnQVdTJyArXG4gICAgICBjdXN0b21fcmVzb3VyY2VzLkF3c0N1c3RvbVJlc291cmNlLlBST1ZJREVSX0ZVTkNUSU9OX1VVSUQucmVwbGFjZShcbiAgICAgICAgLy0vZ2ksXG4gICAgICAgICcnXG4gICAgICApLnN1YnN0cmluZygwLCAxNik7XG5cbiAgICBub2RlcyA9IG5vZGVzLmZpbHRlcigobm9kZSkgPT4ge1xuICAgICAgaWYgKFxuICAgICAgICAvLyBJZ25vcmUgdGhlIGN1c3RvbSByZXNvdXJjZSBhbmQgdGhlIFByb3ZpZGVyIChhcyB3ZWxsIGFzIGFueSBvdGhlciBQcm92aWRlcnMgdXNpbmcgdGhlIHNhbWUgcHJvdmlkZXIgZnVuY3Rpb24pLCBvdGhlcndpc2Ugd2UgY2F1c2VcbiAgICAgICAgLy8gY2lyY3VsYXIgZGVwZW5kZW5jaWVzXG4gICAgICAgIG5vZGUubm9kZS5pZC5zdGFydHNXaXRoKENSSUQpIHx8XG4gICAgICAgIG5vZGUubm9kZS5pZCA9PT0gJ1Byb3ZpZGVyJyB8fFxuICAgICAgICAvLyBJZ25vcmUgc2luZ2xldG9uIGZ1bmN0aW9ucyBhcyB0aGV5IGNhbiBjYXVzZSB2ZXJ5IG9kZCBiZWhhdmlvciBhbmQgY3Jhc2hlc1xuICAgICAgICBub2RlIGluc3RhbmNlb2YgU2luZ2xldG9uRnVuY3Rpb25cbiAgICAgICkge1xuICAgICAgICBpZiAodGhpcy5wcm9wcz8uZGVidWdNb2RlKSB7XG4gICAgICAgICAgY29uc29sZS5pbmZvKGBTa2lwcGluZyAke25vZGUubm9kZS5pZH1gKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5TGFtYmRhICYmXG4gICAgICAgIChub2RlIGluc3RhbmNlb2YgbGFtYmRhLkZ1bmN0aW9uIHx8XG4gICAgICAgICAgbm9kZSBpbnN0YW5jZW9mIE5vZGVqc0Z1bmN0aW9uIHx8XG4gICAgICAgICAgaXNMYW1iZGFGdW5jdGlvbihub2RlKSlcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoZmlsdGVyV2l0aERlZmF1bHRzLnNweVNuc1RvcGljICYmIG5vZGUgaW5zdGFuY2VvZiBzbnMuVG9waWMpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5U25zU3Vic3JpcHRpb24gJiZcbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIHNucy5TdWJzY3JpcHRpb25cbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoZmlsdGVyV2l0aERlZmF1bHRzLnNweVMzICYmIG5vZGUgaW5zdGFuY2VvZiBzMy5CdWNrZXQpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5RHluYW1vREIgJiZcbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIGR5bmFtb0RiLlRhYmxlXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5RHluYW1vREIgJiZcbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIGR5bmFtb0RiLlRhYmxlVjJcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGZpbHRlcldpdGhEZWZhdWx0cy5zcHlFdmVudEJyaWRnZSAmJlxuICAgICAgICBub2RlIGluc3RhbmNlb2YgZXZlbnRzLkV2ZW50QnVzXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5RXZlbnRCcmlkZ2VSdWxlICYmXG4gICAgICAgIG5vZGUgaW5zdGFuY2VvZiBldmVudHMuUnVsZVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZmlsdGVyV2l0aERlZmF1bHRzLnNweVNxcyAmJlxuICAgICAgICBub2RlIGluc3RhbmNlb2YgbGFtYmRhLkNmbkV2ZW50U291cmNlTWFwcGluZ1xuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZmlsdGVyV2l0aERlZmF1bHRzLnNweVNxcyAmJlxuICAgICAgICB0aGlzLnByb3BzPy5zcHlTcXNXaXRoTm9TdWJzY3JpcHRpb25BbmREcm9wQWxsTWVzc2FnZXMgJiZcbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIHNxcy5RdWV1ZVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSk7XG5cbiAgICB0aGlzLmludGVybmFsU3B5Tm9kZXMobm9kZXMpO1xuICAgIHRoaXMuZmluYWxpemVTcHkoKTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlOb2Rlcyhub2RlczogSUNvbnN0cnVjdFtdKSB7XG4gICAgZm9yIChjb25zdCBub2RlIG9mIG5vZGVzKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5Tm9kZShub2RlKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGZpbmFsaXplU3B5KCkge1xuICAgIC8vc2V0IG1hcHBpbmcgcHJvcGVydHkgZm9yIGFsbCBmdW5jdGlvbnMgd2UgY3JlYXRlZFxuICAgIGZvciAoY29uc3QgZnVuYyBvZiB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2wpIHtcbiAgICAgIGZ1bmMuZnVuY3Rpb24uYWRkRW52aXJvbm1lbnQoXG4gICAgICAgIGVudlZhcmlhYmxlTmFtZXMuU1NQWV9JTkZSQV9NQVBQSU5HLFxuICAgICAgICBKU09OLnN0cmluZ2lmeShmdW5jLm1hcHBpbmcpXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vc2V0IG1hcHBpbmcgcHJvcGVydHkgZm9yIGFsbCBmdW5jdGlvbnMgd2Ugc3B5IG9uXG4gICAgZm9yIChjb25zdCBmdW5jIG9mIHRoaXMubGFtYmRhc1NwaWVkKSB7XG4gICAgICBmdW5jLmZ1bmN0aW9uLmFkZEVudmlyb25tZW50KFxuICAgICAgICBlbnZWYXJpYWJsZU5hbWVzLlNTUFlfSU5GUkFfTUFQUElORyxcbiAgICAgICAgSlNPTi5zdHJpbmdpZnkoZnVuYy5tYXBwaW5nKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wcm9wcz8uZ2VuZXJhdGVTcHlFdmVudHNGaWxlTG9jYXRpb24pIHtcbiAgICAgIHRoaXMud3JpdGVTcHlFdmVudHNDbGFzcyh0aGlzLnByb3BzPy5nZW5lcmF0ZVNweUV2ZW50c0ZpbGVMb2NhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRFeHRlbnNpb25Bc3NldExvY2F0aW9uKCkge1xuICAgIGxldCBleHRlbnNpb25Bc3NldExvY2F0aW9uID0gcGF0aC5qb2luKFxuICAgICAgX19kaXJuYW1lLFxuICAgICAgJy4uL2V4dGVuc2lvbi9kaXN0L2xheWVyJ1xuICAgICk7XG5cbiAgICBjb25zdCBleHRlbnNpb25Bc3NldExvY2F0aW9uQWx0ID0gcGF0aC5qb2luKFxuICAgICAgX19kaXJuYW1lLFxuICAgICAgJy4uL2xpYi9leHRlbnNpb24vZGlzdC9sYXllcidcbiAgICApO1xuXG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKGV4dGVuc2lvbkFzc2V0TG9jYXRpb24pKSB7XG4gICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkFsdCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBGb2xkZXIgd2l0aCBhc3NldHMgZm9yIGV4dGVuc2lvbiBkb2VzIG5vdCBleGlzdHMgYXQgJHtleHRlbnNpb25Bc3NldExvY2F0aW9ufSBvciBhdCAke2V4dGVuc2lvbkFzc2V0TG9jYXRpb25BbHR9IGBcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGV4dGVuc2lvbkFzc2V0TG9jYXRpb24gPSBleHRlbnNpb25Bc3NldExvY2F0aW9uQWx0O1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGV4dGVuc2lvbkFzc2V0TG9jYXRpb25XcmFwcGVyID0gcGF0aC5qb2luKFxuICAgICAgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbixcbiAgICAgICdzcHktd3JhcHBlcidcbiAgICApO1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhleHRlbnNpb25Bc3NldExvY2F0aW9uV3JhcHBlcikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFdyYXBwZXIgc2NyaXB0IGZvciBleHRlbnNpb24gZG9lcyBub3QgZXhpc3RzICR7ZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbn1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGV4dGVuc2lvbkFzc2V0TG9jYXRpb25Db2RlID0gcGF0aC5qb2luKFxuICAgICAgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbixcbiAgICAgIGBub2RlanMvbm9kZV9tb2R1bGVzL2ludGVyY2VwdG9yLmpzYFxuICAgICk7XG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKGV4dGVuc2lvbkFzc2V0TG9jYXRpb25Db2RlKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgQ29kZSBmb3IgZXh0ZW5zaW9uIGRvZXMgbm90IGV4aXN0cyAke2V4dGVuc2lvbkFzc2V0TG9jYXRpb25Db2RlfWBcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBleHRlbnNpb25Bc3NldExvY2F0aW9uO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRMYW5ndWFnZUV4dGVuc2lvbkFzc2V0TG9jYXRpb24obGFuZ3VhZ2U6IHN0cmluZykge1xuICAgIGNvbnN0IHJvb3REaXIgPSBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4nKTtcblxuICAgIGxldCBleHRlbnNpb25Bc3NldExvY2F0aW9uID0gcGF0aC5qb2luKHJvb3REaXIsIGBleHRlbnNpb25zLyR7bGFuZ3VhZ2V9YCk7XG5cbiAgICBjb25zdCBleHRlbnNpb25Bc3NldExvY2F0aW9uQWx0ID0gcGF0aC5qb2luKFxuICAgICAgcm9vdERpcixcbiAgICAgIGBsaWIvZXh0ZW5zaW9ucy8ke2xhbmd1YWdlfWBcbiAgICApO1xuXG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKGV4dGVuc2lvbkFzc2V0TG9jYXRpb24pKSB7XG4gICAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkFsdCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBGb2xkZXIgd2l0aCBhc3NldHMgZm9yIGV4dGVuc2lvbiBmb3IgJHtsYW5ndWFnZX0gZG9lcyBub3QgZXhpc3RzIGF0ICR7ZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbn0gb3IgYXQgJHtleHRlbnNpb25Bc3NldExvY2F0aW9uQWx0fSBgXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBleHRlbnNpb25Bc3NldExvY2F0aW9uID0gZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkFsdDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBleHRlbnNpb25Bc3NldExvY2F0aW9uV3JhcHBlciA9IHBhdGguam9pbihcbiAgICAgIC8vIGV4dGVuc2lvbkFzc2V0TG9jYXRpb24uc3Vic3RyaW5nKFxuICAgICAgLy8gICAwLFxuICAgICAgLy8gICBleHRlbnNpb25Bc3NldExvY2F0aW9uLmxhc3RJbmRleE9mKHBhdGguc2VwKVxuICAgICAgLy8gKSxcbiAgICAgIGV4dGVuc2lvbkFzc2V0TG9jYXRpb24sXG4gICAgICAnc3B5LXdyYXBwZXInXG4gICAgKTtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbldyYXBwZXIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBXcmFwcGVyIHNjcmlwdCBmb3IgZXh0ZW5zaW9uIGRvZXMgbm90IGV4aXN0cyBhdCAke2V4dGVuc2lvbkFzc2V0TG9jYXRpb25XcmFwcGVyfWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGV4dGVuc2lvbkFzc2V0TG9jYXRpb247XG4gIH1cblxuICAvKipcbiAgICogV3JpdGUgU3B5RXZlbnRzIGNsYXNzLCB3aGljaCBoZWxwcyB3aXRoIHdyaXRpbmcgdGhlIGNvZGUgZm9yIHRlc3RzLlxuICAgKiBAcGFyYW0gZmlsZUxvY2F0aW9uXG4gICAqL1xuICBwcml2YXRlIHdyaXRlU3B5RXZlbnRzQ2xhc3MoZmlsZUxvY2F0aW9uOiBzdHJpbmcpIHtcbiAgICBmcy5ta2RpclN5bmMocGF0aC5kaXJuYW1lKGZpbGVMb2NhdGlvbiksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXG4gICAgY29uc3QgcHJvcGVydGllcyA9IHRoaXMuc2VydmljZUtleXNcbiAgICAgIC5tYXAoKHNrKSA9PiBgICAke3NrLnJlcGxhY2UoLyMvZywgJycpfTogJyR7c2t9JyA9ICcke3NrfSc7XFxuYClcbiAgICAgIC5qb2luKCcnKTtcblxuICAgIGNvbnN0IGNvZGUgPSBgLyogZXNsaW50LWRpc2FibGUgKi9cXG5leHBvcnQgY2xhc3MgU2VydmVybGVzc1NweUV2ZW50cyB7XFxuJHtwcm9wZXJ0aWVzfX1cXG5gO1xuXG4gICAgZnMud3JpdGVGaWxlU3luYyhmaWxlTG9jYXRpb24sIGNvZGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRBbGxOb2RlcyhwYXJlbnQ6IElDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBub2RlczogSUNvbnN0cnVjdFtdID0gW107XG4gICAgbm9kZXMucHVzaChwYXJlbnQpO1xuICAgIHRoaXMuZ2V0QWxsTm9kZXNSZWN1cnNpdmUocGFyZW50LCBub2Rlcyk7XG4gICAgcmV0dXJuIG5vZGVzO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRBbGxOb2Rlc1JlY3Vyc2l2ZShwYXJlbnQ6IElDb25zdHJ1Y3QsIG5vZGVzOiBJQ29uc3RydWN0W10pIHtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgcGFyZW50Lm5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIG5vZGVzLnB1c2gobm9kZSk7XG4gICAgICB0aGlzLmdldEFsbE5vZGVzUmVjdXJzaXZlKG5vZGUsIG5vZGVzKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5Tm9kZShub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgaWYgKHRoaXMuc3BpZWROb2Rlcy5pbmNsdWRlcyhub2RlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuc3BpZWROb2Rlcy5wdXNoKG5vZGUpO1xuXG4gICAgaWYgKHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5pbmNsdWRlcyhub2RlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2wuZmluZCgocykgPT4gcy5mdW5jdGlvbiA9PT0gbm9kZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5wcm9wcz8uZGVidWdNb2RlKSB7XG4gICAgICBjb25zb2xlLmluZm8oJ1NweSBvbiBub2RlJywgdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKG5vZGUpKTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBub2RlIGluc3RhbmNlb2YgbGFtYmRhLkZ1bmN0aW9uIHx8XG4gICAgICBub2RlIGluc3RhbmNlb2YgTm9kZWpzRnVuY3Rpb24gfHxcbiAgICAgIGlzTGFtYmRhRnVuY3Rpb24obm9kZSlcbiAgICApIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlMYW1iZGEobm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2Ygc25zLlRvcGljKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5U25zVG9waWMobm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2Ygc25zLlN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweVNuc1N1YnNjcmlwdGlvbihub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBzMy5CdWNrZXQpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlTMyhub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBkeW5hbW9EYi5UYWJsZSkge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweUR5bmFtb2RiKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIGR5bmFtb0RiLlRhYmxlVjIpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlEeW5hbW9kYihub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBldmVudHMuRXZlbnRCdXMpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlFdmVudEJ1cyhub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBldmVudHMuUnVsZSkge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweUV2ZW50QnVzUnVsZShub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBsYW1iZGEuQ2ZuRXZlbnRTb3VyY2VNYXBwaW5nKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5U3FzKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHNxcy5RdWV1ZSkge1xuICAgICAgaWYgKHRoaXMucHJvcHM/LnNweVNxc1dpdGhOb1N1YnNjcmlwdGlvbkFuZERyb3BBbGxNZXNzYWdlcykge1xuICAgICAgICB0aGlzLmludGVybmFsU3B5U3B5U3FzV2l0aE5vU3Vic2NyaXB0aW9uKG5vZGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0RXh0ZW5zaW9uRm9yUnVudGltZShcbiAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZSxcbiAgICBhcmNoaXRlY3R1cmU6IGxhbWJkYS5BcmNoaXRlY3R1cmVcbiAgKTogeyBsYXllcjogbGFtYmRhLklMYXllclZlcnNpb247IHNweVdyYXBwZXJQYXRoOiBzdHJpbmcgfSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgbGF5ZXJLZXkgPVxuICAgICAgYHNzcHlfZXh0ZW5zaW9uXyR7cnVudGltZS50b1N0cmluZygpfV8ke2FyY2hpdGVjdHVyZS5uYW1lLnRvU3RyaW5nKCl9YC5yZXBsYWNlKFxuICAgICAgICAvXFwuL2csXG4gICAgICAgICdfJ1xuICAgICAgKTtcblxuICAgIGxldCBsYXllciA9IHRoaXMubGF5ZXJNYXBbbGF5ZXJLZXldO1xuICAgIGxldCBzcHlXcmFwcGVyUGF0aCA9ICcvb3B0L3NweS13cmFwcGVyJztcblxuICAgIHN3aXRjaCAocnVudGltZS5uYW1lKSB7XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLlBZVEhPTl8zXzgubmFtZTpcbiAgICAgIGNhc2UgbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfOS5uYW1lOlxuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5QWVRIT05fM18xMC5uYW1lOlxuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5QWVRIT05fM18xMS5uYW1lOlxuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5QWVRIT05fM18xMi5uYW1lOlxuICAgICAgICBzcHlXcmFwcGVyUGF0aCA9ICcvb3B0L3B5dGhvbi9zcHktd3JhcHBlcic7XG4gICAgICAgIGxheWVyID1cbiAgICAgICAgICBsYXllciB8fFxuICAgICAgICAgIG5ldyBQeXRob25MYXllclZlcnNpb24odGhpcywgbGF5ZXJLZXksIHtcbiAgICAgICAgICAgIGNvbXBhdGlibGVSdW50aW1lczogW3J1bnRpbWVdLFxuICAgICAgICAgICAgY29tcGF0aWJsZUFyY2hpdGVjdHVyZXM6IFthcmNoaXRlY3R1cmVdLFxuICAgICAgICAgICAgZW50cnk6IHRoaXMuZ2V0TGFuZ3VhZ2VFeHRlbnNpb25Bc3NldExvY2F0aW9uKCdweXRob24nKSxcbiAgICAgICAgICAgIGJ1bmRsaW5nOiB7XG4gICAgICAgICAgICAgIGJ1bmRsaW5nRmlsZUFjY2VzczogQnVuZGxpbmdGaWxlQWNjZXNzLlZPTFVNRV9DT1BZLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLk5PREVKU18xMl9YLm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLk5PREVKU18xNF9YLm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLk5PREVKU18xNl9YLm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLk5PREVKU18xOF9YLm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLk5PREVKU18yMF9YLm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLk5PREVKU18yMl9YLm5hbWU6XG4gICAgICAgIGxheWVyID1cbiAgICAgICAgICBsYXllciB8fFxuICAgICAgICAgIG5ldyBsYW1iZGEuTGF5ZXJWZXJzaW9uKHRoaXMsIGxheWVyS2V5LCB7XG4gICAgICAgICAgICBjb21wYXRpYmxlUnVudGltZXM6IFtydW50aW1lXSxcbiAgICAgICAgICAgIGNvbXBhdGlibGVBcmNoaXRlY3R1cmVzOiBbYXJjaGl0ZWN0dXJlXSxcbiAgICAgICAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldCh0aGlzLmdldEV4dGVuc2lvbkFzc2V0TG9jYXRpb24oKSksXG4gICAgICAgICAgfSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgY29uc29sZS5sb2coYE5vIGV4dGVuc2lvbnMgYXZhaWxhYmxlIGZvciAke3J1bnRpbWUudG9TdHJpbmcoKX1gKTtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICB0aGlzLmxheWVyTWFwW2xheWVyS2V5XSA9IGxheWVyO1xuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKGxheWVyKTtcbiAgICByZXR1cm4geyBsYXllciwgc3B5V3JhcHBlclBhdGggfTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlTcHlTcXNXaXRoTm9TdWJzY3JpcHRpb24ocXVldWU6IHNxcy5RdWV1ZSkge1xuICAgIGNvbnN0IHN1YnNjcmlwdGlvbiA9IHRoaXMuZmluZEVsZW1lbnQ8bGFtYmRhLkNmbkV2ZW50U291cmNlTWFwcGluZz4oXG4gICAgICAobjogSUNvbnN0cnVjdCkgPT5cbiAgICAgICAgbiBpbnN0YW5jZW9mIGxhbWJkYS5DZm5FdmVudFNvdXJjZU1hcHBpbmcgJiZcbiAgICAgICAgKG4gYXMgbGFtYmRhLkNmbkV2ZW50U291cmNlTWFwcGluZykuZXZlbnRTb3VyY2VBcm4gPT09IHF1ZXVlLnF1ZXVlQXJuXG4gICAgKTtcblxuICAgIGlmIChzdWJzY3JpcHRpb24pIHtcbiAgICAgIHJldHVybjsgLy9hbHJlYWR5IGhhdmUgc3Vic2NyaXB0aW9uXG4gICAgfVxuXG4gICAgY29uc3QgcXVldWVOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHF1ZXVlKTtcbiAgICBjb25zdCBmdW5jID0gbmV3IE5vZGVqc0Z1bmN0aW9uKFxuICAgICAgdGhpcyxcbiAgICAgIGAke3F1ZXVlTmFtZX1TcXNTdWJzY3JpcHRpb25BbmREcm9wQWxsTWVzc2FnZXNgLFxuICAgICAge1xuICAgICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICAgIHRpbWVvdXQ6IER1cmF0aW9uLnNlY29uZHMoNSksXG4gICAgICAgIHJ1bnRpbWU6IGxhbWJkYS5SdW50aW1lLk5PREVKU18yMl9YLFxuICAgICAgICBoYW5kbGVyOiAnaGFuZGxlcicsXG4gICAgICAgIGVudHJ5OiB0aGlzLmdldEFzc2V0TG9jYXRpb24oXG4gICAgICAgICAgJ2Z1bmN0aW9ucy9zcXNTdWJzY3JpcHRpb25BbmREcm9wQWxsTWVzc2FnZXMuanMnXG4gICAgICAgICksXG4gICAgICAgIGVudmlyb25tZW50OiB0aGlzLmdldERlZmF1bHRMYW1iZGFFbnZpcm9ubWVudFZhcmlhYmxlcygpLFxuICAgICAgfVxuICAgICk7XG4gICAgZnVuYy5hZGRFdmVudFNvdXJjZShuZXcgU3FzRXZlbnRTb3VyY2UocXVldWUpKTtcbiAgICB0aGlzLnNldHVwRm9ySW9UKGZ1bmMpO1xuICAgIGNvbnN0IHsgbGF5ZXIsIHNweVdyYXBwZXJQYXRoIH0gPSB0aGlzLmdldEV4dGVuc2lvbkZvclJ1bnRpbWUoXG4gICAgICBmdW5jLnJ1bnRpbWUsXG4gICAgICBmdW5jLmFyY2hpdGVjdHVyZVxuICAgICkhO1xuICAgIGZ1bmMuYWRkTGF5ZXJzKGxheWVyKTtcblxuICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoJ0FXU19MQU1CREFfRVhFQ19XUkFQUEVSJywgc3B5V3JhcHBlclBhdGgpO1xuXG4gICAgaWYgKHRoaXMucHJvcHM/LmRlYnVnTW9kZSkge1xuICAgICAgZnVuYy5hZGRFbnZpcm9ubWVudChlbnZWYXJpYWJsZU5hbWVzLlNTUFlfREVCVUcsICd0cnVlJyk7XG4gICAgfVxuXG4gICAgdGhpcy5jcmVhdGVkUmVzb3VyY2VzQnlTU3B5LnB1c2goZnVuYyk7XG5cbiAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYFNxcyMke3F1ZXVlTmFtZX1gO1xuXG4gICAgdGhpcy5hZGRNYXBwaW5nVG9GdW5jdGlvbihmdW5jLCB7XG4gICAgICBrZXk6IHF1ZXVlLnF1ZXVlQXJuLFxuICAgICAgdmFsdWU6IHNlcnZpY2VLZXksXG4gICAgfSk7XG5cbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goc2VydmljZUtleSk7XG4gICAgZnVuYy5hZGRFbnZpcm9ubWVudChlbnZWYXJpYWJsZU5hbWVzLlNTUFlfU1VCU0NSSUJFRF9UT19TUVMsICd0cnVlJyk7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5U3FzKG5vZGU6IGxhbWJkYS5DZm5FdmVudFNvdXJjZU1hcHBpbmcpIHtcbiAgICBjb25zdCBxdWV1ZSA9IHRoaXMuZmluZEVsZW1lbnQ8c3FzLlF1ZXVlPihcbiAgICAgIChuOiBJQ29uc3RydWN0KSA9PlxuICAgICAgICBuIGluc3RhbmNlb2Ygc3FzLlF1ZXVlICYmXG4gICAgICAgIChuIGFzIHNxcy5RdWV1ZSkucXVldWVBcm4gPT09IG5vZGUuZXZlbnRTb3VyY2VBcm5cbiAgICApO1xuXG4gICAgY29uc3QgZnVuYyA9IHRoaXMuZmluZEVsZW1lbnQ8bGFtYmRhLkZ1bmN0aW9uPihcbiAgICAgIChuOiBJQ29uc3RydWN0KSA9PlxuICAgICAgICBuIGluc3RhbmNlb2YgbGFtYmRhLkZ1bmN0aW9uICYmXG4gICAgICAgIChuIGFzIGxhbWJkYS5GdW5jdGlvbikuZnVuY3Rpb25OYW1lID09PSBub2RlLmZ1bmN0aW9uTmFtZVxuICAgICk7XG5cbiAgICBpZiAocXVldWUgJiYgZnVuYykge1xuICAgICAgY29uc3QgcXVldWVOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHF1ZXVlKTtcblxuICAgICAgY29uc3Qgc2VydmljZUtleSA9IGBTcXMjJHtxdWV1ZU5hbWV9YDtcblxuICAgICAgdGhpcy5hZGRNYXBwaW5nVG9GdW5jdGlvbihmdW5jLCB7XG4gICAgICAgIGtleTogcXVldWUucXVldWVBcm4sXG4gICAgICAgIHZhbHVlOiBzZXJ2aWNlS2V5LFxuICAgICAgfSk7XG5cbiAgICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoZW52VmFyaWFibGVOYW1lcy5TU1BZX1NVQlNDUklCRURfVE9fU1FTLCAndHJ1ZScpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlRnVuY3Rpb25Gb3JTdWJzY3JpcHRpb24oaW5kZXg6IG51bWJlcikge1xuICAgIGNvbnN0IGZ1bmMgPSBuZXcgbGFtYmRhTm9kZS5Ob2RlanNGdW5jdGlvbih0aGlzLCBgU3Vic2NyaXB0aW9uJHtpbmRleH1gLCB7XG4gICAgICBtZW1vcnlTaXplOiA1MTIsXG4gICAgICB0aW1lb3V0OiBEdXJhdGlvbi5zZWNvbmRzKDUpLFxuICAgICAgcnVudGltZTogbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICBoYW5kbGVyOiAnaGFuZGxlcicsXG4gICAgICBlbnRyeTogdGhpcy5nZXRBc3NldExvY2F0aW9uKCdmdW5jdGlvbnMvc2VuZE1lc3NhZ2UuanMnKSxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIE5PREVfT1BUSU9OUzogJy0tZW5hYmxlLXNvdXJjZS1tYXBzJyxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgdGhpcy5zZXR1cEZvcklvVChmdW5jKTtcbiAgICByZXR1cm4gZnVuYztcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlTMyhzM0J1Y2tldDogczMuQnVja2V0KSB7XG4gICAgczNCdWNrZXQuYWRkRXZlbnROb3RpZmljYXRpb24oXG4gICAgICBzMy5FdmVudFR5cGUuT0JKRUNUX0NSRUFURURfUFVULFxuICAgICAgbmV3IHMzbm90aWYuTGFtYmRhRGVzdGluYXRpb24odGhpcy5sYW1iZGFTdWJzY3JpcHRpb25NYWluLmZ1bmN0aW9uKVxuICAgICk7XG5cbiAgICBjb25zdCBuYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHMzQnVja2V0KTtcblxuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgUzMjJHtuYW1lfWA7XG4gICAgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25NYWluLm1hcHBpbmdbczNCdWNrZXQuYnVja2V0QXJuXSA9IHNlcnZpY2VLZXk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweUR5bmFtb2RiKHRhYmxlOiBkeW5hbW9EYi5UYWJsZSB8IGR5bmFtb0RiLlRhYmxlVjIpIHtcbiAgICAvLyBlbmFibGUgRHluYW1vREIgc3RyZWFtcyB3aXRoIGEgaGFja1xuICAgICh0YWJsZS5ub2RlLmRlZmF1bHRDaGlsZCBhcyBkeW5hbW9EYi5DZm5UYWJsZSkuc3RyZWFtU3BlY2lmaWNhdGlvbiA9IHtcbiAgICAgIHN0cmVhbVZpZXdUeXBlOiBkeW5hbW9EYi5TdHJlYW1WaWV3VHlwZS5ORVdfQU5EX09MRF9JTUFHRVMsXG4gICAgfTtcbiAgICAodGFibGUgYXMgYW55KS50YWJsZVN0cmVhbUFybiA9IChcbiAgICAgIHRhYmxlLm5vZGUuZGVmYXVsdENoaWxkIGFzIGR5bmFtb0RiLkNmblRhYmxlXG4gICAgKS5hdHRyU3RyZWFtQXJuO1xuXG4gICAgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25NYWluLmZ1bmN0aW9uLmFkZEV2ZW50U291cmNlKFxuICAgICAgbmV3IGR5bmFtb0RiU3RyZWFtLkR5bmFtb0V2ZW50U291cmNlKHRhYmxlLCB7XG4gICAgICAgIHN0YXJ0aW5nUG9zaXRpb246IGxhbWJkYS5TdGFydGluZ1Bvc2l0aW9uLkxBVEVTVCxcbiAgICAgICAgYmF0Y2hTaXplOiAxLFxuICAgICAgICByZXRyeUF0dGVtcHRzOiAwLFxuICAgICAgfSlcbiAgICApO1xuXG4gICAgY29uc3QgbmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZSh0YWJsZSk7XG5cbiAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYER5bmFtb0RCIyR7bmFtZX1gO1xuICAgIHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uTWFpbi5tYXBwaW5nW3RhYmxlLnRhYmxlQXJuXSA9IHNlcnZpY2VLZXk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweUV2ZW50QnVzUnVsZShydWxlOiBldmVudHMuUnVsZSkge1xuICAgIGNvbnN0IHsgZXZlbnRCdXNOYW1lIH0gPSBydWxlLm5vZGUuZGVmYXVsdENoaWxkIGFzIGV2ZW50cy5DZm5SdWxlO1xuICAgIGxldCBicmlkZ2VOYW1lID0gJ0RlZmF1bHQnO1xuICAgIGlmICghIWV2ZW50QnVzTmFtZSkge1xuICAgICAgY29uc3QgZXZlbnRCcmlkZ2UgPSB0aGlzLmdldEV2ZW50QnJpZGdlKGV2ZW50QnVzTmFtZSk7XG5cbiAgICAgIGlmICghZXZlbnRCcmlkZ2UpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4gbm90IGZpbmQgRXZlbnRCcmlkZ2Ugd2l0aCBuYW1lIFwiJHtldmVudEJ1c05hbWV9XCJgKTtcbiAgICAgIH1cbiAgICAgIGJyaWRnZU5hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUoZXZlbnRCcmlkZ2UpO1xuICAgIH1cblxuICAgIGNvbnN0IGZ1bmN0aW9uU3Vic2NyaXB0aW9uID0gdGhpcy5wcm92aWRlRnVuY3Rpb25Gb3JTdWJzY3JpcHRpb24oXG4gICAgICAocykgPT4gIXMudXNlZEZvckV2ZW50QnJpZGdlXG4gICAgKTtcbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi51c2VkRm9yRXZlbnRCcmlkZ2UgPSB0cnVlO1xuXG4gICAgcnVsZS5hZGRUYXJnZXQobmV3IHRhcmdldHMuTGFtYmRhRnVuY3Rpb24oZnVuY3Rpb25TdWJzY3JpcHRpb24uZnVuY3Rpb24pKTtcblxuICAgIGNvbnN0IHJ1bGVOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHJ1bGUpO1xuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgRXZlbnRCcmlkZ2VSdWxlIyR7YnJpZGdlTmFtZX0jJHtydWxlTmFtZX1gO1xuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLm1hcHBpbmcuZXZlbnRCcmlkZ2UgPSBzZXJ2aWNlS2V5O1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlFdmVudEJ1cyhldmVudEJ1czogZXZlbnRzLkV2ZW50QnVzKSB7XG4gICAgY29uc3QgZnVuY3Rpb25TdWJzY3JpcHRpb24gPSB0aGlzLnByb3ZpZGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbihcbiAgICAgIChzKSA9PiAhcy51c2VkRm9yRXZlbnRCcmlkZ2VcbiAgICApO1xuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLnVzZWRGb3JFdmVudEJyaWRnZSA9IHRydWU7XG5cbiAgICBjb25zdCBicmlkZ2VOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKGV2ZW50QnVzKTtcbiAgICBjb25zdCBydWxlID0gbmV3IGV2ZW50cy5SdWxlKHRoaXMsIGBSdWxlQWxsJHticmlkZ2VOYW1lfWAsIHtcbiAgICAgIGV2ZW50QnVzLFxuICAgICAgZXZlbnRQYXR0ZXJuOiB7IHZlcnNpb246IFsnMCddIH0sXG4gICAgICB0YXJnZXRzOiBbbmV3IHRhcmdldHMuTGFtYmRhRnVuY3Rpb24oZnVuY3Rpb25TdWJzY3JpcHRpb24uZnVuY3Rpb24pXSxcbiAgICB9KTtcblxuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKHJ1bGUpO1xuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgRXZlbnRCcmlkZ2UjJHticmlkZ2VOYW1lfWA7XG4gICAgZnVuY3Rpb25TdWJzY3JpcHRpb24ubWFwcGluZy5ldmVudEJyaWRnZSA9IHNlcnZpY2VLZXk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweVNuc1RvcGljKHRvcGljOiBzbnMuVG9waWMpIHtcbiAgICBjb25zdCBmdW5jdGlvblN1YnNjcmlwdGlvbiA9IHRoaXMucHJvdmlkZUZ1bmN0aW9uRm9yU3Vic2NyaXB0aW9uKFxuICAgICAgKHMpID0+ICFzLnN1YnNyaWJlZFRvcGljcy5pbmNsdWRlcyh0b3BpYylcbiAgICApO1xuXG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gdG9waWMuYWRkU3Vic2NyaXB0aW9uKFxuICAgICAgbmV3IHNuc1N1YnMuTGFtYmRhU3Vic2NyaXB0aW9uKGZ1bmN0aW9uU3Vic2NyaXB0aW9uLmZ1bmN0aW9uKVxuICAgICk7XG4gICAgdGhpcy5jcmVhdGVkUmVzb3VyY2VzQnlTU3B5LnB1c2goc3Vic2NyaXB0aW9uKTtcbiAgICBjb25zdCB0b3BpY05hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUodG9waWMpO1xuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgU25zVG9waWMjJHt0b3BpY05hbWV9YDtcbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi5tYXBwaW5nW3RvcGljLnRvcGljQXJuXSA9IHNlcnZpY2VLZXk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLnN1YnNyaWJlZFRvcGljcy5wdXNoKHRvcGljKTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlTbnNTdWJzY3JpcHRpb24oc3Vic2NyaXB0aW9uOiBzbnMuU3Vic2NyaXB0aW9uKSB7XG4gICAgaWYgKCFzdWJzY3JpcHRpb24ubm9kZS5zY29wZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHRvcGljID0gdGhpcy5nZXRUb3BpYyhcbiAgICAgIChzdWJzY3JpcHRpb24ubm9kZS5kZWZhdWx0Q2hpbGQgYXMgc25zLkNmblN1YnNjcmlwdGlvbikudG9waWNBcm5cbiAgICApO1xuXG4gICAgaWYgKCF0b3BpYykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gbm90IGZpbmQgVG9waWMnKTtcbiAgICB9XG5cbiAgICBjb25zdCBmdW5jdGlvblN1YnNjcmlwdGlvbiA9IHRoaXMucHJvdmlkZUZ1bmN0aW9uRm9yU3Vic2NyaXB0aW9uKFxuICAgICAgKHMpID0+ICFzLnN1YnNyaWJlZFRvcGljcy5pbmNsdWRlcyh0b3BpYylcbiAgICApO1xuXG4gICAgY29uc3QgeyBmaWx0ZXJQb2xpY3kgfSA9IHN1YnNjcmlwdGlvbi5ub2RlXG4gICAgICAuZGVmYXVsdENoaWxkIGFzIHNucy5DZm5TdWJzY3JpcHRpb247XG5cbiAgICBjb25zdCBzdWJzY3JpcHRpb25DbG9uZSA9IHRvcGljLmFkZFN1YnNjcmlwdGlvbihcbiAgICAgIG5ldyBzbnNTdWJzLkxhbWJkYVN1YnNjcmlwdGlvbihmdW5jdGlvblN1YnNjcmlwdGlvbi5mdW5jdGlvbilcbiAgICApO1xuICAgIChzdWJzY3JpcHRpb25DbG9uZS5ub2RlLmRlZmF1bHRDaGlsZCBhcyBzbnMuQ2ZuU3Vic2NyaXB0aW9uKS5maWx0ZXJQb2xpY3kgPVxuICAgICAgZmlsdGVyUG9saWN5O1xuXG4gICAgdGhpcy5jcmVhdGVkUmVzb3VyY2VzQnlTU3B5LnB1c2goc3Vic2NyaXB0aW9uQ2xvbmUpO1xuXG4gICAgY29uc3QgdG9waWNOYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHRvcGljKTtcbiAgICBjb25zdCB0YXJnZXROYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHN1YnNjcmlwdGlvbi5ub2RlLnNjb3BlKTtcblxuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLnN1YnNyaWJlZFRvcGljcy5wdXNoKHRvcGljKTtcbiAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYFNuc1N1YnNjcmlwdGlvbiMke3RvcGljTmFtZX0jJHt0YXJnZXROYW1lfWA7XG4gICAgZnVuY3Rpb25TdWJzY3JpcHRpb24ubWFwcGluZ1t0b3BpYy50b3BpY0Fybl0gPSBzZXJ2aWNlS2V5O1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgfVxuXG4gIHByaXZhdGUgcHJvdmlkZUZ1bmN0aW9uRm9yU3Vic2NyaXB0aW9uKFxuICAgIGZpbHRlckZ1bmN0aW9uPzogKHN1YnNjcmlwdGlvbjogTGFtYmRhU3Vic2NyaXB0aW9uKSA9PiBib29sZWFuXG4gICkge1xuICAgIGxldCBmdW5jdGlvblN1YnNjcmlwdGlvbjogTGFtYmRhU3Vic2NyaXB0aW9uIHwgdW5kZWZpbmVkO1xuXG4gICAgaWYgKGZpbHRlckZ1bmN0aW9uKSB7XG4gICAgICBmdW5jdGlvblN1YnNjcmlwdGlvbiA9IHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uUG9vbC5maW5kKGZpbHRlckZ1bmN0aW9uKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uUG9vbC5sZW5ndGggPiAwKSB7XG4gICAgICBmdW5jdGlvblN1YnNjcmlwdGlvbiA9IHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uUG9vbFswXTtcbiAgICB9XG5cbiAgICBpZiAoIWZ1bmN0aW9uU3Vic2NyaXB0aW9uKSB7XG4gICAgICBmdW5jdGlvblN1YnNjcmlwdGlvbiA9IHtcbiAgICAgICAgc3Vic3JpYmVkVG9waWNzOiBbXSxcbiAgICAgICAgdXNlZEZvckV2ZW50QnJpZGdlOiBmYWxzZSxcbiAgICAgICAgbWFwcGluZzoge30sXG4gICAgICAgIGZ1bmN0aW9uOiB0aGlzLmNyZWF0ZUZ1bmN0aW9uRm9yU3Vic2NyaXB0aW9uKFxuICAgICAgICAgIHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uUG9vbC5sZW5ndGhcbiAgICAgICAgKSxcbiAgICAgIH07XG4gICAgICB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvblBvb2wucHVzaChmdW5jdGlvblN1YnNjcmlwdGlvbik7XG4gICAgfVxuICAgIHJldHVybiBmdW5jdGlvblN1YnNjcmlwdGlvbjtcbiAgfVxuXG4gIHByaXZhdGUgc2V0dXBGb3JJb1QoZnVuYzogbGFtYmRhLkZ1bmN0aW9uKSB7XG4gICAgZnVuYy5hZGRFbnZpcm9ubWVudChcbiAgICAgIGVudlZhcmlhYmxlTmFtZXMuU1NQWV9ST09UX1NUQUNLLFxuICAgICAgdGhpcy5jbGVhbk5hbWUodGhpcy5maW5kUm9vdFN0YWNrKFN0YWNrLm9mKHRoaXMpKS5ub2RlLmlkKVxuICAgICk7XG4gICAgZnVuYy5hZGRFbnZpcm9ubWVudChlbnZWYXJpYWJsZU5hbWVzLlNTUFlfSU9UX0VORFBPSU5ULCB0aGlzLmlvdEVuZHBvaW50KTtcblxuICAgIGZ1bmMuYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgbmV3IGF3c19pYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgYWN0aW9uczogWydpb3Q6KiddLFxuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgcmVzb3VyY2VzOiBbJyonXSxcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlMYW1iZGEoZnVuYzogbGFtYmRhLkZ1bmN0aW9uKSB7XG4gICAgY29uc3QgeyBsYXllciwgc3B5V3JhcHBlclBhdGggfSA9IHRoaXMuZ2V0RXh0ZW5zaW9uRm9yUnVudGltZShcbiAgICAgIGZ1bmMucnVudGltZSxcbiAgICAgIGZ1bmMuYXJjaGl0ZWN0dXJlIHx8IEFyY2hpdGVjdHVyZS5YODZfNjRcbiAgICApITtcbiAgICBpZiAoIWxheWVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGZ1bmMuYWRkTGF5ZXJzKGxheWVyKTtcblxuICAgIGNvbnN0IGZ1bmN0aW9uTmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZShmdW5jKTtcblxuICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoZW52VmFyaWFibGVOYW1lcy5TU1BZX0ZVTkNUSU9OX05BTUUsIGZ1bmN0aW9uTmFtZSk7XG4gICAgZnVuYy5hZGRFbnZpcm9ubWVudCgnQVdTX0xBTUJEQV9FWEVDX1dSQVBQRVInLCBzcHlXcmFwcGVyUGF0aCk7XG5cbiAgICBpZiAodGhpcy5wcm9wcz8uZGVidWdNb2RlKSB7XG4gICAgICBmdW5jLmFkZEVudmlyb25tZW50KGVudlZhcmlhYmxlTmFtZXMuU1NQWV9ERUJVRywgJ3RydWUnKTtcbiAgICB9XG5cbiAgICB0aGlzLnNldHVwRm9ySW9UKGZ1bmMpO1xuXG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKGBGdW5jdGlvbiMke2Z1bmN0aW9uTmFtZX0jUmVxdWVzdGApO1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChgRnVuY3Rpb24jJHtmdW5jdGlvbk5hbWV9I0Vycm9yYCk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKGBGdW5jdGlvbiMke2Z1bmN0aW9uTmFtZX0jQ29uc29sZWApO1xuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChgRnVuY3Rpb24jJHtmdW5jdGlvbk5hbWV9I1Jlc3BvbnNlYCk7XG5cbiAgICB0aGlzLmFkZE1hcHBpbmdUb0Z1bmN0aW9uKGZ1bmMpO1xuICB9XG5cbiAgcHVibGljIGdldENvbnN0cnVjdE5hbWUoY29uc3RydWN0OiBJQ29uc3RydWN0KSB7XG4gICAgbGV0IGNvbnN0cnVjdE5hbWUgPSBjb25zdHJ1Y3Qubm9kZS5wYXRoO1xuICAgIGNvbnN0IHsgbm9kZSB9ID0gU3RhY2sub2YodGhpcyk7XG5cbiAgICBpZiAoY29uc3RydWN0TmFtZS5zdGFydHNXaXRoKG5vZGUuaWQpKSB7XG4gICAgICBjb25zdHJ1Y3ROYW1lID0gY29uc3RydWN0TmFtZS5zdWJzdHJpbmcobm9kZS5pZC5sZW5ndGggKyAxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5jbGVhbk5hbWUoY29uc3RydWN0TmFtZSk7XG4gIH1cblxuICBwcml2YXRlIGNsZWFuTmFtZShuYW1lOiBzdHJpbmcpIHtcbiAgICAvL3NuYWtlIGNhc2UgdG8gY2FtZWwgY2FzZSBpbmNsdWRpbmcgZGFzaCBhbmQgZmlyc3QgbGV0dGVyIHRvIHVwcGVyIGNhc2VcbiAgICByZXR1cm4gbmFtZVxuICAgICAgLnJlcGxhY2UoL1stX10rL2csICcgJylcbiAgICAgIC5yZXBsYWNlKC9bXlxcd1xcc10vZywgJycpXG4gICAgICAucmVwbGFjZSgvXFxzKC4pL2csICgkMSkgPT4gJDEudG9VcHBlckNhc2UoKSlcbiAgICAgIC5yZXBsYWNlKC9cXHMvZywgJycpXG4gICAgICAucmVwbGFjZSgvXiguKS8sICgkMSkgPT4gJDEudG9VcHBlckNhc2UoKSk7XG4gIH1cblxuICBwcml2YXRlIGdldFRvcGljKHRvcGljQXJuOiBzdHJpbmcpOiBzbnMuVG9waWMgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHRvcGljID0gdGhpcy5maW5kRWxlbWVudDxzbnMuVG9waWM+KFxuICAgICAgKG5vZGU6IElDb25zdHJ1Y3QpID0+XG4gICAgICAgIG5vZGUgaW5zdGFuY2VvZiBzbnMuVG9waWMgJiYgKG5vZGUgYXMgc25zLlRvcGljKS50b3BpY0FybiA9PT0gdG9waWNBcm5cbiAgICApO1xuXG4gICAgcmV0dXJuIHRvcGljO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRFdmVudEJyaWRnZShldmVudEJ1c05hbWU6IHN0cmluZyk6IGV2ZW50cy5JRXZlbnRCdXMgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGV2ZW50QnJpZGdlID0gdGhpcy5maW5kRWxlbWVudDxldmVudHMuSUV2ZW50QnVzPihcbiAgICAgIChub2RlOiBJQ29uc3RydWN0KSA9PlxuICAgICAgICAobm9kZSBpbnN0YW5jZW9mIGV2ZW50cy5FdmVudEJ1cyB8fFxuICAgICAgICAgIG5vZGUuY29uc3RydWN0b3IubmFtZSA9PT0gJ0ltcG9ydGVkRXZlbnRCdXMnKSAmJlxuICAgICAgICAobm9kZSBhcyBldmVudHMuSUV2ZW50QnVzKS5ldmVudEJ1c05hbWUgPT09IGV2ZW50QnVzTmFtZVxuICAgICk7XG5cbiAgICByZXR1cm4gZXZlbnRCcmlkZ2U7XG4gIH1cblxuICBwcml2YXRlIGZpbmRSb290U3RhY2soc3RhY2s6IFN0YWNrKTogU3RhY2sge1xuICAgIGlmIChzdGFjay5uZXN0ZWQpIHtcbiAgICAgIGNvbnN0IHBhcmVudFN0YWNrID0gKHN0YWNrIGFzIE5lc3RlZFN0YWNrKS5uZXN0ZWRTdGFja1BhcmVudDtcbiAgICAgIGlmIChwYXJlbnRTdGFjaykgcmV0dXJuIHRoaXMuZmluZFJvb3RTdGFjayhwYXJlbnRTdGFjayk7XG4gICAgICByZXR1cm4gc3RhY2s7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBzdGFjaztcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGZpbmRFbGVtZW50PFQgZXh0ZW5kcyBJQ29uc3RydWN0ID0gSUNvbnN0cnVjdD4oXG4gICAgZmlsdGVyRnVuYzogKG5vZGU6IElDb25zdHJ1Y3QpID0+IGJvb2xlYW4sXG4gICAgcGFyZW50PzogSUNvbnN0cnVjdFxuICApOiBUIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXBhcmVudCkge1xuICAgICAgcGFyZW50ID0gdGhpcy5maW5kUm9vdFN0YWNrKFN0YWNrLm9mKHRoaXMpKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgcGFyZW50Lm5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIGlmIChmaWx0ZXJGdW5jKG5vZGUpKSB7XG4gICAgICAgIHJldHVybiBub2RlIGFzIFQ7XG4gICAgICB9XG4gICAgICBjb25zdCBlbGVtZW50Rm91bmRJbkNoaWxkID0gdGhpcy5maW5kRWxlbWVudDxUPihmaWx0ZXJGdW5jLCBub2RlKTtcbiAgICAgIGlmIChlbGVtZW50Rm91bmRJbkNoaWxkKSB7XG4gICAgICAgIHJldHVybiBlbGVtZW50Rm91bmRJbkNoaWxkO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBwcml2YXRlIGFkZE1hcHBpbmdUb0Z1bmN0aW9uKFxuICAgIGZ1bmM6IGxhbWJkYS5GdW5jdGlvbixcbiAgICBrZXlWYWx1ZT86IHsga2V5OiBzdHJpbmc7IHZhbHVlOiBzdHJpbmcgfVxuICApIHtcbiAgICBmb3IgKGNvbnN0IGZzIG9mIHRoaXMubGFtYmRhc1NwaWVkKSB7XG4gICAgICBpZiAoZnMuZnVuY3Rpb24gPT09IGZ1bmMpIHtcbiAgICAgICAgaWYgKGtleVZhbHVlKSB7XG4gICAgICAgICAgZnMubWFwcGluZ1trZXlWYWx1ZS5rZXldID0ga2V5VmFsdWUudmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGZzOiBMYW1iZGFTcGllZCA9IHtcbiAgICAgIGZ1bmN0aW9uOiBmdW5jLFxuICAgICAgbWFwcGluZzoge30sXG4gICAgfTtcblxuICAgIGlmIChrZXlWYWx1ZSkge1xuICAgICAgZnMubWFwcGluZ1trZXlWYWx1ZS5rZXldID0ga2V5VmFsdWUudmFsdWU7XG4gICAgfVxuXG4gICAgdGhpcy5sYW1iZGFzU3BpZWQucHVzaChmcyk7XG4gIH1cblxuICBwcml2YXRlIGdldEFzc2V0TG9jYXRpb24obG9jYXRpb246IHN0cmluZykge1xuICAgIGNvbnN0IGxvYyA9IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi9saWIvJyArIGxvY2F0aW9uKTtcblxuICAgIGlmIChmcy5leGlzdHNTeW5jKGxvYykpIHtcbiAgICAgIHJldHVybiBsb2M7XG4gICAgfVxuXG4gICAgY29uc3QgbG9jMiA9IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi8uLi9saWIvJyArIGxvY2F0aW9uKTtcblxuICAgIGlmIChmcy5leGlzdHNTeW5jKGxvYzIpKSB7XG4gICAgICByZXR1cm4gbG9jMjtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYExvY2F0aW9uICR7bG9jfSBhbmQgJHtsb2MyfSBkb2VzIG5vdCBleGlzdHMuYCk7XG4gIH1cbn1cblxudHlwZSBMYW1iZGFTdWJzY3JpcHRpb24gPSB7XG4gIHN1YnNyaWJlZFRvcGljczogc25zLlRvcGljW107XG4gIHVzZWRGb3JFdmVudEJyaWRnZTogYm9vbGVhbjtcbiAgZnVuY3Rpb246IGxhbWJkYU5vZGUuTm9kZWpzRnVuY3Rpb247XG4gIG1hcHBpbmc6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59O1xuXG50eXBlIExhbWJkYVNwaWVkID0ge1xuICBmdW5jdGlvbjogbGFtYmRhLkZ1bmN0aW9uO1xuICBtYXBwaW5nOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xufTtcbiJdfQ==
628
+ ServerlessSpy[_a] = { fqn: "serverless-spy.ServerlessSpy", version: "2.3.18" };
629
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2VydmVybGVzc1NweS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9TZXJ2ZXJsZXNzU3B5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3Qiw4RUFBc0U7QUFDdEUsNkNBUXFCO0FBQ3JCLHFEQUFxRDtBQUNyRCxpREFBaUQ7QUFDakQsMERBQTBEO0FBQzFELGlEQUE2QztBQUM3QyxpREFBaUQ7QUFDakQsdURBSWdDO0FBQ2hDLHVFQUF1RTtBQUN2RSxtRkFBc0U7QUFDdEUsNERBQTREO0FBQzVELHFFQUErRDtBQUMvRCx5Q0FBeUM7QUFDekMsNERBQTREO0FBQzVELDJDQUEyQztBQUMzQyw2REFBNkQ7QUFDN0QsMkNBQTJDO0FBQzNDLDJDQUFtRDtBQUNuRCxnRUFBNkQ7QUFtQjdELE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxJQUFnQixFQUEyQixFQUFFLENBQ3JFLGNBQWMsSUFBSSxJQUFJLElBQUksYUFBYSxJQUFJLElBQUksSUFBSSxTQUFTLElBQUksSUFBSSxDQUFDO0FBRXZFLE1BQU0sb0NBQW9DLEdBQUcsMEJBQTBCLENBQUM7QUFFeEUsTUFBYSxhQUFjLFNBQVEsc0JBQVM7SUFVMUMsWUFDRSxLQUFnQixFQUNoQixFQUFVLEVBQ0YsS0FBMEI7UUFFbEMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUZULFVBQUssR0FBTCxLQUFLLENBQXFCO1FBWjVCLDJCQUFzQixHQUFpQixFQUFFLENBQUM7UUFDMUMsMkJBQXNCLEdBQXlCLEVBQUUsQ0FBQztRQUVsRCxpQkFBWSxHQUFrQixFQUFFLENBQUM7UUFDbEMsZ0JBQVcsR0FBYSxFQUFFLENBQUM7UUFDMUIsZUFBVSxHQUFpQixFQUFFLENBQUM7UUFDOUIsYUFBUSxHQUEyQyxFQUFFLENBQUM7UUFVNUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FDOUIsSUFBSSxDQUFDLGFBQWEsQ0FB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QUFDLFNBQVMsRUFBRSxZQUFZLEdBQUcsUUFBUSxDQUFDLENBQUM7UUFFM0QsSUFBSSxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDeEIsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxZQUFZLEdBQUcsUUFBUSxJQUFJLG1CQUFtQixDQUFDLENBQUM7SUFDbEUsQ0FBQzs7QUE5ekJILHNDQSt6QkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgUHl0aG9uTGF5ZXJWZXJzaW9uIH0gZnJvbSAnQGF3cy1jZGsvYXdzLWxhbWJkYS1weXRob24tYWxwaGEnO1xuaW1wb3J0IHtcbiAgYXdzX2lhbSxcbiAgQnVuZGxpbmdGaWxlQWNjZXNzLFxuICBDZm5PdXRwdXQsXG4gIGN1c3RvbV9yZXNvdXJjZXMsXG4gIER1cmF0aW9uLFxuICBOZXN0ZWRTdGFjayxcbiAgU3RhY2ssXG59IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIGR5bmFtb0RiIGZyb20gJ2F3cy1jZGstbGliL2F3cy1keW5hbW9kYic7XG5pbXBvcnQgKiBhcyBldmVudHMgZnJvbSAnYXdzLWNkay1saWIvYXdzLWV2ZW50cyc7XG5pbXBvcnQgKiBhcyB0YXJnZXRzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1ldmVudHMtdGFyZ2V0cyc7XG5pbXBvcnQgeyBFZmZlY3QgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGxhbWJkYSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7XG4gIEFyY2hpdGVjdHVyZSxcbiAgSUxheWVyVmVyc2lvbixcbiAgU2luZ2xldG9uRnVuY3Rpb24sXG59IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0ICogYXMgZHluYW1vRGJTdHJlYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ldmVudC1zb3VyY2VzJztcbmltcG9ydCB7IFNxc0V2ZW50U291cmNlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ldmVudC1zb3VyY2VzJztcbmltcG9ydCAqIGFzIGxhbWJkYU5vZGUgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ub2RlanMnO1xuaW1wb3J0IHsgTm9kZWpzRnVuY3Rpb24gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhLW5vZGVqcyc7XG5pbXBvcnQgKiBhcyBzMyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtczMnO1xuaW1wb3J0ICogYXMgczNub3RpZiBmcm9tICdhd3MtY2RrLWxpYi9hd3MtczMtbm90aWZpY2F0aW9ucyc7XG5pbXBvcnQgKiBhcyBzbnMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXNucyc7XG5pbXBvcnQgKiBhcyBzbnNTdWJzIGZyb20gJ2F3cy1jZGstbGliL2F3cy1zbnMtc3Vic2NyaXB0aW9ucyc7XG5pbXBvcnQgKiBhcyBzcXMgZnJvbSAnYXdzLWNkay1saWIvYXdzLXNxcyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QsIElDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IGVudlZhcmlhYmxlTmFtZXMgfSBmcm9tICcuL2NvbW1vbi9lbnZWYXJpYWJsZU5hbWVzJztcblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2ZXJsZXNzU3B5UHJvcHMge1xuICByZWFkb25seSBnZW5lcmF0ZVNweUV2ZW50c0ZpbGVMb2NhdGlvbj86IHN0cmluZztcbiAgcmVhZG9ubHkgc3B5U3FzV2l0aE5vU3Vic2NyaXB0aW9uQW5kRHJvcEFsbE1lc3NhZ2VzPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgZGVidWdNb2RlPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTcHlGaWx0ZXIge1xuICByZWFkb25seSBzcHlMYW1iZGE/OiBib29sZWFuO1xuICByZWFkb25seSBzcHlTcXM/OiBib29sZWFuO1xuICByZWFkb25seSBzcHlTbnNUb3BpYz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHNweVNuc1N1YnNyaXB0aW9uPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3B5RXZlbnRCcmlkZ2U/OiBib29sZWFuO1xuICByZWFkb25seSBzcHlFdmVudEJyaWRnZVJ1bGU/OiBib29sZWFuO1xuICByZWFkb25seSBzcHlTMz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHNweUR5bmFtb0RCPzogYm9vbGVhbjtcbn1cblxuY29uc3QgaXNMYW1iZGFGdW5jdGlvbiA9IChub2RlOiBJQ29uc3RydWN0KTogbm9kZSBpcyBsYW1iZGEuRnVuY3Rpb24gPT5cbiAgJ2Z1bmN0aW9uTmFtZScgaW4gbm9kZSAmJiAnZnVuY3Rpb25Bcm4nIGluIG5vZGUgJiYgJ3J1bnRpbWUnIGluIG5vZGU7XG5cbmNvbnN0IHNlcnZlcmxlc3NTcHlJb3RFbmRwb2ludENyTmFtZVByZWZpeCA9ICdTZXJ2ZXJsZXNzU3B5SW90RW5kcG9pbnQnO1xuXG5leHBvcnQgY2xhc3MgU2VydmVybGVzc1NweSBleHRlbmRzIENvbnN0cnVjdCB7XG4gIHByaXZhdGUgY3JlYXRlZFJlc291cmNlc0J5U1NweTogSUNvbnN0cnVjdFtdID0gW107XG4gIHByaXZhdGUgbGFtYmRhU3Vic2NyaXB0aW9uUG9vbDogTGFtYmRhU3Vic2NyaXB0aW9uW10gPSBbXTtcbiAgcHJpdmF0ZSBsYW1iZGFTdWJzY3JpcHRpb25NYWluOiBMYW1iZGFTdWJzY3JpcHRpb247XG4gIHByaXZhdGUgbGFtYmRhc1NwaWVkOiBMYW1iZGFTcGllZFtdID0gW107XG4gIHB1YmxpYyBzZXJ2aWNlS2V5czogc3RyaW5nW10gPSBbXTtcbiAgcHJpdmF0ZSBzcGllZE5vZGVzOiBJQ29uc3RydWN0W10gPSBbXTtcbiAgcHJpdmF0ZSBsYXllck1hcDogUGFydGlhbDxSZWNvcmQ8c3RyaW5nLCBJTGF5ZXJWZXJzaW9uPj4gPSB7fTtcbiAgcHJpdmF0ZSByZWFkb25seSBpb3RFbmRwb2ludDogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgaWQ6IHN0cmluZyxcbiAgICBwcml2YXRlIHByb3BzPzogU2VydmVybGVzc1NweVByb3BzXG4gICkge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCByb290U3RhY2sgPSB0aGlzLmNsZWFuTmFtZShcbiAgICAgIHRoaXMuZmluZFJvb3RTdGFjayhTdGFjay5vZih0aGlzKSkubm9kZS5pZFxuICAgICk7XG5cbiAgICBjb25zdCBnZXRJb1RFbmRwb2ludCA9IG5ldyBjdXN0b21fcmVzb3VyY2VzLkF3c0N1c3RvbVJlc291cmNlKFxuICAgICAgdGhpcyxcbiAgICAgIHNlcnZlcmxlc3NTcHlJb3RFbmRwb2ludENyTmFtZVByZWZpeCxcbiAgICAgIHtcbiAgICAgICAgb25DcmVhdGU6IHtcbiAgICAgICAgICBzZXJ2aWNlOiAnSW90JyxcbiAgICAgICAgICBhY3Rpb246ICdkZXNjcmliZUVuZHBvaW50JyxcbiAgICAgICAgICBwaHlzaWNhbFJlc291cmNlSWQ6XG4gICAgICAgICAgICBjdXN0b21fcmVzb3VyY2VzLlBoeXNpY2FsUmVzb3VyY2VJZC5mcm9tUmVzcG9uc2UoJ2VuZHBvaW50QWRkcmVzcycpLFxuICAgICAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgIGVuZHBvaW50VHlwZTogJ2lvdDpEYXRhLUFUUycsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgb25VcGRhdGU6IHtcbiAgICAgICAgICBzZXJ2aWNlOiAnSW90JyxcbiAgICAgICAgICBhY3Rpb246ICdkZXNjcmliZUVuZHBvaW50JyxcbiAgICAgICAgICBwaHlzaWNhbFJlc291cmNlSWQ6XG4gICAgICAgICAgICBjdXN0b21fcmVzb3VyY2VzLlBoeXNpY2FsUmVzb3VyY2VJZC5mcm9tUmVzcG9uc2UoJ2VuZHBvaW50QWRkcmVzcycpLFxuICAgICAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgICAgIGVuZHBvaW50VHlwZTogJ2lvdDpEYXRhLUFUUycsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgaW5zdGFsbExhdGVzdEF3c1NkazogZmFsc2UsXG4gICAgICAgIHBvbGljeTogY3VzdG9tX3Jlc291cmNlcy5Bd3NDdXN0b21SZXNvdXJjZVBvbGljeS5mcm9tU2RrQ2FsbHMoe1xuICAgICAgICAgIHJlc291cmNlczogY3VzdG9tX3Jlc291cmNlcy5Bd3NDdXN0b21SZXNvdXJjZVBvbGljeS5BTllfUkVTT1VSQ0UsXG4gICAgICAgIH0pLFxuICAgICAgICBmdW5jdGlvbk5hbWU6IHNlcnZlcmxlc3NTcHlJb3RFbmRwb2ludENyTmFtZVByZWZpeCArIHJvb3RTdGFjayxcbiAgICAgIH1cbiAgICApO1xuICAgIHRoaXMuaW90RW5kcG9pbnQgPSBnZXRJb1RFbmRwb2ludC5nZXRSZXNwb25zZUZpZWxkKCdlbmRwb2ludEFkZHJlc3MnKTtcblxuICAgIHRoaXMuY3JlYXRlZFJlc291cmNlc0J5U1NweS5wdXNoKGdldElvVEVuZHBvaW50KTtcblxuICAgIG5ldyBDZm5PdXRwdXQodGhpcywgJ1NlcnZlcmxlc3NTcHlJb1RFbmRwb2ludCcsIHtcbiAgICAgIGtleTogJ1NlcnZlcmxlc3NTcHlXc1VybCcsXG4gICAgICB2YWx1ZTogYCR7dGhpcy5pb3RFbmRwb2ludH0vJHtyb290U3RhY2t9YCxcbiAgICB9KTtcblxuICAgIHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uTWFpbiA9IHRoaXMucHJvdmlkZUZ1bmN0aW9uRm9yU3Vic2NyaXB0aW9uKCk7XG4gIH1cblxuICBwcml2YXRlIGdldERlZmF1bHRMYW1iZGFFbnZpcm9ubWVudFZhcmlhYmxlcygpOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9IHtcbiAgICByZXR1cm4ge1xuICAgICAgTk9ERV9PUFRJT05TOiAnLS1lbmFibGUtc291cmNlLW1hcHMnLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogSW5pdGFsaXplIHNweWluZyBvbiByZXNvdXJjZXMgZ2l2ZW4gYXMgcGFyYW1ldGVyLlxuICAgKiBAcGFyYW0gbm9kZXMgV2hpY2ggcmVvdXJjZXMgYW5kIHRoZWlyIGNoaWxkcmVuIHRvIHNweSBvbi5cbiAgICovXG4gIHB1YmxpYyBzcHlOb2Rlcyhub2RlczogSUNvbnN0cnVjdFtdKSB7XG4gICAgZm9yIChjb25zdCBub2RlIG9mIG5vZGVzKSB7XG4gICAgICBsZXQgbnMgPSB0aGlzLmdldEFsbE5vZGVzKG5vZGUpO1xuICAgICAgdGhpcy5pbnRlcm5hbFNweU5vZGVzKG5zKTtcbiAgICB9XG5cbiAgICB0aGlzLmZpbmFsaXplU3B5KCk7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGFsaXplIHNweWluZyBvbiByZXNvdXJjZXMuXG4gICAqIEBwYXJhbSBmaWx0ZXIgTGltaXQgd2hpY2ggcmVzb3VyY2VzIHRvIHNweSBvbi5cbiAgICovXG4gIHB1YmxpYyBzcHkoZmlsdGVyPzogU3B5RmlsdGVyKSB7XG4gICAgbGV0IG5vZGVzID0gdGhpcy5nZXRBbGxOb2RlcyhTdGFjay5vZih0aGlzKSk7XG5cbiAgICBjb25zdCBmaWx0ZXJXaXRoRGVmYXVsdHM6IFJlcXVpcmVkPFNweUZpbHRlcj4gPSB7XG4gICAgICBzcHlMYW1iZGE6IHRydWUsXG4gICAgICBzcHlTcXM6IHRydWUsXG4gICAgICBzcHlTbnNUb3BpYzogdHJ1ZSxcbiAgICAgIHNweVNuc1N1YnNyaXB0aW9uOiB0cnVlLFxuICAgICAgc3B5RXZlbnRCcmlkZ2U6IHRydWUsXG4gICAgICBzcHlFdmVudEJyaWRnZVJ1bGU6IHRydWUsXG4gICAgICBzcHlTMzogdHJ1ZSxcbiAgICAgIHNweUR5bmFtb0RCOiB0cnVlLFxuICAgICAgLi4uZmlsdGVyLFxuICAgIH07XG5cbiAgICBjb25zdCBDUklEID1cbiAgICAgICdBV1MnICtcbiAgICAgIGN1c3RvbV9yZXNvdXJjZXMuQXdzQ3VzdG9tUmVzb3VyY2UuUFJPVklERVJfRlVOQ1RJT05fVVVJRC5yZXBsYWNlKFxuICAgICAgICAvLS9naSxcbiAgICAgICAgJydcbiAgICAgICkuc3Vic3RyaW5nKDAsIDE2KTtcblxuICAgIG5vZGVzID0gbm9kZXMuZmlsdGVyKChub2RlKSA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgIC8vIElnbm9yZSB0aGUgY3VzdG9tIHJlc291cmNlIGFuZCB0aGUgUHJvdmlkZXIgKGFzIHdlbGwgYXMgYW55IG90aGVyIFByb3ZpZGVycyB1c2luZyB0aGUgc2FtZSBwcm92aWRlciBmdW5jdGlvbiksIG90aGVyd2lzZSB3ZSBjYXVzZVxuICAgICAgICAvLyBjaXJjdWxhciBkZXBlbmRlbmNpZXNcbiAgICAgICAgbm9kZS5ub2RlLmlkLnN0YXJ0c1dpdGgoQ1JJRCkgfHxcbiAgICAgICAgbm9kZS5ub2RlLmlkID09PSAnUHJvdmlkZXInIHx8XG4gICAgICAgIC8vIElnbm9yZSBzaW5nbGV0b24gZnVuY3Rpb25zIGFzIHRoZXkgY2FuIGNhdXNlIHZlcnkgb2RkIGJlaGF2aW9yIGFuZCBjcmFzaGVzXG4gICAgICAgIG5vZGUgaW5zdGFuY2VvZiBTaW5nbGV0b25GdW5jdGlvblxuICAgICAgKSB7XG4gICAgICAgIGlmICh0aGlzLnByb3BzPy5kZWJ1Z01vZGUpIHtcbiAgICAgICAgICBjb25zb2xlLmluZm8oYFNraXBwaW5nICR7bm9kZS5ub2RlLmlkfWApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGZpbHRlcldpdGhEZWZhdWx0cy5zcHlMYW1iZGEgJiZcbiAgICAgICAgKG5vZGUgaW5zdGFuY2VvZiBsYW1iZGEuRnVuY3Rpb24gfHxcbiAgICAgICAgICBub2RlIGluc3RhbmNlb2YgTm9kZWpzRnVuY3Rpb24gfHxcbiAgICAgICAgICBpc0xhbWJkYUZ1bmN0aW9uKG5vZGUpKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5U25zVG9waWMgJiYgbm9kZSBpbnN0YW5jZW9mIHNucy5Ub3BpYykge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGZpbHRlcldpdGhEZWZhdWx0cy5zcHlTbnNTdWJzcmlwdGlvbiAmJlxuICAgICAgICBub2RlIGluc3RhbmNlb2Ygc25zLlN1YnNjcmlwdGlvblxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5UzMgJiYgbm9kZSBpbnN0YW5jZW9mIHMzLkJ1Y2tldCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGZpbHRlcldpdGhEZWZhdWx0cy5zcHlEeW5hbW9EQiAmJlxuICAgICAgICBub2RlIGluc3RhbmNlb2YgZHluYW1vRGIuVGFibGVcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGZpbHRlcldpdGhEZWZhdWx0cy5zcHlEeW5hbW9EQiAmJlxuICAgICAgICBub2RlIGluc3RhbmNlb2YgZHluYW1vRGIuVGFibGVWMlxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgZmlsdGVyV2l0aERlZmF1bHRzLnNweUV2ZW50QnJpZGdlICYmXG4gICAgICAgIG5vZGUgaW5zdGFuY2VvZiBldmVudHMuRXZlbnRCdXNcbiAgICAgICkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGZpbHRlcldpdGhEZWZhdWx0cy5zcHlFdmVudEJyaWRnZVJ1bGUgJiZcbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIGV2ZW50cy5SdWxlXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5U3FzICYmXG4gICAgICAgIG5vZGUgaW5zdGFuY2VvZiBsYW1iZGEuQ2ZuRXZlbnRTb3VyY2VNYXBwaW5nXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKFxuICAgICAgICBmaWx0ZXJXaXRoRGVmYXVsdHMuc3B5U3FzICYmXG4gICAgICAgIHRoaXMucHJvcHM/LnNweVNxc1dpdGhOb1N1YnNjcmlwdGlvbkFuZERyb3BBbGxNZXNzYWdlcyAmJlxuICAgICAgICBub2RlIGluc3RhbmNlb2Ygc3FzLlF1ZXVlXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9KTtcblxuICAgIHRoaXMuaW50ZXJuYWxTcHlOb2Rlcyhub2Rlcyk7XG4gICAgdGhpcy5maW5hbGl6ZVNweSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweU5vZGVzKG5vZGVzOiBJQ29uc3RydWN0W10pIHtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2Ygbm9kZXMpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlOb2RlKG5vZGUpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZmluYWxpemVTcHkoKSB7XG4gICAgLy9zZXQgbWFwcGluZyBwcm9wZXJ0eSBmb3IgYWxsIGZ1bmN0aW9ucyB3ZSBjcmVhdGVkXG4gICAgZm9yIChjb25zdCBmdW5jIG9mIHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uUG9vbCkge1xuICAgICAgZnVuYy5mdW5jdGlvbi5hZGRFbnZpcm9ubWVudChcbiAgICAgICAgZW52VmFyaWFibGVOYW1lcy5TU1BZX0lORlJBX01BUFBJTkcsXG4gICAgICAgIEpTT04uc3RyaW5naWZ5KGZ1bmMubWFwcGluZylcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy9zZXQgbWFwcGluZyBwcm9wZXJ0eSBmb3IgYWxsIGZ1bmN0aW9ucyB3ZSBzcHkgb25cbiAgICBmb3IgKGNvbnN0IGZ1bmMgb2YgdGhpcy5sYW1iZGFzU3BpZWQpIHtcbiAgICAgIGZ1bmMuZnVuY3Rpb24uYWRkRW52aXJvbm1lbnQoXG4gICAgICAgIGVudlZhcmlhYmxlTmFtZXMuU1NQWV9JTkZSQV9NQVBQSU5HLFxuICAgICAgICBKU09OLnN0cmluZ2lmeShmdW5jLm1hcHBpbmcpXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnByb3BzPy5nZW5lcmF0ZVNweUV2ZW50c0ZpbGVMb2NhdGlvbikge1xuICAgICAgdGhpcy53cml0ZVNweUV2ZW50c0NsYXNzKHRoaXMucHJvcHM/LmdlbmVyYXRlU3B5RXZlbnRzRmlsZUxvY2F0aW9uKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldEV4dGVuc2lvbkFzc2V0TG9jYXRpb24oKSB7XG4gICAgbGV0IGV4dGVuc2lvbkFzc2V0TG9jYXRpb24gPSBwYXRoLmpvaW4oXG4gICAgICBfX2Rpcm5hbWUsXG4gICAgICAnLi4vZXh0ZW5zaW9uL2Rpc3QvbGF5ZXInXG4gICAgKTtcblxuICAgIGNvbnN0IGV4dGVuc2lvbkFzc2V0TG9jYXRpb25BbHQgPSBwYXRoLmpvaW4oXG4gICAgICBfX2Rpcm5hbWUsXG4gICAgICAnLi4vbGliL2V4dGVuc2lvbi9kaXN0L2xheWVyJ1xuICAgICk7XG5cbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbikpIHtcbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhleHRlbnNpb25Bc3NldExvY2F0aW9uQWx0KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEZvbGRlciB3aXRoIGFzc2V0cyBmb3IgZXh0ZW5zaW9uIGRvZXMgbm90IGV4aXN0cyBhdCAke2V4dGVuc2lvbkFzc2V0TG9jYXRpb259IG9yIGF0ICR7ZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkFsdH0gYFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbiA9IGV4dGVuc2lvbkFzc2V0TG9jYXRpb25BbHQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbldyYXBwZXIgPSBwYXRoLmpvaW4oXG4gICAgICBleHRlbnNpb25Bc3NldExvY2F0aW9uLFxuICAgICAgJ3NweS13cmFwcGVyJ1xuICAgICk7XG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKGV4dGVuc2lvbkFzc2V0TG9jYXRpb25XcmFwcGVyKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgV3JhcHBlciBzY3JpcHQgZm9yIGV4dGVuc2lvbiBkb2VzIG5vdCBleGlzdHMgJHtleHRlbnNpb25Bc3NldExvY2F0aW9ufWBcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkNvZGUgPSBwYXRoLmpvaW4oXG4gICAgICBleHRlbnNpb25Bc3NldExvY2F0aW9uLFxuICAgICAgYG5vZGVqcy9ub2RlX21vZHVsZXMvaW50ZXJjZXB0b3IuanNgXG4gICAgKTtcbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkNvZGUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBDb2RlIGZvciBleHRlbnNpb24gZG9lcyBub3QgZXhpc3RzICR7ZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbkNvZGV9YFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGV4dGVuc2lvbkFzc2V0TG9jYXRpb247XG4gIH1cblxuICBwcml2YXRlIGdldExhbmd1YWdlRXh0ZW5zaW9uQXNzZXRMb2NhdGlvbihsYW5ndWFnZTogc3RyaW5nKSB7XG4gICAgY29uc3Qgcm9vdERpciA9IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLicpO1xuXG4gICAgbGV0IGV4dGVuc2lvbkFzc2V0TG9jYXRpb24gPSBwYXRoLmpvaW4ocm9vdERpciwgYGV4dGVuc2lvbnMvJHtsYW5ndWFnZX1gKTtcblxuICAgIGNvbnN0IGV4dGVuc2lvbkFzc2V0TG9jYXRpb25BbHQgPSBwYXRoLmpvaW4oXG4gICAgICByb290RGlyLFxuICAgICAgYGxpYi9leHRlbnNpb25zLyR7bGFuZ3VhZ2V9YFxuICAgICk7XG5cbiAgICBpZiAoIWZzLmV4aXN0c1N5bmMoZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbikpIHtcbiAgICAgIGlmICghZnMuZXhpc3RzU3luYyhleHRlbnNpb25Bc3NldExvY2F0aW9uQWx0KSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEZvbGRlciB3aXRoIGFzc2V0cyBmb3IgZXh0ZW5zaW9uIGZvciAke2xhbmd1YWdlfSBkb2VzIG5vdCBleGlzdHMgYXQgJHtleHRlbnNpb25Bc3NldExvY2F0aW9ufSBvciBhdCAke2V4dGVuc2lvbkFzc2V0TG9jYXRpb25BbHR9IGBcbiAgICAgICAgKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGV4dGVuc2lvbkFzc2V0TG9jYXRpb24gPSBleHRlbnNpb25Bc3NldExvY2F0aW9uQWx0O1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGV4dGVuc2lvbkFzc2V0TG9jYXRpb25XcmFwcGVyID0gcGF0aC5qb2luKFxuICAgICAgLy8gZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbi5zdWJzdHJpbmcoXG4gICAgICAvLyAgIDAsXG4gICAgICAvLyAgIGV4dGVuc2lvbkFzc2V0TG9jYXRpb24ubGFzdEluZGV4T2YocGF0aC5zZXApXG4gICAgICAvLyApLFxuICAgICAgZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbixcbiAgICAgICdzcHktd3JhcHBlcidcbiAgICApO1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhleHRlbnNpb25Bc3NldExvY2F0aW9uV3JhcHBlcikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFdyYXBwZXIgc2NyaXB0IGZvciBleHRlbnNpb24gZG9lcyBub3QgZXhpc3RzIGF0ICR7ZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbldyYXBwZXJ9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZXh0ZW5zaW9uQXNzZXRMb2NhdGlvbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBXcml0ZSBTcHlFdmVudHMgY2xhc3MsIHdoaWNoIGhlbHBzIHdpdGggd3JpdGluZyB0aGUgY29kZSBmb3IgdGVzdHMuXG4gICAqIEBwYXJhbSBmaWxlTG9jYXRpb25cbiAgICovXG4gIHByaXZhdGUgd3JpdGVTcHlFdmVudHNDbGFzcyhmaWxlTG9jYXRpb246IHN0cmluZykge1xuICAgIGZzLm1rZGlyU3luYyhwYXRoLmRpcm5hbWUoZmlsZUxvY2F0aW9uKSwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG5cbiAgICBjb25zdCBwcm9wZXJ0aWVzID0gdGhpcy5zZXJ2aWNlS2V5c1xuICAgICAgLm1hcCgoc2spID0+IGAgICR7c2sucmVwbGFjZSgvIy9nLCAnJyl9OiAnJHtza30nID0gJyR7c2t9JztcXG5gKVxuICAgICAgLmpvaW4oJycpO1xuXG4gICAgY29uc3QgY29kZSA9IGAvKiBlc2xpbnQtZGlzYWJsZSAqL1xcbmV4cG9ydCBjbGFzcyBTZXJ2ZXJsZXNzU3B5RXZlbnRzIHtcXG4ke3Byb3BlcnRpZXN9fVxcbmA7XG5cbiAgICBmcy53cml0ZUZpbGVTeW5jKGZpbGVMb2NhdGlvbiwgY29kZSk7XG4gIH1cblxuICBwcml2YXRlIGdldEFsbE5vZGVzKHBhcmVudDogSUNvbnN0cnVjdCkge1xuICAgIGNvbnN0IG5vZGVzOiBJQ29uc3RydWN0W10gPSBbXTtcbiAgICBub2Rlcy5wdXNoKHBhcmVudCk7XG4gICAgdGhpcy5nZXRBbGxOb2Rlc1JlY3Vyc2l2ZShwYXJlbnQsIG5vZGVzKTtcbiAgICByZXR1cm4gbm9kZXM7XG4gIH1cblxuICBwcml2YXRlIGdldEFsbE5vZGVzUmVjdXJzaXZlKHBhcmVudDogSUNvbnN0cnVjdCwgbm9kZXM6IElDb25zdHJ1Y3RbXSkge1xuICAgIGZvciAoY29uc3Qgbm9kZSBvZiBwYXJlbnQubm9kZS5jaGlsZHJlbikge1xuICAgICAgbm9kZXMucHVzaChub2RlKTtcbiAgICAgIHRoaXMuZ2V0QWxsTm9kZXNSZWN1cnNpdmUobm9kZSwgbm9kZXMpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlOb2RlKG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICBpZiAodGhpcy5zcGllZE5vZGVzLmluY2x1ZGVzKG5vZGUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zcGllZE5vZGVzLnB1c2gobm9kZSk7XG5cbiAgICBpZiAodGhpcy5jcmVhdGVkUmVzb3VyY2VzQnlTU3B5LmluY2x1ZGVzKG5vZGUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uUG9vbC5maW5kKChzKSA9PiBzLmZ1bmN0aW9uID09PSBub2RlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnByb3BzPy5kZWJ1Z01vZGUpIHtcbiAgICAgIGNvbnNvbGUuaW5mbygnU3B5IG9uIG5vZGUnLCB0aGlzLmdldENvbnN0cnVjdE5hbWUobm9kZSkpO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIG5vZGUgaW5zdGFuY2VvZiBsYW1iZGEuRnVuY3Rpb24gfHxcbiAgICAgIG5vZGUgaW5zdGFuY2VvZiBOb2RlanNGdW5jdGlvbiB8fFxuICAgICAgaXNMYW1iZGFGdW5jdGlvbihub2RlKVxuICAgICkge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweUxhbWJkYShub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBzbnMuVG9waWMpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlTbnNUb3BpYyhub2RlKTtcbiAgICB9IGVsc2UgaWYgKG5vZGUgaW5zdGFuY2VvZiBzbnMuU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5U25zU3Vic2NyaXB0aW9uKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIHMzLkJ1Y2tldCkge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweVMzKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIGR5bmFtb0RiLlRhYmxlKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5RHluYW1vZGIobm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgZHluYW1vRGIuVGFibGVWMikge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweUR5bmFtb2RiKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIGV2ZW50cy5FdmVudEJ1cykge1xuICAgICAgdGhpcy5pbnRlcm5hbFNweUV2ZW50QnVzKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIGV2ZW50cy5SdWxlKSB7XG4gICAgICB0aGlzLmludGVybmFsU3B5RXZlbnRCdXNSdWxlKG5vZGUpO1xuICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIGxhbWJkYS5DZm5FdmVudFNvdXJjZU1hcHBpbmcpIHtcbiAgICAgIHRoaXMuaW50ZXJuYWxTcHlTcXMobm9kZSk7XG4gICAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2Ygc3FzLlF1ZXVlKSB7XG4gICAgICBpZiAodGhpcy5wcm9wcz8uc3B5U3FzV2l0aE5vU3Vic2NyaXB0aW9uQW5kRHJvcEFsbE1lc3NhZ2VzKSB7XG4gICAgICAgIHRoaXMuaW50ZXJuYWxTcHlTcHlTcXNXaXRoTm9TdWJzY3JpcHRpb24obm9kZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRFeHRlbnNpb25Gb3JSdW50aW1lKFxuICAgIHJ1bnRpbWU6IGxhbWJkYS5SdW50aW1lLFxuICAgIGFyY2hpdGVjdHVyZTogbGFtYmRhLkFyY2hpdGVjdHVyZVxuICApOiB7IGxheWVyOiBsYW1iZGEuSUxheWVyVmVyc2lvbjsgc3B5V3JhcHBlclBhdGg6IHN0cmluZyB9IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBsYXllcktleSA9XG4gICAgICBgc3NweV9leHRlbnNpb25fJHtydW50aW1lLnRvU3RyaW5nKCl9XyR7YXJjaGl0ZWN0dXJlLm5hbWUudG9TdHJpbmcoKX1gLnJlcGxhY2UoXG4gICAgICAgIC9cXC4vZyxcbiAgICAgICAgJ18nXG4gICAgICApO1xuXG4gICAgbGV0IGxheWVyID0gdGhpcy5sYXllck1hcFtsYXllcktleV07XG4gICAgbGV0IHNweVdyYXBwZXJQYXRoID0gJy9vcHQvc3B5LXdyYXBwZXInO1xuXG4gICAgc3dpdGNoIChydW50aW1lLm5hbWUpIHtcbiAgICAgIGNhc2UgbGFtYmRhLlJ1bnRpbWUuUFlUSE9OXzNfOC5uYW1lOlxuICAgICAgY2FzZSBsYW1iZGEuUnVudGltZS5QWVRIT05fM185Lm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLlBZVEhPTl8zXzEwLm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLlBZVEhPTl8zXzExLm5hbWU6XG4gICAgICBjYXNlIGxhbWJkYS5SdW50aW1lLlBZVEhPTl8zXzEyLm5hbWU6XG4gICAgICAgIHNweVdyYXBwZXJQYXRoID0gJy9vcHQvcHl0aG9uL3NweS13cmFwcGVyJztcbiAgICAgICAgbGF5ZXIgPVxuICAgICAgICAgIGxheWVyIHx8XG4gICAgICAgICAgbmV3IFB5dGhvbkxheWVyVmVyc2lvbih0aGlzLCBsYXllcktleSwge1xuICAgICAgICAgICAgY29tcGF0aWJsZVJ1bnRpbWVzOiBbcnVudGltZV0sXG4gICAgICAgICAgICBjb21wYXRpYmxlQXJjaGl0ZWN0dXJlczogW2FyY2hpdGVjdHVyZV0sXG4gICAgICAgICAgICBlbnRyeTogdGhpcy5nZXRMYW5ndWFnZUV4dGVuc2lvbkFzc2V0TG9jYXRpb24oJ3B5dGhvbicpLFxuICAgICAgICAgICAgYnVuZGxpbmc6IHtcbiAgICAgICAgICAgICAgYnVuZGxpbmdGaWxlQWNjZXNzOiBCdW5kbGluZ0ZpbGVBY2Nlc3MuVk9MVU1FX0NPUFksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzEyX1gubmFtZTpcbiAgICAgIGNhc2UgbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzE0X1gubmFtZTpcbiAgICAgIGNhc2UgbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzE2X1gubmFtZTpcbiAgICAgIGNhc2UgbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzE4X1gubmFtZTpcbiAgICAgIGNhc2UgbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzIwX1gubmFtZTpcbiAgICAgIGNhc2UgbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzIyX1gubmFtZTpcbiAgICAgICAgbGF5ZXIgPVxuICAgICAgICAgIGxheWVyIHx8XG4gICAgICAgICAgbmV3IGxhbWJkYS5MYXllclZlcnNpb24odGhpcywgbGF5ZXJLZXksIHtcbiAgICAgICAgICAgIGNvbXBhdGlibGVSdW50aW1lczogW3J1bnRpbWVdLFxuICAgICAgICAgICAgY29tcGF0aWJsZUFyY2hpdGVjdHVyZXM6IFthcmNoaXRlY3R1cmVdLFxuICAgICAgICAgICAgY29kZTogbGFtYmRhLkNvZGUuZnJvbUFzc2V0KHRoaXMuZ2V0RXh0ZW5zaW9uQXNzZXRMb2NhdGlvbigpKSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBjb25zb2xlLmxvZyhgTm8gZXh0ZW5zaW9ucyBhdmFpbGFibGUgZm9yICR7cnVudGltZS50b1N0cmluZygpfWApO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHRoaXMubGF5ZXJNYXBbbGF5ZXJLZXldID0gbGF5ZXI7XG4gICAgdGhpcy5jcmVhdGVkUmVzb3VyY2VzQnlTU3B5LnB1c2gobGF5ZXIpO1xuICAgIHJldHVybiB7IGxheWVyLCBzcHlXcmFwcGVyUGF0aCB9O1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweVNweVNxc1dpdGhOb1N1YnNjcmlwdGlvbihxdWV1ZTogc3FzLlF1ZXVlKSB7XG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gdGhpcy5maW5kRWxlbWVudDxsYW1iZGEuQ2ZuRXZlbnRTb3VyY2VNYXBwaW5nPihcbiAgICAgIChuOiBJQ29uc3RydWN0KSA9PlxuICAgICAgICBuIGluc3RhbmNlb2YgbGFtYmRhLkNmbkV2ZW50U291cmNlTWFwcGluZyAmJlxuICAgICAgICAobiBhcyBsYW1iZGEuQ2ZuRXZlbnRTb3VyY2VNYXBwaW5nKS5ldmVudFNvdXJjZUFybiA9PT0gcXVldWUucXVldWVBcm5cbiAgICApO1xuXG4gICAgaWYgKHN1YnNjcmlwdGlvbikge1xuICAgICAgcmV0dXJuOyAvL2FscmVhZHkgaGF2ZSBzdWJzY3JpcHRpb25cbiAgICB9XG5cbiAgICBjb25zdCBxdWV1ZU5hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUocXVldWUpO1xuICAgIGNvbnN0IGZ1bmMgPSBuZXcgTm9kZWpzRnVuY3Rpb24oXG4gICAgICB0aGlzLFxuICAgICAgYCR7cXVldWVOYW1lfVNxc1N1YnNjcmlwdGlvbkFuZERyb3BBbGxNZXNzYWdlc2AsXG4gICAgICB7XG4gICAgICAgIG1lbW9yeVNpemU6IDUxMixcbiAgICAgICAgdGltZW91dDogRHVyYXRpb24uc2Vjb25kcyg1KSxcbiAgICAgICAgcnVudGltZTogbGFtYmRhLlJ1bnRpbWUuTk9ERUpTXzIyX1gsXG4gICAgICAgIGhhbmRsZXI6ICdoYW5kbGVyJyxcbiAgICAgICAgZW50cnk6IHRoaXMuZ2V0QXNzZXRMb2NhdGlvbihcbiAgICAgICAgICAnZnVuY3Rpb25zL3Nxc1N1YnNjcmlwdGlvbkFuZERyb3BBbGxNZXNzYWdlcy5qcydcbiAgICAgICAgKSxcbiAgICAgICAgZW52aXJvbm1lbnQ6IHRoaXMuZ2V0RGVmYXVsdExhbWJkYUVudmlyb25tZW50VmFyaWFibGVzKCksXG4gICAgICB9XG4gICAgKTtcbiAgICBmdW5jLmFkZEV2ZW50U291cmNlKG5ldyBTcXNFdmVudFNvdXJjZShxdWV1ZSkpO1xuICAgIHRoaXMuc2V0dXBGb3JJb1QoZnVuYyk7XG4gICAgY29uc3QgeyBsYXllciwgc3B5V3JhcHBlclBhdGggfSA9IHRoaXMuZ2V0RXh0ZW5zaW9uRm9yUnVudGltZShcbiAgICAgIGZ1bmMucnVudGltZSxcbiAgICAgIGZ1bmMuYXJjaGl0ZWN0dXJlXG4gICAgKSE7XG4gICAgZnVuYy5hZGRMYXllcnMobGF5ZXIpO1xuXG4gICAgZnVuYy5hZGRFbnZpcm9ubWVudCgnQVdTX0xBTUJEQV9FWEVDX1dSQVBQRVInLCBzcHlXcmFwcGVyUGF0aCk7XG5cbiAgICBpZiAodGhpcy5wcm9wcz8uZGVidWdNb2RlKSB7XG4gICAgICBmdW5jLmFkZEVudmlyb25tZW50KGVudlZhcmlhYmxlTmFtZXMuU1NQWV9ERUJVRywgJ3RydWUnKTtcbiAgICB9XG5cbiAgICB0aGlzLmNyZWF0ZWRSZXNvdXJjZXNCeVNTcHkucHVzaChmdW5jKTtcblxuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgU3FzIyR7cXVldWVOYW1lfWA7XG5cbiAgICB0aGlzLmFkZE1hcHBpbmdUb0Z1bmN0aW9uKGZ1bmMsIHtcbiAgICAgIGtleTogcXVldWUucXVldWVBcm4sXG4gICAgICB2YWx1ZTogc2VydmljZUtleSxcbiAgICB9KTtcblxuICAgIHRoaXMuc2VydmljZUtleXMucHVzaChzZXJ2aWNlS2V5KTtcbiAgICBmdW5jLmFkZEVudmlyb25tZW50KGVudlZhcmlhYmxlTmFtZXMuU1NQWV9TVUJTQ1JJQkVEX1RPX1NRUywgJ3RydWUnKTtcbiAgfVxuXG4gIHByaXZhdGUgaW50ZXJuYWxTcHlTcXMobm9kZTogbGFtYmRhLkNmbkV2ZW50U291cmNlTWFwcGluZykge1xuICAgIGNvbnN0IHF1ZXVlID0gdGhpcy5maW5kRWxlbWVudDxzcXMuUXVldWU+KFxuICAgICAgKG46IElDb25zdHJ1Y3QpID0+XG4gICAgICAgIG4gaW5zdGFuY2VvZiBzcXMuUXVldWUgJiZcbiAgICAgICAgKG4gYXMgc3FzLlF1ZXVlKS5xdWV1ZUFybiA9PT0gbm9kZS5ldmVudFNvdXJjZUFyblxuICAgICk7XG5cbiAgICBjb25zdCBmdW5jID0gdGhpcy5maW5kRWxlbWVudDxsYW1iZGEuRnVuY3Rpb24+KFxuICAgICAgKG46IElDb25zdHJ1Y3QpID0+XG4gICAgICAgIG4gaW5zdGFuY2VvZiBsYW1iZGEuRnVuY3Rpb24gJiZcbiAgICAgICAgKG4gYXMgbGFtYmRhLkZ1bmN0aW9uKS5mdW5jdGlvbk5hbWUgPT09IG5vZGUuZnVuY3Rpb25OYW1lXG4gICAgKTtcblxuICAgIGlmIChxdWV1ZSAmJiBmdW5jKSB7XG4gICAgICBjb25zdCBxdWV1ZU5hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUocXVldWUpO1xuXG4gICAgICBjb25zdCBzZXJ2aWNlS2V5ID0gYFNxcyMke3F1ZXVlTmFtZX1gO1xuXG4gICAgICB0aGlzLmFkZE1hcHBpbmdUb0Z1bmN0aW9uKGZ1bmMsIHtcbiAgICAgICAga2V5OiBxdWV1ZS5xdWV1ZUFybixcbiAgICAgICAgdmFsdWU6IHNlcnZpY2VLZXksXG4gICAgICB9KTtcblxuICAgICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICAgICAgZnVuYy5hZGRFbnZpcm9ubWVudChlbnZWYXJpYWJsZU5hbWVzLlNTUFlfU1VCU0NSSUJFRF9UT19TUVMsICd0cnVlJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbihpbmRleDogbnVtYmVyKSB7XG4gICAgY29uc3QgZnVuYyA9IG5ldyBsYW1iZGFOb2RlLk5vZGVqc0Z1bmN0aW9uKHRoaXMsIGBTdWJzY3JpcHRpb24ke2luZGV4fWAsIHtcbiAgICAgIG1lbW9yeVNpemU6IDUxMixcbiAgICAgIHRpbWVvdXQ6IER1cmF0aW9uLnNlY29uZHMoNSksXG4gICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5OT0RFSlNfMjJfWCxcbiAgICAgIGhhbmRsZXI6ICdoYW5kbGVyJyxcbiAgICAgIGVudHJ5OiB0aGlzLmdldEFzc2V0TG9jYXRpb24oJ2Z1bmN0aW9ucy9zZW5kTWVzc2FnZS5qcycpLFxuICAgICAgZW52aXJvbm1lbnQ6IHtcbiAgICAgICAgTk9ERV9PUFRJT05TOiAnLS1lbmFibGUtc291cmNlLW1hcHMnLFxuICAgICAgfSxcbiAgICB9KTtcbiAgICB0aGlzLnNldHVwRm9ySW9UKGZ1bmMpO1xuICAgIHJldHVybiBmdW5jO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweVMzKHMzQnVja2V0OiBzMy5CdWNrZXQpIHtcbiAgICBzM0J1Y2tldC5hZGRFdmVudE5vdGlmaWNhdGlvbihcbiAgICAgIHMzLkV2ZW50VHlwZS5PQkpFQ1RfQ1JFQVRFRF9QVVQsXG4gICAgICBuZXcgczNub3RpZi5MYW1iZGFEZXN0aW5hdGlvbih0aGlzLmxhbWJkYVN1YnNjcmlwdGlvbk1haW4uZnVuY3Rpb24pXG4gICAgKTtcblxuICAgIGNvbnN0IG5hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUoczNCdWNrZXQpO1xuXG4gICAgY29uc3Qgc2VydmljZUtleSA9IGBTMyMke25hbWV9YDtcbiAgICB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvbk1haW4ubWFwcGluZ1tzM0J1Y2tldC5idWNrZXRBcm5dID0gc2VydmljZUtleTtcbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goc2VydmljZUtleSk7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5RHluYW1vZGIodGFibGU6IGR5bmFtb0RiLlRhYmxlIHwgZHluYW1vRGIuVGFibGVWMikge1xuICAgIC8vIGVuYWJsZSBEeW5hbW9EQiBzdHJlYW1zIHdpdGggYSBoYWNrXG4gICAgKHRhYmxlLm5vZGUuZGVmYXVsdENoaWxkIGFzIGR5bmFtb0RiLkNmblRhYmxlKS5zdHJlYW1TcGVjaWZpY2F0aW9uID0ge1xuICAgICAgc3RyZWFtVmlld1R5cGU6IGR5bmFtb0RiLlN0cmVhbVZpZXdUeXBlLk5FV19BTkRfT0xEX0lNQUdFUyxcbiAgICB9O1xuXG4gICAgT2JqZWN0LmFzc2lnbih0YWJsZSwge1xuICAgICAgdGFibGVTdHJlYW1Bcm46ICh0YWJsZS5ub2RlLmRlZmF1bHRDaGlsZCBhcyBkeW5hbW9EYi5DZm5UYWJsZSlcbiAgICAgICAgLmF0dHJTdHJlYW1Bcm4sXG4gICAgfSk7XG5cbiAgICB0aGlzLmxhbWJkYVN1YnNjcmlwdGlvbk1haW4uZnVuY3Rpb24uYWRkRXZlbnRTb3VyY2UoXG4gICAgICBuZXcgZHluYW1vRGJTdHJlYW0uRHluYW1vRXZlbnRTb3VyY2UodGFibGUsIHtcbiAgICAgICAgc3RhcnRpbmdQb3NpdGlvbjogbGFtYmRhLlN0YXJ0aW5nUG9zaXRpb24uTEFURVNULFxuICAgICAgICBiYXRjaFNpemU6IDEsXG4gICAgICAgIHJldHJ5QXR0ZW1wdHM6IDAsXG4gICAgICB9KVxuICAgICk7XG5cbiAgICBjb25zdCBuYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKHRhYmxlKTtcblxuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgRHluYW1vREIjJHtuYW1lfWA7XG4gICAgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25NYWluLm1hcHBpbmdbdGFibGUudGFibGVBcm5dID0gc2VydmljZUtleTtcbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goc2VydmljZUtleSk7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5RXZlbnRCdXNSdWxlKHJ1bGU6IGV2ZW50cy5SdWxlKSB7XG4gICAgY29uc3QgeyBldmVudEJ1c05hbWUgfSA9IHJ1bGUubm9kZS5kZWZhdWx0Q2hpbGQgYXMgZXZlbnRzLkNmblJ1bGU7XG4gICAgbGV0IGJyaWRnZU5hbWUgPSAnRGVmYXVsdCc7XG4gICAgaWYgKCEhZXZlbnRCdXNOYW1lKSB7XG4gICAgICBjb25zdCBldmVudEJyaWRnZSA9IHRoaXMuZ2V0RXZlbnRCcmlkZ2UoZXZlbnRCdXNOYW1lKTtcblxuICAgICAgaWYgKCFldmVudEJyaWRnZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbiBub3QgZmluZCBFdmVudEJyaWRnZSB3aXRoIG5hbWUgXCIke2V2ZW50QnVzTmFtZX1cImApO1xuICAgICAgfVxuICAgICAgYnJpZGdlTmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZShldmVudEJyaWRnZSk7XG4gICAgfVxuXG4gICAgY29uc3QgZnVuY3Rpb25TdWJzY3JpcHRpb24gPSB0aGlzLnByb3ZpZGVGdW5jdGlvbkZvclN1YnNjcmlwdGlvbihcbiAgICAgIChzKSA9PiAhcy51c2VkRm9yRXZlbnRCcmlkZ2VcbiAgICApO1xuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLnVzZWRGb3JFdmVudEJyaWRnZSA9IHRydWU7XG5cbiAgICBydWxlLmFkZFRhcmdldChuZXcgdGFyZ2V0cy5MYW1iZGFGdW5jdGlvbihmdW5jdGlvblN1YnNjcmlwdGlvbi5mdW5jdGlvbikpO1xuXG4gICAgY29uc3QgcnVsZU5hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUocnVsZSk7XG4gICAgY29uc3Qgc2VydmljZUtleSA9IGBFdmVudEJyaWRnZVJ1bGUjJHticmlkZ2VOYW1lfSMke3J1bGVOYW1lfWA7XG4gICAgZnVuY3Rpb25TdWJzY3JpcHRpb24ubWFwcGluZy5ldmVudEJyaWRnZSA9IHNlcnZpY2VLZXk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweUV2ZW50QnVzKGV2ZW50QnVzOiBldmVudHMuRXZlbnRCdXMpIHtcbiAgICBjb25zdCBmdW5jdGlvblN1YnNjcmlwdGlvbiA9IHRoaXMucHJvdmlkZUZ1bmN0aW9uRm9yU3Vic2NyaXB0aW9uKFxuICAgICAgKHMpID0+ICFzLnVzZWRGb3JFdmVudEJyaWRnZVxuICAgICk7XG4gICAgZnVuY3Rpb25TdWJzY3JpcHRpb24udXNlZEZvckV2ZW50QnJpZGdlID0gdHJ1ZTtcblxuICAgIGNvbnN0IGJyaWRnZU5hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUoZXZlbnRCdXMpO1xuICAgIGNvbnN0IHJ1bGUgPSBuZXcgZXZlbnRzLlJ1bGUodGhpcywgYFJ1bGVBbGwke2JyaWRnZU5hbWV9YCwge1xuICAgICAgZXZlbnRCdXMsXG4gICAgICBldmVudFBhdHRlcm46IHsgdmVyc2lvbjogWycwJ10gfSxcbiAgICAgIHRhcmdldHM6IFtuZXcgdGFyZ2V0cy5MYW1iZGFGdW5jdGlvbihmdW5jdGlvblN1YnNjcmlwdGlvbi5mdW5jdGlvbildLFxuICAgIH0pO1xuXG4gICAgdGhpcy5jcmVhdGVkUmVzb3VyY2VzQnlTU3B5LnB1c2gocnVsZSk7XG4gICAgY29uc3Qgc2VydmljZUtleSA9IGBFdmVudEJyaWRnZSMke2JyaWRnZU5hbWV9YDtcbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi5tYXBwaW5nLmV2ZW50QnJpZGdlID0gc2VydmljZUtleTtcbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goc2VydmljZUtleSk7XG4gIH1cblxuICBwcml2YXRlIGludGVybmFsU3B5U25zVG9waWModG9waWM6IHNucy5Ub3BpYykge1xuICAgIGNvbnN0IGZ1bmN0aW9uU3Vic2NyaXB0aW9uID0gdGhpcy5wcm92aWRlRnVuY3Rpb25Gb3JTdWJzY3JpcHRpb24oXG4gICAgICAocykgPT4gIXMuc3Vic3JpYmVkVG9waWNzLmluY2x1ZGVzKHRvcGljKVxuICAgICk7XG5cbiAgICBjb25zdCBzdWJzY3JpcHRpb24gPSB0b3BpYy5hZGRTdWJzY3JpcHRpb24oXG4gICAgICBuZXcgc25zU3Vicy5MYW1iZGFTdWJzY3JpcHRpb24oZnVuY3Rpb25TdWJzY3JpcHRpb24uZnVuY3Rpb24pXG4gICAgKTtcbiAgICB0aGlzLmNyZWF0ZWRSZXNvdXJjZXNCeVNTcHkucHVzaChzdWJzY3JpcHRpb24pO1xuICAgIGNvbnN0IHRvcGljTmFtZSA9IHRoaXMuZ2V0Q29uc3RydWN0TmFtZSh0b3BpYyk7XG4gICAgY29uc3Qgc2VydmljZUtleSA9IGBTbnNUb3BpYyMke3RvcGljTmFtZX1gO1xuICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uLm1hcHBpbmdbdG9waWMudG9waWNBcm5dID0gc2VydmljZUtleTtcbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goc2VydmljZUtleSk7XG4gICAgZnVuY3Rpb25TdWJzY3JpcHRpb24uc3Vic3JpYmVkVG9waWNzLnB1c2godG9waWMpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweVNuc1N1YnNjcmlwdGlvbihzdWJzY3JpcHRpb246IHNucy5TdWJzY3JpcHRpb24pIHtcbiAgICBpZiAoIXN1YnNjcmlwdGlvbi5ub2RlLnNjb3BlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdG9waWMgPSB0aGlzLmdldFRvcGljKFxuICAgICAgKHN1YnNjcmlwdGlvbi5ub2RlLmRlZmF1bHRDaGlsZCBhcyBzbnMuQ2ZuU3Vic2NyaXB0aW9uKS50b3BpY0FyblxuICAgICk7XG5cbiAgICBpZiAoIXRvcGljKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgZmluZCBUb3BpYycpO1xuICAgIH1cblxuICAgIGNvbnN0IGZ1bmN0aW9uU3Vic2NyaXB0aW9uID0gdGhpcy5wcm92aWRlRnVuY3Rpb25Gb3JTdWJzY3JpcHRpb24oXG4gICAgICAocykgPT4gIXMuc3Vic3JpYmVkVG9waWNzLmluY2x1ZGVzKHRvcGljKVxuICAgICk7XG5cbiAgICBjb25zdCB7IGZpbHRlclBvbGljeSB9ID0gc3Vic2NyaXB0aW9uLm5vZGVcbiAgICAgIC5kZWZhdWx0Q2hpbGQgYXMgc25zLkNmblN1YnNjcmlwdGlvbjtcblxuICAgIGNvbnN0IHN1YnNjcmlwdGlvbkNsb25lID0gdG9waWMuYWRkU3Vic2NyaXB0aW9uKFxuICAgICAgbmV3IHNuc1N1YnMuTGFtYmRhU3Vic2NyaXB0aW9uKGZ1bmN0aW9uU3Vic2NyaXB0aW9uLmZ1bmN0aW9uKVxuICAgICk7XG4gICAgKHN1YnNjcmlwdGlvbkNsb25lLm5vZGUuZGVmYXVsdENoaWxkIGFzIHNucy5DZm5TdWJzY3JpcHRpb24pLmZpbHRlclBvbGljeSA9XG4gICAgICBmaWx0ZXJQb2xpY3k7XG5cbiAgICB0aGlzLmNyZWF0ZWRSZXNvdXJjZXNCeVNTcHkucHVzaChzdWJzY3JpcHRpb25DbG9uZSk7XG5cbiAgICBjb25zdCB0b3BpY05hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUodG9waWMpO1xuICAgIGNvbnN0IHRhcmdldE5hbWUgPSB0aGlzLmdldENvbnN0cnVjdE5hbWUoc3Vic2NyaXB0aW9uLm5vZGUuc2NvcGUpO1xuXG4gICAgZnVuY3Rpb25TdWJzY3JpcHRpb24uc3Vic3JpYmVkVG9waWNzLnB1c2godG9waWMpO1xuICAgIGNvbnN0IHNlcnZpY2VLZXkgPSBgU25zU3Vic2NyaXB0aW9uIyR7dG9waWNOYW1lfSMke3RhcmdldE5hbWV9YDtcbiAgICBmdW5jdGlvblN1YnNjcmlwdGlvbi5tYXBwaW5nW3RvcGljLnRvcGljQXJuXSA9IHNlcnZpY2VLZXk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKHNlcnZpY2VLZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBwcm92aWRlRnVuY3Rpb25Gb3JTdWJzY3JpcHRpb24oXG4gICAgZmlsdGVyRnVuY3Rpb24/OiAoc3Vic2NyaXB0aW9uOiBMYW1iZGFTdWJzY3JpcHRpb24pID0+IGJvb2xlYW5cbiAgKSB7XG4gICAgbGV0IGZ1bmN0aW9uU3Vic2NyaXB0aW9uOiBMYW1iZGFTdWJzY3JpcHRpb24gfCB1bmRlZmluZWQ7XG5cbiAgICBpZiAoZmlsdGVyRnVuY3Rpb24pIHtcbiAgICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uID0gdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25Qb29sLmZpbmQoZmlsdGVyRnVuY3Rpb24pO1xuICAgIH0gZWxzZSBpZiAodGhpcy5sYW1iZGFTdWJzY3JpcHRpb25Qb29sLmxlbmd0aCA+IDApIHtcbiAgICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uID0gdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25Qb29sWzBdO1xuICAgIH1cblxuICAgIGlmICghZnVuY3Rpb25TdWJzY3JpcHRpb24pIHtcbiAgICAgIGZ1bmN0aW9uU3Vic2NyaXB0aW9uID0ge1xuICAgICAgICBzdWJzcmliZWRUb3BpY3M6IFtdLFxuICAgICAgICB1c2VkRm9yRXZlbnRCcmlkZ2U6IGZhbHNlLFxuICAgICAgICBtYXBwaW5nOiB7fSxcbiAgICAgICAgZnVuY3Rpb246IHRoaXMuY3JlYXRlRnVuY3Rpb25Gb3JTdWJzY3JpcHRpb24oXG4gICAgICAgICAgdGhpcy5sYW1iZGFTdWJzY3JpcHRpb25Qb29sLmxlbmd0aFxuICAgICAgICApLFxuICAgICAgfTtcbiAgICAgIHRoaXMubGFtYmRhU3Vic2NyaXB0aW9uUG9vbC5wdXNoKGZ1bmN0aW9uU3Vic2NyaXB0aW9uKTtcbiAgICB9XG4gICAgcmV0dXJuIGZ1bmN0aW9uU3Vic2NyaXB0aW9uO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXR1cEZvcklvVChmdW5jOiBsYW1iZGEuRnVuY3Rpb24pIHtcbiAgICBmdW5jLmFkZEVudmlyb25tZW50KFxuICAgICAgZW52VmFyaWFibGVOYW1lcy5TU1BZX1JPT1RfU1RBQ0ssXG4gICAgICB0aGlzLmNsZWFuTmFtZSh0aGlzLmZpbmRSb290U3RhY2soU3RhY2sub2YodGhpcykpLm5vZGUuaWQpXG4gICAgKTtcbiAgICBmdW5jLmFkZEVudmlyb25tZW50KGVudlZhcmlhYmxlTmFtZXMuU1NQWV9JT1RfRU5EUE9JTlQsIHRoaXMuaW90RW5kcG9pbnQpO1xuXG4gICAgZnVuYy5hZGRUb1JvbGVQb2xpY3koXG4gICAgICBuZXcgYXdzX2lhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBhY3Rpb25zOiBbJ2lvdDoqJ10sXG4gICAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XLFxuICAgICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnRlcm5hbFNweUxhbWJkYShmdW5jOiBsYW1iZGEuRnVuY3Rpb24pIHtcbiAgICBjb25zdCB7IGxheWVyLCBzcHlXcmFwcGVyUGF0aCB9ID0gdGhpcy5nZXRFeHRlbnNpb25Gb3JSdW50aW1lKFxuICAgICAgZnVuYy5ydW50aW1lLFxuICAgICAgZnVuYy5hcmNoaXRlY3R1cmUgfHwgQXJjaGl0ZWN0dXJlLlg4Nl82NFxuICAgICkhO1xuICAgIGlmICghbGF5ZXIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZnVuYy5hZGRMYXllcnMobGF5ZXIpO1xuXG4gICAgY29uc3QgZnVuY3Rpb25OYW1lID0gdGhpcy5nZXRDb25zdHJ1Y3ROYW1lKGZ1bmMpO1xuXG4gICAgZnVuYy5hZGRFbnZpcm9ubWVudChlbnZWYXJpYWJsZU5hbWVzLlNTUFlfRlVOQ1RJT05fTkFNRSwgZnVuY3Rpb25OYW1lKTtcbiAgICBmdW5jLmFkZEVudmlyb25tZW50KCdBV1NfTEFNQkRBX0VYRUNfV1JBUFBFUicsIHNweVdyYXBwZXJQYXRoKTtcblxuICAgIGlmICh0aGlzLnByb3BzPy5kZWJ1Z01vZGUpIHtcbiAgICAgIGZ1bmMuYWRkRW52aXJvbm1lbnQoZW52VmFyaWFibGVOYW1lcy5TU1BZX0RFQlVHLCAndHJ1ZScpO1xuICAgIH1cblxuICAgIHRoaXMuc2V0dXBGb3JJb1QoZnVuYyk7XG5cbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goYEZ1bmN0aW9uIyR7ZnVuY3Rpb25OYW1lfSNSZXF1ZXN0YCk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKGBGdW5jdGlvbiMke2Z1bmN0aW9uTmFtZX0jRXJyb3JgKTtcbiAgICB0aGlzLnNlcnZpY2VLZXlzLnB1c2goYEZ1bmN0aW9uIyR7ZnVuY3Rpb25OYW1lfSNDb25zb2xlYCk7XG4gICAgdGhpcy5zZXJ2aWNlS2V5cy5wdXNoKGBGdW5jdGlvbiMke2Z1bmN0aW9uTmFtZX0jUmVzcG9uc2VgKTtcblxuICAgIHRoaXMuYWRkTWFwcGluZ1RvRnVuY3Rpb24oZnVuYyk7XG4gIH1cblxuICBwdWJsaWMgZ2V0Q29uc3RydWN0TmFtZShjb25zdHJ1Y3Q6IElDb25zdHJ1Y3QpIHtcbiAgICBsZXQgY29uc3RydWN0TmFtZSA9IGNvbnN0cnVjdC5ub2RlLnBhdGg7XG4gICAgY29uc3QgeyBub2RlIH0gPSBTdGFjay5vZih0aGlzKTtcblxuICAgIGlmIChjb25zdHJ1Y3ROYW1lLnN0YXJ0c1dpdGgobm9kZS5pZCkpIHtcbiAgICAgIGNvbnN0cnVjdE5hbWUgPSBjb25zdHJ1Y3ROYW1lLnN1YnN0cmluZyhub2RlLmlkLmxlbmd0aCArIDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmNsZWFuTmFtZShjb25zdHJ1Y3ROYW1lKTtcbiAgfVxuXG4gIHByaXZhdGUgY2xlYW5OYW1lKG5hbWU6IHN0cmluZykge1xuICAgIC8vc25ha2UgY2FzZSB0byBjYW1lbCBjYXNlIGluY2x1ZGluZyBkYXNoIGFuZCBmaXJzdCBsZXR0ZXIgdG8gdXBwZXIgY2FzZVxuICAgIHJldHVybiBuYW1lXG4gICAgICAucmVwbGFjZSgvWy1fXSsvZywgJyAnKVxuICAgICAgLnJlcGxhY2UoL1teXFx3XFxzXS9nLCAnJylcbiAgICAgIC5yZXBsYWNlKC9cXHMoLikvZywgKCQxKSA9PiAkMS50b1VwcGVyQ2FzZSgpKVxuICAgICAgLnJlcGxhY2UoL1xccy9nLCAnJylcbiAgICAgIC5yZXBsYWNlKC9eKC4pLywgKCQxKSA9PiAkMS50b1VwcGVyQ2FzZSgpKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0VG9waWModG9waWNBcm46IHN0cmluZyk6IHNucy5Ub3BpYyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgdG9waWMgPSB0aGlzLmZpbmRFbGVtZW50PHNucy5Ub3BpYz4oXG4gICAgICAobm9kZTogSUNvbnN0cnVjdCkgPT5cbiAgICAgICAgbm9kZSBpbnN0YW5jZW9mIHNucy5Ub3BpYyAmJiAobm9kZSBhcyBzbnMuVG9waWMpLnRvcGljQXJuID09PSB0b3BpY0FyblxuICAgICk7XG5cbiAgICByZXR1cm4gdG9waWM7XG4gIH1cblxuICBwcml2YXRlIGdldEV2ZW50QnJpZGdlKGV2ZW50QnVzTmFtZTogc3RyaW5nKTogZXZlbnRzLklFdmVudEJ1cyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgZXZlbnRCcmlkZ2UgPSB0aGlzLmZpbmRFbGVtZW50PGV2ZW50cy5JRXZlbnRCdXM+KFxuICAgICAgKG5vZGU6IElDb25zdHJ1Y3QpID0+XG4gICAgICAgIChub2RlIGluc3RhbmNlb2YgZXZlbnRzLkV2ZW50QnVzIHx8XG4gICAgICAgICAgbm9kZS5jb25zdHJ1Y3Rvci5uYW1lID09PSAnSW1wb3J0ZWRFdmVudEJ1cycpICYmXG4gICAgICAgIChub2RlIGFzIGV2ZW50cy5JRXZlbnRCdXMpLmV2ZW50QnVzTmFtZSA9PT0gZXZlbnRCdXNOYW1lXG4gICAgKTtcblxuICAgIHJldHVybiBldmVudEJyaWRnZTtcbiAgfVxuXG4gIHByaXZhdGUgZmluZFJvb3RTdGFjayhzdGFjazogU3RhY2spOiBTdGFjayB7XG4gICAgaWYgKHN0YWNrLm5lc3RlZCkge1xuICAgICAgY29uc3QgcGFyZW50U3RhY2sgPSAoc3RhY2sgYXMgTmVzdGVkU3RhY2spLm5lc3RlZFN0YWNrUGFyZW50O1xuICAgICAgaWYgKHBhcmVudFN0YWNrKSByZXR1cm4gdGhpcy5maW5kUm9vdFN0YWNrKHBhcmVudFN0YWNrKTtcbiAgICAgIHJldHVybiBzdGFjaztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHN0YWNrO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZmluZEVsZW1lbnQ8VCBleHRlbmRzIElDb25zdHJ1Y3QgPSBJQ29uc3RydWN0PihcbiAgICBmaWx0ZXJGdW5jOiAobm9kZTogSUNvbnN0cnVjdCkgPT4gYm9vbGVhbixcbiAgICBwYXJlbnQ/OiBJQ29uc3RydWN0XG4gICk6IFQgfCB1bmRlZmluZWQge1xuICAgIGlmICghcGFyZW50KSB7XG4gICAgICBwYXJlbnQgPSB0aGlzLmZpbmRSb290U3RhY2soU3RhY2sub2YodGhpcykpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qgbm9kZSBvZiBwYXJlbnQubm9kZS5jaGlsZHJlbikge1xuICAgICAgaWYgKGZpbHRlckZ1bmMobm9kZSkpIHtcbiAgICAgICAgcmV0dXJuIG5vZGUgYXMgVDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGVsZW1lbnRGb3VuZEluQ2hpbGQgPSB0aGlzLmZpbmRFbGVtZW50PFQ+KGZpbHRlckZ1bmMsIG5vZGUpO1xuICAgICAgaWYgKGVsZW1lbnRGb3VuZEluQ2hpbGQpIHtcbiAgICAgICAgcmV0dXJuIGVsZW1lbnRGb3VuZEluQ2hpbGQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHByaXZhdGUgYWRkTWFwcGluZ1RvRnVuY3Rpb24oXG4gICAgZnVuYzogbGFtYmRhLkZ1bmN0aW9uLFxuICAgIGtleVZhbHVlPzogeyBrZXk6IHN0cmluZzsgdmFsdWU6IHN0cmluZyB9XG4gICkge1xuICAgIGZvciAoY29uc3QgZnMgb2YgdGhpcy5sYW1iZGFzU3BpZWQpIHtcbiAgICAgIGlmIChmcy5mdW5jdGlvbiA9PT0gZnVuYykge1xuICAgICAgICBpZiAoa2V5VmFsdWUpIHtcbiAgICAgICAgICBmcy5tYXBwaW5nW2tleVZhbHVlLmtleV0gPSBrZXlWYWx1ZS52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZnM6IExhbWJkYVNwaWVkID0ge1xuICAgICAgZnVuY3Rpb246IGZ1bmMsXG4gICAgICBtYXBwaW5nOiB7fSxcbiAgICB9O1xuXG4gICAgaWYgKGtleVZhbHVlKSB7XG4gICAgICBmcy5tYXBwaW5nW2tleVZhbHVlLmtleV0gPSBrZXlWYWx1ZS52YWx1ZTtcbiAgICB9XG5cbiAgICB0aGlzLmxhbWJkYXNTcGllZC5wdXNoKGZzKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0QXNzZXRMb2NhdGlvbihsb2NhdGlvbjogc3RyaW5nKSB7XG4gICAgY29uc3QgbG9jID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL2xpYi8nICsgbG9jYXRpb24pO1xuXG4gICAgaWYgKGZzLmV4aXN0c1N5bmMobG9jKSkge1xuICAgICAgcmV0dXJuIGxvYztcbiAgICB9XG5cbiAgICBjb25zdCBsb2MyID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uLy4uL2xpYi8nICsgbG9jYXRpb24pO1xuXG4gICAgaWYgKGZzLmV4aXN0c1N5bmMobG9jMikpIHtcbiAgICAgIHJldHVybiBsb2MyO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihgTG9jYXRpb24gJHtsb2N9IGFuZCAke2xvYzJ9IGRvZXMgbm90IGV4aXN0cy5gKTtcbiAgfVxufVxuXG50eXBlIExhbWJkYVN1YnNjcmlwdGlvbiA9IHtcbiAgc3Vic3JpYmVkVG9waWNzOiBzbnMuVG9waWNbXTtcbiAgdXNlZEZvckV2ZW50QnJpZGdlOiBib29sZWFuO1xuICBmdW5jdGlvbjogbGFtYmRhTm9kZS5Ob2RlanNGdW5jdGlvbjtcbiAgbWFwcGluZzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbn07XG5cbnR5cGUgTGFtYmRhU3BpZWQgPSB7XG4gIGZ1bmN0aW9uOiBsYW1iZGEuRnVuY3Rpb247XG4gIG1hcHBpbmc6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59O1xuIl19
@@ -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 (table as any).tableStreamArn = (\n table.node.defaultChild as dynamoDb.CfnTable\n ).attrStreamArn;\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmDA,MAAM,oBAAoB,SACxB,kBAAkB,QAAQ,iBAAiB,QAAQ,aAAa;AAElE,MAAM,uCAAuC;AAE7C,IAAa,gBAAb,cAAmCA,qBAAU;CAU3C,YACE,OACA,IACA,AAAQC,OACR;AACA,QAAM,OAAO,GAAG;EAFR;gCAZqC,EAAE;gCACM,EAAE;sBAEnB,EAAE;qBACT,EAAE;oBACE,EAAE;kBACsB,EAAE;EAU3D,MAAM,YAAY,KAAK,UACrB,KAAK,cAAcC,kBAAM,GAAG,KAAK,CAAC,CAAC,KAAK,GACzC;EAED,MAAM,iBAAiB,IAAIC,6BAAiB,kBAC1C,MACA,sCACA;GACE,UAAU;IACR,SAAS;IACT,QAAQ;IACR,oBACEA,6BAAiB,mBAAmB,aAAa,kBAAkB;IACrE,YAAY,EACV,cAAc,gBACf;IACF;GACD,UAAU;IACR,SAAS;IACT,QAAQ;IACR,oBACEA,6BAAiB,mBAAmB,aAAa,kBAAkB;IACrE,YAAY,EACV,cAAc,gBACf;IACF;GACD,qBAAqB;GACrB,QAAQA,6BAAiB,wBAAwB,aAAa,EAC5D,WAAWA,6BAAiB,wBAAwB,cACrD,CAAC;GACF,cAAc,uCAAuC;GACtD,CACF;AACD,OAAK,cAAc,eAAe,iBAAiB,kBAAkB;AAErE,OAAK,uBAAuB,KAAK,eAAe;AAEhD,MAAIC,sBAAU,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,YAAYF,kBAAM,GAAG,KAAK,CAAC;EAE5C,MAAMG,qBAA0C;GAC9C,WAAW;GACX,QAAQ;GACR,aAAa;GACb,mBAAmB;GACnB,gBAAgB;GAChB,oBAAoB;GACpB,OAAO;GACP,aAAa;GACb,GAAG;GACJ;EAED,MAAM,OACJ,QACAF,6BAAiB,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,gBAAgBG,0CAChB;AACA,QAAI,KAAK,OAAO,UACd,SAAQ,KAAK,YAAY,KAAK,KAAK,KAAK;AAE1C,WAAO;cAEP,mBAAmB,cAClB,gBAAgBC,uBAAO,YACtB,gBAAgBC,gDAChB,iBAAiB,KAAK,EAExB,QAAO;YACE,mBAAmB,eAAe,gBAAgBC,oBAAI,MAC/D,QAAO;YAEP,mBAAmB,qBACnB,gBAAgBA,oBAAI,aAEpB,QAAO;YACE,mBAAmB,SAAS,gBAAgBC,mBAAG,OACxD,QAAO;YAEP,mBAAmB,eACnB,gBAAgBC,yBAAS,MAEzB,QAAO;YAEP,mBAAmB,eACnB,gBAAgBA,yBAAS,QAEzB,QAAO;YAEP,mBAAmB,kBACnB,gBAAgBC,uBAAO,SAEvB,QAAO;YAEP,mBAAmB,sBACnB,gBAAgBA,uBAAO,KAEvB,QAAO;YAEP,mBAAmB,UACnB,gBAAgBL,uBAAO,sBAEvB,QAAO;YAEP,mBAAmB,UACnB,KAAK,OAAO,8CACZ,gBAAgBM,oBAAI,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,eACZC,qDAAiB,oBACjB,KAAK,UAAU,KAAK,QAAQ,CAC7B;AAIH,OAAK,MAAM,QAAQ,KAAK,aACtB,MAAK,SAAS,eACZA,qDAAiB,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,gBAAgBR,uBAAO,YACvB,gBAAgBC,gDAChB,iBAAiB,KAAK,CAEtB,MAAK,kBAAkB,KAAK;WACnB,gBAAgBC,oBAAI,MAC7B,MAAK,oBAAoB,KAAK;WACrB,gBAAgBA,oBAAI,aAC7B,MAAK,2BAA2B,KAAK;WAC5B,gBAAgBC,mBAAG,OAC5B,MAAK,cAAc,KAAK;WACf,gBAAgBC,yBAAS,MAClC,MAAK,oBAAoB,KAAK;WACrB,gBAAgBA,yBAAS,QAClC,MAAK,oBAAoB,KAAK;WACrB,gBAAgBC,uBAAO,SAChC,MAAK,oBAAoB,KAAK;WACrB,gBAAgBA,uBAAO,KAChC,MAAK,wBAAwB,KAAK;WACzB,gBAAgBL,uBAAO,sBAChC,MAAK,eAAe,KAAK;WAChB,gBAAgBM,oBAAI,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,KAAKN,uBAAO,QAAQ,WAAW;GAC/B,KAAKA,uBAAO,QAAQ,WAAW;GAC/B,KAAKA,uBAAO,QAAQ,YAAY;GAChC,KAAKA,uBAAO,QAAQ,YAAY;GAChC,KAAKA,uBAAO,QAAQ,YAAY;AAC9B,qBAAiB;AACjB,YACE,SACA,IAAIS,qDAAmB,MAAM,UAAU;KACrC,oBAAoB,CAAC,QAAQ;KAC7B,yBAAyB,CAAC,aAAa;KACvC,OAAO,KAAK,kCAAkC,SAAS;KACvD,UAAU,EACR,oBAAoBC,+BAAmB,aACxC;KACF,CAAC;AACJ;GACF,KAAKV,uBAAO,QAAQ,YAAY;GAChC,KAAKA,uBAAO,QAAQ,YAAY;GAChC,KAAKA,uBAAO,QAAQ,YAAY;GAChC,KAAKA,uBAAO,QAAQ,YAAY;GAChC,KAAKA,uBAAO,QAAQ,YAAY;GAChC,KAAKA,uBAAO,QAAQ,YAAY;AAC9B,YACE,SACA,IAAIA,uBAAO,aAAa,MAAM,UAAU;KACtC,oBAAoB,CAAC,QAAQ;KAC7B,yBAAyB,CAAC,aAAa;KACvC,MAAMA,uBAAO,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,aAAaA,uBAAO,yBACnB,EAAmC,mBAAmB,MAAM,SAChE,CAGC;EAGF,MAAM,YAAY,KAAK,iBAAiB,MAAM;EAC9C,MAAM,OAAO,IAAIC,6CACf,MACA,GAAG,UAAU,oCACb;GACE,YAAY;GACZ,SAASU,qBAAS,QAAQ,EAAE;GAC5B,SAASX,uBAAO,QAAQ;GACxB,SAAS;GACT,OAAO,KAAK,iBACV,iDACD;GACD,aAAa,KAAK,sCAAsC;GACzD,CACF;AACD,OAAK,eAAe,IAAIY,oDAAe,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,eAAeL,qDAAiB,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,eAAeA,qDAAiB,wBAAwB,OAAO;;CAGtE,AAAQ,eAAe,MAAoC;EACzD,MAAM,QAAQ,KAAK,aAChB,MACC,aAAaD,oBAAI,SAChB,EAAgB,aAAa,KAAK,eACtC;EAED,MAAM,OAAO,KAAK,aACf,MACC,aAAaN,uBAAO,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,eAAeO,qDAAiB,wBAAwB,OAAO;;;CAIxE,AAAQ,8BAA8B,OAAe;EACnD,MAAM,OAAO,IAAIM,8BAAW,eAAe,MAAM,eAAe,SAAS;GACvE,YAAY;GACZ,SAASF,qBAAS,QAAQ,EAAE;GAC5B,SAASX,uBAAO,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,qBACPG,mBAAG,UAAU,oBACb,IAAIW,iCAAQ,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,gBAAgBV,yBAAS,eAAe,oBACzC;AACD,EAAC,MAAc,iBACb,MAAM,KAAK,aACX;AAEF,OAAK,uBAAuB,SAAS,eACnC,IAAIW,qCAAe,kBAAkB,OAAO;GAC1C,kBAAkBf,uBAAO,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,IAAIgB,+BAAQ,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,IAAIX,uBAAO,KAAK,MAAM,UAAU,cAAc;GACzD;GACA,cAAc,EAAE,SAAS,CAAC,IAAI,EAAE;GAChC,SAAS,CAAC,IAAIW,+BAAQ,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,IAAIC,kCAAQ,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,IAAIA,kCAAQ,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,eACHX,qDAAiB,iBACjB,KAAK,UAAU,KAAK,cAAcZ,kBAAM,GAAG,KAAK,CAAC,CAAC,KAAK,GAAG,CAC3D;AACD,OAAK,eAAeY,qDAAiB,mBAAmB,KAAK,YAAY;AAEzE,OAAK,gBACH,IAAIY,oBAAQ,gBAAgB;GAC1B,SAAS,CAAC,QAAQ;GAClB,QAAQC,2BAAO;GACf,WAAW,CAAC,IAAI;GACjB,CAAC,CACH;;CAGH,AAAQ,kBAAkB,MAAuB;EAC/C,MAAM,EAAE,OAAO,mBAAmB,KAAK,uBACrC,KAAK,SACL,KAAK,gBAAgBC,oCAAa,OACnC;AACD,MAAI,CAAC,MACH;AAEF,OAAK,UAAU,MAAM;EAErB,MAAM,eAAe,KAAK,iBAAiB,KAAK;AAEhD,OAAK,eAAed,qDAAiB,oBAAoB,aAAa;AACtE,OAAK,eAAe,2BAA2B,eAAe;AAE9D,MAAI,KAAK,OAAO,UACd,MAAK,eAAeA,qDAAiB,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,SAASZ,kBAAM,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,gBAAgBO,oBAAI,SAAU,KAAmB,aAAa,SACjE;;CAKH,AAAQ,eAAe,cAAoD;AAQzE,SAPoB,KAAK,aACtB,UACE,gBAAgBG,uBAAO,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,cAAcV,kBAAM,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,MAAM2B,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"}
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\n Object.assign(table, {\n tableStreamArn: (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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"}
@@ -281,7 +281,7 @@ 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
- table.tableStreamArn = table.node.defaultChild.attrStreamArn;
284
+ Object.assign(table, { tableStreamArn: table.node.defaultChild.attrStreamArn });
285
285
  this.lambdaSubscriptionMain.function.addEventSource(new dynamoDbStream.DynamoEventSource(table, {
286
286
  startingPosition: lambda.StartingPosition.LATEST,
287
287
  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 (table as any).tableStreamArn = (\n table.node.defaultChild as dynamoDb.CfnTable\n ).attrStreamArn;\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\n Object.assign(table, {\n tableStreamArn: (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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"}
package/package.json CHANGED
@@ -138,7 +138,7 @@
138
138
  "require": "./lib/index.js"
139
139
  },
140
140
  "license": "MPL-2.0",
141
- "version": "2.3.17",
141
+ "version": "2.3.18",
142
142
  "types": "lib/index.d.ts",
143
143
  "stability": "stable",
144
144
  "jsii": {