@aws/nx-plugin 1.0.0-rc.4 → 1.0.0-rc.41

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 (1138) hide show
  1. package/LICENSE-THIRD-PARTY +5449 -4980
  2. package/README.md +7 -7
  3. package/executors.json +9 -0
  4. package/generators.json +101 -2
  5. package/package.json +35 -17
  6. package/src/agentcore-gateway/attach-upstream.d.ts +33 -0
  7. package/src/agentcore-gateway/attach-upstream.js +38 -0
  8. package/src/agentcore-gateway/attach-upstream.js.map +1 -0
  9. package/src/agentcore-gateway/files/cedar/policies/README.md +52 -0
  10. package/src/agentcore-gateway/files/cedar/policies/permit-all.cedar +11 -0
  11. package/src/agentcore-gateway/files/project/local-dev.ts.template +134 -0
  12. package/src/agentcore-gateway/gateway-connection/generator.d.ts +21 -0
  13. package/src/agentcore-gateway/gateway-connection/generator.js +101 -0
  14. package/src/agentcore-gateway/gateway-connection/generator.js.map +1 -0
  15. package/src/agentcore-gateway/gateway-connection/schema.d.js +6 -0
  16. package/src/agentcore-gateway/gateway-connection/schema.d.js.map +1 -0
  17. package/src/agentcore-gateway/gateway-connection/schema.d.ts +13 -0
  18. package/src/agentcore-gateway/gateway-connection/schema.json +31 -0
  19. package/src/agentcore-gateway/generator.d.ts +25 -0
  20. package/src/agentcore-gateway/generator.js +149 -0
  21. package/src/agentcore-gateway/generator.js.map +1 -0
  22. package/src/agentcore-gateway/mcp-connection/generator.d.ts +19 -0
  23. package/src/agentcore-gateway/mcp-connection/generator.js +59 -0
  24. package/src/agentcore-gateway/mcp-connection/generator.js.map +1 -0
  25. package/src/agentcore-gateway/mcp-connection/schema.d.js +6 -0
  26. package/src/agentcore-gateway/mcp-connection/schema.d.js.map +1 -0
  27. package/src/agentcore-gateway/mcp-connection/schema.d.ts +13 -0
  28. package/src/agentcore-gateway/mcp-connection/schema.json +31 -0
  29. package/src/agentcore-gateway/schema.d.js +6 -0
  30. package/src/agentcore-gateway/schema.d.js.map +1 -0
  31. package/src/agentcore-gateway/schema.d.ts +17 -0
  32. package/src/agentcore-gateway/schema.json +70 -0
  33. package/src/bin/aws-nx-mcp.js +14 -0
  34. package/src/bin/aws-nx-mcp.js.map +1 -0
  35. package/src/connection/{agent-serve-local.d.ts → agent-local-dev.d.ts} +7 -7
  36. package/src/connection/agent-local-dev.js +42 -0
  37. package/src/connection/agent-local-dev.js.map +1 -0
  38. package/src/connection/agent-runtime-config.d.ts +1 -1
  39. package/src/connection/agent-runtime-config.js +9 -14
  40. package/src/connection/agent-runtime-config.js.map +1 -1
  41. package/src/connection/generator.d.ts +7 -14
  42. package/src/connection/generator.js +167 -194
  43. package/src/connection/generator.js.map +1 -1
  44. package/src/connection/local-dev.d.ts +15 -0
  45. package/src/connection/local-dev.js +37 -0
  46. package/src/connection/local-dev.js.map +1 -0
  47. package/src/connection/schema.d.js +6 -0
  48. package/src/connection/schema.d.js.map +1 -0
  49. package/src/connection/schema.d.ts +1 -0
  50. package/src/connection/schema.json +5 -0
  51. package/src/connection/supported-connections.d.ts +107 -0
  52. package/src/connection/supported-connections.js +151 -0
  53. package/src/connection/supported-connections.js.map +1 -0
  54. package/src/index.js +2 -5
  55. package/src/index.js.map +1 -1
  56. package/src/infra/app/__snapshots__/generator.spec.ts.snap +97 -85
  57. package/src/infra/app/files/app/src/main.ts.template +1 -1
  58. package/src/infra/app/files/app/src/stages/application-stage.ts.template +1 -1
  59. package/src/infra/app/generator.d.ts +3 -3
  60. package/src/infra/app/generator.js +142 -122
  61. package/src/infra/app/generator.js.map +1 -1
  62. package/src/infra/app/schema.d.js +6 -0
  63. package/src/infra/app/schema.d.js.map +1 -0
  64. package/src/infra/app/schema.d.ts +1 -1
  65. package/src/infra/app/schema.json +5 -0
  66. package/src/init/generator.d.ts +18 -0
  67. package/src/init/generator.js +35 -0
  68. package/src/init/generator.js.map +1 -0
  69. package/src/init/schema.d.js +6 -0
  70. package/src/init/schema.d.js.map +1 -0
  71. package/src/init/schema.d.ts +16 -0
  72. package/src/init/schema.json +35 -0
  73. package/src/license/__snapshots__/config.spec.ts.snap +23 -0
  74. package/src/license/config-types.d.ts +18 -1
  75. package/src/license/config-types.js +8 -2
  76. package/src/license/config-types.js.map +1 -1
  77. package/src/license/config.d.ts +65 -7
  78. package/src/license/config.js +442 -109
  79. package/src/license/config.js.map +1 -1
  80. package/src/license/dependency-check/check.d.ts +16 -0
  81. package/src/license/dependency-check/check.js +116 -0
  82. package/src/license/dependency-check/check.js.map +1 -0
  83. package/src/license/dependency-check/collectors/collector.d.ts +21 -0
  84. package/src/license/dependency-check/collectors/collector.js +46 -0
  85. package/src/license/dependency-check/collectors/collector.js.map +1 -0
  86. package/src/license/dependency-check/collectors/npm-collector.d.ts +10 -0
  87. package/src/license/dependency-check/collectors/npm-collector.js +68 -0
  88. package/src/license/dependency-check/collectors/npm-collector.js.map +1 -0
  89. package/src/license/dependency-check/collectors/python-collector.d.ts +23 -0
  90. package/src/license/dependency-check/collectors/python-collector.js +114 -0
  91. package/src/license/dependency-check/collectors/python-collector.js.map +1 -0
  92. package/src/license/dependency-check/evaluator.d.ts +9 -0
  93. package/src/license/dependency-check/evaluator.js +94 -0
  94. package/src/license/dependency-check/evaluator.js.map +1 -0
  95. package/src/license/dependency-check/executor-schema.json +6 -0
  96. package/src/license/dependency-check/executor.d.ts +9 -0
  97. package/src/license/dependency-check/executor.js +51 -0
  98. package/src/license/dependency-check/executor.js.map +1 -0
  99. package/src/license/dependency-check/pre-approved.d.ts +6 -0
  100. package/src/license/dependency-check/pre-approved.js +1893 -0
  101. package/src/license/dependency-check/pre-approved.js.map +1 -0
  102. package/src/license/dependency-check/types.d.ts +45 -0
  103. package/src/license/dependency-check/types.js +6 -0
  104. package/src/license/dependency-check/types.js.map +1 -0
  105. package/src/license/generator.d.ts +3 -3
  106. package/src/license/generator.js +126 -30
  107. package/src/license/generator.js.map +1 -1
  108. package/src/license/index.d.ts +8 -0
  109. package/src/license/index.js +7 -0
  110. package/src/license/index.js.map +1 -0
  111. package/src/license/known-exceptions.d.ts +7 -0
  112. package/src/license/known-exceptions.js +39 -0
  113. package/src/license/known-exceptions.js.map +1 -0
  114. package/src/license/schema.d.js +6 -0
  115. package/src/license/schema.d.js.map +1 -0
  116. package/src/license/schema.d.ts +7 -0
  117. package/src/license/schema.json +11 -0
  118. package/src/license/sync/generator.d.ts +2 -2
  119. package/src/license/sync/generator.js +100 -125
  120. package/src/license/sync/generator.js.map +1 -1
  121. package/src/license/sync/project-file-sync.d.ts +3 -3
  122. package/src/license/sync/project-file-sync.js +28 -35
  123. package/src/license/sync/project-file-sync.js.map +1 -1
  124. package/src/mcp-server/generator-info.d.ts +5 -1
  125. package/src/mcp-server/generator-info.js +149 -165
  126. package/src/mcp-server/generator-info.js.map +1 -1
  127. package/src/mcp-server/guide-pipeline.d.ts +1 -1
  128. package/src/mcp-server/guide-pipeline.js +199 -206
  129. package/src/mcp-server/guide-pipeline.js.map +1 -1
  130. package/src/mcp-server/guide-render.js +10 -25
  131. package/src/mcp-server/guide-render.js.map +1 -1
  132. package/src/mcp-server/index.js +6 -10
  133. package/src/mcp-server/index.js.map +1 -1
  134. package/src/mcp-server/mdx-ast.js +42 -56
  135. package/src/mcp-server/mdx-ast.js.map +1 -1
  136. package/src/mcp-server/option-filter.js +33 -47
  137. package/src/mcp-server/option-filter.js.map +1 -1
  138. package/src/mcp-server/schema-registry.d.ts +9 -3
  139. package/src/mcp-server/schema-registry.js +41 -38
  140. package/src/mcp-server/schema-registry.js.map +1 -1
  141. package/src/mcp-server/schema.js +9 -7
  142. package/src/mcp-server/schema.js.map +1 -1
  143. package/src/mcp-server/server.js +22 -24
  144. package/src/mcp-server/server.js.map +1 -1
  145. package/src/mcp-server/tools/add-to-existing-project.d.ts +12 -0
  146. package/src/mcp-server/tools/add-to-existing-project.js +36 -0
  147. package/src/mcp-server/tools/add-to-existing-project.js.map +1 -0
  148. package/src/mcp-server/tools/create-workspace-command.d.ts +1 -1
  149. package/src/mcp-server/tools/create-workspace-command.js +23 -24
  150. package/src/mcp-server/tools/create-workspace-command.js.map +1 -1
  151. package/src/mcp-server/tools/general-guidance.d.ts +3 -3
  152. package/src/mcp-server/tools/general-guidance.js +47 -25
  153. package/src/mcp-server/tools/general-guidance.js.map +1 -1
  154. package/src/mcp-server/tools/generator-guide.d.ts +2 -2
  155. package/src/mcp-server/tools/generator-guide.js +29 -37
  156. package/src/mcp-server/tools/generator-guide.js.map +1 -1
  157. package/src/mcp-server/tools/list-generators.d.ts +2 -2
  158. package/src/mcp-server/tools/list-generators.js +19 -25
  159. package/src/mcp-server/tools/list-generators.js.map +1 -1
  160. package/src/open-api/ts-client/__snapshots__/generator.additional-properties.spec.ts.snap +147 -33
  161. package/src/open-api/ts-client/__snapshots__/generator.arrays.spec.ts.snap +308 -75
  162. package/src/open-api/ts-client/__snapshots__/generator.complex-types.spec.ts.snap +298 -74
  163. package/src/open-api/ts-client/__snapshots__/generator.composite-types.spec.ts.snap +748 -103
  164. package/src/open-api/ts-client/__snapshots__/generator.content-type.spec.ts.snap +230 -37
  165. package/src/open-api/ts-client/__snapshots__/generator.duplicate-types.spec.ts.snap +249 -52
  166. package/src/open-api/ts-client/__snapshots__/generator.edge-cases.spec.ts.snap +5535 -0
  167. package/src/open-api/ts-client/__snapshots__/generator.fast-api-gaps.spec.ts.snap +736 -0
  168. package/src/open-api/ts-client/__snapshots__/generator.fast-api.spec.ts.snap +305 -71
  169. package/src/open-api/ts-client/__snapshots__/generator.multipart.spec.ts.snap +298 -0
  170. package/src/open-api/ts-client/__snapshots__/generator.primitive-types.spec.ts.snap +353 -82
  171. package/src/open-api/ts-client/__snapshots__/generator.request.spec.ts.snap +176 -55
  172. package/src/open-api/ts-client/__snapshots__/generator.reserved-keywords.spec.ts.snap +101 -25
  173. package/src/open-api/ts-client/__snapshots__/generator.response.spec.ts.snap +147 -33
  174. package/src/open-api/ts-client/__snapshots__/generator.spec-compliance.spec.ts.snap +1883 -0
  175. package/src/open-api/ts-client/__snapshots__/generator.streaming.spec.ts.snap +392 -88
  176. package/src/open-api/ts-client/__snapshots__/generator.tags.spec.ts.snap +200 -48
  177. package/src/open-api/ts-client/files/client.gen.ts.template +358 -24
  178. package/src/open-api/ts-client/files/types.gen.ts.template +6 -4
  179. package/src/open-api/ts-client/generator.d.ts +3 -3
  180. package/src/open-api/ts-client/generator.js +41 -26
  181. package/src/open-api/ts-client/generator.js.map +1 -1
  182. package/src/open-api/ts-client/schema.d.js +6 -0
  183. package/src/open-api/ts-client/schema.d.js.map +1 -0
  184. package/src/open-api/ts-hooks/files/options-proxy.gen.ts.template +7 -2
  185. package/src/open-api/ts-hooks/generator.d.ts +3 -3
  186. package/src/open-api/ts-hooks/generator.js +17 -21
  187. package/src/open-api/ts-hooks/generator.js.map +1 -1
  188. package/src/open-api/ts-hooks/generator.spec.tsx +84 -14
  189. package/src/open-api/ts-hooks/schema.d.js +6 -0
  190. package/src/open-api/ts-hooks/schema.d.js.map +1 -0
  191. package/src/open-api/ts-metadata/generator.d.ts +3 -3
  192. package/src/open-api/ts-metadata/generator.js +12 -20
  193. package/src/open-api/ts-metadata/generator.js.map +1 -1
  194. package/src/open-api/ts-metadata/schema.d.js +6 -0
  195. package/src/open-api/ts-metadata/schema.d.js.map +1 -0
  196. package/src/open-api/utils/codegen-data/languages.d.ts +3 -5
  197. package/src/open-api/utils/codegen-data/languages.js +59 -66
  198. package/src/open-api/utils/codegen-data/languages.js.map +1 -1
  199. package/src/open-api/utils/codegen-data/types.d.ts +255 -10
  200. package/src/open-api/utils/codegen-data/types.js +54 -30
  201. package/src/open-api/utils/codegen-data/types.js.map +1 -1
  202. package/src/open-api/utils/codegen-data.d.ts +8 -4
  203. package/src/open-api/utils/codegen-data.js +494 -674
  204. package/src/open-api/utils/codegen-data.js.map +1 -1
  205. package/src/open-api/utils/normalise.d.ts +5 -1
  206. package/src/open-api/utils/normalise.js +437 -246
  207. package/src/open-api/utils/normalise.js.map +1 -1
  208. package/src/open-api/utils/parse.d.ts +2 -2
  209. package/src/open-api/utils/parse.js +11 -13
  210. package/src/open-api/utils/parse.js.map +1 -1
  211. package/src/open-api/utils/parser.d.ts +55 -0
  212. package/src/open-api/utils/parser.js +787 -0
  213. package/src/open-api/utils/parser.js.map +1 -0
  214. package/src/open-api/utils/refs.d.ts +1 -1
  215. package/src/open-api/utils/refs.js +12 -22
  216. package/src/open-api/utils/refs.js.map +1 -1
  217. package/src/open-api/utils/types.d.ts +18 -0
  218. package/src/open-api/utils/types.js +5 -2
  219. package/src/open-api/utils/types.js.map +1 -1
  220. package/src/preset/__snapshots__/generator.spec.ts.snap +109 -28
  221. package/src/preset/generator.d.ts +4 -4
  222. package/src/preset/generator.js +64 -147
  223. package/src/preset/generator.js.map +1 -1
  224. package/src/preset/schema.d.js +6 -0
  225. package/src/preset/schema.d.js.map +1 -0
  226. package/src/preset/schema.d.ts +5 -2
  227. package/src/preset/schema.json +11 -5
  228. package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +320 -0
  229. package/src/py/agent/__snapshots__/generator.frameworks.spec.ts.snap +734 -0
  230. package/src/py/agent/__snapshots__/{generator.spec.ts.snap → generator.protocols.spec.ts.snap} +182 -314
  231. package/src/py/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +189 -0
  232. package/src/py/agent/a2a-connection/files/agent-connection/app/__targetAgentSnakeCase___client_strands.py.template +30 -0
  233. package/src/py/agent/a2a-connection/files/langchain/agent-connection/app/__targetAgentSnakeCase___client_langchain.py.template +28 -0
  234. package/src/py/agent/a2a-connection/generator.d.ts +3 -3
  235. package/src/py/agent/a2a-connection/generator.js +113 -85
  236. package/src/py/agent/a2a-connection/generator.js.map +1 -1
  237. package/src/py/agent/a2a-connection/schema.d.js +8 -0
  238. package/src/py/agent/a2a-connection/schema.d.js.map +1 -0
  239. package/src/py/agent/a2a-connection/schema.d.ts +1 -0
  240. package/src/py/agent/a2a-connection/schema.json +5 -0
  241. package/src/py/agent/files/a2a-langchain/main.py.template +89 -0
  242. package/src/py/agent/files/ag-ui-langchain/main.py.template +83 -0
  243. package/src/py/agent/files/common/agent.py.template +2 -0
  244. package/src/py/agent/files/common-langchain/agent.py.template +30 -0
  245. package/src/py/agent/files/deploy/Dockerfile.template +1 -1
  246. package/src/py/agent/files/http/init.py.template +7 -25
  247. package/src/py/agent/files/http/main.py.template +3 -4
  248. package/src/py/agent/files/http-langchain/main.py.template +84 -0
  249. package/src/py/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +184 -0
  250. package/src/py/agent/gateway-connection/files/agent-connection/app/__gatewaySnakeCase___client_strands.py.template +35 -0
  251. package/src/py/agent/gateway-connection/files/langchain/agent-connection/app/__gatewaySnakeCase___client_langchain.py.template +34 -0
  252. package/src/py/agent/gateway-connection/generator.d.ts +10 -0
  253. package/src/py/agent/gateway-connection/generator.js +119 -0
  254. package/src/py/agent/gateway-connection/generator.js.map +1 -0
  255. package/src/py/agent/gateway-connection/schema.d.js +6 -0
  256. package/src/py/agent/gateway-connection/schema.d.js.map +1 -0
  257. package/src/py/agent/gateway-connection/schema.d.ts +13 -0
  258. package/src/py/agent/gateway-connection/schema.json +31 -0
  259. package/src/py/agent/generator.d.ts +3 -3
  260. package/src/py/agent/generator.js +290 -179
  261. package/src/py/agent/generator.js.map +1 -1
  262. package/src/py/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +153 -89
  263. package/src/py/agent/mcp-connection/files/agent-connection/app/__mcpServerSnakeCase___client_strands.py.template +30 -0
  264. package/src/py/agent/mcp-connection/files/langchain/agent-connection/app/__mcpServerSnakeCase___client_langchain.py.template +30 -0
  265. package/src/py/agent/mcp-connection/generator.d.ts +3 -3
  266. package/src/py/agent/mcp-connection/generator.js +65 -126
  267. package/src/py/agent/mcp-connection/generator.js.map +1 -1
  268. package/src/py/agent/mcp-connection/schema.d.js +8 -0
  269. package/src/py/agent/mcp-connection/schema.d.js.map +1 -0
  270. package/src/py/agent/mcp-connection/schema.d.ts +1 -0
  271. package/src/py/agent/mcp-connection/schema.json +5 -0
  272. package/src/py/agent/react-connection/__snapshots__/generator.spec.ts.snap +11 -19
  273. package/src/py/agent/react-connection/generator.d.ts +4 -4
  274. package/src/py/agent/react-connection/generator.js +55 -59
  275. package/src/py/agent/react-connection/generator.js.map +1 -1
  276. package/src/py/agent/react-connection/{serve-local.d.ts → local-dev.d.ts} +6 -6
  277. package/src/py/agent/react-connection/local-dev.js +36 -0
  278. package/src/py/agent/react-connection/local-dev.js.map +1 -0
  279. package/src/py/agent/react-connection/schema.d.js +8 -0
  280. package/src/py/agent/react-connection/schema.d.js.map +1 -0
  281. package/src/py/agent/react-connection/schema.d.ts +1 -0
  282. package/src/py/agent/react-connection/schema.json +5 -0
  283. package/src/py/agent/schema.d.js +6 -0
  284. package/src/py/agent/schema.d.js.map +1 -0
  285. package/src/py/agent/schema.d.ts +2 -1
  286. package/src/py/agent/schema.json +6 -1
  287. package/src/py/api/generator.d.ts +3 -3
  288. package/src/py/api/generator.js +12 -11
  289. package/src/py/api/generator.js.map +1 -1
  290. package/src/py/api/schema.d.js +6 -0
  291. package/src/py/api/schema.d.js.map +1 -0
  292. package/src/py/api/schema.d.ts +1 -0
  293. package/src/py/api/schema.json +5 -0
  294. package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +1526 -0
  295. package/src/py/dynamodb/agent-connection/__snapshots__/generator.spec.ts.snap +45 -0
  296. package/src/py/dynamodb/agent-connection/generator.d.ts +10 -0
  297. package/src/py/dynamodb/agent-connection/generator.js +39 -0
  298. package/src/py/dynamodb/agent-connection/generator.js.map +1 -0
  299. package/src/py/dynamodb/agent-connection/schema.d.js +8 -0
  300. package/src/py/dynamodb/agent-connection/schema.d.js.map +1 -0
  301. package/src/py/dynamodb/agent-connection/schema.d.ts +15 -0
  302. package/src/py/dynamodb/agent-connection/schema.json +27 -0
  303. package/src/py/dynamodb/fast-api-connection/__snapshots__/generator.spec.ts.snap +23 -0
  304. package/src/py/dynamodb/fast-api-connection/generator.d.ts +10 -0
  305. package/src/py/dynamodb/fast-api-connection/generator.js +37 -0
  306. package/src/py/dynamodb/fast-api-connection/generator.js.map +1 -0
  307. package/src/py/dynamodb/fast-api-connection/schema.d.js +8 -0
  308. package/src/py/dynamodb/fast-api-connection/schema.d.js.map +1 -0
  309. package/src/py/dynamodb/fast-api-connection/schema.d.ts +13 -0
  310. package/src/py/dynamodb/fast-api-connection/schema.json +23 -0
  311. package/src/py/dynamodb/files/__name__/__init__.py.template +6 -0
  312. package/src/py/dynamodb/files/__name__/client.py.template +39 -0
  313. package/src/py/dynamodb/files/__name__/entities/__init__.py.template +4 -0
  314. package/src/py/dynamodb/files/__name__/entities/base.py.template +63 -0
  315. package/src/py/dynamodb/files/__name__/entities/example.py.template +64 -0
  316. package/src/py/dynamodb/files/config.json.template +24 -0
  317. package/src/py/dynamodb/generator.d.ts +10 -0
  318. package/src/py/dynamodb/generator.js +110 -0
  319. package/src/py/dynamodb/generator.js.map +1 -0
  320. package/src/py/dynamodb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +45 -0
  321. package/src/py/dynamodb/mcp-server-connection/generator.d.ts +10 -0
  322. package/src/py/dynamodb/mcp-server-connection/generator.js +39 -0
  323. package/src/py/dynamodb/mcp-server-connection/generator.js.map +1 -0
  324. package/src/py/dynamodb/mcp-server-connection/schema.d.js +8 -0
  325. package/src/py/dynamodb/mcp-server-connection/schema.d.js.map +1 -0
  326. package/src/py/dynamodb/mcp-server-connection/schema.d.ts +15 -0
  327. package/src/py/dynamodb/mcp-server-connection/schema.json +27 -0
  328. package/src/py/dynamodb/schema.d.js +6 -0
  329. package/src/py/dynamodb/schema.d.js.map +1 -0
  330. package/src/py/dynamodb/schema.d.ts +16 -0
  331. package/src/py/dynamodb/schema.json +75 -0
  332. package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +212 -4678
  333. package/src/py/fast-api/__snapshots__/generator.terraform.spec.ts.snap +5409 -0
  334. package/src/py/fast-api/files/app/__name__/init.py.template +5 -22
  335. package/src/py/fast-api/files/app/__name__/main.py.template +4 -1
  336. package/src/py/fast-api/generator.d.ts +3 -3
  337. package/src/py/fast-api/generator.js +90 -87
  338. package/src/py/fast-api/generator.js.map +1 -1
  339. package/src/py/fast-api/react/__snapshots__/generator.spec.ts.snap +4 -3
  340. package/src/py/fast-api/react/generator.d.ts +4 -4
  341. package/src/py/fast-api/react/generator.js +25 -25
  342. package/src/py/fast-api/react/generator.js.map +1 -1
  343. package/src/py/fast-api/react/open-api.d.ts +1 -1
  344. package/src/py/fast-api/react/open-api.js +31 -29
  345. package/src/py/fast-api/react/open-api.js.map +1 -1
  346. package/src/py/fast-api/react/schema.d.js +6 -0
  347. package/src/py/fast-api/react/schema.d.js.map +1 -0
  348. package/src/py/fast-api/react/schema.d.ts +1 -0
  349. package/src/py/fast-api/react/schema.json +5 -0
  350. package/src/py/fast-api/schema.d.js +6 -0
  351. package/src/py/fast-api/schema.d.js.map +1 -0
  352. package/src/py/fast-api/schema.d.ts +1 -0
  353. package/src/py/fast-api/schema.json +5 -0
  354. package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +4 -4
  355. package/src/py/lambda-function/generator.d.ts +3 -3
  356. package/src/py/lambda-function/generator.js +60 -59
  357. package/src/py/lambda-function/generator.js.map +1 -1
  358. package/src/py/lambda-function/schema.d.js +6 -0
  359. package/src/py/lambda-function/schema.d.js.map +1 -0
  360. package/src/py/lambda-function/schema.d.ts +1 -0
  361. package/src/py/lambda-function/schema.json +5 -0
  362. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +208 -19
  363. package/src/py/mcp-server/files/deploy/Dockerfile.template +1 -1
  364. package/src/py/mcp-server/generator.d.ts +3 -3
  365. package/src/py/mcp-server/generator.js +162 -124
  366. package/src/py/mcp-server/generator.js.map +1 -1
  367. package/src/py/mcp-server/schema.d.js +6 -0
  368. package/src/py/mcp-server/schema.d.js.map +1 -0
  369. package/src/py/mcp-server/schema.d.ts +1 -0
  370. package/src/py/mcp-server/schema.json +5 -0
  371. package/src/py/project/generator.d.ts +17 -4
  372. package/src/py/project/generator.js +205 -127
  373. package/src/py/project/generator.js.map +1 -1
  374. package/src/py/project/schema.d.js +6 -0
  375. package/src/py/project/schema.d.js.map +1 -0
  376. package/src/py/project/schema.d.ts +1 -0
  377. package/src/py/project/schema.json +5 -0
  378. package/src/py/rdb/__snapshots__/generator.spec.ts.snap +2038 -0
  379. package/src/py/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +104 -0
  380. package/src/py/rdb/agent-connection/generator.d.ts +10 -0
  381. package/src/py/rdb/agent-connection/generator.js +46 -0
  382. package/src/py/rdb/agent-connection/generator.js.map +1 -0
  383. package/src/py/rdb/agent-connection/schema.d.js +8 -0
  384. package/src/py/rdb/agent-connection/schema.d.js.map +1 -0
  385. package/src/py/rdb/agent-connection/schema.d.ts +15 -0
  386. package/src/py/rdb/agent-connection/schema.json +27 -0
  387. package/src/py/rdb/fast-api-connection/__snapshots__/generator.spec.ts.snap +44 -0
  388. package/src/py/rdb/fast-api-connection/files/__apiModuleName__/dependencies/__rdbNameSnake__.py.template +14 -0
  389. package/src/py/rdb/fast-api-connection/generator.d.ts +10 -0
  390. package/src/py/rdb/fast-api-connection/generator.js +54 -0
  391. package/src/py/rdb/fast-api-connection/generator.js.map +1 -0
  392. package/src/py/rdb/fast-api-connection/schema.d.js +8 -0
  393. package/src/py/rdb/fast-api-connection/schema.d.js.map +1 -0
  394. package/src/py/rdb/fast-api-connection/schema.d.ts +13 -0
  395. package/src/py/rdb/fast-api-connection/schema.json +23 -0
  396. package/src/py/rdb/files/Dockerfile.create-db-user.template +10 -0
  397. package/src/py/rdb/files/Dockerfile.migration.template +10 -0
  398. package/src/py/rdb/files/__name__/__init__.py.template +3 -0
  399. package/src/py/rdb/files/__name__/connection.py.template +55 -0
  400. package/src/py/rdb/files/__name__/create_db_user_handler.py.template +97 -0
  401. package/src/py/rdb/files/__name__/migration_handler.py.template +36 -0
  402. package/src/py/rdb/files/__name__/models/__init__.py.template +3 -0
  403. package/src/py/rdb/files/__name__/models/example.py.template +8 -0
  404. package/src/py/rdb/files/__name__/utils.py.template +104 -0
  405. package/src/py/rdb/files/alembic.ini.template +38 -0
  406. package/src/py/rdb/files/config.json.template +14 -0
  407. package/src/py/rdb/files/migrations/env.py.template +80 -0
  408. package/src/py/rdb/files/migrations/script.py.mako.template +28 -0
  409. package/src/py/rdb/generator.d.ts +6 -0
  410. package/src/py/rdb/generator.js +274 -0
  411. package/src/py/rdb/generator.js.map +1 -0
  412. package/src/py/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +101 -0
  413. package/src/py/rdb/mcp-server-connection/generator.d.ts +10 -0
  414. package/src/py/rdb/mcp-server-connection/generator.js +46 -0
  415. package/src/py/rdb/mcp-server-connection/generator.js.map +1 -0
  416. package/src/py/rdb/mcp-server-connection/schema.d.js +8 -0
  417. package/src/py/rdb/mcp-server-connection/schema.d.js.map +1 -0
  418. package/src/py/rdb/mcp-server-connection/schema.d.ts +15 -0
  419. package/src/py/rdb/mcp-server-connection/schema.json +27 -0
  420. package/src/py/rdb/schema.d.js +6 -0
  421. package/src/py/rdb/schema.d.js.map +1 -0
  422. package/src/py/rdb/schema.d.ts +16 -0
  423. package/src/py/rdb/schema.json +77 -0
  424. package/src/py/rdb/utils.d.ts +6 -0
  425. package/src/py/rdb/utils.js +16 -0
  426. package/src/py/rdb/utils.js.map +1 -0
  427. package/src/sdk/agentcore-gateway.d.ts +6 -0
  428. package/src/sdk/agentcore-gateway.js +7 -0
  429. package/src/sdk/agentcore-gateway.js.map +1 -0
  430. package/src/sdk/connection.d.ts +6 -0
  431. package/src/sdk/connection.js +6 -0
  432. package/src/sdk/connection.js.map +1 -0
  433. package/src/sdk/license.d.ts +8 -0
  434. package/src/sdk/license.js +7 -0
  435. package/src/sdk/license.js.map +1 -0
  436. package/src/sdk/open-api.d.ts +10 -0
  437. package/src/sdk/open-api.js +8 -0
  438. package/src/sdk/open-api.js.map +1 -0
  439. package/src/sdk/py.d.ts +16 -0
  440. package/src/sdk/py.js +11 -0
  441. package/src/sdk/py.js.map +1 -0
  442. package/src/sdk/terraform.d.ts +6 -0
  443. package/src/sdk/terraform.js +7 -0
  444. package/src/sdk/terraform.js.map +1 -0
  445. package/src/sdk/ts.d.ts +33 -0
  446. package/src/sdk/ts.js +35 -0
  447. package/src/sdk/ts.js.map +1 -0
  448. package/{sdk → src/sdk}/utils/ast.d.ts +1 -2
  449. package/src/sdk/utils/ast.js +6 -0
  450. package/src/sdk/utils/ast.js.map +1 -0
  451. package/{sdk → src/sdk}/utils/format.d.ts +1 -1
  452. package/src/sdk/utils/format.js +6 -0
  453. package/src/sdk/utils/format.js.map +1 -0
  454. package/{sdk → src/sdk}/utils/test.d.ts +1 -1
  455. package/src/sdk/utils/test.js +6 -0
  456. package/src/sdk/utils/test.js.map +1 -0
  457. package/src/smithy/project/__snapshots__/generator.spec.ts.snap +19 -24
  458. package/src/smithy/project/files/build.Dockerfile.template +1 -4
  459. package/src/smithy/project/files/src/operations/echo.smithy.template +1 -0
  460. package/src/smithy/project/generator.d.ts +3 -3
  461. package/src/smithy/project/generator.js +64 -57
  462. package/src/smithy/project/generator.js.map +1 -1
  463. package/src/smithy/project/schema.d.js +6 -0
  464. package/src/smithy/project/schema.d.js.map +1 -0
  465. package/src/smithy/project/schema.d.ts +1 -0
  466. package/src/smithy/project/schema.json +5 -0
  467. package/src/smithy/react-connection/__snapshots__/generator.spec.ts.snap +1 -1
  468. package/src/smithy/react-connection/generator.d.ts +3 -3
  469. package/src/smithy/react-connection/generator.js +39 -47
  470. package/src/smithy/react-connection/generator.js.map +1 -1
  471. package/src/smithy/react-connection/schema.d.js +6 -0
  472. package/src/smithy/react-connection/schema.d.js.map +1 -0
  473. package/src/smithy/react-connection/schema.d.ts +1 -0
  474. package/src/smithy/react-connection/schema.json +5 -0
  475. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +824 -120
  476. package/src/smithy/ts/api/files/handler.ts.template +2 -2
  477. package/src/smithy/ts/api/files/local-server.ts.template +2 -2
  478. package/src/smithy/ts/api/files/operations/echo.ts.template +2 -2
  479. package/src/smithy/ts/api/files/service.ts.template +3 -3
  480. package/src/smithy/ts/api/generator.d.ts +3 -3
  481. package/src/smithy/ts/api/generator.js +128 -105
  482. package/src/smithy/ts/api/generator.js.map +1 -1
  483. package/src/smithy/ts/api/schema.d.js +6 -0
  484. package/src/smithy/ts/api/schema.d.js.map +1 -0
  485. package/src/smithy/ts/api/schema.d.ts +1 -0
  486. package/src/smithy/ts/api/schema.json +5 -0
  487. package/src/terraform/project/files/application/src/main.tf.template +6 -1
  488. package/src/terraform/project/files/application/src/providers.tf.template +1 -1
  489. package/src/terraform/project/generator.d.ts +3 -3
  490. package/src/terraform/project/generator.js +156 -104
  491. package/src/terraform/project/generator.js.map +1 -1
  492. package/src/terraform/project/schema.d.js +9 -0
  493. package/src/terraform/project/schema.d.js.map +1 -0
  494. package/src/terraform/project/schema.d.ts +1 -0
  495. package/src/terraform/project/schema.json +5 -0
  496. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +1099 -134
  497. package/src/trpc/backend/files/src/client/index.ts.template +1 -1
  498. package/src/trpc/backend/files/src/handler.ts.template +1 -1
  499. package/src/trpc/backend/files/src/index.ts.template +5 -5
  500. package/src/trpc/backend/files/src/init.ts.template +1 -1
  501. package/src/trpc/backend/files/src/local-server.ts.template +1 -1
  502. package/src/trpc/backend/files/src/middleware/index.ts.template +7 -7
  503. package/src/trpc/backend/files/src/procedures/echo.ts.template +3 -3
  504. package/src/trpc/backend/files/src/router.ts.template +2 -2
  505. package/src/trpc/backend/files/src/schema/echo.ts.template +2 -2
  506. package/src/trpc/backend/files/src/schema/index.ts.template +1 -1
  507. package/src/trpc/backend/generator.d.ts +4 -4
  508. package/src/trpc/backend/generator.js +98 -84
  509. package/src/trpc/backend/generator.js.map +1 -1
  510. package/src/trpc/backend/schema.d.js +6 -0
  511. package/src/trpc/backend/schema.d.js.map +1 -0
  512. package/src/trpc/backend/schema.d.ts +3 -2
  513. package/src/trpc/backend/schema.json +5 -0
  514. package/src/trpc/react/__snapshots__/generator.spec.ts.snap +4 -4
  515. package/src/trpc/react/files/src/components/__apiNameClassName__ClientProvider.tsx.template +3 -3
  516. package/src/trpc/react/generator.d.ts +4 -4
  517. package/src/trpc/react/generator.js +63 -58
  518. package/src/trpc/react/generator.js.map +1 -1
  519. package/src/trpc/react/schema.d.js +6 -0
  520. package/src/trpc/react/schema.d.js.map +1 -0
  521. package/src/trpc/react/schema.d.ts +1 -0
  522. package/src/trpc/react/schema.json +5 -0
  523. package/src/ts/agent/__snapshots__/generator.spec.ts.snap +781 -22
  524. package/src/ts/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +256 -0
  525. package/src/ts/agent/a2a-connection/files/agent-connection/app/__targetAgentKebabCase__-client-strands.ts.template +23 -0
  526. package/src/ts/agent/a2a-connection/generator.d.ts +3 -3
  527. package/src/ts/agent/a2a-connection/generator.js +64 -55
  528. package/src/ts/agent/a2a-connection/generator.js.map +1 -1
  529. package/src/ts/agent/a2a-connection/schema.d.js +8 -0
  530. package/src/ts/agent/a2a-connection/schema.d.js.map +1 -0
  531. package/src/ts/agent/a2a-connection/schema.d.ts +1 -0
  532. package/src/ts/agent/a2a-connection/schema.json +5 -0
  533. package/src/ts/agent/files/a2a/index.ts.template +1 -1
  534. package/src/ts/agent/files/ag-ui/index.ts.template +1 -1
  535. package/src/ts/agent/files/common/agent.ts.template +6 -2
  536. package/src/ts/agent/files/deploy/Dockerfile.template +4 -1
  537. package/src/ts/agent/files/http/client.ts.template +2 -2
  538. package/src/ts/agent/files/http/index.ts.template +2 -2
  539. package/src/ts/agent/files/http/router.ts.template +5 -5
  540. package/src/ts/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +220 -0
  541. package/src/ts/agent/gateway-connection/files/agent-connection/app/__gatewayKebabCase__-client-strands.ts.template +30 -0
  542. package/src/ts/agent/gateway-connection/generator.d.ts +10 -0
  543. package/src/ts/agent/gateway-connection/generator.js +116 -0
  544. package/src/ts/agent/gateway-connection/generator.js.map +1 -0
  545. package/src/ts/agent/gateway-connection/schema.d.js +6 -0
  546. package/src/ts/agent/gateway-connection/schema.d.js.map +1 -0
  547. package/src/ts/agent/gateway-connection/schema.d.ts +13 -0
  548. package/src/ts/agent/gateway-connection/schema.json +31 -0
  549. package/src/ts/agent/generator.d.ts +3 -3
  550. package/src/ts/agent/generator.js +203 -144
  551. package/src/ts/agent/generator.js.map +1 -1
  552. package/src/ts/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +192 -111
  553. package/src/ts/agent/mcp-connection/files/agent-connection/app/__mcpServerKebabCase__-client-strands.ts.template +22 -0
  554. package/src/ts/agent/mcp-connection/generator.d.ts +3 -3
  555. package/src/ts/agent/mcp-connection/generator.js +54 -59
  556. package/src/ts/agent/mcp-connection/generator.js.map +1 -1
  557. package/src/ts/agent/mcp-connection/schema.d.js +8 -0
  558. package/src/ts/agent/mcp-connection/schema.d.js.map +1 -0
  559. package/src/ts/agent/mcp-connection/schema.d.ts +1 -0
  560. package/src/ts/agent/mcp-connection/schema.json +5 -0
  561. package/src/ts/agent/react-connection/generator.d.ts +4 -4
  562. package/src/ts/agent/react-connection/generator.js +86 -80
  563. package/src/ts/agent/react-connection/generator.js.map +1 -1
  564. package/src/ts/agent/react-connection/local-dev.d.ts +13 -0
  565. package/src/ts/agent/react-connection/local-dev.js +17 -0
  566. package/src/ts/agent/react-connection/local-dev.js.map +1 -0
  567. package/src/ts/agent/react-connection/schema.d.js +8 -0
  568. package/src/ts/agent/react-connection/schema.d.js.map +1 -0
  569. package/src/ts/agent/react-connection/schema.d.ts +1 -0
  570. package/src/ts/agent/react-connection/schema.json +5 -0
  571. package/src/ts/agent/schema.d.js +6 -0
  572. package/src/ts/agent/schema.d.js.map +1 -0
  573. package/src/ts/agent/schema.d.ts +1 -0
  574. package/src/ts/agent/schema.json +5 -0
  575. package/src/ts/api/generator.d.ts +3 -3
  576. package/src/ts/api/generator.js +16 -16
  577. package/src/ts/api/generator.js.map +1 -1
  578. package/src/ts/api/schema.d.js +6 -0
  579. package/src/ts/api/schema.d.js.map +1 -0
  580. package/src/ts/api/schema.d.ts +3 -1
  581. package/src/ts/api/schema.json +5 -0
  582. package/src/ts/astro-docs/__snapshots__/generator.spec.ts.snap +15 -16
  583. package/src/ts/astro-docs/files/translation/scripts/translate.ts.template +3 -2
  584. package/src/ts/astro-docs/generator.d.ts +3 -3
  585. package/src/ts/astro-docs/generator.js +71 -54
  586. package/src/ts/astro-docs/generator.js.map +1 -1
  587. package/src/ts/astro-docs/schema.d.js +6 -0
  588. package/src/ts/astro-docs/schema.d.js.map +1 -0
  589. package/src/ts/astro-docs/schema.d.ts +2 -2
  590. package/src/ts/astro-docs/schema.json +3 -3
  591. package/src/ts/docs/generator.d.ts +3 -3
  592. package/src/ts/docs/generator.js +10 -10
  593. package/src/ts/docs/generator.js.map +1 -1
  594. package/src/ts/docs/schema.d.js +6 -0
  595. package/src/ts/docs/schema.d.js.map +1 -0
  596. package/src/ts/docs/schema.d.ts +1 -4
  597. package/src/ts/docs/schema.json +3 -3
  598. package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +400 -512
  599. package/src/ts/dynamodb/agent-connection/__snapshots__/generator.spec.ts.snap +5 -5
  600. package/src/ts/dynamodb/agent-connection/generator.d.ts +3 -3
  601. package/src/ts/dynamodb/agent-connection/generator.js +21 -23
  602. package/src/ts/dynamodb/agent-connection/generator.js.map +1 -1
  603. package/src/ts/dynamodb/agent-connection/schema.d.js +8 -0
  604. package/src/ts/dynamodb/agent-connection/schema.d.js.map +1 -0
  605. package/src/ts/dynamodb/agent-connection/schema.d.ts +1 -0
  606. package/src/ts/dynamodb/agent-connection/schema.json +5 -0
  607. package/src/ts/dynamodb/files/config.json.template +24 -0
  608. package/src/ts/dynamodb/files/src/client.ts.template +30 -11
  609. package/src/ts/dynamodb/files/src/entities/example.ts.template +1 -1
  610. package/src/ts/dynamodb/files/src/entities/index.ts.template +1 -1
  611. package/src/ts/dynamodb/files/src/index.ts.template +2 -11
  612. package/src/ts/dynamodb/generator.d.ts +3 -3
  613. package/src/ts/dynamodb/generator.js +73 -63
  614. package/src/ts/dynamodb/generator.js.map +1 -1
  615. package/src/ts/dynamodb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +5 -5
  616. package/src/ts/dynamodb/mcp-server-connection/generator.d.ts +3 -3
  617. package/src/ts/dynamodb/mcp-server-connection/generator.js +21 -23
  618. package/src/ts/dynamodb/mcp-server-connection/generator.js.map +1 -1
  619. package/src/ts/dynamodb/mcp-server-connection/schema.d.js +8 -0
  620. package/src/ts/dynamodb/mcp-server-connection/schema.d.js.map +1 -0
  621. package/src/ts/dynamodb/mcp-server-connection/schema.d.ts +1 -0
  622. package/src/ts/dynamodb/mcp-server-connection/schema.json +5 -0
  623. package/src/ts/dynamodb/schema.d.js +6 -0
  624. package/src/ts/dynamodb/schema.d.js.map +1 -0
  625. package/src/ts/dynamodb/schema.d.ts +2 -0
  626. package/src/ts/dynamodb/schema.json +25 -2
  627. package/src/ts/dynamodb/smithy-connection/__snapshots__/generator.spec.ts.snap +3 -3
  628. package/src/ts/dynamodb/smithy-connection/generator.d.ts +3 -3
  629. package/src/ts/dynamodb/smithy-connection/generator.js +20 -22
  630. package/src/ts/dynamodb/smithy-connection/generator.js.map +1 -1
  631. package/src/ts/dynamodb/smithy-connection/schema.d.js +8 -0
  632. package/src/ts/dynamodb/smithy-connection/schema.d.js.map +1 -0
  633. package/src/ts/dynamodb/smithy-connection/schema.d.ts +1 -0
  634. package/src/ts/dynamodb/smithy-connection/schema.json +5 -0
  635. package/src/ts/dynamodb/trpc-connection/__snapshots__/generator.spec.ts.snap +3 -3
  636. package/src/ts/dynamodb/trpc-connection/generator.d.ts +3 -3
  637. package/src/ts/dynamodb/trpc-connection/generator.js +20 -22
  638. package/src/ts/dynamodb/trpc-connection/generator.js.map +1 -1
  639. package/src/ts/dynamodb/trpc-connection/schema.d.js +8 -0
  640. package/src/ts/dynamodb/trpc-connection/schema.d.js.map +1 -0
  641. package/src/ts/dynamodb/trpc-connection/schema.d.ts +1 -0
  642. package/src/ts/dynamodb/trpc-connection/schema.json +5 -0
  643. package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +4 -4
  644. package/src/ts/lambda-function/generator.d.ts +3 -3
  645. package/src/ts/lambda-function/generator.js +59 -56
  646. package/src/ts/lambda-function/generator.js.map +1 -1
  647. package/src/ts/lambda-function/io.js +83 -52
  648. package/src/ts/lambda-function/io.js.map +1 -1
  649. package/src/ts/lambda-function/schema.d.js +6 -0
  650. package/src/ts/lambda-function/schema.d.js.map +1 -0
  651. package/src/ts/lambda-function/schema.d.ts +1 -0
  652. package/src/ts/lambda-function/schema.json +5 -0
  653. package/src/ts/lib/__snapshots__/generator.spec.ts.snap +98 -93
  654. package/src/ts/lib/__snapshots__/vitest.spec.ts.snap +24 -0
  655. package/src/ts/lib/biome.d.ts +7 -0
  656. package/src/ts/lib/biome.js +91 -0
  657. package/src/ts/lib/biome.js.map +1 -0
  658. package/src/ts/lib/generator.d.ts +3 -3
  659. package/src/ts/lib/generator.js +107 -108
  660. package/src/ts/lib/generator.js.map +1 -1
  661. package/src/ts/lib/grit/vitest-pass-with-no-tests.grit +1 -4
  662. package/src/ts/lib/schema.d.js +6 -0
  663. package/src/ts/lib/schema.d.js.map +1 -0
  664. package/src/ts/lib/schema.d.ts +1 -1
  665. package/src/ts/lib/schema.json +5 -0
  666. package/src/ts/lib/ts-project-utils.d.ts +12 -2
  667. package/src/ts/lib/ts-project-utils.js +90 -67
  668. package/src/ts/lib/ts-project-utils.js.map +1 -1
  669. package/src/ts/lib/types.d.ts +6 -0
  670. package/src/ts/lib/types.js +5 -2
  671. package/src/ts/lib/types.js.map +1 -1
  672. package/src/ts/lib/vitest.d.ts +2 -2
  673. package/src/ts/lib/vitest.js +29 -26
  674. package/src/ts/lib/vitest.js.map +1 -1
  675. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +208 -42
  676. package/src/ts/mcp-server/files/Dockerfile.template +4 -1
  677. package/src/ts/mcp-server/generator.d.ts +3 -3
  678. package/src/ts/mcp-server/generator.js +181 -136
  679. package/src/ts/mcp-server/generator.js.map +1 -1
  680. package/src/ts/mcp-server/schema.d.js +6 -0
  681. package/src/ts/mcp-server/schema.d.js.map +1 -0
  682. package/src/ts/mcp-server/schema.d.ts +1 -0
  683. package/src/ts/mcp-server/schema.json +5 -0
  684. package/src/ts/nx-generator/__snapshots__/generator.spec.ts.snap +46 -26
  685. package/src/ts/nx-generator/files/common/schema.d.ts.template +1 -0
  686. package/src/ts/nx-generator/files/common/schema.json.template +5 -0
  687. package/src/ts/nx-generator/files/local/generator.ts.template +3 -3
  688. package/src/ts/nx-generator/files/nx-plugin-for-aws/generator/generator.ts.template +6 -7
  689. package/src/ts/nx-generator/generator.d.ts +2 -2
  690. package/src/ts/nx-generator/generator.js +113 -73
  691. package/src/ts/nx-generator/generator.js.map +1 -1
  692. package/src/ts/nx-generator/schema.d.js +6 -0
  693. package/src/ts/nx-generator/schema.d.js.map +1 -0
  694. package/src/ts/nx-generator/schema.d.ts +1 -0
  695. package/src/ts/nx-generator/schema.json +5 -0
  696. package/src/ts/nx-plugin/__snapshots__/generator.spec.ts.snap +30 -18
  697. package/src/ts/nx-plugin/files/mcp-server/server.ts.template +5 -5
  698. package/src/ts/nx-plugin/files/mcp-server/tools/create-workspace-command.ts.template +2 -2
  699. package/src/ts/nx-plugin/files/mcp-server/tools/general-guidance.ts.template +1 -1
  700. package/src/ts/nx-plugin/files/mcp-server/tools/generator-guide.ts.template +2 -2
  701. package/src/ts/nx-plugin/files/mcp-server/tools/list-generators.ts.template +2 -2
  702. package/src/ts/nx-plugin/files/mcp-server/utils.ts.template +3 -3
  703. package/src/ts/nx-plugin/generator.d.ts +3 -3
  704. package/src/ts/nx-plugin/generator.js +61 -50
  705. package/src/ts/nx-plugin/generator.js.map +1 -1
  706. package/src/ts/nx-plugin/schema.d.js +9 -0
  707. package/src/ts/nx-plugin/schema.d.js.map +1 -0
  708. package/src/ts/nx-plugin/schema.json +5 -0
  709. package/src/ts/nx-plugin/utils.d.ts +1 -1
  710. package/src/ts/nx-plugin/utils.js +36 -39
  711. package/src/ts/nx-plugin/utils.js.map +1 -1
  712. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +455 -646
  713. package/src/ts/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +6 -6
  714. package/src/ts/rdb/agent-connection/generator.d.ts +3 -3
  715. package/src/ts/rdb/agent-connection/generator.js +38 -39
  716. package/src/ts/rdb/agent-connection/generator.js.map +1 -1
  717. package/src/ts/rdb/agent-connection/schema.d.js +8 -0
  718. package/src/ts/rdb/agent-connection/schema.d.js.map +1 -0
  719. package/src/ts/rdb/agent-connection/schema.d.ts +1 -0
  720. package/src/ts/rdb/agent-connection/schema.json +5 -0
  721. package/src/ts/rdb/files/Dockerfile.template +8 -1
  722. package/src/ts/rdb/files/config.json.template +14 -0
  723. package/src/ts/rdb/files/prisma.config.ts.template +6 -5
  724. package/src/ts/rdb/files/src/create-db-user-handler.ts.template +9 -11
  725. package/src/ts/rdb/files/src/index.ts.template +1 -2
  726. package/src/ts/rdb/files/src/migration-handler.ts.template +2 -29
  727. package/src/ts/rdb/files/src/prisma.ts.template +33 -25
  728. package/src/ts/rdb/files/src/utils.ts.template +3 -0
  729. package/src/ts/rdb/generator.d.ts +3 -7
  730. package/src/ts/rdb/generator.js +173 -131
  731. package/src/ts/rdb/generator.js.map +1 -1
  732. package/src/ts/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +6 -6
  733. package/src/ts/rdb/mcp-server-connection/generator.d.ts +3 -3
  734. package/src/ts/rdb/mcp-server-connection/generator.js +36 -37
  735. package/src/ts/rdb/mcp-server-connection/generator.js.map +1 -1
  736. package/src/ts/rdb/mcp-server-connection/schema.d.js +8 -0
  737. package/src/ts/rdb/mcp-server-connection/schema.d.js.map +1 -0
  738. package/src/ts/rdb/mcp-server-connection/schema.d.ts +1 -0
  739. package/src/ts/rdb/mcp-server-connection/schema.json +5 -0
  740. package/src/ts/rdb/schema.d.js +6 -0
  741. package/src/ts/rdb/schema.d.js.map +1 -0
  742. package/src/ts/rdb/schema.d.ts +1 -0
  743. package/src/ts/rdb/schema.json +6 -1
  744. package/src/ts/rdb/smithy-connection/__snapshots__/generator.spec.ts.snap +3 -3
  745. package/src/ts/rdb/smithy-connection/generator.d.ts +3 -3
  746. package/src/ts/rdb/smithy-connection/generator.js +46 -43
  747. package/src/ts/rdb/smithy-connection/generator.js.map +1 -1
  748. package/src/ts/rdb/smithy-connection/schema.d.js +8 -0
  749. package/src/ts/rdb/smithy-connection/schema.d.js.map +1 -0
  750. package/src/ts/rdb/smithy-connection/schema.d.ts +1 -0
  751. package/src/ts/rdb/smithy-connection/schema.json +5 -0
  752. package/src/ts/rdb/trpc-connection/__snapshots__/generator.spec.ts.snap +3 -3
  753. package/src/ts/rdb/trpc-connection/generator.d.ts +3 -3
  754. package/src/ts/rdb/trpc-connection/generator.js +36 -31
  755. package/src/ts/rdb/trpc-connection/generator.js.map +1 -1
  756. package/src/ts/rdb/trpc-connection/schema.d.js +8 -0
  757. package/src/ts/rdb/trpc-connection/schema.d.js.map +1 -0
  758. package/src/ts/rdb/trpc-connection/schema.d.ts +1 -0
  759. package/src/ts/rdb/trpc-connection/schema.json +5 -0
  760. package/src/ts/rdb/utils.d.ts +1 -1
  761. package/src/ts/rdb/utils.js +9 -11
  762. package/src/ts/rdb/utils.js.map +1 -1
  763. package/src/ts/react-website/agui/files/common/src/hooks/useAgui__agentNameClassName__.tsx.template +1 -16
  764. package/src/ts/react-website/agui/generator.d.ts +1 -1
  765. package/src/ts/react-website/agui/generator.js +69 -62
  766. package/src/ts/react-website/agui/generator.js.map +1 -1
  767. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +1190 -799
  768. package/src/ts/react-website/app/generator.d.ts +4 -4
  769. package/src/ts/react-website/app/generator.js +217 -192
  770. package/src/ts/react-website/app/generator.js.map +1 -1
  771. package/src/ts/react-website/app/schema.d.js +6 -0
  772. package/src/ts/react-website/app/schema.d.js.map +1 -0
  773. package/src/ts/react-website/app/schema.d.ts +1 -1
  774. package/src/ts/react-website/app/schema.json +11 -6
  775. package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +129 -18
  776. package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +36 -10
  777. package/src/ts/react-website/cognito-auth/__snapshots__/generator.ux-provider.spec.ts.snap +0 -20
  778. package/src/ts/react-website/cognito-auth/files/app/components/CognitoAuth/index.tsx.template +2 -2
  779. package/src/ts/react-website/cognito-auth/generator.d.ts +4 -4
  780. package/src/ts/react-website/cognito-auth/generator.js +64 -63
  781. package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
  782. package/src/ts/react-website/cognito-auth/grit/cloudscape-auth-menu.grit +8 -6
  783. package/src/ts/react-website/cognito-auth/grit/cognito-auth-wrapper.grit +1 -1
  784. package/src/ts/react-website/cognito-auth/grit/none-auth-menu.grit +1 -0
  785. package/src/ts/react-website/cognito-auth/grit/shadcn-auth-menu.grit +3 -1
  786. package/src/ts/react-website/cognito-auth/grit/shadcn-state-declarations.grit +3 -1
  787. package/src/ts/react-website/cognito-auth/schema.d.js +6 -0
  788. package/src/ts/react-website/cognito-auth/schema.d.js.map +1 -0
  789. package/src/ts/react-website/cognito-auth/schema.d.ts +1 -0
  790. package/src/ts/react-website/cognito-auth/schema.json +5 -0
  791. package/src/ts/react-website/cognito-auth/utils.d.ts +1 -1
  792. package/src/ts/react-website/cognito-auth/utils.js +34 -32
  793. package/src/ts/react-website/cognito-auth/utils.js.map +1 -1
  794. package/src/ts/react-website/runtime-config/__snapshots__/generator.spec.ts.snap +2 -2
  795. package/src/ts/react-website/runtime-config/files/app/components/RuntimeConfig/index.tsx.template +2 -2
  796. package/src/ts/react-website/runtime-config/generator.d.ts +3 -3
  797. package/src/ts/react-website/runtime-config/generator.js +29 -31
  798. package/src/ts/react-website/runtime-config/generator.js.map +1 -1
  799. package/src/ts/react-website/runtime-config/schema.d.js +6 -0
  800. package/src/ts/react-website/runtime-config/schema.d.js.map +1 -0
  801. package/src/ts/react-website/runtime-config/schema.d.ts +1 -0
  802. package/src/ts/react-website/runtime-config/schema.json +5 -0
  803. package/src/ts/sync/generator.d.ts +3 -3
  804. package/src/ts/sync/generator.js +58 -59
  805. package/src/ts/sync/generator.js.map +1 -1
  806. package/src/ts/website/app/generator.d.ts +3 -3
  807. package/src/ts/website/app/generator.js +10 -10
  808. package/src/ts/website/app/generator.js.map +1 -1
  809. package/src/ts/website/app/schema.d.js +6 -0
  810. package/src/ts/website/app/schema.d.js.map +1 -0
  811. package/src/ts/website/app/schema.d.ts +1 -1
  812. package/src/ts/website/app/schema.json +11 -6
  813. package/src/ts/website/auth/generator.d.ts +4 -4
  814. package/src/ts/website/auth/generator.js +11 -10
  815. package/src/ts/website/auth/generator.js.map +1 -1
  816. package/src/ts/website/auth/schema.d.js +6 -0
  817. package/src/ts/website/auth/schema.d.js.map +1 -0
  818. package/src/ts/website/auth/schema.d.ts +1 -0
  819. package/src/ts/website/auth/schema.json +5 -0
  820. package/src/utils/agent-chat/agent-chat.d.ts +31 -0
  821. package/src/utils/agent-chat/agent-chat.js +31 -0
  822. package/src/utils/agent-chat/agent-chat.js.map +1 -0
  823. package/src/utils/agent-chat/files/a2a/chat.ts.template +33 -0
  824. package/src/utils/agent-chat/files/ag-ui/chat.ts.template +17 -0
  825. package/src/utils/agent-chat/files/common/agentcore.ts.template +81 -0
  826. package/src/utils/agent-chat/files/http-py/chat.ts.template +43 -0
  827. package/src/utils/agent-chat/files/http-ts/chat.ts.template +54 -0
  828. package/src/utils/agent-connection/agent-connection.d.ts +117 -25
  829. package/src/utils/agent-connection/agent-connection.js +414 -103
  830. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  831. package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client-config.ts.template +93 -0
  832. package/src/utils/agent-connection/files/core-auth/agentcore-endpoints.ts.template +37 -0
  833. package/src/utils/agent-connection/files/core-auth/agentcore-fetch.ts.template +54 -0
  834. package/src/utils/agent-connection/files/core-gateway/agentcore-gateway-mcp-transport.ts.template +41 -0
  835. package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-transport.ts.template +70 -0
  836. package/src/utils/agent-connection/files/core-runtime-config/runtime-config.ts.template +22 -32
  837. package/src/utils/agent-connection/files/core-shared/agentcore-transport.ts.template +39 -0
  838. package/src/utils/agent-connection/files/core-strands/a2a/agentcore-a2a-client-strands.ts.template +61 -0
  839. package/src/utils/agent-connection/files/core-strands/base/model-errors-strands.ts.template +36 -0
  840. package/src/utils/agent-connection/files/{core-runtime-config/with-session-id.ts.template → core-strands/base/with-session-id-strands.ts.template} +1 -1
  841. package/src/utils/agent-connection/files/core-strands/gateway/agentcore-gateway-mcp-client-strands.ts.template +26 -0
  842. package/src/utils/agent-connection/files/core-strands/mcp/agentcore-mcp-client-strands.ts.template +27 -0
  843. package/src/utils/agent-connection/files/py-core-a2a/agentcore_a2a_client_config.py.template +43 -0
  844. package/src/utils/agent-connection/files/py-core-auth/agentcore_endpoints.py.template +47 -0
  845. package/src/utils/agent-connection/files/py-core-auth/auth/session.py.template +51 -0
  846. package/src/utils/agent-connection/files/py-core-gateway/agentcore_gateway_mcp_transport.py.template +28 -0
  847. package/src/utils/agent-connection/files/py-core-langchain/a2a/agentcore_a2a_client_langchain.py.template +99 -0
  848. package/src/utils/agent-connection/files/py-core-langchain/gateway/agentcore_gateway_mcp_client_langchain.py.template +57 -0
  849. package/src/utils/agent-connection/files/py-core-langchain/mcp/agentcore_mcp_client_langchain.py.template +64 -0
  850. package/src/utils/agent-connection/files/py-core-mcp/agentcore_mcp_transport.py.template +34 -0
  851. package/src/utils/agent-connection/files/py-core-runtime-config/runtime_config.py.template +5 -18
  852. package/src/utils/agent-connection/files/py-core-shared/agentcore_transport.py.template +40 -0
  853. package/src/utils/agent-connection/files/py-core-strands/a2a/agentcore_a2a_client_strands.py.template +66 -0
  854. package/src/utils/agent-connection/files/py-core-strands/base/model_errors_strands.py.template +40 -0
  855. package/src/utils/agent-connection/files/py-core-strands/gateway/agentcore_gateway_mcp_client_strands.py.template +22 -0
  856. package/src/utils/agent-connection/files/py-core-strands/mcp/agentcore_mcp_client_strands.py.template +30 -0
  857. package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +11 -3
  858. package/src/utils/agent-core-constructs/agent-core-constructs.js +93 -38
  859. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  860. package/src/utils/agent-core-constructs/files/cdk/app/agent-core/__nameKebabCase__/__nameKebabCase__.ts.template +31 -4
  861. package/src/utils/agent-core-constructs/files/cdk/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.ts.template +50 -0
  862. package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +487 -0
  863. package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/readiness-probe/index.js.template +55 -0
  864. package/src/utils/agent-core-constructs/files/terraform/app/agent-core/__nameKebabCase__/__nameKebabCase__.tf.template +32 -0
  865. package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.tf.template +449 -0
  866. package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/render-cedar.cjs.template +13 -0
  867. package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +151 -13
  868. package/src/utils/agent-core-constructs/files/terraform/core/agentcore-gateway/gateway.tf.template +14 -0
  869. package/src/utils/api-constructs/api-constructs.d.ts +2 -2
  870. package/src/utils/api-constructs/api-constructs.js +36 -31
  871. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  872. package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +8 -8
  873. package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +11 -8
  874. package/src/utils/api-constructs/files/cdk/core/api/http/http-api.ts.template +26 -9
  875. package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account/index.js.template +70 -0
  876. package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account.ts.template +82 -0
  877. package/src/utils/api-constructs/files/cdk/core/api/rest/rest-api.ts.template +54 -18
  878. package/src/utils/api-constructs/files/cdk/core/api/trpc/trpc-utils.ts.template +1 -1
  879. package/src/utils/api-constructs/files/cdk/core/api/utils/utils.ts.template +61 -7
  880. package/src/utils/api-constructs/files/terraform/app/apis/http/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +101 -12
  881. package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +194 -8
  882. package/src/utils/api-constructs/files/terraform/core/api/http/http-api/http-api.tf.template +1 -1
  883. package/src/utils/api-constructs/files/terraform/core/api/rest/api-gateway-account/api-gateway-account.tf.template +83 -0
  884. package/src/utils/api-constructs/files/terraform/core/api/rest/rest-api/rest-api.tf.template +5 -11
  885. package/src/utils/api-constructs/open-api-metadata.d.ts +2 -2
  886. package/src/utils/api-constructs/open-api-metadata.js +22 -22
  887. package/src/utils/api-constructs/open-api-metadata.js.map +1 -1
  888. package/src/utils/ast/website.d.ts +5 -1
  889. package/src/utils/ast/website.js +18 -20
  890. package/src/utils/ast/website.js.map +1 -1
  891. package/src/utils/ast.d.ts +33 -1
  892. package/src/utils/ast.js +146 -70
  893. package/src/utils/ast.js.map +1 -1
  894. package/src/utils/base-tsconfig.d.ts +30 -0
  895. package/src/utils/base-tsconfig.js +32 -0
  896. package/src/utils/base-tsconfig.js.map +1 -0
  897. package/src/utils/bundle/bundle.d.ts +1 -1
  898. package/src/utils/bundle/bundle.js +50 -47
  899. package/src/utils/bundle/bundle.js.map +1 -1
  900. package/src/utils/commands.d.ts +10 -3
  901. package/src/utils/commands.js +60 -26
  902. package/src/utils/commands.js.map +1 -1
  903. package/src/utils/config/index.d.ts +5 -5
  904. package/src/utils/config/index.js +5 -4
  905. package/src/utils/config/index.js.map +1 -1
  906. package/src/utils/config/utils.d.ts +13 -3
  907. package/src/utils/config/utils.js +65 -43
  908. package/src/utils/config/utils.js.map +1 -1
  909. package/src/utils/connection/open-api/files/components/__apiNameClassName__Provider.tsx.template +1 -1
  910. package/src/utils/connection/open-api/react.d.ts +6 -6
  911. package/src/utils/connection/open-api/react.js +81 -77
  912. package/src/utils/connection/open-api/react.js.map +1 -1
  913. package/src/utils/containers.d.ts +1 -1
  914. package/src/utils/containers.js +22 -23
  915. package/src/utils/containers.js.map +1 -1
  916. package/src/utils/docker.d.ts +44 -0
  917. package/src/utils/docker.js +81 -0
  918. package/src/utils/docker.js.map +1 -0
  919. package/src/utils/dynamodb-constructs/dynamodb-constructs.d.ts +3 -3
  920. package/src/utils/dynamodb-constructs/dynamodb-constructs.js +39 -41
  921. package/src/utils/dynamodb-constructs/dynamodb-constructs.js.map +1 -1
  922. package/src/utils/dynamodb-constructs/files/cdk/app/dynamodb/__nameKebabCase__.ts.template +18 -5
  923. package/src/utils/dynamodb-constructs/files/cdk/core/dynamodb.ts.template +1 -1
  924. package/src/utils/dynamodb-constructs/files/terraform/app/dynamodb/__nameKebabCase__/__nameKebabCase__.tf.template +24 -17
  925. package/src/utils/dynamodb-constructs/files/terraform/core/dynamodb/dynamodb.tf.template +1 -1
  926. package/src/utils/files/common/constructs/src/core/index.ts.template +4 -4
  927. package/src/utils/files/common/constructs/src/index.ts.template +2 -2
  928. package/src/utils/files/common/infra-config/src/index.ts.template +3 -3
  929. package/src/utils/files/common/infra-config/src/resolve-stage.ts.template +2 -2
  930. package/src/utils/files/common/infra-config/src/stages.config.ts.template +1 -1
  931. package/src/{ts/dynamodb/files/scripts → utils/files/common/scripts/src/dynamodb}/create-local-table.ts.template +65 -31
  932. package/src/utils/files/common/scripts/src/dynamodb/pull-image.ts.template +13 -0
  933. package/src/utils/files/common/scripts/src/dynamodb/start-container.ts.template +106 -0
  934. package/src/utils/files/common/scripts/src/infra/infra-deploy.ts.template +2 -0
  935. package/src/utils/files/common/scripts/src/infra/infra-destroy.ts.template +2 -0
  936. package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/cdk-command.ts.template +6 -3
  937. package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/run.ts.template +3 -3
  938. package/src/utils/files/common/scripts/src/rdb/mysql/wait-for-mysql-db.ts.template +32 -0
  939. package/src/utils/files/common/scripts/src/rdb/postgres/wait-for-postgres-db.ts.template +32 -0
  940. package/src/utils/files/common/scripts/src/rdb/shared/pull-image.ts.template +16 -0
  941. package/src/utils/files/common/scripts/src/rdb/shared/start-container.ts.template +117 -0
  942. package/src/utils/files/common/shadcn/src/index.ts.template +2 -2
  943. package/src/utils/files/terraform/src/core/asset-bucket/asset-bucket.tf.template +63 -72
  944. package/src/utils/files/terraform/src/core/runtime-config/appconfig/appconfig.tf.template +1 -1
  945. package/src/utils/files/terraform/src/core/runtime-config/appconfig-deployment/appconfig-deployment.tf.template +12 -6
  946. package/src/utils/files/terraform/src/core/runtime-config/entry/entry.tf.template +1 -1
  947. package/src/utils/files/terraform/src/core/runtime-config/read/read.tf.template +9 -4
  948. package/src/utils/files/website/hooks/sigv4/useSigV4.tsx.template +1 -1
  949. package/src/utils/format.d.ts +45 -2
  950. package/src/utils/format.js +332 -81
  951. package/src/utils/format.js.map +1 -1
  952. package/src/utils/fs.d.ts +1 -1
  953. package/src/utils/fs.js +14 -13
  954. package/src/utils/fs.js.map +1 -1
  955. package/src/utils/function-constructs/files/cdk/app/lambda-functions/__nameKebabCase__.ts.template +1 -1
  956. package/src/utils/function-constructs/files/terraform/app/lambda-functions/__nameKebabCase__/__nameKebabCase__.tf.template +2 -2
  957. package/src/utils/function-constructs/function-constructs.d.ts +2 -2
  958. package/src/utils/function-constructs/function-constructs.js +22 -25
  959. package/src/utils/function-constructs/function-constructs.js.map +1 -1
  960. package/src/utils/generators.d.ts +4 -0
  961. package/src/utils/generators.js +18 -20
  962. package/src/utils/generators.js.map +1 -1
  963. package/src/utils/git.d.ts +1 -1
  964. package/src/utils/git.js +19 -34
  965. package/src/utils/git.js.map +1 -1
  966. package/src/utils/iac-providers.js +5 -5
  967. package/src/utils/iac-providers.js.map +1 -1
  968. package/src/utils/iac.d.ts +1 -1
  969. package/src/utils/iac.js +12 -14
  970. package/src/utils/iac.js.map +1 -1
  971. package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +125 -16
  972. package/src/utils/identity-constructs/files/terraform/core/user-identity/add-callback-url/add-callback-url.tf.template +28 -9
  973. package/src/utils/identity-constructs/files/terraform/core/user-identity/identity/identity.tf.template +106 -6
  974. package/src/utils/identity-constructs/files/terraform/core/user-identity/main.tf.template +7 -0
  975. package/src/utils/identity-constructs/identity-constructs.d.ts +2 -2
  976. package/src/utils/identity-constructs/identity-constructs.js +28 -28
  977. package/src/utils/identity-constructs/identity-constructs.js.map +1 -1
  978. package/src/utils/init.d.ts +53 -0
  979. package/src/utils/init.js +252 -0
  980. package/src/utils/init.js.map +1 -0
  981. package/src/utils/install.d.ts +32 -0
  982. package/src/utils/install.js +56 -0
  983. package/src/utils/install.js.map +1 -0
  984. package/src/utils/js.d.ts +4 -0
  985. package/src/utils/js.js +27 -20
  986. package/src/utils/js.js.map +1 -1
  987. package/src/utils/mcp.d.ts +1 -1
  988. package/src/utils/mcp.js +34 -41
  989. package/src/utils/mcp.js.map +1 -1
  990. package/src/utils/metrics.d.ts +9 -3
  991. package/src/utils/metrics.js +61 -46
  992. package/src/utils/metrics.js.map +1 -1
  993. package/src/utils/mock-project-graph.js +8 -12
  994. package/src/utils/mock-project-graph.js.map +1 -1
  995. package/src/utils/module-format.d.ts +28 -0
  996. package/src/utils/module-format.js +28 -0
  997. package/src/utils/module-format.js.map +1 -0
  998. package/src/utils/names.d.ts +22 -0
  999. package/src/utils/names.js +44 -48
  1000. package/src/utils/names.js.map +1 -1
  1001. package/src/utils/npm-scope.d.ts +1 -1
  1002. package/src/utils/npm-scope.js +9 -17
  1003. package/src/utils/npm-scope.js.map +1 -1
  1004. package/src/utils/nx.d.ts +39 -4
  1005. package/src/utils/nx.js +169 -75
  1006. package/src/utils/nx.js.map +1 -1
  1007. package/src/utils/nxlv-python.d.ts +1 -1
  1008. package/src/utils/nxlv-python.js +27 -15
  1009. package/src/utils/nxlv-python.js.map +1 -1
  1010. package/src/utils/object.js +5 -11
  1011. package/src/utils/object.js.map +1 -1
  1012. package/src/utils/paths.d.ts +1 -1
  1013. package/src/utils/paths.js +11 -15
  1014. package/src/utils/paths.js.map +1 -1
  1015. package/src/utils/pkg-manager.js +4 -9
  1016. package/src/utils/pkg-manager.js.map +1 -1
  1017. package/src/utils/pnpm-workspace.d.ts +1 -1
  1018. package/src/utils/pnpm-workspace.js +22 -22
  1019. package/src/utils/pnpm-workspace.js.map +1 -1
  1020. package/src/utils/port.d.ts +29 -7
  1021. package/src/utils/port.js +67 -28
  1022. package/src/utils/port.js.map +1 -1
  1023. package/src/utils/py.d.ts +16 -3
  1024. package/src/utils/py.js +72 -47
  1025. package/src/utils/py.js.map +1 -1
  1026. package/src/utils/rdb-constructs/files/cdk/app/dbs/__nameKebabCase__.ts.template +72 -18
  1027. package/src/utils/rdb-constructs/files/cdk/core/rdb/aurora.ts.template +97 -88
  1028. package/src/utils/rdb-constructs/files/terraform/app/dbs/__nameKebabCase__/__nameKebabCase__.tf.template +127 -53
  1029. package/src/utils/rdb-constructs/files/terraform/core/rdb/aurora/aurora.tf.template +36 -48
  1030. package/src/utils/rdb-constructs/rdb-constructs.d.ts +16 -5
  1031. package/src/utils/rdb-constructs/rdb-constructs.js +38 -41
  1032. package/src/utils/rdb-constructs/rdb-constructs.js.map +1 -1
  1033. package/src/utils/shared-constructs-constants.d.ts +1 -0
  1034. package/src/utils/shared-constructs-constants.js +16 -15
  1035. package/src/utils/shared-constructs-constants.js.map +1 -1
  1036. package/src/utils/shared-constructs.d.ts +2 -2
  1037. package/src/utils/shared-constructs.js +60 -67
  1038. package/src/utils/shared-constructs.js.map +1 -1
  1039. package/src/utils/shared-dynamodb-scripts.d.ts +11 -0
  1040. package/src/utils/shared-dynamodb-scripts.js +25 -0
  1041. package/src/utils/shared-dynamodb-scripts.js.map +1 -0
  1042. package/src/utils/shared-infra-config.d.ts +1 -1
  1043. package/src/utils/shared-infra-config.js +31 -30
  1044. package/src/utils/shared-infra-config.js.map +1 -1
  1045. package/src/utils/shared-infra-scripts.d.ts +11 -0
  1046. package/src/utils/shared-infra-scripts.js +42 -0
  1047. package/src/utils/shared-infra-scripts.js.map +1 -0
  1048. package/src/utils/shared-rdb-scripts.d.ts +16 -0
  1049. package/src/utils/shared-rdb-scripts.js +32 -0
  1050. package/src/utils/shared-rdb-scripts.js.map +1 -0
  1051. package/src/utils/shared-scripts.d.ts +2 -5
  1052. package/src/utils/shared-scripts.js +12 -38
  1053. package/src/utils/shared-scripts.js.map +1 -1
  1054. package/src/utils/shared-shadcn.d.ts +1 -1
  1055. package/src/utils/shared-shadcn.js +65 -71
  1056. package/src/utils/shared-shadcn.js.map +1 -1
  1057. package/src/utils/test.d.ts +15 -1
  1058. package/src/utils/test.js +41 -23
  1059. package/src/utils/test.js.map +1 -1
  1060. package/src/utils/toml.d.ts +1 -1
  1061. package/src/utils/toml.js +10 -14
  1062. package/src/utils/toml.js.map +1 -1
  1063. package/src/utils/versions.d.ts +150 -97
  1064. package/src/utils/versions.js +157 -115
  1065. package/src/utils/versions.js.map +1 -1
  1066. package/src/utils/warm-ruff-cache.d.ts +12 -0
  1067. package/src/utils/warm-ruff-cache.js +39 -0
  1068. package/src/utils/warm-ruff-cache.js.map +1 -0
  1069. package/src/utils/website-constructs/files/cdk/app/static-websites/__websiteNameKebabCase__.ts.template +2 -2
  1070. package/src/utils/website-constructs/files/cdk/core/static-website.ts.template +200 -41
  1071. package/src/utils/website-constructs/files/terraform/app/static-websites/__websiteNameKebabCase__/__websiteNameKebabCase__.tf.template +1 -1
  1072. package/src/utils/website-constructs/files/terraform/core/static-website/static-website.tf.template +145 -93
  1073. package/src/utils/website-constructs/website-constructs.d.ts +2 -2
  1074. package/src/utils/website-constructs/website-constructs.js +38 -30
  1075. package/src/utils/website-constructs/website-constructs.js.map +1 -1
  1076. package/bin/aws-nx-mcp.js +0 -17
  1077. package/bin/aws-nx-mcp.js.map +0 -1
  1078. package/sdk/connection.d.ts +0 -6
  1079. package/sdk/connection.js +0 -10
  1080. package/sdk/connection.js.map +0 -1
  1081. package/sdk/open-api.d.ts +0 -10
  1082. package/sdk/open-api.js +0 -15
  1083. package/sdk/open-api.js.map +0 -1
  1084. package/sdk/py.d.ts +0 -14
  1085. package/sdk/py.js +0 -18
  1086. package/sdk/py.js.map +0 -1
  1087. package/sdk/terraform.d.ts +0 -6
  1088. package/sdk/terraform.js +0 -11
  1089. package/sdk/terraform.js.map +0 -1
  1090. package/sdk/ts.d.ts +0 -29
  1091. package/sdk/ts.js +0 -47
  1092. package/sdk/ts.js.map +0 -1
  1093. package/sdk/utils/ast.js +0 -12
  1094. package/sdk/utils/ast.js.map +0 -1
  1095. package/sdk/utils/format.js +0 -10
  1096. package/sdk/utils/format.js.map +0 -1
  1097. package/sdk/utils/test.js +0 -10
  1098. package/sdk/utils/test.js.map +0 -1
  1099. package/src/connection/agent-serve-local.js +0 -48
  1100. package/src/connection/agent-serve-local.js.map +0 -1
  1101. package/src/connection/serve-local.d.ts +0 -15
  1102. package/src/connection/serve-local.js +0 -41
  1103. package/src/connection/serve-local.js.map +0 -1
  1104. package/src/py/agent/a2a-connection/files/agent-connection/app/__targetAgentSnakeCase___client.py.template +0 -22
  1105. package/src/py/agent/mcp-connection/files/agent-connection/app/__mcpServerSnakeCase___client.py.template +0 -22
  1106. package/src/py/agent/react-connection/serve-local.js +0 -30
  1107. package/src/py/agent/react-connection/serve-local.js.map +0 -1
  1108. package/src/py/agent/scripts/http/chat.ts.template +0 -38
  1109. package/src/ts/agent/a2a-connection/files/agent-connection/app/__targetAgentKebabCase__-client.ts.template +0 -19
  1110. package/src/ts/agent/mcp-connection/files/agent-connection/app/__mcpServerKebabCase__-client.ts.template +0 -19
  1111. package/src/ts/agent/react-connection/serve-local.d.ts +0 -13
  1112. package/src/ts/agent/react-connection/serve-local.js +0 -19
  1113. package/src/ts/agent/react-connection/serve-local.js.map +0 -1
  1114. package/src/ts/agent/scripts/http/chat.ts.template +0 -35
  1115. package/src/ts/dynamodb/files/scripts/pull-image.ts.template +0 -15
  1116. package/src/ts/dynamodb/files/scripts/start-container.ts.template +0 -81
  1117. package/src/ts/dynamodb/files/src/constants.ts.template +0 -9
  1118. package/src/ts/dynamodb/files/src/gsi.ts.template +0 -14
  1119. package/src/ts/lib/eslint.d.ts +0 -14
  1120. package/src/ts/lib/eslint.js +0 -90
  1121. package/src/ts/lib/eslint.js.map +0 -1
  1122. package/src/ts/lib/grit/eslint-dependency-checks-warn.grit +0 -1
  1123. package/src/ts/rdb/files/scripts/docker-pull.ts.template +0 -15
  1124. package/src/ts/rdb/files/scripts/docker-start.ts.template +0 -84
  1125. package/src/ts/rdb/files/scripts/wait-for-db.ts.template +0 -55
  1126. package/src/ts/rdb/files/src/constants.ts.template +0 -8
  1127. package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client.ts.template +0 -123
  1128. package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-client.ts.template +0 -128
  1129. package/src/utils/agent-connection/files/py-core-a2a/agentcore_a2a_client.py.template +0 -120
  1130. package/src/utils/agent-connection/files/py-core-mcp/agentcore_mcp_client.py.template +0 -89
  1131. package/src/utils/files/common/scripts/src/infra-deploy.ts.template +0 -2
  1132. package/src/utils/files/common/scripts/src/infra-destroy.ts.template +0 -2
  1133. package/src/utils/files/terraform/scripts/reset-runtime-config.ts.template +0 -25
  1134. /package/{bin → src/bin}/aws-nx-mcp.d.ts +0 -0
  1135. /package/src/utils/agent-connection/files/{py-core-runtime-config/with_session_id.py.template → py-core-strands/base/with_session_id_strands.py.template} +0 -0
  1136. /package/src/utils/files/common/scripts/src/{index.ts.template → infra/index.ts.template} +0 -0
  1137. /package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/credentials.ts.template +0 -0
  1138. /package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/stage-parser.ts.template +0 -0
