@aligent/cdk-aspects 0.3.2 → 0.5.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @aligent/cdk-aspects
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1630](https://github.com/aligent/cdk-constructs/pull/1630) [`91347d6`](https://github.com/aligent/cdk-constructs/commit/91347d62e048c23ae85f657e97c1dd357c1b2a70) Thanks [@kai-nguyen-aligent](https://github.com/kai-nguyen-aligent)! - Add default aspects for S3 and DynamoDB resources to enforce secure configuration defaults
8
+
9
+ ## 0.4.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#1627](https://github.com/aligent/cdk-constructs/pull/1627) [`a53bad0`](https://github.com/aligent/cdk-constructs/commit/a53bad0c3b8156ec3b57476b4007cdb854785ba6) Thanks [@kai-nguyen-aligent](https://github.com/kai-nguyen-aligent)! - Add new ResourcePrefixAspect
14
+
3
15
  ## 0.3.2
4
16
 
5
17
  ### Patch Changes
package/index.d.ts CHANGED
@@ -1,5 +1,8 @@
1
+ export * from "./lib/defaults/dynamodb";
1
2
  export * from "./lib/defaults/log-group";
2
3
  export * from "./lib/defaults/nodejs-function";
4
+ export * from "./lib/defaults/s3-bucket";
3
5
  export * from "./lib/defaults/step-functions";
4
6
  export * from "./lib/lambda-sfn-versioning";
5
7
  export * from "./lib/microservice-checks";
8
+ export * from "./lib/resource-prefix";
package/index.js CHANGED
@@ -14,9 +14,12 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./lib/defaults/dynamodb"), exports);
17
18
  __exportStar(require("./lib/defaults/log-group"), exports);
18
19
  __exportStar(require("./lib/defaults/nodejs-function"), exports);
20
+ __exportStar(require("./lib/defaults/s3-bucket"), exports);
19
21
  __exportStar(require("./lib/defaults/step-functions"), exports);
20
22
  __exportStar(require("./lib/lambda-sfn-versioning"), exports);
21
23
  __exportStar(require("./lib/microservice-checks"), exports);
22
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsMkRBQXlDO0FBQ3pDLGlFQUErQztBQUMvQyxnRUFBOEM7QUFDOUMsOERBQTRDO0FBQzVDLDREQUEwQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gXCIuL2xpYi9kZWZhdWx0cy9sb2ctZ3JvdXBcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2xpYi9kZWZhdWx0cy9ub2RlanMtZnVuY3Rpb25cIjtcbmV4cG9ydCAqIGZyb20gXCIuL2xpYi9kZWZhdWx0cy9zdGVwLWZ1bmN0aW9uc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vbGliL2xhbWJkYS1zZm4tdmVyc2lvbmluZ1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vbGliL21pY3Jvc2VydmljZS1jaGVja3NcIjtcbiJdfQ==
24
+ __exportStar(require("./lib/resource-prefix"), exports);
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJpbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsMERBQXdDO0FBQ3hDLDJEQUF5QztBQUN6QyxpRUFBK0M7QUFDL0MsMkRBQXlDO0FBQ3pDLGdFQUE4QztBQUM5Qyw4REFBNEM7QUFDNUMsNERBQTBDO0FBQzFDLHdEQUFzQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gXCIuL2xpYi9kZWZhdWx0cy9keW5hbW9kYlwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbGliL2RlZmF1bHRzL2xvZy1ncm91cFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbGliL2RlZmF1bHRzL25vZGVqcy1mdW5jdGlvblwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbGliL2RlZmF1bHRzL3MzLWJ1Y2tldFwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbGliL2RlZmF1bHRzL3N0ZXAtZnVuY3Rpb25zXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9saWIvbGFtYmRhLXNmbi12ZXJzaW9uaW5nXCI7XG5leHBvcnQgKiBmcm9tIFwiLi9saWIvbWljcm9zZXJ2aWNlLWNoZWNrc1wiO1xuZXhwb3J0ICogZnJvbSBcIi4vbGliL3Jlc291cmNlLXByZWZpeFwiO1xuIl19
@@ -0,0 +1,53 @@
1
+ import { type IAspect } from "aws-cdk-lib";
2
+ import { IConstruct } from "constructs";
3
+ interface Config {
4
+ duration: "SHORT" | "MEDIUM" | "LONG";
5
+ }
6
+ /**
7
+ * Aspect that automatically applies configuration-aware defaults to DynamoDB Tables
8
+ *
9
+ * Visits all constructs in the scope and automatically applies configuration-specific
10
+ * removal policies and point-in-time recovery settings to DynamoDB tables.
11
+ * Different configurations balance between cost optimization and data retention needs.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // Apply configuration-specific defaults to all tables
16
+ * Aspects.of(app).add(new DynamoDbDefaultsAspect({ duration: 'SHORT' }));
17
+ *
18
+ * // Tables automatically inherit configuration defaults
19
+ * new Table(stack, 'MyTable', {
20
+ * // point-in-time recovery and removal policy applied automatically
21
+ * });
22
+ * ```
23
+ *
24
+ * @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.Table.html
25
+ */
26
+ export declare class DynamoDbDefaultsAspect implements IAspect {
27
+ private readonly defaultProps;
28
+ /**
29
+ * Creates a new DynamoDbDefaultsAspect
30
+ *
31
+ * @param config - Configuration identifier used to select appropriate defaults.
32
+ */
33
+ constructor(config: Config);
34
+ /**
35
+ * Get duration-specific DynamoDB table properties
36
+ *
37
+ * @param duration - The duration to get the table properties for
38
+ * @returns The table properties for the duration
39
+ */
40
+ private retentionProperties;
41
+ private isProvisionedThroughputConfigured;
42
+ private isOnDemandThroughputConfigured;
43
+ /**
44
+ * Visits a construct and applies configuration-appropriate defaults
45
+ *
46
+ * Applies configuration-specific billing mode, throughput, point-in-time recovery,
47
+ * and removal policies to tables that don't already have these properties explicitly set.
48
+ *
49
+ * @param node - The construct to potentially modify
50
+ */
51
+ visit(node: IConstruct): void;
52
+ }
53
+ export {};
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DynamoDbDefaultsAspect = void 0;
4
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
5
+ const aws_dynamodb_1 = require("aws-cdk-lib/aws-dynamodb");
6
+ /**
7
+ * Aspect that automatically applies configuration-aware defaults to DynamoDB Tables
8
+ *
9
+ * Visits all constructs in the scope and automatically applies configuration-specific
10
+ * removal policies and point-in-time recovery settings to DynamoDB tables.
11
+ * Different configurations balance between cost optimization and data retention needs.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // Apply configuration-specific defaults to all tables
16
+ * Aspects.of(app).add(new DynamoDbDefaultsAspect({ duration: 'SHORT' }));
17
+ *
18
+ * // Tables automatically inherit configuration defaults
19
+ * new Table(stack, 'MyTable', {
20
+ * // point-in-time recovery and removal policy applied automatically
21
+ * });
22
+ * ```
23
+ *
24
+ * @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.Table.html
25
+ */
26
+ class DynamoDbDefaultsAspect {
27
+ /**
28
+ * Creates a new DynamoDbDefaultsAspect
29
+ *
30
+ * @param config - Configuration identifier used to select appropriate defaults.
31
+ */
32
+ constructor(config) {
33
+ this.defaultProps = this.retentionProperties(config.duration);
34
+ }
35
+ /**
36
+ * Get duration-specific DynamoDB table properties
37
+ *
38
+ * @param duration - The duration to get the table properties for
39
+ * @returns The table properties for the duration
40
+ */
41
+ retentionProperties(duration) {
42
+ switch (duration) {
43
+ case "SHORT":
44
+ return {
45
+ billingMode: aws_dynamodb_1.BillingMode.PROVISIONED,
46
+ readCapacity: 1,
47
+ writeCapacity: 1,
48
+ removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
49
+ };
50
+ case "MEDIUM":
51
+ return {
52
+ billingMode: aws_dynamodb_1.BillingMode.PAY_PER_REQUEST,
53
+ maxReadRequestUnits: 100,
54
+ maxWriteRequestUnits: 100,
55
+ removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
56
+ };
57
+ default:
58
+ return {
59
+ billingMode: aws_dynamodb_1.BillingMode.PAY_PER_REQUEST,
60
+ removalPolicy: aws_cdk_lib_1.RemovalPolicy.RETAIN,
61
+ };
62
+ }
63
+ }
64
+ isProvisionedThroughputConfigured() {
65
+ const { billingMode, readCapacity, writeCapacity } = this.defaultProps;
66
+ return (billingMode === aws_dynamodb_1.BillingMode.PROVISIONED &&
67
+ readCapacity !== undefined &&
68
+ writeCapacity !== undefined);
69
+ }
70
+ isOnDemandThroughputConfigured() {
71
+ const { billingMode, maxReadRequestUnits, maxWriteRequestUnits } = this.defaultProps;
72
+ return (billingMode === aws_dynamodb_1.BillingMode.PAY_PER_REQUEST &&
73
+ maxReadRequestUnits !== undefined &&
74
+ maxWriteRequestUnits !== undefined);
75
+ }
76
+ /**
77
+ * Visits a construct and applies configuration-appropriate defaults
78
+ *
79
+ * Applies configuration-specific billing mode, throughput, point-in-time recovery,
80
+ * and removal policies to tables that don't already have these properties explicitly set.
81
+ *
82
+ * @param node - The construct to potentially modify
83
+ */
84
+ visit(node) {
85
+ if (node instanceof aws_dynamodb_1.Table) {
86
+ const { billingMode, readCapacity, writeCapacity, maxReadRequestUnits, maxWriteRequestUnits, removalPolicy, } = this.defaultProps;
87
+ if (removalPolicy) {
88
+ node.applyRemovalPolicy(removalPolicy);
89
+ }
90
+ const cfnTable = node.node.defaultChild;
91
+ if (!cfnTable)
92
+ return;
93
+ if (cfnTable.billingMode === undefined) {
94
+ cfnTable.billingMode = billingMode;
95
+ }
96
+ if (cfnTable.provisionedThroughput === undefined &&
97
+ this.isProvisionedThroughputConfigured()) {
98
+ cfnTable.provisionedThroughput = {
99
+ readCapacityUnits: readCapacity,
100
+ writeCapacityUnits: writeCapacity,
101
+ };
102
+ }
103
+ if (cfnTable.onDemandThroughput === undefined &&
104
+ this.isOnDemandThroughputConfigured()) {
105
+ cfnTable.onDemandThroughput = {
106
+ maxReadRequestUnits,
107
+ maxWriteRequestUnits,
108
+ };
109
+ }
110
+ }
111
+ }
112
+ }
113
+ exports.DynamoDbDefaultsAspect = DynamoDbDefaultsAspect;
114
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1vZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJkeW5hbW9kYi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2Q0FBMEQ7QUFDMUQsMkRBS2tDO0FBT2xDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0gsTUFBYSxzQkFBc0I7SUFHakM7Ozs7T0FJRztJQUNILFlBQVksTUFBYztRQUN4QixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssbUJBQW1CLENBQ3pCLFFBQXFDO1FBRXJDLFFBQVEsUUFBUSxFQUFFLENBQUM7WUFDakIsS0FBSyxPQUFPO2dCQUNWLE9BQU87b0JBQ0wsV0FBVyxFQUFFLDBCQUFXLENBQUMsV0FBVztvQkFDcEMsWUFBWSxFQUFFLENBQUM7b0JBQ2YsYUFBYSxFQUFFLENBQUM7b0JBQ2hCLGFBQWEsRUFBRSwyQkFBYSxDQUFDLE9BQU87aUJBQ3JDLENBQUM7WUFDSixLQUFLLFFBQVE7Z0JBQ1gsT0FBTztvQkFDTCxXQUFXLEVBQUUsMEJBQVcsQ0FBQyxlQUFlO29CQUN4QyxtQkFBbUIsRUFBRSxHQUFHO29CQUN4QixvQkFBb0IsRUFBRSxHQUFHO29CQUN6QixhQUFhLEVBQUUsMkJBQWEsQ0FBQyxPQUFPO2lCQUNyQyxDQUFDO1lBQ0o7Z0JBQ0UsT0FBTztvQkFDTCxXQUFXLEVBQUUsMEJBQVcsQ0FBQyxlQUFlO29CQUN4QyxhQUFhLEVBQUUsMkJBQWEsQ0FBQyxNQUFNO2lCQUNwQyxDQUFDO1FBQ04sQ0FBQztJQUNILENBQUM7SUFFTyxpQ0FBaUM7UUFDdkMsTUFBTSxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQztRQUV2RSxPQUFPLENBQ0wsV0FBVyxLQUFLLDBCQUFXLENBQUMsV0FBVztZQUN2QyxZQUFZLEtBQUssU0FBUztZQUMxQixhQUFhLEtBQUssU0FBUyxDQUM1QixDQUFDO0lBQ0osQ0FBQztJQUVPLDhCQUE4QjtRQUNwQyxNQUFNLEVBQUUsV0FBVyxFQUFFLG1CQUFtQixFQUFFLG9CQUFvQixFQUFFLEdBQzlELElBQUksQ0FBQyxZQUFZLENBQUM7UUFFcEIsT0FBTyxDQUNMLFdBQVcsS0FBSywwQkFBVyxDQUFDLGVBQWU7WUFDM0MsbUJBQW1CLEtBQUssU0FBUztZQUNqQyxvQkFBb0IsS0FBSyxTQUFTLENBQ25DLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILEtBQUssQ0FBQyxJQUFnQjtRQUNwQixJQUFJLElBQUksWUFBWSxvQkFBSyxFQUFFLENBQUM7WUFDMUIsTUFBTSxFQUNKLFdBQVcsRUFDWCxZQUFZLEVBQ1osYUFBYSxFQUNiLG1CQUFtQixFQUNuQixvQkFBb0IsRUFDcEIsYUFBYSxHQUNkLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQztZQUV0QixJQUFJLGFBQWEsRUFBRSxDQUFDO2dCQUNsQixJQUFJLENBQUMsa0JBQWtCLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDekMsQ0FBQztZQUVELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBd0IsQ0FBQztZQUNwRCxJQUFJLENBQUMsUUFBUTtnQkFBRSxPQUFPO1lBRXRCLElBQUksUUFBUSxDQUFDLFdBQVcsS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDdkMsUUFBUSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7WUFDckMsQ0FBQztZQUVELElBQ0UsUUFBUSxDQUFDLHFCQUFxQixLQUFLLFNBQVM7Z0JBQzVDLElBQUksQ0FBQyxpQ0FBaUMsRUFBRSxFQUN4QyxDQUFDO2dCQUNELFFBQVEsQ0FBQyxxQkFBcUIsR0FBRztvQkFDL0IsaUJBQWlCLEVBQUUsWUFBYTtvQkFDaEMsa0JBQWtCLEVBQUUsYUFBYztpQkFDbkMsQ0FBQztZQUNKLENBQUM7WUFFRCxJQUNFLFFBQVEsQ0FBQyxrQkFBa0IsS0FBSyxTQUFTO2dCQUN6QyxJQUFJLENBQUMsOEJBQThCLEVBQUUsRUFDckMsQ0FBQztnQkFDRCxRQUFRLENBQUMsa0JBQWtCLEdBQUc7b0JBQzVCLG1CQUFtQjtvQkFDbkIsb0JBQW9CO2lCQUNyQixDQUFDO1lBQ0osQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUFwSEQsd0RBb0hDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUmVtb3ZhbFBvbGljeSwgdHlwZSBJQXNwZWN0IH0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQge1xuICBCaWxsaW5nTW9kZSxcbiAgQ2ZuVGFibGUsXG4gIFRhYmxlLFxuICB0eXBlIFRhYmxlUHJvcHMsXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZHluYW1vZGJcIjtcbmltcG9ydCB7IElDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuXG5pbnRlcmZhY2UgQ29uZmlnIHtcbiAgZHVyYXRpb246IFwiU0hPUlRcIiB8IFwiTUVESVVNXCIgfCBcIkxPTkdcIjtcbn1cblxuLyoqXG4gKiBBc3BlY3QgdGhhdCBhdXRvbWF0aWNhbGx5IGFwcGxpZXMgY29uZmlndXJhdGlvbi1hd2FyZSBkZWZhdWx0cyB0byBEeW5hbW9EQiBUYWJsZXNcbiAqXG4gKiBWaXNpdHMgYWxsIGNvbnN0cnVjdHMgaW4gdGhlIHNjb3BlIGFuZCBhdXRvbWF0aWNhbGx5IGFwcGxpZXMgY29uZmlndXJhdGlvbi1zcGVjaWZpY1xuICogcmVtb3ZhbCBwb2xpY2llcyBhbmQgcG9pbnQtaW4tdGltZSByZWNvdmVyeSBzZXR0aW5ncyB0byBEeW5hbW9EQiB0YWJsZXMuXG4gKiBEaWZmZXJlbnQgY29uZmlndXJhdGlvbnMgYmFsYW5jZSBiZXR3ZWVuIGNvc3Qgb3B0aW1pemF0aW9uIGFuZCBkYXRhIHJldGVudGlvbiBuZWVkcy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gQXBwbHkgY29uZmlndXJhdGlvbi1zcGVjaWZpYyBkZWZhdWx0cyB0byBhbGwgdGFibGVzXG4gKiBBc3BlY3RzLm9mKGFwcCkuYWRkKG5ldyBEeW5hbW9EYkRlZmF1bHRzQXNwZWN0KHsgZHVyYXRpb246ICdTSE9SVCcgfSkpO1xuICpcbiAqIC8vIFRhYmxlcyBhdXRvbWF0aWNhbGx5IGluaGVyaXQgY29uZmlndXJhdGlvbiBkZWZhdWx0c1xuICogbmV3IFRhYmxlKHN0YWNrLCAnTXlUYWJsZScsIHtcbiAqICAgLy8gcG9pbnQtaW4tdGltZSByZWNvdmVyeSBhbmQgcmVtb3ZhbCBwb2xpY3kgYXBwbGllZCBhdXRvbWF0aWNhbGx5XG4gKiB9KTtcbiAqIGBgYFxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2Nkay9hcGkvdjIvZG9jcy9hd3MtY2RrLWxpYi5hd3NfZHluYW1vZGIuVGFibGUuaHRtbFxuICovXG5leHBvcnQgY2xhc3MgRHluYW1vRGJEZWZhdWx0c0FzcGVjdCBpbXBsZW1lbnRzIElBc3BlY3Qge1xuICBwcml2YXRlIHJlYWRvbmx5IGRlZmF1bHRQcm9wczogVGFibGVQcm9wcztcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBEeW5hbW9EYkRlZmF1bHRzQXNwZWN0XG4gICAqXG4gICAqIEBwYXJhbSBjb25maWcgLSBDb25maWd1cmF0aW9uIGlkZW50aWZpZXIgdXNlZCB0byBzZWxlY3QgYXBwcm9wcmlhdGUgZGVmYXVsdHMuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihjb25maWc6IENvbmZpZykge1xuICAgIHRoaXMuZGVmYXVsdFByb3BzID0gdGhpcy5yZXRlbnRpb25Qcm9wZXJ0aWVzKGNvbmZpZy5kdXJhdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGR1cmF0aW9uLXNwZWNpZmljIER5bmFtb0RCIHRhYmxlIHByb3BlcnRpZXNcbiAgICpcbiAgICogQHBhcmFtIGR1cmF0aW9uIC0gVGhlIGR1cmF0aW9uIHRvIGdldCB0aGUgdGFibGUgcHJvcGVydGllcyBmb3JcbiAgICogQHJldHVybnMgVGhlIHRhYmxlIHByb3BlcnRpZXMgZm9yIHRoZSBkdXJhdGlvblxuICAgKi9cbiAgcHJpdmF0ZSByZXRlbnRpb25Qcm9wZXJ0aWVzKFxuICAgIGR1cmF0aW9uOiBcIlNIT1JUXCIgfCBcIk1FRElVTVwiIHwgXCJMT05HXCJcbiAgKTogVGFibGVQcm9wcyB7XG4gICAgc3dpdGNoIChkdXJhdGlvbikge1xuICAgICAgY2FzZSBcIlNIT1JUXCI6XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgYmlsbGluZ01vZGU6IEJpbGxpbmdNb2RlLlBST1ZJU0lPTkVELFxuICAgICAgICAgIHJlYWRDYXBhY2l0eTogMSxcbiAgICAgICAgICB3cml0ZUNhcGFjaXR5OiAxLFxuICAgICAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgICAgfTtcbiAgICAgIGNhc2UgXCJNRURJVU1cIjpcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBiaWxsaW5nTW9kZTogQmlsbGluZ01vZGUuUEFZX1BFUl9SRVFVRVNULFxuICAgICAgICAgIG1heFJlYWRSZXF1ZXN0VW5pdHM6IDEwMCxcbiAgICAgICAgICBtYXhXcml0ZVJlcXVlc3RVbml0czogMTAwLFxuICAgICAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgICAgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgYmlsbGluZ01vZGU6IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVCxcbiAgICAgICAgICByZW1vdmFsUG9saWN5OiBSZW1vdmFsUG9saWN5LlJFVEFJTixcbiAgICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGlzUHJvdmlzaW9uZWRUaHJvdWdocHV0Q29uZmlndXJlZCgpIHtcbiAgICBjb25zdCB7IGJpbGxpbmdNb2RlLCByZWFkQ2FwYWNpdHksIHdyaXRlQ2FwYWNpdHkgfSA9IHRoaXMuZGVmYXVsdFByb3BzO1xuXG4gICAgcmV0dXJuIChcbiAgICAgIGJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QUk9WSVNJT05FRCAmJlxuICAgICAgcmVhZENhcGFjaXR5ICE9PSB1bmRlZmluZWQgJiZcbiAgICAgIHdyaXRlQ2FwYWNpdHkgIT09IHVuZGVmaW5lZFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGlzT25EZW1hbmRUaHJvdWdocHV0Q29uZmlndXJlZCgpIHtcbiAgICBjb25zdCB7IGJpbGxpbmdNb2RlLCBtYXhSZWFkUmVxdWVzdFVuaXRzLCBtYXhXcml0ZVJlcXVlc3RVbml0cyB9ID1cbiAgICAgIHRoaXMuZGVmYXVsdFByb3BzO1xuXG4gICAgcmV0dXJuIChcbiAgICAgIGJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QgJiZcbiAgICAgIG1heFJlYWRSZXF1ZXN0VW5pdHMgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgbWF4V3JpdGVSZXF1ZXN0VW5pdHMgIT09IHVuZGVmaW5lZFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogVmlzaXRzIGEgY29uc3RydWN0IGFuZCBhcHBsaWVzIGNvbmZpZ3VyYXRpb24tYXBwcm9wcmlhdGUgZGVmYXVsdHNcbiAgICpcbiAgICogQXBwbGllcyBjb25maWd1cmF0aW9uLXNwZWNpZmljIGJpbGxpbmcgbW9kZSwgdGhyb3VnaHB1dCwgcG9pbnQtaW4tdGltZSByZWNvdmVyeSxcbiAgICogYW5kIHJlbW92YWwgcG9saWNpZXMgdG8gdGFibGVzIHRoYXQgZG9uJ3QgYWxyZWFkeSBoYXZlIHRoZXNlIHByb3BlcnRpZXMgZXhwbGljaXRseSBzZXQuXG4gICAqXG4gICAqIEBwYXJhbSBub2RlIC0gVGhlIGNvbnN0cnVjdCB0byBwb3RlbnRpYWxseSBtb2RpZnlcbiAgICovXG4gIHZpc2l0KG5vZGU6IElDb25zdHJ1Y3QpOiB2b2lkIHtcbiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIFRhYmxlKSB7XG4gICAgICBjb25zdCB7XG4gICAgICAgIGJpbGxpbmdNb2RlLFxuICAgICAgICByZWFkQ2FwYWNpdHksXG4gICAgICAgIHdyaXRlQ2FwYWNpdHksXG4gICAgICAgIG1heFJlYWRSZXF1ZXN0VW5pdHMsXG4gICAgICAgIG1heFdyaXRlUmVxdWVzdFVuaXRzLFxuICAgICAgICByZW1vdmFsUG9saWN5LFxuICAgICAgfSA9IHRoaXMuZGVmYXVsdFByb3BzO1xuXG4gICAgICBpZiAocmVtb3ZhbFBvbGljeSkge1xuICAgICAgICBub2RlLmFwcGx5UmVtb3ZhbFBvbGljeShyZW1vdmFsUG9saWN5KTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2ZuVGFibGUgPSBub2RlLm5vZGUuZGVmYXVsdENoaWxkIGFzIENmblRhYmxlO1xuICAgICAgaWYgKCFjZm5UYWJsZSkgcmV0dXJuO1xuXG4gICAgICBpZiAoY2ZuVGFibGUuYmlsbGluZ01vZGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjZm5UYWJsZS5iaWxsaW5nTW9kZSA9IGJpbGxpbmdNb2RlO1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgIGNmblRhYmxlLnByb3Zpc2lvbmVkVGhyb3VnaHB1dCA9PT0gdW5kZWZpbmVkICYmXG4gICAgICAgIHRoaXMuaXNQcm92aXNpb25lZFRocm91Z2hwdXRDb25maWd1cmVkKClcbiAgICAgICkge1xuICAgICAgICBjZm5UYWJsZS5wcm92aXNpb25lZFRocm91Z2hwdXQgPSB7XG4gICAgICAgICAgcmVhZENhcGFjaXR5VW5pdHM6IHJlYWRDYXBhY2l0eSEsXG4gICAgICAgICAgd3JpdGVDYXBhY2l0eVVuaXRzOiB3cml0ZUNhcGFjaXR5ISxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICBjZm5UYWJsZS5vbkRlbWFuZFRocm91Z2hwdXQgPT09IHVuZGVmaW5lZCAmJlxuICAgICAgICB0aGlzLmlzT25EZW1hbmRUaHJvdWdocHV0Q29uZmlndXJlZCgpXG4gICAgICApIHtcbiAgICAgICAgY2ZuVGFibGUub25EZW1hbmRUaHJvdWdocHV0ID0ge1xuICAgICAgICAgIG1heFJlYWRSZXF1ZXN0VW5pdHMsXG4gICAgICAgICAgbWF4V3JpdGVSZXF1ZXN0VW5pdHMsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=
@@ -0,0 +1,51 @@
1
+ import { type IAspect } from "aws-cdk-lib";
2
+ import { IConstruct } from "constructs";
3
+ interface Config {
4
+ duration: "SHORT" | "MEDIUM" | "LONG";
5
+ }
6
+ /**
7
+ * Aspect that automatically applies configuration-aware defaults to S3 Buckets
8
+ *
9
+ * Visits all constructs in the scope and automatically applies configuration-specific
10
+ * lifecycle and removal policies to S3 buckets. Different configurations balance
11
+ * between cost optimization and data retention needs.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // Apply configuration-specific defaults to all buckets
16
+ * Aspects.of(app).add(new S3DefaultsAspect({ autoDelete: true, duration: 'SHORT' }));
17
+ *
18
+ * // Buckets automatically inherit configuration defaults
19
+ * new Bucket(stack, 'MyBucket', {
20
+ * // lifecycle and removal policy applied automatically
21
+ * });
22
+ * ```
23
+ *
24
+ * @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html
25
+ */
26
+ export declare class S3DefaultsAspect implements IAspect {
27
+ private readonly defaultProps;
28
+ /**
29
+ * Creates a new S3DefaultsAspect
30
+ *
31
+ * @param config - Configuration identifier used to select appropriate defaults.
32
+ */
33
+ constructor(config: Config);
34
+ /**
35
+ * Get duration-specific object expiration
36
+ *
37
+ * @param duration - The duration to get the expiration for
38
+ * @returns The expiration Duration, or undefined for LONG retention
39
+ */
40
+ private retentionProperties;
41
+ /**
42
+ * Visits a construct and applies configuration-appropriate defaults
43
+ *
44
+ * Applies a removal policy and lifecycle rules to buckets that don't
45
+ * already have a lifecycle configuration explicitly set.
46
+ *
47
+ * @param node - The construct to potentially modify
48
+ */
49
+ visit(node: IConstruct): void;
50
+ }
51
+ export {};
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.S3DefaultsAspect = void 0;
4
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
5
+ const aws_s3_1 = require("aws-cdk-lib/aws-s3");
6
+ /**
7
+ * Aspect that automatically applies configuration-aware defaults to S3 Buckets
8
+ *
9
+ * Visits all constructs in the scope and automatically applies configuration-specific
10
+ * lifecycle and removal policies to S3 buckets. Different configurations balance
11
+ * between cost optimization and data retention needs.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // Apply configuration-specific defaults to all buckets
16
+ * Aspects.of(app).add(new S3DefaultsAspect({ autoDelete: true, duration: 'SHORT' }));
17
+ *
18
+ * // Buckets automatically inherit configuration defaults
19
+ * new Bucket(stack, 'MyBucket', {
20
+ * // lifecycle and removal policy applied automatically
21
+ * });
22
+ * ```
23
+ *
24
+ * @see https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html
25
+ */
26
+ class S3DefaultsAspect {
27
+ /**
28
+ * Creates a new S3DefaultsAspect
29
+ *
30
+ * @param config - Configuration identifier used to select appropriate defaults.
31
+ */
32
+ constructor(config) {
33
+ const props = this.retentionProperties(config.duration);
34
+ this.defaultProps = { ...props };
35
+ }
36
+ /**
37
+ * Get duration-specific object expiration
38
+ *
39
+ * @param duration - The duration to get the expiration for
40
+ * @returns The expiration Duration, or undefined for LONG retention
41
+ */
42
+ retentionProperties(duration) {
43
+ switch (duration) {
44
+ case "SHORT":
45
+ return {
46
+ lifecycleRules: [{ expiration: aws_cdk_lib_1.Duration.days(30) }],
47
+ removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
48
+ };
49
+ case "MEDIUM":
50
+ return {
51
+ lifecycleRules: [{ expiration: aws_cdk_lib_1.Duration.days(90) }],
52
+ removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY,
53
+ };
54
+ default:
55
+ return {
56
+ lifecycleRules: [],
57
+ removalPolicy: aws_cdk_lib_1.RemovalPolicy.RETAIN,
58
+ };
59
+ }
60
+ }
61
+ /**
62
+ * Visits a construct and applies configuration-appropriate defaults
63
+ *
64
+ * Applies a removal policy and lifecycle rules to buckets that don't
65
+ * already have a lifecycle configuration explicitly set.
66
+ *
67
+ * @param node - The construct to potentially modify
68
+ */
69
+ visit(node) {
70
+ if (node instanceof aws_s3_1.Bucket) {
71
+ const { lifecycleRules, removalPolicy } = this.defaultProps;
72
+ if (removalPolicy) {
73
+ node.applyRemovalPolicy(removalPolicy);
74
+ }
75
+ if (lifecycleRules === null || lifecycleRules === void 0 ? void 0 : lifecycleRules.length) {
76
+ const cfnBucket = node.node.defaultChild;
77
+ if (cfnBucket && cfnBucket.lifecycleConfiguration === undefined) {
78
+ lifecycleRules.forEach(rule => node.addLifecycleRule(rule));
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
84
+ exports.S3DefaultsAspect = S3DefaultsAspect;
85
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiczMtYnVja2V0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiczMtYnVja2V0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZDQUFvRTtBQUNwRSwrQ0FBeUU7QUFPekU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQkc7QUFDSCxNQUFhLGdCQUFnQjtJQUczQjs7OztPQUlHO0lBQ0gsWUFBWSxNQUFjO1FBQ3hCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDeEQsSUFBSSxDQUFDLFlBQVksR0FBRyxFQUFFLEdBQUcsS0FBSyxFQUFFLENBQUM7SUFDbkMsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ssbUJBQW1CLENBQUMsUUFBcUM7UUFDL0QsUUFBUSxRQUFRLEVBQUUsQ0FBQztZQUNqQixLQUFLLE9BQU87Z0JBQ1YsT0FBTztvQkFDTCxjQUFjLEVBQUUsQ0FBQyxFQUFFLFVBQVUsRUFBRSxzQkFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO29CQUNuRCxhQUFhLEVBQUUsMkJBQWEsQ0FBQyxPQUFPO2lCQUNyQyxDQUFDO1lBQ0osS0FBSyxRQUFRO2dCQUNYLE9BQU87b0JBQ0wsY0FBYyxFQUFFLENBQUMsRUFBRSxVQUFVLEVBQUUsc0JBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztvQkFDbkQsYUFBYSxFQUFFLDJCQUFhLENBQUMsT0FBTztpQkFDckMsQ0FBQztZQUNKO2dCQUNFLE9BQU87b0JBQ0wsY0FBYyxFQUFFLEVBQUU7b0JBQ2xCLGFBQWEsRUFBRSwyQkFBYSxDQUFDLE1BQU07aUJBQ3BDLENBQUM7UUFDTixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxLQUFLLENBQUMsSUFBZ0I7UUFDcEIsSUFBSSxJQUFJLFlBQVksZUFBTSxFQUFFLENBQUM7WUFDM0IsTUFBTSxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO1lBQzVELElBQUksYUFBYSxFQUFFLENBQUM7Z0JBQ2xCLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUN6QyxDQUFDO1lBRUQsSUFBSSxjQUFjLGFBQWQsY0FBYyx1QkFBZCxjQUFjLENBQUUsTUFBTSxFQUFFLENBQUM7Z0JBQzNCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBeUIsQ0FBQztnQkFDdEQsSUFBSSxTQUFTLElBQUksU0FBUyxDQUFDLHNCQUFzQixLQUFLLFNBQVMsRUFBRSxDQUFDO29CQUNoRSxjQUFjLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQzlELENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7Q0FDRjtBQTlERCw0Q0E4REMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEdXJhdGlvbiwgUmVtb3ZhbFBvbGljeSwgdHlwZSBJQXNwZWN0IH0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQgeyBCdWNrZXQsIENmbkJ1Y2tldCwgdHlwZSBCdWNrZXRQcm9wcyB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtczNcIjtcbmltcG9ydCB7IElDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuXG5pbnRlcmZhY2UgQ29uZmlnIHtcbiAgZHVyYXRpb246IFwiU0hPUlRcIiB8IFwiTUVESVVNXCIgfCBcIkxPTkdcIjtcbn1cblxuLyoqXG4gKiBBc3BlY3QgdGhhdCBhdXRvbWF0aWNhbGx5IGFwcGxpZXMgY29uZmlndXJhdGlvbi1hd2FyZSBkZWZhdWx0cyB0byBTMyBCdWNrZXRzXG4gKlxuICogVmlzaXRzIGFsbCBjb25zdHJ1Y3RzIGluIHRoZSBzY29wZSBhbmQgYXV0b21hdGljYWxseSBhcHBsaWVzIGNvbmZpZ3VyYXRpb24tc3BlY2lmaWNcbiAqIGxpZmVjeWNsZSBhbmQgcmVtb3ZhbCBwb2xpY2llcyB0byBTMyBidWNrZXRzLiBEaWZmZXJlbnQgY29uZmlndXJhdGlvbnMgYmFsYW5jZVxuICogYmV0d2VlbiBjb3N0IG9wdGltaXphdGlvbiBhbmQgZGF0YSByZXRlbnRpb24gbmVlZHMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEFwcGx5IGNvbmZpZ3VyYXRpb24tc3BlY2lmaWMgZGVmYXVsdHMgdG8gYWxsIGJ1Y2tldHNcbiAqIEFzcGVjdHMub2YoYXBwKS5hZGQobmV3IFMzRGVmYXVsdHNBc3BlY3QoeyBhdXRvRGVsZXRlOiB0cnVlLCBkdXJhdGlvbjogJ1NIT1JUJyB9KSk7XG4gKlxuICogLy8gQnVja2V0cyBhdXRvbWF0aWNhbGx5IGluaGVyaXQgY29uZmlndXJhdGlvbiBkZWZhdWx0c1xuICogbmV3IEJ1Y2tldChzdGFjaywgJ015QnVja2V0Jywge1xuICogICAvLyBsaWZlY3ljbGUgYW5kIHJlbW92YWwgcG9saWN5IGFwcGxpZWQgYXV0b21hdGljYWxseVxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9jZGsvYXBpL3YyL2RvY3MvYXdzLWNkay1saWIuYXdzX3MzLkJ1Y2tldC5odG1sXG4gKi9cbmV4cG9ydCBjbGFzcyBTM0RlZmF1bHRzQXNwZWN0IGltcGxlbWVudHMgSUFzcGVjdCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdFByb3BzOiBCdWNrZXRQcm9wcztcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBTM0RlZmF1bHRzQXNwZWN0XG4gICAqXG4gICAqIEBwYXJhbSBjb25maWcgLSBDb25maWd1cmF0aW9uIGlkZW50aWZpZXIgdXNlZCB0byBzZWxlY3QgYXBwcm9wcmlhdGUgZGVmYXVsdHMuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihjb25maWc6IENvbmZpZykge1xuICAgIGNvbnN0IHByb3BzID0gdGhpcy5yZXRlbnRpb25Qcm9wZXJ0aWVzKGNvbmZpZy5kdXJhdGlvbik7XG4gICAgdGhpcy5kZWZhdWx0UHJvcHMgPSB7IC4uLnByb3BzIH07XG4gIH1cblxuICAvKipcbiAgICogR2V0IGR1cmF0aW9uLXNwZWNpZmljIG9iamVjdCBleHBpcmF0aW9uXG4gICAqXG4gICAqIEBwYXJhbSBkdXJhdGlvbiAtIFRoZSBkdXJhdGlvbiB0byBnZXQgdGhlIGV4cGlyYXRpb24gZm9yXG4gICAqIEByZXR1cm5zIFRoZSBleHBpcmF0aW9uIER1cmF0aW9uLCBvciB1bmRlZmluZWQgZm9yIExPTkcgcmV0ZW50aW9uXG4gICAqL1xuICBwcml2YXRlIHJldGVudGlvblByb3BlcnRpZXMoZHVyYXRpb246IFwiU0hPUlRcIiB8IFwiTUVESVVNXCIgfCBcIkxPTkdcIikge1xuICAgIHN3aXRjaCAoZHVyYXRpb24pIHtcbiAgICAgIGNhc2UgXCJTSE9SVFwiOlxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGxpZmVjeWNsZVJ1bGVzOiBbeyBleHBpcmF0aW9uOiBEdXJhdGlvbi5kYXlzKDMwKSB9XSxcbiAgICAgICAgICByZW1vdmFsUG9saWN5OiBSZW1vdmFsUG9saWN5LkRFU1RST1ksXG4gICAgICAgIH07XG4gICAgICBjYXNlIFwiTUVESVVNXCI6XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbGlmZWN5Y2xlUnVsZXM6IFt7IGV4cGlyYXRpb246IER1cmF0aW9uLmRheXMoOTApIH1dLFxuICAgICAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgICAgfTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbGlmZWN5Y2xlUnVsZXM6IFtdLFxuICAgICAgICAgIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuUkVUQUlOLFxuICAgICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBWaXNpdHMgYSBjb25zdHJ1Y3QgYW5kIGFwcGxpZXMgY29uZmlndXJhdGlvbi1hcHByb3ByaWF0ZSBkZWZhdWx0c1xuICAgKlxuICAgKiBBcHBsaWVzIGEgcmVtb3ZhbCBwb2xpY3kgYW5kIGxpZmVjeWNsZSBydWxlcyB0byBidWNrZXRzIHRoYXQgZG9uJ3RcbiAgICogYWxyZWFkeSBoYXZlIGEgbGlmZWN5Y2xlIGNvbmZpZ3VyYXRpb24gZXhwbGljaXRseSBzZXQuXG4gICAqXG4gICAqIEBwYXJhbSBub2RlIC0gVGhlIGNvbnN0cnVjdCB0byBwb3RlbnRpYWxseSBtb2RpZnlcbiAgICovXG4gIHZpc2l0KG5vZGU6IElDb25zdHJ1Y3QpOiB2b2lkIHtcbiAgICBpZiAobm9kZSBpbnN0YW5jZW9mIEJ1Y2tldCkge1xuICAgICAgY29uc3QgeyBsaWZlY3ljbGVSdWxlcywgcmVtb3ZhbFBvbGljeSB9ID0gdGhpcy5kZWZhdWx0UHJvcHM7XG4gICAgICBpZiAocmVtb3ZhbFBvbGljeSkge1xuICAgICAgICBub2RlLmFwcGx5UmVtb3ZhbFBvbGljeShyZW1vdmFsUG9saWN5KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGxpZmVjeWNsZVJ1bGVzPy5sZW5ndGgpIHtcbiAgICAgICAgY29uc3QgY2ZuQnVja2V0ID0gbm9kZS5ub2RlLmRlZmF1bHRDaGlsZCBhcyBDZm5CdWNrZXQ7XG4gICAgICAgIGlmIChjZm5CdWNrZXQgJiYgY2ZuQnVja2V0LmxpZmVjeWNsZUNvbmZpZ3VyYXRpb24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGxpZmVjeWNsZVJ1bGVzLmZvckVhY2gocnVsZSA9PiBub2RlLmFkZExpZmVjeWNsZVJ1bGUocnVsZSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=
@@ -0,0 +1,68 @@
1
+ import { IAspect } from "aws-cdk-lib";
2
+ import { IConstruct } from "constructs";
3
+ export interface ResourcePrefixAspectProps {
4
+ /**
5
+ * The prefix to apply to all resource names.
6
+ * e.g. 'myapp-prod' → 'myapp-prod-orders'
7
+ */
8
+ prefix: string;
9
+ /**
10
+ * Resource types to skip entirely.
11
+ * e.g. ['AWS::IAM::Role'] to leave IAM role names untouched.
12
+ * @default []
13
+ */
14
+ exclude?: string[];
15
+ }
16
+ /**
17
+ * CDK Aspect that automatically prefixes physical resource names across AWS resources.
18
+ *
19
+ * @remarks
20
+ * **Critical Implementation Notes:**
21
+ *
22
+ * 1. **Stage Synthesis Boundaries**:
23
+ * - CDK `Stage` constructs create synthesis boundaries that prevent App-level aspects
24
+ * from traversing into them
25
+ * - This aspect MUST be applied to each Stage individually, not to the App
26
+ * - Example: `Aspects.of(stage).add(new ResourcePrefixAspect({...}))`
27
+ *
28
+ * 2. **Property Name Casing**:
29
+ * - CloudFormation properties use PascalCase (e.g., `FunctionName`, `BucketName`)
30
+ * - Using camelCase (e.g., `functionName`) will cause errors with versioning aspects
31
+ * - When using `addPropertyOverride()`, always use the exact CloudFormation property name
32
+ *
33
+ * 3. **Aspect Priority with Versioning**:
34
+ * - When combining with LambdaAndStepFunctionVersioningAspect, apply this aspect BEFORE versioning
35
+ * - Use CDK's priority system: `Aspects.of(stage).add(prefixAspect, { priority: 100 })`
36
+ * - Then: `Aspects.of(stage).add(versioningAspect, { priority: 200 })`
37
+ * - Lower priority numbers run first
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // Correct usage with staging
42
+ * const stage = new ApplicationStage(app, 'prod');
43
+ * Aspects.of(stage).add(new ResourcePrefixAspect({ prefix: 'myapp' }), { priority: 100 });
44
+ * Aspects.of(stage).add(new LambdaAndStepFunctionVersioningAspect(), { priority: 200 });
45
+ * ```
46
+ */
47
+ export declare class ResourcePrefixAspect implements IAspect {
48
+ private readonly prefix;
49
+ private readonly exclude;
50
+ constructor(props: ResourcePrefixAspectProps);
51
+ visit(node: IConstruct): void;
52
+ private isAlreadyPrefixed;
53
+ private deriveNameFromLogicalId;
54
+ /**
55
+ * Builds the prefixed name, handling special cases for specific resource types.
56
+ *
57
+ * @param baseName - The base resource name (without prefix)
58
+ * @param cfnResourceType - The CloudFormation resource type
59
+ * @param cfnProperties - The CloudFormation resource properties
60
+ * @returns The final prefixed name with any special case handling applied
61
+ */
62
+ private buildPrefixedName;
63
+ /**
64
+ * Validates resource-specific naming requirements that AWS enforces.
65
+ * Throws synthesis errors for violations.
66
+ */
67
+ private validateResourceName;
68
+ }
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ResourcePrefixAspect = void 0;
4
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
5
+ /**
6
+ * Maps CloudFormation resource types to their name property and AWS length limits.
7
+ * Sources: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html
8
+ */
9
+ const RESOURCE_CONFIG = {
10
+ // Compute
11
+ "AWS::Lambda::Function": { cfnName: "FunctionName", maxLength: 64 },
12
+ // Storage
13
+ "AWS::S3::Bucket": { cfnName: "BucketName", maxLength: 63 },
14
+ "AWS::DynamoDB::Table": { cfnName: "TableName", maxLength: 255 },
15
+ "AWS::DynamoDB::GlobalTable": { cfnName: "TableName", maxLength: 255 },
16
+ // Messaging
17
+ "AWS::SQS::Queue": { cfnName: "QueueName", maxLength: 80 },
18
+ "AWS::SNS::Topic": { cfnName: "TopicName", maxLength: 256 },
19
+ // Eventing & Orchestration
20
+ "AWS::Events::EventBus": { cfnName: "Name", maxLength: 256 },
21
+ "AWS::Events::Rule": { cfnName: "Name", maxLength: 64 },
22
+ "AWS::Events::Connection": { cfnName: "Name", maxLength: 64 },
23
+ "AWS::Pipes::Pipe": { cfnName: "Name", maxLength: 64 },
24
+ "AWS::StepFunctions::StateMachine": {
25
+ cfnName: "StateMachineName",
26
+ maxLength: 80,
27
+ },
28
+ "AWS::StepFunctions::Activity": { cfnName: "Name", maxLength: 80 },
29
+ "AWS::Scheduler::Schedule": { cfnName: "Name", maxLength: 64 },
30
+ "AWS::Scheduler::ScheduleGroup": { cfnName: "Name", maxLength: 64 },
31
+ // API
32
+ "AWS::ApiGateway::RestApi": { cfnName: "Name", maxLength: 128 },
33
+ "AWS::ApiGateway::UsagePlan": { cfnName: "UsagePlanName", maxLength: 128 },
34
+ "AWS::ApiGateway::ApiKey": { cfnName: "Name", maxLength: 128 },
35
+ "AWS::ApiGatewayV2::Api": { cfnName: "Name", maxLength: 128 },
36
+ "AWS::ApiGatewayV2::Authorizer": { cfnName: "Name", maxLength: 128 },
37
+ // Secrets & Config
38
+ "AWS::SecretsManager::Secret": { cfnName: "Name", maxLength: 512 },
39
+ "AWS::SSM::Parameter": { cfnName: "Name", maxLength: 2048 },
40
+ "AWS::AppConfig::Application": { cfnName: "Name", maxLength: 64 },
41
+ "AWS::AppConfig::Environment": { cfnName: "Name", maxLength: 64 },
42
+ // Notifications
43
+ "AWS::Notifications::NotificationConfiguration": {
44
+ cfnName: "Name",
45
+ maxLength: 64,
46
+ },
47
+ // Observability
48
+ "AWS::Logs::LogGroup": { cfnName: "LogGroupName", maxLength: 512 },
49
+ "AWS::CloudWatch::Alarm": { cfnName: "AlarmName", maxLength: 255 },
50
+ // IAM
51
+ "AWS::IAM::Role": { cfnName: "RoleName", maxLength: 64 },
52
+ };
53
+ /**
54
+ * CDK Aspect that automatically prefixes physical resource names across AWS resources.
55
+ *
56
+ * @remarks
57
+ * **Critical Implementation Notes:**
58
+ *
59
+ * 1. **Stage Synthesis Boundaries**:
60
+ * - CDK `Stage` constructs create synthesis boundaries that prevent App-level aspects
61
+ * from traversing into them
62
+ * - This aspect MUST be applied to each Stage individually, not to the App
63
+ * - Example: `Aspects.of(stage).add(new ResourcePrefixAspect({...}))`
64
+ *
65
+ * 2. **Property Name Casing**:
66
+ * - CloudFormation properties use PascalCase (e.g., `FunctionName`, `BucketName`)
67
+ * - Using camelCase (e.g., `functionName`) will cause errors with versioning aspects
68
+ * - When using `addPropertyOverride()`, always use the exact CloudFormation property name
69
+ *
70
+ * 3. **Aspect Priority with Versioning**:
71
+ * - When combining with LambdaAndStepFunctionVersioningAspect, apply this aspect BEFORE versioning
72
+ * - Use CDK's priority system: `Aspects.of(stage).add(prefixAspect, { priority: 100 })`
73
+ * - Then: `Aspects.of(stage).add(versioningAspect, { priority: 200 })`
74
+ * - Lower priority numbers run first
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * // Correct usage with staging
79
+ * const stage = new ApplicationStage(app, 'prod');
80
+ * Aspects.of(stage).add(new ResourcePrefixAspect({ prefix: 'myapp' }), { priority: 100 });
81
+ * Aspects.of(stage).add(new LambdaAndStepFunctionVersioningAspect(), { priority: 200 });
82
+ * ```
83
+ */
84
+ class ResourcePrefixAspect {
85
+ constructor(props) {
86
+ var _a;
87
+ if (!props.prefix || !/^[a-z0-9-]+$/.test(props.prefix))
88
+ throw new Error(`ResourcePrefixAspect: prefix must contain only lowercase alphanumeric characters and hyphens, got "${props.prefix}"`);
89
+ this.prefix = props.prefix;
90
+ this.exclude = new Set((_a = props.exclude) !== null && _a !== void 0 ? _a : []);
91
+ }
92
+ visit(node) {
93
+ var _a, _b;
94
+ if (!(node instanceof aws_cdk_lib_1.CfnResource))
95
+ return;
96
+ const resourceType = node.cfnResourceType;
97
+ const config = RESOURCE_CONFIG[resourceType];
98
+ if (!config || this.exclude.has(resourceType)) {
99
+ return;
100
+ }
101
+ const { cfnName, maxLength } = config;
102
+ const cfnProperties = (_b = (_a = node._cfnProperties) !== null && _a !== void 0 ? _a : node.cfnProperties) !== null && _b !== void 0 ? _b : {};
103
+ // Get any explicitly set name, or derive one from the logical ID
104
+ const existingName = typeof cfnProperties[cfnName] === "string"
105
+ ? cfnProperties[cfnName]
106
+ : undefined;
107
+ const baseName = existingName !== null && existingName !== void 0 ? existingName : this.deriveNameFromLogicalId(node);
108
+ if (this.isAlreadyPrefixed(baseName)) {
109
+ return;
110
+ }
111
+ const finalName = this.buildPrefixedName(baseName, resourceType, cfnProperties);
112
+ const hasError = this.validateResourceName(finalName, resourceType, maxLength, node);
113
+ if (hasError)
114
+ return;
115
+ node.addPropertyOverride(cfnName, finalName);
116
+ }
117
+ isAlreadyPrefixed(name) {
118
+ return (name.startsWith(`${this.prefix}-`) || name.startsWith(`/${this.prefix}/`));
119
+ }
120
+ deriveNameFromLogicalId(node) {
121
+ const logicalId = aws_cdk_lib_1.Stack.of(node).getLogicalId(node);
122
+ return logicalId
123
+ .replace(/[^a-zA-Z0-9]+/g, "-") // non-alphanumeric → dash
124
+ .replace(/^-+|-+$/g, ""); // trim leading/trailing dashes
125
+ }
126
+ /**
127
+ * Builds the prefixed name, handling special cases for specific resource types.
128
+ *
129
+ * @param baseName - The base resource name (without prefix)
130
+ * @param cfnResourceType - The CloudFormation resource type
131
+ * @param cfnProperties - The CloudFormation resource properties
132
+ * @returns The final prefixed name with any special case handling applied
133
+ */
134
+ buildPrefixedName(baseName, cfnResourceType, cfnProperties) {
135
+ // Special case: FIFO queues must end with .fifo suffix
136
+ if (cfnResourceType === "AWS::SQS::Queue" &&
137
+ cfnProperties.fifoQueue === true &&
138
+ !baseName.endsWith(".fifo")) {
139
+ return `${this.prefix}-${baseName}.fifo`;
140
+ }
141
+ // Special case: FIFO topics must end with .fifo suffix
142
+ if (cfnResourceType === "AWS::SNS::Topic" &&
143
+ cfnProperties.fifoTopic === true &&
144
+ !baseName.endsWith(".fifo")) {
145
+ return `${this.prefix}-${baseName}.fifo`;
146
+ }
147
+ // Special case: SSM parameter names use path-style prefix
148
+ if (cfnResourceType === "AWS::SSM::Parameter") {
149
+ return `/${this.prefix}/${baseName}`;
150
+ }
151
+ // Special case: S3 bucket name be lowercase only
152
+ if (cfnResourceType === "AWS::S3::Bucket") {
153
+ return `${this.prefix}-${baseName}`.toLowerCase();
154
+ }
155
+ // Default: simple prefix
156
+ return `${this.prefix}-${baseName}`;
157
+ }
158
+ /**
159
+ * Validates resource-specific naming requirements that AWS enforces.
160
+ * Throws synthesis errors for violations.
161
+ */
162
+ validateResourceName(name, cfnResourceType, maxLength, node) {
163
+ let hasError = false;
164
+ // S3 bucket names cannot contain underscores
165
+ if (cfnResourceType === "AWS::S3::Bucket") {
166
+ if (name !== name.toLowerCase()) {
167
+ aws_cdk_lib_1.Annotations.of(node).addError(`[ResourcePrefixAspect] S3 bucket name "${name}" contains uppercase letters. ` +
168
+ `Bucket names must be lowercase only.`);
169
+ hasError = true;
170
+ }
171
+ if (name.includes("_")) {
172
+ aws_cdk_lib_1.Annotations.of(node).addError(`[ResourcePrefixAspect] S3 bucket name "${name}" contains underscores. ` +
173
+ `Bucket names cannot contain underscores. Use hyphens instead.`);
174
+ hasError = true;
175
+ }
176
+ }
177
+ if (name.length > maxLength) {
178
+ aws_cdk_lib_1.Annotations.of(node).addError(`[ResourcePrefixAspect] "${name}" (${name.length} chars) exceeds the ` +
179
+ `maximum allowed length of ${maxLength} for ${cfnResourceType}. ` +
180
+ `Shorten the resource base name or your prefix ("${this.prefix}").`);
181
+ hasError = true;
182
+ }
183
+ return hasError;
184
+ }
185
+ }
186
+ exports.ResourcePrefixAspect = ResourcePrefixAspect;
187
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UtcHJlZml4LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicmVzb3VyY2UtcHJlZml4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZDQUF1RTtBQWdDdkU7OztHQUdHO0FBQ0gsTUFBTSxlQUFlLEdBQXVDO0lBQzFELFVBQVU7SUFDVix1QkFBdUIsRUFBRSxFQUFFLE9BQU8sRUFBRSxjQUFjLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRTtJQUVuRSxVQUFVO0lBQ1YsaUJBQWlCLEVBQUUsRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUU7SUFDM0Qsc0JBQXNCLEVBQUUsRUFBRSxPQUFPLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUU7SUFDaEUsNEJBQTRCLEVBQUUsRUFBRSxPQUFPLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUU7SUFFdEUsWUFBWTtJQUNaLGlCQUFpQixFQUFFLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFO0lBQzFELGlCQUFpQixFQUFFLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFO0lBRTNELDJCQUEyQjtJQUMzQix1QkFBdUIsRUFBRSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRTtJQUM1RCxtQkFBbUIsRUFBRSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRTtJQUN2RCx5QkFBeUIsRUFBRSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRTtJQUM3RCxrQkFBa0IsRUFBRSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRTtJQUN0RCxrQ0FBa0MsRUFBRTtRQUNsQyxPQUFPLEVBQUUsa0JBQWtCO1FBQzNCLFNBQVMsRUFBRSxFQUFFO0tB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aEIsSUFBSSxRQUFRLEdBQUcsS0FBSyxDQUFDO1FBRXJCLDZDQUE2QztRQUM3QyxJQUFJLGVBQWUsS0FBSyxpQkFBaUIsRUFBRSxDQUFDO1lBQzFDLElBQUksSUFBSSxLQUFLLElBQUksQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDO2dCQUNoQyx5QkFBVyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxRQUFRLENBQzNCLDBDQUEwQyxJQUFJLGdDQUFnQztvQkFDNUUsc0NBQXNDLENBQ3pDLENBQUM7Z0JBQ0YsUUFBUSxHQUFHLElBQUksQ0FBQztZQUNsQixDQUFDO1lBRUQsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ3ZCLHlCQUFXLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FDM0IsMENBQTBDLElBQUksMEJBQTBCO29CQUN0RSwrREFBK0QsQ0FDbEUsQ0FBQztnQkFDRixRQUFRLEdBQUcsSUFBSSxDQUFDO1lBQ2xCLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsTUFBTSxHQUFHLFNBQVMsRUFBRSxDQUFDO1lBQzVCLHlCQUFXLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FDM0IsMkJBQTJCLElBQUksTUFBTSxJQUFJLENBQUMsTUFBTSxzQkFBc0I7Z0JBQ3BFLDZCQUE2QixTQUFTLFFBQVEsZUFBZSxJQUFJO2dCQUNqRSxtREFBbUQsSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUN0RSxDQUFDO1lBQ0YsUUFBUSxHQUFHLElBQUksQ0FBQztRQUNsQixDQUFDO1FBRUQsT0FBTyxRQUFRLENBQUM7SUFDbEIsQ0FBQztDQUNGO0FBL0pELG9EQStKQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFubm90YXRpb25zLCBDZm5SZXNvdXJjZSwgSUFzcGVjdCwgU3RhY2sgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7IElDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuXG5pbnRlcmZhY2UgUmVzb3VyY2VOYW1lQ29uZmlnIHtcbiAgLyoqIFRoZSBDbG91ZEZvcm1hdGlvbiBwcm9wZXJ0eSB0aGF0IGhvbGRzIHRoZSByZXNvdXJjZSdzIHBoeXNpY2FsIG5hbWUgKi9cbiAgY2ZuTmFtZTogc3RyaW5nO1xuICAvKiogTWF4aW11bSBhbGxvd2VkIGNoYXJhY3RlciBsZW5ndGggZm9yIHRoaXMgcmVzb3VyY2UgdHlwZSAqL1xuICBtYXhMZW5ndGg6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBFeHRlbnNpb24gdHlwZSB0byBhY2Nlc3MgaW50ZXJuYWwgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyBvbiBDZm5SZXNvdXJjZS5cbiAqXG4gKiBDREsgZG9lcyBub3QgcHJvdmlkZSBhIHB1YmxpYyBBUEkgdG8gcmVhZCByYXcgQ2xvdWRGb3JtYXRpb24gcHJvcGVydGllcyB0aGF0IGhhdmVcbiAqIGJlZW4gc2V0IG9uIGEgQ2ZuUmVzb3VyY2UuIFRoZSBwcm9wZXJ0aWVzIGBfY2ZuUHJvcGVydGllc2AgYW5kIGBjZm5Qcm9wZXJ0aWVzYCBhcmVcbiAqIHByb3RlY3RlZCBhbmQgb25seSBhY2Nlc3NpYmxlIHdpdGhpbiB0aGUgQ2ZuUmVzb3VyY2UgY2xhc3MgaGllcmFyY2h5LlxuICpcbiAqIFdlIGludmVzdGlnYXRlZCB1c2luZyBDREsncyBwdWJsaWMgQVBJcywgYnV0IHRoZXJlIGlzIG5vIHB1YmxpYyBtZXRob2QgdG8gcmV0cmlldmVcbiAqIHRoZSByYXcgcHJvcGVydHkgdmFsdWVzIHRoYXQgaGF2ZSBiZWVuIHNldCAoZS5nLiwgdmlhIGNvbnN0cnVjdG9yIHByb3BzIG9yIGFkZFByb3BlcnR5T3ZlcnJpZGUpLlxuICogVGhlIG9ubHkgcHVibGljIEFQSXMgYXJlIGZvciB3cml0aW5nIChhZGRQcm9wZXJ0eU92ZXJyaWRlLCBhZGRQcm9wZXJ0eURlbGV0aW9uT3ZlcnJpZGUpIG9yXG4gKiBnZXR0aW5nIGF0dHJpYnV0ZSByZWZlcmVuY2VzIChnZXRBdHQpLCBub3QgZm9yIHJlYWRpbmcgbGl0ZXJhbCBwcm9wZXJ0eSB2YWx1ZXMuXG4gKlxuICogVGhpcyB0eXBlIGFzc2VydGlvbiBpcyBzYWZlIGJlY2F1c2U6XG4gKiAtIFdlIG9ubHkgcmVhZCB0aGVzZSBwcm9wZXJ0aWVzLCBuZXZlciBtb2RpZnkgdGhlbVxuICogLSBXZSBuZWVkIHRvIGNoZWNrIGlmIGEgdXNlciBleHBsaWNpdGx5IHNldCBhIG5hbWUgcHJvcGVydHkgYmVmb3JlIGFwcGx5aW5nIG91ciBwcmVmaXhcbiAqIC0gVGhlIHByb3BlcnRpZXMgZXhpc3QgYXQgcnVudGltZSBhbmQgYXJlIHBhcnQgb2YgQ0RLJ3MgaW50ZXJuYWwgaW1wbGVtZW50YXRpb25cbiAqL1xudHlwZSBDZm5SZXNvdXJjZVdpdGhQcm9wcyA9IENmblJlc291cmNlICYge1xuICByZWFkb25seSBfY2ZuUHJvcGVydGllcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICByZWFkb25seSBjZm5Qcm9wZXJ0aWVzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59O1xuXG4vKipcbiAqIE1hcHMgQ2xvdWRGb3JtYXRpb24gcmVzb3VyY2UgdHlwZXMgdG8gdGhlaXIgbmFtZSBwcm9wZXJ0eSBhbmQgQVdTIGxlbmd0aCBsaW1pdHMuXG4gKiBTb3VyY2VzOiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtdGVtcGxhdGUtcmVzb3VyY2UtdHlwZS1yZWYuaHRtbFxuICovXG5jb25zdCBSRVNPVVJDRV9DT05GSUc6IFJlY29yZDxzdHJpbmcsIFJlc291cmNlTmFtZUNvbmZpZz4gPSB7XG4gIC8vIENvbXB1dGVcbiAgXCJBV1M6OkxhbWJkYTo6RnVuY3Rpb25cIjogeyBjZm5OYW1lOiBcIkZ1bmN0aW9uTmFtZVwiLCBtYXhMZW5ndGg6IDY0IH0sXG5cbiAgLy8gU3RvcmFnZVxuICBcIkFXUzo6UzM6OkJ1Y2tldFwiOiB7IGNmbk5hbWU6IFwiQnVja2V0TmFtZVwiLCBtYXhMZW5ndGg6IDYzIH0sXG4gIFwiQVdTOjpEeW5hbW9EQjo6VGFibGVcIjogeyBjZm5OYW1lOiBcIlRhYmxlTmFtZVwiLCBtYXhMZW5ndGg6IDI1NSB9LFxuICBcIkFXUzo6RHluYW1vREI6Okdsb2JhbFRhYmxlXCI6IHsgY2ZuTmFtZTogXCJUYWJsZU5hbWVcIiwgbWF4TGVuZ3RoOiAyNTUgfSxcblxuICAvLyBNZXNzYWdpbmdcbiAgXCJBV1M6OlNRUzo6UXVldWVcIjogeyBjZm5OYW1lOiBcIlF1ZXVlTmFtZVwiLCBtYXhMZW5ndGg6IDgwIH0sXG4gIFwiQVdTOjpTTlM6OlRvcGljXCI6IHsgY2ZuTmFtZTogXCJUb3BpY05hbWVcIiwgbWF4TGVuZ3RoOiAyNTYgfSxcblxuICAvLyBFdmVudGluZyAmIE9yY2hlc3RyYXRpb25cbiAgXCJBV1M6OkV2ZW50czo6RXZlbnRCdXNcIjogeyBjZm5OYW1lOiBcIk5hbWVcIiwgbWF4TGVuZ3RoOiAyNTYgfSxcbiAgXCJBV1M6OkV2ZW50czo6UnVsZVwiOiB7IGNmbk5hbWU6IFwiTmFtZVwiLCBtYXhMZW5ndGg6IDY0IH0sXG4gIFwiQVdTOjpFdmVudHM6OkNvbm5lY3Rpb25cIjogeyBjZm5OYW1lOiBcIk5hbWVcIiwgbWF4TGVuZ3RoOiA2NCB9LFxuICBcIkFXUzo6UGlwZXM6OlBpcGVcIjogeyBjZm5OYW1lOiBcIk5hbWVcIiwgbWF4TGVuZ3RoOiA2NCB9LFxuICBcIkFXUzo6U3RlcEZ1bmN0aW9uczo6U3RhdGVNYWNoaW5lXCI6IHtcbiAgICBjZm5OYW1lOiBcIlN0YXRlTWFjaGluZU5hbWVcIixcbiAgICBtYXhMZW5ndGg6IDgwLFxuICB9LFxuICBcIkFXUzo6U3RlcEZ1bmN0aW9uczo6QWN0aXZpdHlcIjogeyBjZm5OYW1lOiBcIk5hbWVcIiwgbWF4TGVuZ3RoOiA4MCB9LFxuICBcIkFXUzo6U2NoZWR1bGVyOjpTY2hlZHVsZVwiOiB7IGNmbk5hbWU6IFwiTmFtZVwiLCBtYXhMZW5ndGg6IDY0IH0sXG4gIFwiQVdTOjpTY2hlZHVsZXI6OlNjaGVkdWxlR3JvdXBcIjogeyBjZm5OYW1lOiBcIk5hbWVcIiwgbWF4TGVuZ3RoOiA2NCB9LFxuXG4gIC8vIEFQSVxuICBcIkFXUzo6QXBpR2F0ZXdheTo6UmVzdEFwaVwiOiB7IGNmbk5hbWU6IFwiTmFtZVwiLCBtYXhMZW5ndGg6IDEyOCB9LFxuICBcIkFXUzo6QXBpR2F0ZXdheTo6VXNhZ2VQbGFuXCI6IHsgY2ZuTmFtZTogXCJVc2FnZVBsYW5OYW1lXCIsIG1heExlbmd0aDogMTI4IH0sXG4gIFwiQVdTOjpBcGlHYXRld2F5OjpBcGlLZXlcIjogeyBjZm5OYW1lOiBcIk5hbWVcIiwgbWF4TGVuZ3RoOiAxMjggfSxcbiAgXCJBV1M6OkFwaUdhdGV3YXlWMjo6QXBpXCI6IHsgY2ZuTmFtZTogXCJOYW1lXCIsIG1heExlbmd0aDogMTI4IH0sXG4gIFwiQVdTOjpBcGlHYXRld2F5VjI6OkF1dGhvcml6ZXJcIjogeyBjZm5OYW1lOiBcIk5hbWVcIiwgbWF4TGVuZ3RoOiAxMjggfSxcblxuICAvLyBTZWNyZXRzICYgQ29uZmlnXG4gIFwiQVdTOjpTZWNyZXRzTWFuYWdlcjo6U2VjcmV0XCI6IHsgY2ZuTmFtZTogXCJOYW1lXCIsIG1heExlbmd0aDogNTEyIH0sXG4gIFwiQVdTOjpTU006OlBhcmFtZXRlclwiOiB7IGNmbk5hbWU6IFwiTmFtZVwiLCBtYXhMZW5ndGg6IDIwNDggfSxcbiAgXCJBV1M6OkFwcENvbmZpZzo6QXBwbGljYXRpb25cIjogeyBjZm5OYW1lOiBcIk5hbWVcIiwgbWF4TGVuZ3RoOiA2NCB9LFxuICBcIkFXUzo6QXBwQ29uZmlnOjpFbnZpcm9ubWVudFwiOiB7IGNmbk5hbWU6IFwiTmFtZVwiLCBtYXhMZW5ndGg6IDY0IH0sXG5cbiAgLy8gTm90aWZpY2F0aW9uc1xuICBcIkFXUzo6Tm90aWZpY2F0aW9uczo6Tm90aWZpY2F0aW9uQ29uZmlndXJhdGlvblwiOiB7XG4gICAgY2ZuTmFtZTogXCJOYW1lXCIsXG4gICAgbWF4TGVuZ3RoOiA2NCxcbiAgfSxcblxuICAvLyBPYnNlcnZhYmlsaXR5XG4gIFwiQVdTOjpMb2dzOjpMb2dHcm91cFwiOiB7IGNmbk5hbWU6IFwiTG9nR3JvdXBOYW1lXCIsIG1heExlbmd0aDogNTEyIH0sXG4gIFwiQVdTOjpDbG91ZFdhdGNoOjpBbGFybVwiOiB7IGNmbk5hbWU6IFwiQWxhcm1OYW1lXCIsIG1heExlbmd0aDogMjU1IH0sXG5cbiAgLy8gSUFNXG4gIFwiQVdTOjpJQU06OlJvbGVcIjogeyBjZm5OYW1lOiBcIlJvbGVOYW1lXCIsIG1heExlbmd0aDogNjQgfSxcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb3VyY2VQcmVmaXhBc3BlY3RQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgcHJlZml4IHRvIGFwcGx5IHRvIGFsbCByZXNvdXJjZSBuYW1lcy5cbiAgICogZS5nLiAnbXlhcHAtcHJvZCcg4oaSICdteWFwcC1wcm9kLW9yZGVycydcbiAgICovXG4gIHByZWZpeDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBSZXNvdXJjZSB0eXBlcyB0byBza2lwIGVudGlyZWx5LlxuICAgKiBlLmcuIFsnQVdTOjpJQU06OlJvbGUnXSB0byBsZWF2ZSBJQU0gcm9sZSBuYW1lcyB1bnRvdWNoZWQuXG4gICAqIEBkZWZhdWx0IFtdXG4gICAqL1xuICBleGNsdWRlPzogc3RyaW5nW107XG59XG5cbi8qKlxuICogQ0RLIEFzcGVjdCB0aGF0IGF1dG9tYXRpY2FsbHkgcHJlZml4ZXMgcGh5c2ljYWwgcmVzb3VyY2UgbmFtZXMgYWNyb3NzIEFXUyByZXNvdXJjZXMuXG4gKlxuICogQHJlbWFya3NcbiAqICoqQ3JpdGljYWwgSW1wbGVtZW50YXRpb24gTm90ZXM6KipcbiAqXG4gKiAxLiAqKlN0YWdlIFN5bnRoZXNpcyBCb3VuZGFyaWVzKio6XG4gKiAgICAtIENESyBgU3RhZ2VgIGNvbnN0cnVjdHMgY3JlYXRlIHN5bnRoZXNpcyBib3VuZGFyaWVzIHRoYXQgcHJldmVudCBBcHAtbGV2ZWwgYXNwZWN0c1xuICogICAgICBmcm9tIHRyYXZlcnNpbmcgaW50byB0aGVtXG4gKiAgICAtIFRoaXMgYXNwZWN0IE1VU1QgYmUgYXBwbGllZCB0byBlYWNoIFN0YWdlIGluZGl2aWR1YWxseSwgbm90IHRvIHRoZSBBcHBcbiAqICAgIC0gRXhhbXBsZTogYEFzcGVjdHMub2Yoc3RhZ2UpLmFkZChuZXcgUmVzb3VyY2VQcmVmaXhBc3BlY3Qoey4uLn0pKWBcbiAqXG4gKiAyLiAqKlByb3BlcnR5IE5hbWUgQ2FzaW5nKio6XG4gKiAgICAtIENsb3VkRm9ybWF0aW9uIHByb3BlcnRpZXMgdXNlIFBhc2NhbENhc2UgKGUuZy4sIGBGdW5jdGlvbk5hbWVgLCBgQnVja2V0TmFtZWApXG4gKiAgICAtIFVzaW5nIGNhbWVsQ2FzZSAoZS5nLiwgYGZ1bmN0aW9uTmFtZWApIHdpbGwgY2F1c2UgZXJyb3JzIHdpdGggdmVyc2lvbmluZyBhc3BlY3RzXG4gKiAgICAtIFdoZW4gdXNpbmcgYGFkZFByb3BlcnR5T3ZlcnJpZGUoKWAsIGFsd2F5cyB1c2UgdGhlIGV4YWN0IENsb3VkRm9ybWF0aW9uIHByb3BlcnR5IG5hbWVcbiAqXG4gKiAzLiAqKkFzcGVjdCBQcmlvcml0eSB3aXRoIFZlcnNpb25pbmcqKjpcbiAqICAgIC0gV2hlbiBjb21iaW5pbmcgd2l0aCBMYW1iZGFBbmRTdGVwRnVuY3Rpb25WZXJzaW9uaW5nQXNwZWN0LCBhcHBseSB0aGlzIGFzcGVjdCBCRUZPUkUgdmVyc2lvbmluZ1xuICogICAgLSBVc2UgQ0RLJ3MgcHJpb3JpdHkgc3lzdGVtOiBgQXNwZWN0cy5vZihzdGFnZSkuYWRkKHByZWZpeEFzcGVjdCwgeyBwcmlvcml0eTogMTAwIH0pYFxuICogICAgLSBUaGVuOiBgQXNwZWN0cy5vZihzdGFnZSkuYWRkKHZlcnNpb25pbmdBc3BlY3QsIHsgcHJpb3JpdHk6IDIwMCB9KWBcbiAqICAgIC0gTG93ZXIgcHJpb3JpdHkgbnVtYmVycyBydW4gZmlyc3RcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gQ29ycmVjdCB1c2FnZSB3aXRoIHN0YWdpbmdcbiAqIGNvbnN0IHN0YWdlID0gbmV3IEFwcGxpY2F0aW9uU3RhZ2UoYXBwLCAncHJvZCcpO1xuICogQXNwZWN0cy5vZihzdGFnZSkuYWRkKG5ldyBSZXNvdXJjZVByZWZpeEFzcGVjdCh7IHByZWZpeDogJ215YXBwJyB9KSwgeyBwcmlvcml0eTogMTAwIH0pO1xuICogQXNwZWN0cy5vZihzdGFnZSkuYWRkKG5ldyBMYW1iZGFBbmRTdGVwRnVuY3Rpb25WZXJzaW9uaW5nQXNwZWN0KCksIHsgcHJpb3JpdHk6IDIwMCB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgUmVzb3VyY2VQcmVmaXhBc3BlY3QgaW1wbGVtZW50cyBJQXNwZWN0IHtcbiAgcHJpdmF0ZSByZWFkb25seSBwcmVmaXg6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBleGNsdWRlOiBTZXQ8c3RyaW5nPjtcblxuICBjb25zdHJ1Y3Rvcihwcm9wczogUmVzb3VyY2VQcmVmaXhBc3BlY3RQcm9wcykge1xuICAgIGlmICghcHJvcHMucHJlZml4IHx8ICEvXlthLXowLTktXSskLy50ZXN0KHByb3BzLnByZWZpeCkpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBSZXNvdXJjZVByZWZpeEFzcGVjdDogcHJlZml4IG11c3QgY29udGFpbiBvbmx5IGxvd2VyY2FzZSBhbHBoYW51bWVyaWMgY2hhcmFjdGVycyBhbmQgaHlwaGVucywgZ290IFwiJHtwcm9wcy5wcmVmaXh9XCJgXG4gICAgICApO1xuXG4gICAgdGhpcy5wcmVmaXggPSBwcm9wcy5wcmVmaXg7XG4gICAgdGhpcy5leGNsdWRlID0gbmV3IFNldChwcm9wcy5leGNsdWRlID8/IFtdKTtcbiAgfVxuXG4gIHZpc2l0KG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICBpZiAoIShub2RlIGluc3RhbmNlb2YgQ2ZuUmVzb3VyY2UpKSByZXR1cm47XG5cbiAgICBjb25zdCByZXNvdXJjZVR5cGUgPSBub2RlLmNmblJlc291cmNlVHlwZTtcbiAgICBjb25zdCBjb25maWcgPSBSRVNPVVJDRV9DT05GSUdbcmVzb3VyY2VUeXBlXTtcblxuICAgIGlmICghY29uZmlnIHx8IHRoaXMuZXhjbHVkZS5oYXMocmVzb3VyY2VUeXBlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHsgY2ZuTmFtZSwgbWF4TGVuZ3RoIH0gPSBjb25maWc7XG4gICAgY29uc3QgY2ZuUHJvcGVydGllczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPVxuICAgICAgKG5vZGUgYXMgQ2ZuUmVzb3VyY2VXaXRoUHJvcHMpLl9jZm5Qcm9wZXJ0aWVzID8/XG4gICAgICAobm9kZSBhcyBDZm5SZXNvdXJjZVdpdGhQcm9wcykuY2ZuUHJvcGVydGllcyA/P1xuICAgICAge307XG5cbiAgICAvLyBHZXQgYW55IGV4cGxpY2l0bHkgc2V0IG5hbWUsIG9yIGRlcml2ZSBvbmUgZnJvbSB0aGUgbG9naWNhbCBJRFxuICAgIGNvbnN0IGV4aXN0aW5nTmFtZSA9XG4gICAgICB0eXBlb2YgY2ZuUHJvcGVydGllc1tjZm5OYW1lXSA9PT0gXCJzdHJpbmdcIlxuICAgICAgICA/IGNmblByb3BlcnRpZXNbY2ZuTmFtZV1cbiAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgYmFzZU5hbWUgPSBleGlzdGluZ05hbWUgPz8gdGhpcy5kZXJpdmVOYW1lRnJvbUxvZ2ljYWxJZChub2RlKTtcblxuICAgIGlmICh0aGlzLmlzQWxyZWFkeVByZWZpeGVkKGJhc2VOYW1lKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGZpbmFsTmFtZSA9IHRoaXMuYnVpbGRQcmVmaXhlZE5hbWUoXG4gICAgICBiYXNlTmFtZSxcbiAgICAgIHJlc291cmNlVHlwZSxcbiAgICAgIGNmblByb3BlcnRpZXNcbiAgICApO1xuXG4gICAgY29uc3QgaGFzRXJyb3IgPSB0aGlzLnZhbGlkYXRlUmVzb3VyY2VOYW1lKFxuICAgICAgZmluYWxOYW1lLFxuICAgICAgcmVzb3VyY2VUeXBlLFxuICAgICAgbWF4TGVuZ3RoLFxuICAgICAgbm9kZVxuICAgICk7XG5cbiAgICBpZiAoaGFzRXJyb3IpIHJldHVybjtcblxuICAgIG5vZGUuYWRkUHJvcGVydHlPdmVycmlkZShjZm5OYW1lLCBmaW5hbE5hbWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBpc0FscmVhZHlQcmVmaXhlZChuYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgbmFtZS5zdGFydHNXaXRoKGAke3RoaXMucHJlZml4fS1gKSB8fCBuYW1lLnN0YXJ0c1dpdGgoYC8ke3RoaXMucHJlZml4fS9gKVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGRlcml2ZU5hbWVGcm9tTG9naWNhbElkKG5vZGU6IENmblJlc291cmNlKSB7XG4gICAgY29uc3QgbG9naWNhbElkID0gU3RhY2sub2Yobm9kZSkuZ2V0TG9naWNhbElkKG5vZGUpO1xuICAgIHJldHVybiBsb2dpY2FsSWRcbiAgICAgIC5yZXBsYWNlKC9bXmEtekEtWjAtOV0rL2csIFwiLVwiKSAvLyBub24tYWxwaGFudW1lcmljIOKGkiBkYXNoXG4gICAgICAucmVwbGFjZSgvXi0rfC0rJC9nLCBcIlwiKTsgLy8gdHJpbSBsZWFkaW5nL3RyYWlsaW5nIGRhc2hlc1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgcHJlZml4ZWQgbmFtZSwgaGFuZGxpbmcgc3BlY2lhbCBjYXNlcyBmb3Igc3BlY2lmaWMgcmVzb3VyY2UgdHlwZXMuXG4gICAqXG4gICAqIEBwYXJhbSBiYXNlTmFtZSAtIFRoZSBiYXNlIHJlc291cmNlIG5hbWUgKHdpdGhvdXQgcHJlZml4KVxuICAgKiBAcGFyYW0gY2ZuUmVzb3VyY2VUeXBlIC0gVGhlIENsb3VkRm9ybWF0aW9uIHJlc291cmNlIHR5cGVcbiAgICogQHBhcmFtIGNmblByb3BlcnRpZXMgLSBUaGUgQ2xvdWRGb3JtYXRpb24gcmVzb3VyY2UgcHJvcGVydGllc1xuICAgKiBAcmV0dXJucyBUaGUgZmluYWwgcHJlZml4ZWQgbmFtZSB3aXRoIGFueSBzcGVjaWFsIGNhc2UgaGFuZGxpbmcgYXBwbGllZFxuICAgKi9cbiAgcHJpdmF0ZSBidWlsZFByZWZpeGVkTmFtZShcbiAgICBiYXNlTmFtZTogc3RyaW5nLFxuICAgIGNmblJlc291cmNlVHlwZTogc3RyaW5nLFxuICAgIGNmblByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG4gICk6IHN0cmluZyB7XG4gICAgLy8gU3BlY2lhbCBjYXNlOiBGSUZPIHF1ZXVlcyBtdXN0IGVuZCB3aXRoIC5maWZvIHN1ZmZpeFxuICAgIGlmIChcbiAgICAgIGNmblJlc291cmNlVHlwZSA9PT0gXCJBV1M6OlNRUzo6UXVldWVcIiAmJlxuICAgICAgY2ZuUHJvcGVydGllcy5maWZvUXVldWUgPT09IHRydWUgJiZcbiAgICAgICFiYXNlTmFtZS5lbmRzV2l0aChcIi5maWZvXCIpXG4gICAgKSB7XG4gICAgICByZXR1cm4gYCR7dGhpcy5wcmVmaXh9LSR7YmFzZU5hbWV9LmZpZm9gO1xuICAgIH1cblxuICAgIC8vIFNwZWNpYWwgY2FzZTogRklGTyB0b3BpY3MgbXVzdCBlbmQgd2l0aCAuZmlmbyBzdWZmaXhcbiAgICBpZiAoXG4gICAgICBjZm5SZXNvdXJjZVR5cGUgPT09IFwiQVdTOjpTTlM6OlRvcGljXCIgJiZcbiAgICAgIGNmblByb3BlcnRpZXMuZmlmb1RvcGljID09PSB0cnVlICYmXG4gICAgICAhYmFzZU5hbWUuZW5kc1dpdGgoXCIuZmlmb1wiKVxuICAgICkge1xuICAgICAgcmV0dXJuIGAke3RoaXMucHJlZml4fS0ke2Jhc2VOYW1lfS5maWZvYDtcbiAgICB9XG5cbiAgICAvLyBTcGVjaWFsIGNhc2U6IFNTTSBwYXJhbWV0ZXIgbmFtZXMgdXNlIHBhdGgtc3R5bGUgcHJlZml4XG4gICAgaWYgKGNmblJlc291cmNlVHlwZSA9PT0gXCJBV1M6OlNTTTo6UGFyYW1ldGVyXCIpIHtcbiAgICAgIHJldHVybiBgLyR7dGhpcy5wcmVmaXh9LyR7YmFzZU5hbWV9YDtcbiAgICB9XG5cbiAgICAvLyBTcGVjaWFsIGNhc2U6IFMzIGJ1Y2tldCBuYW1lIGJlIGxvd2VyY2FzZSBvbmx5XG4gICAgaWYgKGNmblJlc291cmNlVHlwZSA9PT0gXCJBV1M6OlMzOjpCdWNrZXRcIikge1xuICAgICAgcmV0dXJuIGAke3RoaXMucHJlZml4fS0ke2Jhc2VOYW1lfWAudG9Mb3dlckNhc2UoKTtcbiAgICB9XG5cbiAgICAvLyBEZWZhdWx0OiBzaW1wbGUgcHJlZml4XG4gICAgcmV0dXJuIGAke3RoaXMucHJlZml4fS0ke2Jhc2VOYW1lfWA7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIHJlc291cmNlLXNwZWNpZmljIG5hbWluZyByZXF1aXJlbWVudHMgdGhhdCBBV1MgZW5mb3JjZXMuXG4gICAqIFRocm93cyBzeW50aGVzaXMgZXJyb3JzIGZvciB2aW9sYXRpb25zLlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVJlc291cmNlTmFtZShcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgY2ZuUmVzb3VyY2VUeXBlOiBzdHJpbmcsXG4gICAgbWF4TGVuZ3RoOiBudW1iZXIsXG4gICAgbm9kZTogSUNvbnN0cnVjdFxuICApOiBib29sZWFuIHtcbiAgICBsZXQgaGFzRXJyb3IgPSBmYWxzZTtcblxuICAgIC8vIFMzIGJ1Y2tldCBuYW1lcyBjYW5ub3QgY29udGFpbiB1bmRlcnNjb3Jlc1xuICAgIGlmIChjZm5SZXNvdXJjZVR5cGUgPT09IFwiQVdTOjpTMzo6QnVja2V0XCIpIHtcbiAgICAgIGlmIChuYW1lICE9PSBuYW1lLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgICAgQW5ub3RhdGlvbnMub2Yobm9kZSkuYWRkRXJyb3IoXG4gICAgICAgICAgYFtSZXNvdXJjZVByZWZpeEFzcGVjdF0gUzMgYnVja2V0IG5hbWUgXCIke25hbWV9XCIgY29udGFpbnMgdXBwZXJjYXNlIGxldHRlcnMuIGAgK1xuICAgICAgICAgICAgYEJ1Y2tldCBuYW1lcyBtdXN0IGJlIGxvd2VyY2FzZSBvbmx5LmBcbiAgICAgICAgKTtcbiAgICAgICAgaGFzRXJyb3IgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAobmFtZS5pbmNsdWRlcyhcIl9cIikpIHtcbiAgICAgICAgQW5ub3RhdGlvbnMub2Yobm9kZSkuYWRkRXJyb3IoXG4gICAgICAgICAgYFtSZXNvdXJjZVByZWZpeEFzcGVjdF0gUzMgYnVja2V0IG5hbWUgXCIke25hbWV9XCIgY29udGFpbnMgdW5kZXJzY29yZXMuIGAgK1xuICAgICAgICAgICAgYEJ1Y2tldCBuYW1lcyBjYW5ub3QgY29udGFpbiB1bmRlcnNjb3Jlcy4gVXNlIGh5cGhlbnMgaW5zdGVhZC5gXG4gICAgICAgICk7XG4gICAgICAgIGhhc0Vycm9yID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAobmFtZS5sZW5ndGggPiBtYXhMZW5ndGgpIHtcbiAgICAgIEFubm90YXRpb25zLm9mKG5vZGUpLmFkZEVycm9yKFxuICAgICAgICBgW1Jlc291cmNlUHJlZml4QXNwZWN0XSBcIiR7bmFtZX1cIiAoJHtuYW1lLmxlbmd0aH0gY2hhcnMpIGV4Y2VlZHMgdGhlIGAgK1xuICAgICAgICAgIGBtYXhpbXVtIGFsbG93ZWQgbGVuZ3RoIG9mICR7bWF4TGVuZ3RofSBmb3IgJHtjZm5SZXNvdXJjZVR5cGV9LiBgICtcbiAgICAgICAgICBgU2hvcnRlbiB0aGUgcmVzb3VyY2UgYmFzZSBuYW1lIG9yIHlvdXIgcHJlZml4IChcIiR7dGhpcy5wcmVmaXh9XCIpLmBcbiAgICAgICk7XG4gICAgICBoYXNFcnJvciA9IHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGhhc0Vycm9yO1xuICB9XG59XG4iXX0=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aligent/cdk-aspects",
3
- "version": "0.3.2",
3
+ "version": "0.5.0",
4
4
  "description": "Collection of CDK Asppects",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",