@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,21 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export { startDevServer, type DevServerOptions } from './dev-server.js';
5
+ export { startSandbox, destroySandbox, type SandboxOptions } from './sandbox.js';
6
+ export { generateClientCode, writeClientCode } from './generate-client.js';
7
+ export { generateSpec, writeSpec } from './generate-spec.js';
8
+ export { validateSpec, type SpecValidationError } from './validate-spec.js';
9
+ export { deploy, type DeployOptions } from './deploy.js';
10
+ export { destroy, type DestroyOptions } from './destroy.js';
11
+ export { openConsole, type ConsoleOptions } from './console.js';
12
+ export { ensureSecrets, loadProductionEnv, loadEnvFile } from './ensure-secrets.js';
13
+ export {
14
+ trackCommand,
15
+ buildAndSendEvent,
16
+ classifyError,
17
+ type CommandName,
18
+ type CommandState,
19
+ type BuildAndSendEventOptions,
20
+ } from '../telemetry/index.js';
21
+ export { telemetry, type TelemetryOptions } from './telemetry.js';
@@ -0,0 +1,230 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { execFileSync, spawn } from "node:child_process";
5
+ import { writeFileSync, mkdirSync, readFileSync } from "node:fs";
6
+ import { join, resolve, dirname } from "node:path";
7
+ import { fileURLToPath, pathToFileURL } from "node:url";
8
+ import { ensureSecrets, loadEnvFile } from './ensure-secrets.js';
9
+ import { applyExternalMigrations } from './external-migrations-step.js';
10
+ import { trackCommand } from '../telemetry/trackCommand.js';
11
+ import { buildAndSendEvent } from '../telemetry/client.js';
12
+ import { getCdkTelemetryEnv } from './cdk-telemetry-env.js';
13
+
14
+ /**
15
+ * Import the backend definition to populate the Scope BB registry.
16
+ *
17
+ * All BB variants set bbName/bbVersion on construction, so importing the
18
+ * backend is sufficient to register every block. `buildAndSendEvent` then
19
+ * reads the registry internally — callers don't need to pass block data.
20
+ * Failures are silently swallowed — telemetry is best-effort.
21
+ */
22
+ async function importBackendForRegistry(backendPath: string): Promise<void> {
23
+ try {
24
+ await import(pathToFileURL(resolve(backendPath)).href);
25
+ } catch {
26
+ // best-effort — telemetry never affects the command
27
+ }
28
+ }
29
+
30
+ export interface SandboxOptions {
31
+ backendPath: string;
32
+ outDir?: string;
33
+ clientPort?: number;
34
+ deployOnly?: boolean;
35
+ /** Custom dev server command. Defaults to 'npx vite'. For Next.js use 'npx next dev'. */
36
+ devCommand?: string;
37
+ }
38
+
39
+ export async function startSandbox(options: SandboxOptions) {
40
+ const { backendPath, outDir = ".blocks-sandbox", clientPort = 3000, deployOnly = false, devCommand } = options;
41
+ const sandboxStartTime = Date.now();
42
+
43
+ // Load .env.local so CDK can read secret ARNs and other config.
44
+ try { loadEnvFile('.env.local'); } catch (e: any) {
45
+ if (e.code !== 'ENOENT') throw e;
46
+ }
47
+
48
+ process.env.BLOCKS_STAGE = 'sandbox';
49
+
50
+ // Provision connection string to SSM SecureString.
51
+ // On first deploy, creates the parameter. On subsequent deploys, updates if changed.
52
+ const secrets = await ensureSecrets('sandbox');
53
+ if (secrets.created.length > 0) {
54
+ console.log(`🔐 Created secrets: ${secrets.created.join(', ')}`);
55
+ }
56
+ if (secrets.updated.length > 0) {
57
+ console.log(`🔐 Updated secrets: ${secrets.updated.join(', ')}`);
58
+ }
59
+
60
+ // Apply external-database migrations to the sandbox database before
61
+ // deploying. No-op unless this app uses an external DB and has ./migrations.
62
+ await applyExternalMigrations({ stage: 'sandbox' });
63
+
64
+ // Import backend to populate Scope BB registry (for telemetry).
65
+ // Runs before CDK deploy so both success and failure paths include block info.
66
+ await importBackendForRegistry(backendPath);
67
+
68
+ console.log("🚀 Deploying to AWS...");
69
+ console.log(" (This may take a few minutes on first deploy)");
70
+
71
+ try {
72
+ execFileSync(
73
+ "npm",
74
+ [
75
+ "exec", "cdk", "--", "deploy",
76
+ "--require-approval", "never",
77
+ "--outputs-file", `${outDir}/outputs.json`,
78
+ "--context", `projectRoot=${process.cwd()}`,
79
+ "--context", "sandboxMode=true",
80
+ "--app", `npm exec tsx -- -C cdk ${backendPath}`,
81
+ ],
82
+ {
83
+ stdio: "inherit",
84
+ env: { ...process.env, NODE_OPTIONS: "--conditions=cdk", ...getCdkTelemetryEnv('sandbox') },
85
+ },
86
+ );
87
+ } catch (error) {
88
+ buildAndSendEvent({
89
+ command: 'sandbox',
90
+ state: 'FAIL',
91
+ duration: Date.now() - sandboxStartTime,
92
+ error: { code: 'CDK_DEPLOY_FAILED', phase: 'deploy' },
93
+ });
94
+ console.error("\n❌ Deployment failed.");
95
+ throw error;
96
+ }
97
+
98
+ const outputs = JSON.parse(readFileSync(`${outDir}/outputs.json`, "utf-8"));
99
+ const stackOutputs = Object.values(outputs)[0] as Record<string, string> || {};
100
+
101
+ const apiUrl = stackOutputs.ApiUrl;
102
+ if (!apiUrl) {
103
+ throw new Error("Could not find API URL in CDK outputs");
104
+ }
105
+
106
+ console.log("\n✅ Sandbox deployed!");
107
+ console.log(`📡 API URL: ${apiUrl}`);
108
+
109
+ buildAndSendEvent({
110
+ command: 'sandbox',
111
+ state: 'SUCCESS',
112
+ duration: Date.now() - sandboxStartTime,
113
+ });
114
+
115
+ // Write config — just apiUrl. Client middleware gets service-specific
116
+ // config from transferables in API responses, not from static config.
117
+ const config: Record<string, string> = { apiUrl, environment: 'sandbox' };
118
+ mkdirSync(outDir, { recursive: true });
119
+ writeFileSync(`${outDir}/config.json`, JSON.stringify(config, null, 2));
120
+
121
+ // Generate client code targeting AWS (aws-runtime condition ensures
122
+ // the backend registers aws-middleware, not mock-middleware).
123
+ const backendDefPath = resolve(join(dirname(resolve(backendPath)), 'index.ts'));
124
+ const clientPath = join(dirname(backendDefPath), 'client.js');
125
+ console.log('📝 Generating client code...');
126
+ const __dirname = dirname(fileURLToPath(import.meta.url));
127
+ const workerPath = join(__dirname, 'generate-client-worker.js');
128
+ execFileSync('node', ['--conditions=aws-runtime', '--import', 'tsx', workerPath, backendDefPath, clientPath], {
129
+ stdio: 'inherit',
130
+ env: { ...process.env, NODE_OPTIONS: '' },
131
+ });
132
+
133
+ if (deployOnly) {
134
+ return apiUrl;
135
+ }
136
+
137
+ console.log("\n👀 Starting CDK watch mode...");
138
+ console.log("🌐 Starting local dev server (proxying to AWS)...");
139
+ console.log(`\n Open http://localhost:${clientPort}\n`);
140
+
141
+ const cdkWatch = spawn("npx", [
142
+ "cdk", "watch", "--hotswap",
143
+ `--outputs-file`, `${outDir}/outputs.json`,
144
+ `--context`, `projectRoot=${process.cwd()}`,
145
+ `--context`, `sandboxMode=true`,
146
+ `--app`, `npm exec tsx -- -C cdk ${backendPath}`
147
+ ], {
148
+ stdio: ["ignore", "pipe", "pipe"],
149
+ env: { ...process.env, NODE_OPTIONS: "--conditions=cdk", ...getCdkTelemetryEnv('sandbox') },
150
+ });
151
+
152
+ cdkWatch.stdout?.on("data", (data) => {
153
+ const str = data.toString().trim();
154
+ if (!str.match(/\[(START|END|REPORT|INIT_START)\s+RequestId:/)) {
155
+ console.log(`[CDK Watch] ${str}`);
156
+ }
157
+ });
158
+ cdkWatch.stderr?.on("data", (data) => {
159
+ console.error(`[CDK Watch] ${data.toString().trim()}`);
160
+ });
161
+
162
+ const devServerCmd = devCommand || `npx tsx watch aws-blocks/scripts/server.ts`;
163
+ const [cmd, ...args] = devServerCmd.split(' ');
164
+
165
+ const devServer = spawn(cmd, args, {
166
+ stdio: "inherit",
167
+ shell: true,
168
+ env: {
169
+ ...process.env,
170
+ NODE_OPTIONS: '',
171
+ BLOCKS_API_URL: apiUrl,
172
+ },
173
+ });
174
+
175
+ const cleanup = () => {
176
+ console.log("\n\n🛑 Stopping local processes...");
177
+ console.log(" (AWS resources are still running)");
178
+ console.log("\n To destroy AWS resources, run: npm run sandbox:destroy\n");
179
+ cdkWatch.kill();
180
+ devServer.kill();
181
+ process.exit(0);
182
+ };
183
+
184
+ process.on("SIGINT", cleanup);
185
+ process.on("SIGTERM", cleanup);
186
+
187
+ await new Promise(() => {});
188
+ }
189
+
190
+ export async function destroySandbox(backendPath: string) {
191
+ return trackCommand('sandbox:destroy', async () => {
192
+ console.log("🗑️ Destroying sandbox...");
193
+
194
+ // Load .env.local so CDK synth can read project refs and other config.
195
+ try { loadEnvFile('.env.local'); } catch (e: any) {
196
+ if (e.code !== 'ENOENT') throw e;
197
+ }
198
+
199
+ const cdkArgs = [
200
+ "exec", "cdk", "--", "destroy",
201
+ "--force",
202
+ "--context", "sandboxMode=true",
203
+ "--app", `npm exec tsx -- -C cdk ${backendPath}`,
204
+ ];
205
+ const cdkEnv = { ...process.env, NODE_OPTIONS: "--conditions=cdk", ...getCdkTelemetryEnv('sandbox') };
206
+ // Retry with backoff for VPC-dependent resources (e.g. Aurora clusters).
207
+ // CloudFormation deletes the cluster first, but its ENIs take 60-120s to
208
+ // detach from the VPC subnets asynchronously. The initial destroy fails
209
+ // because the subnets still have attached ENIs; retrying after the cleanup
210
+ // window lets the VPC delete succeed.
211
+ const retryDelays = [60_000, 120_000]; // 1min, then 2min
212
+
213
+ for (let attempt = 0; ; attempt++) {
214
+ try {
215
+ execFileSync("npm", cdkArgs, { stdio: "inherit", env: cdkEnv });
216
+ console.log(attempt === 0 ? "\n✅ Sandbox destroyed!" : "\n✅ Sandbox destroyed on retry!");
217
+ return;
218
+ } catch (error) {
219
+ if (attempt < retryDelays.length) {
220
+ const delaySec = retryDelays[attempt] / 1000;
221
+ console.log(`\n⏳ Stack deletion failed. Retrying in ${delaySec}s (waiting for resource cleanup)...`);
222
+ await new Promise(r => setTimeout(r, retryDelays[attempt]));
223
+ } else {
224
+ console.error("\n❌ Destroy failed after retries.");
225
+ throw error;
226
+ }
227
+ }
228
+ }
229
+ });
230
+ }
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ // SPDX-License-Identifier: Apache-2.0
4
+
5
+ import { telemetry } from './telemetry.js';
6
+
7
+ telemetry().catch((error) => {
8
+ console.error(error);
9
+ process.exit(1);
10
+ });
@@ -0,0 +1,239 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { describe, it, beforeEach, afterEach } from 'node:test';
5
+ import assert from 'node:assert';
6
+ import { spawnSync } from 'node:child_process';
7
+ import { mkdirSync, writeFileSync, readFileSync, rmSync, existsSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+ import { tmpdir } from 'node:os';
10
+ import { fileURLToPath } from 'node:url';
11
+ import { dirname } from 'node:path';
12
+
13
+ const __dirname = dirname(fileURLToPath(import.meta.url));
14
+ const CLI_SCRIPT = join(__dirname, 'telemetry-cli.js');
15
+
16
+ /** Env overrides that clear CI detection so tests see "default enabled" state. */
17
+ const NO_CI_ENV: Record<string, string> = {
18
+ CI: '',
19
+ CONTINUOUS_INTEGRATION: '',
20
+ BUILD_NUMBER: '',
21
+ CODEBUILD_BUILD_ID: '',
22
+ GITHUB_ACTIONS: '',
23
+ GITLAB_CI: '',
24
+ CIRCLECI: '',
25
+ JENKINS_URL: '',
26
+ TF_BUILD: '',
27
+ BITBUCKET_BUILD_NUMBER: '',
28
+ BUILDKITE: '',
29
+ AWS_BLOCKS_DISABLE_TELEMETRY: '',
30
+ };
31
+
32
+ function createTmpDir(): string {
33
+ const dir = join(tmpdir(), `blocks-telemetry-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
34
+ mkdirSync(dir, { recursive: true });
35
+ return dir;
36
+ }
37
+
38
+ function runCli(args: string[], options?: { cwd?: string; env?: Record<string, string> }): { stdout: string; stderr: string; exitCode: number } {
39
+ const result = spawnSync('node', [CLI_SCRIPT, ...args], {
40
+ cwd: options?.cwd ?? process.cwd(),
41
+ encoding: 'utf-8',
42
+ env: { ...process.env, ...options?.env },
43
+ stdio: ['pipe', 'pipe', 'pipe'],
44
+ });
45
+
46
+ return {
47
+ stdout: result.stdout || '',
48
+ stderr: result.stderr || '',
49
+ exitCode: result.status ?? 1,
50
+ };
51
+ }
52
+
53
+ describe('telemetry CLI', () => {
54
+ let tmpHome: string;
55
+ let tmpProject: string;
56
+
57
+ beforeEach(() => {
58
+ tmpHome = createTmpDir();
59
+ tmpProject = createTmpDir();
60
+ });
61
+
62
+ afterEach(() => {
63
+ rmSync(tmpHome, { recursive: true, force: true });
64
+ rmSync(tmpProject, { recursive: true, force: true });
65
+ });
66
+
67
+ describe('help', () => {
68
+ it('--help shows usage', () => {
69
+ const result = runCli(['--help'], { cwd: tmpProject, env: { HOME: tmpHome } });
70
+ assert.strictEqual(result.exitCode, 0);
71
+ assert.ok(result.stdout.includes('--enable'));
72
+ assert.ok(result.stdout.includes('--disable'));
73
+ assert.ok(result.stdout.includes('--global'));
74
+ });
75
+
76
+ it('-h shows usage', () => {
77
+ const result = runCli(['-h'], { cwd: tmpProject, env: { HOME: tmpHome } });
78
+ assert.strictEqual(result.exitCode, 0);
79
+ assert.ok(result.stdout.includes('--enable'));
80
+ });
81
+ });
82
+
83
+ describe('bare command (shows help)', () => {
84
+ it('shows usage when invoked with no arguments', () => {
85
+ const result = runCli([], { cwd: tmpProject, env: { HOME: tmpHome, ...NO_CI_ENV } });
86
+ assert.strictEqual(result.exitCode, 0);
87
+ assert.ok(result.stdout.includes('Usage:'));
88
+ assert.ok(result.stdout.includes('--enable'));
89
+ assert.ok(result.stdout.includes('--disable'));
90
+ assert.ok(result.stdout.includes('--status'));
91
+ });
92
+ });
93
+
94
+ describe('--enable (project-level default)', () => {
95
+ it('creates .blocks/config.json with telemetry.enabled=true', () => {
96
+ const result = runCli(['--enable'], { cwd: tmpProject, env: { HOME: tmpHome } });
97
+ assert.strictEqual(result.exitCode, 0);
98
+ assert.ok(result.stdout.includes('enabled for this project'));
99
+
100
+ const configPath = join(tmpProject, '.blocks', 'config.json');
101
+ assert.ok(existsSync(configPath));
102
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
103
+ assert.strictEqual(config.telemetry.enabled, true);
104
+ });
105
+ });
106
+
107
+ describe('--disable (project-level default)', () => {
108
+ it('creates .blocks/config.json with telemetry.enabled=false', () => {
109
+ const result = runCli(['--disable'], { cwd: tmpProject, env: { HOME: tmpHome } });
110
+ assert.strictEqual(result.exitCode, 0);
111
+ assert.ok(result.stdout.includes('disabled for this project'));
112
+
113
+ const configPath = join(tmpProject, '.blocks', 'config.json');
114
+ assert.ok(existsSync(configPath));
115
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
116
+ assert.strictEqual(config.telemetry.enabled, false);
117
+ });
118
+ });
119
+
120
+ describe('--enable --global', () => {
121
+ it('creates ~/.blocks/config.json with telemetry.enabled=true', () => {
122
+ const result = runCli(['--enable', '--global'], { cwd: tmpProject, env: { HOME: tmpHome } });
123
+ assert.strictEqual(result.exitCode, 0);
124
+ assert.ok(result.stdout.includes('enabled globally'));
125
+
126
+ const configPath = join(tmpHome, '.blocks', 'config.json');
127
+ assert.ok(existsSync(configPath));
128
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
129
+ assert.strictEqual(config.telemetry.enabled, true);
130
+ });
131
+
132
+ it('preserves existing keys in global config', () => {
133
+ const configDir = join(tmpHome, '.blocks');
134
+ mkdirSync(configDir, { recursive: true });
135
+ writeFileSync(join(configDir, 'config.json'), JSON.stringify({ telemetry: { projectId: 'xyz' }, someKey: 'value' }, null, 2));
136
+
137
+ const result = runCli(['--enable', '--global'], { cwd: tmpProject, env: { HOME: tmpHome } });
138
+ assert.strictEqual(result.exitCode, 0);
139
+
140
+ const config = JSON.parse(readFileSync(join(configDir, 'config.json'), 'utf-8'));
141
+ assert.strictEqual(config.telemetry.enabled, true);
142
+ assert.strictEqual(config.telemetry.projectId, 'xyz');
143
+ assert.strictEqual(config.someKey, 'value');
144
+ });
145
+ });
146
+
147
+ describe('--disable --global', () => {
148
+ it('creates ~/.blocks/config.json with telemetry.enabled=false', () => {
149
+ const result = runCli(['--disable', '--global'], { cwd: tmpProject, env: { HOME: tmpHome } });
150
+ assert.strictEqual(result.exitCode, 0);
151
+ assert.ok(result.stdout.includes('disabled globally'));
152
+
153
+ const configPath = join(tmpHome, '.blocks', 'config.json');
154
+ assert.ok(existsSync(configPath));
155
+ const config = JSON.parse(readFileSync(configPath, 'utf-8'));
156
+ assert.strictEqual(config.telemetry.enabled, false);
157
+ });
158
+ });
159
+
160
+ describe('--status (shows status)', () => {
161
+ it('shows enabled by default when no config exists', () => {
162
+ const result = runCli(['--status'], { cwd: tmpProject, env: { HOME: tmpHome, ...NO_CI_ENV } });
163
+ assert.strictEqual(result.exitCode, 0);
164
+ assert.ok(result.stdout.includes('Telemetry:'));
165
+ assert.ok(result.stdout.includes('Enabled'));
166
+ });
167
+
168
+ it('shows disabled when global config disables telemetry', () => {
169
+ const configDir = join(tmpHome, '.blocks');
170
+ mkdirSync(configDir, { recursive: true });
171
+ writeFileSync(join(configDir, 'config.json'), JSON.stringify({ telemetry: { enabled: false } }));
172
+
173
+ const result = runCli(['--status'], { cwd: tmpProject, env: { HOME: tmpHome, ...NO_CI_ENV } });
174
+ assert.strictEqual(result.exitCode, 0);
175
+ assert.ok(result.stdout.includes('Disabled'));
176
+ assert.ok(result.stdout.includes('Global config'));
177
+ });
178
+
179
+ it('shows disabled when env var is set to 1', () => {
180
+ const result = runCli(['--status'], { cwd: tmpProject, env: { HOME: tmpHome, ...NO_CI_ENV, AWS_BLOCKS_DISABLE_TELEMETRY: '1' } });
181
+ assert.strictEqual(result.exitCode, 0);
182
+ assert.ok(result.stdout.includes('Disabled'));
183
+ assert.ok(result.stdout.includes('AWS_BLOCKS_DISABLE_TELEMETRY'));
184
+ });
185
+
186
+ it('any disable wins — project disabled even if global enabled', () => {
187
+ const globalConfigDir = join(tmpHome, '.blocks');
188
+ mkdirSync(globalConfigDir, { recursive: true });
189
+ writeFileSync(join(globalConfigDir, 'config.json'), JSON.stringify({ telemetry: { enabled: true } }));
190
+
191
+ const projectConfigDir = join(tmpProject, '.blocks');
192
+ mkdirSync(projectConfigDir, { recursive: true });
193
+ writeFileSync(join(projectConfigDir, 'config.json'), JSON.stringify({ telemetry: { enabled: false } }));
194
+
195
+ const result = runCli(['--status'], { cwd: tmpProject, env: { HOME: tmpHome, ...NO_CI_ENV } });
196
+ assert.strictEqual(result.exitCode, 0);
197
+ assert.ok(result.stdout.includes('Disabled'));
198
+ });
199
+
200
+ it('any disable wins — global disabled even if project enabled', () => {
201
+ const globalConfigDir = join(tmpHome, '.blocks');
202
+ mkdirSync(globalConfigDir, { recursive: true });
203
+ writeFileSync(join(globalConfigDir, 'config.json'), JSON.stringify({ telemetry: { enabled: false } }));
204
+
205
+ const projectConfigDir = join(tmpProject, '.blocks');
206
+ mkdirSync(projectConfigDir, { recursive: true });
207
+ writeFileSync(join(projectConfigDir, 'config.json'), JSON.stringify({ telemetry: { enabled: true } }));
208
+
209
+ const result = runCli(['--status'], { cwd: tmpProject, env: { HOME: tmpHome, ...NO_CI_ENV } });
210
+ assert.strictEqual(result.exitCode, 0);
211
+ assert.ok(result.stdout.includes('Disabled'));
212
+ });
213
+ });
214
+
215
+ describe('error handling', () => {
216
+ it('--enable and --disable together exits with error', () => {
217
+ const result = runCli(['--enable', '--disable'], { cwd: tmpProject, env: { HOME: tmpHome } });
218
+ assert.notStrictEqual(result.exitCode, 0);
219
+ assert.ok(result.stderr.includes('mutually exclusive'));
220
+ });
221
+ });
222
+
223
+ describe('unknown flags', () => {
224
+ it('warns about unrecognized flags but still exits 0', () => {
225
+ const result = runCli(['--statu'], { cwd: tmpProject, env: { HOME: tmpHome, ...NO_CI_ENV } });
226
+ assert.strictEqual(result.exitCode, 0);
227
+ assert.ok(result.stderr.includes('Unknown option') || result.stdout.includes('Unknown option'));
228
+ assert.ok(result.stderr.includes('--statu') || result.stdout.includes('--statu'));
229
+ });
230
+
231
+ it('recognized action still runs when unknown flags are present', () => {
232
+ const result = runCli(['--enable', '--typo'], { cwd: tmpProject, env: { HOME: tmpHome, ...NO_CI_ENV } });
233
+ assert.strictEqual(result.exitCode, 0);
234
+ assert.ok(result.stderr.includes('Unknown option') || result.stdout.includes('Unknown option'));
235
+ assert.ok(result.stderr.includes('--typo') || result.stdout.includes('--typo'));
236
+ assert.ok(result.stdout.includes('enabled for this project'));
237
+ });
238
+ });
239
+ });
@@ -0,0 +1,173 @@
1
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { getTelemetryStatus, getGlobalConfigPath, getProjectConfigPath } from '../telemetry/consent.js';
5
+ import { writeConfigTelemetry } from '../telemetry/config-writer.js';
6
+
7
+ export interface TelemetryOptions {
8
+ argv?: string[];
9
+ }
10
+
11
+ interface ParsedFlags {
12
+ action: 'enable' | 'disable' | 'status' | 'help';
13
+ global: boolean;
14
+ }
15
+
16
+ function printUsage(): void {
17
+ console.log(`Usage: npx blocks-telemetry [options]
18
+
19
+ Options:
20
+ --enable Enable telemetry collection
21
+ --disable Disable telemetry collection
22
+ --status Show current telemetry status
23
+ --global Apply globally (~/.blocks/config.json)
24
+ Without this flag, applies to current project (.blocks/config.json)
25
+ --help, -h Show this help message
26
+
27
+ Examples:
28
+ npx blocks-telemetry --status # Show current status
29
+ npx blocks-telemetry --enable # Enable for current project
30
+ npx blocks-telemetry --disable # Disable for current project
31
+ npx blocks-telemetry --enable --global # Enable globally
32
+ npx blocks-telemetry --disable --global # Disable globally
33
+
34
+ Environment:
35
+ AWS_BLOCKS_DISABLE_TELEMETRY=1 Disables telemetry (overrides config files)
36
+ `);
37
+ }
38
+
39
+ const KNOWN_FLAGS = ['--enable', '--disable', '--status', '--global', '--help', '-h'];
40
+
41
+ function parseFlags(argv: string[]): ParsedFlags {
42
+ const args = argv.slice(2);
43
+
44
+ const unknownFlags = args.filter(a => a.startsWith('-') && !KNOWN_FLAGS.includes(a));
45
+ if (unknownFlags.length > 0) {
46
+ console.warn(`Unknown option(s): ${unknownFlags.join(', ')}. These will be ignored. Run 'npx blocks-telemetry --help' to see available options.`);
47
+ }
48
+
49
+ const help = args.includes('--help') || args.includes('-h');
50
+ const enable = args.includes('--enable');
51
+ const disable = args.includes('--disable');
52
+ const statusFlag = args.includes('--status');
53
+ const global = args.includes('--global');
54
+
55
+ if (enable && disable) {
56
+ console.error('Error: --enable and --disable are mutually exclusive.');
57
+ console.error('Run with --help for usage information.');
58
+ process.exit(1);
59
+ }
60
+
61
+ let action: 'enable' | 'disable' | 'status' | 'help' = 'help';
62
+ if (statusFlag) action = 'status';
63
+ if (enable) action = 'enable';
64
+ if (disable) action = 'disable';
65
+ if (help) action = 'help';
66
+
67
+ return { action, global };
68
+ }
69
+
70
+ function handleEnable(global: boolean): void {
71
+ const configPath = global ? getGlobalConfigPath() : getProjectConfigPath();
72
+
73
+ try {
74
+ writeConfigTelemetry(configPath, true);
75
+ } catch (error: unknown) {
76
+ const message = error instanceof Error ? error.message : String(error);
77
+ console.error(`❌ Failed to write config: ${message}`);
78
+ process.exit(1);
79
+ }
80
+
81
+ if (global) {
82
+ console.log('✅ Telemetry enabled globally.');
83
+ console.log(` Config: ${configPath}`);
84
+ } else {
85
+ console.log('✅ Telemetry enabled for this project.');
86
+ console.log(` Config: ${configPath}`);
87
+ }
88
+ }
89
+
90
+ function handleDisable(global: boolean): void {
91
+ const configPath = global ? getGlobalConfigPath() : getProjectConfigPath();
92
+
93
+ try {
94
+ writeConfigTelemetry(configPath, false);
95
+ } catch (error: unknown) {
96
+ const message = error instanceof Error ? error.message : String(error);
97
+ console.error(`❌ Failed to write config: ${message}`);
98
+ process.exit(1);
99
+ }
100
+
101
+ if (global) {
102
+ console.log('✅ Telemetry disabled globally.');
103
+ console.log(` Config: ${configPath}`);
104
+ } else {
105
+ console.log('✅ Telemetry disabled for this project.');
106
+ console.log(` Config: ${configPath}`);
107
+ }
108
+ }
109
+
110
+ function handleStatus(): void {
111
+ const status = getTelemetryStatus();
112
+
113
+ console.log('');
114
+ console.log(` Telemetry: ${status.enabled ? '✅ Enabled' : '❌ Disabled'}`);
115
+ console.log('');
116
+
117
+ const globalConfigPath = getGlobalConfigPath();
118
+ const projectConfigPath = getProjectConfigPath();
119
+
120
+ console.log(' Mechanisms:');
121
+
122
+ if (status.envVar !== undefined) {
123
+ console.log(` AWS_BLOCKS_DISABLE_TELEMETRY = "${status.envVar}"`);
124
+ } else {
125
+ console.log(` AWS_BLOCKS_DISABLE_TELEMETRY = (not set)`);
126
+ }
127
+
128
+ if (status.projectConfig !== undefined) {
129
+ console.log(` Project config (${projectConfigPath}): telemetry.enabled = ${status.projectConfig}`);
130
+ } else {
131
+ console.log(` Project config (${projectConfigPath}): (not configured)`);
132
+ }
133
+
134
+ if (status.globalConfig !== undefined) {
135
+ console.log(` Global config (${globalConfigPath}): telemetry.enabled = ${status.globalConfig}`);
136
+ } else {
137
+ console.log(` Global config (${globalConfigPath}): (not configured)`);
138
+ }
139
+
140
+ console.log('');
141
+ }
142
+
143
+ /**
144
+ * Manage Blocks telemetry consent settings.
145
+ *
146
+ * Parses CLI flags from `process.argv` (or custom argv) and performs the
147
+ * requested action:
148
+ *
149
+ * - `--enable` / `--disable` — toggle telemetry (project-level by default, `--global` for global)
150
+ * - `--status` — display current telemetry status and mechanism values
151
+ * - bare invocation (no flags) — prints help/usage text
152
+ *
153
+ * @param options.argv - Custom argv array (defaults to process.argv)
154
+ */
155
+ export async function telemetry(options?: TelemetryOptions): Promise<void> {
156
+ const argv = options?.argv ?? process.argv;
157
+ const flags = parseFlags(argv);
158
+
159
+ switch (flags.action) {
160
+ case 'enable':
161
+ handleEnable(flags.global);
162
+ break;
163
+ case 'disable':
164
+ handleDisable(flags.global);
165
+ break;
166
+ case 'status':
167
+ handleStatus();
168
+ break;
169
+ case 'help':
170
+ printUsage();
171
+ break;
172
+ }
173
+ }