@aws/nx-plugin 1.0.0-rc.31 → 1.0.0-rc.33

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 (198) hide show
  1. package/LICENSE-THIRD-PARTY +72 -70
  2. package/package.json +5 -5
  3. package/src/infra/app/__snapshots__/generator.spec.ts.snap +15 -15
  4. package/src/infra/app/files/app/src/main.ts.template +1 -1
  5. package/src/infra/app/files/app/src/stages/application-stage.ts.template +1 -1
  6. package/src/infra/app/generator.js +3 -1
  7. package/src/infra/app/generator.js.map +1 -1
  8. package/src/open-api/ts-client/__snapshots__/generator.content-type.spec.ts.snap +64 -3
  9. package/src/open-api/ts-client/__snapshots__/generator.multipart.spec.ts.snap +280 -0
  10. package/src/open-api/ts-client/files/client.gen.ts.template +37 -2
  11. package/src/open-api/ts-client/generator.js +5 -1
  12. package/src/open-api/ts-client/generator.js.map +1 -1
  13. package/src/open-api/ts-hooks/files/options-proxy.gen.ts.template +2 -2
  14. package/src/open-api/ts-hooks/generator.js +5 -1
  15. package/src/open-api/ts-hooks/generator.js.map +1 -1
  16. package/src/open-api/utils/normalise.js +13 -6
  17. package/src/open-api/utils/normalise.js.map +1 -1
  18. package/src/open-api/utils/parser.js +12 -1
  19. package/src/open-api/utils/parser.js.map +1 -1
  20. package/src/open-api/utils/types.d.ts +4 -1
  21. package/src/open-api/utils/types.js.map +1 -1
  22. package/src/preset/__snapshots__/generator.spec.ts.snap +1 -1
  23. package/src/preset/generator.d.ts +1 -1
  24. package/src/preset/generator.js +5 -2
  25. package/src/preset/generator.js.map +1 -1
  26. package/src/preset/schema.d.js.map +1 -1
  27. package/src/preset/schema.d.ts +2 -0
  28. package/src/preset/schema.json +6 -0
  29. package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +7 -7
  30. package/src/py/agent/__snapshots__/generator.frameworks.spec.ts.snap +8 -8
  31. package/src/py/agent/__snapshots__/generator.protocols.spec.ts.snap +89 -3
  32. package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +2 -2
  33. package/src/py/fast-api/__snapshots__/generator.terraform.spec.ts.snap +426 -18
  34. package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +2 -2
  35. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +91 -5
  36. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +283 -11
  37. package/src/smithy/ts/api/files/handler.ts.template +2 -2
  38. package/src/smithy/ts/api/files/local-server.ts.template +2 -2
  39. package/src/smithy/ts/api/files/operations/echo.ts.template +2 -2
  40. package/src/smithy/ts/api/files/service.ts.template +3 -3
  41. package/src/smithy/ts/api/generator.js +3 -1
  42. package/src/smithy/ts/api/generator.js.map +1 -1
  43. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +426 -18
  44. package/src/trpc/backend/files/src/client/index.ts.template +1 -1
  45. package/src/trpc/backend/files/src/handler.ts.template +1 -1
  46. package/src/trpc/backend/files/src/index.ts.template +5 -5
  47. package/src/trpc/backend/files/src/init.ts.template +1 -1
  48. package/src/trpc/backend/files/src/local-server.ts.template +1 -1
  49. package/src/trpc/backend/files/src/middleware/index.ts.template +7 -7
  50. package/src/trpc/backend/files/src/procedures/echo.ts.template +2 -2
  51. package/src/trpc/backend/files/src/router.ts.template +2 -2
  52. package/src/trpc/backend/files/src/schema/index.ts.template +1 -1
  53. package/src/trpc/backend/generator.js +3 -1
  54. package/src/trpc/backend/generator.js.map +1 -1
  55. package/src/ts/agent/__snapshots__/generator.spec.ts.snap +89 -3
  56. package/src/ts/agent/a2a-connection/files/agent-connection/app/__targetAgentKebabCase__-client-strands.ts.template +2 -2
  57. package/src/ts/agent/a2a-connection/generator.js +3 -1
  58. package/src/ts/agent/a2a-connection/generator.js.map +1 -1
  59. package/src/ts/agent/files/a2a/index.ts.template +1 -1
  60. package/src/ts/agent/files/ag-ui/index.ts.template +1 -1
  61. package/src/ts/agent/files/http/client.ts.template +2 -2
  62. package/src/ts/agent/files/http/index.ts.template +2 -2
  63. package/src/ts/agent/files/http/router.ts.template +3 -3
  64. package/src/ts/agent/gateway-connection/files/agent-connection/app/__gatewayKebabCase__-client-strands.ts.template +2 -2
  65. package/src/ts/agent/gateway-connection/generator.js +3 -1
  66. package/src/ts/agent/gateway-connection/generator.js.map +1 -1
  67. package/src/ts/agent/generator.js +5 -2
  68. package/src/ts/agent/generator.js.map +1 -1
  69. package/src/ts/agent/mcp-connection/files/agent-connection/app/__mcpServerKebabCase__-client-strands.ts.template +2 -2
  70. package/src/ts/agent/mcp-connection/generator.js +3 -1
  71. package/src/ts/agent/mcp-connection/generator.js.map +1 -1
  72. package/src/ts/astro-docs/files/translation/scripts/translate.ts.template +3 -2
  73. package/src/ts/astro-docs/generator.js +2 -0
  74. package/src/ts/astro-docs/generator.js.map +1 -1
  75. package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +2 -2
  76. package/src/ts/dynamodb/files/src/client.ts.template +5 -2
  77. package/src/ts/dynamodb/files/src/entities/example.ts.template +1 -1
  78. package/src/ts/dynamodb/files/src/entities/index.ts.template +1 -1
  79. package/src/ts/dynamodb/files/src/index.ts.template +2 -2
  80. package/src/ts/dynamodb/generator.js +3 -1
  81. package/src/ts/dynamodb/generator.js.map +1 -1
  82. package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +2 -2
  83. package/src/ts/lib/generator.js +7 -1
  84. package/src/ts/lib/generator.js.map +1 -1
  85. package/src/ts/lib/ts-project-utils.js +19 -4
  86. package/src/ts/lib/ts-project-utils.js.map +1 -1
  87. package/src/ts/lib/types.d.ts +6 -0
  88. package/src/ts/lib/types.js.map +1 -1
  89. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +94 -31
  90. package/src/ts/mcp-server/generator.js +11 -22
  91. package/src/ts/mcp-server/generator.js.map +1 -1
  92. package/src/ts/nx-generator/files/local/generator.ts.template +2 -2
  93. package/src/ts/nx-generator/files/nx-plugin-for-aws/generator/generator.ts.template +2 -2
  94. package/src/ts/nx-generator/generator.js +5 -2
  95. package/src/ts/nx-generator/generator.js.map +1 -1
  96. package/src/ts/nx-plugin/files/mcp-server/server.ts.template +5 -5
  97. package/src/ts/nx-plugin/files/mcp-server/tools/create-workspace-command.ts.template +2 -2
  98. package/src/ts/nx-plugin/files/mcp-server/tools/general-guidance.ts.template +1 -1
  99. package/src/ts/nx-plugin/files/mcp-server/tools/generator-guide.ts.template +2 -2
  100. package/src/ts/nx-plugin/files/mcp-server/tools/list-generators.ts.template +2 -2
  101. package/src/ts/nx-plugin/files/mcp-server/utils.ts.template +3 -3
  102. package/src/ts/nx-plugin/generator.js +3 -1
  103. package/src/ts/nx-plugin/generator.js.map +1 -1
  104. package/src/ts/nx-plugin/utils.js +7 -4
  105. package/src/ts/nx-plugin/utils.js.map +1 -1
  106. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +4 -4
  107. package/src/ts/rdb/files/src/create-db-user-handler.ts.template +2 -2
  108. package/src/ts/rdb/files/src/index.ts.template +1 -1
  109. package/src/ts/rdb/files/src/migration-handler.ts.template +1 -1
  110. package/src/ts/rdb/files/src/prisma.ts.template +7 -4
  111. package/src/ts/rdb/generator.js +3 -1
  112. package/src/ts/rdb/generator.js.map +1 -1
  113. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +35 -35
  114. package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +2 -2
  115. package/src/utils/agent-chat/agent-chat.js +3 -1
  116. package/src/utils/agent-chat/agent-chat.js.map +1 -1
  117. package/src/utils/agent-chat/files/a2a/chat.ts.template +1 -1
  118. package/src/utils/agent-chat/files/ag-ui/chat.ts.template +1 -1
  119. package/src/utils/agent-chat/files/http-py/chat.ts.template +2 -2
  120. package/src/utils/agent-chat/files/http-ts/chat.ts.template +1 -1
  121. package/src/utils/agent-connection/agent-connection.js +4 -1
  122. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  123. package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client-config.ts.template +2 -2
  124. package/src/utils/agent-connection/files/core-auth/agentcore-fetch.ts.template +1 -1
  125. package/src/utils/agent-connection/files/core-gateway/agentcore-gateway-mcp-transport.ts.template +2 -2
  126. package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-transport.ts.template +2 -2
  127. package/src/utils/agent-connection/files/core-shared/agentcore-transport.ts.template +1 -1
  128. package/src/utils/agent-connection/files/core-strands/a2a/agentcore-a2a-client-strands.ts.template +1 -1
  129. package/src/utils/agent-connection/files/core-strands/base/with-session-id-strands.ts.template +1 -1
  130. package/src/utils/agent-connection/files/core-strands/gateway/agentcore-gateway-mcp-client-strands.ts.template +1 -1
  131. package/src/utils/agent-connection/files/core-strands/mcp/agentcore-mcp-client-strands.ts.template +1 -1
  132. package/src/utils/agent-core-constructs/agent-core-constructs.js +10 -3
  133. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  134. package/src/utils/agent-core-constructs/files/cdk/app/agent-core/__nameKebabCase__/__nameKebabCase__.ts.template +3 -3
  135. package/src/utils/agent-core-constructs/files/cdk/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.ts.template +4 -4
  136. package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +1 -1
  137. package/src/utils/agent-core-constructs/files/terraform/app/agent-core/__nameKebabCase__/__nameKebabCase__.tf.template +27 -0
  138. package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +60 -1
  139. package/src/utils/api-constructs/api-constructs.js +8 -2
  140. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  141. package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +8 -8
  142. package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +8 -8
  143. package/src/utils/api-constructs/files/cdk/core/api/http/http-api.ts.template +3 -3
  144. package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account/index.js.template +32 -20
  145. package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account.ts.template +1 -1
  146. package/src/utils/api-constructs/files/cdk/core/api/rest/rest-api.ts.template +4 -4
  147. package/src/utils/api-constructs/files/cdk/core/api/trpc/trpc-utils.ts.template +1 -1
  148. package/src/utils/api-constructs/files/terraform/app/apis/http/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +69 -1
  149. package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +69 -1
  150. package/src/utils/ast.js +16 -0
  151. package/src/utils/ast.js.map +1 -1
  152. package/src/utils/commands.d.ts +1 -1
  153. package/src/utils/commands.js +4 -1
  154. package/src/utils/commands.js.map +1 -1
  155. package/src/utils/dynamodb-constructs/dynamodb-constructs.js +9 -2
  156. package/src/utils/dynamodb-constructs/dynamodb-constructs.js.map +1 -1
  157. package/src/utils/dynamodb-constructs/files/cdk/app/dynamodb/__nameKebabCase__.ts.template +3 -3
  158. package/src/utils/dynamodb-constructs/files/cdk/core/dynamodb.ts.template +1 -1
  159. package/src/utils/files/common/constructs/src/core/index.ts.template +4 -4
  160. package/src/utils/files/common/constructs/src/index.ts.template +2 -2
  161. package/src/utils/files/common/infra-config/src/index.ts.template +3 -3
  162. package/src/utils/files/common/infra-config/src/resolve-stage.ts.template +2 -2
  163. package/src/utils/files/common/infra-config/src/stages.config.ts.template +1 -1
  164. package/src/utils/files/common/scripts/src/infra/infra-deploy.ts.template +1 -1
  165. package/src/utils/files/common/scripts/src/infra/infra-destroy.ts.template +1 -1
  166. package/src/utils/files/common/scripts/src/infra/stage-credentials/run.ts.template +3 -3
  167. package/src/utils/files/common/shadcn/src/index.ts.template +2 -2
  168. package/src/utils/function-constructs/files/cdk/app/lambda-functions/__nameKebabCase__.ts.template +1 -1
  169. package/src/utils/function-constructs/function-constructs.js +3 -1
  170. package/src/utils/function-constructs/function-constructs.js.map +1 -1
  171. package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +2 -2
  172. package/src/utils/identity-constructs/identity-constructs.js +5 -1
  173. package/src/utils/identity-constructs/identity-constructs.js.map +1 -1
  174. package/src/utils/module-format.d.ts +28 -0
  175. package/src/utils/module-format.js +28 -0
  176. package/src/utils/module-format.js.map +1 -0
  177. package/src/utils/rdb-constructs/files/cdk/app/dbs/__nameKebabCase__.ts.template +5 -5
  178. package/src/utils/rdb-constructs/files/cdk/core/rdb/aurora.ts.template +1 -1
  179. package/src/utils/rdb-constructs/rdb-constructs.js +9 -2
  180. package/src/utils/rdb-constructs/rdb-constructs.js.map +1 -1
  181. package/src/utils/shared-constructs.js +3 -1
  182. package/src/utils/shared-constructs.js.map +1 -1
  183. package/src/utils/shared-infra-config.js +3 -1
  184. package/src/utils/shared-infra-config.js.map +1 -1
  185. package/src/utils/shared-infra-scripts.js +3 -1
  186. package/src/utils/shared-infra-scripts.js.map +1 -1
  187. package/src/utils/shared-shadcn.js +3 -1
  188. package/src/utils/shared-shadcn.js.map +1 -1
  189. package/src/utils/test.d.ts +2 -0
  190. package/src/utils/test.js +7 -1
  191. package/src/utils/test.js.map +1 -1
  192. package/src/utils/versions.d.ts +61 -61
  193. package/src/utils/versions.js +59 -59
  194. package/src/utils/versions.js.map +1 -1
  195. package/src/utils/website-constructs/files/cdk/app/static-websites/__websiteNameKebabCase__.ts.template +2 -2
  196. package/src/utils/website-constructs/files/cdk/core/static-website.ts.template +2 -2
  197. package/src/utils/website-constructs/website-constructs.js +9 -2
  198. package/src/utils/website-constructs/website-constructs.js.map +1 -1
