@aws/nx-plugin 1.0.0-rc.5 → 1.0.0-rc.50

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 (1198) hide show
  1. package/LICENSE-THIRD-PARTY +5300 -5843
  2. package/README.md +7 -7
  3. package/generators.json +120 -8
  4. package/migrations.json +21 -0
  5. package/package.json +39 -20
  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 +61 -0
  10. package/src/agentcore-gateway/files/cedar/policies/permit-all.cedar +26 -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 +166 -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 +71 -0
  33. package/src/connection/{agent-serve-local.d.ts → agent-local-dev.d.ts} +7 -7
  34. package/src/connection/agent-local-dev.js +42 -0
  35. package/src/connection/agent-local-dev.js.map +1 -0
  36. package/src/connection/agent-runtime-config.d.ts +1 -1
  37. package/src/connection/agent-runtime-config.js +9 -14
  38. package/src/connection/agent-runtime-config.js.map +1 -1
  39. package/src/connection/generator.d.ts +7 -14
  40. package/src/connection/generator.js +167 -194
  41. package/src/connection/generator.js.map +1 -1
  42. package/src/connection/local-dev.d.ts +15 -0
  43. package/src/connection/local-dev.js +37 -0
  44. package/src/connection/local-dev.js.map +1 -0
  45. package/src/connection/schema.d.js +6 -0
  46. package/src/connection/schema.d.js.map +1 -0
  47. package/src/connection/schema.d.ts +1 -0
  48. package/src/connection/schema.json +5 -0
  49. package/src/connection/supported-connections.d.ts +107 -0
  50. package/src/connection/supported-connections.js +151 -0
  51. package/src/connection/supported-connections.js.map +1 -0
  52. package/src/index.js +2 -5
  53. package/src/index.js.map +1 -1
  54. package/src/infra/app/__snapshots__/generator.spec.ts.snap +106 -100
  55. package/src/infra/app/files/app/src/main.ts.template +1 -1
  56. package/src/infra/app/files/app/src/stages/application-stage.ts.template +1 -1
  57. package/src/infra/app/generator.d.ts +3 -3
  58. package/src/infra/app/generator.js +146 -123
  59. package/src/infra/app/generator.js.map +1 -1
  60. package/src/infra/app/schema.d.js +6 -0
  61. package/src/infra/app/schema.d.js.map +1 -0
  62. package/src/infra/app/schema.d.ts +1 -1
  63. package/src/infra/app/schema.json +5 -0
  64. package/src/init/generator.d.ts +18 -0
  65. package/src/init/generator.js +35 -0
  66. package/src/init/generator.js.map +1 -0
  67. package/src/init/schema.d.js +6 -0
  68. package/src/init/schema.d.js.map +1 -0
  69. package/src/init/schema.d.ts +16 -0
  70. package/src/init/schema.json +35 -0
  71. package/src/license/config-types.d.ts +2 -2
  72. package/src/license/config-types.js +8 -2
  73. package/src/license/config-types.js.map +1 -1
  74. package/src/license/config.d.ts +4 -4
  75. package/src/license/config.js +267 -242
  76. package/src/license/config.js.map +1 -1
  77. package/src/license/dependency-check/check.d.ts +6 -2
  78. package/src/license/dependency-check/check.js +51 -46
  79. package/src/license/dependency-check/check.js.map +1 -1
  80. package/src/license/dependency-check/collectors/collector.js +41 -71
  81. package/src/license/dependency-check/collectors/collector.js.map +1 -1
  82. package/src/license/dependency-check/collectors/npm-collector.js +34 -41
  83. package/src/license/dependency-check/collectors/npm-collector.js.map +1 -1
  84. package/src/license/dependency-check/collectors/python-collector.d.ts +4 -0
  85. package/src/license/dependency-check/collectors/python-collector.js +55 -62
  86. package/src/license/dependency-check/collectors/python-collector.js.map +1 -1
  87. package/src/license/dependency-check/evaluator.d.ts +1 -1
  88. package/src/license/dependency-check/evaluator.js +40 -68
  89. package/src/license/dependency-check/evaluator.js.map +1 -1
  90. package/src/license/dependency-check/executor.d.ts +1 -1
  91. package/src/license/dependency-check/executor.js +30 -22
  92. package/src/license/dependency-check/executor.js.map +1 -1
  93. package/src/license/dependency-check/pre-approved.js +949 -336
  94. package/src/license/dependency-check/pre-approved.js.map +1 -1
  95. package/src/license/dependency-check/types.js +2 -3
  96. package/src/license/dependency-check/types.js.map +1 -1
  97. package/src/license/generator.d.ts +3 -3
  98. package/src/license/generator.js +65 -68
  99. package/src/license/generator.js.map +1 -1
  100. package/src/license/index.d.ts +2 -2
  101. package/src/license/index.js +3 -9
  102. package/src/license/index.js.map +1 -1
  103. package/src/license/known-exceptions.d.ts +2 -2
  104. package/src/license/known-exceptions.js +19 -13
  105. package/src/license/known-exceptions.js.map +1 -1
  106. package/src/license/schema.d.js +6 -0
  107. package/src/license/schema.d.js.map +1 -0
  108. package/src/license/schema.d.ts +2 -0
  109. package/src/license/schema.json +5 -0
  110. package/src/license/sync/generator.d.ts +2 -2
  111. package/src/license/sync/generator.js +94 -119
  112. package/src/license/sync/generator.js.map +1 -1
  113. package/src/license/sync/project-file-sync.d.ts +2 -2
  114. package/src/license/sync/project-file-sync.js +28 -35
  115. package/src/license/sync/project-file-sync.js.map +1 -1
  116. package/src/mcp-server/dev-server.d.ts +1 -0
  117. package/src/mcp-server/dev-server.js +18 -0
  118. package/src/mcp-server/dev-server.js.map +1 -0
  119. package/src/mcp-server/generator-info.d.ts +5 -1
  120. package/src/mcp-server/generator-info.js +149 -165
  121. package/src/mcp-server/generator-info.js.map +1 -1
  122. package/src/mcp-server/guide-pipeline.d.ts +1 -1
  123. package/src/mcp-server/guide-pipeline.js +199 -206
  124. package/src/mcp-server/guide-pipeline.js.map +1 -1
  125. package/src/mcp-server/guide-render.js +10 -25
  126. package/src/mcp-server/guide-render.js.map +1 -1
  127. package/src/mcp-server/index.js +6 -10
  128. package/src/mcp-server/index.js.map +1 -1
  129. package/src/mcp-server/mdx-ast.js +42 -56
  130. package/src/mcp-server/mdx-ast.js.map +1 -1
  131. package/src/mcp-server/option-filter.js +33 -47
  132. package/src/mcp-server/option-filter.js.map +1 -1
  133. package/src/mcp-server/schema-registry.d.ts +9 -3
  134. package/src/mcp-server/schema-registry.js +41 -38
  135. package/src/mcp-server/schema-registry.js.map +1 -1
  136. package/src/mcp-server/schema.d.ts +1 -1
  137. package/src/mcp-server/schema.js +9 -7
  138. package/src/mcp-server/schema.js.map +1 -1
  139. package/src/mcp-server/server.js +24 -24
  140. package/src/mcp-server/server.js.map +1 -1
  141. package/src/mcp-server/tools/add-to-existing-project.d.ts +12 -0
  142. package/src/mcp-server/tools/add-to-existing-project.js +36 -0
  143. package/src/mcp-server/tools/add-to-existing-project.js.map +1 -0
  144. package/src/mcp-server/tools/create-workspace-command.d.ts +1 -1
  145. package/src/mcp-server/tools/create-workspace-command.js +23 -24
  146. package/src/mcp-server/tools/create-workspace-command.js.map +1 -1
  147. package/src/mcp-server/tools/general-guidance.d.ts +3 -3
  148. package/src/mcp-server/tools/general-guidance.js +53 -31
  149. package/src/mcp-server/tools/general-guidance.js.map +1 -1
  150. package/src/mcp-server/tools/generator-guide.d.ts +2 -2
  151. package/src/mcp-server/tools/generator-guide.js +29 -37
  152. package/src/mcp-server/tools/generator-guide.js.map +1 -1
  153. package/src/mcp-server/tools/list-generators.d.ts +2 -2
  154. package/src/mcp-server/tools/list-generators.js +19 -25
  155. package/src/mcp-server/tools/list-generators.js.map +1 -1
  156. package/src/mcp-server/tools/upgrade-workspace.d.ts +11 -0
  157. package/src/mcp-server/tools/upgrade-workspace.js +32 -0
  158. package/src/mcp-server/tools/upgrade-workspace.js.map +1 -0
  159. package/src/migrations/latest/modernize-function-props-cast/migration.d.ts +6 -0
  160. package/src/migrations/latest/modernize-function-props-cast/migration.js +66 -0
  161. package/src/migrations/latest/modernize-function-props-cast/migration.js.map +1 -0
  162. package/src/migrations/latest/restrict-cors-to-custom-domains/migration.d.ts +6 -0
  163. package/src/migrations/latest/restrict-cors-to-custom-domains/migration.js +110 -0
  164. package/src/migrations/latest/restrict-cors-to-custom-domains/migration.js.map +1 -0
  165. package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.d.ts +6 -0
  166. package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.js +129 -0
  167. package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.js.map +1 -0
  168. package/src/open-api/ts-client/__snapshots__/generator.additional-properties.spec.ts.snap +147 -33
  169. package/src/open-api/ts-client/__snapshots__/generator.arrays.spec.ts.snap +308 -75
  170. package/src/open-api/ts-client/__snapshots__/generator.complex-types.spec.ts.snap +298 -74
  171. package/src/open-api/ts-client/__snapshots__/generator.composite-types.spec.ts.snap +748 -103
  172. package/src/open-api/ts-client/__snapshots__/generator.content-type.spec.ts.snap +230 -37
  173. package/src/open-api/ts-client/__snapshots__/generator.duplicate-types.spec.ts.snap +249 -52
  174. package/src/open-api/ts-client/__snapshots__/generator.edge-cases.spec.ts.snap +5535 -0
  175. package/src/open-api/ts-client/__snapshots__/generator.fast-api-gaps.spec.ts.snap +736 -0
  176. package/src/open-api/ts-client/__snapshots__/generator.fast-api.spec.ts.snap +305 -71
  177. package/src/open-api/ts-client/__snapshots__/generator.multipart.spec.ts.snap +298 -0
  178. package/src/open-api/ts-client/__snapshots__/generator.primitive-types.spec.ts.snap +353 -82
  179. package/src/open-api/ts-client/__snapshots__/generator.request.spec.ts.snap +176 -55
  180. package/src/open-api/ts-client/__snapshots__/generator.reserved-keywords.spec.ts.snap +101 -25
  181. package/src/open-api/ts-client/__snapshots__/generator.response.spec.ts.snap +147 -33
  182. package/src/open-api/ts-client/__snapshots__/generator.spec-compliance.spec.ts.snap +1883 -0
  183. package/src/open-api/ts-client/__snapshots__/generator.streaming.spec.ts.snap +392 -88
  184. package/src/open-api/ts-client/__snapshots__/generator.tags.spec.ts.snap +200 -48
  185. package/src/open-api/ts-client/files/client.gen.ts.template +358 -24
  186. package/src/open-api/ts-client/files/types.gen.ts.template +6 -4
  187. package/src/open-api/ts-client/generator.d.ts +3 -3
  188. package/src/open-api/ts-client/generator.js +41 -26
  189. package/src/open-api/ts-client/generator.js.map +1 -1
  190. package/src/open-api/ts-client/schema.d.js +6 -0
  191. package/src/open-api/ts-client/schema.d.js.map +1 -0
  192. package/src/open-api/ts-hooks/files/options-proxy.gen.ts.template +7 -2
  193. package/src/open-api/ts-hooks/generator.d.ts +3 -3
  194. package/src/open-api/ts-hooks/generator.js +17 -21
  195. package/src/open-api/ts-hooks/generator.js.map +1 -1
  196. package/src/open-api/ts-hooks/generator.spec.tsx +84 -14
  197. package/src/open-api/ts-hooks/schema.d.js +6 -0
  198. package/src/open-api/ts-hooks/schema.d.js.map +1 -0
  199. package/src/open-api/ts-metadata/generator.d.ts +3 -3
  200. package/src/open-api/ts-metadata/generator.js +12 -20
  201. package/src/open-api/ts-metadata/generator.js.map +1 -1
  202. package/src/open-api/ts-metadata/schema.d.js +6 -0
  203. package/src/open-api/ts-metadata/schema.d.js.map +1 -0
  204. package/src/open-api/utils/codegen-data/languages.d.ts +3 -5
  205. package/src/open-api/utils/codegen-data/languages.js +59 -66
  206. package/src/open-api/utils/codegen-data/languages.js.map +1 -1
  207. package/src/open-api/utils/codegen-data/types.d.ts +255 -10
  208. package/src/open-api/utils/codegen-data/types.js +54 -30
  209. package/src/open-api/utils/codegen-data/types.js.map +1 -1
  210. package/src/open-api/utils/codegen-data.d.ts +8 -4
  211. package/src/open-api/utils/codegen-data.js +494 -674
  212. package/src/open-api/utils/codegen-data.js.map +1 -1
  213. package/src/open-api/utils/normalise.d.ts +5 -1
  214. package/src/open-api/utils/normalise.js +437 -246
  215. package/src/open-api/utils/normalise.js.map +1 -1
  216. package/src/open-api/utils/parse.d.ts +2 -2
  217. package/src/open-api/utils/parse.js +11 -13
  218. package/src/open-api/utils/parse.js.map +1 -1
  219. package/src/open-api/utils/parser.d.ts +55 -0
  220. package/src/open-api/utils/parser.js +787 -0
  221. package/src/open-api/utils/parser.js.map +1 -0
  222. package/src/open-api/utils/refs.d.ts +1 -1
  223. package/src/open-api/utils/refs.js +12 -22
  224. package/src/open-api/utils/refs.js.map +1 -1
  225. package/src/open-api/utils/types.d.ts +18 -0
  226. package/src/open-api/utils/types.js +5 -2
  227. package/src/open-api/utils/types.js.map +1 -1
  228. package/src/preset/__snapshots__/generator.spec.ts.snap +149 -28
  229. package/src/preset/generator.d.ts +4 -4
  230. package/src/preset/generator.js +66 -147
  231. package/src/preset/generator.js.map +1 -1
  232. package/src/preset/schema.d.js +6 -0
  233. package/src/preset/schema.d.js.map +1 -0
  234. package/src/preset/schema.d.ts +6 -2
  235. package/src/preset/schema.json +16 -5
  236. package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +321 -0
  237. package/src/py/agent/__snapshots__/generator.frameworks.spec.ts.snap +734 -0
  238. package/src/py/agent/__snapshots__/{generator.spec.ts.snap → generator.protocols.spec.ts.snap} +182 -314
  239. package/src/py/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +189 -0
  240. package/src/py/agent/a2a-connection/files/agent-connection/app/__targetAgentSnakeCase___client_strands.py.template +30 -0
  241. package/src/py/agent/a2a-connection/files/langchain/agent-connection/app/__targetAgentSnakeCase___client_langchain.py.template +28 -0
  242. package/src/py/agent/a2a-connection/generator.d.ts +3 -3
  243. package/src/py/agent/a2a-connection/generator.js +113 -85
  244. package/src/py/agent/a2a-connection/generator.js.map +1 -1
  245. package/src/py/agent/a2a-connection/schema.d.js +8 -0
  246. package/src/py/agent/a2a-connection/schema.d.js.map +1 -0
  247. package/src/py/agent/a2a-connection/schema.d.ts +1 -0
  248. package/src/py/agent/a2a-connection/schema.json +5 -0
  249. package/src/py/agent/files/a2a-langchain/main.py.template +89 -0
  250. package/src/py/agent/files/ag-ui-langchain/main.py.template +83 -0
  251. package/src/py/agent/files/common/agent.py.template +2 -0
  252. package/src/py/agent/files/common-langchain/agent.py.template +30 -0
  253. package/src/py/agent/files/deploy/Dockerfile.template +1 -1
  254. package/src/py/agent/files/http/init.py.template +7 -25
  255. package/src/py/agent/files/http/main.py.template +3 -4
  256. package/src/py/agent/files/http-langchain/main.py.template +84 -0
  257. package/src/py/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +184 -0
  258. package/src/py/agent/gateway-connection/files/agent-connection/app/__gatewaySnakeCase___client_strands.py.template +35 -0
  259. package/src/py/agent/gateway-connection/files/langchain/agent-connection/app/__gatewaySnakeCase___client_langchain.py.template +34 -0
  260. package/src/py/agent/gateway-connection/generator.d.ts +10 -0
  261. package/src/py/agent/gateway-connection/generator.js +119 -0
  262. package/src/py/agent/gateway-connection/generator.js.map +1 -0
  263. package/src/py/agent/gateway-connection/schema.d.js +6 -0
  264. package/src/py/agent/gateway-connection/schema.d.js.map +1 -0
  265. package/src/py/agent/gateway-connection/schema.d.ts +13 -0
  266. package/src/py/agent/gateway-connection/schema.json +31 -0
  267. package/src/py/agent/generator.d.ts +3 -3
  268. package/src/py/agent/generator.js +290 -183
  269. package/src/py/agent/generator.js.map +1 -1
  270. package/src/py/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +153 -89
  271. package/src/py/agent/mcp-connection/files/agent-connection/app/__mcpServerSnakeCase___client_strands.py.template +30 -0
  272. package/src/py/agent/mcp-connection/files/langchain/agent-connection/app/__mcpServerSnakeCase___client_langchain.py.template +30 -0
  273. package/src/py/agent/mcp-connection/generator.d.ts +3 -3
  274. package/src/py/agent/mcp-connection/generator.js +65 -126
  275. package/src/py/agent/mcp-connection/generator.js.map +1 -1
  276. package/src/py/agent/mcp-connection/schema.d.js +8 -0
  277. package/src/py/agent/mcp-connection/schema.d.js.map +1 -0
  278. package/src/py/agent/mcp-connection/schema.d.ts +1 -0
  279. package/src/py/agent/mcp-connection/schema.json +5 -0
  280. package/src/py/agent/react-connection/__snapshots__/generator.spec.ts.snap +11 -19
  281. package/src/py/agent/react-connection/generator.d.ts +4 -4
  282. package/src/py/agent/react-connection/generator.js +55 -59
  283. package/src/py/agent/react-connection/generator.js.map +1 -1
  284. package/src/py/agent/react-connection/{serve-local.d.ts → local-dev.d.ts} +6 -6
  285. package/src/py/agent/react-connection/local-dev.js +36 -0
  286. package/src/py/agent/react-connection/local-dev.js.map +1 -0
  287. package/src/py/agent/react-connection/schema.d.js +8 -0
  288. package/src/py/agent/react-connection/schema.d.js.map +1 -0
  289. package/src/py/agent/react-connection/schema.d.ts +1 -0
  290. package/src/py/agent/react-connection/schema.json +5 -0
  291. package/src/py/agent/schema.d.js +6 -0
  292. package/src/py/agent/schema.d.js.map +1 -0
  293. package/src/py/agent/schema.d.ts +2 -1
  294. package/src/py/agent/schema.json +6 -1
  295. package/src/py/api/generator.d.ts +3 -3
  296. package/src/py/api/generator.js +12 -11
  297. package/src/py/api/generator.js.map +1 -1
  298. package/src/py/api/schema.d.js +6 -0
  299. package/src/py/api/schema.d.js.map +1 -0
  300. package/src/py/api/schema.d.ts +1 -0
  301. package/src/py/api/schema.json +5 -0
  302. package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +1522 -0
  303. package/src/py/dynamodb/agent-connection/__snapshots__/generator.spec.ts.snap +45 -0
  304. package/src/py/dynamodb/agent-connection/generator.d.ts +10 -0
  305. package/src/py/dynamodb/agent-connection/generator.js +39 -0
  306. package/src/py/dynamodb/agent-connection/generator.js.map +1 -0
  307. package/src/py/dynamodb/agent-connection/schema.d.js +8 -0
  308. package/src/py/dynamodb/agent-connection/schema.d.js.map +1 -0
  309. package/src/py/dynamodb/agent-connection/schema.d.ts +15 -0
  310. package/src/py/dynamodb/agent-connection/schema.json +27 -0
  311. package/src/py/dynamodb/fast-api-connection/__snapshots__/generator.spec.ts.snap +23 -0
  312. package/src/py/dynamodb/fast-api-connection/generator.d.ts +10 -0
  313. package/src/py/dynamodb/fast-api-connection/generator.js +37 -0
  314. package/src/py/dynamodb/fast-api-connection/generator.js.map +1 -0
  315. package/src/py/dynamodb/fast-api-connection/schema.d.js +8 -0
  316. package/src/py/dynamodb/fast-api-connection/schema.d.js.map +1 -0
  317. package/src/py/dynamodb/fast-api-connection/schema.d.ts +13 -0
  318. package/src/py/dynamodb/fast-api-connection/schema.json +23 -0
  319. package/src/py/dynamodb/files/__name__/__init__.py.template +6 -0
  320. package/src/py/dynamodb/files/__name__/client.py.template +39 -0
  321. package/src/py/dynamodb/files/__name__/entities/__init__.py.template +4 -0
  322. package/src/py/dynamodb/files/__name__/entities/base.py.template +63 -0
  323. package/src/py/dynamodb/files/__name__/entities/example.py.template +64 -0
  324. package/src/py/dynamodb/files/config.json.template +24 -0
  325. package/src/py/dynamodb/generator.d.ts +10 -0
  326. package/src/py/dynamodb/generator.js +110 -0
  327. package/src/py/dynamodb/generator.js.map +1 -0
  328. package/src/py/dynamodb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +45 -0
  329. package/src/py/dynamodb/mcp-server-connection/generator.d.ts +10 -0
  330. package/src/py/dynamodb/mcp-server-connection/generator.js +39 -0
  331. package/src/py/dynamodb/mcp-server-connection/generator.js.map +1 -0
  332. package/src/py/dynamodb/mcp-server-connection/schema.d.js +8 -0
  333. package/src/py/dynamodb/mcp-server-connection/schema.d.js.map +1 -0
  334. package/src/py/dynamodb/mcp-server-connection/schema.d.ts +15 -0
  335. package/src/py/dynamodb/mcp-server-connection/schema.json +27 -0
  336. package/src/py/dynamodb/schema.d.js +6 -0
  337. package/src/py/dynamodb/schema.d.js.map +1 -0
  338. package/src/py/dynamodb/schema.d.ts +16 -0
  339. package/src/py/dynamodb/schema.json +75 -0
  340. package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +238 -4694
  341. package/src/py/fast-api/__snapshots__/generator.terraform.spec.ts.snap +5409 -0
  342. package/src/py/fast-api/files/app/__name__/init.py.template +5 -22
  343. package/src/py/fast-api/files/app/__name__/main.py.template +4 -1
  344. package/src/py/fast-api/generator.d.ts +3 -3
  345. package/src/py/fast-api/generator.js +90 -87
  346. package/src/py/fast-api/generator.js.map +1 -1
  347. package/src/py/fast-api/react/__snapshots__/generator.spec.ts.snap +4 -3
  348. package/src/py/fast-api/react/generator.d.ts +4 -4
  349. package/src/py/fast-api/react/generator.js +25 -25
  350. package/src/py/fast-api/react/generator.js.map +1 -1
  351. package/src/py/fast-api/react/open-api.d.ts +1 -1
  352. package/src/py/fast-api/react/open-api.js +31 -29
  353. package/src/py/fast-api/react/open-api.js.map +1 -1
  354. package/src/py/fast-api/react/schema.d.js +6 -0
  355. package/src/py/fast-api/react/schema.d.js.map +1 -0
  356. package/src/py/fast-api/react/schema.d.ts +1 -0
  357. package/src/py/fast-api/react/schema.json +5 -0
  358. package/src/py/fast-api/schema.d.js +6 -0
  359. package/src/py/fast-api/schema.d.js.map +1 -0
  360. package/src/py/fast-api/schema.d.ts +1 -0
  361. package/src/py/fast-api/schema.json +5 -0
  362. package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +4 -4
  363. package/src/py/lambda-function/generator.d.ts +3 -3
  364. package/src/py/lambda-function/generator.js +60 -59
  365. package/src/py/lambda-function/generator.js.map +1 -1
  366. package/src/py/lambda-function/schema.d.js +6 -0
  367. package/src/py/lambda-function/schema.d.js.map +1 -0
  368. package/src/py/lambda-function/schema.d.ts +1 -0
  369. package/src/py/lambda-function/schema.json +5 -0
  370. package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +209 -19
  371. package/src/py/mcp-server/files/deploy/Dockerfile.template +1 -1
  372. package/src/py/mcp-server/generator.d.ts +3 -3
  373. package/src/py/mcp-server/generator.js +163 -127
  374. package/src/py/mcp-server/generator.js.map +1 -1
  375. package/src/py/mcp-server/schema.d.js +6 -0
  376. package/src/py/mcp-server/schema.d.js.map +1 -0
  377. package/src/py/mcp-server/schema.d.ts +1 -0
  378. package/src/py/mcp-server/schema.json +5 -0
  379. package/src/py/project/generator.d.ts +17 -4
  380. package/src/py/project/generator.js +229 -130
  381. package/src/py/project/generator.js.map +1 -1
  382. package/src/py/project/schema.d.js +6 -0
  383. package/src/py/project/schema.d.js.map +1 -0
  384. package/src/py/project/schema.d.ts +1 -0
  385. package/src/py/project/schema.json +5 -0
  386. package/src/py/rdb/__snapshots__/generator.spec.ts.snap +2070 -0
  387. package/src/py/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +104 -0
  388. package/src/py/rdb/agent-connection/generator.d.ts +10 -0
  389. package/src/py/rdb/agent-connection/generator.js +46 -0
  390. package/src/py/rdb/agent-connection/generator.js.map +1 -0
  391. package/src/py/rdb/agent-connection/schema.d.js +8 -0
  392. package/src/py/rdb/agent-connection/schema.d.js.map +1 -0
  393. package/src/py/rdb/agent-connection/schema.d.ts +15 -0
  394. package/src/py/rdb/agent-connection/schema.json +27 -0
  395. package/src/py/rdb/fast-api-connection/__snapshots__/generator.spec.ts.snap +44 -0
  396. package/src/py/rdb/fast-api-connection/files/__apiModuleName__/dependencies/__rdbNameSnake__.py.template +14 -0
  397. package/src/py/rdb/fast-api-connection/generator.d.ts +10 -0
  398. package/src/py/rdb/fast-api-connection/generator.js +54 -0
  399. package/src/py/rdb/fast-api-connection/generator.js.map +1 -0
  400. package/src/py/rdb/fast-api-connection/schema.d.js +8 -0
  401. package/src/py/rdb/fast-api-connection/schema.d.js.map +1 -0
  402. package/src/py/rdb/fast-api-connection/schema.d.ts +13 -0
  403. package/src/py/rdb/fast-api-connection/schema.json +23 -0
  404. package/src/py/rdb/files/Dockerfile.create-db-user.template +14 -0
  405. package/src/py/rdb/files/Dockerfile.migration.template +14 -0
  406. package/src/py/rdb/files/__name__/__init__.py.template +3 -0
  407. package/src/py/rdb/files/__name__/connection.py.template +55 -0
  408. package/src/py/rdb/files/__name__/create_db_user_handler.py.template +97 -0
  409. package/src/py/rdb/files/__name__/migration_handler.py.template +36 -0
  410. package/src/py/rdb/files/__name__/models/__init__.py.template +3 -0
  411. package/src/py/rdb/files/__name__/models/example.py.template +8 -0
  412. package/src/py/rdb/files/__name__/utils.py.template +104 -0
  413. package/src/py/rdb/files/alembic.ini.template +38 -0
  414. package/src/py/rdb/files/config.json.template +14 -0
  415. package/src/py/rdb/files/migrations/env.py.template +80 -0
  416. package/src/py/rdb/files/migrations/script.py.mako.template +28 -0
  417. package/src/py/rdb/generator.d.ts +6 -0
  418. package/src/py/rdb/generator.js +280 -0
  419. package/src/py/rdb/generator.js.map +1 -0
  420. package/src/py/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +101 -0
  421. package/src/py/rdb/mcp-server-connection/generator.d.ts +10 -0
  422. package/src/py/rdb/mcp-server-connection/generator.js +46 -0
  423. package/src/py/rdb/mcp-server-connection/generator.js.map +1 -0
  424. package/src/py/rdb/mcp-server-connection/schema.d.js +8 -0
  425. package/src/py/rdb/mcp-server-connection/schema.d.js.map +1 -0
  426. package/src/py/rdb/mcp-server-connection/schema.d.ts +15 -0
  427. package/src/py/rdb/mcp-server-connection/schema.json +27 -0
  428. package/src/py/rdb/schema.d.js +6 -0
  429. package/src/py/rdb/schema.d.js.map +1 -0
  430. package/src/py/rdb/schema.d.ts +16 -0
  431. package/src/py/rdb/schema.json +77 -0
  432. package/src/py/rdb/utils.d.ts +6 -0
  433. package/src/py/rdb/utils.js +16 -0
  434. package/src/py/rdb/utils.js.map +1 -0
  435. package/src/sdk/agentcore-gateway.d.ts +6 -0
  436. package/src/sdk/agentcore-gateway.js +7 -0
  437. package/src/sdk/agentcore-gateway.js.map +1 -0
  438. package/src/sdk/connection.d.ts +6 -0
  439. package/src/sdk/connection.js +6 -0
  440. package/src/sdk/connection.js.map +1 -0
  441. package/src/sdk/license.d.ts +8 -0
  442. package/src/sdk/license.js +7 -0
  443. package/src/sdk/license.js.map +1 -0
  444. package/src/sdk/open-api.d.ts +10 -0
  445. package/src/sdk/open-api.js +8 -0
  446. package/src/sdk/open-api.js.map +1 -0
  447. package/src/sdk/py.d.ts +16 -0
  448. package/src/sdk/py.js +11 -0
  449. package/src/sdk/py.js.map +1 -0
  450. package/src/sdk/terraform.d.ts +6 -0
  451. package/src/sdk/terraform.js +7 -0
  452. package/src/sdk/terraform.js.map +1 -0
  453. package/src/sdk/ts.d.ts +37 -0
  454. package/src/sdk/ts.js +39 -0
  455. package/src/sdk/ts.js.map +1 -0
  456. package/{sdk → src/sdk}/utils/ast.d.ts +1 -2
  457. package/src/sdk/utils/ast.js +6 -0
  458. package/src/sdk/utils/ast.js.map +1 -0
  459. package/{sdk → src/sdk}/utils/format.d.ts +1 -1
  460. package/src/sdk/utils/format.js +6 -0
  461. package/src/sdk/utils/format.js.map +1 -0
  462. package/{sdk → src/sdk}/utils/test.d.ts +1 -1
  463. package/src/sdk/utils/test.js +6 -0
  464. package/src/sdk/utils/test.js.map +1 -0
  465. package/src/smithy/project/__snapshots__/generator.spec.ts.snap +19 -24
  466. package/src/smithy/project/files/build.Dockerfile.template +1 -4
  467. package/src/smithy/project/files/src/operations/echo.smithy.template +1 -0
  468. package/src/smithy/project/generator.d.ts +3 -3
  469. package/src/smithy/project/generator.js +64 -57
  470. package/src/smithy/project/generator.js.map +1 -1
  471. package/src/smithy/project/schema.d.js +6 -0
  472. package/src/smithy/project/schema.d.js.map +1 -0
  473. package/src/smithy/project/schema.d.ts +1 -0
  474. package/src/smithy/project/schema.json +5 -0
  475. package/src/smithy/react-connection/__snapshots__/generator.spec.ts.snap +1 -1
  476. package/src/smithy/react-connection/generator.d.ts +3 -3
  477. package/src/smithy/react-connection/generator.js +39 -47
  478. package/src/smithy/react-connection/generator.js.map +1 -1
  479. package/src/smithy/react-connection/schema.d.js +6 -0
  480. package/src/smithy/react-connection/schema.d.js.map +1 -0
  481. package/src/smithy/react-connection/schema.d.ts +1 -0
  482. package/src/smithy/react-connection/schema.json +5 -0
  483. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +850 -136
  484. package/src/smithy/ts/api/files/handler.ts.template +2 -2
  485. package/src/smithy/ts/api/files/local-server.ts.template +2 -2
  486. package/src/smithy/ts/api/files/operations/echo.ts.template +2 -2
  487. package/src/smithy/ts/api/files/service.ts.template +3 -3
  488. package/src/smithy/ts/api/generator.d.ts +3 -3
  489. package/src/smithy/ts/api/generator.js +131 -105
  490. package/src/smithy/ts/api/generator.js.map +1 -1
  491. package/src/smithy/ts/api/schema.d.js +6 -0
  492. package/src/smithy/ts/api/schema.d.js.map +1 -0
  493. package/src/smithy/ts/api/schema.d.ts +1 -0
  494. package/src/smithy/ts/api/schema.json +5 -0
  495. package/src/terraform/project/files/application/scripts/bootstrap.ts.template +40 -1
  496. package/src/terraform/project/files/application/src/main.tf.template +6 -1
  497. package/src/terraform/project/files/application/src/providers.tf.template +1 -1
  498. package/src/terraform/project/generator.d.ts +3 -3
  499. package/src/terraform/project/generator.js +159 -104
  500. package/src/terraform/project/generator.js.map +1 -1
  501. package/src/terraform/project/schema.d.js +9 -0
  502. package/src/terraform/project/schema.d.js.map +1 -0
  503. package/src/terraform/project/schema.d.ts +1 -0
  504. package/src/terraform/project/schema.json +5 -0
  505. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +1180 -185
  506. package/src/trpc/backend/files/src/client/index.ts.template +1 -1
  507. package/src/trpc/backend/files/src/handler.ts.template +1 -1
  508. package/src/trpc/backend/files/src/index.ts.template +5 -5
  509. package/src/trpc/backend/files/src/init.ts.template +1 -1
  510. package/src/trpc/backend/files/src/local-server.ts.template +1 -1
  511. package/src/trpc/backend/files/src/middleware/index.ts.template +7 -7
  512. package/src/trpc/backend/files/src/procedures/echo.ts.template +3 -3
  513. package/src/trpc/backend/files/src/router.ts.template +2 -2
  514. package/src/trpc/backend/files/src/schema/echo.ts.template +2 -2
  515. package/src/trpc/backend/files/src/schema/index.ts.template +1 -1
  516. package/src/trpc/backend/generator.d.ts +4 -4
  517. package/src/trpc/backend/generator.js +100 -84
  518. package/src/trpc/backend/generator.js.map +1 -1
  519. package/src/trpc/backend/schema.d.js +6 -0
  520. package/src/trpc/backend/schema.d.js.map +1 -0
  521. package/src/trpc/backend/schema.d.ts +3 -2
  522. package/src/trpc/backend/schema.json +5 -0
  523. package/src/trpc/react/__snapshots__/generator.spec.ts.snap +4 -4
  524. package/src/trpc/react/files/src/components/__apiNameClassName__ClientProvider.tsx.template +3 -3
  525. package/src/trpc/react/generator.d.ts +4 -4
  526. package/src/trpc/react/generator.js +64 -59
  527. package/src/trpc/react/generator.js.map +1 -1
  528. package/src/trpc/react/schema.d.js +6 -0
  529. package/src/trpc/react/schema.d.js.map +1 -0
  530. package/src/trpc/react/schema.d.ts +1 -0
  531. package/src/trpc/react/schema.json +5 -0
  532. package/src/ts/agent/__snapshots__/generator.spec.ts.snap +792 -23
  533. package/src/ts/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +257 -0
  534. package/src/ts/agent/a2a-connection/files/agent-connection/app/__targetAgentKebabCase__-client-strands.ts.template +23 -0
  535. package/src/ts/agent/a2a-connection/generator.d.ts +3 -3
  536. package/src/ts/agent/a2a-connection/generator.js +65 -55
  537. package/src/ts/agent/a2a-connection/generator.js.map +1 -1
  538. package/src/ts/agent/a2a-connection/schema.d.js +8 -0
  539. package/src/ts/agent/a2a-connection/schema.d.js.map +1 -0
  540. package/src/ts/agent/a2a-connection/schema.d.ts +1 -0
  541. package/src/ts/agent/a2a-connection/schema.json +5 -0
  542. package/src/ts/agent/files/a2a/index.ts.template +1 -1
  543. package/src/ts/agent/files/ag-ui/index.ts.template +26 -10
  544. package/src/ts/agent/files/common/agent.ts.template +7 -2
  545. package/src/ts/agent/files/deploy/Dockerfile.template +13 -2
  546. package/src/ts/agent/files/http/client.ts.template +2 -2
  547. package/src/ts/agent/files/http/index.ts.template +2 -2
  548. package/src/ts/agent/files/http/router.ts.template +5 -5
  549. package/src/ts/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +221 -0
  550. package/src/ts/agent/gateway-connection/files/agent-connection/app/__gatewayKebabCase__-client-strands.ts.template +30 -0
  551. package/src/ts/agent/gateway-connection/generator.d.ts +10 -0
  552. package/src/ts/agent/gateway-connection/generator.js +117 -0
  553. package/src/ts/agent/gateway-connection/generator.js.map +1 -0
  554. package/src/ts/agent/gateway-connection/schema.d.js +6 -0
  555. package/src/ts/agent/gateway-connection/schema.d.js.map +1 -0
  556. package/src/ts/agent/gateway-connection/schema.d.ts +13 -0
  557. package/src/ts/agent/gateway-connection/schema.json +31 -0
  558. package/src/ts/agent/generator.d.ts +3 -3
  559. package/src/ts/agent/generator.js +213 -145
  560. package/src/ts/agent/generator.js.map +1 -1
  561. package/src/ts/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +193 -111
  562. package/src/ts/agent/mcp-connection/files/agent-connection/app/__mcpServerKebabCase__-client-strands.ts.template +22 -0
  563. package/src/ts/agent/mcp-connection/generator.d.ts +3 -3
  564. package/src/ts/agent/mcp-connection/generator.js +56 -60
  565. package/src/ts/agent/mcp-connection/generator.js.map +1 -1
  566. package/src/ts/agent/mcp-connection/schema.d.js +8 -0
  567. package/src/ts/agent/mcp-connection/schema.d.js.map +1 -0
  568. package/src/ts/agent/mcp-connection/schema.d.ts +1 -0
  569. package/src/ts/agent/mcp-connection/schema.json +5 -0
  570. package/src/ts/agent/react-connection/generator.d.ts +4 -4
  571. package/src/ts/agent/react-connection/generator.js +88 -91
  572. package/src/ts/agent/react-connection/generator.js.map +1 -1
  573. package/src/ts/agent/react-connection/local-dev.d.ts +13 -0
  574. package/src/ts/agent/react-connection/local-dev.js +17 -0
  575. package/src/ts/agent/react-connection/local-dev.js.map +1 -0
  576. package/src/ts/agent/react-connection/schema.d.js +8 -0
  577. package/src/ts/agent/react-connection/schema.d.js.map +1 -0
  578. package/src/ts/agent/react-connection/schema.d.ts +1 -0
  579. package/src/ts/agent/react-connection/schema.json +5 -0
  580. package/src/ts/agent/schema.d.js +6 -0
  581. package/src/ts/agent/schema.d.js.map +1 -0
  582. package/src/ts/agent/schema.d.ts +1 -0
  583. package/src/ts/agent/schema.json +5 -0
  584. package/src/ts/api/generator.d.ts +3 -3
  585. package/src/ts/api/generator.js +16 -16
  586. package/src/ts/api/generator.js.map +1 -1
  587. package/src/ts/api/schema.d.js +6 -0
  588. package/src/ts/api/schema.d.js.map +1 -0
  589. package/src/ts/api/schema.d.ts +3 -1
  590. package/src/ts/api/schema.json +5 -0
  591. package/src/ts/astro-docs/__snapshots__/generator.spec.ts.snap +15 -16
  592. package/src/ts/astro-docs/files/translation/scripts/translate.ts.template +3 -2
  593. package/src/ts/astro-docs/generator.d.ts +3 -3
  594. package/src/ts/astro-docs/generator.js +80 -54
  595. package/src/ts/astro-docs/generator.js.map +1 -1
  596. package/src/ts/astro-docs/schema.d.js +6 -0
  597. package/src/ts/astro-docs/schema.d.js.map +1 -0
  598. package/src/ts/astro-docs/schema.d.ts +2 -2
  599. package/src/ts/astro-docs/schema.json +3 -3
  600. package/src/ts/dcr-proxy/__snapshots__/generator.spec.ts.snap +982 -0
  601. package/src/ts/dcr-proxy/generator.d.ts +10 -0
  602. package/src/ts/dcr-proxy/generator.js +98 -0
  603. package/src/ts/dcr-proxy/generator.js.map +1 -0
  604. package/src/ts/dcr-proxy/schema.d.js +6 -0
  605. package/src/ts/dcr-proxy/schema.d.js.map +1 -0
  606. package/src/ts/dcr-proxy/schema.d.ts +13 -0
  607. package/src/ts/dcr-proxy/schema.json +44 -0
  608. package/src/ts/docs/generator.d.ts +3 -3
  609. package/src/ts/docs/generator.js +10 -10
  610. package/src/ts/docs/generator.js.map +1 -1
  611. package/src/ts/docs/schema.d.js +6 -0
  612. package/src/ts/docs/schema.d.js.map +1 -0
  613. package/src/ts/docs/schema.d.ts +1 -4
  614. package/src/ts/docs/schema.json +3 -3
  615. package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +402 -518
  616. package/src/ts/dynamodb/agent-connection/__snapshots__/generator.spec.ts.snap +5 -5
  617. package/src/ts/dynamodb/agent-connection/generator.d.ts +3 -3
  618. package/src/ts/dynamodb/agent-connection/generator.js +21 -23
  619. package/src/ts/dynamodb/agent-connection/generator.js.map +1 -1
  620. package/src/ts/dynamodb/agent-connection/schema.d.js +8 -0
  621. package/src/ts/dynamodb/agent-connection/schema.d.js.map +1 -0
  622. package/src/ts/dynamodb/agent-connection/schema.d.ts +1 -0
  623. package/src/ts/dynamodb/agent-connection/schema.json +5 -0
  624. package/src/ts/dynamodb/files/config.json.template +24 -0
  625. package/src/ts/dynamodb/files/src/client.ts.template +30 -11
  626. package/src/ts/dynamodb/files/src/entities/example.ts.template +1 -1
  627. package/src/ts/dynamodb/files/src/entities/index.ts.template +1 -1
  628. package/src/ts/dynamodb/files/src/index.ts.template +2 -11
  629. package/src/ts/dynamodb/generator.d.ts +3 -3
  630. package/src/ts/dynamodb/generator.js +76 -63
  631. package/src/ts/dynamodb/generator.js.map +1 -1
  632. package/src/ts/dynamodb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +5 -5
  633. package/src/ts/dynamodb/mcp-server-connection/generator.d.ts +3 -3
  634. package/src/ts/dynamodb/mcp-server-connection/generator.js +21 -23
  635. package/src/ts/dynamodb/mcp-server-connection/generator.js.map +1 -1
  636. package/src/ts/dynamodb/mcp-server-connection/schema.d.js +8 -0
  637. package/src/ts/dynamodb/mcp-server-connection/schema.d.js.map +1 -0
  638. package/src/ts/dynamodb/mcp-server-connection/schema.d.ts +1 -0
  639. package/src/ts/dynamodb/mcp-server-connection/schema.json +5 -0
  640. package/src/ts/dynamodb/schema.d.js +6 -0
  641. package/src/ts/dynamodb/schema.d.js.map +1 -0
  642. package/src/ts/dynamodb/schema.d.ts +2 -0
  643. package/src/ts/dynamodb/schema.json +25 -2
  644. package/src/ts/dynamodb/smithy-connection/__snapshots__/generator.spec.ts.snap +3 -3
  645. package/src/ts/dynamodb/smithy-connection/generator.d.ts +3 -3
  646. package/src/ts/dynamodb/smithy-connection/generator.js +20 -22
  647. package/src/ts/dynamodb/smithy-connection/generator.js.map +1 -1
  648. package/src/ts/dynamodb/smithy-connection/schema.d.js +8 -0
  649. package/src/ts/dynamodb/smithy-connection/schema.d.js.map +1 -0
  650. package/src/ts/dynamodb/smithy-connection/schema.d.ts +1 -0
  651. package/src/ts/dynamodb/smithy-connection/schema.json +5 -0
  652. package/src/ts/dynamodb/trpc-connection/__snapshots__/generator.spec.ts.snap +3 -3
  653. package/src/ts/dynamodb/trpc-connection/generator.d.ts +3 -3
  654. package/src/ts/dynamodb/trpc-connection/generator.js +20 -22
  655. package/src/ts/dynamodb/trpc-connection/generator.js.map +1 -1
  656. package/src/ts/dynamodb/trpc-connection/schema.d.js +8 -0
  657. package/src/ts/dynamodb/trpc-connection/schema.d.js.map +1 -0
  658. package/src/ts/dynamodb/trpc-connection/schema.d.ts +1 -0
  659. package/src/ts/dynamodb/trpc-connection/schema.json +5 -0
  660. package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +8 -6
  661. package/src/ts/lambda-function/files/handler/__lambdaFunctionKebabCase__.ts.template +2 -1
  662. package/src/ts/lambda-function/generator.d.ts +3 -3
  663. package/src/ts/lambda-function/generator.js +60 -56
  664. package/src/ts/lambda-function/generator.js.map +1 -1
  665. package/src/ts/lambda-function/io.js +83 -52
  666. package/src/ts/lambda-function/io.js.map +1 -1
  667. package/src/ts/lambda-function/schema.d.js +6 -0
  668. package/src/ts/lambda-function/schema.d.js.map +1 -0
  669. package/src/ts/lambda-function/schema.d.ts +1 -0
  670. package/src/ts/lambda-function/schema.json +5 -0
  671. package/src/ts/lib/__snapshots__/generator.spec.ts.snap +98 -93
  672. package/src/ts/lib/__snapshots__/vitest.spec.ts.snap +24 -0
  673. package/src/ts/lib/biome.d.ts +7 -0
  674. package/src/ts/lib/biome.js +91 -0
  675. package/src/ts/lib/biome.js.map +1 -0
  676. package/src/ts/lib/generator.d.ts +3 -3
  677. package/src/ts/lib/generator.js +107 -108
  678. package/src/ts/lib/generator.js.map +1 -1
  679. package/src/ts/lib/grit/vitest-pass-with-no-tests.grit +1 -4
  680. package/src/ts/lib/schema.d.js +6 -0
  681. package/src/ts/lib/schema.d.js.map +1 -0
  682. package/src/ts/lib/schema.d.ts +1 -1
  683. package/src/ts/lib/schema.json +5 -0
  684. package/src/ts/lib/ts-project-utils.d.ts +12 -2
  685. package/src/ts/lib/ts-project-utils.js +95 -71
  686. package/src/ts/lib/ts-project-utils.js.map +1 -1
  687. package/src/ts/lib/types.d.ts +6 -0
  688. package/src/ts/lib/types.js +5 -2
  689. package/src/ts/lib/types.js.map +1 -1
  690. package/src/ts/lib/vitest.d.ts +2 -2
  691. package/src/ts/lib/vitest.js +30 -26
  692. package/src/ts/lib/vitest.js.map +1 -1
  693. package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +209 -42
  694. package/src/ts/mcp-server/files/Dockerfile.template +13 -2
  695. package/src/ts/mcp-server/generator.d.ts +3 -3
  696. package/src/ts/mcp-server/generator.js +183 -140
  697. package/src/ts/mcp-server/generator.js.map +1 -1
  698. package/src/ts/mcp-server/schema.d.js +6 -0
  699. package/src/ts/mcp-server/schema.d.js.map +1 -0
  700. package/src/ts/mcp-server/schema.d.ts +1 -0
  701. package/src/ts/mcp-server/schema.json +5 -0
  702. package/src/ts/nx-generator/__snapshots__/generator.spec.ts.snap +46 -26
  703. package/src/ts/nx-generator/files/common/schema.d.ts.template +1 -0
  704. package/src/ts/nx-generator/files/common/schema.json.template +5 -0
  705. package/src/ts/nx-generator/files/local/generator.ts.template +3 -3
  706. package/src/ts/nx-generator/files/nx-plugin-for-aws/generator/generator.ts.template +6 -7
  707. package/src/ts/nx-generator/generator.d.ts +2 -2
  708. package/src/ts/nx-generator/generator.js +118 -73
  709. package/src/ts/nx-generator/generator.js.map +1 -1
  710. package/src/ts/nx-generator/schema.d.js +6 -0
  711. package/src/ts/nx-generator/schema.d.js.map +1 -0
  712. package/src/ts/nx-generator/schema.d.ts +1 -0
  713. package/src/ts/nx-generator/schema.json +5 -0
  714. package/src/ts/nx-migration/files/migration.spec.ts.template +26 -0
  715. package/src/ts/nx-migration/files/migration.ts.template +61 -0
  716. package/src/ts/nx-migration/files/prompt.md.template +46 -0
  717. package/src/ts/nx-migration/generator.d.ts +24 -0
  718. package/src/ts/nx-migration/generator.js +122 -0
  719. package/src/ts/nx-migration/generator.js.map +1 -0
  720. package/src/ts/nx-migration/schema.d.js +6 -0
  721. package/src/ts/nx-migration/schema.d.js.map +1 -0
  722. package/src/ts/nx-migration/schema.d.ts +13 -0
  723. package/src/ts/nx-migration/schema.json +63 -0
  724. package/src/ts/nx-plugin/__snapshots__/generator.spec.ts.snap +36 -25
  725. package/src/ts/nx-plugin/files/mcp-server/resources/GENERAL_GUIDANCE.md.template +5 -6
  726. package/src/ts/nx-plugin/files/mcp-server/server.ts.template +5 -5
  727. package/src/ts/nx-plugin/files/mcp-server/tools/create-workspace-command.ts.template +2 -2
  728. package/src/ts/nx-plugin/files/mcp-server/tools/general-guidance.ts.template +1 -1
  729. package/src/ts/nx-plugin/files/mcp-server/tools/generator-guide.ts.template +2 -2
  730. package/src/ts/nx-plugin/files/mcp-server/tools/list-generators.ts.template +2 -2
  731. package/src/ts/nx-plugin/files/mcp-server/utils.ts.template +4 -4
  732. package/src/ts/nx-plugin/generator.d.ts +3 -3
  733. package/src/ts/nx-plugin/generator.js +61 -50
  734. package/src/ts/nx-plugin/generator.js.map +1 -1
  735. package/src/ts/nx-plugin/schema.d.js +9 -0
  736. package/src/ts/nx-plugin/schema.d.js.map +1 -0
  737. package/src/ts/nx-plugin/schema.json +5 -0
  738. package/src/ts/nx-plugin/utils.d.ts +21 -1
  739. package/src/ts/nx-plugin/utils.js +60 -51
  740. package/src/ts/nx-plugin/utils.js.map +1 -1
  741. package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +551 -642
  742. package/src/ts/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +6 -6
  743. package/src/ts/rdb/agent-connection/generator.d.ts +3 -3
  744. package/src/ts/rdb/agent-connection/generator.js +37 -39
  745. package/src/ts/rdb/agent-connection/generator.js.map +1 -1
  746. package/src/ts/rdb/agent-connection/schema.d.js +8 -0
  747. package/src/ts/rdb/agent-connection/schema.d.js.map +1 -0
  748. package/src/ts/rdb/agent-connection/schema.d.ts +1 -0
  749. package/src/ts/rdb/agent-connection/schema.json +5 -0
  750. package/src/ts/rdb/files/Dockerfile.template +19 -1
  751. package/src/ts/rdb/files/config.json.template +14 -0
  752. package/src/ts/rdb/files/prisma.config.ts.template +6 -5
  753. package/src/ts/rdb/files/src/create-db-user-handler.ts.template +9 -11
  754. package/src/ts/rdb/files/src/index.ts.template +1 -2
  755. package/src/ts/rdb/files/src/migration-handler.ts.template +5 -30
  756. package/src/ts/rdb/files/src/prisma.ts.template +33 -25
  757. package/src/ts/rdb/files/src/utils.ts.template +3 -0
  758. package/src/ts/rdb/generator.d.ts +3 -7
  759. package/src/ts/rdb/generator.js +177 -131
  760. package/src/ts/rdb/generator.js.map +1 -1
  761. package/src/ts/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +6 -6
  762. package/src/ts/rdb/mcp-server-connection/generator.d.ts +3 -3
  763. package/src/ts/rdb/mcp-server-connection/generator.js +35 -37
  764. package/src/ts/rdb/mcp-server-connection/generator.js.map +1 -1
  765. package/src/ts/rdb/mcp-server-connection/schema.d.js +8 -0
  766. package/src/ts/rdb/mcp-server-connection/schema.d.js.map +1 -0
  767. package/src/ts/rdb/mcp-server-connection/schema.d.ts +1 -0
  768. package/src/ts/rdb/mcp-server-connection/schema.json +5 -0
  769. package/src/ts/rdb/schema.d.js +6 -0
  770. package/src/ts/rdb/schema.d.js.map +1 -0
  771. package/src/ts/rdb/schema.d.ts +1 -0
  772. package/src/ts/rdb/schema.json +6 -1
  773. package/src/ts/rdb/smithy-connection/__snapshots__/generator.spec.ts.snap +3 -3
  774. package/src/ts/rdb/smithy-connection/generator.d.ts +3 -3
  775. package/src/ts/rdb/smithy-connection/generator.js +45 -43
  776. package/src/ts/rdb/smithy-connection/generator.js.map +1 -1
  777. package/src/ts/rdb/smithy-connection/schema.d.js +8 -0
  778. package/src/ts/rdb/smithy-connection/schema.d.js.map +1 -0
  779. package/src/ts/rdb/smithy-connection/schema.d.ts +1 -0
  780. package/src/ts/rdb/smithy-connection/schema.json +5 -0
  781. package/src/ts/rdb/trpc-connection/__snapshots__/generator.spec.ts.snap +3 -3
  782. package/src/ts/rdb/trpc-connection/generator.d.ts +3 -3
  783. package/src/ts/rdb/trpc-connection/generator.js +35 -31
  784. package/src/ts/rdb/trpc-connection/generator.js.map +1 -1
  785. package/src/ts/rdb/trpc-connection/schema.d.js +8 -0
  786. package/src/ts/rdb/trpc-connection/schema.d.js.map +1 -0
  787. package/src/ts/rdb/trpc-connection/schema.d.ts +1 -0
  788. package/src/ts/rdb/trpc-connection/schema.json +5 -0
  789. package/src/ts/rdb/utils.d.ts +1 -1
  790. package/src/ts/rdb/utils.js +9 -11
  791. package/src/ts/rdb/utils.js.map +1 -1
  792. package/src/ts/react-website/agui/files/common/src/hooks/useAgui__agentNameClassName__.tsx.template +1 -16
  793. package/src/ts/react-website/agui/generator.d.ts +1 -1
  794. package/src/ts/react-website/agui/generator.js +70 -62
  795. package/src/ts/react-website/agui/generator.js.map +1 -1
  796. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +1387 -813
  797. package/src/ts/react-website/app/generator.d.ts +4 -4
  798. package/src/ts/react-website/app/generator.js +241 -196
  799. package/src/ts/react-website/app/generator.js.map +1 -1
  800. package/src/ts/react-website/app/schema.d.js +6 -0
  801. package/src/ts/react-website/app/schema.d.js.map +1 -0
  802. package/src/ts/react-website/app/schema.d.ts +1 -1
  803. package/src/ts/react-website/app/schema.json +11 -6
  804. package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +139 -26
  805. package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +48 -12
  806. package/src/ts/react-website/cognito-auth/__snapshots__/generator.ux-provider.spec.ts.snap +0 -20
  807. package/src/ts/react-website/cognito-auth/files/app/components/CognitoAuth/index.tsx.template +2 -2
  808. package/src/ts/react-website/cognito-auth/generator.d.ts +4 -4
  809. package/src/ts/react-website/cognito-auth/generator.js +65 -63
  810. package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
  811. package/src/ts/react-website/cognito-auth/grit/cloudscape-auth-menu.grit +8 -6
  812. package/src/ts/react-website/cognito-auth/grit/cognito-auth-wrapper.grit +1 -1
  813. package/src/ts/react-website/cognito-auth/grit/none-auth-menu.grit +1 -0
  814. package/src/ts/react-website/cognito-auth/grit/shadcn-auth-menu.grit +3 -1
  815. package/src/ts/react-website/cognito-auth/grit/shadcn-state-declarations.grit +3 -1
  816. package/src/ts/react-website/cognito-auth/schema.d.js +6 -0
  817. package/src/ts/react-website/cognito-auth/schema.d.js.map +1 -0
  818. package/src/ts/react-website/cognito-auth/schema.d.ts +1 -0
  819. package/src/ts/react-website/cognito-auth/schema.json +5 -0
  820. package/src/ts/react-website/cognito-auth/utils.d.ts +1 -1
  821. package/src/ts/react-website/cognito-auth/utils.js +34 -32
  822. package/src/ts/react-website/cognito-auth/utils.js.map +1 -1
  823. package/src/ts/react-website/runtime-config/__snapshots__/generator.spec.ts.snap +2 -2
  824. package/src/ts/react-website/runtime-config/files/app/components/RuntimeConfig/index.tsx.template +2 -2
  825. package/src/ts/react-website/runtime-config/generator.d.ts +3 -3
  826. package/src/ts/react-website/runtime-config/generator.js +29 -31
  827. package/src/ts/react-website/runtime-config/generator.js.map +1 -1
  828. package/src/ts/react-website/runtime-config/schema.d.js +6 -0
  829. package/src/ts/react-website/runtime-config/schema.d.js.map +1 -0
  830. package/src/ts/react-website/runtime-config/schema.d.ts +1 -0
  831. package/src/ts/react-website/runtime-config/schema.json +5 -0
  832. package/src/ts/sync/generator.d.ts +3 -3
  833. package/src/ts/sync/generator.js +137 -60
  834. package/src/ts/sync/generator.js.map +1 -1
  835. package/src/ts/website/app/generator.d.ts +3 -3
  836. package/src/ts/website/app/generator.js +10 -10
  837. package/src/ts/website/app/generator.js.map +1 -1
  838. package/src/ts/website/app/schema.d.js +6 -0
  839. package/src/ts/website/app/schema.d.js.map +1 -0
  840. package/src/ts/website/app/schema.d.ts +1 -1
  841. package/src/ts/website/app/schema.json +11 -6
  842. package/src/ts/website/auth/generator.d.ts +4 -4
  843. package/src/ts/website/auth/generator.js +11 -10
  844. package/src/ts/website/auth/generator.js.map +1 -1
  845. package/src/ts/website/auth/schema.d.js +6 -0
  846. package/src/ts/website/auth/schema.d.js.map +1 -0
  847. package/src/ts/website/auth/schema.d.ts +1 -0
  848. package/src/ts/website/auth/schema.json +5 -0
  849. package/src/utils/__snapshots__/shared-constructs.spec.ts.snap +21 -0
  850. package/src/utils/agent-chat/agent-chat.d.ts +31 -0
  851. package/src/utils/agent-chat/agent-chat.js +31 -0
  852. package/src/utils/agent-chat/agent-chat.js.map +1 -0
  853. package/src/utils/agent-chat/files/a2a/chat.ts.template +33 -0
  854. package/src/utils/agent-chat/files/ag-ui/chat.ts.template +17 -0
  855. package/src/utils/agent-chat/files/common/agentcore.ts.template +81 -0
  856. package/src/utils/agent-chat/files/http-py/chat.ts.template +43 -0
  857. package/src/utils/agent-chat/files/http-ts/chat.ts.template +54 -0
  858. package/src/utils/agent-connection/agent-connection.d.ts +117 -25
  859. package/src/utils/agent-connection/agent-connection.js +467 -103
  860. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  861. package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client-config.ts.template +93 -0
  862. package/src/utils/agent-connection/files/core-auth/agentcore-endpoints.ts.template +37 -0
  863. package/src/utils/agent-connection/files/core-auth/agentcore-fetch.ts.template +54 -0
  864. package/src/utils/agent-connection/files/core-gateway/agentcore-gateway-mcp-transport.ts.template +41 -0
  865. package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-transport.ts.template +70 -0
  866. package/src/utils/agent-connection/files/core-runtime-config/runtime-config.ts.template +22 -32
  867. package/src/utils/agent-connection/files/core-shared/agentcore-transport.ts.template +39 -0
  868. package/src/utils/agent-connection/files/core-strands/a2a/agentcore-a2a-client-strands.ts.template +61 -0
  869. package/src/utils/agent-connection/files/core-strands/base/model-errors-strands.ts.template +36 -0
  870. package/src/utils/agent-connection/files/core-strands/base/tool-errors-strands.ts.template +22 -0
  871. 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
  872. package/src/utils/agent-connection/files/core-strands/gateway/agentcore-gateway-mcp-client-strands.ts.template +26 -0
  873. package/src/utils/agent-connection/files/core-strands/mcp/agentcore-mcp-client-strands.ts.template +27 -0
  874. package/src/utils/agent-connection/files/py-core-a2a/agentcore_a2a_client_config.py.template +43 -0
  875. package/src/utils/agent-connection/files/py-core-auth/agentcore_endpoints.py.template +47 -0
  876. package/src/utils/agent-connection/files/py-core-auth/auth/session.py.template +51 -0
  877. package/src/utils/agent-connection/files/py-core-gateway/agentcore_gateway_mcp_transport.py.template +28 -0
  878. package/src/utils/agent-connection/files/py-core-langchain/a2a/agentcore_a2a_client_langchain.py.template +99 -0
  879. package/src/utils/agent-connection/files/py-core-langchain/gateway/agentcore_gateway_mcp_client_langchain.py.template +57 -0
  880. package/src/utils/agent-connection/files/py-core-langchain/mcp/agentcore_mcp_client_langchain.py.template +64 -0
  881. package/src/utils/agent-connection/files/py-core-mcp/agentcore_mcp_transport.py.template +34 -0
  882. package/src/utils/agent-connection/files/py-core-runtime-config/runtime_config.py.template +5 -18
  883. package/src/utils/agent-connection/files/py-core-shared/agentcore_transport.py.template +40 -0
  884. package/src/utils/agent-connection/files/py-core-strands/a2a/agentcore_a2a_client_strands.py.template +66 -0
  885. package/src/utils/agent-connection/files/py-core-strands/base/model_errors_strands.py.template +40 -0
  886. package/src/utils/agent-connection/files/py-core-strands/gateway/agentcore_gateway_mcp_client_strands.py.template +22 -0
  887. package/src/utils/agent-connection/files/py-core-strands/mcp/agentcore_mcp_client_strands.py.template +30 -0
  888. package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +12 -3
  889. package/src/utils/agent-core-constructs/agent-core-constructs.js +104 -38
  890. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  891. package/src/utils/agent-core-constructs/files/cdk/app/agent-core/__nameKebabCase__/__nameKebabCase__.ts.template +31 -4
  892. package/src/utils/agent-core-constructs/files/cdk/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.ts.template +85 -0
  893. package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +497 -0
  894. package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/readiness-probe/index.js.template +55 -0
  895. package/src/utils/agent-core-constructs/files/terraform/app/agent-core/__nameKebabCase__/__nameKebabCase__.tf.template +32 -0
  896. package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.tf.template +488 -0
  897. package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/render-cedar.cjs.template +13 -0
  898. package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +151 -13
  899. package/src/utils/agent-core-constructs/files/terraform/core/agentcore-gateway/gateway.tf.template +14 -0
  900. package/src/utils/api-constructs/api-constructs.d.ts +2 -2
  901. package/src/utils/api-constructs/api-constructs.js +50 -31
  902. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  903. package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +20 -15
  904. package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +24 -16
  905. package/src/utils/api-constructs/files/cdk/core/api/http/http-api.ts.template +26 -9
  906. package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account/index.js.template +70 -0
  907. package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account.ts.template +82 -0
  908. package/src/utils/api-constructs/files/cdk/core/api/rest/rest-api.ts.template +54 -18
  909. package/src/utils/api-constructs/files/cdk/core/api/trpc/trpc-utils.ts.template +1 -1
  910. package/src/utils/api-constructs/files/cdk/core/api/utils/utils.ts.template +61 -7
  911. package/src/utils/api-constructs/files/terraform/app/apis/http/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +101 -12
  912. package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +194 -8
  913. package/src/utils/api-constructs/files/terraform/core/api/http/http-api/http-api.tf.template +1 -1
  914. package/src/utils/api-constructs/files/terraform/core/api/rest/api-gateway-account/api-gateway-account.tf.template +83 -0
  915. package/src/utils/api-constructs/files/terraform/core/api/rest/rest-api/rest-api.tf.template +5 -11
  916. package/src/utils/api-constructs/open-api-metadata.d.ts +2 -2
  917. package/src/utils/api-constructs/open-api-metadata.js +22 -22
  918. package/src/utils/api-constructs/open-api-metadata.js.map +1 -1
  919. package/src/utils/ast/website.d.ts +5 -1
  920. package/src/utils/ast/website.js +18 -20
  921. package/src/utils/ast/website.js.map +1 -1
  922. package/src/utils/ast.d.ts +5 -1
  923. package/src/utils/ast.js +107 -89
  924. package/src/utils/ast.js.map +1 -1
  925. package/src/utils/base-tsconfig.d.ts +30 -0
  926. package/src/utils/base-tsconfig.js +32 -0
  927. package/src/utils/base-tsconfig.js.map +1 -0
  928. package/src/utils/bundle/bundle.d.ts +1 -1
  929. package/src/utils/bundle/bundle.js +51 -47
  930. package/src/utils/bundle/bundle.js.map +1 -1
  931. package/src/utils/commands.d.ts +15 -5
  932. package/src/utils/commands.js +87 -28
  933. package/src/utils/commands.js.map +1 -1
  934. package/src/utils/config/index.d.ts +21 -5
  935. package/src/utils/config/index.js +5 -4
  936. package/src/utils/config/index.js.map +1 -1
  937. package/src/utils/config/utils.d.ts +5 -4
  938. package/src/utils/config/utils.js +50 -59
  939. package/src/utils/config/utils.js.map +1 -1
  940. package/src/utils/connection/open-api/files/components/__apiNameClassName__Provider.tsx.template +1 -1
  941. package/src/utils/connection/open-api/react.d.ts +6 -6
  942. package/src/utils/connection/open-api/react.js +82 -77
  943. package/src/utils/connection/open-api/react.js.map +1 -1
  944. package/src/utils/containers.d.ts +1 -1
  945. package/src/utils/containers.js +22 -23
  946. package/src/utils/containers.js.map +1 -1
  947. package/src/utils/dcr-proxy-constructs/dcr-proxy-constructs.d.ts +38 -0
  948. package/src/utils/dcr-proxy-constructs/dcr-proxy-constructs.js +93 -0
  949. package/src/utils/dcr-proxy-constructs/dcr-proxy-constructs.js.map +1 -0
  950. package/src/utils/dcr-proxy-constructs/files/cdk/app/dcr-proxies/__nameKebabCase__/__nameKebabCase__.ts.template +227 -0
  951. package/src/utils/dcr-proxy-constructs/files/project/src/handlers/authorization-server-metadata.ts.template +39 -0
  952. package/src/utils/dcr-proxy-constructs/files/project/src/handlers/authorize.ts.template +26 -0
  953. package/src/utils/dcr-proxy-constructs/files/project/src/handlers/mcp-proxy.ts.template +89 -0
  954. package/src/utils/dcr-proxy-constructs/files/project/src/handlers/protected-resource-metadata.ts.template +13 -0
  955. package/src/utils/dcr-proxy-constructs/files/project/src/handlers/register.ts.template +70 -0
  956. package/src/utils/dcr-proxy-constructs/files/project/src/handlers/token.ts.template +75 -0
  957. package/src/utils/dcr-proxy-constructs/files/terraform/app/dcr-proxies/__nameKebabCase__/__nameKebabCase__.tf.template +410 -0
  958. package/src/utils/dependencies.d.ts +18 -0
  959. package/src/utils/dependencies.js +206 -0
  960. package/src/utils/dependencies.js.map +1 -0
  961. package/src/utils/docker.d.ts +53 -0
  962. package/src/utils/docker.js +92 -0
  963. package/src/utils/docker.js.map +1 -0
  964. package/src/utils/dynamodb-constructs/dynamodb-constructs.d.ts +3 -3
  965. package/src/utils/dynamodb-constructs/dynamodb-constructs.js +39 -41
  966. package/src/utils/dynamodb-constructs/dynamodb-constructs.js.map +1 -1
  967. package/src/utils/dynamodb-constructs/files/cdk/app/dynamodb/__nameKebabCase__.ts.template +18 -5
  968. package/src/utils/dynamodb-constructs/files/cdk/core/dynamodb.ts.template +1 -1
  969. package/src/utils/dynamodb-constructs/files/terraform/app/dynamodb/__nameKebabCase__/__nameKebabCase__.tf.template +24 -17
  970. package/src/utils/dynamodb-constructs/files/terraform/core/dynamodb/dynamodb.tf.template +1 -1
  971. package/src/utils/files/common/constructs/src/core/cloudfront.ts.template +14 -0
  972. package/src/utils/files/common/constructs/src/core/index.ts.template +5 -4
  973. package/src/utils/files/common/constructs/src/index.ts.template +2 -2
  974. package/src/utils/files/common/infra-config/src/index.ts.template +3 -3
  975. package/src/utils/files/common/infra-config/src/resolve-stage.ts.template +2 -2
  976. package/src/utils/files/common/infra-config/src/stages.config.ts.template +1 -1
  977. package/src/{ts/dynamodb/files/scripts → utils/files/common/scripts/src/dynamodb}/create-local-table.ts.template +65 -31
  978. package/src/utils/files/common/scripts/src/dynamodb/pull-image.ts.template +13 -0
  979. package/src/utils/files/common/scripts/src/dynamodb/start-container.ts.template +104 -0
  980. package/src/utils/files/common/scripts/src/infra/infra-deploy.ts.template +2 -0
  981. package/src/utils/files/common/scripts/src/infra/infra-destroy.ts.template +2 -0
  982. package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/cdk-command.ts.template +6 -3
  983. package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/run.ts.template +3 -3
  984. package/src/utils/files/common/scripts/src/rdb/mysql/wait-for-mysql-db.ts.template +32 -0
  985. package/src/utils/files/common/scripts/src/rdb/postgres/wait-for-postgres-db.ts.template +32 -0
  986. package/src/utils/files/common/scripts/src/rdb/shared/pull-image.ts.template +16 -0
  987. package/src/utils/files/common/scripts/src/rdb/shared/start-container.ts.template +115 -0
  988. package/src/utils/files/common/shadcn/readme/README.md.template +3 -3
  989. package/src/utils/files/common/shadcn/src/index.ts.template +2 -2
  990. package/src/utils/files/shadcn/components.json.template +1 -1
  991. package/src/utils/files/terraform/src/core/asset-bucket/asset-bucket.tf.template +63 -72
  992. package/src/utils/files/terraform/src/core/runtime-config/appconfig/appconfig.tf.template +1 -1
  993. package/src/utils/files/terraform/src/core/runtime-config/appconfig-deployment/appconfig-deployment.tf.template +12 -6
  994. package/src/utils/files/terraform/src/core/runtime-config/entry/entry.tf.template +1 -1
  995. package/src/utils/files/terraform/src/core/runtime-config/read/read.tf.template +9 -4
  996. package/src/utils/files/website/hooks/sigv4/useSigV4.tsx.template +1 -1
  997. package/src/utils/format.d.ts +70 -2
  998. package/src/utils/format.js +326 -108
  999. package/src/utils/format.js.map +1 -1
  1000. package/src/utils/fs.d.ts +1 -1
  1001. package/src/utils/fs.js +14 -13
  1002. package/src/utils/fs.js.map +1 -1
  1003. package/src/utils/function-constructs/files/cdk/app/lambda-functions/__nameKebabCase__.ts.template +1 -1
  1004. package/src/utils/function-constructs/files/terraform/app/lambda-functions/__nameKebabCase__/__nameKebabCase__.tf.template +2 -2
  1005. package/src/utils/function-constructs/function-constructs.d.ts +2 -2
  1006. package/src/utils/function-constructs/function-constructs.js +22 -25
  1007. package/src/utils/function-constructs/function-constructs.js.map +1 -1
  1008. package/src/utils/generators.d.ts +4 -0
  1009. package/src/utils/generators.js +18 -20
  1010. package/src/utils/generators.js.map +1 -1
  1011. package/src/utils/git.d.ts +1 -1
  1012. package/src/utils/git.js +19 -34
  1013. package/src/utils/git.js.map +1 -1
  1014. package/src/utils/iac-providers.js +5 -5
  1015. package/src/utils/iac-providers.js.map +1 -1
  1016. package/src/utils/iac.d.ts +1 -1
  1017. package/src/utils/iac.js +12 -14
  1018. package/src/utils/iac.js.map +1 -1
  1019. package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +131 -24
  1020. package/src/utils/identity-constructs/files/terraform/core/user-identity/add-callback-url/add-callback-url.tf.template +28 -9
  1021. package/src/utils/identity-constructs/files/terraform/core/user-identity/identity/identity.tf.template +106 -6
  1022. package/src/utils/identity-constructs/files/terraform/core/user-identity/main.tf.template +7 -0
  1023. package/src/utils/identity-constructs/identity-constructs.d.ts +2 -2
  1024. package/src/utils/identity-constructs/identity-constructs.js +42 -31
  1025. package/src/utils/identity-constructs/identity-constructs.js.map +1 -1
  1026. package/src/utils/init.d.ts +59 -0
  1027. package/src/utils/init.js +282 -0
  1028. package/src/utils/init.js.map +1 -0
  1029. package/src/utils/install.d.ts +32 -0
  1030. package/src/utils/install.js +58 -0
  1031. package/src/utils/install.js.map +1 -0
  1032. package/src/utils/js.d.ts +4 -0
  1033. package/src/utils/js.js +27 -20
  1034. package/src/utils/js.js.map +1 -1
  1035. package/src/utils/mcp.d.ts +10 -1
  1036. package/src/utils/mcp.js +42 -41
  1037. package/src/utils/mcp.js.map +1 -1
  1038. package/src/utils/metrics.d.ts +9 -3
  1039. package/src/utils/metrics.js +61 -46
  1040. package/src/utils/metrics.js.map +1 -1
  1041. package/src/utils/migration-versions.d.ts +95 -0
  1042. package/src/utils/migration-versions.js +128 -0
  1043. package/src/utils/migration-versions.js.map +1 -0
  1044. package/src/utils/mock-project-graph.js +8 -12
  1045. package/src/utils/mock-project-graph.js.map +1 -1
  1046. package/src/utils/module-format.d.ts +25 -0
  1047. package/src/utils/module-format.js +45 -0
  1048. package/src/utils/module-format.js.map +1 -0
  1049. package/src/utils/names.d.ts +22 -0
  1050. package/src/utils/names.js +44 -48
  1051. package/src/utils/names.js.map +1 -1
  1052. package/src/utils/npm-scope.d.ts +1 -5
  1053. package/src/utils/npm-scope.js +7 -20
  1054. package/src/utils/npm-scope.js.map +1 -1
  1055. package/src/utils/nx.d.ts +57 -4
  1056. package/src/utils/nx.js +192 -75
  1057. package/src/utils/nx.js.map +1 -1
  1058. package/src/utils/nxlv-python.d.ts +1 -1
  1059. package/src/utils/nxlv-python.js +27 -15
  1060. package/src/utils/nxlv-python.js.map +1 -1
  1061. package/src/utils/object.js +5 -11
  1062. package/src/utils/object.js.map +1 -1
  1063. package/src/utils/paths.d.ts +1 -1
  1064. package/src/utils/paths.js +11 -15
  1065. package/src/utils/paths.js.map +1 -1
  1066. package/src/utils/pkg-manager.js +4 -9
  1067. package/src/utils/pkg-manager.js.map +1 -1
  1068. package/src/utils/pnpm-workspace.d.ts +1 -12
  1069. package/src/utils/pnpm-workspace.js +16 -43
  1070. package/src/utils/pnpm-workspace.js.map +1 -1
  1071. package/src/utils/port.d.ts +29 -7
  1072. package/src/utils/port.js +67 -28
  1073. package/src/utils/port.js.map +1 -1
  1074. package/src/utils/project-package-json.d.ts +39 -0
  1075. package/src/utils/project-package-json.js +119 -0
  1076. package/src/utils/project-package-json.js.map +1 -0
  1077. package/src/utils/py.d.ts +16 -3
  1078. package/src/utils/py.js +72 -47
  1079. package/src/utils/py.js.map +1 -1
  1080. package/src/utils/rdb-constructs/files/cdk/app/dbs/__nameKebabCase__.ts.template +72 -18
  1081. package/src/utils/rdb-constructs/files/cdk/core/rdb/aurora.ts.template +112 -88
  1082. package/src/utils/rdb-constructs/files/terraform/app/dbs/__nameKebabCase__/__nameKebabCase__.tf.template +127 -53
  1083. package/src/utils/rdb-constructs/files/terraform/core/rdb/aurora/aurora.tf.template +60 -53
  1084. package/src/utils/rdb-constructs/rdb-constructs.d.ts +15 -4
  1085. package/src/utils/rdb-constructs/rdb-constructs.js +38 -41
  1086. package/src/utils/rdb-constructs/rdb-constructs.js.map +1 -1
  1087. package/src/utils/ruff.d.ts +59 -0
  1088. package/src/utils/ruff.js +140 -0
  1089. package/src/utils/ruff.js.map +1 -0
  1090. package/src/utils/shared-constructs-constants.d.ts +1 -0
  1091. package/src/utils/shared-constructs-constants.js +16 -15
  1092. package/src/utils/shared-constructs-constants.js.map +1 -1
  1093. package/src/utils/shared-constructs.d.ts +2 -2
  1094. package/src/utils/shared-constructs.js +61 -67
  1095. package/src/utils/shared-constructs.js.map +1 -1
  1096. package/src/utils/shared-dynamodb-scripts.d.ts +11 -0
  1097. package/src/utils/shared-dynamodb-scripts.js +27 -0
  1098. package/src/utils/shared-dynamodb-scripts.js.map +1 -0
  1099. package/src/utils/shared-infra-config.d.ts +1 -1
  1100. package/src/utils/shared-infra-config.js +31 -30
  1101. package/src/utils/shared-infra-config.js.map +1 -1
  1102. package/src/utils/shared-infra-scripts.d.ts +11 -0
  1103. package/src/utils/shared-infra-scripts.js +43 -0
  1104. package/src/utils/shared-infra-scripts.js.map +1 -0
  1105. package/src/utils/shared-rdb-scripts.d.ts +16 -0
  1106. package/src/utils/shared-rdb-scripts.js +45 -0
  1107. package/src/utils/shared-rdb-scripts.js.map +1 -0
  1108. package/src/utils/shared-scripts.d.ts +2 -5
  1109. package/src/utils/shared-scripts.js +12 -38
  1110. package/src/utils/shared-scripts.js.map +1 -1
  1111. package/src/utils/shared-shadcn.d.ts +1 -1
  1112. package/src/utils/shared-shadcn.js +69 -72
  1113. package/src/utils/shared-shadcn.js.map +1 -1
  1114. package/src/utils/test-git.d.ts +39 -0
  1115. package/src/utils/test-git.js +117 -0
  1116. package/src/utils/test-git.js.map +1 -0
  1117. package/src/utils/test.d.ts +15 -1
  1118. package/src/utils/test.js +46 -23
  1119. package/src/utils/test.js.map +1 -1
  1120. package/src/utils/toml.d.ts +6 -1
  1121. package/src/utils/toml.js +20 -14
  1122. package/src/utils/toml.js.map +1 -1
  1123. package/src/utils/versions.d.ts +161 -99
  1124. package/src/utils/versions.js +177 -116
  1125. package/src/utils/versions.js.map +1 -1
  1126. package/src/utils/website-constructs/files/cdk/app/static-websites/__websiteNameKebabCase__.ts.template +2 -2
  1127. package/src/utils/website-constructs/files/cdk/core/static-website.ts.template +203 -41
  1128. package/src/utils/website-constructs/files/terraform/app/static-websites/__websiteNameKebabCase__/__websiteNameKebabCase__.tf.template +1 -1
  1129. package/src/utils/website-constructs/files/terraform/core/static-website/static-website.tf.template +145 -93
  1130. package/src/utils/website-constructs/website-constructs.d.ts +2 -2
  1131. package/src/utils/website-constructs/website-constructs.js +38 -30
  1132. package/src/utils/website-constructs/website-constructs.js.map +1 -1
  1133. package/bin/aws-nx-mcp.d.ts +0 -2
  1134. package/bin/aws-nx-mcp.js +0 -17
  1135. package/bin/aws-nx-mcp.js.map +0 -1
  1136. package/sdk/connection.d.ts +0 -6
  1137. package/sdk/connection.js +0 -10
  1138. package/sdk/connection.js.map +0 -1
  1139. package/sdk/license.d.ts +0 -8
  1140. package/sdk/license.js +0 -13
  1141. package/sdk/license.js.map +0 -1
  1142. package/sdk/open-api.d.ts +0 -10
  1143. package/sdk/open-api.js +0 -15
  1144. package/sdk/open-api.js.map +0 -1
  1145. package/sdk/py.d.ts +0 -14
  1146. package/sdk/py.js +0 -18
  1147. package/sdk/py.js.map +0 -1
  1148. package/sdk/terraform.d.ts +0 -6
  1149. package/sdk/terraform.js +0 -11
  1150. package/sdk/terraform.js.map +0 -1
  1151. package/sdk/ts.d.ts +0 -29
  1152. package/sdk/ts.js +0 -47
  1153. package/sdk/ts.js.map +0 -1
  1154. package/sdk/utils/ast.js +0 -12
  1155. package/sdk/utils/ast.js.map +0 -1
  1156. package/sdk/utils/format.js +0 -10
  1157. package/sdk/utils/format.js.map +0 -1
  1158. package/sdk/utils/test.js +0 -10
  1159. package/sdk/utils/test.js.map +0 -1
  1160. package/src/connection/agent-serve-local.js +0 -48
  1161. package/src/connection/agent-serve-local.js.map +0 -1
  1162. package/src/connection/serve-local.d.ts +0 -15
  1163. package/src/connection/serve-local.js +0 -41
  1164. package/src/connection/serve-local.js.map +0 -1
  1165. package/src/py/agent/a2a-connection/files/agent-connection/app/__targetAgentSnakeCase___client.py.template +0 -22
  1166. package/src/py/agent/mcp-connection/files/agent-connection/app/__mcpServerSnakeCase___client.py.template +0 -22
  1167. package/src/py/agent/react-connection/serve-local.js +0 -30
  1168. package/src/py/agent/react-connection/serve-local.js.map +0 -1
  1169. package/src/py/agent/scripts/http/chat.ts.template +0 -38
  1170. package/src/ts/agent/a2a-connection/files/agent-connection/app/__targetAgentKebabCase__-client.ts.template +0 -19
  1171. package/src/ts/agent/mcp-connection/files/agent-connection/app/__mcpServerKebabCase__-client.ts.template +0 -19
  1172. package/src/ts/agent/react-connection/serve-local.d.ts +0 -13
  1173. package/src/ts/agent/react-connection/serve-local.js +0 -19
  1174. package/src/ts/agent/react-connection/serve-local.js.map +0 -1
  1175. package/src/ts/agent/scripts/http/chat.ts.template +0 -35
  1176. package/src/ts/dynamodb/files/scripts/pull-image.ts.template +0 -15
  1177. package/src/ts/dynamodb/files/scripts/start-container.ts.template +0 -81
  1178. package/src/ts/dynamodb/files/src/constants.ts.template +0 -9
  1179. package/src/ts/dynamodb/files/src/gsi.ts.template +0 -14
  1180. package/src/ts/lib/eslint.d.ts +0 -14
  1181. package/src/ts/lib/eslint.js +0 -90
  1182. package/src/ts/lib/eslint.js.map +0 -1
  1183. package/src/ts/lib/grit/eslint-dependency-checks-warn.grit +0 -1
  1184. package/src/ts/rdb/files/scripts/pull-image.ts.template +0 -15
  1185. package/src/ts/rdb/files/scripts/start-container.ts.template +0 -84
  1186. package/src/ts/rdb/files/scripts/wait-for-db.ts.template +0 -55
  1187. package/src/ts/rdb/files/src/constants.ts.template +0 -8
  1188. package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client.ts.template +0 -123
  1189. package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-client.ts.template +0 -128
  1190. package/src/utils/agent-connection/files/py-core-a2a/agentcore_a2a_client.py.template +0 -120
  1191. package/src/utils/agent-connection/files/py-core-mcp/agentcore_mcp_client.py.template +0 -89
  1192. package/src/utils/files/common/scripts/src/infra-deploy.ts.template +0 -2
  1193. package/src/utils/files/common/scripts/src/infra-destroy.ts.template +0 -2
  1194. package/src/utils/files/terraform/scripts/reset-runtime-config.ts.template +0 -25
  1195. /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
  1196. /package/src/utils/files/common/scripts/src/{index.ts.template → infra/index.ts.template} +0 -0
  1197. /package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/credentials.ts.template +0 -0
  1198. /package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/stage-parser.ts.template +0 -0
