@aws-blocks/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (394) hide show
  1. package/LICENSE +174 -0
  2. package/dist/api.d.ts +147 -0
  3. package/dist/api.d.ts.map +1 -0
  4. package/dist/api.js +10 -0
  5. package/dist/api.test.d.ts +2 -0
  6. package/dist/api.test.d.ts.map +1 -0
  7. package/dist/api.test.js +19 -0
  8. package/dist/bb-utils.d.ts +11 -0
  9. package/dist/bb-utils.d.ts.map +1 -0
  10. package/dist/bb-utils.js +12 -0
  11. package/dist/builtin-routes.d.ts +6 -0
  12. package/dist/builtin-routes.d.ts.map +1 -0
  13. package/dist/builtin-routes.js +57 -0
  14. package/dist/cdk/__fixtures__/factory-backend.d.ts +3 -0
  15. package/dist/cdk/__fixtures__/factory-backend.d.ts.map +1 -0
  16. package/dist/cdk/__fixtures__/factory-backend.js +6 -0
  17. package/dist/cdk/__fixtures__/fullid-construct-backend.d.ts +2 -0
  18. package/dist/cdk/__fixtures__/fullid-construct-backend.d.ts.map +1 -0
  19. package/dist/cdk/__fixtures__/fullid-construct-backend.js +37 -0
  20. package/dist/cdk/__fixtures__/handler.d.ts +5 -0
  21. package/dist/cdk/__fixtures__/handler.d.ts.map +1 -0
  22. package/dist/cdk/__fixtures__/handler.js +3 -0
  23. package/dist/cdk/__fixtures__/side-effect-backend.d.ts +2 -0
  24. package/dist/cdk/__fixtures__/side-effect-backend.d.ts.map +1 -0
  25. package/dist/cdk/__fixtures__/side-effect-backend.js +5 -0
  26. package/dist/cdk/blocks-backend.d.ts +68 -0
  27. package/dist/cdk/blocks-backend.d.ts.map +1 -0
  28. package/dist/cdk/blocks-backend.js +214 -0
  29. package/dist/cdk/blocks-backend.test.d.ts +2 -0
  30. package/dist/cdk/blocks-backend.test.d.ts.map +1 -0
  31. package/dist/cdk/blocks-backend.test.js +151 -0
  32. package/dist/cdk/blocks-stack.test.d.ts +2 -0
  33. package/dist/cdk/blocks-stack.test.d.ts.map +1 -0
  34. package/dist/cdk/blocks-stack.test.js +78 -0
  35. package/dist/cdk/config-registry.d.ts +26 -0
  36. package/dist/cdk/config-registry.d.ts.map +1 -0
  37. package/dist/cdk/config-registry.js +80 -0
  38. package/dist/cdk/index.d.ts +35 -0
  39. package/dist/cdk/index.d.ts.map +1 -0
  40. package/dist/cdk/index.js +90 -0
  41. package/dist/cdk/mixins.d.ts +28 -0
  42. package/dist/cdk/mixins.d.ts.map +1 -0
  43. package/dist/cdk/mixins.js +37 -0
  44. package/dist/cdk/mixins.test.d.ts +2 -0
  45. package/dist/cdk/mixins.test.d.ts.map +1 -0
  46. package/dist/cdk/mixins.test.js +108 -0
  47. package/dist/cdk/node-version.d.ts +14 -0
  48. package/dist/cdk/node-version.d.ts.map +1 -0
  49. package/dist/cdk/node-version.js +15 -0
  50. package/dist/cdk/stack-metadata.d.ts +12 -0
  51. package/dist/cdk/stack-metadata.d.ts.map +1 -0
  52. package/dist/cdk/stack-metadata.js +22 -0
  53. package/dist/cdk/stack-metadata.test.d.ts +2 -0
  54. package/dist/cdk/stack-metadata.test.d.ts.map +1 -0
  55. package/dist/cdk/stack-metadata.test.js +56 -0
  56. package/dist/cdk/synth-guard.d.ts +14 -0
  57. package/dist/cdk/synth-guard.d.ts.map +1 -0
  58. package/dist/cdk/synth-guard.js +20 -0
  59. package/dist/cdk/synth-guard.test.d.ts +2 -0
  60. package/dist/cdk/synth-guard.test.d.ts.map +1 -0
  61. package/dist/cdk/synth-guard.test.js +15 -0
  62. package/dist/client/index.d.ts +97 -0
  63. package/dist/client/index.d.ts.map +1 -0
  64. package/dist/client/index.js +238 -0
  65. package/dist/client/index.test.d.ts +2 -0
  66. package/dist/client/index.test.d.ts.map +1 -0
  67. package/dist/client/index.test.js +113 -0
  68. package/dist/common/config.d.ts +45 -0
  69. package/dist/common/config.d.ts.map +1 -0
  70. package/dist/common/config.js +154 -0
  71. package/dist/common/config.test.d.ts +2 -0
  72. package/dist/common/config.test.d.ts.map +1 -0
  73. package/dist/common/config.test.js +173 -0
  74. package/dist/common/constants.d.ts +11 -0
  75. package/dist/common/constants.d.ts.map +1 -0
  76. package/dist/common/constants.js +12 -0
  77. package/dist/common/crypto.d.ts +6 -0
  78. package/dist/common/crypto.d.ts.map +1 -0
  79. package/dist/common/crypto.js +14 -0
  80. package/dist/common/index.d.ts +220 -0
  81. package/dist/common/index.d.ts.map +1 -0
  82. package/dist/common/index.js +180 -0
  83. package/dist/common/index.test.d.ts +2 -0
  84. package/dist/common/index.test.d.ts.map +1 -0
  85. package/dist/common/index.test.js +195 -0
  86. package/dist/common/mock-data.d.ts +40 -0
  87. package/dist/common/mock-data.d.ts.map +1 -0
  88. package/dist/common/mock-data.js +39 -0
  89. package/dist/common/official-bb-names.generated.d.ts +7 -0
  90. package/dist/common/official-bb-names.generated.d.ts.map +1 -0
  91. package/dist/common/official-bb-names.generated.js +28 -0
  92. package/dist/common/sdk-registry.d.ts +136 -0
  93. package/dist/common/sdk-registry.d.ts.map +1 -0
  94. package/dist/common/sdk-registry.js +125 -0
  95. package/dist/constants.d.ts +27 -0
  96. package/dist/constants.d.ts.map +1 -0
  97. package/dist/constants.js +28 -0
  98. package/dist/cors.d.ts +39 -0
  99. package/dist/cors.d.ts.map +1 -0
  100. package/dist/cors.js +85 -0
  101. package/dist/cors.test.d.ts +2 -0
  102. package/dist/cors.test.d.ts.map +1 -0
  103. package/dist/cors.test.js +241 -0
  104. package/dist/db-naming.d.ts +21 -0
  105. package/dist/db-naming.d.ts.map +1 -0
  106. package/dist/db-naming.js +38 -0
  107. package/dist/db-naming.test.d.ts +2 -0
  108. package/dist/db-naming.test.d.ts.map +1 -0
  109. package/dist/db-naming.test.js +29 -0
  110. package/dist/errors.d.ts +67 -0
  111. package/dist/errors.d.ts.map +1 -0
  112. package/dist/errors.js +69 -0
  113. package/dist/hosting.d.ts +258 -0
  114. package/dist/hosting.d.ts.map +1 -0
  115. package/dist/hosting.js +340 -0
  116. package/dist/hosting.test.d.ts +2 -0
  117. package/dist/hosting.test.d.ts.map +1 -0
  118. package/dist/hosting.test.js +1077 -0
  119. package/dist/index.cdk.d.ts +13 -0
  120. package/dist/index.cdk.d.ts.map +1 -0
  121. package/dist/index.cdk.js +13 -0
  122. package/dist/index.d.ts +9 -0
  123. package/dist/index.d.ts.map +1 -0
  124. package/dist/index.js +10 -0
  125. package/dist/lambda-handler.d.ts +131 -0
  126. package/dist/lambda-handler.d.ts.map +1 -0
  127. package/dist/lambda-handler.js +610 -0
  128. package/dist/lambda-handler.test.d.ts +2 -0
  129. package/dist/lambda-handler.test.d.ts.map +1 -0
  130. package/dist/lambda-handler.test.js +835 -0
  131. package/dist/pipeline/index.d.ts +4 -0
  132. package/dist/pipeline/index.d.ts.map +1 -0
  133. package/dist/pipeline/index.js +3 -0
  134. package/dist/pipeline/pipeline-construct.d.ts +130 -0
  135. package/dist/pipeline/pipeline-construct.d.ts.map +1 -0
  136. package/dist/pipeline/pipeline-construct.js +484 -0
  137. package/dist/pipeline/pipeline.test.d.ts +2 -0
  138. package/dist/pipeline/pipeline.test.d.ts.map +1 -0
  139. package/dist/pipeline/pipeline.test.js +1231 -0
  140. package/dist/pipeline/types.d.ts +351 -0
  141. package/dist/pipeline/types.d.ts.map +1 -0
  142. package/dist/pipeline/types.js +3 -0
  143. package/dist/raw-route.cdk.d.ts +47 -0
  144. package/dist/raw-route.cdk.d.ts.map +1 -0
  145. package/dist/raw-route.cdk.js +51 -0
  146. package/dist/raw-route.d.ts +119 -0
  147. package/dist/raw-route.d.ts.map +1 -0
  148. package/dist/raw-route.js +239 -0
  149. package/dist/raw-route.mock.d.ts +47 -0
  150. package/dist/raw-route.mock.d.ts.map +1 -0
  151. package/dist/raw-route.mock.js +51 -0
  152. package/dist/raw-route.test.d.ts +2 -0
  153. package/dist/raw-route.test.d.ts.map +1 -0
  154. package/dist/raw-route.test.js +597 -0
  155. package/dist/redact.d.ts +51 -0
  156. package/dist/redact.d.ts.map +1 -0
  157. package/dist/redact.js +134 -0
  158. package/dist/redact.test.d.ts +2 -0
  159. package/dist/redact.test.d.ts.map +1 -0
  160. package/dist/redact.test.js +199 -0
  161. package/dist/rpc.d.ts +54 -0
  162. package/dist/rpc.d.ts.map +1 -0
  163. package/dist/rpc.js +127 -0
  164. package/dist/rpc.test.d.ts +2 -0
  165. package/dist/rpc.test.d.ts.map +1 -0
  166. package/dist/rpc.test.js +60 -0
  167. package/dist/scripts/cdk-telemetry-env.d.ts +13 -0
  168. package/dist/scripts/cdk-telemetry-env.d.ts.map +1 -0
  169. package/dist/scripts/cdk-telemetry-env.js +21 -0
  170. package/dist/scripts/cdk-telemetry-env.test.d.ts +2 -0
  171. package/dist/scripts/cdk-telemetry-env.test.d.ts.map +1 -0
  172. package/dist/scripts/cdk-telemetry-env.test.js +56 -0
  173. package/dist/scripts/cleanup.d.ts +3 -0
  174. package/dist/scripts/cleanup.d.ts.map +1 -0
  175. package/dist/scripts/cleanup.js +35 -0
  176. package/dist/scripts/console.d.ts +6 -0
  177. package/dist/scripts/console.d.ts.map +1 -0
  178. package/dist/scripts/console.js +25 -0
  179. package/dist/scripts/deploy.d.ts +6 -0
  180. package/dist/scripts/deploy.d.ts.map +1 -0
  181. package/dist/scripts/deploy.js +82 -0
  182. package/dist/scripts/destroy.d.ts +6 -0
  183. package/dist/scripts/destroy.d.ts.map +1 -0
  184. package/dist/scripts/destroy.js +30 -0
  185. package/dist/scripts/dev-server-cors.test.d.ts +2 -0
  186. package/dist/scripts/dev-server-cors.test.d.ts.map +1 -0
  187. package/dist/scripts/dev-server-cors.test.js +23 -0
  188. package/dist/scripts/dev-server-telemetry.test.d.ts +2 -0
  189. package/dist/scripts/dev-server-telemetry.test.d.ts.map +1 -0
  190. package/dist/scripts/dev-server-telemetry.test.js +113 -0
  191. package/dist/scripts/dev-server.d.ts +21 -0
  192. package/dist/scripts/dev-server.d.ts.map +1 -0
  193. package/dist/scripts/dev-server.js +456 -0
  194. package/dist/scripts/ensure-secrets.d.ts +31 -0
  195. package/dist/scripts/ensure-secrets.d.ts.map +1 -0
  196. package/dist/scripts/ensure-secrets.js +100 -0
  197. package/dist/scripts/ensure-secrets.test.d.ts +2 -0
  198. package/dist/scripts/ensure-secrets.test.d.ts.map +1 -0
  199. package/dist/scripts/ensure-secrets.test.js +44 -0
  200. package/dist/scripts/external-migrations-step.d.ts +62 -0
  201. package/dist/scripts/external-migrations-step.d.ts.map +1 -0
  202. package/dist/scripts/external-migrations-step.js +243 -0
  203. package/dist/scripts/external-migrations-step.test.d.ts +2 -0
  204. package/dist/scripts/external-migrations-step.test.d.ts.map +1 -0
  205. package/dist/scripts/external-migrations-step.test.js +47 -0
  206. package/dist/scripts/extract-ts-types.d.ts +65 -0
  207. package/dist/scripts/extract-ts-types.d.ts.map +1 -0
  208. package/dist/scripts/extract-ts-types.js +664 -0
  209. package/dist/scripts/extract-ts-types.test.d.ts +2 -0
  210. package/dist/scripts/extract-ts-types.test.d.ts.map +1 -0
  211. package/dist/scripts/extract-ts-types.test.js +497 -0
  212. package/dist/scripts/generate-client-worker.d.ts +2 -0
  213. package/dist/scripts/generate-client-worker.d.ts.map +1 -0
  214. package/dist/scripts/generate-client-worker.js +13 -0
  215. package/dist/scripts/generate-client.d.ts +14 -0
  216. package/dist/scripts/generate-client.d.ts.map +1 -0
  217. package/dist/scripts/generate-client.js +73 -0
  218. package/dist/scripts/generate-client.test.d.ts +2 -0
  219. package/dist/scripts/generate-client.test.d.ts.map +1 -0
  220. package/dist/scripts/generate-client.test.js +48 -0
  221. package/dist/scripts/generate-spec-cli.d.ts +3 -0
  222. package/dist/scripts/generate-spec-cli.d.ts.map +1 -0
  223. package/dist/scripts/generate-spec-cli.js +77 -0
  224. package/dist/scripts/generate-spec-cli.test.d.ts +14 -0
  225. package/dist/scripts/generate-spec-cli.test.d.ts.map +1 -0
  226. package/dist/scripts/generate-spec-cli.test.js +90 -0
  227. package/dist/scripts/generate-spec.d.ts +61 -0
  228. package/dist/scripts/generate-spec.d.ts.map +1 -0
  229. package/dist/scripts/generate-spec.js +746 -0
  230. package/dist/scripts/generate-spec.test.d.ts +12 -0
  231. package/dist/scripts/generate-spec.test.d.ts.map +1 -0
  232. package/dist/scripts/generate-spec.test.js +88 -0
  233. package/dist/scripts/index.d.ts +12 -0
  234. package/dist/scripts/index.d.ts.map +1 -0
  235. package/dist/scripts/index.js +13 -0
  236. package/dist/scripts/sandbox.d.ts +11 -0
  237. package/dist/scripts/sandbox.d.ts.map +1 -0
  238. package/dist/scripts/sandbox.js +200 -0
  239. package/dist/scripts/telemetry-cli.d.ts +3 -0
  240. package/dist/scripts/telemetry-cli.d.ts.map +1 -0
  241. package/dist/scripts/telemetry-cli.js +8 -0
  242. package/dist/scripts/telemetry.d.ts +17 -0
  243. package/dist/scripts/telemetry.d.ts.map +1 -0
  244. package/dist/scripts/telemetry.js +150 -0
  245. package/dist/scripts/telemetry.test.d.ts +2 -0
  246. package/dist/scripts/telemetry.test.d.ts.map +1 -0
  247. package/dist/scripts/telemetry.test.js +203 -0
  248. package/dist/scripts/validate-spec.d.ts +22 -0
  249. package/dist/scripts/validate-spec.d.ts.map +1 -0
  250. package/dist/scripts/validate-spec.js +159 -0
  251. package/dist/server/index.d.ts +3 -0
  252. package/dist/server/index.d.ts.map +1 -0
  253. package/dist/server/index.js +3 -0
  254. package/dist/server/withAuth.d.ts +142 -0
  255. package/dist/server/withAuth.d.ts.map +1 -0
  256. package/dist/server/withAuth.js +261 -0
  257. package/dist/server/withAuth.test.d.ts +2 -0
  258. package/dist/server/withAuth.test.d.ts.map +1 -0
  259. package/dist/server/withAuth.test.js +278 -0
  260. package/dist/telemetry/client.d.ts +59 -0
  261. package/dist/telemetry/client.d.ts.map +1 -0
  262. package/dist/telemetry/client.js +215 -0
  263. package/dist/telemetry/config-writer.d.ts +16 -0
  264. package/dist/telemetry/config-writer.d.ts.map +1 -0
  265. package/dist/telemetry/config-writer.js +36 -0
  266. package/dist/telemetry/consent-commands.test.d.ts +2 -0
  267. package/dist/telemetry/consent-commands.test.d.ts.map +1 -0
  268. package/dist/telemetry/consent-commands.test.js +161 -0
  269. package/dist/telemetry/consent.d.ts +60 -0
  270. package/dist/telemetry/consent.d.ts.map +1 -0
  271. package/dist/telemetry/consent.js +122 -0
  272. package/dist/telemetry/environment.d.ts +33 -0
  273. package/dist/telemetry/environment.d.ts.map +1 -0
  274. package/dist/telemetry/environment.js +87 -0
  275. package/dist/telemetry/identifiers.d.ts +20 -0
  276. package/dist/telemetry/identifiers.d.ts.map +1 -0
  277. package/dist/telemetry/identifiers.js +86 -0
  278. package/dist/telemetry/index.d.ts +6 -0
  279. package/dist/telemetry/index.d.ts.map +1 -0
  280. package/dist/telemetry/index.js +4 -0
  281. package/dist/telemetry/telemetry.test.d.ts +2 -0
  282. package/dist/telemetry/telemetry.test.d.ts.map +1 -0
  283. package/dist/telemetry/telemetry.test.js +1131 -0
  284. package/dist/telemetry/trackCommand.d.ts +32 -0
  285. package/dist/telemetry/trackCommand.d.ts.map +1 -0
  286. package/dist/telemetry/trackCommand.js +102 -0
  287. package/dist/telemetry/types.d.ts +92 -0
  288. package/dist/telemetry/types.d.ts.map +1 -0
  289. package/dist/telemetry/types.js +1 -0
  290. package/dist/types.d.ts +24 -0
  291. package/dist/types.d.ts.map +1 -0
  292. package/dist/types.js +3 -0
  293. package/dist/version.d.ts +2 -0
  294. package/dist/version.d.ts.map +1 -0
  295. package/dist/version.js +2 -0
  296. package/package.json +83 -0
  297. package/src/api.test.ts +25 -0
  298. package/src/api.ts +163 -0
  299. package/src/bb-utils.ts +13 -0
  300. package/src/builtin-routes.ts +62 -0
  301. package/src/cdk/__fixtures__/factory-backend.ts +8 -0
  302. package/src/cdk/__fixtures__/fullid-construct-backend.ts +42 -0
  303. package/src/cdk/__fixtures__/handler.ts +4 -0
  304. package/src/cdk/__fixtures__/side-effect-backend.ts +7 -0
  305. package/src/cdk/blocks-backend.test.ts +207 -0
  306. package/src/cdk/blocks-backend.ts +249 -0
  307. package/src/cdk/blocks-stack.test.ts +106 -0
  308. package/src/cdk/config-registry.ts +106 -0
  309. package/src/cdk/index.ts +115 -0
  310. package/src/cdk/mixins.test.ts +129 -0
  311. package/src/cdk/mixins.ts +41 -0
  312. package/src/cdk/node-version.ts +17 -0
  313. package/src/cdk/stack-metadata.test.ts +71 -0
  314. package/src/cdk/stack-metadata.ts +29 -0
  315. package/src/cdk/synth-guard.test.ts +21 -0
  316. package/src/cdk/synth-guard.ts +23 -0
  317. package/src/client/index.test.ts +118 -0
  318. package/src/client/index.ts +320 -0
  319. package/src/common/config.test.ts +236 -0
  320. package/src/common/config.ts +169 -0
  321. package/src/common/constants.ts +15 -0
  322. package/src/common/crypto.ts +15 -0
  323. package/src/common/index.test.ts +242 -0
  324. package/src/common/index.ts +335 -0
  325. package/src/common/mock-data.ts +52 -0
  326. package/src/common/official-bb-names.generated.ts +29 -0
  327. package/src/common/sdk-registry.ts +150 -0
  328. package/src/constants.ts +31 -0
  329. package/src/cors.test.ts +279 -0
  330. package/src/cors.ts +91 -0
  331. package/src/db-naming.test.ts +48 -0
  332. package/src/db-naming.ts +41 -0
  333. package/src/errors.ts +72 -0
  334. package/src/hosting.test.ts +1431 -0
  335. package/src/hosting.ts +626 -0
  336. package/src/index.cdk.ts +45 -0
  337. package/src/index.ts +22 -0
  338. package/src/lambda-handler.test.ts +1005 -0
  339. package/src/lambda-handler.ts +706 -0
  340. package/src/pipeline/index.ts +12 -0
  341. package/src/pipeline/pipeline-construct.ts +662 -0
  342. package/src/pipeline/pipeline.test.ts +1565 -0
  343. package/src/pipeline/types.ts +384 -0
  344. package/src/raw-route.cdk.ts +56 -0
  345. package/src/raw-route.mock.ts +56 -0
  346. package/src/raw-route.test.ts +819 -0
  347. package/src/raw-route.ts +316 -0
  348. package/src/redact.test.ts +222 -0
  349. package/src/redact.ts +143 -0
  350. package/src/rpc.test.ts +73 -0
  351. package/src/rpc.ts +174 -0
  352. package/src/scripts/cdk-telemetry-env.test.ts +75 -0
  353. package/src/scripts/cdk-telemetry-env.ts +23 -0
  354. package/src/scripts/cleanup.ts +39 -0
  355. package/src/scripts/console.ts +34 -0
  356. package/src/scripts/deploy.ts +106 -0
  357. package/src/scripts/destroy.ts +42 -0
  358. package/src/scripts/dev-server-cors.test.ts +28 -0
  359. package/src/scripts/dev-server-telemetry.test.ts +127 -0
  360. package/src/scripts/dev-server.ts +515 -0
  361. package/src/scripts/ensure-secrets.test.ts +50 -0
  362. package/src/scripts/ensure-secrets.ts +113 -0
  363. package/src/scripts/external-migrations-step.test.ts +64 -0
  364. package/src/scripts/external-migrations-step.ts +269 -0
  365. package/src/scripts/extract-ts-types.test.ts +516 -0
  366. package/src/scripts/extract-ts-types.ts +773 -0
  367. package/src/scripts/generate-client-worker.ts +15 -0
  368. package/src/scripts/generate-client.test.ts +69 -0
  369. package/src/scripts/generate-client.ts +86 -0
  370. package/src/scripts/generate-spec-cli.test.ts +106 -0
  371. package/src/scripts/generate-spec-cli.ts +92 -0
  372. package/src/scripts/generate-spec.test.ts +99 -0
  373. package/src/scripts/generate-spec.ts +833 -0
  374. package/src/scripts/index.ts +21 -0
  375. package/src/scripts/sandbox.ts +230 -0
  376. package/src/scripts/telemetry-cli.ts +10 -0
  377. package/src/scripts/telemetry.test.ts +239 -0
  378. package/src/scripts/telemetry.ts +173 -0
  379. package/src/scripts/validate-spec.ts +199 -0
  380. package/src/server/index.ts +5 -0
  381. package/src/server/withAuth.test.ts +348 -0
  382. package/src/server/withAuth.ts +323 -0
  383. package/src/telemetry/client.ts +226 -0
  384. package/src/telemetry/config-writer.ts +52 -0
  385. package/src/telemetry/consent-commands.test.ts +196 -0
  386. package/src/telemetry/consent.ts +154 -0
  387. package/src/telemetry/environment.ts +100 -0
  388. package/src/telemetry/identifiers.ts +94 -0
  389. package/src/telemetry/index.ts +11 -0
  390. package/src/telemetry/telemetry.test.ts +1343 -0
  391. package/src/telemetry/trackCommand.ts +110 -0
  392. package/src/telemetry/types.ts +92 -0
  393. package/src/types.ts +33 -0
  394. package/src/version.ts +2 -0