@@ -70,6 +70,30 @@ variable "additional_iam_policy_statements" {
70
70
  default = []
71
71
  }
72
72
 
73
+ # VPC Configuration (optional)
74
+ variable "enable_vpc" {
75
+ description = "Run the agent core runtime inside a VPC. Set alongside vpc_id/subnet_ids."
76
+ type = bool
77
+ default = false
78
+ }
79
+
80
+ variable "vpc_id" {
81
+ description = "VPC ID to run the agent core runtime in. Required when enable_vpc is true."
82
+ type = string
83
+ default = null
84
+
85
+ validation {
86
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
87
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
88
+ }
89
+ }
90
+
91
+ variable "subnet_ids" {
92
+ description = "Subnet IDs to run the agent core runtime in. Required when enable_vpc is true."
93
+ type = list(string)
94
+ default = null
95
+ }
96
+
73
97
  variable "tags" {
74
98
  description = "Tags to apply to resources"
75
99
  type = map(string)
@@ -305,6 +329,28 @@ resource "null_resource" "docker_publish" {
305
329
  depends_on = [aws_ecr_repository_policy.agent_core_ecr_policy]
306
330
  }
307
331
 
332
+ # Security group for the agent core runtime, used when running inside a VPC
333
+ resource "aws_security_group" "agent_core_runtime" {
334
+ count = var.enable_vpc ? 1 : 0
335
+
336
+ #checkov:skip=CKV2_AWS_5:Attached to the runtime via network_configuration; Checkov cannot resolve this reference
337
+ name_prefix = "${var.agent_runtime_name}-runtime-"
338
+ description = "Security group for the ${var.agent_runtime_name} agent core runtime"
339
+ vpc_id = var.vpc_id
340
+ tags = var.tags
341
+ }
342
+
343
+ resource "aws_vpc_security_group_egress_rule" "agent_core_runtime_https" {
344
+ count = var.enable_vpc ? 1 : 0
345
+
346
+ security_group_id = aws_security_group.agent_core_runtime[0].id
347
+ cidr_ipv4 = "0.0.0.0/0"
348
+ from_port = 443
349
+ to_port = 443
350
+ ip_protocol = "tcp"
351
+ description = "Allow outbound HTTPS to AWS service endpoints"
352
+ }
353
+
308
354
  # Bedrock AgentCore Agent Runtime
309
355
  resource "aws_bedrockagentcore_agent_runtime" "agent_runtime" {
310
356
  agent_runtime_name = "${var.agent_runtime_name}_${random_id.unique_suffix.hex}"
@@ -331,7 +377,15 @@ resource "aws_bedrockagentcore_agent_runtime" "agent_runtime" {
331
377
  }
332
378
 
333
379
  network_configuration {
334
- network_mode = "PUBLIC"
380
+ network_mode = var.enable_vpc ? "VPC" : "PUBLIC"
381
+
382
+ dynamic "network_mode_config" {
383
+ for_each = var.enable_vpc ? [1] : []
384
+ content {
385
+ security_groups = [aws_security_group.agent_core_runtime[0].id]
386
+ subnets = var.subnet_ids
387
+ }
388
+ }
335
389
  }
336
390
 
337
391
  protocol_configuration {
@@ -433,3 +487,8 @@ output "agent_runtime_version" {
433
487
  description = "Version of the Bedrock Agent Core runtime"
434
488
  value = aws_bedrockagentcore_agent_runtime.agent_runtime.agent_runtime_version
435
489
  }
490
+
491
+ output "security_group_id" {
492
+ description = "Security group ID of the agent core runtime, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
493
+ value = var.enable_vpc ? aws_security_group.agent_core_runtime[0].id : null
494
+ }
@@ -3,6 +3,7 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */ import { generateFiles, joinPathFragments, OverwriteStrategy, updateJson } from "@nx/devkit";
5
5
  import { addStarExport } from "../ast.js";
6
+ import { esmVars } from "../module-format.js";
6
7
  import { addDependencyToTargetIfNotPresent } from "../nx.js";
7
8
  import { PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, SHARED_TERRAFORM_DIR } from "../shared-constructs-constants.js";
8
9
  import { PY_VERSIONS, terraformProviderVersions } from "../versions.js";
@@ -23,7 +24,9 @@ export const addApiGatewayInfra = async (tree, options)=>{
23
24
  * Add an API CDK construct, and update the Runtime Config type to export its url
24
25
  */ const addApiGatewayCdkConstructs = async (tree, options)=>{
25
26
  const generateCoreApiFile = (name)=>{
26
- generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'cdk', 'core', 'api', name), joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'src', 'core', 'api'), {}, {
27
+ generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'cdk', 'core', 'api', name), joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'src', 'core', 'api'), {
28
+ ...esmVars(tree)
29
+ }, {
27
30
  overwriteStrategy: OverwriteStrategy.KeepExisting
28
31
  });
29
32
  };
@@ -34,7 +37,10 @@ export const addApiGatewayInfra = async (tree, options)=>{
34
37
  generateCoreApiFile('trpc');
35
38
  }
36
39
  // Generate app specific CDK construct
37
- generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'cdk', 'app', 'apis', options.constructType), joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'src', 'app', 'apis'), options, {
40
+ generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'cdk', 'app', 'apis', options.constructType), joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'src', 'app', 'apis'), {
41
+ ...options,
42
+ ...esmVars(tree)
43
+ }, {
38
44
  overwriteStrategy: OverwriteStrategy.KeepExisting
39
45
  });
