@digitraffic/common 2022.10.6-1 → 2022.10.10-1

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.
Files changed (95) hide show
  1. package/README.md +54 -0
  2. package/aws/index.d.ts +1 -0
  3. package/aws/index.js +18 -0
  4. package/aws/infra/api/index.d.ts +1 -0
  5. package/aws/infra/api/index.js +18 -0
  6. package/aws/infra/api/responses.js +1 -1
  7. package/aws/infra/stack/lambda-configs.js +1 -1
  8. package/aws/infra/stack/rest_apis.d.ts +1 -0
  9. package/aws/infra/stack/rest_apis.js +8 -2
  10. package/aws/infra/stack/stack-checking-aspect.d.ts +4 -3
  11. package/aws/infra/stack/stack-checking-aspect.js +8 -7
  12. package/aws/infra/stack/stack.d.ts +4 -1
  13. package/aws/infra/stack/stack.js +1 -1
  14. package/aws/infra/usage-plans.js +1 -1
  15. package/aws/types/errors.js +1 -1
  16. package/aws/types/tags.js +1 -1
  17. package/database/last-updated.js +10 -10
  18. package/package.json +3 -2
  19. package/test/httpserver.js +1 -1
  20. package/types/index.d.ts +1 -0
  21. package/types/index.js +18 -0
  22. package/types/language.js +1 -1
  23. package/utils/geometry.js +1 -1
  24. package/src/aws/infra/api/integration.js +0 -52
  25. package/src/aws/infra/api/response.js +0 -61
  26. package/src/aws/infra/api/responses.js +0 -79
  27. package/src/aws/infra/api/static-integration.js +0 -54
  28. package/src/aws/infra/canaries/canary-alarm.js +0 -26
  29. package/src/aws/infra/canaries/canary-parameters.js +0 -3
  30. package/src/aws/infra/canaries/canary-role.js +0 -46
  31. package/src/aws/infra/canaries/canary.js +0 -29
  32. package/src/aws/infra/canaries/database-canary.js +0 -55
  33. package/src/aws/infra/canaries/database-checker.js +0 -109
  34. package/src/aws/infra/canaries/url-canary.js +0 -46
  35. package/src/aws/infra/canaries/url-checker.js +0 -238
  36. package/src/aws/infra/documentation.js +0 -95
  37. package/src/aws/infra/scheduler.js +0 -31
  38. package/src/aws/infra/security-rule.js +0 -39
  39. package/src/aws/infra/sqs-integration.js +0 -93
  40. package/src/aws/infra/sqs-queue.js +0 -130
  41. package/src/aws/infra/stack/lambda-configs.js +0 -93
  42. package/src/aws/infra/stack/monitoredfunction.js +0 -135
  43. package/src/aws/infra/stack/rest_apis.js +0 -179
  44. package/src/aws/infra/stack/stack-checking-aspect.js +0 -163
  45. package/src/aws/infra/stack/stack.js +0 -58
  46. package/src/aws/infra/stack/subscription.js +0 -41
  47. package/src/aws/infra/usage-plans.js +0 -42
  48. package/src/aws/runtime/apikey.js +0 -13
  49. package/src/aws/runtime/digitraffic-integration-response.js +0 -26
  50. package/src/aws/runtime/messaging.js +0 -31
  51. package/src/aws/runtime/s3.js +0 -30
  52. package/src/aws/runtime/secrets/dbsecret.js +0 -96
  53. package/src/aws/runtime/secrets/proxy-holder.js +0 -26
  54. package/src/aws/runtime/secrets/rds-holder.js +0 -26
  55. package/src/aws/runtime/secrets/secret-holder.js +0 -73
  56. package/src/aws/runtime/secrets/secret.js +0 -43
  57. package/src/aws/types/errors.js +0 -9
  58. package/src/aws/types/lambda-response.js +0 -28
  59. package/src/aws/types/mediatypes.js +0 -15
  60. package/src/aws/types/model-with-reference.js +0 -3
  61. package/src/aws/types/proxytypes.js +0 -3
  62. package/src/aws/types/tags.js +0 -7
  63. package/src/database/cached.js +0 -32
  64. package/src/database/database.js +0 -62
  65. package/src/database/last-updated.js +0 -54
  66. package/src/marine/id_utils.js +0 -33
  67. package/src/marine/rtz.js +0 -3
  68. package/src/test/asserter.js +0 -45
  69. package/src/test/db-testutils.js +0 -31
  70. package/src/test/httpserver.js +0 -67
  71. package/src/test/secret.js +0 -25
  72. package/src/test/secrets-manager.js +0 -59
  73. package/src/test/testutils.js +0 -44
  74. package/src/types/input-error.js +0 -7
  75. package/src/types/language.js +0 -10
  76. package/src/types/traffictype.js +0 -13
  77. package/src/types/validator.js +0 -14
  78. package/src/utils/api-model.js +0 -129
  79. package/src/utils/base64.js +0 -21
  80. package/src/utils/date-utils.js +0 -34
  81. package/src/utils/geojson-types.js +0 -18
  82. package/src/utils/geometry.js +0 -140
  83. package/src/utils/retry.js +0 -50
  84. package/src/utils/slack.js +0 -25
  85. package/src/utils/utils.js +0 -40
  86. package/test/marine/id_utils.test.js +0 -69
  87. package/test/promise/promise.test.js +0 -125
  88. package/test/secrets/dbsecret.test.js +0 -71
  89. package/test/secrets/secret-holder.test.js +0 -124
  90. package/test/secrets/secret.test.js +0 -66
  91. package/test/test/httpserver.test.js +0 -87
  92. package/test/utils/date-utils.test.js +0 -51
  93. package/test/utils/geometry.test.js +0 -49
  94. package/test/utils/utils.test.js +0 -49
  95. package/yarn.lock +0 -3200