@@ -0,0 +1,106 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import * as cdk from 'aws-cdk-lib';
5
+ import * as s3 from 'aws-cdk-lib/aws-s3';
6
+ import * as s3deploy from 'aws-cdk-lib/aws-s3-deployment';
7
+ import * as iam from 'aws-cdk-lib/aws-iam';
8
+ import type { Construct } from 'constructs';
9
+
10
+ const REGISTRY_KEY = Symbol.for('BLOCKS_CONFIG_REGISTRY');
11
+
12
+ interface ConfigRegistryState {
13
+ entries: Map<string, unknown>;
14
+ finalized: boolean;
15
+ }
16
+
17
+ /**
18
+ * Get or create the config registry for a given stack.
19
+ * The registry collects BB config entries (env var key → CDK token value)
20
+ * and serializes them to an S3 JSON file at synth time.
21
+ */
22
+ function getRegistry(stack: cdk.Stack): ConfigRegistryState {
23
+ let state = (stack as any)[REGISTRY_KEY] as ConfigRegistryState | undefined;
24
+ if (!state) {
25
+ state = { entries: new Map(), finalized: false };
26
+ (stack as any)[REGISTRY_KEY] = state;
27
+ }
28
+ return state;
29
+ }
30
+
31
+ /**
32
+ * Register a config entry for a Building Block. This replaces
33
+ * `handler.addEnvironment(key, value)` for BB resource mappings.
34
+ *
35
+ * The entry will be serialized into a JSON config file in S3, loaded
36
+ * by the Lambda at cold start. This avoids the 4KB env var limit.
37
+ *
38
+ * @param scope - The CDK construct (used to find the parent stack)
39
+ * @param key - The config key (same string the runtime will use to look it up)
40
+ * @param value - The config value (can be a CDK token that resolves at deploy time)
41
+ */
42
+ export function registerConfig(scope: Construct, key: string, value: unknown): void {
43
+ const stack = cdk.Stack.of(scope);
44
+ const registry = getRegistry(stack);
45
+ registry.entries.set(key, value);
46
+ }
47
+
48
+ /**
49
+ * Finalize the config registry: create an S3 bucket, upload the config JSON,
50
+ * set env vars on the handler, and grant read access.
51
+ *
52
+ * Must be called after all BBs are constructed (i.e., after the backendCDKPath
53
+ * import completes in BlocksStack.create() / BlocksBackend.create()).
54
+ *
55
+ * @param scope - The CDK construct to create resources under
56
+ * @param handler - The Lambda function that needs to read the config
57
+ */
58
+ export function finalizeConfigRegistry(
59
+ scope: Construct,
60
+ handler: cdk.aws_lambda.IFunction,
61
+ ): void {
62
+ const stack = cdk.Stack.of(scope);
63
+ const registry = getRegistry(stack);
64
+
65
+ if (registry.finalized) return;
66
+ registry.finalized = true;
67
+
68
+ if (registry.entries.size === 0) return;
69
+
70
+ const configBucket = new s3.Bucket(scope, 'BlocksConfigBucket', {
71
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
72
+ autoDeleteObjects: true,
73
+ encryption: s3.BucketEncryption.S3_MANAGED,
74
+ blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
75
+ lifecycleRules: [
76
+ { noncurrentVersionExpiration: cdk.Duration.days(1) },
77
+ ],
78
+ });
79
+
80
+ const configKey = 'blocks-config.json';
81
+
82
+ const configObject = cdk.Lazy.any({
83
+ produce: () => Object.fromEntries(registry.entries),
84
+ });
85
+
86
+ const deployment = new s3deploy.BucketDeployment(scope, 'BlocksConfigDeployment', {
87
+ sources: [s3deploy.Source.jsonData(configKey, configObject)],
88
+ destinationBucket: configBucket,
89
+ prune: false,
90
+ });
91
+
92
+ (handler as cdk.aws_lambda.Function).addEnvironment(
93
+ 'BLOCKS_CONFIG_BUCKET',
94
+ configBucket.bucketName,
95
+ );
96
+ (handler as cdk.aws_lambda.Function).addEnvironment(
97
+ 'BLOCKS_CONFIG_KEY',
98
+ configKey,
99
+ );
100
+
101
+ // Scope IAM grant to the specific config key
102
+ (handler as cdk.aws_lambda.Function).addToRolePolicy(new iam.PolicyStatement({
103
+ actions: ['s3:GetObject'],
104
+ resources: [`${configBucket.bucketArn}/${configKey}`],
105
+ }));
106
+ }
@@ -0,0 +1,115 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import * as cdk from 'aws-cdk-lib';
5
+ import { Construct } from 'constructs';
6
+ import {
7
+ type BlocksStackProps,
8
+ type BlocksStack as BaseBlocksStack,
9
+ type ScopeParent,
10
+ type ScopeOptions,
11
+ computeScopeFullId,
12
+ } from '../common/index.js';
13
+ import { setupBlocksInfra, BlocksBackend, assertCdkConditionActive } from './blocks-backend.js';
14
+ import { addBlocksStackMetadata } from './stack-metadata.js';
15
+ import { finalizeConfigRegistry } from './config-registry.js';
16
+
17
+ export { BlocksBackend, type BlocksBackendProps } from './blocks-backend.js';
18
+ export { DEFAULT_NODE_RUNTIME } from './node-version.js';
19
+ export { SandboxDisableDeletionProtection } from './mixins.js';
20
+ export { registerConfig, finalizeConfigRegistry } from './config-registry.js';
21
+ export { synthGuard } from './synth-guard.js';
22
+ export type { ScopeOptions } from '../index.js';
23
+ export { ApiError, isBlocksError } from '../errors.js';
24
+
25
+ export class BlocksStack extends cdk.Stack implements BaseBlocksStack {
26
+ public readonly id: string;
27
+ public readonly apiUrl: string;
28
+ public readonly gateway: cdk.aws_apigateway.RestApi;
29
+ public readonly handler: cdk.aws_lambda_nodejs.NodejsFunction;
30
+ public readonly backendHandlerPath: string;
31
+
32
+ private constructor(scope: Construct, id: string, props: BlocksStackProps) {
33
+ super(scope, id, props);
34
+ this.id = id;
35
+ this.backendHandlerPath = props.backendHandlerPath;
36
+
37
+ // Set globalThis so Building Blocks attach directly to this stack
38
+ (globalThis as any).CURRENT_BLOCKS_STACK = this;
39
+
40
+ const infra = setupBlocksInfra(this, props, id);
41
+ this.handler = infra.handler;
42
+ this.gateway = infra.gateway;
43
+ this.apiUrl = infra.apiUrl;
44
+ }
45
+
46
+ static async create(scope: Construct, id: string, props: BlocksStackProps) {
47
+ assertCdkConditionActive();
48
+
49
+ // Detect ambient pipeline stage scope set by Pipeline appFile imports
50
+ const pipelineScope = (globalThis as any).__PIPELINE_STAGE_SCOPE__;
51
+ const actualScope = pipelineScope || scope;
52
+
53
+ const stack = new BlocksStack(actualScope, id, props);
54
+ // ESM caches modules by URL — append a unique query string so each stage re-executes the module body
55
+ const mod = await import(`${props.backendCDKPath}?stack=${id}`);
56
+ if (typeof mod.default === 'function') {
57
+ try {
58
+ await mod.default(stack);
59
+ } catch (error) {
60
+ throw new Error(`Error executing default export function for stack "${id}": ${error instanceof Error ? error.message : error}`, { cause: error });
61
+ }
62
+ }
63
+ // Finalize BB config → S3 (after all BBs have registered their config)
64
+ finalizeConfigRegistry(stack, stack.handler);
65
+
66
+ new cdk.CfnOutput(stack, 'ApiUrl', { value: stack.apiUrl });
67
+
68
+ addBlocksStackMetadata(stack);
69
+
70
+ return stack;
71
+ }
72
+ }
73
+
74
+ export class Scope extends Construct {
75
+ public readonly id: string;
76
+ public readonly parent: ScopeParent;
77
+
78
+ readonly bbName?: string;
79
+ readonly bbVersion?: string;
80
+
81
+ constructor(id: string, options?: ScopeOptions) {
82
+ const parent = options?.parent || (globalThis as any).CURRENT_BLOCKS_STACK;
83
+ super(parent, id);
84
+ this.id = id;
85
+ this.parent = parent;
86
+ }
87
+
88
+ get handler() {
89
+ // Walk up the construct tree to find the owning BlocksStack/BlocksBackend
90
+ let current: Construct = this;
91
+ while (current.node.scope) {
92
+ current = current.node.scope as Construct;
93
+ if (current instanceof BlocksStack || current instanceof BlocksBackend) {
94
+ return current.handler;
95
+ }
96
+ }
97
+ // Fallback to globalThis for backward compatibility
98
+ return ((globalThis as any).CURRENT_BLOCKS_STACK as { handler: cdk.aws_lambda_nodejs.NodejsFunction }).handler;
99
+ }
100
+
101
+ get fullId(): string {
102
+ return computeScopeFullId(this);
103
+ }
104
+
105
+ protected buildUserAgentChain(): [string, string][] {
106
+ return [];
107
+ }
108
+
109
+ // Plugin registration — no-ops in CDK context (plugins are only used at dev/build time)
110
+ registerClientMiddleware(_packageSpecifier: string): void {}
111
+ registerDevAttachment(_packageSpecifier: string): void {}
112
+ registerLambdaEventHandler(_eventSource: string, _identifier: string, _handler: (record: any) => Promise<void>): void {}
113
+ get clientMiddleware(): readonly string[] { return []; }
114
+ get devAttachments(): readonly string[] { return []; }
115
+ }
@@ -0,0 +1,129 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { test, describe } from 'node:test';
5
+ import assert from 'node:assert';
6
+ import * as cdk from 'aws-cdk-lib';
7
+ import { Template, Match } from 'aws-cdk-lib/assertions';
8
+ import { Table, AttributeType, BillingMode } from 'aws-cdk-lib/aws-dynamodb';
9
+ import * as rds from 'aws-cdk-lib/aws-rds';
10
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
11
+ import { RemovalPolicies, Mixins } from 'aws-cdk-lib';
12
+ import { SandboxDisableDeletionProtection } from './mixins.js';
13
+
14
+ describe('sandbox removal policy', () => {
15
+ test('sandbox mode: DeletionPolicy is Delete on all resources', () => {
16
+ const app = new cdk.App({ context: { sandboxMode: 'true' } });
17
+ const stack = new cdk.Stack(app, 'TestStack');
18
+
19
+ new Table(stack, 'MyTable', {
20
+ partitionKey: { name: 'pk', type: AttributeType.STRING },
21
+ billingMode: BillingMode.PAY_PER_REQUEST,
22
+ });
23
+
24
+ RemovalPolicies.of(stack).destroy();
25
+
26
+ const template = Template.fromStack(stack);
27
+ template.hasResource('AWS::DynamoDB::Table', {
28
+ DeletionPolicy: 'Delete',
29
+ });
30
+ });
31
+
32
+ test('sandbox mode: deletionProtection disabled on RDS cluster', () => {
33
+ const app = new cdk.App({ context: { sandboxMode: 'true' } });
34
+ const stack = new cdk.Stack(app, 'TestStack');
35
+
36
+ const vpc = new ec2.Vpc(stack, 'Vpc', {
37
+ maxAzs: 2,
38
+ natGateways: 0,
39
+ subnetConfiguration: [
40
+ { name: 'isolated', subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
41
+ ],
42
+ });
43
+ new rds.DatabaseCluster(stack, 'Cluster', {
44
+ engine: rds.DatabaseClusterEngine.auroraPostgres({
45
+ version: rds.AuroraPostgresEngineVersion.VER_16_4,
46
+ }),
47
+ writer: rds.ClusterInstance.serverlessV2('Writer'),
48
+ vpc,
49
+ vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
50
+ deletionProtection: true,
51
+ });
52
+
53
+ RemovalPolicies.of(stack).destroy();
54
+ Mixins.of(stack).apply(new SandboxDisableDeletionProtection());
55
+
56
+ const template = Template.fromStack(stack);
57
+ template.hasResourceProperties('AWS::RDS::DBCluster', {
58
+ DeletionProtection: false,
59
+ });
60
+ template.hasResource('AWS::RDS::DBCluster', {
61
+ DeletionPolicy: 'Delete',
62
+ });
63
+ });
64
+
65
+ test('production mode: default DeletionPolicy is Retain (CDK default, no explicit call needed)', () => {
66
+ const app = new cdk.App();
67
+ const stack = new cdk.Stack(app, 'TestStack');
68
+
69
+ new Table(stack, 'MyTable', {
70
+ partitionKey: { name: 'pk', type: AttributeType.STRING },
71
+ billingMode: BillingMode.PAY_PER_REQUEST,
72
+ });
73
+
74
+ // No removal policy call — CDK defaults to RETAIN
75
+ const template = Template.fromStack(stack);
76
+ template.hasResource('AWS::DynamoDB::Table', {
77
+ DeletionPolicy: 'Retain',
78
+ });
79
+ });
80
+
81
+ test('SandboxDisableDeletionProtection mixin: does not set deletionProtection on Aurora instances', () => {
82
+ const app = new cdk.App();
83
+ const stack = new cdk.Stack(app, 'TestStack');
84
+
85
+ const vpc = new ec2.Vpc(stack, 'Vpc', {
86
+ maxAzs: 2,
87
+ natGateways: 0,
88
+ subnetConfiguration: [
89
+ { name: 'isolated', subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
90
+ ],
91
+ });
92
+ new rds.DatabaseCluster(stack, 'Cluster', {
93
+ engine: rds.DatabaseClusterEngine.auroraPostgres({
94
+ version: rds.AuroraPostgresEngineVersion.VER_16_4,
95
+ }),
96
+ writer: rds.ClusterInstance.serverlessV2('Writer'),
97
+ vpc,
98
+ vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
99
+ removalPolicy: cdk.RemovalPolicy.DESTROY,
100
+ });
101
+
102
+ RemovalPolicies.of(stack).destroy();
103
+ Mixins.of(stack).apply(new SandboxDisableDeletionProtection());
104
+
105
+ const template = Template.fromStack(stack);
106
+ // Aurora DB instance should NOT have DeletionProtection set at all
107
+ // (RDS rejects it for cluster members)
108
+ template.hasResourceProperties('AWS::RDS::DBInstance', {
109
+ DeletionProtection: Match.absent(),
110
+ });
111
+ });
112
+
113
+ test('SandboxDisableDeletionProtection mixin: skips constructs without deletionProtection', () => {
114
+ const app = new cdk.App();
115
+ const stack = new cdk.Stack(app, 'TestStack');
116
+
117
+ new Table(stack, 'MyTable', {
118
+ partitionKey: { name: 'pk', type: AttributeType.STRING },
119
+ billingMode: BillingMode.PAY_PER_REQUEST,
120
+ });
121
+
122
+ // Should not throw — DynamoDB Table has no deletionProtection property
123
+ Mixins.of(stack).apply(new SandboxDisableDeletionProtection());
124
+
125
+ const template = Template.fromStack(stack);
126
+ // Table should still synthesize normally
127
+ template.resourceCountIs('AWS::DynamoDB::Table', 1);
128
+ });
129
+ });
@@ -0,0 +1,41 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { Mixin } from 'aws-cdk-lib';
5
+ import type { IConstruct } from 'constructs';
6
+ import type { IMixin } from 'constructs';
7
+
8
+ /**
9
+ * Disables deletion protection on any construct that has a `deletionProtection`
10
+ * property (e.g. RDS clusters, RDS instances). Uses duck-typing so it
11
+ * automatically covers current and future resource types.
12
+ *
13
+ * Intended for sandbox teardown — use in the CDK layer alongside
14
+ * `RemovalPolicies.of(stack).destroy()` to ensure `sandbox:destroy` can
15
+ * delete the entire stack without manual cleanup.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { RemovalPolicies, Mixins } from 'aws-cdk-lib';
20
+ * import { SandboxDisableDeletionProtection } from '@aws-blocks/blocks/cdk';
21
+ *
22
+ * if (sandboxMode) {
23
+ * RemovalPolicies.of(stack).destroy();
24
+ * Mixins.of(stack).apply(new SandboxDisableDeletionProtection());
25
+ * }
26
+ * ```
27
+ */
28
+ export class SandboxDisableDeletionProtection extends Mixin implements IMixin {
29
+ supports(construct: any): boolean {
30
+ return 'deletionProtection' in construct;
31
+ }
32
+ applyTo(node: IConstruct): void {
33
+ // Only flip explicitly-enabled protection. When undefined (the default),
34
+ // deletion protection is already off — setting it to false would emit the
35
+ // property in the CloudFormation template, which breaks Aurora DB instances
36
+ // (RDS rejects DeletionProtection on cluster members).
37
+ if ((node as any).deletionProtection === true) {
38
+ (node as any).deletionProtection = false;
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,17 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { Runtime } from 'aws-cdk-lib/aws-lambda';
5
+
6
+ /**
7
+ * The single source of truth for the Node.js Lambda runtime used by Blocks's
8
+ * own Lambda functions and every Building Block. Set every
9
+ * `aws_lambda.Function` / `NodejsFunction` runtime to this constant rather
10
+ * than hardcoding `Runtime.NODEJS_*_X`, so the whole framework moves in
11
+ * lockstep when the runtime is bumped.
12
+ *
13
+ * Currently the latest Active LTS. This controls only the AWS-managed
14
+ * runtime that executes deployed handlers; it is independent of the Node
15
+ * version a consumer runs the CLI / CDK synth on.
16
+ */
17
+ export const DEFAULT_NODE_RUNTIME = Runtime.NODEJS_24_X;
@@ -0,0 +1,71 @@
1
+ import { test, describe } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import * as cdk from 'aws-cdk-lib';
4
+ import { Template } from 'aws-cdk-lib/assertions';
5
+ import { addBlocksStackMetadata } from './stack-metadata.js';
6
+ import { CORE_VERSION } from '../version.js';
7
+
8
+ describe('addBlocksStackMetadata', () => {
9
+ test('adds AWS::Blocks::Platform metadata with correct version', () => {
10
+ const app = new cdk.App();
11
+ const stack = new cdk.Stack(app, 'TestStack');
12
+
13
+ addBlocksStackMetadata(stack);
14
+
15
+ const template = Template.fromStack(stack);
16
+ const metadata = template.toJSON().Metadata;
17
+ assert.deepStrictEqual(metadata['AWS::Blocks::Platform'], {
18
+ version: CORE_VERSION,
19
+ });
20
+ });
21
+
22
+ test('preserves existing template metadata', () => {
23
+ const app = new cdk.App();
24
+ const stack = new cdk.Stack(app, 'ExistingMetaStack');
25
+ stack.templateOptions.metadata = {
26
+ 'Custom::Existing': { key: 'value' },
27
+ };
28
+
29
+ addBlocksStackMetadata(stack);
30
+
31
+ const template = Template.fromStack(stack);
32
+ const metadata = template.toJSON().Metadata;
33
+ assert.deepStrictEqual(metadata['Custom::Existing'], { key: 'value' });
34
+ assert.deepStrictEqual(metadata['AWS::Blocks::Platform'], {
35
+ version: CORE_VERSION,
36
+ });
37
+ });
38
+
39
+ test('tags deployment-type as production when sandboxMode context is absent', () => {
40
+ const app = new cdk.App();
41
+ const stack = new cdk.Stack(app, 'ProdStack');
42
+
43
+ addBlocksStackMetadata(stack);
44
+
45
+ const assembly = app.synth();
46
+ const stackArtifact = assembly.getStackByName(stack.stackName);
47
+ assert.strictEqual(stackArtifact.tags['blocks:deployment-type'], 'production');
48
+ });
49
+
50
+ test('tags deployment-type as sandbox when sandboxMode context is boolean true', () => {
51
+ const app = new cdk.App({ context: { sandboxMode: true } });
52
+ const stack = new cdk.Stack(app, 'SandboxBoolStack');
53
+
54
+ addBlocksStackMetadata(stack);
55
+
56
+ const assembly = app.synth();
57
+ const stackArtifact = assembly.getStackByName(stack.stackName);
58
+ assert.strictEqual(stackArtifact.tags['blocks:deployment-type'], 'sandbox');
59
+ });
60
+
61
+ test('tags deployment-type as sandbox when sandboxMode context is string "true"', () => {
62
+ const app = new cdk.App({ context: { sandboxMode: 'true' } });
63
+ const stack = new cdk.Stack(app, 'SandboxStringStack');
64
+
65
+ addBlocksStackMetadata(stack);
66
+
67
+ const assembly = app.synth();
68
+ const stackArtifact = assembly.getStackByName(stack.stackName);
69
+ assert.strictEqual(stackArtifact.tags['blocks:deployment-type'], 'sandbox');
70
+ });
71
+ });
@@ -0,0 +1,29 @@
1
+ import * as cdk from 'aws-cdk-lib';
2
+ import { CORE_VERSION } from '../version.js';
3
+
4
+ /**
5
+ * Adds AWS Blocks identification metadata and a deployment-type tag to a CloudFormation stack.
6
+ *
7
+ * Sets `AWS::Blocks::Platform` template metadata with the current core version
8
+ * and applies a `blocks:deployment-type` tag (`sandbox` or `production`) based on
9
+ * the CDK context key `sandboxMode`.
10
+ *
11
+ * @param stack - The CDK stack to annotate.
12
+ */
13
+ export function addBlocksStackMetadata(stack: cdk.Stack): void {
14
+ stack.templateOptions.metadata = {
15
+ ...stack.templateOptions.metadata,
16
+ 'AWS::Blocks::Platform': {
17
+ version: CORE_VERSION,
18
+ },
19
+ };
20
+
21
+ const isSandbox =
22
+ stack.node.tryGetContext('sandboxMode') === 'true' ||
23
+ stack.node.tryGetContext('sandboxMode') === true;
24
+
25
+ cdk.Tags.of(stack).add(
26
+ 'blocks:deployment-type',
27
+ isSandbox ? 'sandbox' : 'production',
28
+ );
29
+ }
@@ -0,0 +1,21 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { test } from 'node:test';
5
+ import assert from 'node:assert';
6
+ import { synthGuard } from './synth-guard.js';
7
+
8
+ test('synthGuard throws an error mentioning the class and method name', () => {
9
+ assert.throws(
10
+ () => synthGuard('MyBlock', 'doThing'),
11
+ (err: Error) => {
12
+ assert.match(err.message, /MyBlock\.doThing\(\) cannot be called during CDK synth/);
13
+ assert.match(err.message, /--conditions=aws-runtime/);
14
+ return true;
15
+ },
16
+ );
17
+ });
18
+
19
+ test('synthGuard always throws (return type is never)', () => {
20
+ assert.throws(() => synthGuard('X', 'y'));
21
+ });
@@ -0,0 +1,23 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ /**
5
+ * Throws an actionable error when a runtime-only method is called during CDK synth.
6
+ *
7
+ * Under `--conditions=cdk` Building Block modules resolve to their CDK construct,
8
+ * which only provisions infrastructure. Data/runtime methods live in the runtime
9
+ * build. Calling them at module top-level (which runs during synth) would otherwise
10
+ * fail with a cryptic `X is not a function` TypeError; this utility turns that into
11
+ * an actionable message directing the user to the correct execution context.
12
+ *
13
+ * @param className - The Building Block class name (e.g. "KVStore", "DistributedTable")
14
+ * @param method - The method that was called (e.g. "get", "put")
15
+ */
16
+ export function synthGuard(className: string, method: string): never {
17
+ throw new Error(
18
+ `${className}.${method}() cannot be called during CDK synth. ` +
19
+ `Data methods run at request time — call them inside an ApiNamespace method, ` +
20
+ `RawRoute handler, job handler, or a runtime script (run with --conditions=aws-runtime), ` +
21
+ `not at the top level of your backend module.`,
22
+ );
23
+ }
@@ -0,0 +1,118 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { describe, it } from 'node:test';
5
+ import assert from 'node:assert';
6
+ import { execSync } from 'node:child_process';
7
+ import { writeFileSync, unlinkSync, mkdtempSync } from 'node:fs';
8
+ import { fileURLToPath } from 'node:url';
9
+ import { dirname, join } from 'node:path';
10
+ import { tmpdir } from 'node:os';
11
+
12
+ /**
13
+ * Tests for the client's URL resolution defensive guard (issue #730).
14
+ *
15
+ * The client module caches API_URL globally, so each test spawns a
16
+ * subprocess with appropriate env vars to get a fresh module instance.
17
+ */
18
+
19
+ const __dirname = dirname(fileURLToPath(import.meta.url));
20
+ const CLIENT_MODULE = join(__dirname, '..', 'client', 'index.js');
21
+
22
+ function runScript(scriptBody: string, env: Record<string, string>): string {
23
+ const tmp = mkdtempSync(join(tmpdir(), 'blocks-client-test-'));
24
+ const scriptPath = join(tmp, 'test.mjs');
25
+ // Use absolute path to import the client module
26
+ const importPath = `file://${CLIENT_MODULE}`;
27
+ const fullScript = `import { ApiNamespaceClient } from '${importPath}';\n${scriptBody}`;
28
+ writeFileSync(scriptPath, fullScript);
29
+ try {
30
+ return execSync(`node ${scriptPath}`, {
31
+ encoding: 'utf-8',
32
+ env: { PATH: process.env.PATH, HOME: process.env.HOME, ...env },
33
+ timeout: 10000,
34
+ }).trim();
35
+ } finally {
36
+ try { unlinkSync(scriptPath); } catch {}
37
+ }
38
+ }
39
+
40
+ describe('Client URL validation (issue #730)', () => {
41
+ it('ApiNamespaceClient with explicit url option containing "undefined" does NOT throw on creation', async () => {
42
+ const { ApiNamespaceClient } = await import('./index.js');
43
+ const client = ApiNamespaceClient('test', { url: 'https://undefined.example.com' });
44
+ assert.ok(client, 'Should create client proxy');
45
+ });
46
+
47
+ it('resolveApiUrl rejects when BLOCKS_API_URL contains "undefined"', () => {
48
+ const result = runScript(`
49
+ const api = ApiNamespaceClient('test');
50
+ try {
51
+ await api.hello();
52
+ console.log('FAIL:no_error');
53
+ } catch (e) {
54
+ if (e.message.includes('Blocks API URL is not configured')) {
55
+ console.log('PASS');
56
+ } else {
57
+ console.log('FAIL:' + e.message);
58
+ }
59
+ }
60
+ `, { BLOCKS_API_URL: 'https://undefined/api' });
61
+ assert.ok(result.includes('PASS'), `Expected PASS, got: ${result}`);
62
+ });
63
+
64
+ it('resolveApiUrl rejects when BLOCKS_CONFIG has missing apiUrl', () => {
65
+ const result = runScript(`
66
+ const api = ApiNamespaceClient('test');
67
+ try {
68
+ await api.hello();
69
+ console.log('FAIL:no_error');
70
+ } catch (e) {
71
+ if (e.message.includes('Blocks API URL is not configured') || e.message.includes('Blocks API URL not configured')) {
72
+ console.log('PASS');
73
+ } else {
74
+ console.log('FAIL:' + e.message);
75
+ }
76
+ }
77
+ `, { BLOCKS_CONFIG: JSON.stringify({ region: 'us-east-1' }) });
78
+ assert.ok(result.includes('PASS'), `Expected PASS, got: ${result}`);
79
+ });
80
+
81
+ it('resolveApiUrl succeeds with valid BLOCKS_API_URL', () => {
82
+ const result = runScript(`
83
+ const api = ApiNamespaceClient('test');
84
+ try {
85
+ await api.hello();
86
+ console.log('FAIL:no_error');
87
+ } catch (e) {
88
+ if (e.message.includes('fetch') || e.message.includes('ENOTFOUND') || e.message.includes('getaddrinfo')) {
89
+ console.log('PASS:url_resolved_fetch_failed');
90
+ } else if (e.message.includes('Blocks API URL')) {
91
+ console.log('FAIL:url_rejected_valid');
92
+ } else {
93
+ console.log('PASS:other');
94
+ }
95
+ }
96
+ `, { BLOCKS_API_URL: 'https://abc123.execute-api.us-east-1.amazonaws.com/prod/aws-blocks' });
97
+ assert.ok(result.includes('PASS'), `Expected PASS, got: ${result}`);
98
+ });
99
+
100
+ it('resolveApiUrl accepts relative URLs (e.g. /aws-blocks/api for SPA hosting)', () => {
101
+ const result = runScript(`
102
+ const api = ApiNamespaceClient('test');
103
+ try {
104
+ await api.hello();
105
+ console.log('FAIL:no_error');
106
+ } catch (e) {
107
+ if (e.message.includes('fetch') || e.message.includes('ENOTFOUND') || e.message.includes('getaddrinfo') || e.message.includes('Invalid URL')) {
108
+ console.log('PASS:url_resolved_fetch_failed');
109
+ } else if (e.message.includes('Blocks API URL')) {
110
+ console.log('FAIL:url_rejected_relative');
111
+ } else {
112
+ console.log('PASS:other');
113
+ }
114
+ }
115
+ `, { BLOCKS_API_URL: '/aws-blocks/api' });
116
+ assert.ok(result.includes('PASS'), `Expected PASS, got: ${result}`);
117
+ });
118
+ });