40
46
  // Export app specific CDK construct
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/utils/api-constructs/api-constructs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { addStarExport } from '../ast';\nimport type { Iac } from '../iac';\nimport { addDependencyToTargetIfNotPresent } from '../nx';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../shared-constructs-constants';\nimport { PY_VERSIONS, terraformProviderVersions } from '../versions';\n\ninterface BackendOptions {\n type: 'trpc' | 'fastapi' | 'smithy';\n integrationPattern: 'isolated' | 'shared';\n}\n\nexport interface TrpcBackendOptions extends BackendOptions {\n type: 'trpc';\n projectAlias: string;\n bundleOutputDir: string;\n authorizerBundleOutputDir?: string;\n}\n\nexport interface FastApiBackendOptions extends BackendOptions {\n type: 'fastapi';\n moduleName: string;\n bundleOutputDir: string;\n}\n\nexport interface SmithyBackendOptions extends BackendOptions {\n type: 'smithy';\n bundleOutputDir: string;\n authorizerBundleOutputDir?: string;\n}\n\nexport interface AddApiGatewayConstructOptions {\n apiProjectName: string;\n apiNameClassName: string;\n apiNameKebabCase: string;\n constructType: 'http' | 'rest';\n backend: TrpcBackendOptions | FastApiBackendOptions | SmithyBackendOptions;\n auth: 'iam' | 'cognito' | 'custom';\n}\n\nexport const addApiGatewayInfra = async (\n tree: Tree,\n options: AddApiGatewayConstructOptions & { iac: Iac },\n) => {\n if (options.iac === 'cdk') {\n await addApiGatewayCdkConstructs(tree, options);\n } else if (options.iac === 'terraform') {\n addApiGatewayTerraformModules(tree, options);\n } else {\n throw new Error(`Unsupported iac ${options.iac}`);\n }\n\n updateJson(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n options.iac === 'cdk' ? SHARED_CONSTRUCTS_DIR : SHARED_TERRAFORM_DIR,\n 'project.json',\n ),\n (config: ProjectConfiguration) => {\n addDependencyToTargetIfNotPresent(\n config,\n 'build',\n `${options.apiProjectName}:build`,\n );\n return config;\n },\n );\n};\n\n/**\n * Add an API CDK construct, and update the Runtime Config type to export its url\n */\nconst addApiGatewayCdkConstructs = async (\n tree: Tree,\n options: AddApiGatewayConstructOptions,\n) => {\n const generateCoreApiFile = (name: string) => {\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'cdk',\n 'core',\n 'api',\n name,\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'api',\n ),\n {},\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n };\n\n // Generate relevant core CDK construct and utilities\n generateCoreApiFile(options.constructType);\n generateCoreApiFile('utils');\n if (options.backend.type === 'trpc') {\n generateCoreApiFile('trpc');\n }\n\n // Generate app specific CDK construct\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'cdk',\n 'app',\n 'apis',\n options.constructType,\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'apis',\n ),\n options,\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Export app specific CDK construct\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'apis',\n 'index.ts',\n ),\n `./${options.apiNameKebabCase}.js`,\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'index.ts',\n ),\n './apis/index.js',\n );\n};\n\n/**\n * Add an API terraform module, and update the Runtime Config type to export its url\n */\nconst addApiGatewayTerraformModules = (\n tree: Tree,\n options: AddApiGatewayConstructOptions,\n) => {\n // Generate core terraform module\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'core',\n 'api',\n options.constructType,\n ),\n joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'core', 'api'),\n { boto3Version: PY_VERSIONS.boto3, ...terraformProviderVersions() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Generate app specific terraform module\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'app',\n 'apis',\n options.constructType,\n ),\n joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'app', 'apis'),\n { ...options, ...terraformProviderVersions() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n};\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateJson","addStarExport","addDependencyToTargetIfNotPresent","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","SHARED_TERRAFORM_DIR","PY_VERSIONS","terraformProviderVersions","addApiGatewayInfra","tree","options","iac","addApiGatewayCdkConstructs","addApiGatewayTerraformModules","Error","config","apiProjectName","generateCoreApiFile","name","dirname","overwriteStrategy","KeepExisting","constructType","backend","type","apiNameKebabCase","boto3Version","boto3"],"mappings":"AAAA;;;CAGC,GACD,SACEA,aAAa,EACbC,iBAAiB,EACjBC,iBAAiB,EAGjBC,UAAU,QACL,aAAa;AACpB,SAASC,aAAa,QAAQ,YAAS;AAEvC,SAASC,iCAAiC,QAAQ,WAAQ;AAC1D,SACEC,YAAY,EACZC,qBAAqB,EACrBC,oBAAoB,QACf,oCAAiC;AACxC,SAASC,WAAW,EAAEC,yBAAyB,QAAQ,iBAAc;AAmCrE,OAAO,MAAMC,qBAAqB,OAChCC,MACAC;IAEA,IAAIA,QAAQC,GAAG,KAAK,OAAO;QACzB,MAAMC,2BAA2BH,MAAMC;IACzC,OAAO,IAAIA,QAAQC,GAAG,KAAK,aAAa;QACtCE,8BAA8BJ,MAAMC;IACtC,OAAO;QACL,MAAM,IAAII,MAAM,CAAC,gBAAgB,EAAEJ,QAAQC,GAAG,EAAE;IAClD;IAEAX,WACES,MACAX,kBACEK,cACAO,QAAQC,GAAG,KAAK,QAAQP,wBAAwBC,sBAChD,iBAEF,CAACU;QACCb,kCACEa,QACA,SACA,GAAGL,QAAQM,cAAc,CAAC,MAAM,CAAC;QAEnC,OAAOD;IACT;AAEJ,EAAE;AAEF;;CAEC,GACD,MAAMH,6BAA6B,OACjCH,MACAC;IAEA,MAAMO,sBAAsB,CAACC;QAC3BrB,cACEY,MACAX,kBACE,YAAYqB,OAAO,EACnB,SACA,OACA,QACA,OACAD,OAEFpB,kBACEK,cACAC,uBACA,OACA,QACA,QAEF,CAAC,GACD;YACEgB,mBAAmBrB,kBAAkBsB,YAAY;QACnD;IAEJ;IAEA,qDAAqD;IACrDJ,oBAAoBP,QAAQY,aAAa;IACzCL,oBAAoB;IACpB,IAAIP,QAAQa,OAAO,CAACC,IAAI,KAAK,QAAQ;QACnCP,oBAAoB;IACtB;IAEA,sCAAsC;IACtCpB,cACEY,MACAX,kBACE,YAAYqB,OAAO,EACnB,SACA,OACA,OACA,QACAT,QAAQY,aAAa,GAEvBxB,kBACEK,cACAC,uBACA,OACA,OACA,SAEFM,SACA;QACEU,mBAAmBrB,kBAAkBsB,YAAY;IACnD;IAGF,oCAAoC;IACpC,MAAMpB,cACJQ,MACAX,kBACEK,cACAC,uBACA,OACA,OACA,QACA,aAEF,CAAC,EAAE,EAAEM,QAAQe,gBAAgB,CAAC,GAAG,CAAC;IAEpC,MAAMxB,cACJQ,MACAX,kBACEK,cACAC,uBACA,OACA,OACA,aAEF;AAEJ;AAEA;;CAEC,GACD,MAAMS,gCAAgC,CACpCJ,MACAC;IAEA,iCAAiC;IACjCb,cACEY,MACAX,kBACE,YAAYqB,OAAO,EACnB,SACA,aACA,QACA,OACAT,QAAQY,aAAa,GAEvBxB,kBAAkBK,cAAcE,sBAAsB,OAAO,QAAQ,QACrE;QAAEqB,cAAcpB,YAAYqB,KAAK;QAAE,GAAGpB,2BAA2B;IAAC,GAClE;QACEa,mBAAmBrB,kBAAkBsB,YAAY;IACnD;IAGF,yCAAyC;IACzCxB,cACEY,MACAX,kBACE,YAAYqB,OAAO,EACnB,SACA,aACA,OACA,QACAT,QAAQY,aAAa,GAEvBxB,kBAAkBK,cAAcE,sBAAsB,OAAO,OAAO,SACpE;QAAE,GAAGK,OAAO;QAAE,GAAGH,2BAA2B;IAAC,GAC7C;QACEa,mBAAmBrB,kBAAkBsB,YAAY;IACnD;AAEJ"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/utils/api-constructs/api-constructs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { addStarExport } from '../ast';\nimport type { Iac } from '../iac';\nimport { esmVars } from '../module-format';\nimport { addDependencyToTargetIfNotPresent } from '../nx';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../shared-constructs-constants';\nimport { PY_VERSIONS, terraformProviderVersions } from '../versions';\n\ninterface BackendOptions {\n type: 'trpc' | 'fastapi' | 'smithy';\n integrationPattern: 'isolated' | 'shared';\n}\n\nexport interface TrpcBackendOptions extends BackendOptions {\n type: 'trpc';\n projectAlias: string;\n bundleOutputDir: string;\n authorizerBundleOutputDir?: string;\n}\n\nexport interface FastApiBackendOptions extends BackendOptions {\n type: 'fastapi';\n moduleName: string;\n bundleOutputDir: string;\n}\n\nexport interface SmithyBackendOptions extends BackendOptions {\n type: 'smithy';\n bundleOutputDir: string;\n authorizerBundleOutputDir?: string;\n}\n\nexport interface AddApiGatewayConstructOptions {\n apiProjectName: string;\n apiNameClassName: string;\n apiNameKebabCase: string;\n constructType: 'http' | 'rest';\n backend: TrpcBackendOptions | FastApiBackendOptions | SmithyBackendOptions;\n auth: 'iam' | 'cognito' | 'custom';\n}\n\nexport const addApiGatewayInfra = async (\n tree: Tree,\n options: AddApiGatewayConstructOptions & { iac: Iac },\n) => {\n if (options.iac === 'cdk') {\n await addApiGatewayCdkConstructs(tree, options);\n } else if (options.iac === 'terraform') {\n addApiGatewayTerraformModules(tree, options);\n } else {\n throw new Error(`Unsupported iac ${options.iac}`);\n }\n\n updateJson(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n options.iac === 'cdk' ? SHARED_CONSTRUCTS_DIR : SHARED_TERRAFORM_DIR,\n 'project.json',\n ),\n (config: ProjectConfiguration) => {\n addDependencyToTargetIfNotPresent(\n config,\n 'build',\n `${options.apiProjectName}:build`,\n );\n return config;\n },\n );\n};\n\n/**\n * Add an API CDK construct, and update the Runtime Config type to export its url\n */\nconst addApiGatewayCdkConstructs = async (\n tree: Tree,\n options: AddApiGatewayConstructOptions,\n) => {\n const generateCoreApiFile = (name: string) => {\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'cdk',\n 'core',\n 'api',\n name,\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'api',\n ),\n { ...esmVars(tree) },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n };\n\n // Generate relevant core CDK construct and utilities\n generateCoreApiFile(options.constructType);\n generateCoreApiFile('utils');\n if (options.backend.type === 'trpc') {\n generateCoreApiFile('trpc');\n }\n\n // Generate app specific CDK construct\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'cdk',\n 'app',\n 'apis',\n options.constructType,\n ),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'apis',\n ),\n { ...options, ...esmVars(tree) },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Export app specific CDK construct\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'apis',\n 'index.ts',\n ),\n `./${options.apiNameKebabCase}.js`,\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'index.ts',\n ),\n './apis/index.js',\n );\n};\n\n/**\n * Add an API terraform module, and update the Runtime Config type to export its url\n */\nconst addApiGatewayTerraformModules = (\n tree: Tree,\n options: AddApiGatewayConstructOptions,\n) => {\n // Generate core terraform module\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'core',\n 'api',\n options.constructType,\n ),\n joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'core', 'api'),\n { boto3Version: PY_VERSIONS.boto3, ...terraformProviderVersions() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Generate app specific terraform module\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n 'terraform',\n 'app',\n 'apis',\n options.constructType,\n ),\n joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'app', 'apis'),\n { ...options, ...terraformProviderVersions() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n};\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateJson","addStarExport","esmVars","addDependencyToTargetIfNotPresent","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","SHARED_TERRAFORM_DIR","PY_VERSIONS","terraformProviderVersions","addApiGatewayInfra","tree","options","iac","addApiGatewayCdkConstructs","addApiGatewayTerraformModules","Error","config","apiProjectName","generateCoreApiFile","name","dirname","overwriteStrategy","KeepExisting","constructType","backend","type","apiNameKebabCase","boto3Version","boto3"],"mappings":"AAAA;;;CAGC,GACD,SACEA,aAAa,EACbC,iBAAiB,EACjBC,iBAAiB,EAGjBC,UAAU,QACL,aAAa;AACpB,SAASC,aAAa,QAAQ,YAAS;AAEvC,SAASC,OAAO,QAAQ,sBAAmB;AAC3C,SAASC,iCAAiC,QAAQ,WAAQ;AAC1D,SACEC,YAAY,EACZC,qBAAqB,EACrBC,oBAAoB,QACf,oCAAiC;AACxC,SAASC,WAAW,EAAEC,yBAAyB,QAAQ,iBAAc;AAmCrE,OAAO,MAAMC,qBAAqB,OAChCC,MACAC;IAEA,IAAIA,QAAQC,GAAG,KAAK,OAAO;QACzB,MAAMC,2BAA2BH,MAAMC;IACzC,OAAO,IAAIA,QAAQC,GAAG,KAAK,aAAa;QACtCE,8BAA8BJ,MAAMC;IACtC,OAAO;QACL,MAAM,IAAII,MAAM,CAAC,gBAAgB,EAAEJ,QAAQC,GAAG,EAAE;IAClD;IAEAZ,WACEU,MACAZ,kBACEM,cACAO,QAAQC,GAAG,KAAK,QAAQP,wBAAwBC,sBAChD,iBAEF,CAACU;QACCb,kCACEa,QACA,SACA,GAAGL,QAAQM,cAAc,CAAC,MAAM,CAAC;QAEnC,OAAOD;IACT;AAEJ,EAAE;AAEF;;CAEC,GACD,MAAMH,6BAA6B,OACjCH,MACAC;IAEA,MAAMO,sBAAsB,CAACC;QAC3BtB,cACEa,MACAZ,kBACE,YAAYsB,OAAO,EACnB,SACA,OACA,QACA,OACAD,OAEFrB,kBACEM,cACAC,uBACA,OACA,QACA,QAEF;YAAE,GAAGH,QAAQQ,KAAK;QAAC,GACnB;YACEW,mBAAmBtB,kBAAkBuB,YAAY;QACnD;IAEJ;IAEA,qDAAqD;IACrDJ,oBAAoBP,QAAQY,aAAa;IACzCL,oBAAoB;IACpB,IAAIP,QAAQa,OAAO,CAACC,IAAI,KAAK,QAAQ;QACnCP,oBAAoB;IACtB;IAEA,sCAAsC;IACtCrB,cACEa,MACAZ,kBACE,YAAYsB,OAAO,EACnB,SACA,OACA,OACA,QACAT,QAAQY,aAAa,GAEvBzB,kBACEM,cACAC,uBACA,OACA,OACA,SAEF;QAAE,GAAGM,OAAO;QAAE,GAAGT,QAAQQ,KAAK;IAAC,GAC/B;QACEW,mBAAmBtB,kBAAkBuB,YAAY;IACnD;IAGF,oCAAoC;IACpC,MAAMrB,cACJS,MACAZ,kBACEM,cACAC,uBACA,OACA,OACA,QACA,aAEF,CAAC,EAAE,EAAEM,QAAQe,gBAAgB,CAAC,GAAG,CAAC;IAEpC,MAAMzB,cACJS,MACAZ,kBACEM,cACAC,uBACA,OACA,OACA,aAEF;AAEJ;AAEA;;CAEC,GACD,MAAMS,gCAAgC,CACpCJ,MACAC;IAEA,iCAAiC;IACjCd,cACEa,MACAZ,kBACE,YAAYsB,OAAO,EACnB,SACA,aACA,QACA,OACAT,QAAQY,aAAa,GAEvBzB,kBAAkBM,cAAcE,sBAAsB,OAAO,QAAQ,QACrE;QAAEqB,cAAcpB,YAAYqB,KAAK;QAAE,GAAGpB,2BAA2B;IAAC,GAClE;QACEa,mBAAmBtB,kBAAkBuB,YAAY;IACnD;IAGF,yCAAyC;IACzCzB,cACEa,MACAZ,kBACE,YAAYsB,OAAO,EACnB,SACA,aACA,OACA,QACAT,QAAQY,aAAa,GAEvBzB,kBAAkBM,cAAcE,sBAAsB,OAAO,OAAO,SACpE;QAAE,GAAGK,OAAO;QAAE,GAAGH,2BAA2B;IAAC,GAC7C;QACEa,mBAAmBtB,kBAAkBuB,YAAY;IACnD;AAEJ"}
@@ -13,7 +13,7 @@ import {
13
13
  <%_ } _%>