@@ -1,135 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MonitoredDBFunction = exports.MonitoredFunction = void 0;
4
- const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
5
- const aws_cloudwatch_actions_1 = require("aws-cdk-lib/aws-cloudwatch-actions");
6
- const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
7
- const lambda_configs_1 = require("../stack/lambda-configs");
8
- const change_case_1 = require("change-case");
9
- const subscription_1 = require("../stack/subscription");
10
- /**
11
- * Creates a Lambda function that monitors default CloudWatch Lambda metrics with CloudWatch Alarms.
12
- */
13
- class MonitoredFunction extends aws_lambda_1.Function {
14
- /**
15
- * @param scope Stack
16
- * @param id Lambda construct Id
17
- * @param functionProps Lambda function properties
18
- * @param alarmSnsTopic SNS topic for alarms
19
- * @param warningSnsTopic SNS topic for warnings
20
- * @param production Is the stack a production stack, used for determining the alarm topic
21
- * @param trafficType Traffic type, used for alarm names. Set to null if Lambda is not related to any traffic type.
22
- * @param props Monitored function properties
23
- */
24
- constructor(scope, id, functionProps, alarmSnsTopic, warningSnsTopic, production, trafficType, props) {
25
- super(scope, id, functionProps);
26
- this.givenName = functionProps.functionName;
27
- const alarmSnsAction = new aws_cloudwatch_actions_1.SnsAction(alarmSnsTopic);
28
- const warningSnsAction = new aws_cloudwatch_actions_1.SnsAction(warningSnsTopic);
29
- if (props?.durationAlarmProps?.create !== false) {
30
- if (!functionProps.timeout) {
31
- throw new Error('Timeout needs to be explicitly set');
32
- }
33
- this.createAlarm(scope, this.metricDuration().with({ statistic: 'max' }), 'Duration', 'Duration alarm', `Duration has exceeded ${functionProps.timeout.toSeconds()} seconds`, trafficType, this.getAlarmActionForEnv(alarmSnsAction, warningSnsAction, production), functionProps.timeout.toMilliseconds(), 1, 1, aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, props?.durationAlarmProps);
34
- }
35
- if (props?.durationWarningProps?.create !== false) {
36
- if (!functionProps.timeout) {
37
- throw new Error('Timeout needs to be explicitly set');
38
- }
39
- this.createAlarm(scope, this.metricDuration().with({ statistic: 'max' }), 'Duration-Warning', 'Duration warning', `Duration is 85 % of max ${functionProps.timeout.toSeconds()} seconds`, trafficType, warningSnsAction, functionProps.timeout.toMilliseconds() * 0.85, 1, 1, aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, props?.durationWarningProps);
40
- }
41
- if (props?.errorAlarmProps?.create !== false) {
42
- this.createAlarm(scope, this.metricErrors(), 'Errors', 'Errors alarm', 'Invocations did not succeed', trafficType, this.getAlarmActionForEnv(alarmSnsAction, warningSnsAction, production), 1, 1, 1, aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD, props?.errorAlarmProps);
43
- }
44
- if (props?.throttleAlarmProps?.create !== false) {
45
- this.createAlarm(scope, this.metricThrottles(), 'Throttles', 'Throttles alarm', 'Has throttled', trafficType, this.getAlarmActionForEnv(alarmSnsAction, warningSnsAction, production), 0, 1, 1, aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD, props?.throttleAlarmProps);
46
- }
47
- }
48
- /**
49
- * Create new MonitoredFunction. Use topics from given DigitrafficStack.
50
- *
51
- * @param stack DigitrafficStack
52
- * @param id Lambda construct Id
53
- * @param functionProps Lambda function properties
54
- * @param props Monitored function properties
55
- */
56
- static create(stack, id, functionProps, props) {
57
- if (props === MonitoredFunction.DISABLE_ALARMS && stack.configuration.production) {
58
- throw new Error(`Function ${functionProps.functionName} has DISABLE_ALARMS. Remove before installing to production or define your own properties!`);
59
- }
60
- return new MonitoredFunction(stack, id, functionProps, stack.alarmTopic, stack.warningTopic, stack.configuration.production, stack.configuration.trafficType, props);
61
- }
62
- /**
63
- * Create new MonitoredFunction. Use topics from given DigitrafficStack. Generate names from given name and configuration shortName.
64
- *
65
- * For example, shortName FOO and given name update-things will create function FOO-UpdateThings and use code from lambda/update-things/update-things.ts method handler.
66
- *
67
- * @param stack DigitrafficStack
68
- * @param name param-case name
69
- * @param environment Lambda environment
70
- * @param functionParameters Lambda function parameters
71
- */
72
- static createV2(stack, name, environment, functionParameters) {
73
- const functionName = functionParameters?.functionName || `${stack.configuration.shortName}-${(0, change_case_1.pascalCase)(name)}`;
74
- const functionProps = (0, lambda_configs_1.databaseFunctionProps)(stack, environment, functionName, name, functionParameters);
75
- return MonitoredFunction.create(stack, functionName, functionProps, functionParameters);
76
- }
77
- createAlarm(stack, metric, alarmId, alarmName, alarmDescription, trafficType, alarmSnsAction, threshold, evaluationPeriods, datapointsToAlarm, comparisonOperator, alarmProps) {
78
- metric.createAlarm(stack, `${this.node.id}-${alarmId}`, {
79
- alarmName: `${trafficType ?? ''} ${stack.stackName} ${this.functionName} ${alarmName}`.trim(),
80
- alarmDescription,
81
- threshold: alarmProps?.threshold ?? threshold,
82
- evaluationPeriods: alarmProps?.evaluationPeriods ?? evaluationPeriods,
83
- datapointsToAlarm: alarmProps?.datapointsToAlarm ?? datapointsToAlarm,
84
- comparisonOperator: alarmProps?.comparisonOperator ?? comparisonOperator,
85
- }).addAlarmAction(alarmSnsAction);
86
- }
87
- getAlarmActionForEnv(alarmAction, warningAction, production) {
88
- return production ? alarmAction : warningAction;
89
- }
90
- }
91
- exports.MonitoredFunction = MonitoredFunction;
92
- /** disable all alarms */
93
- MonitoredFunction.DISABLE_ALARMS = {
94
- durationAlarmProps: {
95
- create: false,
96
- },
97
- durationWarningProps: {
98
- create: false,
99
- },
100
- errorAlarmProps: {
101
- create: false,
102
- },
103
- throttleAlarmProps: {
104
- create: false,
105
- },
106
- };
107
- class MonitoredDBFunction {
108
- /**
109
- * Create new MonitoredDBFunction. Use topics from given DigitrafficStack. Generate names from given name and configuration shortName.
110
- * Grant secret and create log subscription.
111
- *
112
- * For example, shortName FOO and given name update-things will create function FOO-UpdateThings and use code from lambda/update-things/update-things.ts method handler.
113
- *
114
- * If you don't need to pass any extra arguments to lambda-environment, you can leave environment out and this function will create the
115
- * default Lambda Environment with SECRET_ID and DB_APPLICATION.
116
- *
117
- * @param stack DigitrafficStack
118
- * @param name param-case name
119
- * @param environment Lambda environment
120
- * @param functionParameters Lambda function parameters
121
- */
122
- static create(stack, name, environment, functionParameters) {
123
- const functionName = functionParameters?.functionName || `${stack.configuration.shortName}-${(0, change_case_1.pascalCase)(name)}`;
124
- const env = environment ? environment : stack.createLambdaEnvironment();
125
- const functionProps = (0, lambda_configs_1.databaseFunctionProps)(stack, env, functionName, name, functionParameters);
126
- const mf = MonitoredFunction.create(stack, functionName, functionProps, functionParameters);
127
- stack.grantSecret(mf);
128
- if (stack.configuration.logsDestinationArn) {
129
- new subscription_1.DigitrafficLogSubscriptions(stack, mf);
130
- }
131
- return mf;
132
- }
133
- }
134
- exports.MonitoredDBFunction = MonitoredDBFunction;
135
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9uaXRvcmVkZnVuY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvYXdzL2luZnJhL3N0YWNrL21vbml0b3JlZGZ1bmN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHVEQUErRDtBQUUvRCwrRUFBNkQ7QUFDN0QsK0RBQXNFO0FBR3RFLDREQUE4RztBQUM5Ryw2Q0FBdUM7QUFDdkMsd0RBQWtFO0FBK0JsRTs7R0FFRztBQUNILE1BQWEsaUJBQWtCLFNBQVEscUJBQVE7SUFzRTNDOzs7Ozs7Ozs7T0FTRztJQUNILFlBQ0ksS0FBWSxFQUNaLEVBQVUsRUFDVixhQUE0QixFQUM1QixhQUFxQixFQUNyQixlQUF1QixFQUN2QixVQUFtQixFQUNuQixXQUErQixFQUMvQixLQUE4QjtRQUU5QixLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxhQUFhLENBQUMsQ0FBQztRQUVoQyxJQUFJLENBQUMsU0FBUyxHQUFHLGFBQWEsQ0FBQyxZQUFzQixDQUFDO1FBRXRELE1BQU0sY0FBYyxHQUFHLElBQUksa0NBQVMsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNwRCxNQUFNLGdCQUFnQixHQUFHLElBQUksa0NBQVMsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUV4RCxJQUFJLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxNQUFNLEtBQUssS0FBSyxFQUFFO1lBQzdDLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFO2dCQUN4QixNQUFNLElBQUksS0FBSyxDQUFDLG9DQUFvQyxDQUFDLENBQUM7YUFDekQ7WUFFRCxJQUFJLENBQUMsV0FBVyxDQUNaLEtBQUssRUFDTCxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUMsU0FBUyxFQUFFLEtBQUssRUFBQyxDQUFDLEVBQzlDLFVBQVUsRUFDVixnQkFBZ0IsRUFDaEIseUJBQXlCLGFBQWEsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLFVB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QUEyQixDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztTQUM5QztRQUVELE9BQU8sRUFBRSxDQUFDO0lBQ2QsQ0FBQztDQUNKO0FBbkNELGtEQW1DQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7RnVuY3Rpb24sIEZ1bmN0aW9uUHJvcHN9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0IHtTdGFja30gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQge1Nuc0FjdGlvbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1jbG91ZHdhdGNoLWFjdGlvbnNcIjtcbmltcG9ydCB7Q29tcGFyaXNvbk9wZXJhdG9yLCBNZXRyaWN9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2xvdWR3YXRjaFwiO1xuaW1wb3J0IHtEaWdpdHJhZmZpY1N0YWNrfSBmcm9tIFwiLi4vc3RhY2svc3RhY2tcIjtcbmltcG9ydCB7SVRvcGljfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXNuc1wiO1xuaW1wb3J0IHtkYXRhYmFzZUZ1bmN0aW9uUHJvcHMsIExhbWJkYUVudmlyb25tZW50LCBNb25pdG9yZWRGdW5jdGlvblBhcmFtZXRlcnN9IGZyb20gXCIuLi9zdGFjay9sYW1iZGEtY29uZmlnc1wiO1xuaW1wb3J0IHtwYXNjYWxDYXNlfSBmcm9tIFwiY2hhbmdlLWNhc2VcIjtcbmltcG9ydCB7RGlnaXRyYWZmaWNMb2dTdWJzY3JpcHRpb25zfSBmcm9tIFwiLi4vc3RhY2svc3Vic2NyaXB0aW9uXCI7XG5pbXBvcnQge1RyYWZmaWNUeXBlfSBmcm9tIFwiLi4vLi4vLi4vdHlwZXMvdHJhZmZpY3R5cGVcIjtcblxuLyoqXG4gKiBBbGxvd3MgY3VzdG9taXphdGlvbiBvZiBDbG91ZFdhdGNoIEFsYXJtIHByb3BlcnRpZXNcbiAqL1xuZXhwb3J0IHR5cGUgTW9uaXRvcmVkRnVuY3Rpb25BbGFybVByb3BzID0ge1xuICAgIC8qKlxuICAgICAqIFNldHRpbmcgdGhpcyB0byBmYWxzZSB3aWxsIG5vdCBjcmVhdGUgYSBDbG91ZFdhdGNoIGFsYXJtXG4gICAgICovXG4gICAgcmVhZG9ubHkgY3JlYXRlOiBib29sZWFuXG5cbiAgICByZWFkb25seSB0aHJlc2hvbGQ/OiBudW1iZXJcblxuICAgIHJlYWRvbmx5IGV2YWx1YXRpb25QZXJpb2RzPzogbnVtYmVyXG5cbiAgICByZWFkb25seSBkYXRhcG9pbnRzVG9BbGFybT86IG51bWJlclxuXG4gICAgcmVhZG9ubHkgY29tcGFyaXNvbk9wZXJhdG9yPzogQ29tcGFyaXNvbk9wZXJhdG9yXG59XG5cbmV4cG9ydCB0eXBlIE1vbml0b3JlZEZ1bmN0aW9uUHJvcHMgPSB7XG4gICAgcmVhZG9ubHkgZHVyYXRpb25BbGFybVByb3BzPzogTW9uaXRvcmVkRnVuY3Rpb25BbGFybVByb3BzXG5cbiAgICByZWFkb25seSBkdXJhdGlvbldhcm5pbmdQcm9wcz86IE1vbml0b3JlZEZ1bmN0aW9uQWxhcm1Qcm9wc1xuXG4gICAgcmVhZG9ubHkgZXJyb3JBbGFybVByb3BzPzogTW9uaXRvcmVkRnVuY3Rpb25BbGFybVByb3BzXG5cbiAgICByZWFkb25seSB0aHJvdHRsZUFsYXJtUHJvcHM/OiBNb25pdG9yZWRGdW5jdGlvbkFsYXJtUHJvcHNcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgTGFtYmRhIGZ1bmN0aW9uIHRoYXQgbW9uaXRvcnMgZGVmYXVsdCBDbG91ZFdhdGNoIExhbWJkYSBtZXRyaWNzIHdpdGggQ2xvdWRXYXRjaCBBbGFybXMuXG4gKi9cbmV4cG9ydCBjbGFzcyBNb25pdG9yZWRGdW5jdGlvbiBleHRlbmRzIEZ1bmN0aW9uIHtcbiAgICByZWFkb25seSBnaXZlbk5hbWU6IHN0cmluZztcblxuICAgIC8qKiBkaXNhYmxlIGFsbCBhbGFybXMgKi9cbiAgICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERJU0FCTEVfQUxBUk1TOiBNb25pdG9yZWRGdW5jdGlvblByb3BzID0ge1xuICAgICAgICBkdXJhdGlvbkFsYXJtUHJvcHM6IHtcbiAgICAgICAgICAgIGNyZWF0ZTogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICAgIGR1cmF0aW9uV2FybmluZ1Byb3BzOiB7XG4gICAgICAgICAgICBjcmVhdGU6IGZhbHNlLFxuICAgICAgICB9LFxuICAgICAgICBlcnJvckFsYXJtUHJvcHM6IHtcbiAgICAgICAgICAgIGNyZWF0ZTogZmFsc2UsXG4gICAgICAgIH0sXG4gICAgICAgIHRocm90dGxlQWxhcm1Qcm9wczoge1xuICAgICAgICAgICAgY3JlYXRlOiBmYWxzZSxcbiAgICAgICAgfSxcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIG5ldyBNb25pdG9yZWRGdW5jdGlvbi4gIFVzZSB0b3BpY3MgZnJvbSBnaXZlbiBEaWdpdHJhZmZpY1N0YWNrLlxuICAgICAqXG4gICAgICogQHBhcmFtIHN0YWNrIERpZ2l0cmFmZmljU3RhY2tcbiAgICAgKiBAcGFyYW0gaWQgTGFtYmRhIGNvbnN0cnVjdCBJZFxuICAgICAqIEBwYXJhbSBmdW5jdGlvblByb3BzIExhbWJkYSBmdW5jdGlvbiBwcm9wZXJ0aWVzXG4gICAgICogQHBhcmFtIHByb3BzIE1vbml0b3JlZCBmdW5jdGlvbiBwcm9wZXJ0aWVzXG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZShzdGFjazogRGlnaXRyYWZmaWNTdGFjayxcbiAgICAgICAgaWQ6IHN0cmluZyxcbiAgICAgICAgZnVuY3Rpb25Qcm9wczogRnVuY3Rpb25Qcm9wcyxcbiAgICAgICAgcHJvcHM/OiBNb25pdG9yZWRGdW5jdGlvblByb3BzKTogTW9uaXRvcmVkRnVuY3Rpb24ge1xuXG4gICAgICAgIGlmIChwcm9wcyA9PT0gTW9uaXRvcmVkRnVuY3Rpb24uRElTQUJMRV9BTEFSTVMgJiYgc3RhY2suY29uZmlndXJhdGlvbi5wcm9kdWN0aW9uKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZ1bmN0aW9uICR7ZnVuY3Rpb25Qcm9wcy5mdW5jdGlvbk5hbWV9IGhhcyBESVNBQkxFX0FMQVJNUy4gIFJlbW92ZSBiZWZvcmUgaW5zdGFsbGluZyB0byBwcm9kdWN0aW9uIG9yIGRlZmluZSB5b3VyIG93biBwcm9wZXJ0aWVzIWApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5ldyBNb25pdG9yZWRGdW5jdGlvbihcbiAgICAgICAgICAgIHN0YWNrLFxuICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICBmdW5jdGlvblByb3BzLFxuICAgICAgICAgICAgc3RhY2suYWxhcm1Ub3BpYyxcbiAgICAgICAgICAgIHN0YWNrLndhcm5pbmdUb3BpYyxcbiAgICAgICAgICAgIHN0YWNrLmNvbmZpZ3VyYXRpb24ucHJvZHVjdGlvbixcbiAgICAgICAgICAgIHN0YWNrLmNvbmZpZ3VyYXRpb24udHJhZmZpY1R5cGUsXG4gICAgICAgICAgICBwcm9wcyxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgbmV3IE1vbml0b3JlZEZ1bmN0aW9uLiAgVXNlIHRvcGljcyBmcm9tIGdpdmVuIERpZ2l0cmFmZmljU3RhY2suICBHZW5lcmF0ZSBuYW1lcyBmcm9tIGdpdmVuIG5hbWUgYW5kIGNvbmZpZ3VyYXRpb24gc2hvcnROYW1lLlxuICAgICAqXG4gICAgICogRm9yIGV4YW1wbGUsIHNob3J0TmFtZSBGT08gYW5kIGdpdmVuIG5hbWUgdXBkYXRlLXRoaW5ncyB3aWxsIGNyZWF0ZSBmdW5jdGlvbiBGT08tVXBkYXRlVGhpbmdzIGFuZCB1c2UgY29kZSBmcm9tIGxhbWJkYS91cGRhdGUtdGhpbmdzL3VwZGF0ZS10aGluZ3MudHMgbWV0aG9kIGhhbmRsZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gc3RhY2sgRGlnaXRyYWZmaWNTdGFja1xuICAgICAqIEBwYXJhbSBuYW1lIHBhcmFtLWNhc2UgbmFtZVxuICAgICAqIEBwYXJhbSBlbnZpcm9ubWVudCBMYW1iZGEgZW52aXJvbm1lbnRcbiAgICAgKiBAcGFyYW0gZnVuY3Rpb25QYXJhbWV0ZXJzIExhbWJkYSBmdW5jdGlvbiBwYXJhbWV0ZXJzXG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZVYyKHN0YWNrOiBEaWdpdHJhZmZpY1N0YWNrLFxuICAgICAgICBuYW1lOiBzdHJpbmcsXG4gICAgICAgIGVudmlyb25tZW50OiBMYW1iZGFFbnZpcm9ubWVudCxcbiAgICAgICAgZnVuY3Rpb25QYXJhbWV0ZXJzPzogTW9uaXRvcmVkRnVuY3Rpb25QYXJhbWV0ZXJzKTogTW9uaXRvcmVkRnVuY3Rpb24ge1xuICAgICAgICBjb25zdCBmdW5jdGlvbk5hbWUgPSBmdW5jdGlvblBhcmFtZXRlcnM/LmZ1bmN0aW9uTmFtZSB8fCBgJHtzdGFjay5jb25maWd1cmF0aW9uLnNob3J0TmFtZX0tJHtwYXNjYWxDYXNlKG5hbWUpfWA7XG4gICAgICAgIGNvbnN0IGZ1bmN0aW9uUHJvcHMgPSBkYXRhYmFzZUZ1bmN0aW9uUHJvcHMoXG4gICAgICAgICAgICBzdGFjaywgZW52aXJvbm1lbnQsIGZ1bmN0aW9uTmFtZSwgbmFtZSwgZnVuY3Rpb25QYXJhbWV0ZXJzLFxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiBNb25pdG9yZWRGdW5jdGlvbi5jcmVhdGUoc3RhY2ssIGZ1bmN0aW9uTmFtZSwgZnVuY3Rpb25Qcm9wcywgZnVuY3Rpb25QYXJhbWV0ZXJzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gc2NvcGUgU3RhY2tcbiAgICAgKiBAcGFyYW0gaWQgTGFtYmRhIGNvbnN0cnVjdCBJZFxuICAgICAqIEBwYXJhbSBmdW5jdGlvblByb3BzIExhbWJkYSBmdW5jdGlvbiBwcm9wZXJ0aWVzXG4gICAgICogQHBhcmFtIGFsYXJtU25zVG9waWMgU05TIHRvcGljIGZvciBhbGFybXNcbiAgICAgKiBAcGFyYW0gd2FybmluZ1Nuc1RvcGljIFNOUyB0b3BpYyBmb3Igd2FybmluZ3NcbiAgICAgKiBAcGFyYW0gcHJvZHVjdGlvbiBJcyB0aGUgc3RhY2sgYSBwcm9kdWN0aW9uIHN0YWNrLCB1c2VkIGZvciBkZXRlcm1pbmluZyB0aGUgYWxhcm0gdG9waWNcbiAgICAgKiBAcGFyYW0gdHJhZmZpY1R5cGUgVHJhZmZpYyB0eXBlLCB1c2VkIGZvciBhbGFybSBuYW1lcy4gU2V0IHRvIG51bGwgaWYgTGFtYmRhIGlzIG5vdCByZWxhdGVkIHRvIGFueSB0cmFmZmljIHR5cGUuXG4gICAgICogQHBhcmFtIHByb3BzIE1vbml0b3JlZCBmdW5jdGlvbiBwcm9wZXJ0aWVzXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHNjb3BlOiBTdGFjayxcbiAgICAgICAgaWQ6IHN0cmluZyxcbiAgICAgICAgZnVuY3Rpb25Qcm9wczogRnVuY3Rpb25Qcm9wcyxcbiAgICAgICAgYWxhcm1TbnNUb3BpYzogSVRvcGljLFxuICAgICAgICB3YXJuaW5nU25zVG9waWM6IElUb3BpYyxcbiAgICAgICAgcHJvZHVjdGlvbjogYm9vbGVhbixcbiAgICAgICAgdHJhZmZpY1R5cGU6IFRyYWZmaWNUeXBlIHwgbnVsbCxcbiAgICAgICAgcHJvcHM/OiBNb25pdG9yZWRGdW5jdGlvblByb3BzLFxuICAgICkge1xuICAgICAgICBzdXBlcihzY29wZSwgaWQsIGZ1bmN0aW9uUHJvcHMpO1xuXG4gICAgICAgIHRoaXMuZ2l2ZW5OYW1lID0gZnVuY3Rpb25Qcm9wcy5mdW5jdGlvbk5hbWUgYXMgc3RyaW5nO1xuXG4gICAgICAgIGNvbnN0IGFsYXJtU25zQWN0aW9uID0gbmV3IFNuc0FjdGlvbihhbGFybVNuc1RvcGljKTtcbiAgICAgICAgY29uc3Qgd2FybmluZ1Nuc0FjdGlvbiA9IG5ldyBTbnNBY3Rpb24od2FybmluZ1Nuc1RvcGljKTtcblxuICAgICAgICBpZiAocHJvcHM/LmR1cmF0aW9uQWxhcm1Qcm9wcz8uY3JlYXRlICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgaWYgKCFmdW5jdGlvblByb3BzLnRpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RpbWVvdXQgbmVlZHMgdG8gYmUgZXhwbGljaXRseSBzZXQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jcmVhdGVBbGFybShcbiAgICAgICAgICAgICAgICBzY29wZSxcbiAgICAgICAgICAgICAgICB0aGlzLm1ldHJpY0R1cmF0aW9uKCkud2l0aCh7c3RhdGlzdGljOiAnbWF4J30pLFxuICAgICAgICAgICAgICAgICdEdXJhdGlvbicsXG4gICAgICAgICAgICAgICAgJ0R1cmF0aW9uIGFsYXJtJyxcbiAgICAgICAgICAgICAgICBgRHVyYXRpb24gaGFzIGV4Y2VlZGVkICR7ZnVuY3Rpb25Qcm9wcy50aW1lb3V0LnRvU2Vjb25kcygpfSBzZWNvbmRzYCxcbiAgICAgICAgICAgICAgICB0cmFmZmljVHlwZSxcbiAgICAgICAgICAgICAgICB0aGlzLmdldEFsYXJtQWN0aW9uRm9yRW52KGFsYXJtU25zQWN0aW9uLCB3YXJuaW5nU25zQWN0aW9uLCBwcm9kdWN0aW9uKSxcbiAgICAgICAgICAgICAgICBmdW5jdGlvblByb3BzLnRpbWVvdXQudG9NaWxsaXNlY29uZHMoKSxcbiAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9PUl9FUVVBTF9UT19USFJFU0hPTEQsXG4gICAgICAgICAgICAgICAgcHJvcHM/LmR1cmF0aW9uQWxhcm1Qcm9wcyxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHByb3BzPy5kdXJhdGlvbldhcm5pbmdQcm9wcz8uY3JlYXRlICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgaWYgKCFmdW5jdGlvblByb3BzLnRpbWVvdXQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RpbWVvdXQgbmVlZHMgdG8gYmUgZXhwbGljaXRseSBzZXQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jcmVhdGVBbGFybShcbiAgICAgICAgICAgICAgICBzY29wZSxcbiAgICAgICAgICAgICAgICB0aGlzLm1ldHJpY0R1cmF0aW9uKCkud2l0aCh7c3RhdGlzdGljOiAnbWF4J30pLFxuICAgICAgICAgICAgICAgICdEdXJhdGlvbi1XYXJuaW5nJyxcbiAgICAgICAgICAgICAgICAnRHVyYXRpb24gd2FybmluZycsXG4gICAgICAgICAgICAgICAgYER1cmF0aW9uIGlzIDg1ICUgb2YgbWF4ICR7ZnVuY3Rpb25Qcm9wcy50aW1lb3V0LnRvU2Vjb25kcygpfSBzZWNvbmRzYCxcbiAgICAgICAgICAgICAgICB0cmFmZmljVHlwZSxcbiAgICAgICAgICAgICAgICB3YXJuaW5nU25zQWN0aW9uLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uUHJvcHMudGltZW91dC50b01pbGxpc2Vjb25kcygpICogMC44NSxcbiAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9PUl9FUVVBTF9UT19USFJFU0hPTEQsXG4gICAgICAgICAgICAgICAgcHJvcHM/LmR1cmF0aW9uV2FybmluZ1Byb3BzLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwcm9wcz8uZXJyb3JBbGFybVByb3BzPy5jcmVhdGUgIT09IGZhbHNlKSB7XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZUFsYXJtKFxuICAgICAgICAgICAgICAgIHNjb3BlLFxuICAgICAgICAgICAgICAgIHRoaXMubWV0cmljRXJyb3JzKCksXG4gICAgICAgICAgICAgICAgJ0Vycm9ycycsXG4gICAgICAgICAgICAgICAgJ0Vycm9ycyBhbGFybScsXG4gICAgICAgICAgICAgICAgJ0ludm9jYXRpb25zIGRpZCBub3Qgc3VjY2VlZCcsXG4gICAgICAgICAgICAgICAgdHJhZmZpY1R5cGUsXG4gICAgICAgICAgICAgICAgdGhpcy5nZXRBbGFybUFjdGlvbkZvckVudihhbGFybVNuc0FjdGlvbiwgd2FybmluZ1Nuc0FjdGlvbiwgcHJvZHVjdGlvbiksXG4gICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9PUl9FUVVBTF9UT19USFJFU0hPTEQsXG4gICAgICAgICAgICAgICAgcHJvcHM/LmVycm9yQWxhcm1Qcm9wcyxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocHJvcHM/LnRocm90dGxlQWxhcm1Qcm9wcz8uY3JlYXRlICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgdGhpcy5jcmVhdGVBbGFybShcbiAgICAgICAgICAgICAgICBzY29wZSxcbiAgICAgICAgICAgICAgICB0aGlzLm1ldHJpY1Rocm90dGxlcygpLFxuICAgICAgICAgICAgICAgICdUaHJvdHRsZXMnLFxuICAgICAgICAgICAgICAgICdUaHJvdHRsZXMgYWxhcm0nLFxuICAgICAgICAgICAgICAgICdIYXMgdGhyb3R0bGVkJyxcbiAgICAgICAgICAgICAgICB0cmFmZmljVHlwZSxcbiAgICAgICAgICAgICAgICB0aGlzLmdldEFsYXJtQWN0aW9uRm9yRW52KGFsYXJtU25zQWN0aW9uLCB3YXJuaW5nU25zQWN0aW9uLCBwcm9kdWN0aW9uKSxcbiAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICAgIDEsXG4gICAgICAgICAgICAgICAgMSxcbiAgICAgICAgICAgICAgICBDb21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX1RIUkVTSE9MRCxcbiAgICAgICAgICAgICAgICBwcm9wcz8udGhyb3R0bGVBbGFybVByb3BzLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgY3JlYXRlQWxhcm0oXG4gICAgICAgIHN0YWNrOiBTdGFjayxcbiAgICAgICAgbWV0cmljOiBNZXRyaWMsXG4gICAgICAgIGFsYXJtSWQ6IHN0cmluZyxcbiAgICAgICAgYWxhcm1OYW1lOiBzdHJpbmcsXG4gICAgICAgIGFsYXJtRGVzY3JpcHRpb246IHN0cmluZyxcbiAgICAgICAgdHJhZmZpY1R5cGU6IFRyYWZmaWNUeXBlIHwgbnVsbCxcbiAgICAgICAgYWxhcm1TbnNBY3Rpb246IFNuc0FjdGlvbixcbiAgICAgICAgdGhyZXNob2xkOiBudW1iZXIsXG4gICAgICAgIGV2YWx1YXRpb25QZXJpb2RzOiBudW1iZXIsXG4gICAgICAgIGRhdGFwb2ludHNUb0FsYXJtOiBudW1iZXIsXG4gICAgICAgIGNvbXBhcmlzb25PcGVyYXRvcjogQ29tcGFyaXNvbk9wZXJhdG9yLFxuICAgICAgICBhbGFybVByb3BzPzogTW9uaXRvcmVkRnVuY3Rpb25BbGFybVByb3BzLFxuICAgICkge1xuICAgICAgICBtZXRyaWMuY3JlYXRlQWxhcm0oc3RhY2ssIGAke3RoaXMubm9kZS5pZH0tJHthbGFybUlkfWAsIHtcbiAgICAgICAgICAgIGFsYXJtTmFtZTogYCR7dHJhZmZpY1R5cGUgPz8gJyd9ICR7c3RhY2suc3RhY2tOYW1lfSAke3RoaXMuZnVuY3Rpb25OYW1lfSAke2FsYXJtTmFtZX1gLnRyaW0oKSxcbiAgICAgICAgICAgIGFsYXJtRGVzY3JpcHRpb24sXG4gICAgICAgICAgICB0aHJlc2hvbGQ6IGFsYXJtUHJvcHM/LnRocmVzaG9sZCA/PyB0aHJlc2hvbGQsXG4gICAgICAgICAgICBldmFsdWF0aW9uUGVyaW9kczogYWxhcm1Qcm9wcz8uZXZhbHVhdGlvblBlcmlvZHMgPz8gZXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICAgICAgICBkYXRhcG9pbnRzVG9BbGFybTogYWxhcm1Qcm9wcz8uZGF0YXBvaW50c1RvQWxhcm0gPz8gZGF0YXBvaW50c1RvQWxhcm0sXG4gICAgICAgICAgICBjb21wYXJpc29uT3BlcmF0b3I6IGFsYXJtUHJvcHM/LmNvbXBhcmlzb25PcGVyYXRvciA/PyBjb21wYXJpc29uT3BlcmF0b3IsXG4gICAgICAgIH0pLmFkZEFsYXJtQWN0aW9uKGFsYXJtU25zQWN0aW9uKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldEFsYXJtQWN0aW9uRm9yRW52KGFsYXJtQWN0aW9uOiBTbnNBY3Rpb24sXG4gICAgICAgIHdhcm5pbmdBY3Rpb246IFNuc0FjdGlvbixcbiAgICAgICAgcHJvZHVjdGlvbjogYm9vbGVhbik6IFNuc0FjdGlvbiB7XG5cbiAgICAgICAgcmV0dXJuIHByb2R1Y3Rpb24gPyBhbGFybUFjdGlvbiA6IHdhcm5pbmdBY3Rpb247XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgTW9uaXRvcmVkREJGdW5jdGlvbiB7XG4gICAgLyoqXG4gICAgICogQ3JlYXRlIG5ldyBNb25pdG9yZWREQkZ1bmN0aW9uLiAgVXNlIHRvcGljcyBmcm9tIGdpdmVuIERpZ2l0cmFmZmljU3RhY2suICBHZW5lcmF0ZSBuYW1lcyBmcm9tIGdpdmVuIG5hbWUgYW5kIGNvbmZpZ3VyYXRpb24gc2hvcnROYW1lLlxuICAgICAqIEdyYW50IHNlY3JldCBhbmQgY3JlYXRlIGxvZyBzdWJzY3JpcHRpb24uXG4gICAgICpcbiAgICAgKiBGb3IgZXhhbXBsZSwgc2hvcnROYW1lIEZPTyBhbmQgZ2l2ZW4gbmFtZSB1cGRhdGUtdGhpbmdzIHdpbGwgY3JlYXRlIGZ1bmN0aW9uIEZPTy1VcGRhdGVUaGluZ3MgYW5kIHVzZSBjb2RlIGZyb20gbGFtYmRhL3VwZGF0ZS10aGluZ3MvdXBkYXRlLXRoaW5ncy50cyBtZXRob2QgaGFuZGxlci5cbiAgICAgKlxuICAgICAqIElmIHlvdSBkb24ndCBuZWVkIHRvIHBhc3MgYW55IGV4dHJhIGFyZ3VtZW50cyB0byBsYW1iZGEtZW52aXJvbm1lbnQsIHlvdSBjYW4gbGVhdmUgZW52aXJvbm1lbnQgb3V0IGFuZCB0aGlzIGZ1bmN0aW9uIHdpbGwgY3JlYXRlIHRoZVxuICAgICAqIGRlZmF1bHQgTGFtYmRhIEVudmlyb25tZW50IHdpdGggU0VDUkVUX0lEIGFuZCBEQl9BUFBMSUNBVElPTi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBzdGFjayBEaWdpdHJhZmZpY1N0YWNrXG4gICAgICogQHBhcmFtIG5hbWUgcGFyYW0tY2FzZSBuYW1lXG4gICAgICogQHBhcmFtIGVudmlyb25tZW50IExhbWJkYSBlbnZpcm9ubWVudFxuICAgICAqIEBwYXJhbSBmdW5jdGlvblBhcmFtZXRlcnMgTGFtYmRhIGZ1bmN0aW9uIHBhcmFtZXRlcnNcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlKHN0YWNrOiBEaWdpdHJhZmZpY1N0YWNrLFxuICAgICAgICBuYW1lOiBzdHJpbmcsXG4gICAgICAgIGVudmlyb25tZW50PzogTGFtYmRhRW52aXJvbm1lbnQsXG4gICAgICAgIGZ1bmN0aW9uUGFyYW1ldGVycz86IE1vbml0b3JlZEZ1bmN0aW9uUGFyYW1ldGVycyk6IE1vbml0b3JlZEZ1bmN0aW9uIHtcbiAgICAgICAgY29uc3QgZnVuY3Rpb25OYW1lID0gZnVuY3Rpb25QYXJhbWV0ZXJzPy5mdW5jdGlvbk5hbWUgfHwgYCR7c3RhY2suY29uZmlndXJhdGlvbi5zaG9ydE5hbWV9LSR7cGFzY2FsQ2FzZShuYW1lKX1gO1xuICAgICAgICBjb25zdCBlbnYgPSBlbnZpcm9ubWVudCA/IGVudmlyb25tZW50IDogc3RhY2suY3JlYXRlTGFtYmRhRW52aXJvbm1lbnQoKTtcbiAgICAgICAgY29uc3QgZnVuY3Rpb25Qcm9wcyA9IGRhdGFiYXNlRnVuY3Rpb25Qcm9wcyhcbiAgICAgICAgICAgIHN0YWNrLCBlbnYsIGZ1bmN0aW9uTmFtZSwgbmFtZSwgZnVuY3Rpb25QYXJhbWV0ZXJzLFxuICAgICAgICApO1xuXG4gICAgICAgIGNvbnN0IG1mID0gTW9uaXRvcmVkRnVuY3Rpb24uY3JlYXRlKHN0YWNrLCBmdW5jdGlvbk5hbWUsIGZ1bmN0aW9uUHJvcHMsIGZ1bmN0aW9uUGFyYW1ldGVycyk7XG5cbiAgICAgICAgc3RhY2suZ3JhbnRTZWNyZXQobWYpO1xuXG4gICAgICAgIGlmIChzdGFjay5jb25maWd1cmF0aW9uLmxvZ3NEZXN0aW5hdGlvbkFybikge1xuICAgICAgICAgICAgbmV3IERpZ2l0cmFmZmljTG9nU3Vic2NyaXB0aW9ucyhzdGFjaywgbWYpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG1mO1xuICAgIH1cbn1cbiJdfQ==
@@ -1,179 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createIpRestrictionPolicyDocument = exports.createDefaultPolicyDocument = exports.createRestApi = exports.setReturnCodeForMissingAuthenticationToken = exports.add401Support = exports.add404Support = exports.DigitrafficRestApi = void 0;
4
- const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
5
- const aws_iam_1 = require("aws-cdk-lib/aws-iam");
6
- const usage_plans_1 = require("../usage-plans");
7
- const api_model_1 = require("../../../utils/api-model");
8
- const mediatypes_1 = require("../../types/mediatypes");
9
- const R = require("ramda");
10
- class DigitrafficRestApi extends aws_apigateway_1.RestApi {
11
- constructor(stack, apiId, apiName, allowFromIpAddresses, config) {
12
- const policyDocument = allowFromIpAddresses == null ? createDefaultPolicyDocument() : createIpRestrictionPolicyDocument(allowFromIpAddresses);
13
- // override default config with given extra config
14
- const apiConfig = { ...{
15
- deployOptions: {
16
- loggingLevel: aws_apigateway_1.MethodLoggingLevel.ERROR,
17
- },
18
- restApiName: apiName,
19
- endpointTypes: [aws_apigateway_1.EndpointType.REGIONAL],
20
- policy: policyDocument,
21
- }, ...config };
22
- super(stack, apiId, apiConfig);
23
- this.apiKeyIds = [];
24
- add404Support(this, stack);
25
- }
26
- hostname() {
27
- return `${this.restApiId}.execute-api.${this.stack.region}.amazonaws.com`;
28
- }
29
- createUsagePlan(apiKeyId, apiKeyName) {
30
- const newKeyId = (0, usage_plans_1.createUsagePlan)(this, apiKeyId, apiKeyName).keyId;
31
- this.apiKeyIds.push(newKeyId);
32
- return newKeyId;
33
- }
34
- createUsagePlanV2(apiName) {
35
- const newKeyId = (0, usage_plans_1.createDefaultUsagePlan)(this, apiName).keyId;
36
- this.apiKeyIds.push(newKeyId);
37
- return newKeyId;
38
- }
39
- addJsonModel(modelName, schema) {
40
- return this.getModelWithReference(this.addModel(modelName, {
41
- contentType: mediatypes_1.MediaType.APPLICATION_JSON,
42
- modelName,
43
- schema,
44
- }));
45
- }
46
- addCSVModel(modelName) {
47
- return this.getModelWithReference(this.addModel(modelName, {
48
- contentType: mediatypes_1.MediaType.TEXT_CSV,
49
- modelName,
50
- schema: {},
51
- }));
52
- }
53
- getModelWithReference(model) {
54
- return R.assoc('modelReference', (0, api_model_1.getModelReference)(model.modelId, this.restApiId), model);
55
- }
56
- addDocumentationPart(resource, parameterName, resourceName, type, properties) {
57
- const location = {
58
- type,
59
- path: resource.path,
60
- name: type !== 'METHOD' ? parameterName : undefined,
61
- };
62
- new aws_apigateway_1.CfnDocumentationPart(this.stack, resourceName, {
63
- restApiId: resource.api.restApiId,
64
- location,
65
- properties: JSON.stringify(properties),
66
- });
67
- }
68
- documentResource(resource, ...documentationPart) {
69
- documentationPart.forEach(dp => this.addDocumentationPart(resource, dp.parameterName, `${resource.path}.${dp.parameterName}.Documentation`, dp.type, dp.documentationProperties));
70
- }
71
- }
72
- exports.DigitrafficRestApi = DigitrafficRestApi;
73
- /**
74
- * Due to AWS API design API Gateway will always return 403 'Missing Authentication Token' for requests
75
- * with a non-existent endpoint. This function translates this response to a 404.
76
- * Requests with an invalid or missing API key are not affected (still return 403 'Forbidden').
77
- * @param restApi RestApi
78
- * @param stack Construct
79
- */
80
- function add404Support(restApi, stack) {
81
- new aws_apigateway_1.GatewayResponse(stack, `MissingAuthenticationTokenResponse-${restApi.restApiName}`, {
82
- restApi,
83
- type: aws_apigateway_1.ResponseType.MISSING_AUTHENTICATION_TOKEN,
84
- statusCode: '404',
85
- templates: {
86
- 'application/json': '{"message": "Not found"}',
87
- },
88
- });
89
- }
90
- exports.add404Support = add404Support;
91
- function add401Support(restApi, stack) {
92
- new aws_apigateway_1.GatewayResponse(stack, `AuthenticationFailedResponse-${restApi.restApiName}`, {
93
- restApi,
94
- type: aws_apigateway_1.ResponseType.UNAUTHORIZED,
95
- statusCode: "401",
96
- responseHeaders: {
97
- 'WWW-Authenticate': "'Basic'",
98
- },
99
- });
100
- }
101
- exports.add401Support = add401Support;
102
- /**
103
- * Due to AWS API design API Gateway will always return 403 'Missing Authentication Token' for requests
104
- * with a non-existent endpoint. This function converts this response to a custom one.
105
- * Requests with an invalid or missing API key are not affected (still return 403 'Forbidden').
106
- * @param returnCode
107
- * @param message
108
- * @param restApi RestApi
109
- * @param stack Construct
110
- */
111
- function setReturnCodeForMissingAuthenticationToken(returnCode, message, restApi, stack) {
112
- new aws_apigateway_1.GatewayResponse(stack, `MissingAuthenticationTokenResponse-${restApi.restApiName}`, {
113
- restApi,
114
- type: aws_apigateway_1.ResponseType.MISSING_AUTHENTICATION_TOKEN,
115
- statusCode: `${returnCode}`,
116
- templates: {
117
- 'application/json': `{"message": ${message}}`,
118
- },
119
- });
120
- }
121
- exports.setReturnCodeForMissingAuthenticationToken = setReturnCodeForMissingAuthenticationToken;
122
- function createRestApi(stack, apiId, apiName, allowFromIpAddresses) {
123
- const policyDocument = allowFromIpAddresses == null ? createDefaultPolicyDocument() : createIpRestrictionPolicyDocument(allowFromIpAddresses);
124
- const restApi = new aws_apigateway_1.RestApi(stack, apiId, {
125
- deployOptions: {
126
- loggingLevel: aws_apigateway_1.MethodLoggingLevel.ERROR,
127
- },
128
- restApiName: apiName,
129
- endpointTypes: [aws_apigateway_1.EndpointType.REGIONAL],
130
- policy: policyDocument,
131
- });
132
- add404Support(restApi, stack);
133
- return restApi;
134
- }
135
- exports.createRestApi = createRestApi;
136
- function createDefaultPolicyDocument() {
137
- return new aws_iam_1.PolicyDocument({
138
- statements: [
139
- new aws_iam_1.PolicyStatement({
140
- effect: aws_iam_1.Effect.ALLOW,
141
- actions: [
142
- "execute-api:Invoke",
143
- ],
144
- resources: [
145
- "*",
146
- ],
147
- principals: [
148
- new aws_iam_1.AnyPrincipal(),
149
- ],
150
- }),
151
- ],
152
- });
153
- }
154
- exports.createDefaultPolicyDocument = createDefaultPolicyDocument;
155
- function createIpRestrictionPolicyDocument(allowFromIpAddresses) {
156
- return new aws_iam_1.PolicyDocument({
157
- statements: [
158
- new aws_iam_1.PolicyStatement({
159
- effect: aws_iam_1.Effect.ALLOW,
160
- conditions: {
161
- "IpAddress": {
162
- "aws:SourceIp": allowFromIpAddresses,
163
- },
164
- },
165
- actions: [
166
- "execute-api:Invoke",
167
- ],
168
- resources: [
169
- "*",
170
- ],
171
- principals: [
172
- new aws_iam_1.AnyPrincipal(),
173
- ],
174
- }),
175
- ],
176
- });
177
- }
178
- exports.createIpRestrictionPolicyDocument = createIpRestrictionPolicyDocument;
179
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdF9hcGlzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2F3cy9pbmZyYS9zdGFjay9yZXN0X2FwaXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsK0RBT29DO0FBQ3BDLGlEQUEwRjtBQUcxRixnREFBdUU7QUFFdkUsd0RBQTJEO0FBQzNELHVEQUFpRDtBQUdqRCwyQkFBNEI7QUFFNUIsTUFBYSxrQkFBbUIsU0FBUSx3QkFBTztJQUczQyxZQUNJLEtBQXVCLEVBQUUsS0FBYSxFQUFFLE9BQWUsRUFBRSxvQkFBMkMsRUFBRSxNQUE4QjtRQUVwSSxNQUFNLGNBQWMsR0FBRyxvQkFBb0IsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLDJCQUEyQixFQUFFLENBQUMsQ0FBQyxDQUFDLGlDQUFpQyxDQUFDLG9CQUFvQixDQUFDLENBQUM7UUFFOUksa0RBQWtEO1FBQ2xELE1BQU0sU0FBUyxHQUFHLEVBQUMsR0FBRztnQkFDbEIsYUFBYSxFQUFFO29CQUNYLFlBQVksRUFBRSxtQ0FBa0IsQ0FBQyxLQUFLO2lCQUN6QztnQkFDRCxXQUFXLEVBQUUsT0FBTztnQkFDcEIsYUFBYSxFQUFFLENBQUMsNkJBQVksQ0FBQyxRQUFRLENBQUM7Z0JBQ3RDLE1BQU0sRUFBRSxjQUFjO2FBQ3pCLEVBQUUsR0FBRyxNQUFNLEVBQUMsQ0FBQztRQUVkLEtBQUssQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBRS9CLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO1FBRXBCLGFBQWEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVELFFBQVE7UUFDSixPQUFPLEdBQUcsSUFBSSxDQUFDLFNBQVMsZ0JBQWlCLElBQUksQ0FBQyxLQUEwQixDQUFDLE1BQU0sZ0JBQWdCLENBQUM7SUFDcEcsQ0FBQztJQUVELGVBQWUsQ0FBQyxRQUFnQixFQUFFLFVBQWtCO1FBQ2hELE1BQU0sUUFBUSxHQUFHLElBQUEsNkJBQWUsRUFBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUVuRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUU5QixPQUFPLFFBQVEsQ0FBQztJQUNwQixDQUFDO0lBRUQsaUJBQWlCLENBQUMsT0FBZTtRQUM3QixNQUFNLFFBQVEsR0FBRyxJQUFBLG9DQUFzQixFQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQyxLQUFLLENBQUM7UUFFN0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFOUIsT0FBTyxRQUFRLENBQUM7SUFDcEIsQ0FBQztJQUVELFlBQVksQ0FBQyxTQUFpQixFQUFFLE1BQWtCO1FBQzlDLE9BQU8sSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxFQUFFO1lBQ3ZELFdBQVcsRUFBRSxzQkFBUyxDQUFDLGdCQUFnQjtZQUN2QyxTQUFTO1lBQ1QsTUFBTTtTQUNULENBQUMsQ0FBQyxDQUFDO0lBQ1IsQ0FBQztJQUVELFdBQVcsQ0FBQyxTQUFpQjtRQUN6QixPQUFPLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRTtZQUN2RCxXQUFXLEVBQUUsc0JBQVMsQ0FBQyxRQUFRO1lBQy9CLFNBQVM7WUFDVCxNQUFNLEVBQUUsRUFBRTtTQUNiLENBQUMsQ0FBQyxDQUFDO0lBQ1IsQ0FBQztJQUVPLHFCQUFxQixDQUFDLEtBQVk7UUFDdEMsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUFFLElBQUEsNkJBQWlCLEVBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsS0FBSyxDQUF1QixDQUFDO0lBQ3BILENBQUM7SUFFTyxvQkFBb0IsQ0FDeEIsUUFBa0IsRUFBRSxhQUFxQixFQUFFLFlBQW9CLEVBQUUsSUFBWSxFQUFFLFVBQW1DO1FBRWxILE1BQU0sUUFBUSxHQUEwQztZQUNwRCxJQUFJO1lBQ0osSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUFJO1lBQ25CLElBQUksRUFBRSxJQUFJLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLFNBQVM7U0FDdEQsQ0FBQztRQUVGLElBQUkscUNBQW9CLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxZQUFZLEVBQUU7WUFDL0MsU0FBUyxFQUFFLFFBQVEsQ0FBQyxHQUFHLENBQUMsU0FBUztZQUNqQyxRQUFRO1lBQ1IsVUFBVSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDO1NBQ3pDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxRQUFrQixFQUFFLEdBQUcsaUJBQXNDO1FBQzFFLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FDckQsUUFBUSxFQUFFLEVBQUUsQ0FBQyxhQUFhLEVBQUUsR0FBRyxRQUFRLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxhQUFhLGdCQUFnQixFQUFFLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLHVCQUF1QixDQUN4SCxDQUFDLENBQUM7SUFDUCxDQUFDO0NBQ0o7QUF0RkQsZ0RBc0ZDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsU0FBZ0IsYUFBYSxDQUFDLE9BQWdCLEVBQUUsS0FBZ0I7SUFDNUQsSUFBSSxnQ0FBZSxDQUFDLEtBQUssRUFBRSxzQ0FBc0MsT0FBTyxDQUFDLFdBQVcsRUFBRSxFQUFFO1FBQ3BGLE9BQU87UUFDUCxJQUFJLEVBQUUsNkJBQVksQ0FBQyw0QkFBNEI7UUFDL0MsVUFBVSxFQUFFLEtBQUs7UUFDakIsU0FBUyxFQUFFO1lBQ1Asa0JBQWtCLEVBQUUsMEJBQTBCO1NBQ2pEO0tBQ0osQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQVRELHNDQVNDO0FBRUQsU0FBZ0IsYUFBYSxDQUFDLE9BQWdCLEVBQUUsS0FBZ0I7SUFDNUQsSUFBSSxnQ0FBZSxDQUFDLEtBQUssRUFBRSxnQ0FBZ0MsT0FBTyxDQUFDLFdBQVcsRUFBRSxFQUFFO1FBQzlFLE9BQU87UUFDUCxJQUFJLEVBQUUsNkJBQVksQ0FBQyxZQUFZO1FBQy9CLFVBQVUsRUFBRSxLQUFLO1FBQ2pCLGVBQWUsRUFBRTtZQUNiLGtCQUFrQixFQUFFLFNBQVM7U0FDaEM7S0FDSixDQUFDLENBQUM7QUFDUCxDQUFDO0FBVEQsc0NBU0M7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILFNBQWdCLDBDQUEwQyxDQUFDLFVBQWtCLEVBQ3pFLE9BQWUsRUFDZixPQUFnQixFQUNoQixLQUFnQjtJQUVoQixJQUFJLGdDQUFlLENBQUMsS0FBSyxFQUFFLHNDQUFzQyxPQUFPLENBQUMsV0FBVyxFQUFFLEVBQUU7UUFDcEYsT0FBTztRQUNQLElBQUksRUFBRSw2QkFBWSxDQUFDLDRCQUE0QjtRQUMvQyxVQUFVLEVBQUUsR0FBRyxVQUFVLEVBQUU7UUFDM0IsU0FBUyxFQUFFO1lBQ1Asa0JBQWtCLEVBQUUsZUFBZSxPQUFPLEdBQUc7U0FDaEQ7S0FDSixDQUFDLENBQUM7QUFDUCxDQUFDO0FBYkQsZ0dBYUM7QUFFRCxTQUFnQixhQUFhLENBQUMsS0FBZ0IsRUFBRSxLQUFhLEVBQUUsT0FBZSxFQUFFLG9CQUEyQztJQUN2SCxNQUFNLGNBQWMsR0FBRyxvQkFBb0IsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLDJCQUEyQixFQUFFLENBQUMsQ0FBQyxDQUFDLGlDQUFpQyxDQUFDLG9CQUFvQixDQUFDLENBQUM7SUFDOUksTUFBTSxPQUFPLEdBQUcsSUFBSSx3QkFBTyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUU7UUFDdEMsYUFBYSxFQUFFO1lBQ1gsWUFBWSxFQUFFLG1DQUFrQixDQUFDLEtBQUs7U0FDekM7UUFDRCxXQUFXLEVBQUUsT0FBTztRQUNwQixhQUFhLEVBQUUsQ0FBQyw2QkFBWSxDQUFDLFFBQVEsQ0FBQztRQUN0QyxNQUFNLEVBQUUsY0FBYztLQUN6QixDQUFDLENBQUM7SUFDSCxhQUFhLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzlCLE9BQU8sT0FBTyxDQUFDO0FBQ25CLENBQUM7QUFaRCxzQ0FZQztBQUVELFNBQWdCLDJCQUEyQjtJQUN2QyxPQUFPLElBQUksd0JBQWMsQ0FBQztRQUN0QixVQUFVLEVBQUU7WUFDUixJQUFJLHlCQUFlLENBQUM7Z0JBQ2hCLE1BQU0sRUFBRSxnQkFBTSxDQUFDLEtBQUs7Z0JBQ3BCLE9BQU8sRUFBRTtvQkFDTCxvQkFBb0I7aUJBQ3ZCO2dCQUNELFNBQVMsRUFBRTtvQkFDUCxHQUFHO2lCQUNOO2dCQUNELFVBQVUsRUFBRTtvQkFDUixJQUFJLHNCQUFZLEVBQUU7aUJBQ3JCO2FBQ0osQ0FBQztTQUNMO0tBQ0osQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQWpCRCxrRUFpQkM7QUFHRCxTQUFnQixpQ0FBaUMsQ0FBQyxvQkFBOEI7SUFDNUUsT0FBTyxJQUFJLHdCQUFjLENBQUM7UUFDdEIsVUFBVSxFQUFFO1lBQ1IsSUFBSSx5QkFBZSxDQUFDO2dCQUNoQixNQUFNLEVBQUUsZ0JBQU0sQ0FBQyxLQUFLO2dCQUNwQixVQUFVLEVBQUU7b0JBQ1IsV0FBVyxFQUFFO3dCQUNULGNBQWMsRUFBRSxvQkFBb0I7cUJBQ3ZDO2lCQUNKO2dCQUNELE9BQU8sRUFBRTtvQkFDTCxvQkFBb0I7aUJBQ3ZCO2dCQUNELFNBQVMsRUFBRTtvQkFDUCxHQUFHO2lCQUNOO2dCQUNELFVBQVUsRUFBRTtvQkFDUixJQUFJLHNCQUFZLEVBQUU7aUJBQ3JCO2FBQ0osQ0FBQztTQUNMO0tBQ0osQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQXRCRCw4RUFzQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gICAgUmVzdEFwaSxcclxuICAgIE1ldGhvZExvZ2dpbmdMZXZlbCxcclxuICAgIEdhdGV3YXlSZXNwb25zZSxcclxuICAgIFJlc3BvbnNlVHlwZSxcclxuICAgIEVuZHBvaW50VHlwZSxcclxuICAgIFJlc3RBcGlQcm9wcywgSnNvblNjaGVtYSwgTW9kZWwsIENmbkRvY3VtZW50YXRpb25QYXJ0LCBSZXNvdXJjZSxcclxufSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtYXBpZ2F0ZXdheSc7XHJcbmltcG9ydCB7UG9saWN5RG9jdW1lbnQsIFBvbGljeVN0YXRlbWVudCwgRWZmZWN0LCBBbnlQcmluY2lwYWx9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xyXG5pbXBvcnQge0NvbnN0cnVjdH0gZnJvbSBcImNvbnN0cnVjdHNcIjtcclxuaW1wb3J0IHtEaWdpdHJhZmZpY1N0YWNrfSBmcm9tIFwiLi9zdGFja1wiO1xyXG5pbXBvcnQge2NyZWF0ZURlZmF1bHRVc2FnZVBsYW4sIGNyZWF0ZVVzYWdlUGxhbn0gZnJvbSBcIi4uL3VzYWdlLXBsYW5zXCI7XHJcbmltcG9ydCB7TW9kZWxXaXRoUmVmZXJlbmNlfSBmcm9tIFwiLi4vLi4vdHlwZXMvbW9kZWwtd2l0aC1yZWZlcmVuY2VcIjtcclxuaW1wb3J0IHtnZXRNb2RlbFJlZmVyZW5jZX0gZnJvbSBcIi4uLy4uLy4uL3V0aWxzL2FwaS1tb2RlbFwiO1xyXG5pbXBvcnQge01lZGlhVHlwZX0gZnJvbSBcIi4uLy4uL3R5cGVzL21lZGlhdHlwZXNcIjtcclxuaW1wb3J0IHtEb2N1bWVudGF0aW9uUGFydCwgRG9jdW1lbnRhdGlvblByb3BlcnRpZXN9IGZyb20gXCIuLi9kb2N1bWVudGF0aW9uXCI7XHJcblxyXG5pbXBvcnQgUiA9IHJlcXVpcmUoJ3JhbWRhJyk7XHJcblxyXG5leHBvcnQgY2xhc3MgRGlnaXRyYWZmaWNSZXN0QXBpIGV4dGVuZHMgUmVzdEFwaSB7XHJcbiAgICByZWFkb25seSBhcGlLZXlJZHM6IHN0cmluZ1tdO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICAgIHN0YWNrOiBEaWdpdHJhZmZpY1N0YWNrLCBhcGlJZDogc3RyaW5nLCBhcGlOYW1lOiBzdHJpbmcsIGFsbG93RnJvbUlwQWRkcmVzc2VzPzogc3RyaW5nW10gfCB1bmRlZmluZWQsIGNvbmZpZz86IFBhcnRpYWw8UmVzdEFwaVByb3BzPixcclxuICAgICkge1xyXG4gICAgICAgIGNvbnN0IHBvbGljeURvY3VtZW50ID0gYWxsb3dGcm9tSXBBZGRyZXNzZXMgPT0gbnVsbCA/IGNyZWF0ZURlZmF1bHRQb2xpY3lEb2N1bWVudCgpIDogY3JlYXRlSXBSZXN0cmljdGlvblBvbGljeURvY3VtZW50KGFsbG93RnJvbUlwQWRkcmVzc2VzKTtcclxuXHJcbiAgICAgICAgLy8gb3ZlcnJpZGUgZGVmYXVsdCBjb25maWcgd2l0aCBnaXZlbiBleHRyYSBjb25maWdcclxuICAgICAgICBjb25zdCBhcGlDb25maWcgPSB7Li4ue1xyXG4gICAgICAgICAgICBkZXBsb3lPcHRpb25zOiB7XHJcbiAgICAgICAgICAgICAgICBsb2dnaW5nTGV2ZWw6IE1ldGhvZExvZ2dpbmdMZXZlbC5FUlJPUixcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgcmVzdEFwaU5hbWU6IGFwaU5hbWUsXHJcbiAgICAgICAgICAgIGVuZHBvaW50VHlwZXM6IFtFbmRwb2ludFR5cGUuUkVHSU9OQUxdLFxyXG4gICAgICAgICAgICBwb2xpY3k6IHBvbGljeURvY3VtZW50LFxyXG4gICAgICAgIH0sIC4uLmNvbmZpZ307XHJcblxyXG4gICAgICAgIHN1cGVyKHN0YWNrLCBhcGlJZCwgYXBpQ29uZmlnKTtcclxuXHJcbiAgICAgICAgdGhpcy5hcGlLZXlJZHMgPSBbXTtcclxuXHJcbiAgICAgICAgYWRkNDA0U3VwcG9ydCh0aGlzLCBzdGFjayk7XHJcbiAgICB9XHJcblxyXG4gICAgaG9zdG5hbWUoKTogc3RyaW5nIHtcclxuICAgICAgICByZXR1cm4gYCR7dGhpcy5yZXN0QXBpSWR9LmV4ZWN1dGUtYXBpLiR7KHRoaXMuc3RhY2sgYXMgRGlnaXRyYWZmaWNTdGFjaykucmVnaW9ufS5hbWF6b25hd3MuY29tYDtcclxuICAgIH1cclxuXHJcbiAgICBjcmVhdGVVc2FnZVBsYW4oYXBpS2V5SWQ6IHN0cmluZywgYXBpS2V5TmFtZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgICAgICBjb25zdCBuZXdLZXlJZCA9IGNyZWF0ZVVzYWdlUGxhbih0aGlzLCBhcGlLZXlJZCwgYXBpS2V5TmFtZSkua2V5SWQ7XHJcblxyXG4gICAgICAgIHRoaXMuYXBpS2V5SWRzLnB1c2gobmV3S2V5SWQpO1xyXG5cclxuICAgICAgICByZXR1cm4gbmV3S2V5SWQ7XHJcbiAgICB9XHJcblxyXG4gICAgY3JlYXRlVXNhZ2VQbGFuVjIoYXBpTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgICAgICBjb25zdCBuZXdLZXlJZCA9IGNyZWF0ZURlZmF1bHRVc2FnZVBsYW4odGhpcywgYXBpTmFtZSkua2V5SWQ7XHJcblxyXG4gICAgICAgIHRoaXMuYXBpS2V5SWRzLnB1c2gobmV3S2V5SWQpO1xyXG5cclxuICAgICAgICByZXR1cm4gbmV3S2V5SWQ7XHJcbiAgICB9XHJcblxyXG4gICAgYWRkSnNvbk1vZGVsKG1vZGVsTmFtZTogc3RyaW5nLCBzY2hlbWE6IEpzb25TY2hlbWEpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5nZXRNb2RlbFdpdGhSZWZlcmVuY2UodGhpcy5hZGRNb2RlbChtb2RlbE5hbWUsIHtcclxuICAgICAgICAgICAgY29udGVudFR5cGU6IE1lZGlhVHlwZS5BUFBMSUNBVElPTl9KU09OLFxyXG4gICAgICAgICAgICBtb2RlbE5hbWUsXHJcbiAgICAgICAgICAgIHNjaGVtYSxcclxuICAgICAgICB9KSk7XHJcbiAgICB9XHJcblxyXG4gICAgYWRkQ1NWTW9kZWwobW9kZWxOYW1lOiBzdHJpbmcpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5nZXRNb2RlbFdpdGhSZWZlcmVuY2UodGhpcy5hZGRNb2RlbChtb2RlbE5hbWUsIHtcclxuICAgICAgICAgICAgY29udGVudFR5cGU6IE1lZGlhVHlwZS5URVhUX0NTVixcclxuICAgICAgICAgICAgbW9kZWxOYW1lLFxyXG4gICAgICAgICAgICBzY2hlbWE6IHt9LFxyXG4gICAgICAgIH0pKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGdldE1vZGVsV2l0aFJlZmVyZW5jZShtb2RlbDogTW9kZWwpOiBNb2RlbFdpdGhSZWZlcmVuY2Uge1xyXG4gICAgICAgIHJldHVybiBSLmFzc29jKCdtb2RlbFJlZmVyZW5jZScsIGdldE1vZGVsUmVmZXJlbmNlKG1vZGVsLm1vZGVsSWQsIHRoaXMucmVzdEFwaUlkKSwgbW9kZWwpIGFzIE1vZGVsV2l0aFJlZmVyZW5jZTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGFkZERvY3VtZW50YXRpb25QYXJ0KFxyXG4gICAgICAgIHJlc291cmNlOiBSZXNvdXJjZSwgcGFyYW1ldGVyTmFtZTogc3RyaW5nLCByZXNvdXJjZU5hbWU6IHN0cmluZywgdHlwZTogc3RyaW5nLCBwcm9wZXJ0aWVzOiBEb2N1bWVudGF0aW9uUHJvcGVydGllcyxcclxuICAgICkge1xyXG4gICAgICAgIGNvbnN0IGxvY2F0aW9uOiBDZm5Eb2N1bWVudGF0aW9uUGFydC5Mb2NhdGlvblByb3BlcnR5ID0ge1xyXG4gICAgICAgICAgICB0eXBlLFxyXG4gICAgICAgICAgICBwYXRoOiByZXNvdXJjZS5wYXRoLFxyXG4gICAgICAgICAgICBuYW1lOiB0eXBlICE9PSAnTUVUSE9EJyA/IHBhcmFtZXRlck5hbWUgOiB1bmRlZmluZWQsXHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgbmV3IENmbkRvY3VtZW50YXRpb25QYXJ0KHRoaXMuc3RhY2ssIHJlc291cmNlTmFtZSwge1xyXG4gICAgICAgICAgICByZXN0QXBpSWQ6IHJlc291cmNlLmFwaS5yZXN0QXBpSWQsXHJcbiAgICAgICAgICAgIGxvY2F0aW9uLFxyXG4gICAgICAgICAgICBwcm9wZXJ0aWVzOiBKU09OLnN0cmluZ2lmeShwcm9wZXJ0aWVzKSxcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBkb2N1bWVudFJlc291cmNlKHJlc291cmNlOiBSZXNvdXJjZSwgLi4uZG9jdW1lbnRhdGlvblBhcnQ6IERvY3VtZW50YXRpb25QYXJ0W10pIHtcclxuICAgICAgICBkb2N1bWVudGF0aW9uUGFydC5mb3JFYWNoKGRwID0+IHRoaXMuYWRkRG9jdW1lbnRhdGlvblBhcnQoXHJcbiAgICAgICAgICAgIHJlc291cmNlLCBkcC5wYXJhbWV0ZXJOYW1lLCBgJHtyZXNvdXJjZS5wYXRofS4ke2RwLnBhcmFtZXRlck5hbWV9LkRvY3VtZW50YXRpb25gLCBkcC50eXBlLCBkcC5kb2N1bWVudGF0aW9uUHJvcGVydGllcyxcclxuICAgICAgICApKTtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIER1ZSB0byBBV1MgQVBJIGRlc2lnbiBBUEkgR2F0ZXdheSB3aWxsIGFsd2F5cyByZXR1cm4gNDAzICdNaXNzaW5nIEF1dGhlbnRpY2F0aW9uIFRva2VuJyBmb3IgcmVxdWVzdHNcclxuICogd2l0aCBhIG5vbi1leGlzdGVudCBlbmRwb2ludC4gVGhpcyBmdW5jdGlvbiB0cmFuc2xhdGVzIHRoaXMgcmVzcG9uc2UgdG8gYSA0MDQuXHJcbiAqIFJlcXVlc3RzIHdpdGggYW4gaW52YWxpZCBvciBtaXNzaW5nIEFQSSBrZXkgYXJlIG5vdCBhZmZlY3RlZCAoc3RpbGwgcmV0dXJuIDQwMyAnRm9yYmlkZGVuJykuXHJcbiAqIEBwYXJhbSByZXN0QXBpIFJlc3RBcGlcclxuICogQHBhcmFtIHN0YWNrIENvbnN0cnVjdFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGFkZDQwNFN1cHBvcnQocmVzdEFwaTogUmVzdEFwaSwgc3RhY2s6IENvbnN0cnVjdCkge1xyXG4gICAgbmV3IEdhdGV3YXlSZXNwb25zZShzdGFjaywgYE1pc3NpbmdBdXRoZW50aWNhdGlvblRva2VuUmVzcG9uc2UtJHtyZXN0QXBpLnJlc3RBcGlOYW1lfWAsIHtcclxuICAgICAgICByZXN0QXBpLFxyXG4gICAgICAgIHR5cGU6IFJlc3BvbnNlVHlwZS5NSVNTSU5HX0FVVEhFTlRJQ0FUSU9OX1RPS0VOLFxyXG4gICAgICAgIHN0YXR1c0NvZGU6ICc0MDQnLFxyXG4gICAgICAgIHRlbXBsYXRlczoge1xyXG4gICAgICAgICAgICAnYXBwbGljYXRpb24vanNvbic6ICd7XCJtZXNzYWdlXCI6IFwiTm90IGZvdW5kXCJ9JyxcclxuICAgICAgICB9LFxyXG4gICAgfSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBhZGQ0MDFTdXBwb3J0KHJlc3RBcGk6IFJlc3RBcGksIHN0YWNrOiBDb25zdHJ1Y3QpIHtcclxuICAgIG5ldyBHYXRld2F5UmVzcG9uc2Uoc3RhY2ssIGBBdXRoZW50aWNhdGlvbkZhaWxlZFJlc3BvbnNlLSR7cmVzdEFwaS5yZXN0QXBpTmFtZX1gLCB7XHJcbiAgICAgICAgcmVzdEFwaSxcclxuICAgICAgICB0eXBlOiBSZXNwb25zZVR5cGUuVU5BVVRIT1JJWkVELFxyXG4gICAgICAgIHN0YXR1c0NvZGU6IFwiNDAxXCIsXHJcbiAgICAgICAgcmVzcG9uc2VIZWFkZXJzOiB7XHJcbiAgICAgICAgICAgICdXV1ctQXV0aGVudGljYXRlJzogXCInQmFzaWMnXCIsXHJcbiAgICAgICAgfSxcclxuICAgIH0pO1xyXG59XHJcblxyXG4vKipcclxuICogRHVlIHRvIEFXUyBBUEkgZGVzaWduIEFQSSBHYXRld2F5IHdpbGwgYWx3YXlzIHJldHVybiA0MDMgJ01pc3NpbmcgQXV0aGVudGljYXRpb24gVG9rZW4nIGZvciByZXF1ZXN0c1xyXG4gKiB3aXRoIGEgbm9uLWV4aXN0ZW50IGVuZHBvaW50LiBUaGlzIGZ1bmN0aW9uIGNvbnZlcnRzIHRoaXMgcmVzcG9uc2UgdG8gYSBjdXN0b20gb25lLlxyXG4gKiBSZXF1ZXN0cyB3aXRoIGFuIGludmFsaWQgb3IgbWlzc2luZyBBUEkga2V5IGFyZSBub3QgYWZmZWN0ZWQgKHN0aWxsIHJldHVybiA0MDMgJ0ZvcmJpZGRlbicpLlxyXG4gKiBAcGFyYW0gcmV0dXJuQ29kZVxyXG4gKiBAcGFyYW0gbWVzc2FnZVxyXG4gKiBAcGFyYW0gcmVzdEFwaSBSZXN0QXBpXHJcbiAqIEBwYXJhbSBzdGFjayBDb25zdHJ1Y3RcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBzZXRSZXR1cm5Db2RlRm9yTWlzc2luZ0F1dGhlbnRpY2F0aW9uVG9rZW4ocmV0dXJuQ29kZTogbnVtYmVyLFxyXG4gICAgbWVzc2FnZTogc3RyaW5nLFxyXG4gICAgcmVzdEFwaTogUmVzdEFwaSxcclxuICAgIHN0YWNrOiBDb25zdHJ1Y3QpIHtcclxuXHJcbiAgICBuZXcgR2F0ZXdheVJlc3BvbnNlKHN0YWNrLCBgTWlzc2luZ0F1dGhlbnRpY2F0aW9uVG9rZW5SZXNwb25zZS0ke3Jlc3RBcGkucmVzdEFwaU5hbWV9YCwge1xyXG4gICAgICAgIHJlc3RBcGksXHJcbiAgICAgICAgdHlwZTogUmVzcG9uc2VUeXBlLk1JU1NJTkdfQVVUSEVOVElDQVRJT05fVE9LRU4sXHJcbiAgICAgICAgc3RhdHVzQ29kZTogYCR7cmV0dXJuQ29kZX1gLFxyXG4gICAgICAgIHRlbXBsYXRlczoge1xyXG4gICAgICAgICAgICAnYXBwbGljYXRpb24vanNvbic6IGB7XCJtZXNzYWdlXCI6ICR7bWVzc2FnZX19YCxcclxuICAgICAgICB9LFxyXG4gICAgfSk7XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVSZXN0QXBpKHN0YWNrOiBDb25zdHJ1Y3QsIGFwaUlkOiBzdHJpbmcsIGFwaU5hbWU6IHN0cmluZywgYWxsb3dGcm9tSXBBZGRyZXNzZXM/OiBzdHJpbmdbXSB8IHVuZGVmaW5lZCk6IFJlc3RBcGkge1xyXG4gICAgY29uc3QgcG9saWN5RG9jdW1lbnQgPSBhbGxvd0Zyb21JcEFkZHJlc3NlcyA9PSBudWxsID8gY3JlYXRlRGVmYXVsdFBvbGljeURvY3VtZW50KCkgOiBjcmVhdGVJcFJlc3RyaWN0aW9uUG9saWN5RG9jdW1lbnQoYWxsb3dGcm9tSXBBZGRyZXNzZXMpO1xyXG4gICAgY29uc3QgcmVzdEFwaSA9IG5ldyBSZXN0QXBpKHN0YWNrLCBhcGlJZCwge1xyXG4gICAgICAgIGRlcGxveU9wdGlvbnM6IHtcclxuICAgICAgICAgICAgbG9nZ2luZ0xldmVsOiBNZXRob2RMb2dnaW5nTGV2ZWwuRVJST1IsXHJcbiAgICAgICAgfSxcclxuICAgICAgICByZXN0QXBpTmFtZTogYXBpTmFtZSxcclxuICAgICAgICBlbmRwb2ludFR5cGVzOiBbRW5kcG9pbnRUeXBlLlJFR0lPTkFMXSxcclxuICAgICAgICBwb2xpY3k6IHBvbGljeURvY3VtZW50LFxyXG4gICAgfSk7XHJcbiAgICBhZGQ0MDRTdXBwb3J0KHJlc3RBcGksIHN0YWNrKTtcclxuICAgIHJldHVybiByZXN0QXBpO1xyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRGVmYXVsdFBvbGljeURvY3VtZW50KCkge1xyXG4gICAgcmV0dXJuIG5ldyBQb2xpY3lEb2N1bWVudCh7XHJcbiAgICAgICAgc3RhdGVtZW50czogW1xyXG4gICAgICAgICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcclxuICAgICAgICAgICAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XLFxyXG4gICAgICAgICAgICAgICAgYWN0aW9uczogW1xyXG4gICAgICAgICAgICAgICAgICAgIFwiZXhlY3V0ZS1hcGk6SW52b2tlXCIsXHJcbiAgICAgICAgICAgICAgICBdLFxyXG4gICAgICAgICAgICAgICAgcmVzb3VyY2VzOiBbXHJcbiAgICAgICAgICAgICAgICAgICAgXCIqXCIsXHJcbiAgICAgICAgICAgICAgICBdLFxyXG4gICAgICAgICAgICAgICAgcHJpbmNpcGFsczogW1xyXG4gICAgICAgICAgICAgICAgICAgIG5ldyBBbnlQcmluY2lwYWwoKSxcclxuICAgICAgICAgICAgICAgIF0sXHJcbiAgICAgICAgICAgIH0pLFxyXG4gICAgICAgIF0sXHJcbiAgICB9KTtcclxufVxyXG5cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVJcFJlc3RyaWN0aW9uUG9saWN5RG9jdW1lbnQoYWxsb3dGcm9tSXBBZGRyZXNzZXM6IHN0cmluZ1tdKTogUG9saWN5RG9jdW1lbnQge1xyXG4gICAgcmV0dXJuIG5ldyBQb2xpY3lEb2N1bWVudCh7XHJcbiAgICAgICAgc3RhdGVtZW50czogW1xyXG4gICAgICAgICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcclxuICAgICAgICAgICAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XLFxyXG4gICAgICAgICAgICAgICAgY29uZGl0aW9uczoge1xyXG4gICAgICAgICAgICAgICAgICAgIFwiSXBBZGRyZXNzXCI6IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgXCJhd3M6U291cmNlSXBcIjogYWxsb3dGcm9tSXBBZGRyZXNzZXMsXHJcbiAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICBhY3Rpb25zOiBbXHJcbiAgICAgICAgICAgICAgICAgICAgXCJleGVjdXRlLWFwaTpJbnZva2VcIixcclxuICAgICAgICAgICAgICAgIF0sXHJcbiAgICAgICAgICAgICAgICByZXNvdXJjZXM6IFtcclxuICAgICAgICAgICAgICAgICAgICBcIipcIixcclxuICAgICAgICAgICAgICAgIF0sXHJcbiAgICAgICAgICAgICAgICBwcmluY2lwYWxzOiBbXHJcbiAgICAgICAgICAgICAgICAgICAgbmV3IEFueVByaW5jaXBhbCgpLFxyXG4gICAgICAgICAgICAgICAgXSxcclxuICAgICAgICAgICAgfSksXHJcbiAgICAgICAgXSxcclxuICAgIH0pO1xyXG59XHJcbiJdfQ==
@@ -1,163 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.StackCheckingAspect = void 0;
4
- const aws_cdk_lib_1 = require("aws-cdk-lib");
5
- const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
6
- const aws_s3_1 = require("aws-cdk-lib/aws-s3");
7
- const stack_1 = require("./stack");
8
- const aws_apigateway_1 = require("aws-cdk-lib/aws-apigateway");
9
- const change_case_1 = require("change-case");
10
- const aws_sqs_1 = require("aws-cdk-lib/aws-sqs");
11
- const aws_logs_1 = require("aws-cdk-lib/aws-logs");
12
- const MAX_CONCURRENCY_LIMIT = 100;
13
- const NODE_RUNTIME = aws_lambda_1.Runtime.NODEJS_14_X.name;
14
- var ResourceType;
15
- (function (ResourceType) {
16
- ResourceType["stackName"] = "STACK_NAME";
17
- ResourceType["reservedConcurrentConcurrency"] = "RESERVED_CONCURRENT_CONCURRENCY";
18
- ResourceType["functionTimeout"] = "FUNCTION_TIMEOUT";
19
- ResourceType["functionMemorySize"] = "FUNCTION_MEMORY_SIZE";
20
- ResourceType["functionRuntime"] = "FUNCTION_RUNTIME";
21
- ResourceType["functionName"] = "FUNCTION_NAME";
22
- ResourceType["tagSolution"] = "TAG_SOLUTION";
23
- ResourceType["bucketPublicity"] = "BUCKET_PUBLICITY";
24
- ResourceType["resourcePath"] = "RESOURCE_PATH";
25
- ResourceType["queueEncryption"] = "QUEUE_ENCRYPTION";
26
- ResourceType["logGroupRetention"] = "LOG_GROUP_RETENTION";
27
- })(ResourceType || (ResourceType = {}));
28
- class StackCheckingAspect {
29
- constructor(configuration) {
30
- this.configuration = configuration;
31
- }
32
- static create(stack) {
33
- return new StackCheckingAspect(stack.configuration);
34
- }
35
- visit(node) {
36
- //console.info("visiting class " + node.constructor.name);
37
- this.checkStack(node);
38
- this.checkFunction(node);
39
- this.checkTags(node);
40
- this.checkBucket(node);
41
- this.checkResourceCasing(node);
42
- this.checkQueueEncryption(node);
43
- this.checkLogGroupRetention(node);
44
- }
45
- isWhitelisted(key) {
46
- return this?.configuration?.whitelistedResources?.some(wl => {
47
- return key.matchAll(new RegExp(wl, 'g'));
48
- });
49
- }
50
- addAnnotation(node, key, message, isError = true) {
51
- const resourceKey = `${node.node.path}/${key}`;
52
- const isWhiteListed = this.isWhitelisted(resourceKey);
53
- const annotationMessage = `${resourceKey}:${message}`;
54
- // error && whitelisted -> warning
55
- // warning && whitelisted -> nothing
56
- if (isError && !isWhiteListed) {
57
- aws_cdk_lib_1.Annotations.of(node).addError(annotationMessage);
58
- }
59
- else if ((!isError && !isWhiteListed) || (isError && isWhiteListed)) {
60
- aws_cdk_lib_1.Annotations.of(node).addWarning(annotationMessage);
61
- }
62
- }
63
- checkStack(node) {
64
- if (node instanceof stack_1.DigitrafficStack) {
65
- if ((node.stackName.includes('Test') || node.stackName.includes('Tst')) && node.configuration?.production) {
66
- this.addAnnotation(node, ResourceType.stackName, 'Production is set for Test-stack');
67
- }
68
- if ((node.stackName.includes('Prod') || node.stackName.includes('Prd')) && !node.configuration?.production) {
69
- this.addAnnotation(node, ResourceType.stackName, 'Production is not set for Production-stack');
70
- }
71
- }
72
- }
73
- checkFunction(node) {
74
- if (node instanceof aws_lambda_1.CfnFunction) {
75
- if (!node.reservedConcurrentExecutions) {
76
- this.addAnnotation(node, ResourceType.reservedConcurrentConcurrency, 'Function must have reservedConcurrentConcurrency');
77
- }
78
- else if (node.reservedConcurrentExecutions > MAX_CONCURRENCY_LIMIT) {
79
- this.addAnnotation(node, ResourceType.reservedConcurrentConcurrency, 'Function reservedConcurrentConcurrency too high!');
80
- }
81
- if (!node.timeout) {
82
- this.addAnnotation(node, ResourceType.functionTimeout, 'Function must have timeout');
83
- }
84
- if (!node.memorySize) {
85
- this.addAnnotation(node, ResourceType.functionMemorySize, 'Function must have memorySize');
86
- }
87
- if (node.runtime !== NODE_RUNTIME) {
88
- this.addAnnotation(node, ResourceType.functionRuntime, 'wrong runtime ' + node.runtime);
89
- }
90
- if (this.configuration?.shortName && node.functionName && node.functionName.indexOf(this.configuration.shortName) !== 0) {
91
- this.addAnnotation(node, ResourceType.functionName, 'Function name does not begin with ' + this.configuration.shortName);
92
- }
93
- }
94
- }
95
- checkTags(node) {
96
- if (node instanceof aws_cdk_lib_1.Stack) {
97
- if (!node.tags.tagValues()[stack_1.SOLUTION_KEY]) {
98
- this.addAnnotation(node, ResourceType.tagSolution, 'Solution tag is missing');
99
- }
100
- }
101
- }
102
- checkBucket(node) {
103
- if (node instanceof aws_s3_1.CfnBucket) {
104
- const c = node.publicAccessBlockConfiguration;
105
- if (c) {
106
- if (!c.blockPublicAcls || !c.blockPublicPolicy || !c.ignorePublicAcls || !c.restrictPublicBuckets) {
107
- this.addAnnotation(node, ResourceType.bucketPublicity, 'Check bucket publicity');
108
- }
109
- }
110
- }
111
- }
112
- static isValidPath(path) {
113
- // if path includes . or { check only the trailing part of path
114
- if (path.includes('.')) {
115
- return this.isValidPath(path.split('.')[0]);
116
- }
117
- if (path.includes('{')) {
118
- return this.isValidPath(path.split('{')[0]);
119
- }
120
- return (0, change_case_1.paramCase)(path) === path;
121
- }
122
- static isValidQueryString(name) {
123
- return (0, change_case_1.snakeCase)(name) === name;
124
- }
125
- checkResourceCasing(node) {
126
- if (node instanceof aws_apigateway_1.CfnResource) {
127
- if (!StackCheckingAspect.isValidPath(node.pathPart)) {
128
- this.addAnnotation(node, ResourceType.resourcePath, 'Path part should be in kebab-case');
129
- }
130
- }
131
- else if (node instanceof aws_apigateway_1.CfnMethod) {
132
- const integration = node.integration;
133
- if (integration && integration.requestParameters) {
134
- Object.keys(integration.requestParameters).forEach(key => {
135
- const split = key.split('.');
136
- const type = split[2];
137
- const name = split[3];
138
- if (type === 'querystring' && !StackCheckingAspect.isValidQueryString(name)) {
139
- this.addAnnotation(node, name, 'Querystring should be in snake_case');
140
- }
141
- });
142
- }
143
- }
144
- }
145
- checkQueueEncryption(node) {
146
- if (node instanceof aws_sqs_1.CfnQueue) {
147
- if (!node.kmsMasterKeyId) {
148
- this.addAnnotation(node, ResourceType.queueEncryption, 'Queue must have encryption enabled');
149
- }
150
- }
151
- }
152
- checkLogGroupRetention(node) {
153
- if (node instanceof aws_logs_1.LogRetention) {
154
- const child = node.node.defaultChild;
155
- const retention = child._cfnProperties.RetentionInDays;
156
- if (!retention) {
157
- this.addAnnotation(node, ResourceType.logGroupRetention, 'Log group must define log group retention');
158
- }
159
- }
160
- }
161
- }
162
- exports.StackCheckingAspect = StackCheckingAspect;
163
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2stY2hlY2tpbmctYXNwZWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2F3cy9pbmZyYS9zdGFjay9zdGFjay1jaGVja2luZy1hc3BlY3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkNBQXdEO0FBQ3hELHVEQUE0RDtBQUM1RCwrQ0FBNkM7QUFDN0MsbUNBQTJFO0FBRTNFLCtEQUFrRTtBQUNsRSw2Q0FBaUQ7QUFDakQsaURBQTZDO0FBQzdDLG1EQUFrRDtBQUdsRCxNQUFNLHFCQUFxQixHQUFHLEdBQUcsQ0FBQztBQUNsQyxNQUFNLFlBQVksR0FBRyxvQkFBTyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUM7QUFFOUMsSUFBSyxZQVlKO0FBWkQsV0FBSyxZQUFZO0lBQ2Isd0NBQXdCLENBQUE7SUFDeEIsaUZBQWlFLENBQUE7SUFDakUsb0RBQW9DLENBQUE7SUFDcEMsMkRBQTJDLENBQUE7SUFDM0Msb0RBQW9DLENBQUE7SUFDcEMsOENBQThCLENBQUE7SUFDOUIsNENBQTRCLENBQUE7SUFDNUIsb0RBQW9DLENBQUE7SUFDcEMsOENBQThCLENBQUE7SUFDOUIsb0RBQW9DLENBQUE7SUFDcEMseURBQXlDLENBQUE7QUFDN0MsQ0FBQyxFQVpJLFlBQVksS0FBWixZQUFZLFFBWWhCO0FBRUQsTUFBYSxtQkFBbUI7SUFHNUIsWUFBWSxhQUFrQztRQUMxQyxJQUFJLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQztJQUN2QyxDQUFDO0lBRUQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUF1QjtRQUNqQyxPQUFPLElBQUksbUJBQW1CLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFTSxLQUFLLENBQUMsSUFBZ0I7UUFDekIsMERBQTBEO1FBRTFELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENB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LGNBQWMsQ0FBQyxlQUFlLENBQUM7WUFFdkQsSUFBSSxDQUFDLFNBQVMsRUFBRTtnQkFDWixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxZQUFZLENBQUMsaUJBQWlCLEVBQUUsMkNBQTJDLENBQUMsQ0FBQzthQUN6RztTQUNKO0lBQ0wsQ0FBQztDQUNKO0FBOUpELGtEQThKQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7QW5ub3RhdGlvbnMsIElBc3BlY3QsIFN0YWNrfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7Q2ZuRnVuY3Rpb24sIFJ1bnRpbWV9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1sYW1iZGEnO1xuaW1wb3J0IHtDZm5CdWNrZXR9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtczNcIjtcbmltcG9ydCB7RGlnaXRyYWZmaWNTdGFjaywgU09MVVRJT05fS0VZLCBTdGFja0NvbmZpZ3VyYXRpb259IGZyb20gXCIuL3N0YWNrXCI7XG5pbXBvcnQge0lDb25zdHJ1Y3R9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQge0Nmbk1ldGhvZCwgQ2ZuUmVzb3VyY2V9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtYXBpZ2F0ZXdheVwiO1xuaW1wb3J0IHtwYXJhbUNhc2UsIHNuYWtlQ2FzZX0gZnJvbSBcImNoYW5nZS1jYXNlXCI7XG5pbXBvcnQge0NmblF1ZXVlfSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXNxc1wiO1xuaW1wb3J0IHtMb2dSZXRlbnRpb259IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtbG9nc1wiO1xuaW1wb3J0IEludGVncmF0aW9uUHJvcGVydHkgPSBDZm5NZXRob2QuSW50ZWdyYXRpb25Qcm9wZXJ0eTtcblxuY29uc3QgTUFYX0NPTkNVUlJFTkNZX0xJTUlUID0gMTAwO1xuY29uc3QgTk9ERV9SVU5USU1FID0gUnVudGltZS5OT0RFSlNfMTRfWC5uYW1lO1xuXG5lbnVtIFJlc291cmNlVHlwZSB7XG4gICAgc3RhY2tOYW1lID0gXCJTVEFDS19OQU1FXCIsXG4gICAgcmVzZXJ2ZWRDb25jdXJyZW50Q29uY3VycmVuY3kgPSBcIlJFU0VSVkVEX0NPTkNVUlJFTlRfQ09OQ1VSUkVOQ1lcIixcbiAgICBmdW5jdGlvblRpbWVvdXQgPSBcIkZVTkNUSU9OX1RJTUVPVVRcIixcbiAgICBmdW5jdGlvbk1lbW9yeVNpemUgPSBcIkZVTkNUSU9OX01FTU9SWV9TSVpFXCIsXG4gICAgZnVuY3Rpb25SdW50aW1lID0gXCJGVU5DVElPTl9SVU5USU1FXCIsXG4gICAgZnVuY3Rpb25OYW1lID0gXCJGVU5DVElPTl9OQU1FXCIsXG4gICAgdGFnU29sdXRpb24gPSBcIlRBR19TT0xVVElPTlwiLFxuICAgIGJ1Y2tldFB1YmxpY2l0eSA9IFwiQlVDS0VUX1BVQkxJQ0lUWVwiLFxuICAgIHJlc291cmNlUGF0aCA9IFwiUkVTT1VSQ0VfUEFUSFwiLFxuICAgIHF1ZXVlRW5jcnlwdGlvbiA9IFwiUVVFVUVfRU5DUllQVElPTlwiLFxuICAgIGxvZ0dyb3VwUmV0ZW50aW9uID0gXCJMT0dfR1JPVVBfUkVURU5USU9OXCIsXG59XG5cbmV4cG9ydCBjbGFzcyBTdGFja0NoZWNraW5nQXNwZWN0IGltcGxlbWVudHMgSUFzcGVjdCB7XG4gICAgcHJpdmF0ZSByZWFkb25seSBjb25maWd1cmF0aW9uPzogU3RhY2tDb25maWd1cmF0aW9uO1xuXG4gICAgY29uc3RydWN0b3IoY29uZmlndXJhdGlvbj86IFN0YWNrQ29uZmlndXJhdGlvbikge1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUoc3RhY2s6IERpZ2l0cmFmZmljU3RhY2spIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTdGFja0NoZWNraW5nQXNwZWN0KHN0YWNrLmNvbmZpZ3VyYXRpb24pO1xuICAgIH1cblxuICAgIHB1YmxpYyB2aXNpdChub2RlOiBJQ29uc3RydWN0KTogdm9pZCB7XG4gICAgICAgIC8vY29uc29sZS5pbmZvKFwidmlzaXRpbmcgY2xhc3MgXCIgKyBub2RlLmNvbnN0cnVjdG9yLm5hbWUpO1xuXG4gICAgICAgIHRoaXMuY2hlY2tTdGFjayhub2RlKTtcbiAgICAgICAgdGhpcy5jaGVja0Z1bmN0aW9uKG5vZGUpO1xuICAgICAgICB0aGlzLmNoZWNrVGFncyhub2RlKTtcbiAgICAgICAgdGhpcy5jaGVja0J1Y2tldChub2RlKTtcbiAgICAgICAgdGhpcy5jaGVja1Jlc291cmNlQ2FzaW5nKG5vZGUpO1xuICAgICAgICB0aGlzLmNoZWNrUXVldWVFbmNyeXB0aW9uKG5vZGUpO1xuICAgICAgICB0aGlzLmNoZWNrTG9nR3JvdXBSZXRlbnRpb24obm9kZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBpc1doaXRlbGlzdGVkKGtleTogc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiB0aGlzPy5jb25maWd1cmF0aW9uPy53aGl0ZWxpc3RlZFJlc291cmNlcz8uc29tZSh3bCA9PiB7XG4gICAgICAgICAgICByZXR1cm4ga2V5Lm1hdGNoQWxsKG5ldyBSZWdFeHAod2wsICdnJykpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGFkZEFubm90YXRpb24obm9kZTogSUNvbnN0cnVjdCwga2V5OiBSZXNvdXJjZVR5cGUgfCBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZywgaXNFcnJvciA9IHRydWUpIHtcbiAgICAgICAgY29uc3QgcmVzb3VyY2VLZXkgPSBgJHtub2RlLm5vZGUucGF0aH0vJHtrZXl9YDtcbiAgICAgICAgY29uc3QgaXNXaGl0ZUxpc3RlZCA9IHRoaXMuaXNXaGl0ZWxpc3RlZChyZXNvdXJjZUtleSk7XG4gICAgICAgIGNvbnN0IGFubm90YXRpb25NZXNzYWdlID0gYCR7cmVzb3VyY2VLZXl9OiR7bWVzc2FnZX1gO1xuXG4gICAgICAgIC8vIGVycm9yICYmIHdoaXRlbGlzdGVkIC0+IHdhcm5pbmdcbiAgICAgICAgLy8gd2FybmluZyAmJiB3aGl0ZWxpc3RlZCAtPiBub3RoaW5nXG4gICAgICAgIGlmIChpc0Vycm9yICYmICFpc1doaXRlTGlzdGVkKSB7XG4gICAgICAgICAgICBBbm5vdGF0aW9ucy5vZihub2RlKS5hZGRFcnJvcihhbm5vdGF0aW9uTWVzc2FnZSk7XG4gICAgICAgIH0gZWxzZSBpZiAoKCFpc0Vycm9yICYmICFpc1doaXRlTGlzdGVkKSB8fCAoaXNFcnJvciAmJiBpc1doaXRlTGlzdGVkKSkge1xuICAgICAgICAgICAgQW5ub3RhdGlvbnMub2Yobm9kZSkuYWRkV2FybmluZyhhbm5vdGF0aW9uTWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGNoZWNrU3RhY2sobm9kZTogSUNvbnN0cnVjdCkge1xuICAgICAgICBpZiAobm9kZSBpbnN0YW5jZW9mIERpZ2l0cmFmZmljU3RhY2spIHtcbiAgICAgICAgICAgIGlmICgobm9kZS5zdGFja05hbWUuaW5jbHVkZXMoJ1Rlc3QnKSB8fCBub2RlLnN0YWNrTmFtZS5pbmNsdWRlcygnVHN0JykpICYmIG5vZGUuY29uZmlndXJhdGlvbj8ucHJvZHVjdGlvbikge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkQW5ub3RhdGlvbihub2RlLCBSZXNvdXJjZVR5cGUuc3RhY2tOYW1lLCAnUHJvZHVjdGlvbiBpcyBzZXQgZm9yIFRlc3Qtc3RhY2snKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKChub2RlLnN0YWNrTmFtZS5pbmNsdWRlcygnUHJvZCcpIHx8IG5vZGUuc3RhY2tOYW1lLmluY2x1ZGVzKCdQcmQnKSkgJiYgIW5vZGUuY29uZmlndXJhdGlvbj8ucHJvZHVjdGlvbikge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkQW5ub3RhdGlvbihub2RlLCBSZXNvdXJjZVR5cGUuc3RhY2tOYW1lLCAnUHJvZHVjdGlvbiBpcyBub3Qgc2V0IGZvciBQcm9kdWN0aW9uLXN0YWNrJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGNoZWNrRnVuY3Rpb24obm9kZTogSUNvbnN0cnVjdCkge1xuICAgICAgICBpZiAobm9kZSBpbnN0YW5jZW9mIENmbkZ1bmN0aW9uKSB7XG4gICAgICAgICAgICBpZiAoIW5vZGUucmVzZXJ2ZWRDb25jdXJyZW50RXhlY3V0aW9ucykge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkQW5ub3RhdGlvbihub2RlLCBSZXNvdXJjZVR5cGUucmVzZXJ2ZWRDb25jdXJyZW50Q29uY3VycmVuY3ksICdGdW5jdGlvbiBtdXN0IGhhdmUgcmVzZXJ2ZWRDb25jdXJyZW50Q29uY3VycmVuY3knKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobm9kZS5yZXNlcnZlZENvbmN1cnJlbnRFeGVjdXRpb25zID4gTUFYX0NPTkNVUlJFTkNZX0xJTUlUKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRBbm5vdGF0aW9uKG5vZGUsIFJlc291cmNlVHlwZS5yZXNlcnZlZENvbmN1cnJlbnRDb25jdXJyZW5jeSwgJ0Z1bmN0aW9uIHJlc2VydmVkQ29uY3VycmVudENvbmN1cnJlbmN5IHRvbyBoaWdoIScpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIW5vZGUudGltZW91dCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkQW5ub3RhdGlvbihub2RlLCBSZXNvdXJjZVR5cGUuZnVuY3Rpb25UaW1lb3V0LCAnRnVuY3Rpb24gbXVzdCBoYXZlIHRpbWVvdXQnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFub2RlLm1lbW9yeVNpemUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEFubm90YXRpb24obm9kZSwgUmVzb3VyY2VUeXBlLmZ1bmN0aW9uTWVtb3J5U2l6ZSwgJ0Z1bmN0aW9uIG11c3QgaGF2ZSBtZW1vcnlTaXplJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChub2RlLnJ1bnRpbWUgIT09IE5PREVfUlVOVElNRSkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkQW5ub3RhdGlvbihub2RlLCBSZXNvdXJjZVR5cGUuZnVuY3Rpb25SdW50aW1lLCd3cm9uZyBydW50aW1lICcgKyBub2RlLnJ1bnRpbWUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uPy5zaG9ydE5hbWUgJiYgbm9kZS5mdW5jdGlvbk5hbWUgJiYgbm9kZS5mdW5jdGlvbk5hbWUuaW5kZXhPZih0aGlzLmNvbmZpZ3VyYXRpb24uc2hvcnROYW1lKSAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkQW5ub3RhdGlvbihub2RlLCBSZXNvdXJjZVR5cGUuZnVuY3Rpb25OYW1lLCAnRnVuY3Rpb24gbmFtZSBkb2VzIG5vdCBiZWdpbiB3aXRoICcgKyB0aGlzLmNvbmZpZ3VyYXRpb24uc2hvcnROYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgY2hlY2tUYWdzKG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICAgICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBTdGFjaykge1xuICAgICAgICAgICAgaWYgKCFub2RlLnRhZ3MudGFnVmFsdWVzKClbU09MVVRJT05fS0VZXSkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkQW5ub3RhdGlvbihub2RlLCBSZXNvdXJjZVR5cGUudGFnU29sdXRpb24sICdTb2x1dGlvbiB0YWcgaXMgbWlzc2luZycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjaGVja0J1Y2tldChub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgICAgIGlmIChub2RlIGluc3RhbmNlb2YgQ2ZuQnVja2V0KSB7XG4gICAgICAgICAgICBjb25zdCBjID0gbm9kZS5wdWJsaWNBY2Nlc3NCbG9ja0NvbmZpZ3VyYXRpb24gYXMgQ2ZuQnVja2V0LlB1YmxpY0FjY2Vzc0Jsb2NrQ29uZmlndXJhdGlvblByb3BlcnR5O1xuXG4gICAgICAgICAgICBpZiAoYykge1xuICAgICAgICAgICAgICAgIGlmICghYy5ibG9ja1B1YmxpY0FjbHMgfHwgIWMuYmxvY2tQdWJsaWNQb2xpY3kgfHwgIWMuaWdub3JlUHVibGljQWNscyB8fCAhYy5yZXN0cmljdFB1YmxpY0J1Y2tldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRBbm5vdGF0aW9uKG5vZGUsIFJlc291cmNlVHlwZS5idWNrZXRQdWJsaWNpdHksICdDaGVjayBidWNrZXQgcHVibGljaXR5Jyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNWYWxpZFBhdGgocGF0aDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIC8vIGlmIHBhdGggaW5jbHVkZXMgLiBvciB7IGNoZWNrIG9ubHkgdGhlIHRyYWlsaW5nIHBhcnQgb2YgcGF0aFxuICAgICAgICBpZiAocGF0aC5pbmNsdWRlcygnLicpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5pc1ZhbGlkUGF0aChwYXRoLnNwbGl0KCcuJylbMF0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhdGguaW5jbHVkZXMoJ3snKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXNWYWxpZFBhdGgocGF0aC5zcGxpdCgneycpWzBdKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwYXJhbUNhc2UocGF0aCkgPT09IHBhdGg7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzdGF0aWMgaXNWYWxpZFF1ZXJ5U3RyaW5nKG5hbWU6IHN0cmluZykge1xuICAgICAgICByZXR1cm4gc25ha2VDYXNlKG5hbWUpID09PSBuYW1lO1xuICAgIH1cblxuICAgIHByaXZhdGUgY2hlY2tSZXNvdXJjZUNhc2luZyhub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgICAgIGlmIChub2RlIGluc3RhbmNlb2YgQ2ZuUmVzb3VyY2UpIHtcbiAgICAgICAgICAgIGlmICghU3RhY2tDaGVja2luZ0FzcGVjdC5pc1ZhbGlkUGF0aChub2RlLnBhdGhQYXJ0KSkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkQW5ub3RhdGlvbihub2RlLCBSZXNvdXJjZVR5cGUucmVzb3VyY2VQYXRoLCAnUGF0aCBwYXJ0IHNob3VsZCBiZSBpbiBrZWJhYi1jYXNlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAobm9kZSBpbnN0YW5jZW9mIENmbk1ldGhvZCkge1xuICAgICAgICAgICAgY29uc3QgaW50ZWdyYXRpb24gPSBub2RlLmludGVncmF0aW9uIGFzIEludGVncmF0aW9uUHJvcGVydHk7XG5cbiAgICAgICAgICAgIGlmIChpbnRlZ3JhdGlvbiAmJiBpbnRlZ3JhdGlvbi5yZXF1ZXN0UGFyYW1ldGVycykge1xuICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKGludGVncmF0aW9uLnJlcXVlc3RQYXJhbWV0ZXJzKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNwbGl0ID0ga2V5LnNwbGl0KCcuJyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHR5cGUgPSBzcGxpdFsyXTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmFtZSA9IHNwbGl0WzNdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlID09PSAncXVlcnlzdHJpbmcnICYmICFTdGFja0NoZWNraW5nQXNwZWN0LmlzVmFsaWRRdWVyeVN0cmluZyhuYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRBbm5vdGF0aW9uKG5vZGUsIG5hbWUsICdRdWVyeXN0cmluZyBzaG91bGQgYmUgaW4gc25ha2VfY2FzZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGNoZWNrUXVldWVFbmNyeXB0aW9uKG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICAgICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBDZm5RdWV1ZSkge1xuICAgICAgICAgICAgaWYgKCFub2RlLmttc01hc3RlcktleUlkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRBbm5vdGF0aW9uKG5vZGUsIFJlc291cmNlVHlwZS5xdWV1ZUVuY3J5cHRpb24sICdRdWV1ZSBtdXN0IGhhdmUgZW5jcnlwdGlvbiBlbmFibGVkJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGNoZWNrTG9nR3JvdXBSZXRlbnRpb24obm9kZTogSUNvbnN0cnVjdCkge1xuICAgICAgICBpZiAobm9kZSBpbnN0YW5jZW9mIExvZ1JldGVudGlvbikge1xuICAgICAgICAgICAgY29uc3QgY2hpbGQgPSBub2RlLm5vZGUuZGVmYXVsdENoaWxkIGFzIHVua25vd24gYXMgUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgc3RyaW5nPj47XG4gICAgICAgICAgICBjb25zdCByZXRlbnRpb24gPSBjaGlsZC5fY2ZuUHJvcGVydGllcy5SZXRlbnRpb25JbkRheXM7XG5cbiAgICAgICAgICAgIGlmICghcmV0ZW50aW9uKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRBbm5vdGF0aW9uKG5vZGUsIFJlc291cmNlVHlwZS5sb2dHcm91cFJldGVudGlvbiwgJ0xvZyBncm91cCBtdXN0IGRlZmluZSBsb2cgZ3JvdXAgcmV0ZW50aW9uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59XG4iXX0=