@@ -22,144 +22,6 @@ datasource db {
22
22
  "
23
23
  `;
24
24
 
25
- exports[`ts#rdb generator > should add mysql prisma dependencies when engine is MySQL > packages/db/scripts/docker-pull.ts 1`] = `
26
- "import { spawnSync } from 'child_process';
27
-
28
- const ENGINE = 'docker';
29
- const image = process.argv[2];
30
-
31
- const inspect = spawnSync(ENGINE, ['image', 'inspect', image], {
32
- stdio: 'ignore',
33
- });
34
-
35
- if (inspect.status !== 0) {
36
- const pull = spawnSync(ENGINE, ['pull', image], { stdio: 'inherit' });
37
- if (pull.status !== 0) {
38
- process.exit(pull.status ?? 1);
39
- }
40
- }
41
- "
42
- `;
43
-
44
- exports[`ts#rdb generator > should add mysql prisma dependencies when engine is MySQL > packages/db/scripts/docker-start.ts 1`] = `
45
- "import { spawn, spawnSync } from 'child_process';
46
-
47
- const ENGINE = 'docker';
48
-
49
- const [containerName, image, hostPort, dbName, dbPassword] =
50
- process.argv.slice(2);
51
-
52
- const containerExists = (): boolean =>
53
- spawnSync(ENGINE, ['container', 'inspect', containerName], {
54
- stdio: 'ignore',
55
- }).status === 0;
56
-
57
- const isRunning = (): boolean => {
58
- const result = spawnSync(
59
- ENGINE,
60
- ['container', 'inspect', '-f', '{{.State.Running}}', containerName],
61
- { encoding: 'utf-8' },
62
- );
63
- return result.status === 0 && result.stdout.trim() === 'true';
64
- };
65
-
66
- if (containerExists()) {
67
- if (!isRunning()) {
68
- const start = spawnSync(ENGINE, ['start', containerName], {
69
- stdio: 'inherit',
70
- });
71
- if (start.status !== 0) process.exit(start.status ?? 1);
72
- }
73
- } else {
74
- const runArgs = [
75
- 'run',
76
- '--name',
77
- containerName,
78
- '-e',
79
- \`MYSQL_DATABASE=\${dbName}\`,
80
- '-e',
81
- \`MYSQL_ROOT_PASSWORD=\${dbPassword}\`,
82
- '-p',
83
- \`\${hostPort}:3306\`,
84
- '-v',
85
- \`\${containerName}-data:/var/lib/mysql\`,
86
- '-d',
87
- image,
88
- ];
89
- const create = spawnSync(ENGINE, runArgs, { stdio: 'inherit' });
90
- if (create.status !== 0) process.exit(create.status ?? 1);
91
- }
92
-
93
- const logs = spawn(ENGINE, ['logs', '-f', containerName], {
94
- stdio: ['ignore', 'inherit', 'inherit'],
95
- });
96
-
97
- let exiting = false;
98
-
99
- const cleanup = () => {
100
- if (exiting) return;
101
- exiting = true;
102
- spawnSync(ENGINE, ['stop', containerName], { stdio: 'ignore' });
103
- logs.kill();
104
- process.exit(0);
105
- };
106
-
107
- process.on('SIGTERM', cleanup);
108
- process.on('SIGINT', cleanup);
109
- process.on('SIGHUP', cleanup);
110
-
111
- logs.on('exit', (code) => {
112
- if (!exiting) process.exit(code ?? 0);
113
- });
114
- "
115
- `;
116
-
117
- exports[`ts#rdb generator > should add mysql prisma dependencies when engine is MySQL > packages/db/scripts/wait-for-db.ts 1`] = `
118
- "import { createConnection, Connection } from 'mariadb';
119
-
120
- const noop = () => undefined;
121
-
122
- const [portArg, dbArg, userArg, passwordArg] = process.argv.slice(2);
123
- const timeoutAt = Date.now() + 60000;
124
-
125
- while (Date.now() < timeoutAt) {
126
- let conn: Connection | undefined;
127
- try {
128
- conn = await createConnection({
129
- host: 'localhost',
130
- port: parseInt(portArg),
131
- user: userArg,
132
- password: passwordArg,
133
- database: dbArg,
134
- connectTimeout: 500,
135
- allowPublicKeyRetrieval: true,
136
- });
137
- await conn.end();
138
- console.log('Database is ready.');
139
- process.exit(0);
140
- } catch {
141
- console.log('Database is not ready.');
142
- await conn?.end().catch(noop);
143
- }
144
- await new Promise((r) => setTimeout(r, 200));
145
- }
146
-
147
- throw new Error(\`Timed out waiting for mysql on port \${portArg}\`);
148
- "
149
- `;
150
-
151
- exports[`ts#rdb generator > should add mysql prisma dependencies when engine is MySQL > packages/db/src/constants.ts 1`] = `
152
- "export const DB_PACKAGE_NAME = 'Db';
153
-
154
- // Local development connection details (used when SERVE_LOCAL=true, see serve-local Nx target)
155
- export const LOCAL_DB_PORT = 3306;
156
- export const LOCAL_DB_HOST = 'localhost';
157
- export const LOCAL_DB_NAME = 'database_name';
158
- export const LOCAL_DB_USER = 'root';
159
- export const LOCAL_DB_PASSWORD = 'password';
160
- "
161
- `;
162
-
163
25
  exports[`ts#rdb generator > should add mysql prisma dependencies when engine is MySQL > packages/db/src/create-db-user-handler.ts 1`] = `
164
26
  "import type { CloudFormationCustomResourceEvent } from 'aws-lambda';
165
27
  import { randomBytes } from 'node:crypto';
@@ -206,7 +68,7 @@ const ensureDatabaseUser = async (dbUser: string): Promise<void> => {
206
68
  [
207
69
  \`CREATE USER IF NOT EXISTS \${quotedUser}@\${quotedHost} IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS'\`,
208
70
  \`ALTER USER \${quotedUser}@\${quotedHost} IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS' REQUIRE SSL\`,
209
- \`GRANT ALL PRIVILEGES ON \${quotedDbName}.* TO \${quotedUser}@\${quotedHost}\`,
71
+ \`GRANT SELECT, INSERT, UPDATE, DELETE ON \${quotedDbName}.* TO \${quotedUser}@\${quotedHost}\`,
210
72
  ].join(';\\n'),
211
73
  );
212
74
  } finally {
@@ -237,8 +99,7 @@ export const handler = async (
237
99
  `;
238
100
 
239
101
  exports[`ts#rdb generator > should add mysql prisma dependencies when engine is MySQL > packages/db/src/index.ts 1`] = `
240
- "export { DB_PACKAGE_NAME } from './constants.js';
241
- export { getPrisma } from './prisma.js';
102
+ "export { getPrisma } from './prisma.js';
242
103
  "
243
104
  `;
244
105
 
@@ -277,26 +138,30 @@ exports[`ts#rdb generator > should add mysql prisma dependencies when engine is
277
138
  "import { PrismaMariaDb } from '@prisma/adapter-mariadb';
278
139
  import { Signer } from '@aws-sdk/rds-signer';
279
140
  import { Prisma, PrismaClient } from '../generated/prisma/client.js';
280
- import {
281
- DB_PACKAGE_NAME,
282
- LOCAL_DB_HOST,
283
- LOCAL_DB_NAME,
284
- LOCAL_DB_PASSWORD,
285
- LOCAL_DB_PORT,
286
- LOCAL_DB_USER,
287
- } from './constants.js';
141
+ import { readFileSync } from 'fs';
142
+ import { join, dirname } from 'path';
143
+ import { fileURLToPath } from 'url';
288
144
  import { getDatabaseConfig } from './utils.js';
289
145
 
146
+ // Generated: must match runtimeConfigKey in config.json
147
+ const runtimeConfigKey = 'Db';
148
+
149
+ const __dirname = dirname(fileURLToPath(import.meta.url));
150
+ // config.json is only present in local dev (not included in the deployed bundle); guard with LOCAL_DEV check
151
+ const localDev = () =>
152
+ JSON.parse(readFileSync(join(__dirname, '../config.json'), 'utf-8')).localDev;
153
+
290
154
  export const getPrisma = async <LogOpts extends Prisma.LogLevel>(
291
155
  log: LogOpts[] = ['warn', 'error'] as LogOpts[],
292
156
  ): Promise<PrismaClient<LogOpts>> => {
293
- if (process.env.SERVE_LOCAL === 'true') {
157
+ if (process.env.LOCAL_DEV === 'true') {
158
+ const { host, port, dbName, dbUser, dbPassword } = localDev();
294
159
  const adapter = new PrismaMariaDb({
295
- host: LOCAL_DB_HOST,
296
- port: LOCAL_DB_PORT,
297
- database: LOCAL_DB_NAME,
298
- user: LOCAL_DB_USER,
299
- password: LOCAL_DB_PASSWORD,
160
+ host,
161
+ port,
162
+ database: dbName,
163
+ user: dbUser,
164
+ password: dbPassword,
300
165
  allowPublicKeyRetrieval: true,
301
166
  });
302
167
  return new PrismaClient({
@@ -306,7 +171,7 @@ export const getPrisma = async <LogOpts extends Prisma.LogLevel>(
306
171
  }
307
172
 
308
173
  const { hostname, port, database, dbUser, region } =
309
- await getDatabaseConfig(DB_PACKAGE_NAME);
174
+ await getDatabaseConfig(runtimeConfigKey);
310
175
  const iamAuthToken = await new Signer({
311
176
  hostname,
312
177
  port,
@@ -431,6 +296,9 @@ const transientErrorPatterns = [
431
296
  'ECONNREFUSED',
432
297
  'ENOTFOUND',
433
298
  'P1000', // Prisma: authentication failed
299
+ 'P1001', // Prisma: can't reach database server
300
+ 'P1002', // Prisma: database server reached but timed out
301
+ 'P1010', // Prisma: user denied access (IAM auth grant not yet propagated)
434
302
  'ER_ACCESS_DENIED_ERROR', // MySQL: access denied
435
303
  ];
436
304
 
@@ -491,14 +359,10 @@ import { CustomResource } from 'aws-cdk-lib';
491
359
  import { IConnectable, IVpc, Port, SubnetType } from 'aws-cdk-lib/aws-ec2';
492
360
  import { IGrantable, Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam';
493
361
  import { Key } from 'aws-cdk-lib/aws-kms';
494
- import { Platform } from 'aws-cdk-lib/aws-ecr-assets';
495
362
  import {
496
363
  Architecture,
497
- Code,
498
- DockerImageCode,
499
- DockerImageFunction,
500
364
  Function,
501
- Runtime,
365
+ FunctionOptions,
502
366
  Tracing,
503
367
  } from 'aws-cdk-lib/aws-lambda';
504
368
  import {
@@ -614,16 +478,6 @@ export interface AuroraDatabaseProps extends _AuroraDatabaseProps {
614
478
  */
615
479
  readonly runtimeConfigKey: string;
616
480
 
617
- /**
618
- * Migration bundle used to create a migration handler Lambda.
619
- */
620
- readonly migrationBundleDir: string;
621
-
622
- /**
623
- * Bundle used to create or reconcile the application database user.
624
- */
625
- readonly createDbUserBundleDir: string;
626
-
627
481
  /**
628
482
  * Writer instance for the Aurora cluster.
629
483
  */
@@ -663,6 +517,21 @@ export interface AuroraDatabaseProps extends _AuroraDatabaseProps {
663
517
  * @default true
664
518
  */
665
519
  readonly enableKeyRotation?: boolean;
520
+
521
+ /**
522
+ * Whether to export Aurora engine logs to CloudWatch Logs.
523
+ * See https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_LogAccess.html
524
+ *
525
+ * @default false
526
+ */
527
+ readonly enableCloudwatchLogs?: boolean;
528
+
529
+ /**
530
+ * Whether to enable Performance Insights on the Aurora writer instance.
531
+ *
532
+ * @default true
533
+ */
534
+ readonly enablePerformanceInsights?: boolean;
666
535
  }
667
536
 
668
537
  /**
@@ -683,8 +552,6 @@ export abstract class AuroraDatabase extends Construct {
683
552
  adminUser,
684
553
  databaseName,
685
554
  runtimeConfigKey,
686
- migrationBundleDir,
687
- createDbUserBundleDir,
688
555
  vpcSubnets,
689
556
  writer,
690
557
  enableRdsProxy = true,
@@ -692,6 +559,8 @@ export abstract class AuroraDatabase extends Construct {
692
559
  deletionProtection = true,
693
560
  removalPolicy = RemovalPolicy.RETAIN,
694
561
  enableKeyRotation = true,
562
+ enableCloudwatchLogs = false,
563
+ enablePerformanceInsights = true,
695
564
  engine,
696
565
  engineVersion,
697
566
  ...clusterProps
@@ -707,12 +576,24 @@ export abstract class AuroraDatabase extends Construct {
707
576
  vpc,
708
577
  vpcSubnets,
709
578
  engine: engine.clusterEngine(engineVersion ?? engine.defaultVersion),
710
- writer: writer ?? ClusterInstance.serverlessV2('writer'),
579
+ writer:
580
+ writer ??
581
+ ClusterInstance.serverlessV2('writer', {
582
+ enablePerformanceInsights,
583
+ performanceInsightEncryptionKey: enablePerformanceInsights
584
+ ? key
585
+ : undefined,
586
+ }),
711
587
  credentials: Credentials.fromGeneratedSecret(adminUser, {
712
588
  encryptionKey: key,
713
589
  }),
714
590
  iamAuthentication: true,
715
591
  monitoringInterval: Duration.seconds(5),
592
+ cloudwatchLogsExports: enableCloudwatchLogs
593
+ ? engine.type === 'mysql'
594
+ ? ['audit', 'error', 'general', 'slowquery']
595
+ : ['postgresql']
596
+ : undefined,
716
597
  defaultDatabaseName: databaseName,
717
598
  storageEncrypted: true,
718
599
  storageEncryptionKey: key,
@@ -748,23 +629,23 @@ export abstract class AuroraDatabase extends Construct {
748
629
  this.proxy?.endpoint ?? this.cluster.clusterEndpoint.hostname;
749
630
  const databasePort = this.cluster.clusterEndpoint.port;
750
631
 
751
- const createDbUserHandler = new Function(this, 'CreateDbUserHandler', {
752
- code: Code.fromAsset(createDbUserBundleDir),
753
- handler: 'index.handler',
754
- runtime: Runtime.NODEJS_LATEST,
632
+ const commonProps: FunctionOptions = {
633
+ vpc,
755
634
  timeout: Duration.minutes(5),
756
635
  tracing: Tracing.ACTIVE,
757
- vpc,
636
+ architecture: Architecture.ARM_64,
637
+ };
638
+
639
+ const createDbUserHandler = this.createDbUserHandler({
640
+ ...commonProps,
758
641
  vpcSubnets: {
759
642
  subnetType: SubnetType.PRIVATE_WITH_EGRESS,
760
643
  },
761
- environment: {
762
- DATABASE_SECRET_ARN: this.cluster.secret!.secretArn,
763
- NODE_EXTRA_CA_CERTS: '/var/runtime/ca-cert.pem',
764
- },
765
- architecture: Architecture.ARM_64,
766
644
  });
767
-
645
+ createDbUserHandler.addEnvironment(
646
+ 'DATABASE_SECRET_ARN',
647
+ this.cluster.secret!.secretArn,
648
+ );
768
649
  this.cluster.connections.allowDefaultPortFrom(
769
650
  createDbUserHandler,
770
651
  'Allow the create-db-user handler to connect to the database',
@@ -801,40 +682,21 @@ export abstract class AuroraDatabase extends Construct {
801
682
  region: Stack.of(this).region,
802
683
  });
803
684
 
804
- const migrationHandler = new DockerImageFunction(this, 'MigrationHandler', {
805
- code: DockerImageCode.fromImageAsset(migrationBundleDir, {
806
- platform: Platform.LINUX_ARM64,
807
- }),
685
+ const migrationHandler = this.createMigrationHandler({
686
+ ...commonProps,
808
687
  memorySize: 1024,
809
- timeout: Duration.minutes(5),
810
- tracing: Tracing.ACTIVE,
811
- vpc,
812
- environment:
813
- engine.type === 'mysql'
814
- ? {
815
- DATABASE_SECRET_ARN: this.cluster.secret!.secretArn,
816
- }
817
- : {
818
- HOSTNAME: databaseHostname,
819
- DATABASE: databaseName,
820
- PORT: databasePort.toString(),
821
- DBUSER: this.dbUser,
822
- },
823
- architecture: Architecture.ARM_64,
824
688
  });
689
+ migrationHandler.addEnvironment(
690
+ 'DATABASE_SECRET_ARN',
691
+ this.cluster.secret!.secretArn,
692
+ );
693
+ this.cluster.connections.allowDefaultPortFrom(migrationHandler);
694
+ this.grantSecretRead(migrationHandler);
825
695
 
826
- if (engine.type === 'mysql') {
827
- this.cluster.connections.allowDefaultPortFrom(migrationHandler);
828
- this.grantSecretRead(migrationHandler);
829
- } else {
830
- this.allowDefaultPortFrom(migrationHandler);
831
- this.grantConnect(migrationHandler);
832
- }
833
-
834
- const trigger = new Trigger(this, 'MigrationTrigger', {
696
+ const migrationTrigger = new Trigger(this, 'MigrationTrigger', {
835
697
  handler: migrationHandler,
836
698
  });
837
- trigger.node.addDependency(createDbUserResource);
699
+ migrationTrigger.node.addDependency(createDbUserResource);
838
700
 
839
701
  new CfnOutput(this, 'ClusterEndpoint', {
840
702
  value: this.cluster.clusterEndpoint.hostname,
@@ -847,6 +709,18 @@ export abstract class AuroraDatabase extends Construct {
847
709
  }
848
710
  }
849
711
 
712
+ /**
713
+ * Creates the Lambda handler used to create or reconcile the application database user.
714
+ */
715
+ protected abstract createDbUserHandler(baseProps: FunctionOptions): Function;
716
+
717
+ /**
718
+ * Creates the Lambda handler used to run database migrations.
719
+ */
720
+ protected abstract createMigrationHandler(
721
+ baseProps: FunctionOptions,
722
+ ): Function;
723
+
850
724
  public allowDefaultPortFrom(other: IConnectable, description?: string): void {
851
725
  if (this.proxy) {
852
726
  this.proxy.connections.allowFrom(
@@ -874,17 +748,14 @@ export abstract class AuroraDatabase extends Construct {
874
748
 
875
749
  exports[`ts#rdb generator > should add mysql prisma dependencies when engine is MySQL 2`] = `
876
750
  "import { defineConfig } from 'prisma/config';
751
+ import { readFileSync } from 'fs';
877
752
 
878
753
  const getDatabaseUrl = async () => {
879
- if (process.env.SERVE_LOCAL === 'true') {
880
- const {
881
- LOCAL_DB_HOST,
882
- LOCAL_DB_NAME,
883
- LOCAL_DB_PASSWORD,
884
- LOCAL_DB_PORT,
885
- LOCAL_DB_USER,
886
- } = await import('./src/constants.js');
887
- return \`mysql://\${LOCAL_DB_USER}:\${LOCAL_DB_PASSWORD}@\${LOCAL_DB_HOST}:\${LOCAL_DB_PORT}/\${LOCAL_DB_NAME}\`;
754
+ if (process.env.LOCAL_DEV === 'true') {
755
+ const { host, port, dbName, dbUser, dbPassword } = JSON.parse(
756
+ readFileSync('config.json', 'utf-8'),
757
+ ).localDev;
758
+ return \`mysql://\${dbUser}:\${dbPassword}@\${host}:\${port}/\${dbName}\`;
888
759
  }
889
760
  return process.env.DATABASE_URL;
890
761
  };
@@ -911,15 +782,15 @@ terraform {
911
782
  required_providers {
912
783
  aws = {
913
784
  source = "hashicorp/aws"
914
- version = "~> 6.33"
785
+ version = "6.54.0"
915
786
  }
916
787
  null = {
917
788
  source = "hashicorp/null"
918
- version = ">= 3.0"
789
+ version = "3.3.0"
919
790
  }
920
791
  random = {
921
792
  source = "hashicorp/random"
922
- version = ">= 3.0"
793
+ version = "3.9.0"
923
794
  }
924
795
  }
925
796
  }
@@ -1063,10 +934,19 @@ variable "tags" {
1063
934
  default = {}
1064
935
  }
1065
936
 
937
+ # Suffix appended to physical resource names so that multiple deployments
938
+ # (e.g. separate environments in the same account and region) don't collide.
939
+ resource "random_string" "suffix" {
940
+ length = 8
941
+ special = false
942
+ upper = false
943
+ }
944
+
1066
945
  locals {
1067
946
  default_port = var.engine == "aurora-mysql" ? 3306 : 5432
1068
947
  default_engine_version = var.engine == "aurora-mysql" ? "8.0.mysql_aurora.3.12.0" : "17.7"
1069
948
  parameter_group_family = var.engine == "aurora-mysql" ? "aurora-mysql8.0" : "aurora-postgresql\${split(".", coalesce(var.engine_version, local.default_engine_version))[0]}"
949
+ cluster_name = "\${var.name}-aurora-\${random_string.suffix.result}"
1070
950
  }
1071
951
 
1072
952
  resource "aws_rds_cluster_parameter_group" "database" {
@@ -1164,7 +1044,7 @@ resource "aws_security_group" "database" {
1164
1044
  }
1165
1045
 
1166
1046
  resource "aws_db_subnet_group" "database" {
1167
- name = "\${var.name}-aurora"
1047
+ name = local.cluster_name
1168
1048
  subnet_ids = var.subnet_ids
1169
1049
 
1170
1050
  tags = merge(var.tags, {
@@ -1204,7 +1084,7 @@ resource "aws_secretsmanager_secret_version" "credentials" {
1204
1084
  resource "aws_rds_cluster" "database" {
1205
1085
  #checkov:skip=CKV2_AWS_27:Query logging can be enabled with enable_cloudwatch_logs; this module defaults to CDK-equivalent behavior unless logging is requested
1206
1086
  #checkov:skip=CKV_AWS_139:Deletion protection is enabled but checkov is unable to detect it correctly
1207
- cluster_identifier = "\${var.name}-aurora"
1087
+ cluster_identifier = local.cluster_name
1208
1088
  engine = var.engine
1209
1089
  engine_version = coalesce(var.engine_version, local.default_engine_version)
1210
1090
  database_name = var.database_name
@@ -1218,7 +1098,7 @@ resource "aws_rds_cluster" "database" {
1218
1098
  kms_key_id = aws_kms_key.database.arn
1219
1099
  deletion_protection = var.deletion_protection
1220
1100
  skip_final_snapshot = var.skip_final_snapshot
1221
- final_snapshot_identifier = var.skip_final_snapshot ? null : "\${var.name}-aurora-final-snapshot"
1101
+ final_snapshot_identifier = var.skip_final_snapshot ? null : "\${local.cluster_name}-final-snapshot"
1222
1102
  iam_database_authentication_enabled = true
1223
1103
  monitoring_interval = 5
1224
1104
  monitoring_role_arn = aws_iam_role.enhanced_monitoring.arn
@@ -1238,7 +1118,7 @@ resource "aws_rds_cluster" "database" {
1238
1118
  resource "aws_rds_cluster_instance" "database" {
1239
1119
  count = var.instance_count
1240
1120
 
1241
- identifier = "\${var.name}-aurora-\${count.index + 1}"
1121
+ identifier = "\${local.cluster_name}-\${count.index + 1}"
1242
1122
  cluster_identifier = aws_rds_cluster.database.id
1243
1123
  instance_class = "db.serverless"
1244
1124
  engine = aws_rds_cluster.database.engine
@@ -1292,7 +1172,7 @@ resource "aws_vpc_security_group_ingress_rule" "rotation_to_database" {
1292
1172
  resource "aws_cloudformation_stack" "credentials_rotation" {
1293
1173
  #checkov:skip=CKV_AWS_124:SNS event notifications are not required for the credentials rotation stack
1294
1174
  count = var.enable_credential_rotation ? 1 : 0
1295
- name = "\${var.name}-aurora-credentials-rotation"
1175
+ name = "\${local.cluster_name}-credentials-rotation"
1296
1176
 
1297
1177
  capabilities = ["CAPABILITY_IAM", "CAPABILITY_AUTO_EXPAND"]
1298
1178
 
@@ -1306,7 +1186,7 @@ resource "aws_cloudformation_stack" "credentials_rotation" {
1306
1186
  SecretId = aws_secretsmanager_secret.credentials.arn
1307
1187
  HostedRotationLambda = {
1308
1188
  RotationType = var.engine == "aurora-mysql" ? "MySQLSingleUser" : "PostgreSQLSingleUser"
1309
- RotationLambdaName = "\${var.name}-aurora-credentials-rotation"
1189
+ RotationLambdaName = "\${local.cluster_name}-credentials-rotation"
1310
1190
  VpcSecurityGroupIds = aws_security_group.rotation[0].id
1311
1191
  VpcSubnetIds = join(",", var.lambda_subnet_ids)
1312
1192
  }
@@ -1349,27 +1229,6 @@ resource "aws_iam_role" "proxy" {
1349
1229
  })
1350
1230
  }
1351
1231
 
1352
- resource "aws_iam_role_policy" "proxy_secret_access" {
1353
- count = var.enable_rds_proxy ? 1 : 0
1354
- role = aws_iam_role.proxy[0].name
1355
-
1356
- policy = jsonencode({
1357
- Version = "2012-10-17"
1358
- Statement = [
1359
- {
1360
- Effect = "Allow"
1361
- Action = ["secretsmanager:GetSecretValue"]
1362
- Resource = [aws_secretsmanager_secret.credentials.arn]
1363
- },
1364
- {
1365
- Effect = "Allow"
1366
- Action = ["kms:Decrypt"]
1367
- Resource = [aws_kms_key.database.arn]
1368
- }
1369
- ]
1370
- })
1371
- }
1372
-
1373
1232
  resource "aws_security_group" "proxy" {
1374
1233
  #checkov:skip=CKV2_AWS_5:Security group is attached to aws_db_proxy.aurora; Checkov cannot resolve count-conditional cross-resource references
1375
1234
  count = var.enable_rds_proxy ? 1 : 0
@@ -1386,24 +1245,13 @@ resource "aws_security_group" "proxy" {
1386
1245
  resource "aws_db_proxy" "aurora" {
1387
1246
  count = var.enable_rds_proxy ? 1 : 0
1388
1247
 
1389
- name = "\${var.name}-proxy"
1248
+ name = "\${var.name}-proxy-\${random_string.suffix.result}"
1390
1249
  default_auth_scheme = "IAM_AUTH"
1391
1250
  engine_family = var.engine == "aurora-mysql" ? "MYSQL" : "POSTGRESQL"
1392
1251
  role_arn = aws_iam_role.proxy[0].arn
1393
1252
  vpc_subnet_ids = var.subnet_ids
1394
1253
  vpc_security_group_ids = [aws_security_group.proxy[0].id]
1395
1254
  require_tls = true
1396
-
1397
- auth {
1398
- auth_scheme = "SECRETS"
1399
- iam_auth = "REQUIRED"
1400
- secret_arn = aws_secretsmanager_secret.credentials.arn
1401
- }
1402
-
1403
- depends_on = [
1404
- aws_iam_role_policy.proxy_secret_access,
1405
- aws_secretsmanager_secret_version.credentials,
1406
- ]
1407
1255
  }
1408
1256
 
1409
1257
  resource "aws_db_proxy_default_target_group" "default" {
@@ -1435,9 +1283,9 @@ resource "null_resource" "proxy_target_ready" {
1435
1283
  deadline=$((start_time + 600))
1436
1284
  while true; do
1437
1285
  target_state=$(aws rds describe-db-proxy-targets \\
1438
- --region \${data.aws_region.current.region} \\
1439
- --db-proxy-name \${self.triggers.db_proxy_name} \\
1440
- --target-group-name \${self.triggers.target_group_name} \\
1286
+ --region "$AWS_REGION" \\
1287
+ --db-proxy-name "$DB_PROXY_NAME" \\
1288
+ --target-group-name "$TARGET_GROUP_NAME" \\
1441
1289
  --query "Targets[?Type=='RDS_INSTANCE'] | [0].TargetHealth.State" \\
1442
1290
  --output text)
1443
1291
 
@@ -1447,13 +1295,19 @@ resource "null_resource" "proxy_target_ready" {
1447
1295
 
1448
1296
  current_time=$(date +%s)
1449
1297
  if [ "$current_time" -ge "$deadline" ]; then
1450
- echo "RDS Proxy target \${self.triggers.db_cluster_identifier} did not become AVAILABLE within 10 minutes. Last state: $target_state"
1298
+ echo "RDS Proxy target $DB_CLUSTER_IDENTIFIER did not become AVAILABLE within 10 minutes. Last state: $target_state"
1451
1299
  exit 1
1452
1300
  fi
1453
1301
 
1454
1302
  sleep 10
1455
1303
  done
1456
1304
  EOT
1305
+ environment = {
1306
+ AWS_REGION = data.aws_region.current.region
1307
+ DB_PROXY_NAME = self.triggers.db_proxy_name
1308
+ TARGET_GROUP_NAME = self.triggers.target_group_name
1309
+ DB_CLUSTER_IDENTIFIER = self.triggers.db_cluster_identifier
1310
+ }
1457
1311
  }
1458
1312
 
1459
1313
  depends_on = [
@@ -1532,7 +1386,7 @@ resource "aws_iam_role_policy_attachment" "backup" {
1532
1386
  resource "aws_backup_vault" "database" {
1533
1387
  count = var.enable_backup ? 1 : 0
1534
1388
 
1535
- name = "\${var.name}-aurora-backup"
1389
+ name = "\${local.cluster_name}-backup"
1536
1390
  kms_key_arn = aws_kms_key.database.arn
1537
1391
  tags = var.tags
1538
1392
  }
@@ -1540,7 +1394,7 @@ resource "aws_backup_vault" "database" {
1540
1394
  resource "aws_backup_plan" "database" {
1541
1395
  count = var.enable_backup ? 1 : 0
1542
1396
 
1543
- name = "\${var.name}-aurora-backup"
1397
+ name = "\${local.cluster_name}-backup"
1544
1398
 
1545
1399
  rule {
1546
1400
  rule_name = "daily-backup"
@@ -1580,6 +1434,11 @@ output "proxy_resource_id" {
1580
1434
  value = var.enable_rds_proxy ? split(":", aws_db_proxy.aurora[0].arn)[6] : null
1581
1435
  }
1582
1436
 
1437
+ output "connect_resource_id" {
1438
+ description = "Resource ID to use in IAM rds-db:connect policies for the application database user. Resolves to the RDS Proxy resource ID when the proxy is enabled (the default), or the Aurora cluster resource ID when it is disabled — connecting through the proxy and connecting directly to the cluster are different IAM permission boundaries."
1439
+ value = var.enable_rds_proxy ? split(":", aws_db_proxy.aurora[0].arn)[6] : aws_rds_cluster.database.cluster_resource_id
1440
+ }
1441
+
1583
1442
  output "cluster_endpoint" {
1584
1443
  description = "Writer endpoint of the Aurora cluster or proxy."
1585
1444
  value = var.enable_rds_proxy ? aws_db_proxy.aurora[0].endpoint : aws_rds_cluster.database.endpoint
@@ -1654,19 +1513,19 @@ exports[`ts#rdb generator > should generate terraform modules when iac is Terraf
1654
1513
  required_providers {
1655
1514
  archive = {
1656
1515
  source = "hashicorp/archive"
1657
- version = "~> 2.5"
1516
+ version = "2.8.0"
1658
1517
  }
1659
1518
  aws = {
1660
1519
  source = "hashicorp/aws"
1661
- version = "~> 6.33"
1520
+ version = "6.54.0"
1662
1521
  }
1663
1522
  null = {
1664
1523
  source = "hashicorp/null"
1665
- version = ">= 3.0"
1524
+ version = "3.3.0"
1666
1525
  }
1667
1526
  random = {
1668
1527
  source = "hashicorp/random"
1669
- version = ">= 3.0"
1528
+ version = "3.9.0"
1670
1529
  }
1671
1530
  }
1672
1531
  }
@@ -1770,12 +1629,13 @@ variable "tags" {
1770
1629
  default = {}
1771
1630
  }
1772
1631
 
1773
- variable "docker_image_tag" {
1632
+ variable "migration_docker_image_tag" {
1774
1633
  description = "Docker image tag for the migration handler. Defaults to the tag built by the Nx docker target."
1775
1634
  type = string
1776
1635
  default = "proj-db-migration:latest"
1777
1636
  }
1778
1637
 
1638
+
1779
1639
  variable "asset_bucket_name" {
1780
1640
  description = "Name of the shared asset S3 bucket used to stage the Lambda deployment zip. Instantiate the \`core/asset-bucket\` module once per deployment and pass its \`bucket_name\` output here."
1781
1641
  type = string
@@ -1791,10 +1651,12 @@ resource "random_string" "suffix" {
1791
1651
  }
1792
1652
 
1793
1653
  locals {
1794
- create_db_user_bundle_path = "\${path.module}/../../../../../../../dist/packages/db/bundle/create-db-user"
1795
- migration_function_name = "db-migration-\${random_string.suffix.result}"
1654
+ config = jsondecode(file("\${path.module}/../../../../../../../packages/db/config.json"))
1655
+ runtime_config_key = local.config.runtimeConfigKey
1656
+ create_db_user_bundle_path = "\${path.module}/../../../../../../../dist/packages/db/bundle/create-db-user"
1657
+ migration_function_name = "db-migration-\${random_string.suffix.result}"
1796
1658
  create_db_user_function_name = "db-create-db-user-\${random_string.suffix.result}"
1797
- database_runtime_user = "db_\${random_string.suffix.result}"
1659
+ database_runtime_user = "db_\${random_string.suffix.result}"
1798
1660
  }
1799
1661
 
1800
1662
  module "aurora" {
@@ -1860,7 +1722,7 @@ module "add_rdb_to_runtime_config" {
1860
1722
  source = "../../../core/runtime-config/entry"
1861
1723
 
1862
1724
  namespace = "database"
1863
- key = "Db"
1725
+ key = local.runtime_config_key
1864
1726
  value = {
1865
1727
  hostname = module.aurora.cluster_endpoint
1866
1728
  port = module.aurora.cluster_port
@@ -1873,9 +1735,8 @@ module "add_rdb_to_runtime_config" {
1873
1735
 
1874
1736
  resource "aws_ecr_repository" "migration_handler" {
1875
1737
  #checkov:skip=CKV_AWS_136:AES256 encryption is sufficient for ECR repositories
1876
- #checkov:skip=CKV_AWS_51:Mutable tags are intentional; the migration handler is always pushed as latest and redeployment is gated on docker_digest changes in null_resource.docker_publish
1877
1738
  name = "db-migration-\${random_string.suffix.result}"
1878
- image_tag_mutability = "MUTABLE"
1739
+ image_tag_mutability = "IMMUTABLE"
1879
1740
  force_delete = true
1880
1741
 
1881
1742
  image_scanning_configuration {
@@ -1923,22 +1784,34 @@ resource "aws_ecr_repository_policy" "migration_handler" {
1923
1784
  }
1924
1785
 
1925
1786
  data "external" "docker_digest" {
1926
- program = ["sh", "-c", "echo '{\\"digest\\":\\"'$(docker inspect \${var.docker_image_tag} --format '{{.Id}}')'\\"}' "]
1787
+ program = ["sh", "-c", "echo '{\\"digest\\":\\"'$(docker inspect \${var.migration_docker_image_tag} --format '{{.Id}}')'\\"}' "]
1788
+ }
1789
+
1790
+ locals {
1791
+ # Content-based, immutable image tag derived from the local image digest
1792
+ image_tag = replace(data.external.docker_digest.result.digest, "sha256:", "")
1927
1793
  }
1928
1794
 
1929
1795
  resource "null_resource" "docker_publish" {
1930
1796
  triggers = {
1931
1797
  docker_digest = data.external.docker_digest.result.digest
1932
1798
  repository_url = aws_ecr_repository.migration_handler.repository_url
1933
- docker_image_tag = var.docker_image_tag
1799
+ migration_docker_image_tag = var.migration_docker_image_tag
1800
+ image_tag = local.image_tag
1934
1801
  }
1935
1802
 
1936
1803
  provisioner "local-exec" {
1937
1804
  command = <<-EOT
1938
- aws ecr get-login-password --region \${data.aws_region.current.region} | docker login --username AWS --password-stdin \${self.triggers.repository_url}
1939
- docker tag \${self.triggers.docker_image_tag} \${self.triggers.repository_url}:latest
1940
- docker push \${self.triggers.repository_url}:latest
1805
+ aws ecr get-login-password --region "$AWS_REGION" | docker login --username AWS --password-stdin "$REPOSITORY_URL"
1806
+ docker tag "$MIGRATION_DOCKER_IMAGE_TAG" "$REPOSITORY_URL:$IMAGE_TAG"
1807
+ docker push "$REPOSITORY_URL:$IMAGE_TAG"
1941
1808
  EOT
1809
+ environment = {
1810
+ AWS_REGION = data.aws_region.current.region
1811
+ REPOSITORY_URL = self.triggers.repository_url
1812
+ MIGRATION_DOCKER_IMAGE_TAG = self.triggers.migration_docker_image_tag
1813
+ IMAGE_TAG = self.triggers.image_tag
1814
+ }
1942
1815
  }
1943
1816
 
1944
1817
  depends_on = [aws_ecr_repository_policy.migration_handler]
@@ -1987,11 +1860,16 @@ resource "aws_iam_role_policy" "migration_handler_access" {
1987
1860
  {
1988
1861
  Effect = "Allow"
1989
1862
  Action = [
1990
- "rds-db:connect"
1863
+ "secretsmanager:GetSecretValue"
1991
1864
  ]
1992
- Resource = [
1993
- "arn:aws:rds-db:\${data.aws_region.current.region}:\${data.aws_caller_identity.current.account_id}:dbuser:\${var.enable_rds_proxy ? module.aurora.proxy_resource_id : module.aurora.cluster_resource_id}/\${local.database_runtime_user}"
1865
+ Resource = [module.aurora.secret_arn]
1866
+ },
1867
+ {
1868
+ Effect = "Allow"
1869
+ Action = [
1870
+ "kms:Decrypt"
1994
1871
  ]
1872
+ Resource = [module.aurora.kms_key_arn]
1995
1873
  }
1996
1874
  ]
1997
1875
  })
@@ -2080,7 +1958,7 @@ resource "aws_security_group" "migration_handler" {
2080
1958
 
2081
1959
  resource "aws_vpc_security_group_egress_rule" "migration_handler_to_database" {
2082
1960
  security_group_id = aws_security_group.migration_handler.id
2083
- referenced_security_group_id = module.aurora.security_group_id
1961
+ referenced_security_group_id = module.aurora.database_security_group_id
2084
1962
  from_port = module.aurora.cluster_port
2085
1963
  to_port = module.aurora.cluster_port
2086
1964
  ip_protocol = "tcp"
@@ -2122,7 +2000,7 @@ resource "aws_vpc_security_group_egress_rule" "create_db_user_https" {
2122
2000
  }
2123
2001
 
2124
2002
  resource "aws_vpc_security_group_ingress_rule" "migration_handler_to_database" {
2125
- security_group_id = module.aurora.security_group_id
2003
+ security_group_id = module.aurora.database_security_group_id
2126
2004
  referenced_security_group_id = aws_security_group.migration_handler.id
2127
2005
  from_port = module.aurora.cluster_port
2128
2006
  to_port = module.aurora.cluster_port
@@ -2196,10 +2074,10 @@ resource "null_resource" "create_db_user_trigger" {
2196
2074
  command = <<-EOT
2197
2075
  output_file=$(mktemp)
2198
2076
  response=$(aws lambda invoke \\
2199
- --region \${data.aws_region.current.region} \\
2200
- --function-name \${self.triggers.function_name} \\
2077
+ --region "$AWS_REGION" \\
2078
+ --function-name "$FUNCTION_NAME" \\
2201
2079
  --cli-binary-format raw-in-base64-out \\
2202
- --payload '{"RequestType":"Create","PhysicalResourceId":"db-user:\${self.triggers.db_user}"}' \\
2080
+ --payload "{\\"RequestType\\":\\"Create\\",\\"PhysicalResourceId\\":\\"db-user:$DB_USER\\"}" \\
2203
2081
  "$output_file")
2204
2082
  cat "$output_file"
2205
2083
  echo "$response"
@@ -2209,6 +2087,11 @@ resource "null_resource" "create_db_user_trigger" {
2209
2087
  fi
2210
2088
  rm -f "$output_file"
2211
2089
  EOT
2090
+ environment = {
2091
+ AWS_REGION = data.aws_region.current.region
2092
+ FUNCTION_NAME = self.triggers.function_name
2093
+ DB_USER = self.triggers.db_user
2094
+ }
2212
2095
  }
2213
2096
 
2214
2097
  depends_on = [aws_lambda_function.create_db_user, module.aurora]
@@ -2222,7 +2105,7 @@ resource "aws_lambda_function" "migration_handler" {
2222
2105
  package_type = "Image"
2223
2106
  function_name = local.migration_function_name
2224
2107
  role = aws_iam_role.migration_handler.arn
2225
- image_uri = "\${aws_ecr_repository.migration_handler.repository_url}:latest"
2108
+ image_uri = "\${aws_ecr_repository.migration_handler.repository_url}:\${local.image_tag}"
2226
2109
  memory_size = 1024
2227
2110
  timeout = 300
2228
2111
  architectures = ["arm64"]
@@ -2238,10 +2121,7 @@ resource "aws_lambda_function" "migration_handler" {
2238
2121
 
2239
2122
  environment {
2240
2123
  variables = {
2241
- HOSTNAME = module.aurora.cluster_endpoint
2242
- DATABASE = module.aurora.database_name
2243
- PORT = tostring(module.aurora.cluster_port)
2244
- DBUSER = local.database_runtime_user
2124
+ DATABASE_SECRET_ARN = module.aurora.secret_arn
2245
2125
  }
2246
2126
  }
2247
2127
 
@@ -2271,8 +2151,8 @@ resource "null_resource" "migration_trigger" {
2271
2151
  command = <<-EOT
2272
2152
  output_file=$(mktemp)
2273
2153
  response=$(aws lambda invoke \\
2274
- --region \${data.aws_region.current.region} \\
2275
- --function-name \${self.triggers.function_name} \\
2154
+ --region "$AWS_REGION" \\
2155
+ --function-name "$FUNCTION_NAME" \\
2276
2156
  --cli-binary-format raw-in-base64-out \\
2277
2157
  "$output_file")
2278
2158
  cat "$output_file"
@@ -2283,6 +2163,10 @@ resource "null_resource" "migration_trigger" {
2283
2163
  fi
2284
2164
  rm -f "$output_file"
2285
2165
  EOT
2166
+ environment = {
2167
+ AWS_REGION = data.aws_region.current.region
2168
+ FUNCTION_NAME = self.triggers.function_name
2169
+ }
2286
2170
  }
2287
2171
 
2288
2172
  depends_on = [
@@ -2313,6 +2197,11 @@ output "proxy_resource_id" {
2313
2197
  value = module.aurora.proxy_resource_id
2314
2198
  }
2315
2199
 
2200
+ output "connect_resource_id" {
2201
+ description = "Resource ID to use in IAM rds-db:connect policies for the application database user. Resolves to the RDS Proxy resource ID when the proxy is enabled (the default), or the Aurora cluster resource ID when it is disabled — connecting through the proxy and connecting directly to the cluster are different IAM permission boundaries."
2202
+ value = module.aurora.connect_resource_id
2203
+ }
2204
+
2316
2205
  output "kms_key_arn" {
2317
2206
  description = "ARN of the KMS key protecting Aurora and the admin credentials secret, used to grant decrypt access alongside secret_arn."
2318
2207
  value = module.aurora.kms_key_arn
@@ -2347,7 +2236,6 @@ output "database_runtime_user" {
2347
2236
  description = "Application database user created for IAM-authenticated access."
2348
2237
  value = local.database_runtime_user
2349
2238
  }
2350
-
2351
2239
  "
2352
2240
  `;
2353
2241
 
@@ -2361,15 +2249,15 @@ terraform {
2361
2249
  required_providers {
2362
2250
  aws = {
2363
2251
  source = "hashicorp/aws"
2364
- version = "~> 6.33"
2252
+ version = "6.54.0"
2365
2253
  }
2366
2254
  null = {
2367
2255
  source = "hashicorp/null"
2368
- version = ">= 3.0"
2256
+ version = "3.3.0"
2369
2257
  }
2370
2258
  random = {
2371
2259
  source = "hashicorp/random"
2372
- version = ">= 3.0"
2260
+ version = "3.9.0"
2373
2261
  }
2374
2262
  }
2375
2263
  }
@@ -2513,10 +2401,19 @@ variable "tags" {
2513
2401
  default = {}
2514
2402
  }
2515
2403
 
2404
+ # Suffix appended to physical resource names so that multiple deployments
2405
+ # (e.g. separate environments in the same account and region) don't collide.
2406
+ resource "random_string" "suffix" {
2407
+ length = 8
2408
+ special = false
2409
+ upper = false
2410
+ }
2411
+
2516
2412
  locals {
2517
2413
  default_port = var.engine == "aurora-mysql" ? 3306 : 5432
2518
2414
  default_engine_version = var.engine == "aurora-mysql" ? "8.0.mysql_aurora.3.12.0" : "17.7"
2519
2415
  parameter_group_family = var.engine == "aurora-mysql" ? "aurora-mysql8.0" : "aurora-postgresql\${split(".", coalesce(var.engine_version, local.default_engine_version))[0]}"
2416
+ cluster_name = "\${var.name}-aurora-\${random_string.suffix.result}"
2520
2417
  }
2521
2418
 
2522
2419
  resource "aws_rds_cluster_parameter_group" "database" {
@@ -2614,7 +2511,7 @@ resource "aws_security_group" "database" {
2614
2511
  }
2615
2512
 
2616
2513
  resource "aws_db_subnet_group" "database" {
2617
- name = "\${var.name}-aurora"
2514
+ name = local.cluster_name
2618
2515
  subnet_ids = var.subnet_ids
2619
2516
 
2620
2517
  tags = merge(var.tags, {
@@ -2654,7 +2551,7 @@ resource "aws_secretsmanager_secret_version" "credentials" {
2654
2551
  resource "aws_rds_cluster" "database" {
2655
2552
  #checkov:skip=CKV2_AWS_27:Query logging can be enabled with enable_cloudwatch_logs; this module defaults to CDK-equivalent behavior unless logging is requested
2656
2553
  #checkov:skip=CKV_AWS_139:Deletion protection is enabled but checkov is unable to detect it correctly
2657
- cluster_identifier = "\${var.name}-aurora"
2554
+ cluster_identifier = local.cluster_name
2658
2555
  engine = var.engine
2659
2556
  engine_version = coalesce(var.engine_version, local.default_engine_version)
2660
2557
  database_name = var.database_name
@@ -2668,7 +2565,7 @@ resource "aws_rds_cluster" "database" {
2668
2565
  kms_key_id = aws_kms_key.database.arn
2669
2566
  deletion_protection = var.deletion_protection
2670
2567
  skip_final_snapshot = var.skip_final_snapshot
2671
- final_snapshot_identifier = var.skip_final_snapshot ? null : "\${var.name}-aurora-final-snapshot"
2568
+ final_snapshot_identifier = var.skip_final_snapshot ? null : "\${local.cluster_name}-final-snapshot"
2672
2569
  iam_database_authentication_enabled = true
2673
2570
  monitoring_interval = 5
2674
2571
  monitoring_role_arn = aws_iam_role.enhanced_monitoring.arn
@@ -2688,7 +2585,7 @@ resource "aws_rds_cluster" "database" {
2688
2585
  resource "aws_rds_cluster_instance" "database" {
2689
2586
  count = var.instance_count
2690
2587
 
2691
- identifier = "\${var.name}-aurora-\${count.index + 1}"
2588
+ identifier = "\${local.cluster_name}-\${count.index + 1}"
2692
2589
  cluster_identifier = aws_rds_cluster.database.id
2693
2590
  instance_class = "db.serverless"
2694
2591
  engine = aws_rds_cluster.database.engine
@@ -2742,7 +2639,7 @@ resource "aws_vpc_security_group_ingress_rule" "rotation_to_database" {
2742
2639
  resource "aws_cloudformation_stack" "credentials_rotation" {
2743
2640
  #checkov:skip=CKV_AWS_124:SNS event notifications are not required for the credentials rotation stack
2744
2641
  count = var.enable_credential_rotation ? 1 : 0
2745
- name = "\${var.name}-aurora-credentials-rotation"
2642
+ name = "\${local.cluster_name}-credentials-rotation"
2746
2643
 
2747
2644
  capabilities = ["CAPABILITY_IAM", "CAPABILITY_AUTO_EXPAND"]
2748
2645
 
@@ -2756,7 +2653,7 @@ resource "aws_cloudformation_stack" "credentials_rotation" {
2756
2653
  SecretId = aws_secretsmanager_secret.credentials.arn
2757
2654
  HostedRotationLambda = {
2758
2655
  RotationType = var.engine == "aurora-mysql" ? "MySQLSingleUser" : "PostgreSQLSingleUser"
2759
- RotationLambdaName = "\${var.name}-aurora-credentials-rotation"
2656
+ RotationLambdaName = "\${local.cluster_name}-credentials-rotation"
2760
2657
  VpcSecurityGroupIds = aws_security_group.rotation[0].id
2761
2658
  VpcSubnetIds = join(",", var.lambda_subnet_ids)
2762
2659
  }
@@ -2799,27 +2696,6 @@ resource "aws_iam_role" "proxy" {
2799
2696
  })
2800
2697
  }
2801
2698
 
2802
- resource "aws_iam_role_policy" "proxy_secret_access" {
2803
- count = var.enable_rds_proxy ? 1 : 0
2804
- role = aws_iam_role.proxy[0].name
2805
-
2806
- policy = jsonencode({
2807
- Version = "2012-10-17"
2808
- Statement = [
2809
- {
2810
- Effect = "Allow"
2811
- Action = ["secretsmanager:GetSecretValue"]
2812
- Resource = [aws_secretsmanager_secret.credentials.arn]
2813
- },
2814
- {
2815
- Effect = "Allow"
2816
- Action = ["kms:Decrypt"]
2817
- Resource = [aws_kms_key.database.arn]
2818
- }
2819
- ]
2820
- })
2821
- }
2822
-
2823
2699
  resource "aws_security_group" "proxy" {
2824
2700
  #checkov:skip=CKV2_AWS_5:Security group is attached to aws_db_proxy.aurora; Checkov cannot resolve count-conditional cross-resource references
2825
2701
  count = var.enable_rds_proxy ? 1 : 0
@@ -2836,24 +2712,13 @@ resource "aws_security_group" "proxy" {
2836
2712
  resource "aws_db_proxy" "aurora" {
2837
2713
  count = var.enable_rds_proxy ? 1 : 0
2838
2714
 
2839
- name = "\${var.name}-proxy"
2715
+ name = "\${var.name}-proxy-\${random_string.suffix.result}"
2840
2716
  default_auth_scheme = "IAM_AUTH"
2841
2717
  engine_family = var.engine == "aurora-mysql" ? "MYSQL" : "POSTGRESQL"
2842
2718
  role_arn = aws_iam_role.proxy[0].arn
2843
2719
  vpc_subnet_ids = var.subnet_ids
2844
2720
  vpc_security_group_ids = [aws_security_group.proxy[0].id]
2845
2721
  require_tls = true
2846
-
2847
- auth {
2848
- auth_scheme = "SECRETS"
2849
- iam_auth = "REQUIRED"
2850
- secret_arn = aws_secretsmanager_secret.credentials.arn
2851
- }
2852
-
2853
- depends_on = [
2854
- aws_iam_role_policy.proxy_secret_access,
2855
- aws_secretsmanager_secret_version.credentials,
2856
- ]
2857
2722
  }
2858
2723
 
2859
2724
  resource "aws_db_proxy_default_target_group" "default" {
@@ -2885,9 +2750,9 @@ resource "null_resource" "proxy_target_ready" {
2885
2750
  deadline=$((start_time + 600))
2886
2751
  while true; do
2887
2752
  target_state=$(aws rds describe-db-proxy-targets \\
2888
- --region \${data.aws_region.current.region} \\
2889
- --db-proxy-name \${self.triggers.db_proxy_name} \\
2890
- --target-group-name \${self.triggers.target_group_name} \\
2753
+ --region "$AWS_REGION" \\
2754
+ --db-proxy-name "$DB_PROXY_NAME" \\
2755
+ --target-group-name "$TARGET_GROUP_NAME" \\
2891
2756
  --query "Targets[?Type=='RDS_INSTANCE'] | [0].TargetHealth.State" \\
2892
2757
  --output text)
2893
2758
 
@@ -2897,13 +2762,19 @@ resource "null_resource" "proxy_target_ready" {
2897
2762
 
2898
2763
  current_time=$(date +%s)
2899
2764
  if [ "$current_time" -ge "$deadline" ]; then
2900
- echo "RDS Proxy target \${self.triggers.db_cluster_identifier} did not become AVAILABLE within 10 minutes. Last state: $target_state"
2765
+ echo "RDS Proxy target $DB_CLUSTER_IDENTIFIER did not become AVAILABLE within 10 minutes. Last state: $target_state"
2901
2766
  exit 1
2902
2767
  fi
2903
2768
 
2904
2769
  sleep 10
2905
2770
  done
2906
2771
  EOT
2772
+ environment = {
2773
+ AWS_REGION = data.aws_region.current.region
2774
+ DB_PROXY_NAME = self.triggers.db_proxy_name
2775
+ TARGET_GROUP_NAME = self.triggers.target_group_name
2776
+ DB_CLUSTER_IDENTIFIER = self.triggers.db_cluster_identifier
2777
+ }
2907
2778
  }
2908
2779
 
2909
2780
  depends_on = [
@@ -2982,7 +2853,7 @@ resource "aws_iam_role_policy_attachment" "backup" {
2982
2853
  resource "aws_backup_vault" "database" {
2983
2854
  count = var.enable_backup ? 1 : 0
2984
2855
 
2985
- name = "\${var.name}-aurora-backup"
2856
+ name = "\${local.cluster_name}-backup"
2986
2857
  kms_key_arn = aws_kms_key.database.arn
2987
2858
  tags = var.tags
2988
2859
  }
@@ -2990,7 +2861,7 @@ resource "aws_backup_vault" "database" {
2990
2861
  resource "aws_backup_plan" "database" {
2991
2862
  count = var.enable_backup ? 1 : 0
2992
2863
 
2993
- name = "\${var.name}-aurora-backup"
2864
+ name = "\${local.cluster_name}-backup"
2994
2865
 
2995
2866
  rule {
2996
2867
  rule_name = "daily-backup"
@@ -3030,6 +2901,11 @@ output "proxy_resource_id" {
3030
2901
  value = var.enable_rds_proxy ? split(":", aws_db_proxy.aurora[0].arn)[6] : null
3031
2902
  }
3032
2903
 
2904
+ output "connect_resource_id" {
2905
+ description = "Resource ID to use in IAM rds-db:connect policies for the application database user. Resolves to the RDS Proxy resource ID when the proxy is enabled (the default), or the Aurora cluster resource ID when it is disabled — connecting through the proxy and connecting directly to the cluster are different IAM permission boundaries."
2906
+ value = var.enable_rds_proxy ? split(":", aws_db_proxy.aurora[0].arn)[6] : aws_rds_cluster.database.cluster_resource_id
2907
+ }
2908
+
3033
2909
  output "cluster_endpoint" {
3034
2910
  description = "Writer endpoint of the Aurora cluster or proxy."
3035
2911
  value = var.enable_rds_proxy ? aws_db_proxy.aurora[0].endpoint : aws_rds_cluster.database.endpoint
@@ -3104,19 +2980,19 @@ exports[`ts#rdb generator > should generate terraform modules with MySQL engine
3104
2980
  required_providers {
3105
2981
  archive = {
3106
2982
  source = "hashicorp/archive"
3107
- version = "~> 2.5"
2983
+ version = "2.8.0"
3108
2984
  }
3109
2985
  aws = {
3110
2986
  source = "hashicorp/aws"
3111
- version = "~> 6.33"
2987
+ version = "6.54.0"
3112
2988
  }
3113
2989
  null = {
3114
2990
  source = "hashicorp/null"
3115
- version = ">= 3.0"
2991
+ version = "3.3.0"
3116
2992
  }
3117
2993
  random = {
3118
2994
  source = "hashicorp/random"
3119
- version = ">= 3.0"
2995
+ version = "3.9.0"
3120
2996
  }
3121
2997
  }
3122
2998
  }
@@ -3220,12 +3096,13 @@ variable "tags" {
3220
3096
  default = {}
3221
3097
  }
3222
3098
 
3223
- variable "docker_image_tag" {
3099
+ variable "migration_docker_image_tag" {
3224
3100
  description = "Docker image tag for the migration handler. Defaults to the tag built by the Nx docker target."
3225
3101
  type = string
3226
3102
  default = "proj-db-migration:latest"
3227
3103
  }
3228
3104
 
3105
+
3229
3106
  variable "asset_bucket_name" {
3230
3107
  description = "Name of the shared asset S3 bucket used to stage the Lambda deployment zip. Instantiate the \`core/asset-bucket\` module once per deployment and pass its \`bucket_name\` output here."
3231
3108
  type = string
@@ -3241,10 +3118,12 @@ resource "random_string" "suffix" {
3241
3118
  }
3242
3119
 
3243
3120
  locals {
3244
- create_db_user_bundle_path = "\${path.module}/../../../../../../../dist/packages/db/bundle/create-db-user"
3245
- migration_function_name = "db-migration-\${random_string.suffix.result}"
3121
+ config = jsondecode(file("\${path.module}/../../../../../../../packages/db/config.json"))
3122
+ runtime_config_key = local.config.runtimeConfigKey
3123
+ create_db_user_bundle_path = "\${path.module}/../../../../../../../dist/packages/db/bundle/create-db-user"
3124
+ migration_function_name = "db-migration-\${random_string.suffix.result}"
3246
3125
  create_db_user_function_name = "db-create-db-user-\${random_string.suffix.result}"
3247
- database_runtime_user = "db_\${random_string.suffix.result}"
3126
+ database_runtime_user = "db_\${random_string.suffix.result}"
3248
3127
  }
3249
3128
 
3250
3129
  module "aurora" {
@@ -3283,10 +3162,17 @@ resource "aws_iam_role_policy" "proxy_db_user_connect" {
3283
3162
  Statement = [
3284
3163
  {
3285
3164
  Effect = "Allow"
3286
- Action = ["rds-db:connect"]
3287
- Resource = [
3288
- "arn:aws:rds-db:\${data.aws_region.current.region}:\${data.aws_caller_identity.current.account_id}:dbuser:\${module.aurora.cluster_resource_id}/\${local.database_runtime_user}"
3165
+ Action = [
3166
+ "secretsmanager:GetSecretValue"
3289
3167
  ]
3168
+ Resource = [module.aurora.secret_arn]
3169
+ },
3170
+ {
3171
+ Effect = "Allow"
3172
+ Action = [
3173
+ "kms:Decrypt"
3174
+ ]
3175
+ Resource = [module.aurora.kms_key_arn]
3290
3176
  }
3291
3177
  ]
3292
3178
  })
@@ -3310,7 +3196,7 @@ module "add_rdb_to_runtime_config" {
3310
3196
  source = "../../../core/runtime-config/entry"
3311
3197
 
3312
3198
  namespace = "database"
3313
- key = "Db"
3199
+ key = local.runtime_config_key
3314
3200
  value = {
3315
3201
  hostname = module.aurora.cluster_endpoint
3316
3202
  port = module.aurora.cluster_port
@@ -3323,9 +3209,8 @@ module "add_rdb_to_runtime_config" {
3323
3209
 
3324
3210
  resource "aws_ecr_repository" "migration_handler" {
3325
3211
  #checkov:skip=CKV_AWS_136:AES256 encryption is sufficient for ECR repositories
3326
- #checkov:skip=CKV_AWS_51:Mutable tags are intentional; the migration handler is always pushed as latest and redeployment is gated on docker_digest changes in null_resource.docker_publish
3327
3212
  name = "db-migration-\${random_string.suffix.result}"
3328
- image_tag_mutability = "MUTABLE"
3213
+ image_tag_mutability = "IMMUTABLE"
3329
3214
  force_delete = true
3330
3215
 
3331
3216
  image_scanning_configuration {
@@ -3373,22 +3258,34 @@ resource "aws_ecr_repository_policy" "migration_handler" {
3373
3258
  }
3374
3259
 
3375
3260
  data "external" "docker_digest" {
3376
- program = ["sh", "-c", "echo '{\\"digest\\":\\"'$(docker inspect \${var.docker_image_tag} --format '{{.Id}}')'\\"}' "]
3261
+ program = ["sh", "-c", "echo '{\\"digest\\":\\"'$(docker inspect \${var.migration_docker_image_tag} --format '{{.Id}}')'\\"}' "]
3262
+ }
3263
+
3264
+ locals {
3265
+ # Content-based, immutable image tag derived from the local image digest
3266
+ image_tag = replace(data.external.docker_digest.result.digest, "sha256:", "")
3377
3267
  }
3378
3268
 
3379
3269
  resource "null_resource" "docker_publish" {
3380
3270
  triggers = {
3381
3271
  docker_digest = data.external.docker_digest.result.digest
3382
3272
  repository_url = aws_ecr_repository.migration_handler.repository_url
3383
- docker_image_tag = var.docker_image_tag
3273
+ migration_docker_image_tag = var.migration_docker_image_tag
3274
+ image_tag = local.image_tag
3384
3275
  }
3385
3276
 
3386
3277
  provisioner "local-exec" {
3387
3278
  command = <<-EOT
3388
- aws ecr get-login-password --region \${data.aws_region.current.region} | docker login --username AWS --password-stdin \${self.triggers.repository_url}
3389
- docker tag \${self.triggers.docker_image_tag} \${self.triggers.repository_url}:latest
3390
- docker push \${self.triggers.repository_url}:latest
3279
+ aws ecr get-login-password --region "$AWS_REGION" | docker login --username AWS --password-stdin "$REPOSITORY_URL"
3280
+ docker tag "$MIGRATION_DOCKER_IMAGE_TAG" "$REPOSITORY_URL:$IMAGE_TAG"
3281
+ docker push "$REPOSITORY_URL:$IMAGE_TAG"
3391
3282
  EOT
3283
+ environment = {
3284
+ AWS_REGION = data.aws_region.current.region
3285
+ REPOSITORY_URL = self.triggers.repository_url
3286
+ MIGRATION_DOCKER_IMAGE_TAG = self.triggers.migration_docker_image_tag
3287
+ IMAGE_TAG = self.triggers.image_tag
3288
+ }
3392
3289
  }
3393
3290
 
3394
3291
  depends_on = [aws_ecr_repository_policy.migration_handler]
@@ -3651,10 +3548,10 @@ resource "null_resource" "create_db_user_trigger" {
3651
3548
  command = <<-EOT
3652
3549
  output_file=$(mktemp)
3653
3550
  response=$(aws lambda invoke \\
3654
- --region \${data.aws_region.current.region} \\
3655
- --function-name \${self.triggers.function_name} \\
3551
+ --region "$AWS_REGION" \\
3552
+ --function-name "$FUNCTION_NAME" \\
3656
3553
  --cli-binary-format raw-in-base64-out \\
3657
- --payload '{"RequestType":"Create","PhysicalResourceId":"db-user:\${self.triggers.db_user}"}' \\
3554
+ --payload "{\\"RequestType\\":\\"Create\\",\\"PhysicalResourceId\\":\\"db-user:$DB_USER\\"}" \\
3658
3555
  "$output_file")
3659
3556
  cat "$output_file"
3660
3557
  echo "$response"
@@ -3664,6 +3561,11 @@ resource "null_resource" "create_db_user_trigger" {
3664
3561
  fi
3665
3562
  rm -f "$output_file"
3666
3563
  EOT
3564
+ environment = {
3565
+ AWS_REGION = data.aws_region.current.region
3566
+ FUNCTION_NAME = self.triggers.function_name
3567
+ DB_USER = self.triggers.db_user
3568
+ }
3667
3569
  }
3668
3570
 
3669
3571
  depends_on = [aws_lambda_function.create_db_user, module.aurora]
@@ -3677,7 +3579,7 @@ resource "aws_lambda_function" "migration_handler" {
3677
3579
  package_type = "Image"
3678
3580
  function_name = local.migration_function_name
3679
3581
  role = aws_iam_role.migration_handler.arn
3680
- image_uri = "\${aws_ecr_repository.migration_handler.repository_url}:latest"
3582
+ image_uri = "\${aws_ecr_repository.migration_handler.repository_url}:\${local.image_tag}"
3681
3583
  memory_size = 1024
3682
3584
  timeout = 300
3683
3585
  architectures = ["arm64"]
@@ -3722,8 +3624,8 @@ resource "null_resource" "migration_trigger" {
3722
3624
  command = <<-EOT
3723
3625
  output_file=$(mktemp)
3724
3626
  response=$(aws lambda invoke \\
3725
- --region \${data.aws_region.current.region} \\
3726
- --function-name \${self.triggers.function_name} \\
3627
+ --region "$AWS_REGION" \\
3628
+ --function-name "$FUNCTION_NAME" \\
3727
3629
  --cli-binary-format raw-in-base64-out \\
3728
3630
  "$output_file")
3729
3631
  cat "$output_file"
@@ -3734,6 +3636,10 @@ resource "null_resource" "migration_trigger" {
3734
3636
  fi
3735
3637
  rm -f "$output_file"
3736
3638
  EOT
3639
+ environment = {
3640
+ AWS_REGION = data.aws_region.current.region
3641
+ FUNCTION_NAME = self.triggers.function_name
3642
+ }
3737
3643
  }
3738
3644
 
3739
3645
  depends_on = [
@@ -3764,6 +3670,11 @@ output "proxy_resource_id" {
3764
3670
  value = module.aurora.proxy_resource_id
3765
3671
  }
3766
3672
 
3673
+ output "connect_resource_id" {
3674
+ description = "Resource ID to use in IAM rds-db:connect policies for the application database user. Resolves to the RDS Proxy resource ID when the proxy is enabled (the default), or the Aurora cluster resource ID when it is disabled — connecting through the proxy and connecting directly to the cluster are different IAM permission boundaries."
3675
+ value = module.aurora.connect_resource_id
3676
+ }
3677
+
3767
3678
  output "kms_key_arn" {
3768
3679
  description = "ARN of the KMS key protecting Aurora and the admin credentials secret, used to grant decrypt access alongside secret_arn."
3769
3680
  value = module.aurora.kms_key_arn
@@ -3798,7 +3709,6 @@ output "database_runtime_user" {
3798
3709
  description = "Application database user created for IAM-authenticated access."
3799
3710
  value = local.database_runtime_user
3800
3711
  }
3801
-
3802
3712
  "
3803
3713
  `;
3804
3714
 
@@ -3824,148 +3734,6 @@ datasource db {
3824
3734
  "
3825
3735
  `;
3826
3736
 
3827
- exports[`ts#rdb generator > should generate the aurora shared construct > packages/db/scripts/docker-pull.ts 1`] = `
3828
- "import { spawnSync } from 'child_process';
3829
-
3830
- const ENGINE = 'docker';
3831
- const image = process.argv[2];
3832
-
3833
- const inspect = spawnSync(ENGINE, ['image', 'inspect', image], {
3834
- stdio: 'ignore',
3835
- });
3836
-
3837
- if (inspect.status !== 0) {
3838
- const pull = spawnSync(ENGINE, ['pull', image], { stdio: 'inherit' });
3839
- if (pull.status !== 0) {
3840
- process.exit(pull.status ?? 1);
3841
- }
3842
- }
3843
- "
3844
- `;
3845
-
3846
- exports[`ts#rdb generator > should generate the aurora shared construct > packages/db/scripts/docker-start.ts 1`] = `
3847
- "import { spawn, spawnSync } from 'child_process';
3848
-
3849
- const ENGINE = 'docker';
3850
-
3851
- const [containerName, image, hostPort, dbName, dbUser, dbPassword] =
3852
- process.argv.slice(2);
3853
-
3854
- const containerExists = (): boolean =>
3855
- spawnSync(ENGINE, ['container', 'inspect', containerName], {
3856
- stdio: 'ignore',
3857
- }).status === 0;
3858
-
3859
- const isRunning = (): boolean => {
3860
- const result = spawnSync(
3861
- ENGINE,
3862
- ['container', 'inspect', '-f', '{{.State.Running}}', containerName],
3863
- { encoding: 'utf-8' },
3864
- );
3865
- return result.status === 0 && result.stdout.trim() === 'true';
3866
- };
3867
-
3868
- if (containerExists()) {
3869
- if (!isRunning()) {
3870
- const start = spawnSync(ENGINE, ['start', containerName], {
3871
- stdio: 'inherit',
3872
- });
3873
- if (start.status !== 0) process.exit(start.status ?? 1);
3874
- }
3875
- } else {
3876
- const runArgs = [
3877
- 'run',
3878
- '--name',
3879
- containerName,
3880
- '-e',
3881
- \`POSTGRES_DB=\${dbName}\`,
3882
- '-e',
3883
- \`POSTGRES_USER=\${dbUser}\`,
3884
- '-e',
3885
- \`POSTGRES_PASSWORD=\${dbPassword}\`,
3886
- '-e',
3887
- \`PGDATA=/var/lib/postgresql/17/docker\`,
3888
- '-p',
3889
- \`\${hostPort}:5432\`,
3890
- '-v',
3891
- \`\${containerName}-data:/var/lib/postgresql\`,
3892
- '-d',
3893
- image,
3894
- ];
3895
- const create = spawnSync(ENGINE, runArgs, { stdio: 'inherit' });
3896
- if (create.status !== 0) process.exit(create.status ?? 1);
3897
- }
3898
-
3899
- const logs = spawn(ENGINE, ['logs', '-f', containerName], {
3900
- stdio: ['ignore', 'inherit', 'inherit'],
3901
- });
3902
-
3903
- let exiting = false;
3904
-
3905
- const cleanup = () => {
3906
- if (exiting) return;
3907
- exiting = true;
3908
- spawnSync(ENGINE, ['stop', containerName], { stdio: 'ignore' });
3909
- logs.kill();
3910
- process.exit(0);
3911
- };
3912
-
3913
- process.on('SIGTERM', cleanup);
3914
- process.on('SIGINT', cleanup);
3915
- process.on('SIGHUP', cleanup);
3916
-
3917
- logs.on('exit', (code) => {
3918
- if (!exiting) process.exit(code ?? 0);
3919
- });
3920
- "
3921
- `;
3922
-
3923
- exports[`ts#rdb generator > should generate the aurora shared construct > packages/db/scripts/wait-for-db.ts 1`] = `
3924
- "import { Client } from 'pg';
3925
-
3926
- const noop = () => undefined;
3927
-
3928
- const [portArg, dbArg, userArg, passwordArg] = process.argv.slice(2);
3929
- const timeoutAt = Date.now() + 60000;
3930
-
3931
- while (Date.now() < timeoutAt) {
3932
- const client = new Client({
3933
- host: 'localhost',
3934
- port: parseInt(portArg),
3935
- user: userArg,
3936
- password: passwordArg,
3937
- database: dbArg,
3938
- connectionTimeoutMillis: 500,
3939
- });
3940
- client.on('error', noop);
3941
- try {
3942
- await client.connect();
3943
- await client.end();
3944
- console.log('Database is ready.');
3945
- process.exit(0);
3946
- } catch {
3947
- console.log('Database is not ready.');
3948
- await client.end().catch(noop);
3949
- }
3950
- await new Promise((r) => setTimeout(r, 200));
3951
- }
3952
-
3953
- throw new Error(\`Timed out waiting for postgres on port \${portArg}\`);
3954
- "
3955
- `;
3956
-
3957
- exports[`ts#rdb generator > should generate the aurora shared construct > packages/db/src/constants.ts 1`] = `
3958
- "export const DB_PACKAGE_NAME = 'Db';
3959
-
3960
- // Local development connection details (used when SERVE_LOCAL=true, see serve-local Nx target)
3961
- export const LOCAL_DB_PORT = 5432;
3962
- export const LOCAL_DB_HOST = 'localhost';
3963
- export const LOCAL_DB_NAME = 'database_name';
3964
- export const LOCAL_DB_USER = 'dbadmin';
3965
- export const LOCAL_DB_PASSWORD = 'password';
3966
- "
3967
- `;
3968
-
3969
3737
  exports[`ts#rdb generator > should generate the aurora shared construct > packages/db/src/create-db-user-handler.ts 1`] = `
3970
3738
  "import type { CloudFormationCustomResourceEvent } from 'aws-lambda';
3971
3739
  import { randomBytes } from 'node:crypto';
@@ -4015,14 +3783,12 @@ const ensureDatabaseUser = async (dbUser: string): Promise<void> => {
4015
3783
 
4016
3784
  await client.query(
4017
3785
  \`ALTER ROLE \${quotedDbUser} WITH LOGIN;
4018
- GRANT ALL PRIVILEGES ON DATABASE \${quotedDbName} TO \${quotedDbUser};
4019
- GRANT USAGE, CREATE ON SCHEMA public TO \${quotedDbUser};
4020
- GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO \${quotedDbUser};
4021
- GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO \${quotedDbUser};
4022
- GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO \${quotedDbUser};
4023
- ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO \${quotedDbUser};
4024
- ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO \${quotedDbUser};
4025
- ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON FUNCTIONS TO \${quotedDbUser};
3786
+ GRANT CONNECT ON DATABASE \${quotedDbName} TO \${quotedDbUser};
3787
+ GRANT USAGE ON SCHEMA public TO \${quotedDbUser};
3788
+ GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO \${quotedDbUser};
3789
+ GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO \${quotedDbUser};
3790
+ ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO \${quotedDbUser};
3791
+ ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT ON SEQUENCES TO \${quotedDbUser};
4026
3792
  GRANT rds_iam TO \${quotedDbUser};\`,
4027
3793
  );
4028
3794
 
@@ -4057,36 +3823,23 @@ export const handler = async (
4057
3823
  `;
4058
3824
 
4059
3825
  exports[`ts#rdb generator > should generate the aurora shared construct > packages/db/src/index.ts 1`] = `
4060
- "export { DB_PACKAGE_NAME } from './constants.js';
4061
- export { getPrisma } from './prisma.js';
3826
+ "export { getPrisma } from './prisma.js';
4062
3827
  "
4063
3828
  `;
4064
3829
 
4065
3830
  exports[`ts#rdb generator > should generate the aurora shared construct > packages/db/src/migration-handler.ts 1`] = `
4066
3831
  "import { execFile } from 'node:child_process';
4067
3832
  import { promisify } from 'node:util';
4068
- import { Signer } from '@aws-sdk/rds-signer';
4069
- import { withConnectionRetry } from './utils.js';
3833
+ import { getDatabaseSecret, withConnectionRetry } from './utils.js';
4070
3834
 
4071
3835
  const buildDatabaseUrl = async (): Promise<string> => {
4072
- const hostname = process.env.HOSTNAME!;
4073
- const port = process.env.PORT!;
4074
- const database = process.env.DATABASE!;
4075
- const dbUser = process.env.DBUSER!;
4076
- const region = process.env.AWS_REGION!;
4077
-
4078
- const iamAuthToken = await new Signer({
4079
- hostname,
4080
- port: Number(port),
4081
- region,
4082
- username: dbUser,
4083
- }).getAuthToken();
3836
+ const { host, port, dbname, username, password } = await getDatabaseSecret();
4084
3837
 
4085
3838
  return (
4086
- \`postgresql://\${encodeURIComponent(dbUser)}\` +
4087
- \`:\${encodeURIComponent(iamAuthToken)}\` +
4088
- \`@\${hostname}:\${port}/\${database}\` +
4089
- \`?sslaccept=strict\` // \`sslaccept\` is the correct parameter here for postgresql. The Prisma CLI Rust engine does not use the standard libpq \`sslmode\` option.
3839
+ \`postgresql://\${encodeURIComponent(username)}\` +
3840
+ \`:\${encodeURIComponent(password)}\` +
3841
+ \`@\${host}:\${port}/\${dbname}\` +
3842
+ \`?sslaccept=strict\`
4090
3843
  );
4091
3844
  };
4092
3845
 
@@ -4110,16 +3863,19 @@ exports[`ts#rdb generator > should generate the aurora shared construct > packag
4110
3863
  import { Signer } from '@aws-sdk/rds-signer';
4111
3864
  import { Prisma, PrismaClient } from '../generated/prisma/client.js';
4112
3865
  import { Pool } from 'pg';
4113
- import {
4114
- DB_PACKAGE_NAME,
4115
- LOCAL_DB_HOST,
4116
- LOCAL_DB_NAME,
4117
- LOCAL_DB_PASSWORD,
4118
- LOCAL_DB_PORT,
4119
- LOCAL_DB_USER,
4120
- } from './constants.js';
3866
+ import { readFileSync } from 'fs';
3867
+ import { join, dirname } from 'path';
3868
+ import { fileURLToPath } from 'url';
4121
3869
  import { getDatabaseConfig } from './utils.js';
4122
3870
 
3871
+ // Generated: must match runtimeConfigKey in config.json
3872
+ const runtimeConfigKey = 'Db';
3873
+
3874
+ const __dirname = dirname(fileURLToPath(import.meta.url));
3875
+ // config.json is only present in local dev (not included in the deployed bundle); guard with LOCAL_DEV check
3876
+ const localDev = () =>
3877
+ JSON.parse(readFileSync(join(__dirname, '../config.json'), 'utf-8')).localDev;
3878
+
4123
3879
  let prismaClient: PrismaClient<Prisma.LogLevel> | undefined;
4124
3880
 
4125
3881
  export const getPrisma = async <LogOpts extends Prisma.LogLevel>(
@@ -4127,14 +3883,15 @@ export const getPrisma = async <LogOpts extends Prisma.LogLevel>(
4127
3883
  ): Promise<PrismaClient<LogOpts>> => {
4128
3884
  if (prismaClient) return prismaClient;
4129
3885
 
4130
- if (process.env.SERVE_LOCAL === 'true') {
3886
+ if (process.env.LOCAL_DEV === 'true') {
3887
+ const { host, port, dbName, dbUser, dbPassword } = localDev();
4131
3888
  const adapter = new PrismaPg(
4132
3889
  new Pool({
4133
- host: LOCAL_DB_HOST,
4134
- port: LOCAL_DB_PORT,
4135
- database: LOCAL_DB_NAME,
4136
- user: LOCAL_DB_USER,
4137
- password: LOCAL_DB_PASSWORD,
3890
+ host,
3891
+ port,
3892
+ database: dbName,
3893
+ user: dbUser,
3894
+ password: dbPassword,
4138
3895
  allowExitOnIdle: true,
4139
3896
  }),
4140
3897
  );
@@ -4146,7 +3903,7 @@ export const getPrisma = async <LogOpts extends Prisma.LogLevel>(
4146
3903
  }
4147
3904
 
4148
3905
  const { hostname, port, database, dbUser, region } =
4149
- await getDatabaseConfig(DB_PACKAGE_NAME);
3906
+ await getDatabaseConfig(runtimeConfigKey);
4150
3907
  const adapter = new PrismaPg(
4151
3908
  new Pool({
4152
3909
  host: hostname,
@@ -4276,6 +4033,9 @@ const transientErrorPatterns = [
4276
4033
  'ECONNREFUSED',
4277
4034
  'ENOTFOUND',
4278
4035
  'P1000', // Prisma: authentication failed
4036
+ 'P1001', // Prisma: can't reach database server
4037
+ 'P1002', // Prisma: database server reached but timed out
4038
+ 'P1010', // Prisma: user denied access (IAM auth grant not yet propagated)
4279
4039
  'ER_ACCESS_DENIED_ERROR', // MySQL: access denied
4280
4040
  ];
4281
4041
 
@@ -4336,14 +4096,10 @@ import { CustomResource } from 'aws-cdk-lib';
4336
4096
  import { IConnectable, IVpc, Port, SubnetType } from 'aws-cdk-lib/aws-ec2';
4337
4097
  import { IGrantable, Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam';
4338
4098
  import { Key } from 'aws-cdk-lib/aws-kms';
4339
- import { Platform } from 'aws-cdk-lib/aws-ecr-assets';
4340
4099
  import {
4341
4100
  Architecture,
4342
- Code,
4343
- DockerImageCode,
4344
- DockerImageFunction,
4345
4101
  Function,
4346
- Runtime,
4102
+ FunctionOptions,
4347
4103
  Tracing,
4348
4104
  } from 'aws-cdk-lib/aws-lambda';
4349
4105
  import {
@@ -4459,16 +4215,6 @@ export interface AuroraDatabaseProps extends _AuroraDatabaseProps {
4459
4215
  */
4460
4216
  readonly runtimeConfigKey: string;
4461
4217
 
4462
- /**
4463
- * Migration bundle used to create a migration handler Lambda.
4464
- */
4465
- readonly migrationBundleDir: string;
4466
-
4467
- /**
4468
- * Bundle used to create or reconcile the application database user.
4469
- */
4470
- readonly createDbUserBundleDir: string;
4471
-
4472
4218
  /**
4473
4219
  * Writer instance for the Aurora cluster.
4474
4220
  */
@@ -4508,6 +4254,21 @@ export interface AuroraDatabaseProps extends _AuroraDatabaseProps {
4508
4254
  * @default true
4509
4255
  */
4510
4256
  readonly enableKeyRotation?: boolean;
4257
+
4258
+ /**
4259
+ * Whether to export Aurora engine logs to CloudWatch Logs.
4260
+ * See https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_LogAccess.html
4261
+ *
4262
+ * @default false
4263
+ */
4264
+ readonly enableCloudwatchLogs?: boolean;
4265
+
4266
+ /**
4267
+ * Whether to enable Performance Insights on the Aurora writer instance.
4268
+ *
4269
+ * @default true
4270
+ */
4271
+ readonly enablePerformanceInsights?: boolean;
4511
4272
  }
4512
4273
 
4513
4274
  /**
@@ -4528,8 +4289,6 @@ export abstract class AuroraDatabase extends Construct {
4528
4289
  adminUser,
4529
4290
  databaseName,
4530
4291
  runtimeConfigKey,
4531
- migrationBundleDir,
4532
- createDbUserBundleDir,
4533
4292
  vpcSubnets,
4534
4293
  writer,
4535
4294
  enableRdsProxy = true,
@@ -4537,6 +4296,8 @@ export abstract class AuroraDatabase extends Construct {
4537
4296
  deletionProtection = true,
4538
4297
  removalPolicy = RemovalPolicy.RETAIN,
4539
4298
  enableKeyRotation = true,
4299
+ enableCloudwatchLogs = false,
4300
+ enablePerformanceInsights = true,
4540
4301
  engine,
4541
4302
  engineVersion,
4542
4303
  ...clusterProps
@@ -4552,12 +4313,24 @@ export abstract class AuroraDatabase extends Construct {
4552
4313
  vpc,
4553
4314
  vpcSubnets,
4554
4315
  engine: engine.clusterEngine(engineVersion ?? engine.defaultVersion),
4555
- writer: writer ?? ClusterInstance.serverlessV2('writer'),
4316
+ writer:
4317
+ writer ??
4318
+ ClusterInstance.serverlessV2('writer', {
4319
+ enablePerformanceInsights,
4320
+ performanceInsightEncryptionKey: enablePerformanceInsights
4321
+ ? key
4322
+ : undefined,
4323
+ }),
4556
4324
  credentials: Credentials.fromGeneratedSecret(adminUser, {
4557
4325
  encryptionKey: key,
4558
4326
  }),
4559
4327
  iamAuthentication: true,
4560
4328
  monitoringInterval: Duration.seconds(5),
4329
+ cloudwatchLogsExports: enableCloudwatchLogs
4330
+ ? engine.type === 'mysql'
4331
+ ? ['audit', 'error', 'general', 'slowquery']
4332
+ : ['postgresql']
4333
+ : undefined,
4561
4334
  defaultDatabaseName: databaseName,
4562
4335
  storageEncrypted: true,
4563
4336
  storageEncryptionKey: key,
@@ -4593,23 +4366,23 @@ export abstract class AuroraDatabase extends Construct {
4593
4366
  this.proxy?.endpoint ?? this.cluster.clusterEndpoint.hostname;
4594
4367
  const databasePort = this.cluster.clusterEndpoint.port;
4595
4368
 
4596
- const createDbUserHandler = new Function(this, 'CreateDbUserHandler', {
4597
- code: Code.fromAsset(createDbUserBundleDir),
4598
- handler: 'index.handler',
4599
- runtime: Runtime.NODEJS_LATEST,
4369
+ const commonProps: FunctionOptions = {
4370
+ vpc,
4600
4371
  timeout: Duration.minutes(5),
4601
4372
  tracing: Tracing.ACTIVE,
4602
- vpc,
4373
+ architecture: Architecture.ARM_64,
4374
+ };
4375
+
4376
+ const createDbUserHandler = this.createDbUserHandler({
4377
+ ...commonProps,
4603
4378
  vpcSubnets: {
4604
4379
  subnetType: SubnetType.PRIVATE_WITH_EGRESS,
4605
4380
  },
4606
- environment: {
4607
- DATABASE_SECRET_ARN: this.cluster.secret!.secretArn,
4608
- NODE_EXTRA_CA_CERTS: '/var/runtime/ca-cert.pem',
4609
- },
4610
- architecture: Architecture.ARM_64,
4611
4381
  });
4612
-
4382
+ createDbUserHandler.addEnvironment(
4383
+ 'DATABASE_SECRET_ARN',
4384
+ this.cluster.secret!.secretArn,
4385
+ );
4613
4386
  this.cluster.connections.allowDefaultPortFrom(
4614
4387
  createDbUserHandler,
4615
4388
  'Allow the create-db-user handler to connect to the database',
@@ -4646,40 +4419,21 @@ export abstract class AuroraDatabase extends Construct {
4646
4419
  region: Stack.of(this).region,
4647
4420
  });
4648
4421
 
4649
- const migrationHandler = new DockerImageFunction(this, 'MigrationHandler', {
4650
- code: DockerImageCode.fromImageAsset(migrationBundleDir, {
4651
- platform: Platform.LINUX_ARM64,
4652
- }),
4422
+ const migrationHandler = this.createMigrationHandler({
4423
+ ...commonProps,
4653
4424
  memorySize: 1024,
4654
- timeout: Duration.minutes(5),
4655
- tracing: Tracing.ACTIVE,
4656
- vpc,
4657
- environment:
4658
- engine.type === 'mysql'
4659
- ? {
4660
- DATABASE_SECRET_ARN: this.cluster.secret!.secretArn,
4661
- }
4662
- : {
4663
- HOSTNAME: databaseHostname,
4664
- DATABASE: databaseName,
4665
- PORT: databasePort.toString(),
4666
- DBUSER: this.dbUser,
4667
- },
4668
- architecture: Architecture.ARM_64,
4669
4425
  });
4426
+ migrationHandler.addEnvironment(
4427
+ 'DATABASE_SECRET_ARN',
4428
+ this.cluster.secret!.secretArn,
4429
+ );
4430
+ this.cluster.connections.allowDefaultPortFrom(migrationHandler);
4431
+ this.grantSecretRead(migrationHandler);
4670
4432
 
4671
- if (engine.type === 'mysql') {
4672
- this.cluster.connections.allowDefaultPortFrom(migrationHandler);
4673
- this.grantSecretRead(migrationHandler);
4674
- } else {
4675
- this.allowDefaultPortFrom(migrationHandler);
4676
- this.grantConnect(migrationHandler);
4677
- }
4678
-
4679
- const trigger = new Trigger(this, 'MigrationTrigger', {
4433
+ const migrationTrigger = new Trigger(this, 'MigrationTrigger', {
4680
4434
  handler: migrationHandler,
4681
4435
  });
4682
- trigger.node.addDependency(createDbUserResource);
4436
+ migrationTrigger.node.addDependency(createDbUserResource);
4683
4437
 
4684
4438
  new CfnOutput(this, 'ClusterEndpoint', {
4685
4439
  value: this.cluster.clusterEndpoint.hostname,
@@ -4692,6 +4446,18 @@ export abstract class AuroraDatabase extends Construct {
4692
4446
  }
4693
4447
  }
4694
4448
 
4449
+ /**
4450
+ * Creates the Lambda handler used to create or reconcile the application database user.
4451
+ */
4452
+ protected abstract createDbUserHandler(baseProps: FunctionOptions): Function;
4453
+
4454
+ /**
4455
+ * Creates the Lambda handler used to run database migrations.
4456
+ */
4457
+ protected abstract createMigrationHandler(
4458
+ baseProps: FunctionOptions,
4459
+ ): Function;
4460
+
4695
4461
  public allowDefaultPortFrom(other: IConnectable, description?: string): void {
4696
4462
  if (this.proxy) {
4697
4463
  this.proxy.connections.allowFrom(
@@ -4720,8 +4486,17 @@ export abstract class AuroraDatabase extends Construct {
4720
4486
  exports[`ts#rdb generator > should generate the aurora shared construct 2`] = `
4721
4487
  "import * as path from 'path';
4722
4488
  import * as url from 'url';
4489
+ import { readFileSync } from 'fs';
4723
4490
  import { Construct } from 'constructs';
4724
- import { DB_PACKAGE_NAME } from ':proj/db';
4491
+ import { Platform } from 'aws-cdk-lib/aws-ecr-assets';
4492
+ import {
4493
+ Code,
4494
+ DockerImageCode,
4495
+ DockerImageFunction,
4496
+ Function,
4497
+ FunctionOptions,
4498
+ Runtime,
4499
+ } from 'aws-cdk-lib/aws-lambda';
4725
4500
  import {
4726
4501
  AuroraDatabase,
4727
4502
  AuroraDatabaseEngines,
@@ -4729,14 +4504,29 @@ import {
4729
4504
  } from '../../core/rdb/aurora.js';
4730
4505
  import { findWorkspaceRoot } from '../../core/workspace.js';
4731
4506
 
4507
+ const { runtimeConfigKey } = JSON.parse(
4508
+ readFileSync(
4509
+ path.join(
4510
+ findWorkspaceRoot(url.fileURLToPath(new URL(import.meta.url))),
4511
+ 'packages/db/config.json',
4512
+ ),
4513
+ 'utf-8',
4514
+ ),
4515
+ ) as { runtimeConfigKey: string };
4516
+
4517
+ const migrationBundleDir = path.join(
4518
+ findWorkspaceRoot(url.fileURLToPath(new URL(import.meta.url))),
4519
+ 'dist/packages/db/bundle/migration',
4520
+ );
4521
+
4522
+ const createDbUserBundleDir = path.join(
4523
+ findWorkspaceRoot(url.fileURLToPath(new URL(import.meta.url))),
4524
+ 'dist/packages/db/bundle/create-db-user',
4525
+ );
4526
+
4732
4527
  export type DbProps = Omit<
4733
4528
  AuroraDatabaseProps,
4734
- | 'databaseName'
4735
- | 'adminUser'
4736
- | 'createDbUserBundleDir'
4737
- | 'engine'
4738
- | 'runtimeConfigKey'
4739
- | 'migrationBundleDir'
4529
+ 'databaseName' | 'adminUser' | 'runtimeConfigKey' | 'engine'
4740
4530
  >;
4741
4531
 
4742
4532
  /**
@@ -4748,35 +4538,47 @@ export class Db extends AuroraDatabase {
4748
4538
  ...props,
4749
4539
  databaseName: 'database_name',
4750
4540
  adminUser: 'databaseUser',
4751
- runtimeConfigKey: DB_PACKAGE_NAME,
4752
- migrationBundleDir: path.join(
4753
- findWorkspaceRoot(url.fileURLToPath(new URL(import.meta.url))),
4754
- 'dist/packages/db/bundle/migration',
4755
- ),
4756
- createDbUserBundleDir: path.join(
4757
- findWorkspaceRoot(url.fileURLToPath(new URL(import.meta.url))),
4758
- 'dist/packages/db/bundle/create-db-user',
4759
- ),
4541
+ runtimeConfigKey,
4760
4542
  engine: AuroraDatabaseEngines.postgres({}),
4761
4543
  });
4762
4544
  }
4545
+
4546
+ protected override createDbUserHandler(baseProps: FunctionOptions): Function {
4547
+ return new Function(this, 'CreateDbUserHandler', {
4548
+ ...baseProps,
4549
+ code: Code.fromAsset(createDbUserBundleDir),
4550
+ handler: 'index.handler',
4551
+ runtime: Runtime.NODEJS_LATEST,
4552
+ environment: {
4553
+ NODE_EXTRA_CA_CERTS: '/var/runtime/ca-cert.pem',
4554
+ },
4555
+ });
4556
+ }
4557
+
4558
+ protected override createMigrationHandler(
4559
+ baseProps: FunctionOptions,
4560
+ ): Function {
4561
+ return new DockerImageFunction(this, 'MigrationHandler', {
4562
+ ...baseProps,
4563
+ code: DockerImageCode.fromImageAsset(migrationBundleDir, {
4564
+ platform: Platform.LINUX_ARM64,
4565
+ }),
4566
+ });
4567
+ }
4763
4568
  }
4764
4569
  "
4765
4570
  `;
4766
4571
 
4767
4572
  exports[`ts#rdb generator > should generate the aurora shared construct 3`] = `
4768
4573
  "import { defineConfig } from 'prisma/config';
4574
+ import { readFileSync } from 'fs';
4769
4575
 
4770
4576
  const getDatabaseUrl = async () => {
4771
- if (process.env.SERVE_LOCAL === 'true') {
4772
- const {
4773
- LOCAL_DB_HOST,
4774
- LOCAL_DB_NAME,
4775
- LOCAL_DB_PASSWORD,
4776
- LOCAL_DB_PORT,
4777
- LOCAL_DB_USER,
4778
- } = await import('./src/constants.js');
4779
- return \`postgresql://\${LOCAL_DB_USER}:\${LOCAL_DB_PASSWORD}@\${LOCAL_DB_HOST}:\${LOCAL_DB_PORT}/\${LOCAL_DB_NAME}\`;
4577
+ if (process.env.LOCAL_DEV === 'true') {
4578
+ const { host, port, dbName, dbUser, dbPassword } = JSON.parse(
4579
+ readFileSync('config.json', 'utf-8'),
4580
+ ).localDev;
4581
+ return \`postgresql://\${dbUser}:\${dbPassword}@\${host}:\${port}/\${dbName}\`;
4780
4582
  }
4781
4583
  return process.env.DATABASE_URL;
4782
4584
  };
@@ -4796,9 +4598,16 @@ export default defineConfig({
4796
4598
  exports[`ts#rdb generator > should generate the aurora shared construct 4`] = `
4797
4599
  "FROM public.ecr.aws/lambda/nodejs:24
4798
4600
 
4601
+ # Upgrade npm to a version free of known HIGH/CRITICAL vulnerabilities
4602
+ RUN npm install -g npm@12.0.1
4603
+
4799
4604
  WORKDIR \${LAMBDA_TASK_ROOT}
4800
4605
 
4801
- RUN npm install prisma@7.8.0
4606
+ # npm blocks dependency install scripts by default; allow prisma's so its
4607
+ # postinstall downloads the schema-engine binary needed to run migrations.
4608
+ RUN printf 'allow-scripts[]=prisma\\nallow-scripts[]=@prisma/engines\\n' > .npmrc \\
4609
+ && npm install prisma@7.8.0 \\
4610
+ && rm .npmrc
4802
4611
 
4803
4612
  COPY index.js ./index.js
4804
4613
  COPY prisma ./prisma