14
14
  } from 'aws-cdk-lib/aws-lambda';
15
15
  import { Duration<%_ if (backend.type === 'fastapi') { _%>, Stack<%_ } _%> } from 'aws-cdk-lib';
16
- import { RuntimeConfig } from '../../core/runtime-config.js';
16
+ import { RuntimeConfig } from '../../core/runtime-config<% if (esm) { %>.js<% } %>';
17
17
  import {
18
18
  CorsHttpMethod,
19
19
  CfnApi,
@@ -41,10 +41,10 @@ import {
41
41
  ApiIntegrations,
42
42
  HttpApiIntegration,
43
43
  IntegrationBuilder,
44
- } from '../../core/api/utils.js';
45
- import { HttpApi } from '../../core/api/http-api.js';
44
+ } from '../../core/api/utils<% if (esm) { %>.js<% } %>';
45
+ import { HttpApi } from '../../core/api/http-api<% if (esm) { %>.js<% } %>';
46
46
  <%_ if (backend.type === 'trpc') { _%>
47
- import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
47
+ import { Procedures, routerToOperations } from '../../core/api/trpc-utils<% if (esm) { %>.js<% } %>';
48
48
  import { AppRouter, appRouter } from '<%= backend.projectAlias %>';
49
49
 
50
50
  // String union type for all API operation names
@@ -116,7 +116,7 @@ export class <%= apiNameClassName %><
116
116
  url.fileURLToPath(
117
117
  new URL(
118
118
  '../../../../../../<%- backend.bundleOutputDir %>',
119
- import.meta.url,
119
+ <% if (esm) { %>import.meta.url<% } else { %>require('url').pathToFileURL(__filename).href<% } %>,
120
120
  ),
121
121
  ),
122
122
  ),