@@ -32,7 +32,7 @@ export default defineConfig(() => ({
32
32
  // plugins: [],
33
33
  // },
34
34
  build: {
35
- outDir: '../dist/test-app',
35
+ outDir: '../dist/test-app/bundle',
36
36
  emptyOutDir: true,
37
37
  reportCompressedSize: true,
38
38
  commonjsOptions: {
@@ -40,6 +40,7 @@ export default defineConfig(() => ({
40
40
  },
41
41
  },
42
42
  test: {
43
+ passWithNoTests: true,
43
44
  name: '@proj/test-app',
44
45
  watch: false,
45
46
  globals: true,
@@ -50,9 +51,8 @@ export default defineConfig(() => ({
50
51
  reportsDirectory: './test-output/vitest/coverage',
51
52
  provider: 'v8' as const,
52
53
  },
53
- passWithNoTests: true,
54
54
  },
55
- resolve: { tsconfigPaths: true },
55
+ resolve: { tsconfigPaths: true, dedupe: ['react', 'react-dom'] },
56
56
  define: { global: {} },
57
57
  }));
58
58
  "
@@ -88,7 +88,7 @@ export default defineConfig(() => ({
88
88
  // plugins: [],
89
89
  // },
90
90
  build: {
91
- outDir: '../dist/test-app',
91
+ outDir: '../dist/test-app/bundle',
92
92
  emptyOutDir: true,
93
93
  reportCompressedSize: true,
94
94
  commonjsOptions: {
@@ -96,6 +96,7 @@ export default defineConfig(() => ({
96
96
  },
97
97
  },
98
98
  test: {
99
+ passWithNoTests: true,
99
100
  name: '@proj/test-app',
100
101
  watch: false,
101
102
  globals: true,
@@ -106,9 +107,8 @@ export default defineConfig(() => ({
106
107
  reportsDirectory: './test-output/vitest/coverage',
107
108
  provider: 'v8' as const,
108
109
  },
109
- passWithNoTests: true,
110
110
  },
111
- resolve: { tsconfigPaths: true },
111
+ resolve: { tsconfigPaths: true, dedupe: ['react', 'react-dom'] },
112
112
  define: { global: {} },
113
113
  }));
114
114
  "
@@ -131,12 +131,12 @@ exports[`react-website generator > TailwindCSS integration > terraform iac > sho
131
131
  required_providers {
132
132
  aws = {
133
133
  source = "hashicorp/aws"
134
- version = "~> 6.0"
134
+ version = "6.55.0"
135
135
  configuration_aliases = [aws.us_east_1]
136
136
  }
137
137
  random = {
138
138
  source = "hashicorp/random"
139
- version = "~> 3.1"
139
+ version = "3.9.0"
140
140
  }
141
141
  }
142
142
  }
@@ -152,6 +152,31 @@ variable "website_file_path" {
152
152
  type = string
153
153
  }
154
154
 
155
+ variable "custom_domain_names" {
156
+ description = "Custom domain names (aliases) for the CloudFront distribution. Requires acm_certificate_arn."
157
+ type = list(string)
158
+ default = []
159
+ }
160
+
161
+ variable "acm_certificate_arn" {
162
+ description = "ARN of an ACM certificate (in us-east-1) for the custom domain names. When set, viewers are required to use TLS 1.2 or later."
163
+ type = string
164
+ default = null
165
+ }
166
+
167
+ # Content-Security-Policy enforced on all responses. Restricts scripts and
168
+ # framing to mitigate XSS and clickjacking, while permitting HTTPS/WSS calls
169
+ # (connect-src) to AWS service endpoints such as API Gateway, Cognito and
170
+ # Bedrock AgentCore which are only known at deploy time. Edit this to tighten
171
+ # connect-src to your specific origins once they are known.
172
+ locals {
173
+ content_security_policy = "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' https: wss:; object-src 'none'; base-uri 'self'; frame-ancestors 'none'"
174
+
175
+ # Delivery source/destination names have a 60 character maximum. Truncate the
176
+ # website name so the longest delivery name stays within the limit.
177
+ access_logs_name_prefix = substr(lower(var.website_name), 0, 16)
178
+ }
179
+
155
180
 
156
181
  # Data sources
157
182
  data "aws_caller_identity" "current" {}
@@ -188,6 +213,26 @@ resource "aws_kms_key" "website_key" {
188
213
  ]
189
214
  Resource = "*"
190
215
  },
216
+ {
217
+ Sid = "AllowCloudWatchLogs"
218
+ Effect = "Allow"
219
+ Principal = {
220
+ Service = "logs.\${data.aws_region.current.region}.amazonaws.com"
221
+ }
222
+ Action = [
223
+ "kms:Encrypt",
224
+ "kms:Decrypt",
225
+ "kms:ReEncrypt*",
226
+ "kms:GenerateDataKey*",
227
+ "kms:DescribeKey"
228
+ ]
229
+ Resource = "*"
230
+ Condition = {
231
+ ArnLike = {
232
+ "kms:EncryptionContext:aws:logs:arn" = "arn:aws:logs:\${data.aws_region.current.region}:\${data.aws_caller_identity.current.account_id}:log-group:*"
233
+ }
234
+ }
235
+ },
191
236
  {
192
237
  Sid = "AllowCloudFrontServicePrincipalSSE-KMS"
193
238
  Effect = "Allow"
@@ -219,18 +264,12 @@ resource "aws_kms_alias" "website_key_alias" {
219
264
  target_key_id = aws_kms_key.website_key.key_id
220
265
  }
221
266
 
222
- # Access Logs Bucket
223
- resource "aws_s3_bucket" "access_logs" {
224
- #checkov:skip=CKV2_AWS_61:Lifecycle configuration not required for access logs bucket
225
- #checkov:skip=CKV_AWS_144:Cross-region replication not required for access logs
226
- #checkov:skip=CKV2_AWS_62:Event notifications not required for access logs bucket
227
- #checkov:skip=CKV_AWS_21:Versioning disabled for access logs to reduce storage costs
228
- bucket = "\${lower(var.website_name)}-access-logs-\${random_id.bucket_suffix.hex}"
229
- force_destroy = true
230
-
231
- tags = {
232
- Name = "\${lower(var.website_name)}-access-logs"
233
- }
267
+ # CloudWatch log group receiving S3 server access logs for the website and
268
+ # distribution log buckets.
269
+ resource "aws_cloudwatch_log_group" "access_logs" {
270
+ name = "/aws/s3/\${lower(var.website_name)}-access-logs-\${random_id.bucket_suffix.hex}"
271
+ retention_in_days = 365
272
+ kms_key_id = aws_kms_key.website_key.arn
234
273
  }
235
274
 
236
275
  resource "random_id" "unique_suffix" {
@@ -241,63 +280,12 @@ resource "random_id" "bucket_suffix" {
241
280
  byte_length = 8
242
281
  }
243
282
 
244
- resource "aws_s3_bucket_versioning" "access_logs_versioning" {
245
- bucket = aws_s3_bucket.access_logs.id
246
- versioning_configuration {
247
- status = "Disabled"
248
- }
249
- }
250
-
251
- resource "aws_s3_bucket_server_side_encryption_configuration" "access_logs_encryption" {
252
- bucket = aws_s3_bucket.access_logs.id
253
-
254
- rule {
255
- apply_server_side_encryption_by_default {
256
- kms_master_key_id = aws_kms_key.website_key.arn
257
- sse_algorithm = "aws:kms"
258
- }
259
- }
260
- }
261
-
262
- resource "aws_s3_bucket_public_access_block" "access_logs_pab" {
263
- bucket = aws_s3_bucket.access_logs.id
264
-
265
- block_public_acls = true
266
- block_public_policy = true
267
- ignore_public_acls = true
268
- restrict_public_buckets = true
269
- }
270
-
271
- resource "aws_s3_bucket_policy" "access_logs_ssl_policy" {
272
- bucket = aws_s3_bucket.access_logs.id
273
-
274
- policy = jsonencode({
275
- Version = "2012-10-17"
276
- Statement = [
277
- {
278
- Sid = "DenyInsecureConnections"
279
- Effect = "Deny"
280
- Principal = "*"
281
- Action = "s3:*"
282
- Resource = [
283
- aws_s3_bucket.access_logs.arn,
284
- "\${aws_s3_bucket.access_logs.arn}/*"
285
- ]
286
- Condition = {
287
- Bool = {
288
- "aws:SecureTransport" = "false"
289
- }
290
- }
291
- }
292
- ]
293
- })
294
- }
295
-
296
283
  # Website Bucket
297
284
  resource "aws_s3_bucket" "website" {
298
285
  #checkov:skip=CKV2_AWS_61:Lifecycle configuration not required for static website content
299
286
  #checkov:skip=CKV_AWS_144:Cross-region replication not required for static website
300
287
  #checkov:skip=CKV2_AWS_62:Event notifications not required for static website bucket
288
+ #checkov:skip=CKV_AWS_18:Server access logs are delivered to CloudWatch Logs (see aws_cloudwatch_log_delivery.website)
301
289
  bucket = "\${lower(var.website_name)}-website-\${random_id.bucket_suffix.hex}"
302
290
  force_destroy = true
303
291
 
@@ -341,20 +329,35 @@ resource "aws_s3_bucket_ownership_controls" "website_ownership" {
341
329
  }
342
330
  }
343
331
 
344
- resource "aws_s3_bucket_logging" "website_logging" {
345
- bucket = aws_s3_bucket.website.id
332
+ # Deliver the website bucket's server access logs to CloudWatch Logs.
333
+ resource "aws_cloudwatch_log_delivery_source" "website" {
334
+ name = "\${local.access_logs_name_prefix}-website-logs-\${random_id.bucket_suffix.hex}"
335
+ log_type = "S3_SERVER_ACCESS_LOGS"
336
+ resource_arn = aws_s3_bucket.website.arn
337
+ }
338
+
339
+ resource "aws_cloudwatch_log_delivery_destination" "access_logs" {
340
+ name = "\${local.access_logs_name_prefix}-access-logs-\${random_id.bucket_suffix.hex}"
341
+
342
+ delivery_destination_configuration {
343
+ destination_resource_arn = aws_cloudwatch_log_group.access_logs.arn
344
+ }
345
+ }
346
346
 
347
- target_bucket = aws_s3_bucket.access_logs.id
348
- target_prefix = "website-access-logs/"
347
+ resource "aws_cloudwatch_log_delivery" "website" {
348
+ delivery_source_name = aws_cloudwatch_log_delivery_source.website.name
349
+ delivery_destination_arn = aws_cloudwatch_log_delivery_destination.access_logs.arn
349
350
  }
350
351
 
351
352
 
352
- # Distribution Log Bucket
353
+ # Distribution Log Bucket — holds CloudFront standard access logs (CloudFront
354
+ # delivers only to S3). Its own S3 server access logs go to CloudWatch Logs.
353
355
  resource "aws_s3_bucket" "distribution_logs" {
354
356
  #checkov:skip=CKV2_AWS_61:Lifecycle configuration not required for CloudFront logs
355
357
  #checkov:skip=CKV_AWS_144:Cross-region replication not required for CloudFront logs
356
358
  #checkov:skip=CKV2_AWS_62:Event notifications not required for CloudFront logs bucket
357
359
  #checkov:skip=CKV_AWS_21:Versioning not required for CloudFront access logs
360
+ #checkov:skip=CKV_AWS_18:Server access logs are delivered to CloudWatch Logs (see aws_cloudwatch_log_delivery.distribution_logs)
358
361
  bucket = "\${lower(var.website_name)}-distribution-logs-\${random_id.bucket_suffix.hex}"
359
362
  force_destroy = true
360
363
 
@@ -400,11 +403,16 @@ resource "aws_s3_bucket_acl" "distribution_logs_acl" {
400
403
  depends_on = [aws_s3_bucket_ownership_controls.distribution_logs_ownership]
401
404
  }
402
405
 
403
- resource "aws_s3_bucket_logging" "distribution_logs_logging" {
404
- bucket = aws_s3_bucket.distribution_logs.id
406
+ # Deliver the distribution log bucket's server access logs to CloudWatch Logs.
407
+ resource "aws_cloudwatch_log_delivery_source" "distribution_logs" {
408
+ name = "\${local.access_logs_name_prefix}-distribution-logs-\${random_id.bucket_suffix.hex}"
409
+ log_type = "S3_SERVER_ACCESS_LOGS"
410
+ resource_arn = aws_s3_bucket.distribution_logs.arn
411
+ }
405
412
 
406
- target_bucket = aws_s3_bucket.access_logs.id
407
- target_prefix = "distribution-access-logs/"
413
+ resource "aws_cloudwatch_log_delivery" "distribution_logs" {
414
+ delivery_source_name = aws_cloudwatch_log_delivery_source.distribution_logs.name
415
+ delivery_destination_arn = aws_cloudwatch_log_delivery_destination.access_logs.arn
408
416
  }
409
417
 
410
418
  resource "aws_s3_bucket_policy" "distribution_logs_ssl_policy" {
@@ -512,13 +520,42 @@ resource "aws_cloudfront_origin_access_control" "website_oac" {
512
520
  signing_protocol = "sigv4"
513
521
  }
514
522
 
523
+ # Security headers applied to all responses.
524
+ resource "aws_cloudfront_response_headers_policy" "website" {
525
+ name = "\${aws_s3_bucket.website.bucket}-security-headers"
526
+
527
+ security_headers_config {
528
+ strict_transport_security {
529
+ access_control_max_age_sec = 63072000
530
+ include_subdomains = true
531
+ preload = true
532
+ override = true
533
+ }
534
+ content_type_options {
535
+ override = true
536
+ }
537
+ frame_options {
538
+ frame_option = "DENY"
539
+ override = true
540
+ }
541
+ referrer_policy {
542
+ referrer_policy = "strict-origin-when-cross-origin"
543
+ override = true
544
+ }
545
+ content_security_policy {
546
+ content_security_policy = local.content_security_policy
547
+ override = true
548
+ }
549
+ }
550
+ }
551
+
515
552
  # CloudFront Distribution
516
553
  resource "aws_cloudfront_distribution" "website" {
554
+ # See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistValuesGeneral.html
517
555
  #checkov:skip=CKV_AWS_174:Using CloudFront default certificate which does not support TLS v1.2
518
556
  #checkov:skip=CKV_AWS_310:Origin failover not required for single S3 origin static website
519
557
  #checkov:skip=CKV_AWS_374:Geo restrictions not required for global web application
520
558
  #checkov:skip=CKV2_AWS_42:Custom SSL certificate not required for development - using CloudFront default
521
- #checkov:skip=CKV2_AWS_32:Response headers policy not required for basic static website
522
559
  #checkov:skip=CKV2_AWS_47:WAF includes AWSManagedRulesKnownBadInputsRuleSet which provides Log4j protection
523
560
  origin {
524
561
  domain_name = aws_s3_bucket.website.bucket_regional_domain_name
@@ -530,6 +567,7 @@ resource "aws_cloudfront_distribution" "website" {
530
567
  is_ipv6_enabled = true
531
568
  default_root_object = "index.html"
532
569
  web_acl_id = aws_wafv2_web_acl.cloudfront_waf.arn
570
+ aliases = var.custom_domain_names
533
571
 
534
572
  logging_config {
535
573
  include_cookies = false
@@ -548,11 +586,12 @@ resource "aws_cloudfront_distribution" "website" {
548
586
  }
549
587
  }
550
588
 
551
- viewer_protocol_policy = "redirect-to-https"
552
- min_ttl = 0
553
- default_ttl = 3600
554
- max_ttl = 86400
555
- compress = true
589
+ viewer_protocol_policy = "redirect-to-https"
590
+ response_headers_policy_id = aws_cloudfront_response_headers_policy.website.id
591
+ min_ttl = 0
592
+ default_ttl = 3600
593
+ max_ttl = 86400
594
+ compress = true
556
595
  }
557
596
 
558
597
  # Custom error responses for SPA routing
@@ -575,7 +614,10 @@ resource "aws_cloudfront_distribution" "website" {
575
614
  }
576
615
 
577
616
  viewer_certificate {
578
- cloudfront_default_certificate = true
617
+ cloudfront_default_certificate = var.acm_certificate_arn == null
618
+ acm_certificate_arn = var.acm_certificate_arn
619
+ ssl_support_method = var.acm_certificate_arn == null ? null : "sni-only"
620
+ minimum_protocol_version = var.acm_certificate_arn == null ? "TLSv1" : "TLSv1.2_2021"
579
621
  }
580
622
 
581
623
  tags = {
@@ -656,8 +698,8 @@ resource "null_resource" "upload_website_files" {
656
698
 
657
699
  provisioner "local-exec" {
658
700
  command = <<-EOT
659
- cd "\${path.root}"
660
- uv run --with boto3 python3 -c "
701
+ cd "$ROOT_PATH"
702
+ uv run --with boto3==1.43.51 python3 -c "
661
703
  import os
662
704
  import sys
663
705
  import boto3
@@ -745,9 +787,14 @@ def sync_to_s3(local_path, bucket_name):
745
787
  sys.exit(1)
746
788
 
747
789
  # Execute sync
748
- sync_to_s3('\${var.website_file_path}', '\${aws_s3_bucket.website.bucket}')
790
+ sync_to_s3(os.environ['WEBSITE_FILE_PATH'], os.environ['BUCKET_NAME'])
749
791
  "
750
792
  EOT
793
+ environment = {
794
+ ROOT_PATH = path.root
795
+ WEBSITE_FILE_PATH = var.website_file_path
796
+ BUCKET_NAME = aws_s3_bucket.website.bucket
797
+ }
751
798
  }
752
799
 
753
800
  depends_on = [aws_s3_bucket_policy.website_cloudfront_policy]
@@ -755,11 +802,12 @@ sync_to_s3('\${var.website_file_path}', '\${aws_s3_bucket.website.bucket}')
755
802
 
756
803
  # Upload runtime config file
757
804
  resource "aws_s3_object" "runtime_config" {
758
- bucket = aws_s3_bucket.website.id
759
- key = "runtime-config.json"
760
- content = module.runtime_config_reader.config_json
761
- content_type = "application/json"
762
- etag = md5(module.runtime_config_reader.config_json)
805
+ bucket = aws_s3_bucket.website.id
806
+ key = "runtime-config.json"
807
+ content = module.runtime_config_reader.config_json
808
+ content_type = "application/json"
809
+ cache_control = "no-cache"
810
+ etag = md5(module.runtime_config_reader.config_json)
763
811
 
764
812
  depends_on = [null_resource.upload_website_files]
765
813
  }
@@ -774,8 +822,9 @@ resource "null_resource" "cloudfront_invalidation" {
774
822
 
775
823
  provisioner "local-exec" {
776
824
  command = <<-EOT
777
- uv run --with boto3 python3 -c "
825
+ uv run --with boto3==1.43.51 python3 -c "
778
826
  import boto3
827
+ import os
779
828
  import sys
780
829
  from botocore.exceptions import ClientError, NoCredentialsError
781
830
 
@@ -797,7 +846,7 @@ def create_invalidation(distribution_id):
797
846
 
798
847
  invalidation_id = response['Invalidation']['Id']
799
848
  print(f'CloudFront cache invalidation created: {invalidation_id}')
800
- print(f'Distribution: \${aws_cloudfront_distribution.website.id}')
849
+ print(f'Distribution: {distribution_id}')
801
850
  print(f'Status: {response[\\"Invalidation\\"][\\"Status\\"]}')
802
851
 
803
852
  except NoCredentialsError:
@@ -811,9 +860,12 @@ def create_invalidation(distribution_id):
811
860
  sys.exit(1)
812
861
 
813
862
  # Execute invalidation
814
- create_invalidation('\${aws_cloudfront_distribution.website.id}')
863
+ create_invalidation(os.environ['DISTRIBUTION_ID'])
815
864
  "
816
865
  EOT
866
+ environment = {
867
+ DISTRIBUTION_ID = aws_cloudfront_distribution.website.id
868
+ }
817
869
  }
818
870
 
819
871
  depends_on = [
@@ -856,7 +908,7 @@ output "waf_web_acl_arn" {
856
908
  required_providers {
857
909
  aws = {
858
910
  source = "hashicorp/aws"
859
- version = "~> 6.0"
911
+ version = "6.55.0"
860
912
  configuration_aliases = [aws.us_east_1]
861
913
  }
862
914
  }
@@ -905,61 +957,83 @@ vitest.config.*.timestamp*
905
957
  runtime-config.json"
906
958
  `;
907
959
 
908
- exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > .prettierrc 1`] = `
909
- "{ "singleQuote": true }
910
- "
911
- `;
960
+ exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > .prettierrc 1`] = `"{"singleQuote":true}"`;
912
961
 
913
- exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > eslint.config.mjs 1`] = `
914
- "import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
915
- import nx from '@nx/eslint-plugin';
916
-
917
- export default [
918
- eslintPluginPrettierRecommended,
919
- ...nx.configs['flat/base'],
920
- ...nx.configs['flat/typescript'],
921
- ...nx.configs['flat/javascript'],
922
- {
923
- ignores: [
924
- '**/dist',
925
- '**/out-tsc',
926
- '**/vite.config.*.timestamp*',
927
- '**/vitest.config.*.timestamp*',
928
- ],
962
+ exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > biome.json 1`] = `
963
+ "{
964
+ "$schema": "https://biomejs.dev/schemas/2.5.4/schema.json",
965
+ "root": true,
966
+ "formatter": {
967
+ "enabled": true,
968
+ "indentStyle": "space",
969
+ "indentWidth": 2,
970
+ "lineWidth": 80
929
971
  },
930
- {
931
- files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
932
- rules: {
933
- '@nx/enforce-module-boundaries': [
934
- 'error',
935
- {
936
- enforceBuildableLibDependency: true,
937
- allow: ['^.*/eslint(\\\\.base)?\\\\.config\\\\.[cm]?[jt]s$'],
938
- depConstraints: [
939
- {
940
- sourceTag: '*',
941
- onlyDependOnLibsWithTags: ['*'],
942
- },
943
- ],
944
- },
945
- ],
972
+ "javascript": {
973
+ "formatter": {
974
+ "quoteStyle": "single",
975
+ "trailingCommas": "all"
946
976
  },
977
+ "resolver": {
978
+ "experimentalPnpmCatalogs": true
979
+ }
947
980
  },
948
- {
949
- files: [
950
- '**/*.ts',
951
- '**/*.tsx',
952
- '**/*.cts',
953
- '**/*.mts',
954
- '**/*.js',
955
- '**/*.jsx',
956
- '**/*.cjs',
957
- '**/*.mjs',
958
- ],
959
- // Override or add rules here
960
- rules: {},
981
+ "css": {
982
+ "formatter": {
983
+ "quoteStyle": "single"
984
+ },
985
+ "linter": {
986
+ "enabled": false
987
+ }
961
988
  },
962
- ];
989
+ "linter": {
990
+ "enabled": true,
991
+ "rules": {
992
+ "preset": "none",
993
+ "correctness": {
994
+ "noUndeclaredDependencies": "error"
995
+ }
996
+ }
997
+ },
998
+ "assist": {
999
+ "actions": {
1000
+ "source": {
1001
+ "organizeImports": "on"
1002
+ }
1003
+ }
1004
+ },
1005
+ "files": {
1006
+ "includes": [
1007
+ "**",
1008
+ "!**/dist",
1009
+ "!**/out-tsc",
1010
+ "!**/node_modules",
1011
+ "!**/.nx",
1012
+ "!**/.venv",
1013
+ "!**/.grit",
1014
+ "!**/*.css",
1015
+ "!**/*.gen.*",
1016
+ "!**/generated/**",
1017
+ "!**/tsconfig*.json"
1018
+ ]
1019
+ },
1020
+ "overrides": [
1021
+ {
1022
+ "includes": [
1023
+ "**/*.config.{ts,mts,cts,js,mjs,cjs}",
1024
+ "**/*.{spec,test}.{ts,tsx,mts,cts,js,jsx,mjs,cjs}",
1025
+ "**/*.stories.{ts,tsx}"
1026
+ ],
1027
+ "linter": {
1028
+ "rules": {
1029
+ "correctness": {
1030
+ "noUndeclaredDependencies": "off"
1031
+ }
1032
+ }
1033
+ }
1034
+ }
1035
+ ]
1036
+ }
963
1037
  "
964
1038
  `;
965
1039
 
@@ -971,52 +1045,72 @@ exports[`react-website generator > Tanstack router integration > should generate
971
1045
  "targetDefaults": {
972
1046
  "build": {
973
1047
  "cache": true,
974
- "dependsOn": ["^build"],
975
1048
  "inputs": ["default"]
976
1049
  },
977
1050
  "lint": {
978
1051
  "cache": true
979
1052
  },
980
- "@nx/eslint:lint": {
981
- "cache": true,
982
- "inputs": [
983
- "default",
984
- "^default",
985
- "{workspaceRoot}/.eslintrc.json",
986
- "{workspaceRoot}/.eslintignore",
987
- "{workspaceRoot}/eslint.config.mjs",
988
- "{workspaceRoot}/tools/eslint-rules/**/*"
989
- ]
990
- },
991
- "@nx/vite:build": {
992
- "cache": true,
1053
+ "test": {
993
1054
  "dependsOn": ["^build"],
994
- "inputs": ["default", "^default"]
1055
+ "inputs": ["default"]
995
1056
  },
996
1057
  "@nx/vitest:test": {
997
1058
  "cache": true,
998
- "inputs": ["default", "^default"],
1059
+ "inputs": ["default", "^production"],
999
1060
  "configurations": {
1000
1061
  "update-snapshot": {
1001
1062
  "args": "--update"
1002
1063
  }
1003
1064
  }
1004
1065
  },
1005
- "test": {
1006
- "dependsOn": ["^build"],
1007
- "inputs": ["default"]
1008
- },
1009
1066
  "compile": {
1010
1067
  "cache": true,
1011
1068
  "inputs": ["default"]
1012
1069
  }
1013
1070
  },
1071
+ "plugins": [
1072
+ {
1073
+ "plugin": "@nx/js/typescript",
1074
+ "options": {
1075
+ "typecheck": {
1076
+ "targetName": "typecheck"
1077
+ },
1078
+ "build": {
1079
+ "targetName": "compile",
1080
+ "configName": "tsconfig.lib.json",
1081
+ "buildDepsName": "build-deps",
1082
+ "watchDepsName": "watch-deps"
1083
+ }
1084
+ }
1085
+ },
1086
+ {
1087
+ "plugin": "@nx/vite/plugin",
1088
+ "options": {
1089
+ "buildTargetName": "bundle",
1090
+ "serveTargetName": "serve",
1091
+ "devTargetName": "serve",
1092
+ "previewTargetName": "preview",
1093
+ "serveStaticTargetName": "serve-static",
1094
+ "typecheckTargetName": "vite:typecheck",
1095
+ "buildDepsTargetName": "build-deps",
1096
+ "watchDepsTargetName": "watch-deps"
1097
+ }
1098
+ },
1099
+ {
1100
+ "plugin": "@nx/vitest",
1101
+ "options": {
1102
+ "testTargetName": "test",
1103
+ "ciTargetName": "test-ci",
1104
+ "testMode": "watch"
1105
+ }
1106
+ }
1107
+ ],
1014
1108
  "generators": {
1015
1109
  "@nx/react": {
1016
1110
  "application": {
1017
1111
  "babel": true,
1018
1112
  "style": "css",
1019
- "linter": "eslint",
1113
+ "linter": "none",
1020
1114
  "bundler": "vite"
1021
1115
  },
1022
1116
  "component": {
@@ -1024,39 +1118,19 @@ exports[`react-website generator > Tanstack router integration > should generate
1024
1118
  },
1025
1119
  "library": {
1026
1120
  "style": "css",
1027
- "linter": "eslint"
1121
+ "linter": "none"
1028
1122
  }
1029
1123
  }
1030
1124
  },
1031
1125
  "namedInputs": {
1032
- "eslint": [
1033
- "default",
1034
- "{workspaceRoot}/eslint.config.mjs",
1035
- "{projectRoot}/eslint.config.mjs"
1036
- ],
1126
+ "biome": ["default", "{workspaceRoot}/biome.json"],
1037
1127
  "default": [
1038
1128
  {
1039
1129
  "dependentTasksOutputFiles": "**/*",
1040
1130
  "transitive": true
1041
1131
  }
1042
1132
  ]
1043
- },
1044
- "plugins": [
1045
- {
1046
- "plugin": "@nx/js/typescript",
1047
- "options": {
1048
- "typecheck": {
1049
- "targetName": "typecheck"
1050
- },
1051
- "build": {
1052
- "targetName": "compile",
1053
- "configName": "tsconfig.lib.json",
1054
- "buildDepsName": "build-deps",
1055
- "watchDepsName": "watch-deps"
1056
- }
1057
- }
1058
- }
1059
- ]
1133
+ }
1060
1134
  }
1061
1135
  "
1062
1136
  `;
@@ -1064,58 +1138,35 @@ exports[`react-website generator > Tanstack router integration > should generate
1064
1138
  exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > package.json 1`] = `
1065
1139
  "{
1066
1140
  "name": "@proj/source",
1067
- "dependencies": {
1068
- "@cloudscape-design/board-components": "3.0.187",
1069
- "@cloudscape-design/components": "3.0.1304",
1070
- "@cloudscape-design/global-styles": "1.0.59",
1071
- "aws-cdk-lib": "2.257.0",
1072
- "constructs": "10.6.0",
1073
- "react": "19.2.7",
1074
- "react-dom": "19.2.7",
1075
- "tailwindcss": "4.3.0"
1076
- },
1141
+ "dependencies": {},
1077
1142
  "devDependencies": {
1078
- "@eslint/js": "^9.8.0",
1079
- "@nx/eslint": "22.7.5",
1080
- "@nx/eslint-plugin": "22.7.5",
1081
- "@nx/js": "22.7.5",
1082
- "@nx/react": "22.7.5",
1083
- "@nx/vite": "22.7.5",
1084
- "@nx/vitest": "22.7.5",
1085
- "@nx/web": "22.7.5",
1086
- "@swc-node/register": "~1.11.1",
1087
- "@swc/cli": "~0.8.0",
1088
- "@swc/core": "~1.15.5",
1143
+ "@nx/js": "23.1.0",
1144
+ "@nx/react": "catalog:",
1145
+ "@nx/vite": "23.1.0",
1146
+ "@nx/vitest": "23.1.0",
1147
+ "@nx/web": "23.1.0",
1089
1148
  "@swc/helpers": "~0.5.18",
1090
- "@tailwindcss/vite": "4.3.0",
1149
+ "@tailwindcss/vite": "catalog:",
1091
1150
  "@testing-library/dom": "10.4.0",
1092
1151
  "@testing-library/react": "16.3.0",
1093
- "@types/node": "25.9.1",
1152
+ "@types/node": "catalog:",
1094
1153
  "@types/react": "^19.0.0",
1095
1154
  "@types/react-dom": "^19.0.0",
1096
1155
  "@vitejs/plugin-react": "^6.0.0",
1097
- "@vitest/coverage-v8": "4.1.7",
1098
- "@vitest/ui": "4.1.7",
1099
- "eslint": "^9.8.0",
1100
- "eslint-config-prettier": "^10.0.0",
1101
- "eslint-plugin-import": "2.31.0",
1102
- "eslint-plugin-jsx-a11y": "6.10.1",
1103
- "eslint-plugin-prettier": "5.5.6",
1104
- "eslint-plugin-react": "7.35.0",
1105
- "eslint-plugin-react-hooks": "5.0.0",
1156
+ "@vitest/coverage-v8": "catalog:",
1157
+ "@vitest/ui": "catalog:",
1106
1158
  "jiti": "2.4.2",
1107
- "jsdom": "~22.1.0",
1108
- "jsonc-eslint-parser": "3.1.0",
1109
- "prettier": "3.8.3",
1110
- "typescript": "~5.9.2",
1111
- "typescript-eslint": "^8.40.0",
1112
- "vite": "8.0.14",
1113
- "vitest": "4.1.7"
1159
+ "jsdom": "^27.1.0",
1160
+ "typescript": "~6.0.3",
1161
+ "vite": "catalog:",
1162
+ "vitest": "catalog:"
1114
1163
  },
1115
1164
  "type": "module",
1116
- "scripts": {
1117
- "dev": "nx serve-local @proj/test-app"
1118
- }
1165
+ "workspaces": [
1166
+ "packages/*",
1167
+ "test-app",
1168
+ "packages/common/constructs"
1169
+ ]
1119
1170
  }
1120
1171
  "
1121
1172
  `;
@@ -1153,35 +1204,25 @@ You can also automatiaclly fix some lint errors by running the following command
1153
1204
 
1154
1205
  - [common-constructs reference docs](TODO)
1155
1206
  - [Learn more about NX](https://nx.dev/getting-started/intro)
1207
+
1156
1208
  "
1157
1209
  `;
1158
1210
 
1159
- exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > packages/common/constructs/eslint.config.mjs 1`] = `
1160
- "import baseConfig from '../../../eslint.config.mjs';
1161
-
1162
- export default [
1163
- ...baseConfig,
1164
- {
1165
- files: ['**/*.json'],
1166
- rules: {
1167
- '@nx/dependency-checks': [
1168
- 'warn',
1169
- {
1170
- ignoredFiles: [
1171
- '{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}',
1172
- '{projectRoot}/vitest.config.{js,ts,mjs,mts}',
1173
- ],
1174
- },
1175
- ],
1176
- },
1177
- languageOptions: {
1178
- parser: await import('jsonc-eslint-parser'),
1179
- },
1180
- },
1181
- {
1182
- ignores: ['**/out-tsc'],
1211
+ exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > packages/common/constructs/package.json 1`] = `
1212
+ "{
1213
+ "name": "@proj/common-constructs",
1214
+ "version": "0.0.1",
1215
+ "private": true,
1216
+ "type": "module",
1217
+ "dependencies": {
1218
+ "aws-cdk-lib": "catalog:",
1219
+ "constructs": "catalog:",
1220
+ "tslib": "^2.3.0"
1183
1221
  },
1184
- ];
1222
+ "devDependencies": {
1223
+ "@types/node": "catalog:"
1224
+ }
1225
+ }
1185
1226
  "
1186
1227
  `;
1187
1228
 
@@ -1192,6 +1233,9 @@ exports[`react-website generator > Tanstack router integration > should generate
1192
1233
  "sourceRoot": "packages/common/constructs/src",
1193
1234
  "projectType": "library",
1194
1235
  "tags": [],
1236
+ "metadata": {
1237
+ "generator": "ts#project"
1238
+ },
1195
1239
  "targets": {
1196
1240
  "build": {
1197
1241
  "dependsOn": ["lint", "compile", "test", "@proj/test-app:build"]
@@ -1204,29 +1248,39 @@ exports[`react-website generator > Tanstack router integration > should generate
1204
1248
  "cwd": "{projectRoot}"
1205
1249
  }
1206
1250
  },
1207
- "lint": {
1208
- "executor": "@nx/eslint:lint",
1251
+ "format": {
1252
+ "executor": "nx:run-commands",
1209
1253
  "cache": true,
1210
- "inputs": ["eslint"],
1254
+ "inputs": ["biome"],
1255
+ "options": {
1256
+ "command": "biome format {projectRoot}"
1257
+ },
1211
1258
  "configurations": {
1212
1259
  "fix": {
1213
- "fix": true
1260
+ "command": "biome format --write {projectRoot}"
1214
1261
  },
1215
1262
  "skip-lint": {
1216
- "force": true
1263
+ "command": "node -e \\"\\""
1217
1264
  }
1218
1265
  }
1219
1266
  },
1220
- "test": {
1221
- "executor": "@nx/vitest:test",
1222
- "outputs": ["{options.reportsDirectory}"],
1267
+ "lint": {
1268
+ "executor": "nx:run-commands",
1269
+ "cache": true,
1270
+ "inputs": ["biome"],
1271
+ "dependsOn": ["format"],
1223
1272
  "options": {
1224
- "reportsDirectory": "{workspaceRoot}/coverage/{projectRoot}"
1273
+ "command": "biome lint {projectRoot}"
1274
+ },
1275
+ "configurations": {
1276
+ "fix": {
1277
+ "command": "biome check --write {projectRoot}"
1278
+ },
1279
+ "skip-lint": {
1280
+ "command": "node -e \\"\\""
1281
+ }
1225
1282
  }
1226
1283
  }
1227
- },
1228
- "metadata": {
1229
- "generator": "ts#project"
1230
1284
  }
1231
1285
  }
1232
1286
  "
@@ -1337,10 +1391,31 @@ export const suppressRules = (
1337
1391
  "
1338
1392
  `;
1339
1393
 
1394
+ exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > packages/common/constructs/src/core/cloudfront.ts 1`] = `
1395
+ "import { CfnDistribution, Distribution } from 'aws-cdk-lib/aws-cloudfront';
1396
+
1397
+ /**
1398
+ * Finds the domain names associated with a CloudFront distribution.
1399
+ *
1400
+ * Includes the distribution's default \`*.cloudfront.net\` domain name plus any custom
1401
+ * domain names (aliases) configured on it.
1402
+ */
1403
+ export const findCloudFrontDomainNames = (
1404
+ distribution: Distribution,
1405
+ ): string[] => {
1406
+ const cfnDistribution = distribution.node.defaultChild as CfnDistribution;
1407
+ const distributionConfig =
1408
+ cfnDistribution.distributionConfig as CfnDistribution.DistributionConfigProperty;
1409
+ return [distribution.domainName, ...(distributionConfig.aliases ?? [])];
1410
+ };
1411
+ "
1412
+ `;
1413
+
1340
1414
  exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > packages/common/constructs/src/core/index.ts 1`] = `
1341
1415
  "export * from './static-website.js';
1342
1416
  export * from './app.js';
1343
1417
  export * from './checkov.js';
1418
+ export * from './cloudfront.js';
1344
1419
  export * from './runtime-config.js';
1345
1420
  export * from './workspace.js';
1346
1421
  "
@@ -1536,11 +1611,21 @@ exports[`react-website generator > Tanstack router integration > should generate
1536
1611
  "import {
1537
1612
  CfnOutput,
1538
1613
  CfnResource,
1614
+ Duration,
1539
1615
  Lazy,
1616
+ Names,
1540
1617
  RemovalPolicy,
1541
1618
  Stack,
1542
1619
  } from 'aws-cdk-lib';
1543
- import { Distribution, ViewerProtocolPolicy } from 'aws-cdk-lib/aws-cloudfront';
1620
+ import {
1621
+ Distribution,
1622
+ HeadersFrameOption,
1623
+ HeadersReferrerPolicy,
1624
+ ResponseHeadersPolicy,
1625
+ SecurityPolicyProtocol,
1626
+ ViewerProtocolPolicy,
1627
+ } from 'aws-cdk-lib/aws-cloudfront';
1628
+ import { ICertificate } from 'aws-cdk-lib/aws-certificatemanager';
1544
1629
  import { S3BucketOrigin } from 'aws-cdk-lib/aws-cloudfront-origins';
1545
1630
  import {
1546
1631
  BlockPublicAccess,
@@ -1549,18 +1634,56 @@ import {
1549
1634
  IBucket,
1550
1635
  ObjectOwnership,
1551
1636
  } from 'aws-cdk-lib/aws-s3';
1552
- import { BucketDeployment, Source } from 'aws-cdk-lib/aws-s3-deployment';
1637
+ import {
1638
+ BucketDeployment,
1639
+ CacheControl,
1640
+ Source,
1641
+ } from 'aws-cdk-lib/aws-s3-deployment';
1553
1642
  import { Construct } from 'constructs';
1554
1643
  import { RuntimeConfig } from './runtime-config.js';
1555
1644
  import { Key } from 'aws-cdk-lib/aws-kms';
1645
+ import {
1646
+ CfnDelivery,
1647
+ CfnDeliveryDestination,
1648
+ CfnDeliverySource,
1649
+ LogGroup,
1650
+ RetentionDays,
1651
+ } from 'aws-cdk-lib/aws-logs';
1652
+ import { Effect, PolicyStatement, ServicePrincipal } from 'aws-cdk-lib/aws-iam';
1556
1653
  import { CfnWebACL } from 'aws-cdk-lib/aws-wafv2';
1557
1654
  import { suppressRules } from './checkov.js';
1558
1655
 
1559
1656
  const DEFAULT_RUNTIME_CONFIG_FILENAME = 'runtime-config.json';
1560
1657
 
1658
+ // Content-Security-Policy enforced on all responses. Restricts scripts and
1659
+ // framing to mitigate XSS and clickjacking, while permitting HTTPS/WSS calls
1660
+ // (connect-src) to AWS service endpoints such as API Gateway, Cognito and
1661
+ // Bedrock AgentCore which are only known at deploy time. Edit this to tighten
1662
+ // connect-src to your specific origins once they are known.
1663
+ const CONTENT_SECURITY_POLICY = [
1664
+ "default-src 'self'",
1665
+ "script-src 'self'",
1666
+ "style-src 'self' 'unsafe-inline'",
1667
+ "img-src 'self' data:",
1668
+ "font-src 'self' data:",
1669
+ "connect-src 'self' https: wss:",
1670
+ "object-src 'none'",
1671
+ "base-uri 'self'",
1672
+ "frame-ancestors 'none'",
1673
+ ].join('; ');
1674
+
1561
1675
  export interface StaticWebsiteProps {
1562
1676
  readonly websiteName: string;
1563
1677
  readonly websiteFilePath: string;
1678
+ /**
1679
+ * Custom domain names for the CloudFront distribution. Requires \`certificate\`.
1680
+ */
1681
+ readonly domainNames?: string[];
1682
+ /**
1683
+ * ACM certificate for the custom domain names. Must be in us-east-1.
1684
+ * When provided, viewers are required to use TLS 1.2 or later.
1685
+ */
1686
+ readonly certificate?: ICertificate;
1564
1687
  }
1565
1688
 
1566
1689
  /**
@@ -1579,39 +1702,48 @@ export class StaticWebsite extends Construct {
1579
1702
  constructor(
1580
1703
  scope: Construct,
1581
1704
  id: string,
1582
- { websiteFilePath, websiteName }: StaticWebsiteProps,
1705
+ {
1706
+ websiteFilePath,
1707
+ websiteName,
1708
+ domainNames,
1709
+ certificate,
1710
+ }: StaticWebsiteProps,
1583
1711
  ) {
1584
1712
  super(scope, id);
1585
- this.node.setContext(
1586
- '@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy',
1587
- true,
1588
- );
1589
1713
 
1590
1714
  const websiteKey = new Key(this, 'WebsiteKey', {
1591
1715
  enableKeyRotation: true,
1592
1716
  });
1593
1717
 
1594
- const accessLogsBucket = new Bucket(this, 'AccessLogsBucket', {
1595
- versioned: false,
1596
- enforceSSL: true,
1597
- autoDeleteObjects: true,
1598
- removalPolicy: RemovalPolicy.DESTROY,
1599
- encryption: BucketEncryption.KMS,
1718
+ // Allow CloudWatch Logs to use the website key for server access log delivery.
1719
+ const stack = Stack.of(this);
1720
+ websiteKey.addToResourcePolicy(
1721
+ new PolicyStatement({
1722
+ effect: Effect.ALLOW,
1723
+ principals: [
1724
+ new ServicePrincipal(\`logs.\${stack.region}.amazonaws.com\`),
1725
+ ],
1726
+ actions: [
1727
+ 'kms:Encrypt',
1728
+ 'kms:Decrypt',
1729
+ 'kms:ReEncrypt*',
1730
+ 'kms:GenerateDataKey*',
1731
+ 'kms:DescribeKey',
1732
+ ],
1733
+ resources: ['*'],
1734
+ conditions: {
1735
+ ArnLike: {
1736
+ 'kms:EncryptionContext:aws:logs:arn': \`arn:aws:logs:\${stack.region}:\${stack.account}:log-group:*\`,
1737
+ },
1738
+ },
1739
+ }),
1740
+ );
1741
+
1742
+ const accessLogs = new LogGroup(this, 'AccessLogs', {
1743
+ retention: RetentionDays.ONE_YEAR,
1600
1744
  encryptionKey: websiteKey,
1601
- objectOwnership: ObjectOwnership.OBJECT_WRITER,
1602
- publicReadAccess: false,
1603
- blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
1745
+ removalPolicy: RemovalPolicy.DESTROY,
1604
1746
  });
1605
- suppressRules(
1606
- accessLogsBucket,
1607
- ['CKV_AWS_21'],
1608
- 'Access log bucket does not need versioning enabled',
1609
- );
1610
- suppressRules(
1611
- accessLogsBucket,
1612
- ['CKV_AWS_18'],
1613
- 'Access log bucket does not need an access log bucket',
1614
- );
1615
1747
 
1616
1748
  // S3 Bucket to hold website files
1617
1749
  this.websiteBucket = new Bucket(this, 'WebsiteBucket', {
@@ -1624,13 +1756,23 @@ export class StaticWebsite extends Construct {
1624
1756
  objectOwnership: ObjectOwnership.BUCKET_OWNER_ENFORCED,
1625
1757
  publicReadAccess: false,
1626
1758
  blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
1627
- serverAccessLogsPrefix: 'website-access-logs',
1628
- serverAccessLogsBucket: accessLogsBucket,
1629
1759
  });
1760
+ suppressRules(
1761
+ this.websiteBucket,
1762
+ ['CKV_AWS_18'],
1763
+ 'Server access logs are delivered to CloudWatch Logs',
1764
+ );
1765
+ this.deliverAccessLogsToCloudWatch(
1766
+ 'Website',
1767
+ this.websiteBucket,
1768
+ accessLogs,
1769
+ );
1630
1770
  // Web ACL
1631
1771
  const wafStack = new CloudfrontWebAcl(this, 'waf');
1632
1772
 
1633
- // Cloudfront Distribution
1773
+ // Bucket holding CloudFront standard access logs. CloudFront delivers its
1774
+ // own logs to S3 only, so this bucket is retained; its S3 server access
1775
+ // logs are delivered to CloudWatch Logs.
1634
1776
  const logBucket = new Bucket(this, 'DistributionLogBucket', {
1635
1777
  enforceSSL: true,
1636
1778
  autoDeleteObjects: true,
@@ -1640,14 +1782,48 @@ export class StaticWebsite extends Construct {
1640
1782
  objectOwnership: ObjectOwnership.BUCKET_OWNER_PREFERRED,
1641
1783
  publicReadAccess: false,
1642
1784
  blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
1643
- serverAccessLogsPrefix: 'distribution-access-logs',
1644
- serverAccessLogsBucket: accessLogsBucket,
1645
1785
  });
1646
1786
  suppressRules(
1647
1787
  logBucket,
1648
1788
  ['CKV_AWS_21'],
1649
1789
  'Distribution log bucket does not need versioning enabled',
1650
1790
  );
1791
+ suppressRules(
1792
+ logBucket,
1793
+ ['CKV_AWS_18'],
1794
+ 'Server access logs are delivered to CloudWatch Logs',
1795
+ );
1796
+ this.deliverAccessLogsToCloudWatch('Distribution', logBucket, accessLogs);
1797
+
1798
+ // Security headers applied to all responses.
1799
+ const responseHeadersPolicy = new ResponseHeadersPolicy(
1800
+ this,
1801
+ 'ResponseHeadersPolicy',
1802
+ {
1803
+ securityHeadersBehavior: {
1804
+ strictTransportSecurity: {
1805
+ accessControlMaxAge: Duration.days(730),
1806
+ includeSubdomains: true,
1807
+ preload: true,
1808
+ override: true,
1809
+ },
1810
+ contentTypeOptions: { override: true },
1811
+ frameOptions: {
1812
+ frameOption: HeadersFrameOption.DENY,
1813
+ override: true,
1814
+ },
1815
+ referrerPolicy: {
1816
+ referrerPolicy:
1817
+ HeadersReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
1818
+ override: true,
1819
+ },
1820
+ contentSecurityPolicy: {
1821
+ contentSecurityPolicy: CONTENT_SECURITY_POLICY,
1822
+ override: true,
1823
+ },
1824
+ },
1825
+ },
1826
+ );
1651
1827
 
1652
1828
  const defaultRootObject = 'index.html';
1653
1829
  this.cloudFrontDistribution = new Distribution(
@@ -1657,9 +1833,17 @@ export class StaticWebsite extends Construct {
1657
1833
  webAclId: wafStack.wafArn,
1658
1834
  enableLogging: true,
1659
1835
  logBucket: logBucket,
1836
+ ...(certificate
1837
+ ? {
1838
+ certificate,
1839
+ domainNames,
1840
+ minimumProtocolVersion: SecurityPolicyProtocol.TLS_V1_2_2021,
1841
+ }
1842
+ : {}),
1660
1843
  defaultBehavior: {
1661
1844
  origin: S3BucketOrigin.withOriginAccessControl(this.websiteBucket),
1662
1845
  viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
1846
+ responseHeadersPolicy,
1663
1847
  },
1664
1848
  defaultRootObject,
1665
1849
  errorResponses: [
@@ -1676,16 +1860,31 @@ export class StaticWebsite extends Construct {
1676
1860
  ],
1677
1861
  },
1678
1862
  );
1679
- suppressRules(
1680
- this.cloudFrontDistribution,
1681
- ['CKV_AWS_174'],
1682
- 'Cloudfront default certificate does not use TLS 1.2',
1683
- );
1863
+ if (!certificate) {
1864
+ // See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistValuesGeneral.html
1865
+ suppressRules(
1866
+ this.cloudFrontDistribution,
1867
+ ['CKV_AWS_174'],
1868
+ 'Cloudfront default certificate does not use TLS 1.2',
1869
+ );
1870
+ }
1684
1871
 
1685
1872
  // Deploy Website
1686
1873
  this.bucketDeployment = new BucketDeployment(this, 'WebsiteDeployment', {
1874
+ sources: [Source.asset(websiteFilePath)],
1875
+ destinationBucket: this.websiteBucket,
1876
+ // Files in the distribution's edge caches will be invalidated after files are uploaded to the destination bucket.
1877
+ distribution: this.cloudFrontDistribution,
1878
+ // Exclude the runtime config from this deployment's sync so its default pruning
1879
+ // never deletes the file managed separately by RuntimeConfigDeployment below.
1880
+ exclude: [DEFAULT_RUNTIME_CONFIG_FILENAME],
1881
+ memoryLimit: 1024,
1882
+ });
1883
+
1884
+ // Deploy runtime-config.json separately so it is never cached - clients
1885
+ // must always fetch the latest configuration.
1886
+ new BucketDeployment(this, 'RuntimeConfigDeployment', {
1687
1887
  sources: [
1688
- Source.asset(websiteFilePath),
1689
1888
  Source.data(
1690
1889
  DEFAULT_RUNTIME_CONFIG_FILENAME,
1691
1890
  Lazy.string({
@@ -1697,8 +1896,9 @@ export class StaticWebsite extends Construct {
1697
1896
  ),
1698
1897
  ],
1699
1898
  destinationBucket: this.websiteBucket,
1700
- // Files in the distribution's edge caches will be invalidated after files are uploaded to the destination bucket.
1701
1899
  distribution: this.cloudFrontDistribution,
1900
+ cacheControl: [CacheControl.noCache()],
1901
+ prune: false,
1702
1902
  memoryLimit: 1024,
1703
1903
  });
1704
1904
 
@@ -1719,6 +1919,44 @@ export class StaticWebsite extends Construct {
1719
1919
  value: this.websiteBucket.bucketName,
1720
1920
  });
1721
1921
  }
1922
+
1923
+ /**
1924
+ * Delivers a bucket's S3 server access logs to a CloudWatch log group using
1925
+ * CloudWatch Logs vended log delivery.
1926
+ */
1927
+ private deliverAccessLogsToCloudWatch(
1928
+ id: string,
1929
+ bucket: IBucket,
1930
+ logGroup: LogGroup,
1931
+ ) {
1932
+ const source: CfnDeliverySource = new CfnDeliverySource(
1933
+ this,
1934
+ \`\${id}AccessLogsSource\`,
1935
+ {
1936
+ name: Lazy.string({
1937
+ produce: () => Names.uniqueResourceName(source, { maxLength: 60 }),
1938
+ }),
1939
+ logType: 'S3_SERVER_ACCESS_LOGS',
1940
+ resourceArn: bucket.bucketArn,
1941
+ },
1942
+ );
1943
+ const destination: CfnDeliveryDestination = new CfnDeliveryDestination(
1944
+ this,
1945
+ \`\${id}AccessLogsDestination\`,
1946
+ {
1947
+ name: Lazy.string({
1948
+ produce: () =>
1949
+ Names.uniqueResourceName(destination, { maxLength: 60 }),
1950
+ }),
1951
+ destinationResourceArn: logGroup.logGroupArn,
1952
+ },
1953
+ );
1954
+ const delivery = new CfnDelivery(this, \`\${id}AccessLogsDelivery\`, {
1955
+ deliverySourceName: source.name,
1956
+ deliveryDestinationArn: destination.attrArn,
1957
+ });
1958
+ delivery.addDependency(source);
1959
+ }
1722
1960
  }
1723
1961
 
1724
1962
  export class CloudfrontWebAcl extends Stack {
@@ -1841,9 +2079,13 @@ exports[`react-website generator > Tanstack router integration > should generate
1841
2079
  "emitDeclarationOnly": false,
1842
2080
  "module": "nodenext",
1843
2081
  "moduleResolution": "nodenext",
1844
- "types": ["node"]
2082
+ "types": [
2083
+ "node"
2084
+ ]
1845
2085
  },
1846
- "include": ["src/**/*.ts"],
2086
+ "include": [
2087
+ "src/**/*.ts"
2088
+ ],
1847
2089
  "references": [],
1848
2090
  "exclude": [
1849
2091
  "vite.config.ts",
@@ -1909,6 +2151,7 @@ export default defineConfig(() => ({
1909
2151
  root: __dirname,
1910
2152
  cacheDir: '../../../node_modules/.vite/packages/common/constructs',
1911
2153
  test: {
2154
+ passWithNoTests: true,
1912
2155
  name: '@proj/common-constructs',
1913
2156
  watch: false,
1914
2157
  globals: true,
@@ -1919,7 +2162,6 @@ export default defineConfig(() => ({
1919
2162
  reportsDirectory: './test-output/vitest/coverage',
1920
2163
  provider: 'v8' as const,
1921
2164
  },
1922
- passWithNoTests: true,
1923
2165
  },
1924
2166
  }));
1925
2167
  "
@@ -1927,15 +2169,30 @@ export default defineConfig(() => ({
1927
2169
 
1928
2170
  exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > pnpm-workspace.yaml 1`] = `
1929
2171
  "packages:
1930
- - 'packages/*'
1931
- - 'test-app'
1932
- - 'packages/common/*'
2172
+ - packages/*
2173
+ - test-app
2174
+ - packages/common/*
2175
+ catalog:
2176
+ vite: 8.1.5
2177
+ vitest: 4.1.10
2178
+ '@vitest/coverage-v8': 4.1.10
2179
+ constructs: 10.7.0
2180
+ aws-cdk-lib: 2.261.0
2181
+ '@types/node': 26.1.1
2182
+ react: 19.2.7
2183
+ react-dom: 19.2.7
2184
+ '@cloudscape-design/components': 3.0.1330
2185
+ '@cloudscape-design/board-components': 3.0.205
2186
+ '@cloudscape-design/global-styles': 1.0.62
2187
+ tailwindcss: 4.3.3
2188
+ '@nx/react': 23.1.0
2189
+ '@vitest/ui': 4.1.10
2190
+ '@tailwindcss/vite': 4.3.3
1933
2191
  "
1934
2192
  `;
1935
2193
 
1936
2194
  exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > test-app/README.md 1`] = `
1937
2195
  "# @proj/test-app
1938
-
1939
2196
  This library was generated with [@aws/nx-plugin](https://github.com/awslabs/nx-plugin-for-aws/).
1940
2197
 
1941
2198
  ## Building
@@ -1984,24 +2241,8 @@ In order to integrate with cognito or trpc backends, you need to have a \`runtim
1984
2241
  "
1985
2242
  `;
1986
2243
 
1987
- exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > test-app/eslint.config.mjs 1`] = `
1988
- "import nx from '@nx/eslint-plugin';
1989
- import baseConfig from '../eslint.config.mjs';
1990
-
1991
- export default [
1992
- ...nx.configs['flat/react'],
1993
- ...baseConfig,
1994
- {
1995
- files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
1996
- // Override or add rules here
1997
- rules: {},
1998
- },
1999
- ];
2000
- "
2001
- `;
2002
-
2003
2244
  exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > test-app/index.html 1`] = `
2004
- "<!doctype html>
2245
+ "<!DOCTYPE html>
2005
2246
  <html lang="en">
2006
2247
  <head>
2007
2248
  <meta charset="utf-8" />
@@ -2020,6 +2261,25 @@ exports[`react-website generator > Tanstack router integration > should generate
2020
2261
  "
2021
2262
  `;
2022
2263
 
2264
+ exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > test-app/package.json 1`] = `
2265
+ "{
2266
+ "name": "@proj/test-app",
2267
+ "version": "0.0.1",
2268
+ "private": true,
2269
+ "type": "module",
2270
+ "dependencies": {
2271
+ "@cloudscape-design/board-components": "catalog:",
2272
+ "@cloudscape-design/components": "catalog:",
2273
+ "@cloudscape-design/global-styles": "catalog:",
2274
+ "react": "catalog:",
2275
+ "react-dom": "catalog:",
2276
+ "tailwindcss": "catalog:"
2277
+ },
2278
+ "devDependencies": {}
2279
+ }
2280
+ "
2281
+ `;
2282
+
2023
2283
  exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > test-app/project.json 1`] = `
2024
2284
  "{
2025
2285
  "name": "@proj/test-app",
@@ -2035,29 +2295,10 @@ exports[`react-website generator > Tanstack router integration > should generate
2035
2295
  },
2036
2296
  "targets": {
2037
2297
  "build": {
2038
- "dependsOn": ["lint", "compile", "bundle", "test"],
2039
- "options": {
2040
- "outputPath": "dist/{projectRoot}/bundle"
2041
- }
2042
- },
2043
- "bundle": {
2044
- "executor": "@nx/vite:build",
2045
- "outputs": ["{options.outputPath}"],
2046
- "defaultConfiguration": "production",
2047
- "options": {
2048
- "outputPath": "dist/{projectRoot}/bundle"
2049
- },
2050
- "configurations": {
2051
- "development": {
2052
- "mode": "development"
2053
- },
2054
- "production": {
2055
- "mode": "production"
2056
- }
2057
- }
2298
+ "dependsOn": ["lint", "compile", "test", "bundle"]
2058
2299
  },
2059
2300
  "compile": {
2060
- "dependsOn": ["bundle"],
2301
+ "dependsOn": ["^build"],
2061
2302
  "executor": "nx:run-commands",
2062
2303
  "outputs": ["{workspaceRoot}/dist/{projectRoot}/tsc"],
2063
2304
  "options": {
@@ -2065,83 +2306,54 @@ exports[`react-website generator > Tanstack router integration > should generate
2065
2306
  "cwd": "{projectRoot}"
2066
2307
  }
2067
2308
  },
2068
- "lint": {
2069
- "executor": "@nx/eslint:lint",
2070
- "cache": true,
2071
- "inputs": ["eslint"],
2072
- "configurations": {
2073
- "fix": {
2074
- "fix": true
2075
- },
2076
- "skip-lint": {
2077
- "force": true
2078
- }
2079
- }
2080
- },
2081
- "load:runtime-config": {
2309
+ "dev": {
2082
2310
  "executor": "nx:run-commands",
2083
- "metadata": {
2084
- "description": "Load runtime config from your deployed stack for dev purposes. You must set your AWS CLI credentials whilst calling 'pnpm nx run @proj/test-app:load:runtime-config'"
2085
- },
2311
+ "continuous": true,
2086
2312
  "options": {
2087
- "command": "aws s3 cp s3://\`aws cloudformation describe-stacks --query \\"Stacks[?starts_with(StackName, 'proj-')][].Outputs[] | [?contains(OutputKey, 'TestAppWebsiteBucketName')].OutputValue\\" --output text\`/runtime-config.json \\"{projectRoot}/public/runtime-config.json\\""
2313
+ "command": "vite --mode local-dev",
2314
+ "cwd": "{projectRoot}"
2088
2315
  }
2089
2316
  },
2090
- "preview": {
2091
- "dependsOn": ["build"],
2092
- "executor": "@nx/vite:preview-server",
2093
- "defaultConfiguration": "development",
2317
+ "format": {
2318
+ "executor": "nx:run-commands",
2319
+ "cache": true,
2320
+ "inputs": ["biome"],
2094
2321
  "options": {
2095
- "buildTarget": "@proj/test-app:build"
2322
+ "command": "biome format {projectRoot}"
2096
2323
  },
2097
2324
  "configurations": {
2098
- "development": {
2099
- "buildTarget": "@proj/test-app:build:development"
2325
+ "fix": {
2326
+ "command": "biome format --write {projectRoot}"
2100
2327
  },
2101
- "production": {
2102
- "buildTarget": "@proj/test-app:build:production"
2328
+ "skip-lint": {
2329
+ "command": "node -e \\"\\""
2103
2330
  }
2104
2331
  }
2105
2332
  },
2106
- "serve": {
2107
- "executor": "@nx/vite:dev-server",
2108
- "defaultConfiguration": "development",
2333
+ "lint": {
2334
+ "executor": "nx:run-commands",
2335
+ "cache": true,
2336
+ "inputs": ["biome"],
2109
2337
  "options": {
2110
- "buildTarget": "@proj/test-app:build"
2338
+ "command": "biome lint {projectRoot}"
2111
2339
  },
2112
2340
  "configurations": {
2113
- "development": {
2114
- "buildTarget": "@proj/test-app:build:development",
2115
- "hmr": true
2341
+ "fix": {
2342
+ "command": "biome check --write {projectRoot}"
2116
2343
  },
2117
- "production": {
2118
- "buildTarget": "@proj/test-app:build:production",
2119
- "hmr": false
2344
+ "skip-lint": {
2345
+ "command": "node -e \\"\\""
2120
2346
  }
2121
- }
2122
- },
2123
- "serve-local": {
2124
- "executor": "@nx/vite:dev-server",
2125
- "options": {
2126
- "buildTarget": "@proj/test-app:build:development",
2127
- "hmr": true,
2128
- "mode": "serve-local"
2129
2347
  },
2130
- "continuous": true
2348
+ "dependsOn": ["format"]
2131
2349
  },
2132
- "serve-static": {
2133
- "executor": "@nx/web:file-server",
2134
- "dependsOn": ["build"],
2135
- "options": {
2136
- "buildTarget": "@proj/test-app:build",
2137
- "spa": true
2138
- }
2139
- },
2140
- "test": {
2141
- "executor": "@nx/vitest:test",
2142
- "outputs": ["{options.reportsDirectory}"],
2350
+ "load:runtime-config": {
2351
+ "executor": "nx:run-commands",
2352
+ "metadata": {
2353
+ "description": "Load runtime config from your deployed stack for dev purposes. You must set your AWS CLI credentials whilst calling 'pnpm nx run @proj/test-app:load:runtime-config'"
2354
+ },
2143
2355
  "options": {
2144
- "reportsDirectory": "{workspaceRoot}/coverage/{projectRoot}"
2356
+ "command": "aws s3 cp s3://\`aws cloudformation describe-stacks --query \\"Stacks[?starts_with(StackName, 'proj-')][].Outputs[] | [?contains(OutputKey, 'TestAppWebsiteBucketName')].OutputValue\\" --output text\`/runtime-config.json \\"{projectRoot}/public/runtime-config.json\\""
2145
2357
  }
2146
2358
  }
2147
2359
  }
@@ -2349,15 +2561,22 @@ exports[`react-website generator > Tanstack router integration > should generate
2349
2561
  "outDir": "../dist/test-app/tsc",
2350
2562
  "tsBuildInfoFile": "../dist/test-app/tsc/tsconfig.lib.tsbuildinfo",
2351
2563
  "jsx": "react-jsx",
2352
- "lib": ["DOM"],
2564
+ "lib": [
2565
+ "DOM"
2566
+ ],
2353
2567
  "types": [
2354
2568
  "node",
2355
2569
  "@nx/react/typings/cssmodule.d.ts",
2356
2570
  "@nx/react/typings/image.d.ts",
2357
2571
  "vite/client"
2358
- ]
2572
+ ],
2573
+ "rootDir": "src",
2574
+ "module": "esnext",
2575
+ "moduleResolution": "bundler"
2359
2576
  },
2360
2577
  "exclude": [
2578
+ "out-tsc",
2579
+ "dist",
2361
2580
  "src/**/*.spec.ts",
2362
2581
  "src/**/*.test.ts",
2363
2582
  "src/**/*.spec.tsx",
@@ -2371,7 +2590,12 @@ exports[`react-website generator > Tanstack router integration > should generate
2371
2590
  "vitest.config.ts",
2372
2591
  "vitest.config.mts"
2373
2592
  ],
2374
- "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
2593
+ "include": [
2594
+ "src/**/*.js",
2595
+ "src/**/*.jsx",
2596
+ "src/**/*.ts",
2597
+ "src/**/*.tsx"
2598
+ ]
2375
2599
  }
2376
2600
  "
2377
2601
  `;
@@ -2410,7 +2634,10 @@ exports[`react-website generator > Tanstack router integration > should generate
2410
2634
  "vitest",
2411
2635
  "@nx/react/typings/cssmodule.d.ts",
2412
2636
  "@nx/react/typings/image.d.ts"
2413
- ]
2637
+ ],
2638
+ "jsx": "react-jsx",
2639
+ "module": "esnext",
2640
+ "moduleResolution": "bundler"
2414
2641
  },
2415
2642
  "include": [
2416
2643
  "vite.config.ts",
@@ -2459,7 +2686,7 @@ export default defineConfig(() => ({
2459
2686
  // plugins: [],
2460
2687
  // },
2461
2688
  build: {
2462
- outDir: '../dist/test-app',
2689
+ outDir: '../dist/test-app/bundle',
2463
2690
  emptyOutDir: true,
2464
2691
  reportCompressedSize: true,
2465
2692
  commonjsOptions: {
@@ -2467,6 +2694,7 @@ export default defineConfig(() => ({
2467
2694
  },
2468
2695
  },
2469
2696
  test: {
2697
+ passWithNoTests: true,
2470
2698
  name: '@proj/test-app',
2471
2699
  watch: false,
2472
2700
  globals: true,
@@ -2477,9 +2705,8 @@ export default defineConfig(() => ({
2477
2705
  reportsDirectory: './test-output/vitest/coverage',
2478
2706
  provider: 'v8' as const,
2479
2707
  },
2480
- passWithNoTests: true,
2481
2708
  },
2482
- resolve: { tsconfigPaths: true },
2709
+ resolve: { tsconfigPaths: true, dedupe: ['react', 'react-dom'] },
2483
2710
  define: { global: {} },
2484
2711
  }));
2485
2712
  "
@@ -2489,9 +2716,14 @@ exports[`react-website generator > Tanstack router integration > should generate
2489
2716
  "{
2490
2717
  "compilerOptions": {
2491
2718
  "paths": {
2492
- ":proj/test-app": ["./test-app/src/index.ts"],
2493
- ":proj/common-constructs": ["./packages/common/constructs/src/index.ts"]
2719
+ "@proj/test-app": [
2720
+ "./test-app/src/index.ts"
2721
+ ],
2722
+ "@proj/common-constructs": [
2723
+ "./packages/common/constructs/src/index.ts"
2724
+ ]
2494
2725
  },
2726
+ "composite": true,
2495
2727
  "rootDir": "."
2496
2728
  }
2497
2729
  }
@@ -2500,6 +2732,9 @@ exports[`react-website generator > Tanstack router integration > should generate
2500
2732
 
2501
2733
  exports[`react-website generator > Tanstack router integration > should generate website with no router correctly > tsconfig.json 1`] = `
2502
2734
  "{
2735
+ "extends": "./tsconfig.base.json",
2736
+ "files": [],
2737
+ "include": [],
2503
2738
  "references": [
2504
2739
  {
2505
2740
  "path": "./test-app"
@@ -2528,61 +2763,83 @@ vitest.config.*.timestamp*
2528
2763
  runtime-config.json"
2529
2764
  `;
2530
2765
 
2531
- exports[`react-website generator > Tanstack router integration > should generate website with router correctly > .prettierrc 1`] = `
2532
- "{ "singleQuote": true }
2533
- "
2534
- `;
2766
+ exports[`react-website generator > Tanstack router integration > should generate website with router correctly > .prettierrc 1`] = `"{"singleQuote":true}"`;
2535
2767
 
2536
- exports[`react-website generator > Tanstack router integration > should generate website with router correctly > eslint.config.mjs 1`] = `
2537
- "import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
2538
- import nx from '@nx/eslint-plugin';
2539
-
2540
- export default [
2541
- eslintPluginPrettierRecommended,
2542
- ...nx.configs['flat/base'],
2543
- ...nx.configs['flat/typescript'],
2544
- ...nx.configs['flat/javascript'],
2545
- {
2546
- ignores: [
2547
- '**/dist',
2548
- '**/out-tsc',
2549
- '**/vite.config.*.timestamp*',
2550
- '**/vitest.config.*.timestamp*',
2551
- ],
2768
+ exports[`react-website generator > Tanstack router integration > should generate website with router correctly > biome.json 1`] = `
2769
+ "{
2770
+ "$schema": "https://biomejs.dev/schemas/2.5.4/schema.json",
2771
+ "root": true,
2772
+ "formatter": {
2773
+ "enabled": true,
2774
+ "indentStyle": "space",
2775
+ "indentWidth": 2,
2776
+ "lineWidth": 80
2552
2777
  },
2553
- {
2554
- files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
2555
- rules: {
2556
- '@nx/enforce-module-boundaries': [
2557
- 'error',
2558
- {
2559
- enforceBuildableLibDependency: true,
2560
- allow: ['^.*/eslint(\\\\.base)?\\\\.config\\\\.[cm]?[jt]s$'],
2561
- depConstraints: [
2562
- {
2563
- sourceTag: '*',
2564
- onlyDependOnLibsWithTags: ['*'],
2565
- },
2566
- ],
2567
- },
2568
- ],
2778
+ "javascript": {
2779
+ "formatter": {
2780
+ "quoteStyle": "single",
2781
+ "trailingCommas": "all"
2569
2782
  },
2783
+ "resolver": {
2784
+ "experimentalPnpmCatalogs": true
2785
+ }
2570
2786
  },
2571
- {
2572
- files: [
2573
- '**/*.ts',
2574
- '**/*.tsx',
2575
- '**/*.cts',
2576
- '**/*.mts',
2577
- '**/*.js',
2578
- '**/*.jsx',
2579
- '**/*.cjs',
2580
- '**/*.mjs',
2581
- ],
2582
- // Override or add rules here
2583
- rules: {},
2787
+ "css": {
2788
+ "formatter": {
2789
+ "quoteStyle": "single"
2790
+ },
2791
+ "linter": {
2792
+ "enabled": false
2793
+ }
2584
2794
  },
2585
- ];
2795
+ "linter": {
2796
+ "enabled": true,
2797
+ "rules": {
2798
+ "preset": "none",
2799
+ "correctness": {
2800
+ "noUndeclaredDependencies": "error"
2801
+ }
2802
+ }
2803
+ },
2804
+ "assist": {
2805
+ "actions": {
2806
+ "source": {
2807
+ "organizeImports": "on"
2808
+ }
2809
+ }
2810
+ },
2811
+ "files": {
2812
+ "includes": [
2813
+ "**",
2814
+ "!**/dist",
2815
+ "!**/out-tsc",
2816
+ "!**/node_modules",
2817
+ "!**/.nx",
2818
+ "!**/.venv",
2819
+ "!**/.grit",
2820
+ "!**/*.css",
2821
+ "!**/*.gen.*",
2822
+ "!**/generated/**",
2823
+ "!**/tsconfig*.json"
2824
+ ]
2825
+ },
2826
+ "overrides": [
2827
+ {
2828
+ "includes": [
2829
+ "**/*.config.{ts,mts,cts,js,mjs,cjs}",
2830
+ "**/*.{spec,test}.{ts,tsx,mts,cts,js,jsx,mjs,cjs}",
2831
+ "**/*.stories.{ts,tsx}"
2832
+ ],
2833
+ "linter": {
2834
+ "rules": {
2835
+ "correctness": {
2836
+ "noUndeclaredDependencies": "off"
2837
+ }
2838
+ }
2839
+ }
2840
+ }
2841
+ ]
2842
+ }
2586
2843
  "
2587
2844
  `;
2588
2845
 
@@ -2594,52 +2851,72 @@ exports[`react-website generator > Tanstack router integration > should generate
2594
2851
  "targetDefaults": {
2595
2852
  "build": {
2596
2853
  "cache": true,
2597
- "dependsOn": ["^build"],
2598
2854
  "inputs": ["default"]
2599
2855
  },
2600
2856
  "lint": {
2601
2857
  "cache": true
2602
2858
  },
2603
- "@nx/eslint:lint": {
2604
- "cache": true,
2605
- "inputs": [
2606
- "default",
2607
- "^default",
2608
- "{workspaceRoot}/.eslintrc.json",
2609
- "{workspaceRoot}/.eslintignore",
2610
- "{workspaceRoot}/eslint.config.mjs",
2611
- "{workspaceRoot}/tools/eslint-rules/**/*"
2612
- ]
2613
- },
2614
- "@nx/vite:build": {
2615
- "cache": true,
2859
+ "test": {
2616
2860
  "dependsOn": ["^build"],
2617
- "inputs": ["default", "^default"]
2861
+ "inputs": ["default"]
2618
2862
  },
2619
2863
  "@nx/vitest:test": {
2620
2864
  "cache": true,
2621
- "inputs": ["default", "^default"],
2865
+ "inputs": ["default", "^production"],
2622
2866
  "configurations": {
2623
2867
  "update-snapshot": {
2624
2868
  "args": "--update"
2625
2869
  }
2626
2870
  }
2627
2871
  },
2628
- "test": {
2629
- "dependsOn": ["^build"],
2630
- "inputs": ["default"]
2631
- },
2632
2872
  "compile": {
2633
2873
  "cache": true,
2634
2874
  "inputs": ["default"]
2635
2875
  }
2636
2876
  },
2877
+ "plugins": [
2878
+ {
2879
+ "plugin": "@nx/js/typescript",
2880
+ "options": {
2881
+ "typecheck": {
2882
+ "targetName": "typecheck"
2883
+ },
2884
+ "build": {
2885
+ "targetName": "compile",
2886
+ "configName": "tsconfig.lib.json",
2887
+ "buildDepsName": "build-deps",
2888
+ "watchDepsName": "watch-deps"
2889
+ }
2890
+ }
2891
+ },
2892
+ {
2893
+ "plugin": "@nx/vite/plugin",
2894
+ "options": {
2895
+ "buildTargetName": "bundle",
2896
+ "serveTargetName": "serve",
2897
+ "devTargetName": "serve",
2898
+ "previewTargetName": "preview",
2899
+ "serveStaticTargetName": "serve-static",
2900
+ "typecheckTargetName": "vite:typecheck",
2901
+ "buildDepsTargetName": "build-deps",
2902
+ "watchDepsTargetName": "watch-deps"
2903
+ }
2904
+ },
2905
+ {
2906
+ "plugin": "@nx/vitest",
2907
+ "options": {
2908
+ "testTargetName": "test",
2909
+ "ciTargetName": "test-ci",
2910
+ "testMode": "watch"
2911
+ }
2912
+ }
2913
+ ],
2637
2914
  "generators": {
2638
2915
  "@nx/react": {
2639
2916
  "application": {
2640
2917
  "babel": true,
2641
2918
  "style": "css",
2642
- "linter": "eslint",
2919
+ "linter": "none",
2643
2920
  "bundler": "vite"
2644
2921
  },
2645
2922
  "component": {
@@ -2647,39 +2924,19 @@ exports[`react-website generator > Tanstack router integration > should generate
2647
2924
  },
2648
2925
  "library": {
2649
2926
  "style": "css",
2650
- "linter": "eslint"
2927
+ "linter": "none"
2651
2928
  }
2652
2929
  }
2653
2930
  },
2654
2931
  "namedInputs": {
2655
- "eslint": [
2656
- "default",
2657
- "{workspaceRoot}/eslint.config.mjs",
2658
- "{projectRoot}/eslint.config.mjs"
2659
- ],
2932
+ "biome": ["default", "{workspaceRoot}/biome.json"],
2660
2933
  "default": [
2661
2934
  {
2662
2935
  "dependentTasksOutputFiles": "**/*",
2663
2936
  "transitive": true
2664
2937
  }
2665
2938
  ]
2666
- },
2667
- "plugins": [
2668
- {
2669
- "plugin": "@nx/js/typescript",
2670
- "options": {
2671
- "typecheck": {
2672
- "targetName": "typecheck"
2673
- },
2674
- "build": {
2675
- "targetName": "compile",
2676
- "configName": "tsconfig.lib.json",
2677
- "buildDepsName": "build-deps",
2678
- "watchDepsName": "watch-deps"
2679
- }
2680
- }
2681
- }
2682
- ]
2939
+ }
2683
2940
  }
2684
2941
  "
2685
2942
  `;
@@ -2687,63 +2944,39 @@ exports[`react-website generator > Tanstack router integration > should generate
2687
2944
  exports[`react-website generator > Tanstack router integration > should generate website with router correctly > package.json 1`] = `
2688
2945
  "{
2689
2946
  "name": "@proj/source",
2690
- "dependencies": {
2691
- "@cloudscape-design/board-components": "3.0.187",
2692
- "@cloudscape-design/components": "3.0.1304",
2693
- "@cloudscape-design/global-styles": "1.0.59",
2694
- "@tanstack/react-router": "1.170.10",
2695
- "aws-cdk-lib": "2.257.0",
2696
- "constructs": "10.6.0",
2697
- "react": "19.2.7",
2698
- "react-dom": "19.2.7",
2699
- "tailwindcss": "4.3.0"
2700
- },
2947
+ "dependencies": {},
2701
2948
  "devDependencies": {
2702
- "@eslint/js": "^9.8.0",
2703
- "@nx/eslint": "22.7.5",
2704
- "@nx/eslint-plugin": "22.7.5",
2705
- "@nx/js": "22.7.5",
2706
- "@nx/react": "22.7.5",
2707
- "@nx/vite": "22.7.5",
2708
- "@nx/vitest": "22.7.5",
2709
- "@nx/web": "22.7.5",
2710
- "@swc-node/register": "~1.11.1",
2711
- "@swc/cli": "~0.8.0",
2712
- "@swc/core": "~1.15.5",
2949
+ "@nx/js": "23.1.0",
2950
+ "@nx/react": "catalog:",
2951
+ "@nx/vite": "23.1.0",
2952
+ "@nx/vitest": "23.1.0",
2953
+ "@nx/web": "23.1.0",
2713
2954
  "@swc/helpers": "~0.5.18",
2714
- "@tailwindcss/vite": "4.3.0",
2715
- "@tanstack/router-generator": "1.167.12",
2716
- "@tanstack/router-plugin": "1.168.13",
2717
- "@tanstack/router-utils": "1.162.1",
2718
- "@tanstack/virtual-file-routes": "1.162.0",
2955
+ "@tailwindcss/vite": "catalog:",
2956
+ "@tanstack/router-generator": "catalog:",
2957
+ "@tanstack/router-plugin": "catalog:",
2958
+ "@tanstack/router-utils": "catalog:",
2959
+ "@tanstack/virtual-file-routes": "catalog:",
2719
2960
  "@testing-library/dom": "10.4.0",
2720
2961
  "@testing-library/react": "16.3.0",
2721
- "@types/node": "25.9.1",
2962
+ "@types/node": "catalog:",
2722
2963
  "@types/react": "^19.0.0",
2723
2964
  "@types/react-dom": "^19.0.0",
2724
2965
  "@vitejs/plugin-react": "^6.0.0",
2725
- "@vitest/coverage-v8": "4.1.7",
2726
- "@vitest/ui": "4.1.7",
2727
- "eslint": "^9.8.0",
2728
- "eslint-config-prettier": "^10.0.0",
2729
- "eslint-plugin-import": "2.31.0",
2730
- "eslint-plugin-jsx-a11y": "6.10.1",
2731
- "eslint-plugin-prettier": "5.5.6",
2732
- "eslint-plugin-react": "7.35.0",
2733
- "eslint-plugin-react-hooks": "5.0.0",
2966
+ "@vitest/coverage-v8": "catalog:",
2967
+ "@vitest/ui": "catalog:",
2734
2968
  "jiti": "2.4.2",
2735
- "jsdom": "~22.1.0",
2736
- "jsonc-eslint-parser": "3.1.0",
2737
- "prettier": "3.8.3",
2738
- "typescript": "~5.9.2",
2739
- "typescript-eslint": "^8.40.0",
2740
- "vite": "8.0.14",
2741
- "vitest": "4.1.7"
2969
+ "jsdom": "^27.1.0",
2970
+ "typescript": "~6.0.3",
2971
+ "vite": "catalog:",
2972
+ "vitest": "catalog:"
2742
2973
  },
2743
2974
  "type": "module",
2744
- "scripts": {
2745
- "dev": "nx serve-local @proj/test-app"
2746
- }
2975
+ "workspaces": [
2976
+ "packages/*",
2977
+ "test-app",
2978
+ "packages/common/constructs"
2979
+ ]
2747
2980
  }
2748
2981
  "
2749
2982
  `;
@@ -2781,35 +3014,25 @@ You can also automatiaclly fix some lint errors by running the following command
2781
3014
 
2782
3015
  - [common-constructs reference docs](TODO)
2783
3016
  - [Learn more about NX](https://nx.dev/getting-started/intro)
3017
+
2784
3018
  "
2785
3019
  `;
2786
3020
 
2787
- exports[`react-website generator > Tanstack router integration > should generate website with router correctly > packages/common/constructs/eslint.config.mjs 1`] = `
2788
- "import baseConfig from '../../../eslint.config.mjs';
2789
-
2790
- export default [
2791
- ...baseConfig,
2792
- {
2793
- files: ['**/*.json'],
2794
- rules: {
2795
- '@nx/dependency-checks': [
2796
- 'warn',
2797
- {
2798
- ignoredFiles: [
2799
- '{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}',
2800
- '{projectRoot}/vitest.config.{js,ts,mjs,mts}',
2801
- ],
2802
- },
2803
- ],
2804
- },
2805
- languageOptions: {
2806
- parser: await import('jsonc-eslint-parser'),
2807
- },
2808
- },
2809
- {
2810
- ignores: ['**/out-tsc'],
3021
+ exports[`react-website generator > Tanstack router integration > should generate website with router correctly > packages/common/constructs/package.json 1`] = `
3022
+ "{
3023
+ "name": "@proj/common-constructs",
3024
+ "version": "0.0.1",
3025
+ "private": true,
3026
+ "type": "module",
3027
+ "dependencies": {
3028
+ "aws-cdk-lib": "catalog:",
3029
+ "constructs": "catalog:",
3030
+ "tslib": "^2.3.0"
2811
3031
  },
2812
- ];
3032
+ "devDependencies": {
3033
+ "@types/node": "catalog:"
3034
+ }
3035
+ }
2813
3036
  "
2814
3037
  `;
2815
3038
 
@@ -2820,6 +3043,9 @@ exports[`react-website generator > Tanstack router integration > should generate
2820
3043
  "sourceRoot": "packages/common/constructs/src",
2821
3044
  "projectType": "library",
2822
3045
  "tags": [],
3046
+ "metadata": {
3047
+ "generator": "ts#project"
3048
+ },
2823
3049
  "targets": {
2824
3050
  "build": {
2825
3051
  "dependsOn": ["lint", "compile", "test", "@proj/test-app:build"]
@@ -2832,29 +3058,39 @@ exports[`react-website generator > Tanstack router integration > should generate
2832
3058
  "cwd": "{projectRoot}"
2833
3059
  }
2834
3060
  },
2835
- "lint": {
2836
- "executor": "@nx/eslint:lint",
3061
+ "format": {
3062
+ "executor": "nx:run-commands",
2837
3063
  "cache": true,
2838
- "inputs": ["eslint"],
3064
+ "inputs": ["biome"],
3065
+ "options": {
3066
+ "command": "biome format {projectRoot}"
3067
+ },
2839
3068
  "configurations": {
2840
3069
  "fix": {
2841
- "fix": true
3070
+ "command": "biome format --write {projectRoot}"
2842
3071
  },
2843
3072
  "skip-lint": {
2844
- "force": true
3073
+ "command": "node -e \\"\\""
2845
3074
  }
2846
3075
  }
2847
3076
  },
2848
- "test": {
2849
- "executor": "@nx/vitest:test",
2850
- "outputs": ["{options.reportsDirectory}"],
3077
+ "lint": {
3078
+ "executor": "nx:run-commands",
3079
+ "cache": true,
3080
+ "inputs": ["biome"],
3081
+ "dependsOn": ["format"],
2851
3082
  "options": {
2852
- "reportsDirectory": "{workspaceRoot}/coverage/{projectRoot}"
3083
+ "command": "biome lint {projectRoot}"
3084
+ },
3085
+ "configurations": {
3086
+ "fix": {
3087
+ "command": "biome check --write {projectRoot}"
3088
+ },
3089
+ "skip-lint": {
3090
+ "command": "node -e \\"\\""
3091
+ }
2853
3092
  }
2854
3093
  }
2855
- },
2856
- "metadata": {
2857
- "generator": "ts#project"
2858
3094
  }
2859
3095
  }
2860
3096
  "
@@ -2965,10 +3201,31 @@ export const suppressRules = (
2965
3201
  "
2966
3202
  `;
2967
3203
 
3204
+ exports[`react-website generator > Tanstack router integration > should generate website with router correctly > packages/common/constructs/src/core/cloudfront.ts 1`] = `
3205
+ "import { CfnDistribution, Distribution } from 'aws-cdk-lib/aws-cloudfront';
3206
+
3207
+ /**
3208
+ * Finds the domain names associated with a CloudFront distribution.
3209
+ *
3210
+ * Includes the distribution's default \`*.cloudfront.net\` domain name plus any custom
3211
+ * domain names (aliases) configured on it.
3212
+ */
3213
+ export const findCloudFrontDomainNames = (
3214
+ distribution: Distribution,
3215
+ ): string[] => {
3216
+ const cfnDistribution = distribution.node.defaultChild as CfnDistribution;
3217
+ const distributionConfig =
3218
+ cfnDistribution.distributionConfig as CfnDistribution.DistributionConfigProperty;
3219
+ return [distribution.domainName, ...(distributionConfig.aliases ?? [])];
3220
+ };
3221
+ "
3222
+ `;
3223
+
2968
3224
  exports[`react-website generator > Tanstack router integration > should generate website with router correctly > packages/common/constructs/src/core/index.ts 1`] = `
2969
3225
  "export * from './static-website.js';
2970
3226
  export * from './app.js';
2971
3227
  export * from './checkov.js';
3228
+ export * from './cloudfront.js';
2972
3229
  export * from './runtime-config.js';
2973
3230
  export * from './workspace.js';
2974
3231
  "
@@ -3164,11 +3421,21 @@ exports[`react-website generator > Tanstack router integration > should generate
3164
3421
  "import {
3165
3422
  CfnOutput,
3166
3423
  CfnResource,
3424
+ Duration,
3167
3425
  Lazy,
3426
+ Names,
3168
3427
  RemovalPolicy,
3169
3428
  Stack,
3170
3429
  } from 'aws-cdk-lib';
3171
- import { Distribution, ViewerProtocolPolicy } from 'aws-cdk-lib/aws-cloudfront';
3430
+ import {
3431
+ Distribution,
3432
+ HeadersFrameOption,
3433
+ HeadersReferrerPolicy,
3434
+ ResponseHeadersPolicy,
3435
+ SecurityPolicyProtocol,
3436
+ ViewerProtocolPolicy,
3437
+ } from 'aws-cdk-lib/aws-cloudfront';
3438
+ import { ICertificate } from 'aws-cdk-lib/aws-certificatemanager';
3172
3439
  import { S3BucketOrigin } from 'aws-cdk-lib/aws-cloudfront-origins';
3173
3440
  import {
3174
3441
  BlockPublicAccess,
@@ -3177,18 +3444,56 @@ import {
3177
3444
  IBucket,
3178
3445
  ObjectOwnership,
3179
3446
  } from 'aws-cdk-lib/aws-s3';
3180
- import { BucketDeployment, Source } from 'aws-cdk-lib/aws-s3-deployment';
3447
+ import {
3448
+ BucketDeployment,
3449
+ CacheControl,
3450
+ Source,
3451
+ } from 'aws-cdk-lib/aws-s3-deployment';
3181
3452
  import { Construct } from 'constructs';
3182
3453
  import { RuntimeConfig } from './runtime-config.js';
3183
3454
  import { Key } from 'aws-cdk-lib/aws-kms';
3455
+ import {
3456
+ CfnDelivery,
3457
+ CfnDeliveryDestination,
3458
+ CfnDeliverySource,
3459
+ LogGroup,
3460
+ RetentionDays,
3461
+ } from 'aws-cdk-lib/aws-logs';
3462
+ import { Effect, PolicyStatement, ServicePrincipal } from 'aws-cdk-lib/aws-iam';
3184
3463
  import { CfnWebACL } from 'aws-cdk-lib/aws-wafv2';
3185
3464
  import { suppressRules } from './checkov.js';
3186
3465
 
3187
3466
  const DEFAULT_RUNTIME_CONFIG_FILENAME = 'runtime-config.json';
3188
3467
 
3468
+ // Content-Security-Policy enforced on all responses. Restricts scripts and
3469
+ // framing to mitigate XSS and clickjacking, while permitting HTTPS/WSS calls
3470
+ // (connect-src) to AWS service endpoints such as API Gateway, Cognito and
3471
+ // Bedrock AgentCore which are only known at deploy time. Edit this to tighten
3472
+ // connect-src to your specific origins once they are known.
3473
+ const CONTENT_SECURITY_POLICY = [
3474
+ "default-src 'self'",
3475
+ "script-src 'self'",
3476
+ "style-src 'self' 'unsafe-inline'",
3477
+ "img-src 'self' data:",
3478
+ "font-src 'self' data:",
3479
+ "connect-src 'self' https: wss:",
3480
+ "object-src 'none'",
3481
+ "base-uri 'self'",
3482
+ "frame-ancestors 'none'",
3483
+ ].join('; ');
3484
+
3189
3485
  export interface StaticWebsiteProps {
3190
3486
  readonly websiteName: string;
3191
3487
  readonly websiteFilePath: string;
3488
+ /**
3489
+ * Custom domain names for the CloudFront distribution. Requires \`certificate\`.
3490
+ */
3491
+ readonly domainNames?: string[];
3492
+ /**
3493
+ * ACM certificate for the custom domain names. Must be in us-east-1.
3494
+ * When provided, viewers are required to use TLS 1.2 or later.
3495
+ */
3496
+ readonly certificate?: ICertificate;
3192
3497
  }
3193
3498
 
3194
3499
  /**
@@ -3207,39 +3512,48 @@ export class StaticWebsite extends Construct {
3207
3512
  constructor(
3208
3513
  scope: Construct,
3209
3514
  id: string,
3210
- { websiteFilePath, websiteName }: StaticWebsiteProps,
3515
+ {
3516
+ websiteFilePath,
3517
+ websiteName,
3518
+ domainNames,
3519
+ certificate,
3520
+ }: StaticWebsiteProps,
3211
3521
  ) {
3212
3522
  super(scope, id);
3213
- this.node.setContext(
3214
- '@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy',
3215
- true,
3216
- );
3217
3523
 
3218
3524
  const websiteKey = new Key(this, 'WebsiteKey', {
3219
3525
  enableKeyRotation: true,
3220
3526
  });
3221
3527
 
3222
- const accessLogsBucket = new Bucket(this, 'AccessLogsBucket', {
3223
- versioned: false,
3224
- enforceSSL: true,
3225
- autoDeleteObjects: true,
3226
- removalPolicy: RemovalPolicy.DESTROY,
3227
- encryption: BucketEncryption.KMS,
3528
+ // Allow CloudWatch Logs to use the website key for server access log delivery.
3529
+ const stack = Stack.of(this);
3530
+ websiteKey.addToResourcePolicy(
3531
+ new PolicyStatement({
3532
+ effect: Effect.ALLOW,
3533
+ principals: [
3534
+ new ServicePrincipal(\`logs.\${stack.region}.amazonaws.com\`),
3535
+ ],
3536
+ actions: [
3537
+ 'kms:Encrypt',
3538
+ 'kms:Decrypt',
3539
+ 'kms:ReEncrypt*',
3540
+ 'kms:GenerateDataKey*',
3541
+ 'kms:DescribeKey',
3542
+ ],
3543
+ resources: ['*'],
3544
+ conditions: {
3545
+ ArnLike: {
3546
+ 'kms:EncryptionContext:aws:logs:arn': \`arn:aws:logs:\${stack.region}:\${stack.account}:log-group:*\`,
3547
+ },
3548
+ },
3549
+ }),
3550
+ );
3551
+
3552
+ const accessLogs = new LogGroup(this, 'AccessLogs', {
3553
+ retention: RetentionDays.ONE_YEAR,
3228
3554
  encryptionKey: websiteKey,
3229
- objectOwnership: ObjectOwnership.OBJECT_WRITER,
3230
- publicReadAccess: false,
3231
- blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
3555
+ removalPolicy: RemovalPolicy.DESTROY,
3232
3556
  });
3233
- suppressRules(
3234
- accessLogsBucket,
3235
- ['CKV_AWS_21'],
3236
- 'Access log bucket does not need versioning enabled',
3237
- );
3238
- suppressRules(
3239
- accessLogsBucket,
3240
- ['CKV_AWS_18'],
3241
- 'Access log bucket does not need an access log bucket',
3242
- );
3243
3557
 
3244
3558
  // S3 Bucket to hold website files
3245
3559
  this.websiteBucket = new Bucket(this, 'WebsiteBucket', {
@@ -3252,13 +3566,23 @@ export class StaticWebsite extends Construct {
3252
3566
  objectOwnership: ObjectOwnership.BUCKET_OWNER_ENFORCED,
3253
3567
  publicReadAccess: false,
3254
3568
  blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
3255
- serverAccessLogsPrefix: 'website-access-logs',
3256
- serverAccessLogsBucket: accessLogsBucket,
3257
3569
  });
3570
+ suppressRules(
3571
+ this.websiteBucket,
3572
+ ['CKV_AWS_18'],
3573
+ 'Server access logs are delivered to CloudWatch Logs',
3574
+ );
3575
+ this.deliverAccessLogsToCloudWatch(
3576
+ 'Website',
3577
+ this.websiteBucket,
3578
+ accessLogs,
3579
+ );
3258
3580
  // Web ACL
3259
3581
  const wafStack = new CloudfrontWebAcl(this, 'waf');
3260
3582
 
3261
- // Cloudfront Distribution
3583
+ // Bucket holding CloudFront standard access logs. CloudFront delivers its
3584
+ // own logs to S3 only, so this bucket is retained; its S3 server access
3585
+ // logs are delivered to CloudWatch Logs.
3262
3586
  const logBucket = new Bucket(this, 'DistributionLogBucket', {
3263
3587
  enforceSSL: true,
3264
3588
  autoDeleteObjects: true,
@@ -3268,14 +3592,48 @@ export class StaticWebsite extends Construct {
3268
3592
  objectOwnership: ObjectOwnership.BUCKET_OWNER_PREFERRED,
3269
3593
  publicReadAccess: false,
3270
3594
  blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
3271
- serverAccessLogsPrefix: 'distribution-access-logs',
3272
- serverAccessLogsBucket: accessLogsBucket,
3273
3595
  });
3274
3596
  suppressRules(
3275
3597
  logBucket,
3276
3598
  ['CKV_AWS_21'],
3277
3599
  'Distribution log bucket does not need versioning enabled',
3278
3600
  );
3601
+ suppressRules(
3602
+ logBucket,
3603
+ ['CKV_AWS_18'],
3604
+ 'Server access logs are delivered to CloudWatch Logs',
3605
+ );
3606
+ this.deliverAccessLogsToCloudWatch('Distribution', logBucket, accessLogs);
3607
+
3608
+ // Security headers applied to all responses.
3609
+ const responseHeadersPolicy = new ResponseHeadersPolicy(
3610
+ this,
3611
+ 'ResponseHeadersPolicy',
3612
+ {
3613
+ securityHeadersBehavior: {
3614
+ strictTransportSecurity: {
3615
+ accessControlMaxAge: Duration.days(730),
3616
+ includeSubdomains: true,
3617
+ preload: true,
3618
+ override: true,
3619
+ },
3620
+ contentTypeOptions: { override: true },
3621
+ frameOptions: {
3622
+ frameOption: HeadersFrameOption.DENY,
3623
+ override: true,
3624
+ },
3625
+ referrerPolicy: {
3626
+ referrerPolicy:
3627
+ HeadersReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
3628
+ override: true,
3629
+ },
3630
+ contentSecurityPolicy: {
3631
+ contentSecurityPolicy: CONTENT_SECURITY_POLICY,
3632
+ override: true,
3633
+ },
3634
+ },
3635
+ },
3636
+ );
3279
3637
 
3280
3638
  const defaultRootObject = 'index.html';
3281
3639
  this.cloudFrontDistribution = new Distribution(
@@ -3285,9 +3643,17 @@ export class StaticWebsite extends Construct {
3285
3643
  webAclId: wafStack.wafArn,
3286
3644
  enableLogging: true,
3287
3645
  logBucket: logBucket,
3646
+ ...(certificate
3647
+ ? {
3648
+ certificate,
3649
+ domainNames,
3650
+ minimumProtocolVersion: SecurityPolicyProtocol.TLS_V1_2_2021,
3651
+ }
3652
+ : {}),
3288
3653
  defaultBehavior: {
3289
3654
  origin: S3BucketOrigin.withOriginAccessControl(this.websiteBucket),
3290
3655
  viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
3656
+ responseHeadersPolicy,
3291
3657
  },
3292
3658
  defaultRootObject,
3293
3659
  errorResponses: [
@@ -3304,16 +3670,31 @@ export class StaticWebsite extends Construct {
3304
3670
  ],
3305
3671
  },
3306
3672
  );
3307
- suppressRules(
3308
- this.cloudFrontDistribution,
3309
- ['CKV_AWS_174'],
3310
- 'Cloudfront default certificate does not use TLS 1.2',
3311
- );
3673
+ if (!certificate) {
3674
+ // See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistValuesGeneral.html
3675
+ suppressRules(
3676
+ this.cloudFrontDistribution,
3677
+ ['CKV_AWS_174'],
3678
+ 'Cloudfront default certificate does not use TLS 1.2',
3679
+ );
3680
+ }
3312
3681
 
3313
3682
  // Deploy Website
3314
3683
  this.bucketDeployment = new BucketDeployment(this, 'WebsiteDeployment', {
3684
+ sources: [Source.asset(websiteFilePath)],
3685
+ destinationBucket: this.websiteBucket,
3686
+ // Files in the distribution's edge caches will be invalidated after files are uploaded to the destination bucket.
3687
+ distribution: this.cloudFrontDistribution,
3688
+ // Exclude the runtime config from this deployment's sync so its default pruning
3689
+ // never deletes the file managed separately by RuntimeConfigDeployment below.
3690
+ exclude: [DEFAULT_RUNTIME_CONFIG_FILENAME],
3691
+ memoryLimit: 1024,
3692
+ });
3693
+
3694
+ // Deploy runtime-config.json separately so it is never cached - clients
3695
+ // must always fetch the latest configuration.
3696
+ new BucketDeployment(this, 'RuntimeConfigDeployment', {
3315
3697
  sources: [
3316
- Source.asset(websiteFilePath),
3317
3698
  Source.data(
3318
3699
  DEFAULT_RUNTIME_CONFIG_FILENAME,
3319
3700
  Lazy.string({
@@ -3325,8 +3706,9 @@ export class StaticWebsite extends Construct {
3325
3706
  ),
3326
3707
  ],
3327
3708
  destinationBucket: this.websiteBucket,
3328
- // Files in the distribution's edge caches will be invalidated after files are uploaded to the destination bucket.
3329
3709
  distribution: this.cloudFrontDistribution,
3710
+ cacheControl: [CacheControl.noCache()],
3711
+ prune: false,
3330
3712
  memoryLimit: 1024,
3331
3713
  });
3332
3714
 
@@ -3347,6 +3729,44 @@ export class StaticWebsite extends Construct {
3347
3729
  value: this.websiteBucket.bucketName,
3348
3730
  });
3349
3731
  }
3732
+
3733
+ /**
3734
+ * Delivers a bucket's S3 server access logs to a CloudWatch log group using
3735
+ * CloudWatch Logs vended log delivery.
3736
+ */
3737
+ private deliverAccessLogsToCloudWatch(
3738
+ id: string,
3739
+ bucket: IBucket,
3740
+ logGroup: LogGroup,
3741
+ ) {
3742
+ const source: CfnDeliverySource = new CfnDeliverySource(
3743
+ this,
3744
+ \`\${id}AccessLogsSource\`,
3745
+ {
3746
+ name: Lazy.string({
3747
+ produce: () => Names.uniqueResourceName(source, { maxLength: 60 }),
3748
+ }),
3749
+ logType: 'S3_SERVER_ACCESS_LOGS',
3750
+ resourceArn: bucket.bucketArn,
3751
+ },
3752
+ );
3753
+ const destination: CfnDeliveryDestination = new CfnDeliveryDestination(
3754
+ this,
3755
+ \`\${id}AccessLogsDestination\`,
3756
+ {
3757
+ name: Lazy.string({
3758
+ produce: () =>
3759
+ Names.uniqueResourceName(destination, { maxLength: 60 }),
3760
+ }),
3761
+ destinationResourceArn: logGroup.logGroupArn,
3762
+ },
3763
+ );
3764
+ const delivery = new CfnDelivery(this, \`\${id}AccessLogsDelivery\`, {
3765
+ deliverySourceName: source.name,
3766
+ deliveryDestinationArn: destination.attrArn,
3767
+ });
3768
+ delivery.addDependency(source);
3769
+ }
3350
3770
  }
3351
3771
 
3352
3772
  export class CloudfrontWebAcl extends Stack {
@@ -3469,9 +3889,13 @@ exports[`react-website generator > Tanstack router integration > should generate
3469
3889
  "emitDeclarationOnly": false,
3470
3890
  "module": "nodenext",
3471
3891
  "moduleResolution": "nodenext",
3472
- "types": ["node"]
3892
+ "types": [
3893
+ "node"
3894
+ ]
3473
3895
  },
3474
- "include": ["src/**/*.ts"],
3896
+ "include": [
3897
+ "src/**/*.ts"
3898
+ ],
3475
3899
  "references": [],
3476
3900
  "exclude": [
3477
3901
  "vite.config.ts",
@@ -3537,6 +3961,7 @@ export default defineConfig(() => ({
3537
3961
  root: __dirname,
3538
3962
  cacheDir: '../../../node_modules/.vite/packages/common/constructs',
3539
3963
  test: {
3964
+ passWithNoTests: true,
3540
3965
  name: '@proj/common-constructs',
3541
3966
  watch: false,
3542
3967
  globals: true,
@@ -3547,7 +3972,6 @@ export default defineConfig(() => ({
3547
3972
  reportsDirectory: './test-output/vitest/coverage',
3548
3973
  provider: 'v8' as const,
3549
3974
  },
3550
- passWithNoTests: true,
3551
3975
  },
3552
3976
  }));
3553
3977
  "
@@ -3555,15 +3979,35 @@ export default defineConfig(() => ({
3555
3979
 
3556
3980
  exports[`react-website generator > Tanstack router integration > should generate website with router correctly > pnpm-workspace.yaml 1`] = `
3557
3981
  "packages:
3558
- - 'packages/*'
3559
- - 'test-app'
3560
- - 'packages/common/*'
3982
+ - packages/*
3983
+ - test-app
3984
+ - packages/common/*
3985
+ catalog:
3986
+ vite: 8.1.5
3987
+ vitest: 4.1.10
3988
+ '@vitest/coverage-v8': 4.1.10
3989
+ constructs: 10.7.0
3990
+ aws-cdk-lib: 2.261.0
3991
+ '@types/node': 26.1.1
3992
+ react: 19.2.7
3993
+ react-dom: 19.2.7
3994
+ '@cloudscape-design/components': 3.0.1330
3995
+ '@cloudscape-design/board-components': 3.0.205
3996
+ '@cloudscape-design/global-styles': 1.0.62
3997
+ tailwindcss: 4.3.3
3998
+ '@tanstack/react-router': 1.170.18
3999
+ '@nx/react': 23.1.0
4000
+ '@vitest/ui': 4.1.10
4001
+ '@tailwindcss/vite': 4.3.3
4002
+ '@tanstack/router-plugin': 1.168.22
4003
+ '@tanstack/router-generator': 1.167.21
4004
+ '@tanstack/virtual-file-routes': 1.162.0
4005
+ '@tanstack/router-utils': 1.162.2
3561
4006
  "
3562
4007
  `;
3563
4008
 
3564
4009
  exports[`react-website generator > Tanstack router integration > should generate website with router correctly > test-app/README.md 1`] = `
3565
4010
  "# @proj/test-app
3566
-
3567
4011
  This library was generated with [@aws/nx-plugin](https://github.com/awslabs/nx-plugin-for-aws/).
3568
4012
 
3569
4013
  ## Building
@@ -3612,24 +4056,8 @@ In order to integrate with cognito or trpc backends, you need to have a \`runtim
3612
4056
  "
3613
4057
  `;
3614
4058
 
3615
- exports[`react-website generator > Tanstack router integration > should generate website with router correctly > test-app/eslint.config.mjs 1`] = `
3616
- "import nx from '@nx/eslint-plugin';
3617
- import baseConfig from '../eslint.config.mjs';
3618
-
3619
- export default [
3620
- ...nx.configs['flat/react'],
3621
- ...baseConfig,
3622
- {
3623
- files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
3624
- // Override or add rules here
3625
- rules: {},
3626
- },
3627
- ];
3628
- "
3629
- `;
3630
-
3631
4059
  exports[`react-website generator > Tanstack router integration > should generate website with router correctly > test-app/index.html 1`] = `
3632
- "<!doctype html>
4060
+ "<!DOCTYPE html>
3633
4061
  <html lang="en">
3634
4062
  <head>
3635
4063
  <meta charset="utf-8" />
@@ -3648,6 +4076,26 @@ exports[`react-website generator > Tanstack router integration > should generate
3648
4076
  "
3649
4077
  `;
3650
4078
 
4079
+ exports[`react-website generator > Tanstack router integration > should generate website with router correctly > test-app/package.json 1`] = `
4080
+ "{
4081
+ "name": "@proj/test-app",
4082
+ "version": "0.0.1",
4083
+ "private": true,
4084
+ "type": "module",
4085
+ "dependencies": {
4086
+ "@cloudscape-design/board-components": "catalog:",
4087
+ "@cloudscape-design/components": "catalog:",
4088
+ "@cloudscape-design/global-styles": "catalog:",
4089
+ "@tanstack/react-router": "catalog:",
4090
+ "react": "catalog:",
4091
+ "react-dom": "catalog:",
4092
+ "tailwindcss": "catalog:"
4093
+ },
4094
+ "devDependencies": {}
4095
+ }
4096
+ "
4097
+ `;
4098
+
3651
4099
  exports[`react-website generator > Tanstack router integration > should generate website with router correctly > test-app/project.json 1`] = `
3652
4100
  "{
3653
4101
  "name": "@proj/test-app",
@@ -3663,29 +4111,10 @@ exports[`react-website generator > Tanstack router integration > should generate
3663
4111
  },
3664
4112
  "targets": {
3665
4113
  "build": {
3666
- "dependsOn": ["lint", "compile", "bundle", "test"],
3667
- "options": {
3668
- "outputPath": "dist/{projectRoot}/bundle"
3669
- }
3670
- },
3671
- "bundle": {
3672
- "executor": "@nx/vite:build",
3673
- "outputs": ["{options.outputPath}"],
3674
- "defaultConfiguration": "production",
3675
- "options": {
3676
- "outputPath": "dist/{projectRoot}/bundle"
3677
- },
3678
- "configurations": {
3679
- "development": {
3680
- "mode": "development"
3681
- },
3682
- "production": {
3683
- "mode": "production"
3684
- }
3685
- }
4114
+ "dependsOn": ["lint", "compile", "test", "bundle"]
3686
4115
  },
3687
4116
  "compile": {
3688
- "dependsOn": ["bundle"],
4117
+ "dependsOn": ["^build"],
3689
4118
  "executor": "nx:run-commands",
3690
4119
  "outputs": ["{workspaceRoot}/dist/{projectRoot}/tsc"],
3691
4120
  "options": {
@@ -3693,83 +4122,54 @@ exports[`react-website generator > Tanstack router integration > should generate
3693
4122
  "cwd": "{projectRoot}"
3694
4123
  }
3695
4124
  },
3696
- "lint": {
3697
- "executor": "@nx/eslint:lint",
3698
- "cache": true,
3699
- "inputs": ["eslint"],
3700
- "configurations": {
3701
- "fix": {
3702
- "fix": true
3703
- },
3704
- "skip-lint": {
3705
- "force": true
3706
- }
3707
- }
3708
- },
3709
- "load:runtime-config": {
4125
+ "dev": {
3710
4126
  "executor": "nx:run-commands",
3711
- "metadata": {
3712
- "description": "Load runtime config from your deployed stack for dev purposes. You must set your AWS CLI credentials whilst calling 'pnpm nx run @proj/test-app:load:runtime-config'"
3713
- },
4127
+ "continuous": true,
3714
4128
  "options": {
3715
- "command": "aws s3 cp s3://\`aws cloudformation describe-stacks --query \\"Stacks[?starts_with(StackName, 'proj-')][].Outputs[] | [?contains(OutputKey, 'TestAppWebsiteBucketName')].OutputValue\\" --output text\`/runtime-config.json \\"{projectRoot}/public/runtime-config.json\\""
4129
+ "command": "vite --mode local-dev",
4130
+ "cwd": "{projectRoot}"
3716
4131
  }
3717
4132
  },
3718
- "preview": {
3719
- "dependsOn": ["build"],
3720
- "executor": "@nx/vite:preview-server",
3721
- "defaultConfiguration": "development",
4133
+ "format": {
4134
+ "executor": "nx:run-commands",
4135
+ "cache": true,
4136
+ "inputs": ["biome"],
3722
4137
  "options": {
3723
- "buildTarget": "@proj/test-app:build"
4138
+ "command": "biome format {projectRoot}"
3724
4139
  },
3725
4140
  "configurations": {
3726
- "development": {
3727
- "buildTarget": "@proj/test-app:build:development"
4141
+ "fix": {
4142
+ "command": "biome format --write {projectRoot}"
3728
4143
  },
3729
- "production": {
3730
- "buildTarget": "@proj/test-app:build:production"
4144
+ "skip-lint": {
4145
+ "command": "node -e \\"\\""
3731
4146
  }
3732
4147
  }
3733
4148
  },
3734
- "serve": {
3735
- "executor": "@nx/vite:dev-server",
3736
- "defaultConfiguration": "development",
4149
+ "lint": {
4150
+ "executor": "nx:run-commands",
4151
+ "cache": true,
4152
+ "inputs": ["biome"],
3737
4153
  "options": {
3738
- "buildTarget": "@proj/test-app:build"
4154
+ "command": "biome lint {projectRoot}"
3739
4155
  },
3740
4156
  "configurations": {
3741
- "development": {
3742
- "buildTarget": "@proj/test-app:build:development",
3743
- "hmr": true
4157
+ "fix": {
4158
+ "command": "biome check --write {projectRoot}"
3744
4159
  },
3745
- "production": {
3746
- "buildTarget": "@proj/test-app:build:production",
3747
- "hmr": false
4160
+ "skip-lint": {
4161
+ "command": "node -e \\"\\""
3748
4162
  }
3749
- }
3750
- },
3751
- "serve-local": {
3752
- "executor": "@nx/vite:dev-server",
3753
- "options": {
3754
- "buildTarget": "@proj/test-app:build:development",
3755
- "hmr": true,
3756
- "mode": "serve-local"
3757
4163
  },
3758
- "continuous": true
3759
- },
3760
- "serve-static": {
3761
- "executor": "@nx/web:file-server",
3762
- "dependsOn": ["build"],
3763
- "options": {
3764
- "buildTarget": "@proj/test-app:build",
3765
- "spa": true
3766
- }
4164
+ "dependsOn": ["format"]
3767
4165
  },
3768
- "test": {
3769
- "executor": "@nx/vitest:test",
3770
- "outputs": ["{options.reportsDirectory}"],
4166
+ "load:runtime-config": {
4167
+ "executor": "nx:run-commands",
4168
+ "metadata": {
4169
+ "description": "Load runtime config from your deployed stack for dev purposes. You must set your AWS CLI credentials whilst calling 'pnpm nx run @proj/test-app:load:runtime-config'"
4170
+ },
3771
4171
  "options": {
3772
- "reportsDirectory": "{workspaceRoot}/coverage/{projectRoot}"
4172
+ "command": "aws s3 cp s3://\`aws cloudformation describe-stacks --query \\"Stacks[?starts_with(StackName, 'proj-')][].Outputs[] | [?contains(OutputKey, 'TestAppWebsiteBucketName')].OutputValue\\" --output text\`/runtime-config.json \\"{projectRoot}/public/runtime-config.json\\""
3773
4173
  }
3774
4174
  }
3775
4175
  }
@@ -4161,15 +4561,22 @@ exports[`react-website generator > Tanstack router integration > should generate
4161
4561
  "outDir": "../dist/test-app/tsc",
4162
4562
  "tsBuildInfoFile": "../dist/test-app/tsc/tsconfig.lib.tsbuildinfo",
4163
4563
  "jsx": "react-jsx",
4164
- "lib": ["DOM"],
4564
+ "lib": [
4565
+ "DOM"
4566
+ ],
4165
4567
  "types": [
4166
4568
  "node",
4167
4569
  "@nx/react/typings/cssmodule.d.ts",
4168
4570
  "@nx/react/typings/image.d.ts",
4169
4571
  "vite/client"
4170
- ]
4572
+ ],
4573
+ "rootDir": "src",
4574
+ "module": "esnext",
4575
+ "moduleResolution": "bundler"
4171
4576
  },
4172
4577
  "exclude": [
4578
+ "out-tsc",
4579
+ "dist",
4173
4580
  "src/**/*.spec.ts",
4174
4581
  "src/**/*.test.ts",
4175
4582
  "src/**/*.spec.tsx",
@@ -4183,7 +4590,12 @@ exports[`react-website generator > Tanstack router integration > should generate
4183
4590
  "vitest.config.ts",
4184
4591
  "vitest.config.mts"
4185
4592
  ],
4186
- "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"]
4593
+ "include": [
4594
+ "src/**/*.js",
4595
+ "src/**/*.jsx",
4596
+ "src/**/*.ts",
4597
+ "src/**/*.tsx"
4598
+ ]
4187
4599
  }
4188
4600
  "
4189
4601
  `;
@@ -4222,7 +4634,10 @@ exports[`react-website generator > Tanstack router integration > should generate
4222
4634
  "vitest",
4223
4635
  "@nx/react/typings/cssmodule.d.ts",
4224
4636
  "@nx/react/typings/image.d.ts"
4225
- ]
4637
+ ],
4638
+ "jsx": "react-jsx",
4639
+ "module": "esnext",
4640
+ "moduleResolution": "bundler"
4226
4641
  },
4227
4642
  "include": [
4228
4643
  "vite.config.ts",
@@ -4280,7 +4695,7 @@ export default defineConfig(() => ({
4280
4695
  // plugins: [],
4281
4696
  // },
4282
4697
  build: {
4283
- outDir: '../dist/test-app',
4698
+ outDir: '../dist/test-app/bundle',
4284
4699
  emptyOutDir: true,
4285
4700
  reportCompressedSize: true,
4286
4701
  commonjsOptions: {
@@ -4288,6 +4703,7 @@ export default defineConfig(() => ({
4288
4703
  },
4289
4704
  },
4290
4705
  test: {
4706
+ passWithNoTests: true,
4291
4707
  name: '@proj/test-app',
4292
4708
  watch: false,
4293
4709
  globals: true,
@@ -4298,9 +4714,8 @@ export default defineConfig(() => ({
4298
4714
  reportsDirectory: './test-output/vitest/coverage',
4299
4715
  provider: 'v8' as const,
4300
4716
  },
4301
- passWithNoTests: true,
4302
4717
  },
4303
- resolve: { tsconfigPaths: true },
4718
+ resolve: { tsconfigPaths: true, dedupe: ['react', 'react-dom'] },
4304
4719
  define: { global: {} },
4305
4720
  }));
4306
4721
  "
@@ -4310,9 +4725,14 @@ exports[`react-website generator > Tanstack router integration > should generate
4310
4725
  "{
4311
4726
  "compilerOptions": {
4312
4727
  "paths": {
4313
- ":proj/test-app": ["./test-app/src/index.ts"],
4314
- ":proj/common-constructs": ["./packages/common/constructs/src/index.ts"]
4728
+ "@proj/test-app": [
4729
+ "./test-app/src/index.ts"
4730
+ ],
4731
+ "@proj/common-constructs": [
4732
+ "./packages/common/constructs/src/index.ts"
4733
+ ]
4315
4734
  },
4735
+ "composite": true,
4316
4736
  "rootDir": "."
4317
4737
  }
4318
4738
  }
@@ -4321,6 +4741,9 @@ exports[`react-website generator > Tanstack router integration > should generate
4321
4741
 
4322
4742
  exports[`react-website generator > Tanstack router integration > should generate website with router correctly > tsconfig.json 1`] = `
4323
4743
  "{
4744
+ "extends": "./tsconfig.base.json",
4745
+ "files": [],
4746
+ "include": [],
4324
4747
  "references": [
4325
4748
  {
4326
4749
  "path": "./test-app"
@@ -4393,7 +4816,7 @@ export default defineConfig(() => ({
4393
4816
  // plugins: [],
4394
4817
  // },
4395
4818
  build: {
4396
- outDir: '../dist/test-app',
4819
+ outDir: '../dist/test-app/bundle',
4397
4820
  emptyOutDir: true,
4398
4821
  reportCompressedSize: true,
4399
4822
  commonjsOptions: {
@@ -4401,6 +4824,7 @@ export default defineConfig(() => ({
4401
4824
  },
4402
4825
  },
4403
4826
  test: {
4827
+ passWithNoTests: true,
4404
4828
  name: '@proj/test-app',
4405
4829
  watch: false,
4406
4830
  globals: true,
@@ -4411,9 +4835,8 @@ export default defineConfig(() => ({
4411
4835
  reportsDirectory: './test-output/vitest/coverage',
4412
4836
  provider: 'v8' as const,
4413
4837
  },
4414
- passWithNoTests: true,
4415
4838
  },
4416
- resolve: { tsconfigPaths: true },
4839
+ resolve: { tsconfigPaths: true, dedupe: ['react', 'react-dom'] },
4417
4840
  define: { global: {} },
4418
4841
  }));
4419
4842
  "
@@ -4658,6 +5081,7 @@ exports[`react-website generator > should generate shared constructs > common/co
4658
5081
  "export * from './static-website.js';
4659
5082
  export * from './app.js';
4660
5083
  export * from './checkov.js';
5084
+ export * from './cloudfront.js';
4661
5085
  export * from './runtime-config.js';
4662
5086
  export * from './workspace.js';
4663
5087
  "
@@ -4667,11 +5091,21 @@ exports[`react-website generator > should generate shared constructs > common/co
4667
5091
  "import {
4668
5092
  CfnOutput,
4669
5093
  CfnResource,
5094
+ Duration,
4670
5095
  Lazy,
5096
+ Names,
4671
5097
  RemovalPolicy,
4672
5098
  Stack,
4673
5099
  } from 'aws-cdk-lib';
4674
- import { Distribution, ViewerProtocolPolicy } from 'aws-cdk-lib/aws-cloudfront';
5100
+ import {
5101
+ Distribution,
5102
+ HeadersFrameOption,
5103
+ HeadersReferrerPolicy,
5104
+ ResponseHeadersPolicy,
5105
+ SecurityPolicyProtocol,
5106
+ ViewerProtocolPolicy,
5107
+ } from 'aws-cdk-lib/aws-cloudfront';
5108
+ import { ICertificate } from 'aws-cdk-lib/aws-certificatemanager';
4675
5109
  import { S3BucketOrigin } from 'aws-cdk-lib/aws-cloudfront-origins';
4676
5110
  import {
4677
5111
  BlockPublicAccess,
@@ -4680,18 +5114,56 @@ import {
4680
5114
  IBucket,
4681
5115
  ObjectOwnership,
4682
5116
  } from 'aws-cdk-lib/aws-s3';
4683
- import { BucketDeployment, Source } from 'aws-cdk-lib/aws-s3-deployment';
5117
+ import {
5118
+ BucketDeployment,
5119
+ CacheControl,
5120
+ Source,
5121
+ } from 'aws-cdk-lib/aws-s3-deployment';
4684
5122
  import { Construct } from 'constructs';
4685
5123
  import { RuntimeConfig } from './runtime-config.js';
4686
5124
  import { Key } from 'aws-cdk-lib/aws-kms';
5125
+ import {
5126
+ CfnDelivery,
5127
+ CfnDeliveryDestination,
5128
+ CfnDeliverySource,
5129
+ LogGroup,
5130
+ RetentionDays,
5131
+ } from 'aws-cdk-lib/aws-logs';
5132
+ import { Effect, PolicyStatement, ServicePrincipal } from 'aws-cdk-lib/aws-iam';
4687
5133
  import { CfnWebACL } from 'aws-cdk-lib/aws-wafv2';
4688
5134
  import { suppressRules } from './checkov.js';
4689
5135
 
4690
5136
  const DEFAULT_RUNTIME_CONFIG_FILENAME = 'runtime-config.json';
4691
5137
 
5138
+ // Content-Security-Policy enforced on all responses. Restricts scripts and
5139
+ // framing to mitigate XSS and clickjacking, while permitting HTTPS/WSS calls
5140
+ // (connect-src) to AWS service endpoints such as API Gateway, Cognito and
5141
+ // Bedrock AgentCore which are only known at deploy time. Edit this to tighten
5142
+ // connect-src to your specific origins once they are known.
5143
+ const CONTENT_SECURITY_POLICY = [
5144
+ "default-src 'self'",
5145
+ "script-src 'self'",
5146
+ "style-src 'self' 'unsafe-inline'",
5147
+ "img-src 'self' data:",
5148
+ "font-src 'self' data:",
5149
+ "connect-src 'self' https: wss:",
5150
+ "object-src 'none'",
5151
+ "base-uri 'self'",
5152
+ "frame-ancestors 'none'",
5153
+ ].join('; ');
5154
+
4692
5155
  export interface StaticWebsiteProps {
4693
5156
  readonly websiteName: string;
4694
5157
  readonly websiteFilePath: string;
5158
+ /**
5159
+ * Custom domain names for the CloudFront distribution. Requires \`certificate\`.
5160
+ */
5161
+ readonly domainNames?: string[];
5162
+ /**
5163
+ * ACM certificate for the custom domain names. Must be in us-east-1.
5164
+ * When provided, viewers are required to use TLS 1.2 or later.
5165
+ */
5166
+ readonly certificate?: ICertificate;
4695
5167
  }
4696
5168
 
4697
5169
  /**
@@ -4710,39 +5182,48 @@ export class StaticWebsite extends Construct {
4710
5182
  constructor(
4711
5183
  scope: Construct,
4712
5184
  id: string,
4713
- { websiteFilePath, websiteName }: StaticWebsiteProps,
5185
+ {
5186
+ websiteFilePath,
5187
+ websiteName,
5188
+ domainNames,
5189
+ certificate,
5190
+ }: StaticWebsiteProps,
4714
5191
  ) {
4715
5192
  super(scope, id);
4716
- this.node.setContext(
4717
- '@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy',
4718
- true,
4719
- );
4720
5193
 
4721
5194
  const websiteKey = new Key(this, 'WebsiteKey', {
4722
5195
  enableKeyRotation: true,
4723
5196
  });
4724
5197
 
4725
- const accessLogsBucket = new Bucket(this, 'AccessLogsBucket', {
4726
- versioned: false,
4727
- enforceSSL: true,
4728
- autoDeleteObjects: true,
4729
- removalPolicy: RemovalPolicy.DESTROY,
4730
- encryption: BucketEncryption.KMS,
5198
+ // Allow CloudWatch Logs to use the website key for server access log delivery.
5199
+ const stack = Stack.of(this);
5200
+ websiteKey.addToResourcePolicy(
5201
+ new PolicyStatement({
5202
+ effect: Effect.ALLOW,
5203
+ principals: [
5204
+ new ServicePrincipal(\`logs.\${stack.region}.amazonaws.com\`),
5205
+ ],
5206
+ actions: [
5207
+ 'kms:Encrypt',
5208
+ 'kms:Decrypt',
5209
+ 'kms:ReEncrypt*',
5210
+ 'kms:GenerateDataKey*',
5211
+ 'kms:DescribeKey',
5212
+ ],
5213
+ resources: ['*'],
5214
+ conditions: {
5215
+ ArnLike: {
5216
+ 'kms:EncryptionContext:aws:logs:arn': \`arn:aws:logs:\${stack.region}:\${stack.account}:log-group:*\`,
5217
+ },
5218
+ },
5219
+ }),
5220
+ );
5221
+
5222
+ const accessLogs = new LogGroup(this, 'AccessLogs', {
5223
+ retention: RetentionDays.ONE_YEAR,
4731
5224
  encryptionKey: websiteKey,
4732
- objectOwnership: ObjectOwnership.OBJECT_WRITER,
4733
- publicReadAccess: false,
4734
- blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
5225
+ removalPolicy: RemovalPolicy.DESTROY,
4735
5226
  });
4736
- suppressRules(
4737
- accessLogsBucket,
4738
- ['CKV_AWS_21'],
4739
- 'Access log bucket does not need versioning enabled',
4740
- );
4741
- suppressRules(
4742
- accessLogsBucket,
4743
- ['CKV_AWS_18'],
4744
- 'Access log bucket does not need an access log bucket',
4745
- );
4746
5227
 
4747
5228
  // S3 Bucket to hold website files
4748
5229
  this.websiteBucket = new Bucket(this, 'WebsiteBucket', {
@@ -4755,13 +5236,23 @@ export class StaticWebsite extends Construct {
4755
5236
  objectOwnership: ObjectOwnership.BUCKET_OWNER_ENFORCED,
4756
5237
  publicReadAccess: false,
4757
5238
  blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
4758
- serverAccessLogsPrefix: 'website-access-logs',
4759
- serverAccessLogsBucket: accessLogsBucket,
4760
5239
  });
5240
+ suppressRules(
5241
+ this.websiteBucket,
5242
+ ['CKV_AWS_18'],
5243
+ 'Server access logs are delivered to CloudWatch Logs',
5244
+ );
5245
+ this.deliverAccessLogsToCloudWatch(
5246
+ 'Website',
5247
+ this.websiteBucket,
5248
+ accessLogs,
5249
+ );
4761
5250
  // Web ACL
4762
5251
  const wafStack = new CloudfrontWebAcl(this, 'waf');
4763
5252
 
4764
- // Cloudfront Distribution
5253
+ // Bucket holding CloudFront standard access logs. CloudFront delivers its
5254
+ // own logs to S3 only, so this bucket is retained; its S3 server access
5255
+ // logs are delivered to CloudWatch Logs.
4765
5256
  const logBucket = new Bucket(this, 'DistributionLogBucket', {
4766
5257
  enforceSSL: true,
4767
5258
  autoDeleteObjects: true,
@@ -4771,14 +5262,48 @@ export class StaticWebsite extends Construct {
4771
5262
  objectOwnership: ObjectOwnership.BUCKET_OWNER_PREFERRED,
4772
5263
  publicReadAccess: false,
4773
5264
  blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
4774
- serverAccessLogsPrefix: 'distribution-access-logs',
4775
- serverAccessLogsBucket: accessLogsBucket,
4776
5265
  });
4777
5266
  suppressRules(
4778
5267
  logBucket,
4779
5268
  ['CKV_AWS_21'],
4780
5269
  'Distribution log bucket does not need versioning enabled',
4781
5270
  );
5271
+ suppressRules(
5272
+ logBucket,
5273
+ ['CKV_AWS_18'],
5274
+ 'Server access logs are delivered to CloudWatch Logs',
5275
+ );
5276
+ this.deliverAccessLogsToCloudWatch('Distribution', logBucket, accessLogs);
5277
+
5278
+ // Security headers applied to all responses.
5279
+ const responseHeadersPolicy = new ResponseHeadersPolicy(
5280
+ this,
5281
+ 'ResponseHeadersPolicy',
5282
+ {
5283
+ securityHeadersBehavior: {
5284
+ strictTransportSecurity: {
5285
+ accessControlMaxAge: Duration.days(730),
5286
+ includeSubdomains: true,
5287
+ preload: true,
5288
+ override: true,
5289
+ },
5290
+ contentTypeOptions: { override: true },
5291
+ frameOptions: {
5292
+ frameOption: HeadersFrameOption.DENY,
5293
+ override: true,
5294
+ },
5295
+ referrerPolicy: {
5296
+ referrerPolicy:
5297
+ HeadersReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN,
5298
+ override: true,
5299
+ },
5300
+ contentSecurityPolicy: {
5301
+ contentSecurityPolicy: CONTENT_SECURITY_POLICY,
5302
+ override: true,
5303
+ },
5304
+ },
5305
+ },
5306
+ );
4782
5307
 
4783
5308
  const defaultRootObject = 'index.html';
4784
5309
  this.cloudFrontDistribution = new Distribution(
@@ -4788,9 +5313,17 @@ export class StaticWebsite extends Construct {
4788
5313
  webAclId: wafStack.wafArn,
4789
5314
  enableLogging: true,
4790
5315
  logBucket: logBucket,
5316
+ ...(certificate
5317
+ ? {
5318
+ certificate,
5319
+ domainNames,
5320
+ minimumProtocolVersion: SecurityPolicyProtocol.TLS_V1_2_2021,
5321
+ }
5322
+ : {}),
4791
5323
  defaultBehavior: {
4792
5324
  origin: S3BucketOrigin.withOriginAccessControl(this.websiteBucket),
4793
5325
  viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
5326
+ responseHeadersPolicy,
4794
5327
  },
4795
5328
  defaultRootObject,
4796
5329
  errorResponses: [
@@ -4807,16 +5340,31 @@ export class StaticWebsite extends Construct {
4807
5340
  ],
4808
5341
  },
4809
5342
  );
4810
- suppressRules(
4811
- this.cloudFrontDistribution,
4812
- ['CKV_AWS_174'],
4813
- 'Cloudfront default certificate does not use TLS 1.2',
4814
- );
5343
+ if (!certificate) {
5344
+ // See https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistValuesGeneral.html
5345
+ suppressRules(
5346
+ this.cloudFrontDistribution,
5347
+ ['CKV_AWS_174'],
5348
+ 'Cloudfront default certificate does not use TLS 1.2',
5349
+ );
5350
+ }
4815
5351
 
4816
5352
  // Deploy Website
4817
5353
  this.bucketDeployment = new BucketDeployment(this, 'WebsiteDeployment', {
5354
+ sources: [Source.asset(websiteFilePath)],
5355
+ destinationBucket: this.websiteBucket,
5356
+ // Files in the distribution's edge caches will be invalidated after files are uploaded to the destination bucket.
5357
+ distribution: this.cloudFrontDistribution,
5358
+ // Exclude the runtime config from this deployment's sync so its default pruning
5359
+ // never deletes the file managed separately by RuntimeConfigDeployment below.
5360
+ exclude: [DEFAULT_RUNTIME_CONFIG_FILENAME],
5361
+ memoryLimit: 1024,
5362
+ });
5363
+
5364
+ // Deploy runtime-config.json separately so it is never cached - clients
5365
+ // must always fetch the latest configuration.
5366
+ new BucketDeployment(this, 'RuntimeConfigDeployment', {
4818
5367
  sources: [
4819
- Source.asset(websiteFilePath),
4820
5368
  Source.data(
4821
5369
  DEFAULT_RUNTIME_CONFIG_FILENAME,
4822
5370
  Lazy.string({
@@ -4828,8 +5376,9 @@ export class StaticWebsite extends Construct {
4828
5376
  ),
4829
5377
  ],
4830
5378
  destinationBucket: this.websiteBucket,
4831
- // Files in the distribution's edge caches will be invalidated after files are uploaded to the destination bucket.
4832
5379
  distribution: this.cloudFrontDistribution,
5380
+ cacheControl: [CacheControl.noCache()],
5381
+ prune: false,
4833
5382
  memoryLimit: 1024,
4834
5383
  });
4835
5384
 
@@ -4850,6 +5399,44 @@ export class StaticWebsite extends Construct {
4850
5399
  value: this.websiteBucket.bucketName,
4851
5400
  });
4852
5401
  }
5402
+
5403
+ /**
5404
+ * Delivers a bucket's S3 server access logs to a CloudWatch log group using
5405
+ * CloudWatch Logs vended log delivery.
5406
+ */
5407
+ private deliverAccessLogsToCloudWatch(
5408
+ id: string,
5409
+ bucket: IBucket,
5410
+ logGroup: LogGroup,
5411
+ ) {
5412
+ const source: CfnDeliverySource = new CfnDeliverySource(
5413
+ this,
5414
+ \`\${id}AccessLogsSource\`,
5415
+ {
5416
+ name: Lazy.string({
5417
+ produce: () => Names.uniqueResourceName(source, { maxLength: 60 }),
5418
+ }),
5419
+ logType: 'S3_SERVER_ACCESS_LOGS',
5420
+ resourceArn: bucket.bucketArn,
5421
+ },
5422
+ );
5423
+ const destination: CfnDeliveryDestination = new CfnDeliveryDestination(
5424
+ this,
5425
+ \`\${id}AccessLogsDestination\`,
5426
+ {
5427
+ name: Lazy.string({
5428
+ produce: () =>
5429
+ Names.uniqueResourceName(destination, { maxLength: 60 }),
5430
+ }),
5431
+ destinationResourceArn: logGroup.logGroupArn,
5432
+ },
5433
+ );
5434
+ const delivery = new CfnDelivery(this, \`\${id}AccessLogsDelivery\`, {
5435
+ deliverySourceName: source.name,
5436
+ deliveryDestinationArn: destination.attrArn,
5437
+ });
5438
+ delivery.addDependency(source);
5439
+ }
4853
5440
  }
4854
5441
 
4855
5442
  export class CloudfrontWebAcl extends Stack {
@@ -4973,19 +5560,7 @@ root &&
4973
5560
  "
4974
5561
  `;
4975
5562
 
4976
- exports[`react-website generator > should handle npm scope prefix correctly > scoped-dependencies 1`] = `
4977
- {
4978
- "@cloudscape-design/board-components": "3.0.187",
4979
- "@cloudscape-design/components": "3.0.1304",
4980
- "@cloudscape-design/global-styles": "1.0.59",
4981
- "@tanstack/react-router": "1.170.10",
4982
- "aws-cdk-lib": "2.257.0",
4983
- "constructs": "10.6.0",
4984
- "react": "19.2.7",
4985
- "react-dom": "19.2.7",
4986
- "tailwindcss": "4.3.0",
4987
- }
4988
- `;
5563
+ exports[`react-website generator > should handle npm scope prefix correctly > scoped-dependencies 1`] = `{}`;
4989
5564
 
4990
5565
  exports[`react-website generator ux tests > Cloudscape > should update package.json with required dependencies > test-app/src/components/AppLayout/index.tsx 1`] = `
4991
5566
  "import * as React from 'react';
@@ -5331,8 +5906,8 @@ import {
5331
5906
  SidebarInset,
5332
5907
  SidebarProvider,
5333
5908
  SidebarTrigger,
5334
- } from ':proj/common-shadcn/components/ui/sidebar';
5335
- import { Separator } from ':proj/common-shadcn/components/ui/separator';
5909
+ } from '@proj/common-shadcn/components/ui/sidebar';
5910
+ import { Separator } from '@proj/common-shadcn/components/ui/separator';
5336
5911
  import Config from '../../config';
5337
5912
 
5338
5913
  import { Link, useLocation, useMatchRoute } from '@tanstack/react-router';
@@ -5343,7 +5918,7 @@ import {
5343
5918
  BreadcrumbList,
5344
5919
  BreadcrumbPage,
5345
5920
  BreadcrumbSeparator,
5346
- } from ':proj/common-shadcn/components/ui/breadcrumb';
5921
+ } from '@proj/common-shadcn/components/ui/breadcrumb';
5347
5922
  import { AppSidebar } from '../app-sidebar';
5348
5923
 
5349
5924
  const getBreadcrumbs = (
@@ -5454,7 +6029,7 @@ import {
5454
6029
  Alert as ShadcnAlert,
5455
6030
  AlertDescription,
5456
6031
  AlertTitle,
5457
- } from ':proj/common-shadcn/components/ui/alert';
6032
+ } from '@proj/common-shadcn/components/ui/alert';
5458
6033
 
5459
6034
  type AlertType = 'info' | 'error';
5460
6035
 
@@ -5494,7 +6069,7 @@ import {
5494
6069
  SidebarMenu,
5495
6070
  SidebarMenuButton,
5496
6071
  SidebarMenuItem,
5497
- } from ':proj/common-shadcn/components/ui/sidebar';
6072
+ } from '@proj/common-shadcn/components/ui/sidebar';
5498
6073
  import { Link } from '@tanstack/react-router';
5499
6074
 
5500
6075
  import Config from '../config';
@@ -5536,7 +6111,7 @@ export function AppSidebar() {
5536
6111
  `;
5537
6112
 
5538
6113
  exports[`react-website generator ux tests > Shadcn > should update package.json with required dependencies > test-app/src/components/spinner.tsx 1`] = `
5539
- "import { Spinner as ShadcnSpinner } from ':proj/common-shadcn/components/ui/spinner';
6114
+ "import { Spinner as ShadcnSpinner } from '@proj/common-shadcn/components/ui/spinner';
5540
6115
 
5541
6116
  export const Spinner = ShadcnSpinner;
5542
6117
  "
@@ -5687,6 +6262,5 @@ function RouteComponent() {
5687
6262
 
5688
6263
  exports[`react-website generator ux tests > Shadcn > should update package.json with required dependencies > test-app/src/styles.css 1`] = `
5689
6264
  "@import '../../packages/common/shadcn/src/styles/globals.css';
5690
- @source './**/*.{ts,tsx}';
5691
- "
6265
+ @source './**/*.{ts,tsx}';"
5692
6266
  `;