@aws/nx-plugin 0.45.1 → 0.47.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.
Files changed (114) hide show
  1. package/package.json +1 -1
  2. package/src/infra/app/generator.js +4 -1
  3. package/src/infra/app/generator.js.map +1 -1
  4. package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +3729 -0
  5. package/src/py/fast-api/generator.js +57 -50
  6. package/src/py/fast-api/generator.js.map +1 -1
  7. package/src/py/fast-api/react/__snapshots__/generator.spec.ts.snap +1 -0
  8. package/src/py/fast-api/schema.d.ts +1 -0
  9. package/src/py/fast-api/schema.json +8 -0
  10. package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +310 -0
  11. package/src/py/lambda-function/generator.js +15 -25
  12. package/src/py/lambda-function/generator.js.map +1 -1
  13. package/src/py/lambda-function/schema.d.ts +1 -0
  14. package/src/py/lambda-function/schema.json +8 -0
  15. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +590 -0
  16. package/src/py/mcp-server/generator.js +4 -18
  17. package/src/py/mcp-server/generator.js.map +1 -1
  18. package/src/py/mcp-server/schema.d.ts +1 -0
  19. package/src/py/mcp-server/schema.json +8 -0
  20. package/src/py/strands-agent/__snapshots__/generator.spec.ts.snap +590 -0
  21. package/src/py/strands-agent/generator.js +4 -18
  22. package/src/py/strands-agent/generator.js.map +1 -1
  23. package/src/py/strands-agent/schema.d.ts +1 -0
  24. package/src/py/strands-agent/schema.json +8 -0
  25. package/src/terraform/project/generator.js +23 -7
  26. package/src/terraform/project/generator.js.map +1 -1
  27. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +3729 -0
  28. package/src/trpc/backend/generator.js +6 -17
  29. package/src/trpc/backend/generator.js.map +1 -1
  30. package/src/trpc/backend/schema.d.ts +1 -0
  31. package/src/trpc/backend/schema.json +8 -0
  32. package/src/trpc/react/__snapshots__/generator.spec.ts.snap +1 -0
  33. package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +310 -0
  34. package/src/ts/lambda-function/generator.js +15 -27
  35. package/src/ts/lambda-function/generator.js.map +1 -1
  36. package/src/ts/lambda-function/schema.d.ts +1 -0
  37. package/src/ts/lambda-function/schema.json +8 -0
  38. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +590 -0
  39. package/src/ts/mcp-server/generator.js +4 -18
  40. package/src/ts/mcp-server/generator.js.map +1 -1
  41. package/src/ts/mcp-server/schema.d.ts +1 -0
  42. package/src/ts/mcp-server/schema.json +8 -0
  43. package/src/ts/nx-plugin/generator.js +1 -0
  44. package/src/ts/nx-plugin/generator.js.map +1 -1
  45. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +756 -0
  46. package/src/ts/react-website/app/generator.js +42 -43
  47. package/src/ts/react-website/app/generator.js.map +1 -1
  48. package/src/ts/react-website/app/schema.d.ts +1 -0
  49. package/src/ts/react-website/app/schema.json +8 -0
  50. package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +259 -0
  51. package/src/ts/react-website/cognito-auth/generator.js +10 -13
  52. package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
  53. package/src/ts/react-website/cognito-auth/schema.d.ts +1 -0
  54. package/src/ts/react-website/cognito-auth/schema.json +8 -0
  55. package/src/ts/react-website/runtime-config/__snapshots__/generator.spec.ts.snap +0 -40
  56. package/src/ts/react-website/runtime-config/generator.js +0 -2
  57. package/src/ts/react-website/runtime-config/generator.js.map +1 -1
  58. package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +11 -5
  59. package/src/utils/agent-core-constructs/agent-core-constructs.js +51 -10
  60. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  61. package/src/utils/agent-core-constructs/files/terraform/app/agent-core/__nameKebabCase__/__nameKebabCase__.tf.template +46 -0
  62. package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +536 -0
  63. package/src/utils/api-constructs/api-constructs.d.ts +4 -4
  64. package/src/utils/api-constructs/api-constructs.js +45 -5
  65. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  66. package/src/utils/api-constructs/files/terraform/app/apis/http/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +392 -0
  67. package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +518 -0
  68. package/src/utils/api-constructs/files/terraform/core/api/http/http-api/http-api.tf.template +250 -0
  69. package/src/utils/api-constructs/files/terraform/core/api/rest/rest-api/rest-api.tf.template +150 -0
  70. package/src/utils/files/terraform/src/core/runtime-config/entry/entry.tf.template +119 -0
  71. package/src/utils/files/terraform/src/core/runtime-config/read/read.tf.template +28 -0
  72. package/src/utils/files/terraform/src/metrics/metrics.tf.template +3 -2
  73. package/src/{py/lambda-function/files/common/constructs/src/app/lambda-functions/__constructFunctionKebabCase__.ts.template → utils/function-constructs/files/cdk/app/lambda-functions/__functionNameKebabCase__.ts.template} +5 -5
  74. package/src/utils/function-constructs/files/terraform/app/lambda-functions/__functionNameKebabCase__/__functionNameKebabCase__.tf.template +150 -0
  75. package/src/utils/function-constructs/function-constructs.d.ts +19 -0
  76. package/src/utils/function-constructs/function-constructs.js +57 -0
  77. package/src/utils/function-constructs/function-constructs.js.map +1 -0
  78. package/src/utils/identity-constructs/files/terraform/core/user-identity/add-callback-url/add-callback-url.tf.template +123 -0
  79. package/src/utils/identity-constructs/files/terraform/core/user-identity/identity/identity.tf.template +421 -0
  80. package/src/utils/identity-constructs/files/terraform/core/user-identity/main.tf.template +47 -0
  81. package/src/utils/identity-constructs/identity-constructs.d.ts +15 -0
  82. package/src/utils/identity-constructs/identity-constructs.js +84 -0
  83. package/src/utils/identity-constructs/identity-constructs.js.map +1 -0
  84. package/src/utils/metrics.js +1 -1
  85. package/src/utils/metrics.js.map +1 -1
  86. package/src/utils/py.d.ts +5 -0
  87. package/src/utils/py.js +9 -1
  88. package/src/utils/py.js.map +1 -1
  89. package/src/utils/shared-constructs-constants.d.ts +2 -0
  90. package/src/utils/shared-constructs-constants.js +3 -1
  91. package/src/utils/shared-constructs-constants.js.map +1 -1
  92. package/src/utils/shared-constructs.js +26 -2
  93. package/src/utils/shared-constructs.js.map +1 -1
  94. package/src/utils/versions.d.ts +3 -1
  95. package/src/utils/versions.js +2 -0
  96. package/src/utils/versions.js.map +1 -1
  97. package/src/utils/website-constructs/files/terraform/app/static-websites/__websiteNameKebabCase__/__websiteNameKebabCase__.tf.template +42 -0
  98. package/src/utils/website-constructs/files/terraform/core/static-website/static-website.tf.template +709 -0
  99. package/src/utils/website-constructs/website-constructs.d.ts +18 -0
  100. package/src/utils/website-constructs/website-constructs.js +61 -0
  101. package/src/utils/website-constructs/website-constructs.js.map +1 -0
  102. package/src/ts/lambda-function/files/common/constructs/src/app/lambda-functions/__constructFunctionNameKebabCase__.ts.template +0 -24
  103. /package/src/utils/agent-core-constructs/files/{app → cdk/app}/agent-core/__nameKebabCase__/Dockerfile.template +0 -0
  104. /package/src/utils/agent-core-constructs/files/{app → cdk/app}/agent-core/__nameKebabCase__/__nameKebabCase__.ts.template +0 -0
  105. /package/src/utils/agent-core-constructs/files/{core → cdk/core}/agent-core/runtime.ts.template +0 -0
  106. /package/src/utils/api-constructs/files/{app → cdk/app}/apis/http/__apiNameKebabCase__.ts.template +0 -0
  107. /package/src/utils/api-constructs/files/{app → cdk/app}/apis/rest/__apiNameKebabCase__.ts.template +0 -0
  108. /package/src/utils/api-constructs/files/{core → cdk/core}/api/http/http-api.ts.template +0 -0
  109. /package/src/utils/api-constructs/files/{core → cdk/core}/api/rest/rest-api.ts.template +0 -0
  110. /package/src/utils/api-constructs/files/{core → cdk/core}/api/trpc/trpc-utils.ts.template +0 -0
  111. /package/src/utils/api-constructs/files/{core → cdk/core}/api/utils/utils.ts.template +0 -0
  112. /package/src/{ts/react-website/cognito-auth/files/common/constructs/src → utils/identity-constructs/files/cdk}/core/user-identity.ts.template +0 -0
  113. /package/src/{ts/react-website/app/files/common/constructs/src → utils/website-constructs/files/cdk}/app/static-websites/__websiteNameKebabCase__.ts.template +0 -0
  114. /package/src/{ts/react-website/app/files/common/constructs/src → utils/website-constructs/files/cdk}/core/static-website.ts.template +0 -0