@@ -127,7 +127,7 @@ export class <%= apiNameClassName %><
127
127
  url.fileURLToPath(
128
128
  new URL(
129
129
  '../../../../../../<%- backend.bundleOutputDir %>',
130
- import.meta.url,
130
+ <% if (esm) { %>import.meta.url<% } else { %>require('url').pathToFileURL(__filename).href<% } %>,
131
131
  ),
132
132
  ),
133
133
  ),
@@ -184,7 +184,7 @@ export class <%= apiNameClassName %><
184
184
  url.fileURLToPath(
185
185
  new URL(
186
186
  '../../../../../../<%- backend.authorizerBundleOutputDir %>',
187
- import.meta.url,
187
+ <% if (esm) { %>import.meta.url<% } else { %>require('url').pathToFileURL(__filename).href<% } %>,
188
188
  ),
189
189
  ),
190
190
  ),
@@ -195,7 +195,7 @@ export class <%= apiNameClassName %><
195
195
  url.fileURLToPath(
196
196
  new URL(
197
197
  '../../../../../../<%- backend.bundleOutputDir %>',
198
- import.meta.url,
198
+ <% if (esm) { %>import.meta.url<% } else { %>require('url').pathToFileURL(__filename).href<% } %>,
199
199
  ),
200
200
  ),