@@ -0,0 +1,250 @@
1
+ # Core HTTP API Gateway module
2
+ # This module creates the API Gateway HTTP API, stage, and logging resources
3
+
4
+ terraform {
5
+ required_version = ">= 1.0"
6
+
7
+ required_providers {
8
+ aws = {
9
+ source = "hashicorp/aws"
10
+ version = "~> 6.0"
11
+ }
12
+ }
13
+ }
14
+
15
+ # Core HTTP API Gateway Variables
16
+
17
+ variable "api_name" {
18
+ description = "Name of the HTTP API Gateway"
19
+ type = string
20
+ }
21
+
22
+ variable "api_description" {
23
+ description = "Description of the HTTP API Gateway"
24
+ type = string
25
+ default = "HTTP API Gateway"
26
+ }
27
+
28
+ variable "stage_name" {
29
+ description = "Name of the API Gateway stage"
30
+ type = string
31
+ default = "prod"
32
+ }
33
+
34
+ variable "stage_auto_deploy" {
35
+ description = "Whether to automatically deploy the API stage"
36
+ type = bool
37
+ default = true
38
+ }
39
+
40
+ # CORS Configuration
41
+
42
+ variable "cors_allow_credentials" {
43
+ description = "Whether to allow credentials in CORS requests"
44
+ type = bool
45
+ default = false
46
+ }
47
+
48
+ variable "cors_allow_headers" {
49
+ description = "List of allowed headers for CORS"
50
+ type = list(string)
51
+ default = ["authorization", "content-type", "x-amz-content-sha256", "x-amz-date", "x-amz-security-token"]
52
+ }
53
+
54
+ variable "cors_allow_methods" {
55
+ description = "List of allowed HTTP methods for CORS"
56
+ type = list(string)
57
+ default = ["*"]
58
+ }
59
+
60
+ variable "cors_allow_origins" {
61
+ description = "List of allowed origins for CORS"
62
+ type = list(string)
63
+ default = ["*"]
64
+ }
65
+
66
+ variable "cors_expose_headers" {
67
+ description = "List of headers to expose in CORS responses"
68
+ type = list(string)
69
+ default = []
70
+ }
71
+
72
+ variable "cors_max_age" {
73
+ description = "Maximum age for CORS preflight requests in seconds"
74
+ type = number
75
+ default = 86400
76
+ }
77
+
78
+ # Tags
79
+
80
+ variable "tags" {
81
+ description = "Tags to apply to all resources"
82
+ type = map(string)
83
+ default = {}
84
+ }
85
+
86
+ # Data sources
87
+ data "aws_region" "current" {}
88
+ data "aws_caller_identity" "current" {}
89
+
90
+ # Resources
91
+
92
+ # KMS key for CloudWatch log group encryption
93
+ resource "aws_kms_key" "logs_key" {
94
+ description = "KMS key for CloudWatch log group encryption"
95
+ deletion_window_in_days = 7
96
+ enable_key_rotation = true
97
+
98
+ policy = jsonencode({
99
+ Version = "2012-10-17"
100
+ Statement = [
101
+ {
102
+ Sid = "Enable IAM User Permissions"
103
+ Effect = "Allow"
104
+ Principal = {
105
+ AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
106
+ }
107
+ Action = "kms:*"
108
+ Resource = "*"
109
+ },
110
+ {
111
+ Sid = "Allow CloudWatch Logs"
112
+ Effect = "Allow"
113
+ Principal = {
114
+ Service = "logs.${data.aws_region.current.name}.amazonaws.com"
115
+ }
116
+ Action = [
117
+ "kms:Encrypt",
118
+ "kms:Decrypt",
119
+ "kms:ReEncrypt*",
120
+ "kms:GenerateDataKey*",
121
+ "kms:DescribeKey"
122
+ ]
123
+ Resource = "*"
124
+ Condition = {
125
+ ArnEquals = {
126
+ "kms:EncryptionContext:aws:logs:arn" = "arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:/aws/apigateway/${var.api_name}"
127
+ }
128
+ }
129
+ }
130
+ ]
131
+ })
132
+
133
+ tags = var.tags
134
+ }
135
+
136
+ resource "aws_kms_alias" "logs_key_alias" {
137
+ name = "alias/${var.api_name}-api-logs-encryption"
138
+ target_key_id = aws_kms_key.logs_key.key_id
139
+ }
140
+
141
+ # HTTP API Gateway
142
+ resource "aws_apigatewayv2_api" "http_api" {
143
+ name = var.api_name
144
+ protocol_type = "HTTP"
145
+ description = var.api_description
146
+
147
+ cors_configuration {
148
+ allow_credentials = var.cors_allow_credentials
149
+ allow_headers = var.cors_allow_headers
150
+ allow_methods = var.cors_allow_methods
151
+ allow_origins = var.cors_allow_origins
152
+ expose_headers = var.cors_expose_headers
153
+ max_age = var.cors_max_age
154
+ }
155
+
156
+ tags = var.tags
157
+ }
158
+
159
+ # API Gateway stage
160
+ resource "aws_apigatewayv2_stage" "api_stage" {
161
+ api_id = aws_apigatewayv2_api.http_api.id
162
+ name = var.stage_name
163
+ auto_deploy = var.stage_auto_deploy
164
+
165
+ access_log_settings {
166
+ destination_arn = aws_cloudwatch_log_group.api_logs.arn
167
+ format = jsonencode({
168
+ requestId = "$context.requestId"
169
+ ip = "$context.identity.sourceIp"
170
+ requestTime = "$context.requestTime"
171
+ httpMethod = "$context.httpMethod"
172
+ routeKey = "$context.routeKey"
173
+ status = "$context.status"
174
+ protocol = "$context.protocol"
175
+ responseLength = "$context.responseLength"
176
+ error = "$context.error.message"
177
+ integrationError = "$context.integrationErrorMessage"
178
+ })
179
+ }
180
+
181
+ default_route_settings {
182
+ throttling_burst_limit = 5000
183
+ throttling_rate_limit = 10000
184
+ }
185
+
186
+ tags = var.tags
187
+
188
+ depends_on = [aws_cloudwatch_log_group.api_logs]
189
+ }
190
+
191
+ # CloudWatch Log Group for API Gateway
192
+ resource "aws_cloudwatch_log_group" "api_logs" {
193
+ #checkov:skip=CKV_AWS_338:Log retention set to forever
194
+ #checkov:skip=CKV_AWS_66:Log retention set to forever
195
+ name = "/aws/apigateway/${var.api_name}"
196
+ kms_key_id = aws_kms_key.logs_key.arn
197
+ tags = var.tags
198
+ }
199
+
200
+ # Outputs
201
+
202
+ output "api_id" {
203
+ description = "ID of the HTTP API Gateway"
204
+ value = aws_apigatewayv2_api.http_api.id
205
+ }
206
+
207
+ output "api_arn" {
208
+ description = "ARN of the HTTP API Gateway"
209
+ value = aws_apigatewayv2_api.http_api.arn
210
+ }
211
+
212
+ output "api_endpoint" {
213
+ description = "Base URL of the HTTP API Gateway"
214
+ value = aws_apigatewayv2_api.http_api.api_endpoint
215
+ }
216
+
217
+ output "api_execution_arn" {
218
+ description = "Execution ARN of the HTTP API Gateway"
219
+ value = aws_apigatewayv2_api.http_api.execution_arn
220
+ }
221
+
222
+ output "stage_id" {
223
+ description = "ID of the API Gateway stage"
224
+ value = aws_apigatewayv2_stage.api_stage.id
225
+ }
226
+
227
+ output "stage_arn" {
228
+ description = "ARN of the API Gateway stage"
229
+ value = aws_apigatewayv2_stage.api_stage.arn
230
+ }
231
+
232
+ output "stage_execution_arn" {
233
+ description = "Execution ARN of the API Gateway stage"
234
+ value = aws_apigatewayv2_stage.api_stage.execution_arn
235
+ }
236
+
237
+ output "stage_invoke_url" {
238
+ description = "Invoke URL of the API Gateway stage"
239
+ value = aws_apigatewayv2_stage.api_stage.invoke_url
240
+ }
241
+
242
+ output "api_log_group_name" {
243
+ description = "Name of the API Gateway CloudWatch log group"
244
+ value = aws_cloudwatch_log_group.api_logs.name
245
+ }
246
+
247
+ output "api_log_group_arn" {
248
+ description = "ARN of the API Gateway CloudWatch log group"
249
+ value = aws_cloudwatch_log_group.api_logs.arn
250
+ }
@@ -0,0 +1,150 @@
1
+ # Core REST API Gateway module
2
+ # This module creates the API Gateway REST API, deployment, stage, and logging resources
3
+
4
+ terraform {
5
+ required_version = ">= 1.0"
6
+
7
+ required_providers {
8
+ aws = {
9
+ source = "hashicorp/aws"
10
+ version = "~> 6.0"
11
+ }
12
+ }
13
+ }
14
+
15
+ # Core REST API Gateway Variables
16
+
17
+ variable "api_name" {
18
+ description = "Name of the REST API Gateway"
19
+ type = string
20
+ }
21
+
22
+ variable "api_description" {
23
+ description = "Description of the REST API Gateway"
24
+ type = string
25
+ default = "REST API Gateway"
26
+ }
27
+
28
+ variable "stage_name" {
29
+ description = "Name of the API Gateway stage"
30
+ type = string
31
+ default = "prod"
32
+ }
33
+
34
+ variable "stage_auto_deploy" {
35
+ description = "Whether to automatically deploy the API stage"
36
+ type = bool
37
+ default = true
38
+ }
39
+
40
+ # CORS Configuration
41
+
42
+ variable "cors_allow_headers" {
43
+ description = "List of allowed headers for CORS"
44
+ type = list(string)
45
+ default = ["authorization", "content-type", "x-amz-content-sha256", "x-amz-date", "x-amz-security-token"]
46
+ }
47
+
48
+ variable "cors_allow_methods" {
49
+ description = "List of allowed HTTP methods for CORS"
50
+ type = list(string)
51
+ default = ["*"]
52
+ }
53
+
54
+ variable "cors_allow_origins" {
55
+ description = "List of allowed origins for CORS"
56
+ type = list(string)
57
+ default = ["*"]
58
+ }
59
+
60
+ # Tags
61
+
62
+ variable "tags" {
63
+ description = "Tags to apply to all resources"
64
+ type = map(string)
65
+ default = {}
66
+ }
67
+
68
+ # Data sources
69
+ data "aws_region" "current" {}
70
+ data "aws_caller_identity" "current" {}
71
+
72
+ # Resources
73
+
74
+ # Note: CloudWatch logging removed due to account-level CloudWatch Logs role ARN requirement
75
+
76
+ # REST API Gateway
77
+ resource "aws_api_gateway_rest_api" "rest_api" {
78
+ name = var.api_name
79
+ description = var.api_description
80
+
81
+ endpoint_configuration {
82
+ types = ["REGIONAL"]
83
+ }
84
+
85
+ lifecycle {
86
+ create_before_destroy = true
87
+ }
88
+
89
+ tags = var.tags
90
+ }
91
+
92
+ # Note: Deployment and stage are created in the consuming module (e.g., foo-api.tf)
93
+ # after all methods and integrations are defined
94
+
95
+ # Note: CloudWatch Log Group removed due to account-level CloudWatch Logs role ARN requirement
96
+
97
+ # Gateway Response for CORS (4XX errors)
98
+ resource "aws_api_gateway_gateway_response" "cors_4xx" {
99
+ rest_api_id = aws_api_gateway_rest_api.rest_api.id
100
+ response_type = "DEFAULT_4XX"
101
+
102
+ response_parameters = {
103
+ "gatewayresponse.header.Access-Control-Allow-Origin" = "'${join(",", var.cors_allow_origins)}'"
104
+ "gatewayresponse.header.Access-Control-Allow-Headers" = "'${join(",", var.cors_allow_headers)}'"
105
+ "gatewayresponse.header.Access-Control-Allow-Methods" = "'${join(",", var.cors_allow_methods)}'"
106
+ }
107
+ }
108
+
109
+ # Gateway Response for CORS (5XX errors)
110
+ resource "aws_api_gateway_gateway_response" "cors_5xx" {
111
+ rest_api_id = aws_api_gateway_rest_api.rest_api.id
112
+ response_type = "DEFAULT_5XX"
113
+
114
+ response_parameters = {
115
+ "gatewayresponse.header.Access-Control-Allow-Origin" = "'${join(",", var.cors_allow_origins)}'"
116
+ "gatewayresponse.header.Access-Control-Allow-Headers" = "'${join(",", var.cors_allow_headers)}'"
117
+ "gatewayresponse.header.Access-Control-Allow-Methods" = "'${join(",", var.cors_allow_methods)}'"
118
+ }
119
+ }
120
+
121
+ # Outputs
122
+
123
+ output "api_id" {
124
+ description = "ID of the REST API Gateway"
125
+ value = aws_api_gateway_rest_api.rest_api.id
126
+ }
127
+
128
+ output "api_arn" {
129
+ description = "ARN of the REST API Gateway"
130
+ value = aws_api_gateway_rest_api.rest_api.arn
131
+ }
132
+
133
+ output "api_endpoint" {
134
+ description = "Base URL of the REST API Gateway"
135
+ value = "https://${aws_api_gateway_rest_api.rest_api.id}.execute-api.${data.aws_region.current.id}.amazonaws.com"
136
+ }
137
+
138
+ output "api_execution_arn" {
139
+ description = "Execution ARN of the REST API Gateway"
140
+ value = aws_api_gateway_rest_api.rest_api.execution_arn
141
+ }
142
+
143
+ output "api_root_resource_id" {
144
+ description = "Root resource ID of the REST API Gateway"
145
+ value = aws_api_gateway_rest_api.rest_api.root_resource_id
146
+ }
147
+
148
+ # Note: Stage and deployment outputs are provided by the consuming module
149
+
150
+ # Note: CloudWatch log group outputs removed due to account-level CloudWatch Logs role ARN requirement
@@ -0,0 +1,119 @@
1
+ terraform {
2
+ required_providers {
3
+ local = {
4
+ source = "hashicorp/local"
5
+ version = "~> 2.0"
6
+ }
7
+ }
8
+ }
9
+
10
+ # Variables
11
+ variable "key_path" {
12
+ description = "Dot-separated path for the configuration key (e.g., 'apis.FooApi', 'cognito.userPoolId')"
13
+ type = string
14
+ }
15
+
16
+ variable "value" {
17
+ description = "Value to set at the key path"
18
+ type = any
19
+ }
20
+
21
+ locals {
22
+ config_file_path = "${path.module}/../../../../../../../dist/packages/common/terraform/runtime-config.json"
23
+ }
24
+
25
+ # This module writes an entry to runtime-config.json which is provided to any static websites
26
+ # as a way to pass deploy-time values to the UI such as API urls
27
+
28
+ data "external" "updated_config" {
29
+ program = ["uv", "run", "python", "-c", <<-EOT
30
+ import json
31
+ import sys
32
+ import os
33
+ import time
34
+ import fcntl
35
+ from pathlib import Path
36
+
37
+ # Read input from Terraform
38
+ input_data = json.load(sys.stdin)
39
+ config_file = input_data['config_file']
40
+ key_path = input_data['key_path']
41
+ value = json.loads(input_data['value'])
42
+
43
+ # Create lock file path
44
+ lock_file = config_file + '.lock'
45
+
46
+ # Ensure directory exists
47
+ Path(config_file).parent.mkdir(parents=True, exist_ok=True)
48
+
49
+ # Acquire exclusive lock with retry mechanism
50
+ max_retries = 30
51
+ retry_delay = 1.0
52
+
53
+ for attempt in range(max_retries):
54
+ try:
55
+ # Open lock file for exclusive access
56
+ with open(lock_file, 'w') as lock_fd:
57
+ # Try to acquire exclusive lock (non-blocking)
58
+ fcntl.flock(lock_fd.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
59
+
60
+ # Critical section - file operations under lock
61
+ try:
62
+ # Create empty base config if file doesn't exist
63
+ if not os.path.exists(config_file):
64
+ base_config = {}
65
+ with open(config_file, 'w') as f:
66
+ json.dump(base_config, f, indent=2)
67
+
68
+ # Read current config
69
+ with open(config_file, 'r') as f:
70
+ config = json.load(f)
71
+
72
+ # Set the nested key using dot notation
73
+ keys = key_path.split('.')
74
+ current = config
75
+ for key in keys[:-1]:
76
+ if key not in current:
77
+ current[key] = {}
78
+ current = current[key]
79
+ current[keys[-1]] = value
80
+
81
+ # Write updated config back to file atomically
82
+ temp_file = config_file + '.tmp'
83
+ with open(temp_file, 'w') as f:
84
+ json.dump(config, f, indent=2)
85
+ os.rename(temp_file, config_file)
86
+
87
+ # Output the updated config for Terraform
88
+ print(json.dumps({"updated_json": json.dumps(config)}))
89
+
90
+ # Success - break out of retry loop
91
+ break
92
+
93
+ finally:
94
+ # Lock is automatically released when file is closed
95
+ pass
96
+
97
+ except (IOError, OSError) as e:
98
+ if attempt < max_retries - 1:
99
+ # Wait before retrying
100
+ time.sleep(retry_delay)
101
+ continue
102
+ else:
103
+ # Final attempt failed
104
+ raise Exception(f"Failed to acquire lock after {max_retries} attempts: {e}")
105
+
106
+ # Clean up lock file if it exists
107
+ try:
108
+ os.remove(lock_file)
109
+ except OSError:
110
+ pass
111
+ EOT
112
+ ]
113
+
114
+ query = {
115
+ config_file = local.config_file_path
116
+ key_path = var.key_path
117
+ value = jsonencode(var.value)
118
+ }
119
+ }
@@ -0,0 +1,28 @@
1
+ terraform {
2
+ required_providers {
3
+ local = {
4
+ source = "hashicorp/local"
5
+ version = "~> 2.0"
6
+ }
7
+ }
8
+ }
9
+
10
+ locals {
11
+ config_file_path = "${path.module}/../../../../../../../dist/packages/common/terraform/runtime-config.json"
12
+ }
13
+
14
+ # Read the runtime config file - will fail gracefully if file doesn't exist
15
+ data "local_file" "runtime_config" {
16
+ filename = local.config_file_path
17
+ }
18
+
19
+ # Outputs
20
+ output "config" {
21
+ description = "Runtime configuration object"
22
+ value = jsondecode(data.local_file.runtime_config.content)
23
+ }
24
+
25
+ output "config_json" {
26
+ description = "Runtime configuration as JSON string"
27
+ value = data.local_file.runtime_config.content
28
+ }
@@ -1,7 +1,8 @@
1
1
  # CloudFormation stack for metrics tracking
2
2
  resource "aws_cloudformation_stack" "metrics" {
3
+ #checkov:skip=CKV_AWS_124:Metrics stack does not require SNS notifications
3
4
  name = "nx-plugin-metrics"
4
-
5
+
5
6
  template_body = jsonencode({
6
7
  AWSTemplateFormatVersion = "2010-09-09"
7
8
  Description = "<%= metricId %> (version:<%= version %>) (tag:<%= tags %>)"
@@ -12,7 +13,7 @@ resource "aws_cloudformation_stack" "metrics" {
12
13
  }
13
14
  }
14
15
  })
15
-
16
+
16
17
  tags = {
17
18
  Purpose = "nx-plugin-metrics"
18
19
  }
@@ -3,15 +3,15 @@ import * as url from 'url';
3
3
  import { Code, Function, Runtime, Tracing } from 'aws-cdk-lib/aws-lambda';
4
4
  import { Duration } from 'aws-cdk-lib';
5
5
 
6
- export class <%= constructFunctionClassName %> extends Function {
6
+ export class <%= functionNameClassName %> extends Function {
7
7
  constructor(scope: Construct, id: string) {
8
8
  super(scope, id, {
9
9
  timeout: Duration.seconds(30),
10
- runtime: Runtime.PYTHON_3_12,
11
- handler: '<%= constructHandlerFilePath %>',
10
+ runtime: <%= runtime %>,
11
+ handler: '<%= handler %>',
12
12
  code: Code.fromAsset(url.fileURLToPath(
13
13
  new URL(
14
- '../../../../../../dist/<%= dir %>/bundle',
14
+ '../../../../../../<%- bundlePathFromRoot %>',
15
15
  import.meta.url
16
16
  )
17
17
  )),
@@ -21,4 +21,4 @@ export class <%= constructFunctionClassName %> extends Function {
21
21
  },
22
22
  });
23
23
  }
24
- }
24
+ }