201
201
  ),
@@ -12,7 +12,7 @@ import {
12
12
  SnapStartConf,
13
13
  <%_ } _%>
14
14
  } from 'aws-cdk-lib/aws-lambda';
15
- import { RuntimeConfig } from '../../core/runtime-config.js';
15
+ import { RuntimeConfig } from '../../core/runtime-config<% if (esm) { %>.js<% } %>';
16
16
  import {
17
17
  AuthorizationType,
18
18
  LambdaIntegration,
@@ -44,10 +44,10 @@ import {
44
44
  ApiIntegrations,
45
45
  IntegrationBuilder,
46
46
  RestApiIntegration,
47
- } from '../../core/api/utils.js';
48
- import { AddCorsPreflightAspect, RestApi } from '../../core/api/rest-api.js';
47
+ } from '../../core/api/utils<% if (esm) { %>.js<% } %>';
48
+ import { AddCorsPreflightAspect, RestApi } from '../../core/api/rest-api<% if (esm) { %>.js<% } %>';
49
49
  <%_ if (backend.type === 'trpc') { _%>
50
- import { Procedures, routerToOperations } from '../../core/api/trpc-utils.js';
50
+ import { Procedures, routerToOperations } from '../../core/api/trpc-utils<% if (esm) { %>.js<% } %>';
51
51
  import { AppRouter, appRouter } from '<%= backend.projectAlias %>';
52
52
 
53
53
  // String union type for all API operation names
@@ -126,7 +126,7 @@ export class <%= apiNameClassName %><
126
126
  url.fileURLToPath(
127
127
  new URL(
128
128
  '../../../../../../<%- backend.bundleOutputDir %>',
129
- import.meta.url,
129
+ <% if (esm) { %>import.meta.url<% } else { %>require('url').pathToFileURL(__filename).href<% } %>,
130
130
  ),
131
131
  ),
132
132
  ),
@@ -137,7 +137,7 @@ export class <%= apiNameClassName %><
137
137
  url.fileURLToPath(
138
138
  new URL(
139
139
  '../../../../../../<%- backend.bundleOutputDir %>',
140
- import.meta.url,
140
+ <% if (esm) { %>import.meta.url<% } else { %>require('url').pathToFileURL(__filename).href<% } %>,
141
141
  ),
142
142
  ),
143
143
  ),
@@ -204,7 +204,7 @@ export class <%= apiNameClassName %><
204
204
  url.fileURLToPath(
205
205
  new URL(
206
206
  '../../../../../../<%- backend.authorizerBundleOutputDir %>',
207
- import.meta.url,
207
+ <% if (esm) { %>import.meta.url<% } else { %>require('url').pathToFileURL(__filename).href<% } %>,
208
208
  ),
209
209
  ),
210
210
  ),
@@ -215,7 +215,7 @@ export class <%= apiNameClassName %><
215
215
  url.fileURLToPath(
216
216
  new URL(
217
217
  '../../../../../../<%- backend.bundleOutputDir %>',
218
- import.meta.url,
218
+ <% if (esm) { %>import.meta.url<% } else { %>require('url').pathToFileURL(__filename).href<% } %>,
219
219
  ),
220
220
  ),
221
221
  ),
@@ -1,10 +1,10 @@
1
1
  import { Construct } from 'constructs';
2
- import { RuntimeConfig } from '../runtime-config.js';
2
+ import { RuntimeConfig } from '../runtime-config<% if (esm) { %>.js<% } %>';
3
3
  import {
4
4
  ApiIntegrations,
5
5
  HttpApiIntegration,
6
6
  OperationDetails,
7
- } from './utils.js';
7
+ } from './utils<% if (esm) { %>.js<% } %>';
8
8
  import { CfnOutput, Stack } from 'aws-cdk-lib';
9
9
  import {
10
10
  HttpApi as _HttpApi,
@@ -17,7 +17,7 @@ import {
17
17
  import { LogGroup } from 'aws-cdk-lib/aws-logs';
18
18
  import { Key } from 'aws-cdk-lib/aws-kms';
19
19
  import { ServicePrincipal } from 'aws-cdk-lib/aws-iam';
20
- import { suppressRules } from '../checkov.js';
20
+ import { suppressRules } from '../checkov<% if (esm) { %>.js<% } %>';
21
21
 
22
22
  /**
23
23
  * Properties for creating an HttpApi construct.
@@ -16,32 +16,23 @@ const iam = new IAMClient();
16
16
 
17
17
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
18
18
 
19
- const hasLiveRole = async () => {
20
- const { cloudwatchRoleArn } = await apigw.send(new GetAccountCommand({}));
21
- if (!cloudwatchRoleArn) return false;
22
- try {
23
- await iam.send(
24
- new GetRoleCommand({ RoleName: cloudwatchRoleArn.split('/').pop() }),
25
- );
26
- return true;
27
- } catch (e) {
28
- if (e.name === 'NoSuchEntityException') return false;
29
- throw e;
30
- }
31
- };
32
-
33
19
  const RETRYABLE = ['BadRequestException', 'TooManyRequestsException'];
34
20
 
35
- const setRole = async (value) => {
36
- const command = new UpdateAccountCommand({
37
- patchOperations: [{ op: 'replace', path: '/cloudwatchRoleArn', value }],
38
- });
39
- // Retry while the freshly created role propagates through IAM, and on throttling
21
+ // Throttling may surface as a bare 429 with no modeled error code, so check
22
+ // response metadata as well as error names
23
+ const isRetryable = (e) =>
24
+ RETRYABLE.includes(e.name) ||
25
+ e.$metadata?.httpStatusCode === 429 ||
26
+ e.$retryable?.throttling === true;
27
+
28
+ // Retry while the freshly created role propagates through IAM, and on
29
+ // throttling of the account-level API (shared across concurrent deployments)
30
+ const send = async (command) => {
40
31
  for (let attempt = 0; ; attempt++) {
41
32
  try {
42
33
  return await apigw.send(command);
43
34
  } catch (e) {
44
- if (RETRYABLE.includes(e.name) && attempt < 11) {
35
+ if (isRetryable(e) && attempt < 11) {
45
36
  await sleep(5000);
46
37
  } else {
47
38
  throw e;
@@ -50,6 +41,27 @@ const setRole = async (value) => {
50
41
  }
51
42
  };
52
43
 
44
+ const hasLiveRole = async () => {
45
+ const { cloudwatchRoleArn } = await send(new GetAccountCommand({}));
46
+ if (!cloudwatchRoleArn) return false;
47
+ try {
48
+ await iam.send(
49
+ new GetRoleCommand({ RoleName: cloudwatchRoleArn.split('/').pop() }),
50
+ );
51
+ return true;
52
+ } catch (e) {
53
+ if (e.name === 'NoSuchEntityException') return false;
54
+ throw e;
55
+ }
56
+ };
57
+
58
+ const setRole = (value) =>
59
+ send(
60
+ new UpdateAccountCommand({
61
+ patchOperations: [{ op: 'replace', path: '/cloudwatchRoleArn', value }],
62
+ }),
63
+ );
64
+
53
65
  exports.handler = async (event) => {
54
66
  if (event.RequestType !== 'Delete' && !(await hasLiveRole())) {
55
67
  await setRole(event.ResourceProperties.CloudWatchRoleArn);
@@ -50,7 +50,7 @@ export class ApiGatewayAccount extends Construct {
50
50
  handler: 'index.handler',
51
51
  timeout: Duration.minutes(2),
52
52
  code: Code.fromAsset(
53
- url.fileURLToPath(new URL('./api-gateway-account', import.meta.url)),
53
+ url.fileURLToPath(new URL('./api-gateway-account', <% if (esm) { %>import.meta.url<% } else { %>require('url').pathToFileURL(__filename).href<% } %>)),
54
54
  ),
55
55
  });
56
56
  const { region } = Stack.of(this);
@@ -19,14 +19,14 @@ import {
19
19
  import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs';
20
20
  import { Key } from 'aws-cdk-lib/aws-kms';
21
21
  import { ServicePrincipal } from 'aws-cdk-lib/aws-iam';
22
- import { RuntimeConfig } from '../runtime-config.js';
23
- import { ApiGatewayAccount } from './api-gateway-account.js';
22
+ import { RuntimeConfig } from '../runtime-config<% if (esm) { %>.js<% } %>';
23
+ import { ApiGatewayAccount } from './api-gateway-account<% if (esm) { %>.js<% } %>';
24
24
  import {
25
25
  ApiIntegrations,
26
26
  OperationDetails,
27
27
  RestApiIntegration,
28
- } from './utils.js';
29
- import { suppressRules } from '../checkov.js';
28
+ } from './utils<% if (esm) { %>.js<% } %>';
29
+ import { suppressRules } from '../checkov<% if (esm) { %>.js<% } %>';
30
30
 
31
31
  /**
32
32
  * Properties for creating a RestApi construct.
@@ -1,5 +1,5 @@
1
1
  import { TRPCRouterRecord, AnyTRPCRouter } from '@trpc/server';
2
- import { OperationDetails } from './utils.js';
2
+ import { OperationDetails } from './utils<% if (esm) { %>.js<% } %>';
3
3
  import { HttpMethod } from 'aws-cdk-lib/aws-apigatewayv2';
4
4
 
5
5
  /**
@@ -43,6 +43,30 @@ variable "asset_bucket_name" {
43
43
  type = string
44
44
  }
45
45
 
46
+ # VPC Configuration (optional)
47
+ variable "enable_vpc" {
48
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
49
+ type = bool
50
+ default = false
51
+ }
52
+
53
+ variable "vpc_id" {
54
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
55
+ type = string
56
+ default = null
57
+
58
+ validation {
59
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
60
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
61
+ }
62
+ }
63
+
64
+ variable "subnet_ids" {
65
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
66
+ type = list(string)
67
+ default = null
68
+ }
69
+
46
70
  # CORS Configuration (passed to core module)
47
71
  variable "cors_allow_credentials" {
48
72
  description = "Whether to allow credentials in CORS requests"
@@ -129,10 +153,32 @@ module "http_api" {
129
153
  tags = var.tags
130
154
  }
131
155
 
156
+ # Security group for the API Lambda function, used when deployed into a VPC
157
+ resource "aws_security_group" "api_lambda" {
158
+ count = var.enable_vpc ? 1 : 0
159
+
160
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
161
+ name_prefix = "<%- apiNameKebabCase %>-lambda-"
162
+ description = "Security group for the <%- apiNameClassName %> API Lambda function"
163
+ vpc_id = var.vpc_id
164
+ tags = var.tags
165
+ }
166
+
167
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
168
+ count = var.enable_vpc ? 1 : 0
169
+
170
+ security_group_id = aws_security_group.api_lambda[0].id
171
+ cidr_ipv4 = "0.0.0.0/0"
172
+ from_port = 443
173
+ to_port = 443
174
+ ip_protocol = "tcp"
175
+ description = "Allow outbound HTTPS to AWS service endpoints"
176
+ }
177
+
132
178
  # Lambda function
133
179
  # This configures a single "router" lambda to serve all requests
134
180
  resource "aws_lambda_function" "api_lambda" {
135
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
181
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
136
182
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
137
183
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
138
184
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -163,6 +209,14 @@ resource "aws_lambda_function" "api_lambda" {
163
209
  mode = "Active"
164
210
  }
165
211
 
212
+ dynamic "vpc_config" {
213
+ for_each = var.enable_vpc ? [1] : []
214
+ content {
215
+ subnet_ids = var.subnet_ids
216
+ security_group_ids = [aws_security_group.api_lambda[0].id]
217
+ }
218
+ }
219
+
166
220
  <%_ if (backend.type === 'fastapi') { _%>
167
221
  # Enable SnapStart for faster cold starts
168
222
  snap_start {
@@ -181,6 +235,8 @@ resource "aws_lambda_function" "api_lambda" {
181
235
  }
182
236
 
183
237
  tags = var.tags
238
+
239
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
184
240
  }
185
241
 
186
242
  # IAM role for Lambda execution
@@ -215,6 +271,13 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
215
271
  role = aws_iam_role.lambda_execution_role.name
216
272
  }
217
273
 
274
+ # Attach VPC access policy to Lambda role when deployed into a VPC
275
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
276
+ count = var.enable_vpc ? 1 : 0
277
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
278
+ role = aws_iam_role.lambda_execution_role.name
279
+ }
280
+
218
281
  # Additional IAM policies for Lambda (if provided)
219
282
  resource "aws_iam_role_policy" "lambda_additional_policies" {
220
283
  count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
@@ -527,6 +590,11 @@ output "lambda_execution_role_name" {
527
590
  value = aws_iam_role.lambda_execution_role.name
528
591
  }
529
592
 
593
+ output "security_group_id" {
594
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
595
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
596
+ }
597
+
530
598
  # Integration Outputs
531
599
  output "integration_id" {
532
600
  description = "ID of the Lambda integration"
@@ -43,6 +43,30 @@ variable "asset_bucket_name" {
43
43
  type = string
44
44
  }
45
45
 
46
+ # VPC Configuration (optional)
47
+ variable "enable_vpc" {
48
+ description = "Deploy the Lambda function into a VPC. Set alongside vpc_id/subnet_ids."
49
+ type = bool
50
+ default = false
51
+ }
52
+
53
+ variable "vpc_id" {
54
+ description = "VPC ID to deploy the Lambda function into. Required when enable_vpc is true."
55
+ type = string
56
+ default = null
57
+
58
+ validation {
59
+ condition = !var.enable_vpc || (var.vpc_id != null && var.subnet_ids != null)
60
+ error_message = "vpc_id and subnet_ids must be set when enable_vpc is true."
61
+ }
62
+ }
63
+
64
+ variable "subnet_ids" {
65
+ description = "Subnet IDs to deploy the Lambda function into. Required when enable_vpc is true."
66
+ type = list(string)
67
+ default = null
68
+ }
69
+
46
70
  # CORS Configuration (passed to core module)
47
71
 
48
72
  variable "cors_allow_headers" {
@@ -139,9 +163,31 @@ resource "aws_wafv2_web_acl_association" "api_waf_association" {
139
163
  depends_on = [aws_api_gateway_stage.api_stage]
140
164
  }
141
165
 
166
+ # Security group for the API Lambda function, used when deployed into a VPC
167
+ resource "aws_security_group" "api_lambda" {
168
+ count = var.enable_vpc ? 1 : 0
169
+
170
+ #checkov:skip=CKV2_AWS_5:Attached to api_lambda via vpc_config block; Checkov cannot resolve this reference
171
+ name_prefix = "<%- apiNameKebabCase %>-lambda-"
172
+ description = "Security group for the <%- apiNameClassName %> API Lambda function"
173
+ vpc_id = var.vpc_id
174
+ tags = var.tags
175
+ }
176
+
177
+ resource "aws_vpc_security_group_egress_rule" "api_lambda_https" {
178
+ count = var.enable_vpc ? 1 : 0
179
+
180
+ security_group_id = aws_security_group.api_lambda[0].id
181
+ cidr_ipv4 = "0.0.0.0/0"
182
+ from_port = 443
183
+ to_port = 443
184
+ ip_protocol = "tcp"
185
+ description = "Allow outbound HTTPS to AWS service endpoints"
186
+ }
187
+
142
188
  # Lambda function
143
189
  resource "aws_lambda_function" "api_lambda" {
144
- #checkov:skip=CKV_AWS_117:Lambda function does not need to be in VPC for this use case
190
+ #checkov:skip=CKV_AWS_117:Lambda function is optionally deployed into a VPC via vpc_id/subnet_ids; not required for this use case
145
191
  #checkov:skip=CKV_AWS_116:Dead Letter Queue not required for this simple API use case
146
192
  #checkov:skip=CKV_AWS_272:Code signing not required for this use case
147
193
  #checkov:skip=CKV_AWS_115:Concurrent execution limit not required for this use case
@@ -172,6 +218,14 @@ resource "aws_lambda_function" "api_lambda" {
172
218
  mode = "Active"
173
219
  }
174
220
 
221
+ dynamic "vpc_config" {
222
+ for_each = var.enable_vpc ? [1] : []
223
+ content {
224
+ subnet_ids = var.subnet_ids
225
+ security_group_ids = [aws_security_group.api_lambda[0].id]
226
+ }
227
+ }
228
+
175
229
  <%_ if (backend.type === 'fastapi') { _%>
176
230
  # Enable SnapStart for faster cold starts
177
231
  snap_start {
@@ -190,6 +244,8 @@ resource "aws_lambda_function" "api_lambda" {
190
244
  }
191
245
 
192
246
  tags = var.tags
247
+
248
+ depends_on = [aws_iam_role_policy_attachment.lambda_vpc_access]
193
249
  }
194
250
 
195
251
  # IAM role for Lambda execution
@@ -224,6 +280,13 @@ resource "aws_iam_role_policy_attachment" "lambda_xray_execution" {
224
280
  role = aws_iam_role.lambda_execution_role.name
225
281
  }
226
282
 
283
+ # Attach VPC access policy to Lambda role when deployed into a VPC
284
+ resource "aws_iam_role_policy_attachment" "lambda_vpc_access" {
285
+ count = var.enable_vpc ? 1 : 0
286
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
287
+ role = aws_iam_role.lambda_execution_role.name
288
+ }
289
+
227
290
  # Additional IAM policies for Lambda (if provided)
228
291
  resource "aws_iam_role_policy" "lambda_additional_policies" {
229
292
  count = length(var.additional_iam_policy_statements) > 0 ? 1 : 0
@@ -794,6 +857,11 @@ output "lambda_execution_role_name" {
794
857
  value = aws_iam_role.lambda_execution_role.name
795
858
  }
796
859
 
860
+ output "security_group_id" {
861
+ description = "Security group ID of the API Lambda function, for use in ingress rules on resources it must reach (e.g. a database). Null unless enable_vpc is true."
862
+ value = var.enable_vpc ? aws_security_group.api_lambda[0].id : null
863
+ }
864
+
797
865
  # Integration Outputs
798
866
  output "integration_id" {
799
867
  description = "ID of the Lambda integration"