@aws/nx-plugin 1.0.0-rc.54 → 1.0.0-rc.56

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 (284) hide show
  1. package/migrations.json +50 -0
  2. package/package.json +1 -1
  3. package/src/agentcore-gateway/gateway-connection/generator.js +3 -1
  4. package/src/agentcore-gateway/gateway-connection/generator.js.map +1 -1
  5. package/src/agentcore-gateway/generator.d.ts +49 -1
  6. package/src/agentcore-gateway/generator.js +55 -22
  7. package/src/agentcore-gateway/generator.js.map +1 -1
  8. package/src/agentcore-gateway/mcp-connection/generator.js +3 -1
  9. package/src/agentcore-gateway/mcp-connection/generator.js.map +1 -1
  10. package/src/infra/app/__snapshots__/generator.spec.ts.snap +2 -0
  11. package/src/infra/app/generator.d.ts +43 -0
  12. package/src/infra/app/generator.js +47 -18
  13. package/src/infra/app/generator.js.map +1 -1
  14. package/src/init/generator.d.ts +13 -0
  15. package/src/init/generator.js +14 -3
  16. package/src/init/generator.js.map +1 -1
  17. package/src/migrations/latest/backfill-generator-metadata/migration.d.ts +96 -0
  18. package/src/migrations/latest/backfill-generator-metadata/migration.js +670 -0
  19. package/src/migrations/latest/backfill-generator-metadata/migration.js.map +1 -0
  20. package/src/migrations/latest/dynamodb-local-remove-optimize-flag/migration.d.ts +6 -0
  21. package/src/migrations/latest/dynamodb-local-remove-optimize-flag/migration.js +89 -0
  22. package/src/migrations/latest/dynamodb-local-remove-optimize-flag/migration.js.map +1 -0
  23. package/src/migrations/latest/modernize-function-props-cast/migration.js +0 -1
  24. package/src/migrations/latest/modernize-function-props-cast/migration.js.map +1 -1
  25. package/src/migrations/latest/order-access-log-delivery-after-bucket-policy/migration.js +0 -1
  26. package/src/migrations/latest/order-access-log-delivery-after-bucket-policy/migration.js.map +1 -1
  27. package/src/migrations/latest/restrict-cors-to-custom-domains/migration.js +0 -2
  28. package/src/migrations/latest/restrict-cors-to-custom-domains/migration.js.map +1 -1
  29. package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.js +0 -1
  30. package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.js.map +1 -1
  31. package/src/migrations/latest/user-identity-waf-allow-localhost-callback/migration.js +0 -2
  32. package/src/migrations/latest/user-identity-waf-allow-localhost-callback/migration.js.map +1 -1
  33. package/src/preset/generator.d.ts +13 -0
  34. package/src/preset/generator.js +12 -3
  35. package/src/preset/generator.js.map +1 -1
  36. package/src/py/agent/a2a-connection/generator.d.ts +24 -0
  37. package/src/py/agent/a2a-connection/generator.js +49 -20
  38. package/src/py/agent/a2a-connection/generator.js.map +1 -1
  39. package/src/py/agent/gateway-connection/generator.d.ts +23 -0
  40. package/src/py/agent/gateway-connection/generator.js +45 -11
  41. package/src/py/agent/gateway-connection/generator.js.map +1 -1
  42. package/src/py/agent/generator.d.ts +146 -1
  43. package/src/py/agent/generator.js +173 -76
  44. package/src/py/agent/generator.js.map +1 -1
  45. package/src/py/agent/mcp-connection/generator.d.ts +23 -0
  46. package/src/py/agent/mcp-connection/generator.js +45 -11
  47. package/src/py/agent/mcp-connection/generator.js.map +1 -1
  48. package/src/py/agent/react-connection/generator.d.ts +146 -0
  49. package/src/py/agent/react-connection/generator.js +27 -4
  50. package/src/py/agent/react-connection/generator.js.map +1 -1
  51. package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +0 -2
  52. package/src/py/dynamodb/agent-connection/__snapshots__/generator.spec.ts.snap +18 -0
  53. package/src/py/dynamodb/agent-connection/generator.js +7 -1
  54. package/src/py/dynamodb/agent-connection/generator.js.map +1 -1
  55. package/src/py/dynamodb/fast-api-connection/__snapshots__/generator.spec.ts.snap +9 -0
  56. package/src/py/dynamodb/fast-api-connection/generator.js +3 -1
  57. package/src/py/dynamodb/fast-api-connection/generator.js.map +1 -1
  58. package/src/py/dynamodb/generator.d.ts +29 -0
  59. package/src/py/dynamodb/generator.js +32 -12
  60. package/src/py/dynamodb/generator.js.map +1 -1
  61. package/src/py/dynamodb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +18 -0
  62. package/src/py/dynamodb/mcp-server-connection/generator.js +7 -1
  63. package/src/py/dynamodb/mcp-server-connection/generator.js.map +1 -1
  64. package/src/py/fast-api/generator.d.ts +63 -0
  65. package/src/py/fast-api/generator.js +58 -23
  66. package/src/py/fast-api/generator.js.map +1 -1
  67. package/src/py/fast-api/react/generator.d.ts +16 -1
  68. package/src/py/fast-api/react/generator.js +15 -3
  69. package/src/py/fast-api/react/generator.js.map +1 -1
  70. package/src/py/lambda-function/generator.d.ts +21 -0
  71. package/src/py/lambda-function/generator.js +29 -10
  72. package/src/py/lambda-function/generator.js.map +1 -1
  73. package/src/py/mcp-server/generator.d.ts +60 -0
  74. package/src/py/mcp-server/generator.js +62 -25
  75. package/src/py/mcp-server/generator.js.map +1 -1
  76. package/src/py/project/generator.d.ts +13 -0
  77. package/src/py/project/generator.js +29 -10
  78. package/src/py/project/generator.js.map +1 -1
  79. package/src/py/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +19 -0
  80. package/src/py/rdb/agent-connection/generator.js +7 -1
  81. package/src/py/rdb/agent-connection/generator.js.map +1 -1
  82. package/src/py/rdb/fast-api-connection/__snapshots__/generator.spec.ts.snap +7 -0
  83. package/src/py/rdb/fast-api-connection/generator.js +3 -1
  84. package/src/py/rdb/fast-api-connection/generator.js.map +1 -1
  85. package/src/py/rdb/generator.d.ts +89 -0
  86. package/src/py/rdb/generator.js +88 -40
  87. package/src/py/rdb/generator.js.map +1 -1
  88. package/src/py/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +18 -0
  89. package/src/py/rdb/mcp-server-connection/generator.js +7 -1
  90. package/src/py/rdb/mcp-server-connection/generator.js.map +1 -1
  91. package/src/smithy/project/generator.d.ts +7 -0
  92. package/src/smithy/project/generator.js +8 -2
  93. package/src/smithy/project/generator.js.map +1 -1
  94. package/src/smithy/react-connection/generator.d.ts +15 -0
  95. package/src/smithy/react-connection/generator.js +17 -3
  96. package/src/smithy/react-connection/generator.js.map +1 -1
  97. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +1 -0
  98. package/src/smithy/ts/api/generator.d.ts +79 -0
  99. package/src/smithy/ts/api/generator.js +77 -33
  100. package/src/smithy/ts/api/generator.js.map +1 -1
  101. package/src/terraform/project/generator.d.ts +50 -0
  102. package/src/terraform/project/generator.js +63 -17
  103. package/src/terraform/project/generator.js.map +1 -1
  104. package/src/trpc/backend/generator.d.ts +84 -0
  105. package/src/trpc/backend/generator.js +98 -38
  106. package/src/trpc/backend/generator.js.map +1 -1
  107. package/src/trpc/react/generator.d.ts +37 -0
  108. package/src/trpc/react/generator.js +63 -26
  109. package/src/trpc/react/generator.js.map +1 -1
  110. package/src/ts/agent/a2a-connection/generator.d.ts +46 -0
  111. package/src/ts/agent/a2a-connection/generator.js +53 -16
  112. package/src/ts/agent/a2a-connection/generator.js.map +1 -1
  113. package/src/ts/agent/gateway-connection/generator.d.ts +37 -0
  114. package/src/ts/agent/gateway-connection/generator.js +41 -14
  115. package/src/ts/agent/gateway-connection/generator.js.map +1 -1
  116. package/src/ts/agent/generator.d.ts +162 -0
  117. package/src/ts/agent/generator.js +166 -75
  118. package/src/ts/agent/generator.js.map +1 -1
  119. package/src/ts/agent/mcp-connection/generator.d.ts +37 -0
  120. package/src/ts/agent/mcp-connection/generator.js +41 -14
  121. package/src/ts/agent/mcp-connection/generator.js.map +1 -1
  122. package/src/ts/agent/react-connection/generator.d.ts +186 -0
  123. package/src/ts/agent/react-connection/generator.js +70 -21
  124. package/src/ts/agent/react-connection/generator.js.map +1 -1
  125. package/src/ts/astro-docs/generator.d.ts +38 -0
  126. package/src/ts/astro-docs/generator.js +58 -19
  127. package/src/ts/astro-docs/generator.js.map +1 -1
  128. package/src/ts/dcr-proxy/generator.d.ts +24 -0
  129. package/src/ts/dcr-proxy/generator.js +31 -14
  130. package/src/ts/dcr-proxy/generator.js.map +1 -1
  131. package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +0 -2
  132. package/src/ts/dynamodb/agent-connection/__snapshots__/generator.spec.ts.snap +18 -0
  133. package/src/ts/dynamodb/agent-connection/generator.js +7 -1
  134. package/src/ts/dynamodb/agent-connection/generator.js.map +1 -1
  135. package/src/ts/dynamodb/generator.d.ts +41 -0
  136. package/src/ts/dynamodb/generator.js +47 -20
  137. package/src/ts/dynamodb/generator.js.map +1 -1
  138. package/src/ts/dynamodb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +18 -0
  139. package/src/ts/dynamodb/mcp-server-connection/generator.js +7 -1
  140. package/src/ts/dynamodb/mcp-server-connection/generator.js.map +1 -1
  141. package/src/ts/dynamodb/smithy-connection/__snapshots__/generator.spec.ts.snap +9 -0
  142. package/src/ts/dynamodb/smithy-connection/generator.js +3 -1
  143. package/src/ts/dynamodb/smithy-connection/generator.js.map +1 -1
  144. package/src/ts/dynamodb/trpc-connection/__snapshots__/generator.spec.ts.snap +9 -0
  145. package/src/ts/dynamodb/trpc-connection/generator.js +3 -1
  146. package/src/ts/dynamodb/trpc-connection/generator.js.map +1 -1
  147. package/src/ts/lambda-function/generator.d.ts +38 -0
  148. package/src/ts/lambda-function/generator.js +49 -20
  149. package/src/ts/lambda-function/generator.js.map +1 -1
  150. package/src/ts/lib/generator.d.ts +7 -0
  151. package/src/ts/lib/generator.js +8 -1
  152. package/src/ts/lib/generator.js.map +1 -1
  153. package/src/ts/lib/ts-project-utils.d.ts +3 -1
  154. package/src/ts/lib/ts-project-utils.js +3 -2
  155. package/src/ts/lib/ts-project-utils.js.map +1 -1
  156. package/src/ts/lib/vitest.d.ts +10 -1
  157. package/src/ts/lib/vitest.js +14 -2
  158. package/src/ts/lib/vitest.js.map +1 -1
  159. package/src/ts/mcp-server/generator.d.ts +71 -0
  160. package/src/ts/mcp-server/generator.js +73 -36
  161. package/src/ts/mcp-server/generator.js.map +1 -1
  162. package/src/ts/nx-generator/generator.d.ts +3 -0
  163. package/src/ts/nx-generator/generator.js +8 -2
  164. package/src/ts/nx-generator/generator.js.map +1 -1
  165. package/src/ts/nx-migration/files/migration.ts.template +4 -0
  166. package/src/ts/nx-migration/generator.d.ts +3 -0
  167. package/src/ts/nx-migration/generator.js +8 -2
  168. package/src/ts/nx-migration/generator.js.map +1 -1
  169. package/src/ts/nx-plugin/generator.d.ts +3 -0
  170. package/src/ts/nx-plugin/generator.js +8 -2
  171. package/src/ts/nx-plugin/generator.js.map +1 -1
  172. package/src/ts/nx-plugin/utils.d.ts +7 -2
  173. package/src/ts/nx-plugin/utils.js +10 -4
  174. package/src/ts/nx-plugin/utils.js.map +1 -1
  175. package/src/ts/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +10 -0
  176. package/src/ts/rdb/agent-connection/generator.js +8 -1
  177. package/src/ts/rdb/agent-connection/generator.js.map +1 -1
  178. package/src/ts/rdb/generator.d.ts +101 -0
  179. package/src/ts/rdb/generator.js +93 -41
  180. package/src/ts/rdb/generator.js.map +1 -1
  181. package/src/ts/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +10 -0
  182. package/src/ts/rdb/mcp-server-connection/generator.js +8 -1
  183. package/src/ts/rdb/mcp-server-connection/generator.js.map +1 -1
  184. package/src/ts/rdb/smithy-connection/__snapshots__/generator.spec.ts.snap +9 -0
  185. package/src/ts/rdb/smithy-connection/generator.js +4 -1
  186. package/src/ts/rdb/smithy-connection/generator.js.map +1 -1
  187. package/src/ts/rdb/trpc-connection/__snapshots__/generator.spec.ts.snap +9 -0
  188. package/src/ts/rdb/trpc-connection/generator.js +3 -1
  189. package/src/ts/rdb/trpc-connection/generator.js.map +1 -1
  190. package/src/ts/react-website/agui/generator.d.ts +86 -0
  191. package/src/ts/react-website/agui/generator.js +63 -28
  192. package/src/ts/react-website/agui/generator.js.map +1 -1
  193. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +8 -2
  194. package/src/ts/react-website/app/generator.d.ts +136 -1
  195. package/src/ts/react-website/app/generator.js +109 -40
  196. package/src/ts/react-website/app/generator.js.map +1 -1
  197. package/src/ts/react-website/cognito-auth/generator.d.ts +19 -0
  198. package/src/ts/react-website/cognito-auth/generator.js +21 -9
  199. package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
  200. package/src/utils/add-dependencies.d.ts +38 -0
  201. package/src/utils/add-dependencies.js +83 -0
  202. package/src/utils/add-dependencies.js.map +1 -0
  203. package/src/utils/agent-connection/agent-connection.d.ts +27 -6
  204. package/src/utils/agent-connection/agent-connection.js +47 -18
  205. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  206. package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +19 -1
  207. package/src/utils/agent-core-constructs/agent-core-constructs.js +26 -6
  208. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  209. package/src/utils/api-constructs/api-constructs.d.ts +21 -2
  210. package/src/utils/api-constructs/api-constructs.js +26 -5
  211. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  212. package/src/utils/bundle/bundle.d.ts +6 -1
  213. package/src/utils/bundle/bundle.js +8 -2
  214. package/src/utils/bundle/bundle.js.map +1 -1
  215. package/src/utils/commands.d.ts +5 -4
  216. package/src/utils/commands.js +2 -6
  217. package/src/utils/commands.js.map +1 -1
  218. package/src/utils/connection/open-api/react.d.ts +18 -1
  219. package/src/utils/connection/open-api/react.js +27 -3
  220. package/src/utils/connection/open-api/react.js.map +1 -1
  221. package/src/utils/declared-dependencies.d.ts +140 -0
  222. package/src/utils/declared-dependencies.js +64 -0
  223. package/src/utils/declared-dependencies.js.map +1 -0
  224. package/src/utils/docker.d.ts +10 -1
  225. package/src/utils/docker.js +7 -3
  226. package/src/utils/docker.js.map +1 -1
  227. package/src/utils/files/common/scripts/src/dynamodb/start-container.ts.template +0 -1
  228. package/src/utils/fs.d.ts +15 -4
  229. package/src/utils/fs.js +26 -13
  230. package/src/utils/fs.js.map +1 -1
  231. package/src/utils/init.d.ts +14 -1
  232. package/src/utils/init.js +25 -7
  233. package/src/utils/init.js.map +1 -1
  234. package/src/utils/migration-versions.d.ts +25 -6
  235. package/src/utils/migration-versions.js +72 -14
  236. package/src/utils/migration-versions.js.map +1 -1
  237. package/src/utils/nx.d.ts +18 -0
  238. package/src/utils/nx.js +4 -0
  239. package/src/utils/nx.js.map +1 -1
  240. package/src/utils/py.d.ts +3 -2
  241. package/src/utils/py.js +10 -10
  242. package/src/utils/py.js.map +1 -1
  243. package/src/utils/shared-constructs-constants.d.ts +39 -4
  244. package/src/utils/shared-constructs-constants.js +29 -0
  245. package/src/utils/shared-constructs-constants.js.map +1 -1
  246. package/src/utils/shared-constructs.d.ts +4 -1
  247. package/src/utils/shared-constructs.js +5 -4
  248. package/src/utils/shared-constructs.js.map +1 -1
  249. package/src/utils/shared-dynamodb-scripts.d.ts +8 -1
  250. package/src/utils/shared-dynamodb-scripts.js +11 -3
  251. package/src/utils/shared-dynamodb-scripts.js.map +1 -1
  252. package/src/utils/shared-infra-scripts.d.ts +16 -1
  253. package/src/utils/shared-infra-scripts.js +18 -3
  254. package/src/utils/shared-infra-scripts.js.map +1 -1
  255. package/src/utils/shared-rdb-scripts.d.ts +12 -1
  256. package/src/utils/shared-rdb-scripts.js +17 -3
  257. package/src/utils/shared-rdb-scripts.js.map +1 -1
  258. package/src/utils/shared-shadcn.d.ts +26 -1
  259. package/src/utils/shared-shadcn.js +31 -14
  260. package/src/utils/shared-shadcn.js.map +1 -1
  261. package/src/utils/version-upgrade-migration/migration.d.ts +14 -0
  262. package/src/utils/version-upgrade-migration/migration.js +16 -0
  263. package/src/utils/version-upgrade-migration/migration.js.map +1 -0
  264. package/src/utils/version-upgrade-migration/nx-package-updates.d.ts +45 -0
  265. package/src/utils/version-upgrade-migration/nx-package-updates.js +50 -0
  266. package/src/utils/version-upgrade-migration/nx-package-updates.js.map +1 -0
  267. package/src/utils/version-upgrade-migration/owned-dependencies.d.ts +50 -0
  268. package/src/utils/version-upgrade-migration/owned-dependencies.js +98 -0
  269. package/src/utils/version-upgrade-migration/owned-dependencies.js.map +1 -0
  270. package/src/utils/version-upgrade-migration/register.d.ts +23 -0
  271. package/src/utils/version-upgrade-migration/register.js +38 -0
  272. package/src/utils/version-upgrade-migration/register.js.map +1 -0
  273. package/src/utils/version-upgrade-migration/sync-metrics-version.d.ts +13 -0
  274. package/src/utils/version-upgrade-migration/sync-metrics-version.js +33 -0
  275. package/src/utils/version-upgrade-migration/sync-metrics-version.js.map +1 -0
  276. package/src/utils/version-upgrade-migration/sync-vended-versions.d.ts +10 -0
  277. package/src/utils/version-upgrade-migration/sync-vended-versions.js +504 -0
  278. package/src/utils/version-upgrade-migration/sync-vended-versions.js.map +1 -0
  279. package/src/utils/version-upgrade-migration/vended-upgrade.d.ts +14 -0
  280. package/src/utils/version-upgrade-migration/vended-upgrade.js +40 -0
  281. package/src/utils/version-upgrade-migration/vended-upgrade.js.map +1 -0
  282. package/src/utils/versions.d.ts +25 -5
  283. package/src/utils/versions.js +46 -4
  284. package/src/utils/versions.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/docker.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n joinPathFragments,\n type ProjectConfiguration,\n type Tree,\n} from '@nx/devkit';\nimport { FsCommands } from './fs';\nimport { addDependencyToTargetIfNotPresent } from './nx';\nimport { CONTAINER_VERSIONS, TS_VERSIONS } from './versions';\n\nconst TRIVY_IGNORE_FILE = '.trivyignore';\n\nconst TRIVY_IGNORE_CONTENTS = `# Trivy ignore file. Add one vulnerability ID (e.g. CVE-2021-12345) per line to\n# suppress it during the image scan (\\`nx run-many --target trivy\\`).\n# https://trivy.dev/latest/docs/configuration/filtering/#by-finding-ids\n`;\n\n/**\n * Substitution variables for the vended Node `Dockerfile` templates: the npm\n * version to install globally, and the versions its dependency overrides pin.\n */\nexport const nodeImageVersions = () => ({\n npmVersion: TS_VERSIONS.npm,\n minimatchVersion: TS_VERSIONS.minimatch,\n});\n\nexport interface DockerScanTargetOptions {\n /**\n * Project configuration to add the scan target to (mutated in place).\n */\n readonly project: ProjectConfiguration;\n /**\n * Container engine command to invoke (\\`docker\\` or \\`finch\\`).\n */\n readonly containerEngine: string;\n /**\n * Name of the scan target to add, e.g. \\`my-agent-trivy\\`.\n */\n readonly trivyTargetName: string;\n /**\n * Name of the docker target that builds the image(s) to scan. The scan\n * target depends on it.\n */\n readonly dockerTargetName: string;\n /**\n * Tags of the images built by the docker target which should be scanned.\n */\n readonly imageTags: string[];\n}\n\n/**\n * Add a cacheable Trivy scan target for the images built by a docker target\n * and wire it under the aggregate \\`trivy\\` target. The scan is not part of\n * \\`build\\` — run \\`nx run-many --target trivy\\` (the root \\`trivy\\` script) in CI.\n *\n * The scan target depends on the docker target and declares the project source\n * as its inputs, so an unchanged image is never re-scanned (a cache hit skips\n * the scan entirely). Each image is saved to a tarball under\n * \\`dist/<projectRoot>/trivy/<scan-key>\\` (kept out of any Docker build context)\n * and scanned with the pinned ECR-hosted Trivy image via a workspace-relative\n * bind mount, so the same commands work under both docker and finch. The scan\n * exits non-zero (exit code 1) on HIGH/CRITICAL vulnerabilities.\n *\n * A \\`.trivyignore\\` is vended at the project root (kept if it already exists)\n * for suppressing findings.\n */\nexport const addDockerScanTarget = (\n tree: Tree,\n options: DockerScanTargetOptions,\n): void => {\n const { project, containerEngine, trivyTargetName, dockerTargetName } =\n options;\n const { imageTags } = options;\n const projectRoot = project.root;\n\n const ignoreFilePath = joinPathFragments(projectRoot, TRIVY_IGNORE_FILE);\n if (!tree.exists(ignoreFilePath)) {\n tree.write(ignoreFilePath, TRIVY_IGNORE_CONTENTS);\n }\n\n // Stage scan artifacts in a directory unique to this scan target so that\n // sibling targets in the same project (e.g. multiple agents) don't clobber\n // each other's tarballs when run in parallel. The first image tag is unique\n // per target, so it makes a stable, collision-free key.\n const scanKey = imageTags[0].replace(/[^a-zA-Z0-9-]/g, '-');\n const scanDir = joinPathFragments('dist', projectRoot, 'trivy', scanKey);\n const trivyImage = `public.ecr.aws/aquasecurity/trivy:${CONTAINER_VERSIONS.trivy}`;\n\n const fs = new FsCommands(tree);\n const commands = [\n fs.rm(scanDir),\n fs.mkdir(scanDir),\n fs.cp(ignoreFilePath, joinPathFragments(scanDir, TRIVY_IGNORE_FILE)),\n ];\n\n imageTags.forEach((imageTag, index) => {\n const tarName = `image-${index}.tar`;\n commands.push(\n `${containerEngine} save -o ${joinPathFragments(scanDir, tarName)} ${imageTag}`,\n `${containerEngine} run --rm -v \"./${scanDir}\":/scan ${trivyImage} image --input /scan/${tarName} --ignorefile /scan/${TRIVY_IGNORE_FILE} --scanners vuln --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 --no-progress -q`,\n );\n });\n\n project.targets ??= {};\n project.targets[trivyTargetName] = {\n cache: true,\n // The scanned image is fully determined by the project source, so caching\n // on the source ensures an unchanged image is never re-scanned.\n inputs: ['default', '^production'],\n outputs: [`{workspaceRoot}/${scanDir}`],\n executor: 'nx:run-commands',\n options: {\n commands,\n parallel: false,\n },\n dependsOn: [dockerTargetName],\n };\n\n // Aggregate per-component scan targets under a single `trivy` target. The\n // scan is intentionally NOT wired into `build`: image scanning is slow and\n // its result depends on the ever-changing vulnerability database (a scan\n // that passes today can fail tomorrow when a new CVE is published), so\n // coupling it to `build` would make local and CI builds non-deterministic.\n // Run `nx run-many --target trivy` (the root `trivy` script) in CI instead.\n if (trivyTargetName !== 'trivy') {\n addDependencyToTargetIfNotPresent(project, 'trivy', trivyTargetName);\n }\n};\n"],"names":["joinPathFragments","FsCommands","addDependencyToTargetIfNotPresent","CONTAINER_VERSIONS","TS_VERSIONS","TRIVY_IGNORE_FILE","TRIVY_IGNORE_CONTENTS","nodeImageVersions","npmVersion","npm","minimatchVersion","minimatch","addDockerScanTarget","tree","options","project","containerEngine","trivyTargetName","dockerTargetName","imageTags","projectRoot","root","ignoreFilePath","exists","write","scanKey","replace","scanDir","trivyImage","trivy","fs","commands","rm","mkdir","cp","forEach","imageTag","index","tarName","push","targets","cache","inputs","outputs","executor","parallel","dependsOn"],"mappings":"AAAA;;;CAGC,GACD,SACEA,iBAAiB,QAGZ,aAAa;AACpB,SAASC,UAAU,QAAQ,UAAO;AAClC,SAASC,iCAAiC,QAAQ,UAAO;AACzD,SAASC,kBAAkB,EAAEC,WAAW,QAAQ,gBAAa;AAE7D,MAAMC,oBAAoB;AAE1B,MAAMC,wBAAwB,CAAC;;;AAG/B,CAAC;AAED;;;CAGC,GACD,OAAO,MAAMC,oBAAoB,IAAO,CAAA;QACtCC,YAAYJ,YAAYK,GAAG;QAC3BC,kBAAkBN,YAAYO,SAAS;IACzC,CAAA,EAAG;AA0BH;;;;;;;;;;;;;;;CAeC,GACD,OAAO,MAAMC,sBAAsB,CACjCC,MACAC;IAEA,MAAM,EAAEC,OAAO,EAAEC,eAAe,EAAEC,eAAe,EAAEC,gBAAgB,EAAE,GACnEJ;IACF,MAAM,EAAEK,SAAS,EAAE,GAAGL;IACtB,MAAMM,cAAcL,QAAQM,IAAI;IAEhC,MAAMC,iBAAiBtB,kBAAkBoB,aAAaf;IACtD,IAAI,CAACQ,KAAKU,MAAM,CAACD,iBAAiB;QAChCT,KAAKW,KAAK,CAACF,gBAAgBhB;IAC7B;IAEA,yEAAyE;IACzE,2EAA2E;IAC3E,4EAA4E;IAC5E,wDAAwD;IACxD,MAAMmB,UAAUN,SAAS,CAAC,EAAE,CAACO,OAAO,CAAC,kBAAkB;IACvD,MAAMC,UAAU3B,kBAAkB,QAAQoB,aAAa,SAASK;IAChE,MAAMG,aAAa,CAAC,kCAAkC,EAAEzB,mBAAmB0B,KAAK,EAAE;IAElF,MAAMC,KAAK,IAAI7B,WAAWY;IAC1B,MAAMkB,WAAW;QACfD,GAAGE,EAAE,CAACL;QACNG,GAAGG,KAAK,CAACN;QACTG,GAAGI,EAAE,CAACZ,gBAAgBtB,kBAAkB2B,SAAStB;KAClD;IAEDc,UAAUgB,OAAO,CAAC,CAACC,UAAUC;QAC3B,MAAMC,UAAU,CAAC,MAAM,EAAED,MAAM,IAAI,CAAC;QACpCN,SAASQ,IAAI,CACX,GAAGvB,gBAAgB,SAAS,EAAEhB,kBAAkB2B,SAASW,SAAS,CAAC,EAAEF,UAAU,EAC/E,GAAGpB,gBAAgB,gBAAgB,EAAEW,QAAQ,QAAQ,EAAEC,WAAW,qBAAqB,EAAEU,QAAQ,oBAAoB,EAAEjC,kBAAkB,yFAAyF,CAAC;IAEvO;IAEAU,QAAQyB,OAAO,KAAK,CAAC;IACrBzB,QAAQyB,OAAO,CAACvB,gBAAgB,GAAG;QACjCwB,OAAO;QACP,0EAA0E;QAC1E,gEAAgE;QAChEC,QAAQ;YAAC;YAAW;SAAc;QAClCC,SAAS;YAAC,CAAC,gBAAgB,EAAEhB,SAAS;SAAC;QACvCiB,UAAU;QACV9B,SAAS;YACPiB;YACAc,UAAU;QACZ;QACAC,WAAW;YAAC5B;SAAiB;IAC/B;IAEA,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,uEAAuE;IACvE,2EAA2E;IAC3E,4EAA4E;IAC5E,IAAID,oBAAoB,SAAS;QAC/Bf,kCAAkCa,SAAS,SAASE;IACtD;AACF,EAAE"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/docker.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n joinPathFragments,\n type ProjectConfiguration,\n type Tree,\n} from '@nx/devkit';\nimport {\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from './declared-dependencies';\nimport { FS_DEPENDENCIES, FsCommands } from './fs';\nimport { addDependencyToTargetIfNotPresent } from './nx';\nimport { CONTAINER_VERSIONS, TS_VERSIONS } from './versions';\n\n/** Dependencies a caller must declare to add a Docker scan target. */\nexport const DOCKER_DEPENDENCIES = [...FS_DEPENDENCIES] as const;\n\nconst TRIVY_IGNORE_FILE = '.trivyignore';\n\nconst TRIVY_IGNORE_CONTENTS = `# Trivy ignore file. Add one vulnerability ID (e.g. CVE-2021-12345) per line to\n# suppress it during the image scan (\\`nx run-many --target trivy\\`).\n# https://trivy.dev/latest/docs/configuration/filtering/#by-finding-ids\n`;\n\n/**\n * Substitution variables for the vended Node `Dockerfile` templates: the npm\n * version to install globally, and the versions its dependency overrides pin.\n */\nexport const nodeImageVersions = () => ({\n npmVersion: TS_VERSIONS.npm,\n minimatchVersion: TS_VERSIONS.minimatch,\n});\n\nexport interface DockerScanTargetOptions {\n /**\n * Project configuration to add the scan target to (mutated in place).\n */\n readonly project: ProjectConfiguration;\n /**\n * Container engine command to invoke (\\`docker\\` or \\`finch\\`).\n */\n readonly containerEngine: string;\n /**\n * Name of the scan target to add, e.g. \\`my-agent-trivy\\`.\n */\n readonly trivyTargetName: string;\n /**\n * Name of the docker target that builds the image(s) to scan. The scan\n * target depends on it.\n */\n readonly dockerTargetName: string;\n /**\n * Tags of the images built by the docker target which should be scanned.\n */\n readonly imageTags: string[];\n}\n\n/**\n * Add a cacheable Trivy scan target for the images built by a docker target\n * and wire it under the aggregate \\`trivy\\` target. The scan is not part of\n * \\`build\\` — run \\`nx run-many --target trivy\\` (the root \\`trivy\\` script) in CI.\n *\n * The scan target depends on the docker target and declares the project source\n * as its inputs, so an unchanged image is never re-scanned (a cache hit skips\n * the scan entirely). Each image is saved to a tarball under\n * \\`dist/<projectRoot>/trivy/<scan-key>\\` (kept out of any Docker build context)\n * and scanned with the pinned ECR-hosted Trivy image via a workspace-relative\n * bind mount, so the same commands work under both docker and finch. The scan\n * exits non-zero (exit code 1) on HIGH/CRITICAL vulnerabilities.\n *\n * A \\`.trivyignore\\` is vended at the project root (kept if it already exists)\n * for suppressing findings.\n */\nexport const addDockerScanTarget = <const D extends DependencyDeclaration>(\n tree: Tree,\n options: DockerScanTargetOptions,\n declaration: D & MustDeclare<typeof DOCKER_DEPENDENCIES, D>,\n): void => {\n const { project, containerEngine, trivyTargetName, dockerTargetName } =\n options;\n const { imageTags } = options;\n const projectRoot = project.root;\n\n const ignoreFilePath = joinPathFragments(projectRoot, TRIVY_IGNORE_FILE);\n if (!tree.exists(ignoreFilePath)) {\n tree.write(ignoreFilePath, TRIVY_IGNORE_CONTENTS);\n }\n\n // Stage scan artifacts in a directory unique to this scan target so that\n // sibling targets in the same project (e.g. multiple agents) don't clobber\n // each other's tarballs when run in parallel. The first image tag is unique\n // per target, so it makes a stable, collision-free key.\n const scanKey = imageTags[0].replace(/[^a-zA-Z0-9-]/g, '-');\n const scanDir = joinPathFragments('dist', projectRoot, 'trivy', scanKey);\n const trivyImage = `public.ecr.aws/aquasecurity/trivy:${CONTAINER_VERSIONS.trivy}`;\n\n const fs = new FsCommands(\n tree,\n forDependencies<typeof DOCKER_DEPENDENCIES>(declaration),\n );\n const commands = [\n fs.rm(scanDir),\n fs.mkdir(scanDir),\n fs.cp(ignoreFilePath, joinPathFragments(scanDir, TRIVY_IGNORE_FILE)),\n ];\n\n imageTags.forEach((imageTag, index) => {\n const tarName = `image-${index}.tar`;\n commands.push(\n `${containerEngine} save -o ${joinPathFragments(scanDir, tarName)} ${imageTag}`,\n `${containerEngine} run --rm -v \"./${scanDir}\":/scan ${trivyImage} image --input /scan/${tarName} --ignorefile /scan/${TRIVY_IGNORE_FILE} --scanners vuln --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 --no-progress -q`,\n );\n });\n\n project.targets ??= {};\n project.targets[trivyTargetName] = {\n cache: true,\n // The scanned image is fully determined by the project source, so caching\n // on the source ensures an unchanged image is never re-scanned.\n inputs: ['default', '^production'],\n outputs: [`{workspaceRoot}/${scanDir}`],\n executor: 'nx:run-commands',\n options: {\n commands,\n parallel: false,\n },\n dependsOn: [dockerTargetName],\n };\n\n // Aggregate per-component scan targets under a single `trivy` target. The\n // scan is intentionally NOT wired into `build`: image scanning is slow and\n // its result depends on the ever-changing vulnerability database (a scan\n // that passes today can fail tomorrow when a new CVE is published), so\n // coupling it to `build` would make local and CI builds non-deterministic.\n // Run `nx run-many --target trivy` (the root `trivy` script) in CI instead.\n if (trivyTargetName !== 'trivy') {\n addDependencyToTargetIfNotPresent(project, 'trivy', trivyTargetName);\n }\n};\n"],"names":["joinPathFragments","forDependencies","FS_DEPENDENCIES","FsCommands","addDependencyToTargetIfNotPresent","CONTAINER_VERSIONS","TS_VERSIONS","DOCKER_DEPENDENCIES","TRIVY_IGNORE_FILE","TRIVY_IGNORE_CONTENTS","nodeImageVersions","npmVersion","npm","minimatchVersion","minimatch","addDockerScanTarget","tree","options","declaration","project","containerEngine","trivyTargetName","dockerTargetName","imageTags","projectRoot","root","ignoreFilePath","exists","write","scanKey","replace","scanDir","trivyImage","trivy","fs","commands","rm","mkdir","cp","forEach","imageTag","index","tarName","push","targets","cache","inputs","outputs","executor","parallel","dependsOn"],"mappings":"AAAA;;;CAGC,GACD,SACEA,iBAAiB,QAGZ,aAAa;AACpB,SAEEC,eAAe,QAEV,6BAA0B;AACjC,SAASC,eAAe,EAAEC,UAAU,QAAQ,UAAO;AACnD,SAASC,iCAAiC,QAAQ,UAAO;AACzD,SAASC,kBAAkB,EAAEC,WAAW,QAAQ,gBAAa;AAE7D,oEAAoE,GACpE,OAAO,MAAMC,sBAAsB;OAAIL;CAAgB,CAAU;AAEjE,MAAMM,oBAAoB;AAE1B,MAAMC,wBAAwB,CAAC;;;AAG/B,CAAC;AAED;;;CAGC,GACD,OAAO,MAAMC,oBAAoB,IAAO,CAAA;QACtCC,YAAYL,YAAYM,GAAG;QAC3BC,kBAAkBP,YAAYQ,SAAS;IACzC,CAAA,EAAG;AA0BH;;;;;;;;;;;;;;;CAeC,GACD,OAAO,MAAMC,sBAAsB,CACjCC,MACAC,SACAC;IAEA,MAAM,EAAEC,OAAO,EAAEC,eAAe,EAAEC,eAAe,EAAEC,gBAAgB,EAAE,GACnEL;IACF,MAAM,EAAEM,SAAS,EAAE,GAAGN;IACtB,MAAMO,cAAcL,QAAQM,IAAI;IAEhC,MAAMC,iBAAiB1B,kBAAkBwB,aAAahB;IACtD,IAAI,CAACQ,KAAKW,MAAM,CAACD,iBAAiB;QAChCV,KAAKY,KAAK,CAACF,gBAAgBjB;IAC7B;IAEA,yEAAyE;IACzE,2EAA2E;IAC3E,4EAA4E;IAC5E,wDAAwD;IACxD,MAAMoB,UAAUN,SAAS,CAAC,EAAE,CAACO,OAAO,CAAC,kBAAkB;IACvD,MAAMC,UAAU/B,kBAAkB,QAAQwB,aAAa,SAASK;IAChE,MAAMG,aAAa,CAAC,kCAAkC,EAAE3B,mBAAmB4B,KAAK,EAAE;IAElF,MAAMC,KAAK,IAAI/B,WACba,MACAf,gBAA4CiB;IAE9C,MAAMiB,WAAW;QACfD,GAAGE,EAAE,CAACL;QACNG,GAAGG,KAAK,CAACN;QACTG,GAAGI,EAAE,CAACZ,gBAAgB1B,kBAAkB+B,SAASvB;KAClD;IAEDe,UAAUgB,OAAO,CAAC,CAACC,UAAUC;QAC3B,MAAMC,UAAU,CAAC,MAAM,EAAED,MAAM,IAAI,CAAC;QACpCN,SAASQ,IAAI,CACX,GAAGvB,gBAAgB,SAAS,EAAEpB,kBAAkB+B,SAASW,SAAS,CAAC,EAAEF,UAAU,EAC/E,GAAGpB,gBAAgB,gBAAgB,EAAEW,QAAQ,QAAQ,EAAEC,WAAW,qBAAqB,EAAEU,QAAQ,oBAAoB,EAAElC,kBAAkB,yFAAyF,CAAC;IAEvO;IAEAW,QAAQyB,OAAO,KAAK,CAAC;IACrBzB,QAAQyB,OAAO,CAACvB,gBAAgB,GAAG;QACjCwB,OAAO;QACP,0EAA0E;QAC1E,gEAAgE;QAChEC,QAAQ;YAAC;YAAW;SAAc;QAClCC,SAAS;YAAC,CAAC,gBAAgB,EAAEhB,SAAS;SAAC;QACvCiB,UAAU;QACV/B,SAAS;YACPkB;YACAc,UAAU;QACZ;QACAC,WAAW;YAAC5B;SAAiB;IAC/B;IAEA,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,uEAAuE;IACvE,2EAA2E;IAC3E,4EAA4E;IAC5E,IAAID,oBAAoB,SAAS;QAC/BjB,kCAAkCe,SAAS,SAASE;IACtD;AACF,EAAE"}
@@ -64,7 +64,6 @@ for (;;) {
64
64
  '-sharedDb',
65
65
  '-dbPath', './data',
66
66
  '-port', `${port}`,
67
- '-optimizeDbBeforeStartup',
68
67
  ];
69
68
  const create = spawnSync(containerEngine, runArgs, { stdio: 'pipe' });
70
69
  if (create.status === 0) {
package/src/utils/fs.d.ts CHANGED
@@ -3,14 +3,25 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import type { Tree } from '@nx/devkit';
6
+ import { type DependencyDeclaration, type MustDeclare } from './declared-dependencies';
7
+ /** Dependencies a caller must declare to use `FsCommands`. */
8
+ export declare const FS_DEPENDENCIES: readonly [{
9
+ readonly name: "ncp";
10
+ }, {
11
+ readonly name: "rimraf";
12
+ }, {
13
+ readonly name: "make-dir-cli";
14
+ }];
6
15
  /**
7
- * Utility class for creating platform agnostic commands for filesystem operations.
8
- * Adds the required dependencies to the root package json
16
+ * Platform agnostic commands for filesystem operations, adding the CLIs they
17
+ * need to the root package.json.
9
18
  */
10
- export declare class FsCommands {
19
+ export declare class FsCommands<D extends DependencyDeclaration> {
11
20
  private tree;
12
- constructor(tree: Tree);
21
+ private declaration;
22
+ constructor(tree: Tree, declaration: D & MustDeclare<typeof FS_DEPENDENCIES, D>);
13
23
  cp(src: string, dst: string): string;
14
24
  rm(dir: string): string;
15
25
  mkdir(dir: string): string;
26
+ private add;
16
27
  }
package/src/utils/fs.js CHANGED
@@ -1,34 +1,47 @@
1
1
  /**
2
2
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
- */ import { addDependenciesToPackageJson } from "./dependencies.js";
4
+ */ import { forDependencies } from "./declared-dependencies.js";
5
+ import { addDependenciesToPackageJson } from "./dependencies.js";
5
6
  import { withVersions } from "./versions.js";
7
+ /** Dependencies a caller must declare to use `FsCommands`. */ export const FS_DEPENDENCIES = [
8
+ {
9
+ name: 'ncp'
10
+ },
11
+ {
12
+ name: 'rimraf'
13
+ },
14
+ {
15
+ name: 'make-dir-cli'
16
+ }
17
+ ];
6
18
  /**
7
- * Utility class for creating platform agnostic commands for filesystem operations.
8
- * Adds the required dependencies to the root package json
19
+ * Platform agnostic commands for filesystem operations, adding the CLIs they
20
+ * need to the root package.json.
9
21
  */ export class FsCommands {
10
22
  tree;
11
- constructor(tree){
23
+ declaration;
24
+ constructor(tree, declaration){
12
25
  this.tree = tree;
26
+ this.declaration = declaration;
13
27
  }
14
28
  cp(src, dst) {
15
- addDependenciesToPackageJson(this.tree, {}, withVersions([
16
- 'ncp'
17
- ]));
29
+ this.add('ncp');
18
30
  return `ncp ${src} ${dst}`;
19
31
  }
20
32
  rm(dir) {
21
- addDependenciesToPackageJson(this.tree, {}, withVersions([
22
- 'rimraf'
23
- ]));
33
+ this.add('rimraf');
24
34
  return `rimraf ${dir}`;
25
35
  }
26
36
  mkdir(dir) {
27
- addDependenciesToPackageJson(this.tree, {}, withVersions([
28
- 'make-dir-cli'
29
- ]));
37
+ this.add('make-dir-cli');
30
38
  return `make-dir ${dir}`;
31
39
  }
40
+ add(dep) {
41
+ addDependenciesToPackageJson(this.tree, {}, withVersions(forDependencies(this.declaration), [
42
+ dep
43
+ ]));
44
+ }
32
45
  }
33
46
 
34
47
  //# sourceMappingURL=fs.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/fs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Tree } from '@nx/devkit';\nimport { addDependenciesToPackageJson } from './dependencies';\nimport { withVersions } from './versions';\n\n/**\n * Utility class for creating platform agnostic commands for filesystem operations.\n * Adds the required dependencies to the root package json\n */\nexport class FsCommands {\n private tree: Tree;\n\n constructor(tree: Tree) {\n this.tree = tree;\n }\n\n public cp(src: string, dst: string) {\n addDependenciesToPackageJson(this.tree, {}, withVersions(['ncp']));\n return `ncp ${src} ${dst}`;\n }\n\n public rm(dir: string) {\n addDependenciesToPackageJson(this.tree, {}, withVersions(['rimraf']));\n return `rimraf ${dir}`;\n }\n\n public mkdir(dir: string) {\n addDependenciesToPackageJson(this.tree, {}, withVersions(['make-dir-cli']));\n return `make-dir ${dir}`;\n }\n}\n"],"names":["addDependenciesToPackageJson","withVersions","FsCommands","tree","cp","src","dst","rm","dir","mkdir"],"mappings":"AAAA;;;CAGC,GAED,SAASA,4BAA4B,QAAQ,oBAAiB;AAC9D,SAASC,YAAY,QAAQ,gBAAa;AAE1C;;;CAGC,GACD,OAAO,MAAMC;IACHC,KAAW;IAEnB,YAAYA,IAAU,CAAE;QACtB,IAAI,CAACA,IAAI,GAAGA;IACd;IAEOC,GAAGC,GAAW,EAAEC,GAAW,EAAE;QAClCN,6BAA6B,IAAI,CAACG,IAAI,EAAE,CAAC,GAAGF,aAAa;YAAC;SAAM;QAChE,OAAO,CAAC,IAAI,EAAEI,IAAI,CAAC,EAAEC,KAAK;IAC5B;IAEOC,GAAGC,GAAW,EAAE;QACrBR,6BAA6B,IAAI,CAACG,IAAI,EAAE,CAAC,GAAGF,aAAa;YAAC;SAAS;QACnE,OAAO,CAAC,OAAO,EAAEO,KAAK;IACxB;IAEOC,MAAMD,GAAW,EAAE;QACxBR,6BAA6B,IAAI,CAACG,IAAI,EAAE,CAAC,GAAGF,aAAa;YAAC;SAAe;QACzE,OAAO,CAAC,SAAS,EAAEO,KAAK;IAC1B;AACF"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/fs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Tree } from '@nx/devkit';\nimport {\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from './declared-dependencies';\nimport { addDependenciesToPackageJson } from './dependencies';\nimport { type ITsDepVersion, withVersions } from './versions';\n\n/** Dependencies a caller must declare to use `FsCommands`. */\nexport const FS_DEPENDENCIES = [\n { name: 'ncp' },\n { name: 'rimraf' },\n { name: 'make-dir-cli' },\n] as const satisfies readonly { name: ITsDepVersion }[];\n\n/**\n * Platform agnostic commands for filesystem operations, adding the CLIs they\n * need to the root package.json.\n */\nexport class FsCommands<D extends DependencyDeclaration> {\n private tree: Tree;\n private declaration: D;\n\n constructor(\n tree: Tree,\n declaration: D & MustDeclare<typeof FS_DEPENDENCIES, D>,\n ) {\n this.tree = tree;\n this.declaration = declaration;\n }\n\n public cp(src: string, dst: string) {\n this.add('ncp');\n return `ncp ${src} ${dst}`;\n }\n\n public rm(dir: string) {\n this.add('rimraf');\n return `rimraf ${dir}`;\n }\n\n public mkdir(dir: string) {\n this.add('make-dir-cli');\n return `make-dir ${dir}`;\n }\n\n private add(dep: (typeof FS_DEPENDENCIES)[number]['name']) {\n addDependenciesToPackageJson(\n this.tree,\n {},\n withVersions(forDependencies<typeof FS_DEPENDENCIES>(this.declaration), [\n dep,\n ]),\n );\n }\n}\n"],"names":["forDependencies","addDependenciesToPackageJson","withVersions","FS_DEPENDENCIES","name","FsCommands","tree","declaration","cp","src","dst","add","rm","dir","mkdir","dep"],"mappings":"AAAA;;;CAGC,GAED,SAEEA,eAAe,QAEV,6BAA0B;AACjC,SAASC,4BAA4B,QAAQ,oBAAiB;AAC9D,SAA6BC,YAAY,QAAQ,gBAAa;AAE9D,4DAA4D,GAC5D,OAAO,MAAMC,kBAAkB;IAC7B;QAAEC,MAAM;IAAM;IACd;QAAEA,MAAM;IAAS;IACjB;QAAEA,MAAM;IAAe;CACxB,CAAuD;AAExD;;;CAGC,GACD,OAAO,MAAMC;IACHC,KAAW;IACXC,YAAe;IAEvB,YACED,IAAU,EACVC,WAAuD,CACvD;QACA,IAAI,CAACD,IAAI,GAAGA;QACZ,IAAI,CAACC,WAAW,GAAGA;IACrB;IAEOC,GAAGC,GAAW,EAAEC,GAAW,EAAE;QAClC,IAAI,CAACC,GAAG,CAAC;QACT,OAAO,CAAC,IAAI,EAAEF,IAAI,CAAC,EAAEC,KAAK;IAC5B;IAEOE,GAAGC,GAAW,EAAE;QACrB,IAAI,CAACF,GAAG,CAAC;QACT,OAAO,CAAC,OAAO,EAAEE,KAAK;IACxB;IAEOC,MAAMD,GAAW,EAAE;QACxB,IAAI,CAACF,GAAG,CAAC;QACT,OAAO,CAAC,SAAS,EAAEE,KAAK;IAC1B;IAEQF,IAAII,GAA6C,EAAE;QACzDd,6BACE,IAAI,CAACK,IAAI,EACT,CAAC,GACDJ,aAAaF,gBAAwC,IAAI,CAACO,WAAW,GAAG;YACtEQ;SACD;IAEL;AACF"}
@@ -4,7 +4,20 @@
4
4
  */
5
5
  import { OverwriteStrategy, type Tree } from '@nx/devkit';
6
6
  import { type Containers } from './containers';
7
+ import { type DependencyDeclaration, type MustDeclare } from './declared-dependencies';
7
8
  import type { Iac } from './iac';
9
+ /** Dependencies a caller must declare to apply the workspace init. */
10
+ export declare const INIT_DEPENDENCIES: readonly [{
11
+ readonly name: "nx";
12
+ }, {
13
+ readonly name: "@nx/js";
14
+ }, {
15
+ readonly name: "@nx/workspace";
16
+ }, {
17
+ readonly name: "typescript";
18
+ }, {
19
+ readonly name: "@biomejs/biome";
20
+ }];
8
21
  export declare const PNPM_BUILT_DEPENDENCIES: string[];
9
22
  /**
10
23
  * Options controlling how the workspace is initialised. These mirror the
@@ -56,4 +69,4 @@ export interface ApplyWorkspaceInitOptions {
56
69
  * existing projects — those are decisions for the user (see the "add to an
57
70
  * existing workspace" guide).
58
71
  */
59
- export declare const applyWorkspaceInit: (tree: Tree, { iac, containers, mcp, readmeOverwriteStrategy, overwriteScripts, catalogs, }: ApplyWorkspaceInitOptions) => Promise<void>;
72
+ export declare const applyWorkspaceInit: <const D extends DependencyDeclaration>(tree: Tree, { iac, containers, mcp, readmeOverwriteStrategy, overwriteScripts, catalogs, }: ApplyWorkspaceInitOptions, declaration: D & MustDeclare<typeof INIT_DEPENDENCIES, D>) => Promise<void>;
package/src/utils/init.js CHANGED
@@ -4,7 +4,6 @@
4
4
  */ import { generateFiles, joinPathFragments, OverwriteStrategy, readNxJson, updateJson, updateNxJson } from "@nx/devkit";
5
5
  import { initGenerator } from "@nx/js";
6
6
  import yaml from "js-yaml";
7
- import { readModulePackageJson } from "nx/src/utils/package-json";
8
7
  import GeneratorsJson from "../../generators.json" with {
9
8
  type: 'json'
10
9
  };
@@ -12,6 +11,7 @@ import { SYNC_GENERATOR_NAME as TS_SYNC_GENERATOR_NAME } from "../ts/sync/genera
12
11
  import { BASE_TSCONFIG_COMPILER_OPTIONS } from "./base-tsconfig.js";
13
12
  import { ensureAwsNxPluginConfig, updateAwsNxPluginConfig } from "./config/utils.js";
14
13
  import { inferContainers } from "./containers.js";
14
+ import { forDependencies } from "./declared-dependencies.js";
15
15
  import { addDependenciesToPackageJson, detectWorkspacePackageManager } from "./dependencies.js";
16
16
  import { getDefaultBiomeConfig } from "./format.js";
17
17
  import { configureMcpServers } from "./mcp.js";
@@ -24,6 +24,23 @@ const WORKSPACES = [
24
24
  'packages/*'
25
25
  ];
26
26
  const NX_TYPESCRIPT_SYNC_GENERATOR = '@nx/js:typescript-sync';
27
+ /** Dependencies a caller must declare to apply the workspace init. */ export const INIT_DEPENDENCIES = [
28
+ {
29
+ name: 'nx'
30
+ },
31
+ {
32
+ name: '@nx/js'
33
+ },
34
+ {
35
+ name: '@nx/workspace'
36
+ },
37
+ {
38
+ name: 'typescript'
39
+ },
40
+ {
41
+ name: '@biomejs/biome'
42
+ }
43
+ ];
27
44
  // Built dependencies whose install scripts the generated workspace trusts.
28
45
  // `onlyBuiltDependencies` is the pnpm 10 key (silently ignored by pnpm 11);
29
46
  // pnpm 11 reads `allowBuilds` instead. Any dep NOT in this allowlist will
@@ -157,7 +174,7 @@ export const PNPM_BUILT_DEPENDENCIES = [
157
174
  * compiler options, migrate a workspace's package manager, or restructure
158
175
  * existing projects — those are decisions for the user (see the "add to an
159
176
  * existing workspace" guide).
160
- */ export const applyWorkspaceInit = async (tree, { iac, containers, mcp, readmeOverwriteStrategy = OverwriteStrategy.KeepExisting, overwriteScripts = false, catalogs = true })=>{
177
+ */ export const applyWorkspaceInit = async (tree, { iac, containers, mcp, readmeOverwriteStrategy = OverwriteStrategy.KeepExisting, overwriteScripts = false, catalogs = true }, declaration)=>{
161
178
  const resolvedContainers = !containers || containers === 'infer' ? inferContainers() : containers;
162
179
  // The catalogs flag is written explicitly (even when true) so the workspace
163
180
  // records its dependency-management choice.
@@ -238,12 +255,13 @@ export const PNPM_BUILT_DEPENDENCIES = [
238
255
  // `@nx/js` must be a root dependency for the `@nx/js:typescript-sync`
239
256
  // generator registered in nx.json to resolve (npm doesn't hoist the
240
257
  // plugin's own copy reliably).
241
- const nxVersion = readModulePackageJson('@nx/js').packageJson.version;
242
258
  addDependenciesToPackageJson(tree, {}, {
243
- nx: nxVersion,
244
- '@nx/js': nxVersion,
245
- '@nx/workspace': nxVersion,
246
- ...withVersions([
259
+ ...withVersions(forDependencies(declaration), [
260
+ 'nx',
261
+ '@nx/js',
262
+ '@nx/workspace'
263
+ ]),
264
+ ...withVersions(forDependencies(declaration), [
247
265
  'typescript',
248
266
  '@biomejs/biome'
249
267
  ]),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/init.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n readNxJson,\n type Tree,\n updateJson,\n updateNxJson,\n} from '@nx/devkit';\nimport { initGenerator } from '@nx/js';\nimport { readFileSync } from 'fs';\nimport yaml from 'js-yaml';\nimport { readModulePackageJson } from 'nx/src/utils/package-json';\nimport GeneratorsJson from '../../generators.json' with { type: 'json' };\nimport { SYNC_GENERATOR_NAME as TS_SYNC_GENERATOR_NAME } from '../ts/sync/generator';\nimport { BASE_TSCONFIG_COMPILER_OPTIONS } from './base-tsconfig';\nimport {\n ensureAwsNxPluginConfig,\n updateAwsNxPluginConfig,\n} from './config/utils';\nimport { type Containers, inferContainers } from './containers';\nimport {\n addDependenciesToPackageJson,\n detectWorkspacePackageManager,\n} from './dependencies';\nimport { getDefaultBiomeConfig } from './format';\nimport type { Iac } from './iac';\nimport { configureMcpServers } from './mcp';\nimport { getNpmScope } from './npm-scope';\nimport {\n mergeTargetDefault,\n nxPluginMcpDependency,\n nxPluginSelfDependency,\n} from './nx';\nimport { getPackageManagerDisplayCommands } from './pkg-manager';\nimport { workspaceGlobs } from './project-package-json';\nimport { withVersions } from './versions';\n\nconst WORKSPACES = ['packages/*'];\nconst NX_TYPESCRIPT_SYNC_GENERATOR = '@nx/js:typescript-sync';\n\n// Built dependencies whose install scripts the generated workspace trusts.\n// `onlyBuiltDependencies` is the pnpm 10 key (silently ignored by pnpm 11);\n// pnpm 11 reads `allowBuilds` instead. Any dep NOT in this allowlist will\n// have its install scripts skipped with a warning — matching pnpm 10's\n// default behaviour. The user can opt-in later via `pnpm approve-builds`.\nexport const PNPM_BUILT_DEPENDENCIES = ['@swc/core', 'esbuild', 'nx', 'sharp'];\n\n/**\n * Options controlling how the workspace is initialised. These mirror the\n * preset schema so a workspace created via the preset and one initialised via\n * the `init` generator end up in the same shape.\n */\nexport interface ApplyWorkspaceInitOptions {\n /** The IaC provider to record in the plugin config. */\n readonly iac: Iac;\n /**\n * The container engine to record. `undefined`/`'infer'` picks docker when\n * installed, else finch.\n */\n readonly containers?: Containers | 'infer';\n /** Whether to configure MCP servers for coding agents. Defaults to true. */\n readonly mcp?: boolean;\n /**\n * How to treat the generated workspace README. The preset owns the README of\n * a greenfield workspace (`Overwrite`); the `init` generator must not clobber\n * an existing workspace's README (`KeepExisting`, the default).\n */\n readonly readmeOverwriteStrategy?: OverwriteStrategy;\n /**\n * Whether to overwrite root package.json scripts that already exist. The\n * preset owns a greenfield workspace's scripts (`true`); the `init`\n * generator must not clobber an existing workspace's scripts (`false`,\n * the default) — it only adds the convenience scripts that are absent.\n */\n readonly overwriteScripts?: boolean;\n /**\n * Whether generators use the package manager's dependency catalog. On pnpm\n * this also sets `catalogMode: strict` so `pnpm add` records new deps in the\n * catalog. Defaults to true.\n */\n readonly catalogs?: boolean;\n}\n\n/**\n * Add or repair the pnpm `allowBuilds` / `onlyBuiltDependencies` allowlist for\n * the workspace's `packages` globs, without clobbering any packages the user\n * has already declared.\n *\n * A workspace not created by the preset commonly has either no\n * `pnpm-workspace.yaml`, one missing the `packages` globs, or one carrying the\n * broken `set this to true or false` placeholder pnpm writes when it skips a\n * build script. This makes the file self-consistent so the first generator's\n * install doesn't fail with `ERR_PNPM_IGNORED_BUILDS`.\n */\nconst setUpPnpmWorkspace = (tree: Tree, catalogs: boolean) => {\n const existing = tree.exists('pnpm-workspace.yaml')\n ? ((yaml.load(tree.read('pnpm-workspace.yaml', 'utf-8') ?? '') as Record<\n string,\n unknown\n >) ?? {})\n : {};\n\n // Preserve any packages globs the user already has, ensuring ours are present.\n const packages = Array.from(\n new Set([...((existing.packages as string[]) ?? []), ...WORKSPACES]),\n );\n\n const allowBuilds = {\n ...(typeof existing.allowBuilds === 'object' && existing.allowBuilds\n ? (existing.allowBuilds as Record<string, unknown>)\n : {}),\n // Overwrite any non-boolean (e.g. the \"set this to true or false\"\n // placeholder) with an explicit true for the deps we trust.\n ...Object.fromEntries(PNPM_BUILT_DEPENDENCIES.map((dep) => [dep, true])),\n };\n\n // `strict` makes `pnpm add` record new deps in the catalog; it only gates\n // that flow, so pre-declared direct ranges (e.g. tslib) still install.\n // Preserve an explicit user choice.\n const catalogMode = catalogs\n ? (existing.catalogMode ?? 'strict')\n : existing.catalogMode;\n\n tree.write(\n 'pnpm-workspace.yaml',\n yaml.dump(\n {\n ...existing,\n packages,\n allowBuilds,\n onlyBuiltDependencies: PNPM_BUILT_DEPENDENCIES,\n ...(catalogMode ? { catalogMode } : {}),\n },\n { quotingType: \"'\" },\n ),\n );\n};\n\n/**\n * Configure the workspace's package manager for a monorepo layout.\n *\n * pnpm workspaces are declared in `pnpm-workspace.yaml`; every other package\n * manager reads the `workspaces` field of the root `package.json`.\n */\nconst setUpWorkspaces = (tree: Tree, catalogs: boolean) => {\n if (detectWorkspacePackageManager(tree) === 'pnpm') {\n setUpPnpmWorkspace(tree, catalogs);\n } else {\n updateJson(tree, 'package.json', (json) => {\n // The `workspaces` field may be the object form ({ \"packages\": [...] })\n // accepted by yarn and bun — extend the globs while preserving the form.\n const globs = Array.from(\n new Set([...workspaceGlobs(json.workspaces), ...WORKSPACES]),\n );\n return {\n ...json,\n workspaces:\n json.workspaces !== undefined && !Array.isArray(json.workspaces)\n ? { ...json.workspaces, packages: globs }\n : globs,\n };\n });\n }\n};\n\n/**\n * Ensure the workspace has a `tsconfig.base.json`.\n *\n * `@nx/js` `initGenerator` (with `addTsPlugin`) normally creates this, but it\n * short-circuits when the workspace already has a root `tsconfig.json` — in\n * which case no base file is written and the next project generator fails with\n * `Cannot find tsconfig.base.json`. So we create a compatible one when it's\n * absent. An existing base is left untouched: the user may have tuned it, and\n * rewriting shared compiler options can break other projects (see the\n * \"add to an existing workspace\" guide).\n */\nconst ensureBaseTsConfig = (tree: Tree) => {\n if (tree.exists('tsconfig.base.json')) {\n return;\n }\n tree.write(\n 'tsconfig.base.json',\n JSON.stringify(\n {\n compilerOptions: {\n ...BASE_TSCONFIG_COMPILER_OPTIONS,\n customConditions: [getNpmScope(tree)],\n },\n },\n null,\n 2,\n ),\n );\n};\n\n/**\n * Ensure the workspace has a root `tsconfig.json`.\n *\n * Nx's `@nx/js:typescript-sync` generator hard-fails with\n * `Missing root \"tsconfig.json\"` when it's absent. The plugin's TypeScript\n * projects reference each other via this file, so we guarantee a minimal one\n * exists (sync populates its `references`).\n */\nconst ensureRootTsConfig = (tree: Tree) => {\n if (tree.exists('tsconfig.json')) {\n return;\n }\n tree.write(\n 'tsconfig.json',\n JSON.stringify(\n {\n extends: './tsconfig.base.json',\n files: [],\n references: [],\n },\n null,\n 2,\n ),\n );\n};\n\n/**\n * Transform an Nx workspace into one ready to run `@aws/nx-plugin` generators.\n *\n * This is the deterministic core shared by the workspace preset and the `init`\n * generator. It is safe to re-run: every step is idempotent (config merges,\n * keyed nx.json / package.json entries, create-if-missing files), so running\n * it against an already-initialised workspace is a no-op.\n *\n * It preserves the workspace's module format: the root package.json `type`\n * field is owned by the preset (written from its `--module` option) and left\n * untouched here. It does NOT rewrite an existing `tsconfig.base.json`'s\n * compiler options, migrate a workspace's package manager, or restructure\n * existing projects — those are decisions for the user (see the \"add to an\n * existing workspace\" guide).\n */\nexport const applyWorkspaceInit = async (\n tree: Tree,\n {\n iac,\n containers,\n mcp,\n readmeOverwriteStrategy = OverwriteStrategy.KeepExisting,\n overwriteScripts = false,\n catalogs = true,\n }: ApplyWorkspaceInitOptions,\n) => {\n const resolvedContainers =\n !containers || containers === 'infer' ? inferContainers() : containers;\n\n // The catalogs flag is written explicitly (even when true) so the workspace\n // records its dependency-management choice.\n await ensureAwsNxPluginConfig(tree);\n await updateAwsNxPluginConfig(tree, {\n iac: { provider: iac },\n containers: { engine: resolvedContainers },\n packageManager: { catalogs },\n });\n\n // Set up the TypeScript plugin, base tsconfig, formatter etc. `@nx/js`\n // creates `tsconfig.base.json` when absent, but skips it when a root\n // `tsconfig.json` already exists — so we ensure both explicitly below.\n await initGenerator(tree, {\n formatter: 'none',\n addTsPlugin: true,\n });\n\n ensureBaseTsConfig(tree);\n ensureRootTsConfig(tree);\n\n setUpWorkspaces(tree, catalogs);\n\n const nxJson = readNxJson(tree);\n updateNxJson(tree, {\n ...nxJson,\n // Preserve an explicit analytics choice in an existing workspace.\n analytics: (nxJson as { analytics?: boolean }).analytics ?? false,\n targetDefaults: {\n ...nxJson.targetDefaults,\n compile: mergeTargetDefault(nxJson.targetDefaults?.compile, (base) => ({\n ...base,\n syncGenerators: [\n ...(base.syncGenerators ?? []).filter(\n (g) =>\n ![TS_SYNC_GENERATOR_NAME, NX_TYPESCRIPT_SYNC_GENERATOR].includes(\n g,\n ),\n ),\n NX_TYPESCRIPT_SYNC_GENERATOR,\n TS_SYNC_GENERATOR_NAME,\n ],\n })),\n },\n });\n\n const CONVENIENCE_SCRIPTS = {\n dev: 'nx run-many --target dev',\n build: 'nx run-many --target build',\n lint: 'nx run-many --target lint --configuration=fix',\n test: 'nx run-many --target test --all',\n // Trivy container image scanning is not part of `build` (its result\n // depends on the ever-changing vulnerability database); run it explicitly,\n // e.g. in CI.\n trivy: 'nx run-many --target trivy --all',\n 'build:skip-lint': 'nx run-many --target build --configuration=skip-lint',\n 'build:all': 'nx run-many --target build --all',\n 'affected:all': 'nx affected --target build',\n };\n updateJson(tree, 'package.json', (packageJson) => ({\n ...packageJson,\n // The root `type` field is owned by the preset (written explicitly from\n // its `--module` option). `init` preserves an existing workspace's field\n // as-is: an ESM workspace already carries `type: \"module\"` (that is how\n // the format is inferred), and introducing a `type` into a CommonJS\n // workspace that lacks one changes behaviour for frameworks that parse it\n // (e.g. Next.js starts treating the app's ESM source as CJS).\n scripts: overwriteScripts\n ? { ...packageJson.scripts, ...CONVENIENCE_SCRIPTS }\n : { ...CONVENIENCE_SCRIPTS, ...packageJson.scripts },\n }));\n\n // Pin the workspace's `nx` to the version the plugin's @nx/* packages are\n // built against. A mismatched workspace nx (even a patch apart) hoists a\n // second nested nx under @nx/js, and the two instances deadlock `nx sync`.\n // `@nx/js` must be a root dependency for the `@nx/js:typescript-sync`\n // generator registered in nx.json to resolve (npm doesn't hoist the\n // plugin's own copy reliably).\n const nxVersion = readModulePackageJson('@nx/js').packageJson.version;\n addDependenciesToPackageJson(\n tree,\n {},\n {\n nx: nxVersion,\n '@nx/js': nxVersion,\n '@nx/workspace': nxVersion,\n ...withVersions(['typescript', '@biomejs/biome']),\n // Declare the plugin the generators are running from, plus the MCP server\n // package the vended config runs, so both are pinned in the workspace's\n // lockfile and upgrading them upgrades what the agents use.\n ...nxPluginSelfDependency(tree),\n ...nxPluginMcpDependency(tree),\n },\n );\n\n // Write biome.json for formatting and linting\n if (!tree.exists('biome.json')) {\n tree.write(\n 'biome.json',\n JSON.stringify(getDefaultBiomeConfig(tree), null, 2),\n );\n }\n\n generateFiles(\n tree, // the virtual file system\n joinPathFragments(import.meta.dirname, '..', 'preset', 'files'),\n '.',\n {\n projectName: getNpmScope(tree),\n generators: Object.entries(GeneratorsJson.generators)\n .filter(([_, v]) => !v['hidden'])\n .map(([k, v]) => ({ name: k, description: v.description })),\n ...(() => {\n const cmds = getPackageManagerDisplayCommands();\n return {\n pkgMgrCmd: cmds.exec,\n buildCmd: `${cmds.run} build`,\n lintCmd: `${cmds.run} lint`,\n };\n })(),\n },\n {\n overwriteStrategy: readmeOverwriteStrategy,\n },\n );\n\n if (mcp !== false) {\n configureMcpServers(tree);\n }\n};\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","readNxJson","updateJson","updateNxJson","initGenerator","yaml","readModulePackageJson","GeneratorsJson","type","SYNC_GENERATOR_NAME","TS_SYNC_GENERATOR_NAME","BASE_TSCONFIG_COMPILER_OPTIONS","ensureAwsNxPluginConfig","updateAwsNxPluginConfig","inferContainers","addDependenciesToPackageJson","detectWorkspacePackageManager","getDefaultBiomeConfig","configureMcpServers","getNpmScope","mergeTargetDefault","nxPluginMcpDependency","nxPluginSelfDependency","getPackageManagerDisplayCommands","workspaceGlobs","withVersions","WORKSPACES","NX_TYPESCRIPT_SYNC_GENERATOR","PNPM_BUILT_DEPENDENCIES","setUpPnpmWorkspace","tree","catalogs","existing","exists","load","read","packages","Array","from","Set","allowBuilds","Object","fromEntries","map","dep","catalogMode","write","dump","onlyBuiltDependencies","quotingType","setUpWorkspaces","json","globs","workspaces","undefined","isArray","ensureBaseTsConfig","JSON","stringify","compilerOptions","customConditions","ensureRootTsConfig","extends","files","references","applyWorkspaceInit","iac","containers","mcp","readmeOverwriteStrategy","KeepExisting","overwriteScripts","resolvedContainers","provider","engine","packageManager","formatter","addTsPlugin","nxJson","analytics","targetDefaults","compile","base","syncGenerators","filter","g","includes","CONVENIENCE_SCRIPTS","dev","build","lint","test","trivy","packageJson","scripts","nxVersion","version","nx","dirname","projectName","generators","entries","_","v","k","name","description","cmds","pkgMgrCmd","exec","buildCmd","run","lintCmd","overwriteStrategy"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/init.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n readNxJson,\n type Tree,\n updateJson,\n updateNxJson,\n} from '@nx/devkit';\nimport { initGenerator } from '@nx/js';\nimport { readFileSync } from 'fs';\nimport yaml from 'js-yaml';\nimport GeneratorsJson from '../../generators.json' with { type: 'json' };\nimport { SYNC_GENERATOR_NAME as TS_SYNC_GENERATOR_NAME } from '../ts/sync/generator';\nimport { BASE_TSCONFIG_COMPILER_OPTIONS } from './base-tsconfig';\nimport {\n ensureAwsNxPluginConfig,\n updateAwsNxPluginConfig,\n} from './config/utils';\nimport { type Containers, inferContainers } from './containers';\nimport {\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from './declared-dependencies';\nimport {\n addDependenciesToPackageJson,\n detectWorkspacePackageManager,\n} from './dependencies';\nimport { getDefaultBiomeConfig } from './format';\nimport type { Iac } from './iac';\nimport { configureMcpServers } from './mcp';\nimport { getNpmScope } from './npm-scope';\nimport {\n mergeTargetDefault,\n nxPluginMcpDependency,\n nxPluginSelfDependency,\n} from './nx';\nimport { getPackageManagerDisplayCommands } from './pkg-manager';\nimport { workspaceGlobs } from './project-package-json';\nimport { type ITsDepVersion, withVersions } from './versions';\n\nconst WORKSPACES = ['packages/*'];\nconst NX_TYPESCRIPT_SYNC_GENERATOR = '@nx/js:typescript-sync';\n\n/** Dependencies a caller must declare to apply the workspace init. */\nexport const INIT_DEPENDENCIES = [\n { name: 'nx' },\n { name: '@nx/js' },\n { name: '@nx/workspace' },\n { name: 'typescript' },\n { name: '@biomejs/biome' },\n] as const satisfies readonly { name: ITsDepVersion }[];\n\n// Built dependencies whose install scripts the generated workspace trusts.\n// `onlyBuiltDependencies` is the pnpm 10 key (silently ignored by pnpm 11);\n// pnpm 11 reads `allowBuilds` instead. Any dep NOT in this allowlist will\n// have its install scripts skipped with a warning — matching pnpm 10's\n// default behaviour. The user can opt-in later via `pnpm approve-builds`.\nexport const PNPM_BUILT_DEPENDENCIES = ['@swc/core', 'esbuild', 'nx', 'sharp'];\n\n/**\n * Options controlling how the workspace is initialised. These mirror the\n * preset schema so a workspace created via the preset and one initialised via\n * the `init` generator end up in the same shape.\n */\nexport interface ApplyWorkspaceInitOptions {\n /** The IaC provider to record in the plugin config. */\n readonly iac: Iac;\n /**\n * The container engine to record. `undefined`/`'infer'` picks docker when\n * installed, else finch.\n */\n readonly containers?: Containers | 'infer';\n /** Whether to configure MCP servers for coding agents. Defaults to true. */\n readonly mcp?: boolean;\n /**\n * How to treat the generated workspace README. The preset owns the README of\n * a greenfield workspace (`Overwrite`); the `init` generator must not clobber\n * an existing workspace's README (`KeepExisting`, the default).\n */\n readonly readmeOverwriteStrategy?: OverwriteStrategy;\n /**\n * Whether to overwrite root package.json scripts that already exist. The\n * preset owns a greenfield workspace's scripts (`true`); the `init`\n * generator must not clobber an existing workspace's scripts (`false`,\n * the default) — it only adds the convenience scripts that are absent.\n */\n readonly overwriteScripts?: boolean;\n /**\n * Whether generators use the package manager's dependency catalog. On pnpm\n * this also sets `catalogMode: strict` so `pnpm add` records new deps in the\n * catalog. Defaults to true.\n */\n readonly catalogs?: boolean;\n}\n\n/**\n * Add or repair the pnpm `allowBuilds` / `onlyBuiltDependencies` allowlist for\n * the workspace's `packages` globs, without clobbering any packages the user\n * has already declared.\n *\n * A workspace not created by the preset commonly has either no\n * `pnpm-workspace.yaml`, one missing the `packages` globs, or one carrying the\n * broken `set this to true or false` placeholder pnpm writes when it skips a\n * build script. This makes the file self-consistent so the first generator's\n * install doesn't fail with `ERR_PNPM_IGNORED_BUILDS`.\n */\nconst setUpPnpmWorkspace = (tree: Tree, catalogs: boolean) => {\n const existing = tree.exists('pnpm-workspace.yaml')\n ? ((yaml.load(tree.read('pnpm-workspace.yaml', 'utf-8') ?? '') as Record<\n string,\n unknown\n >) ?? {})\n : {};\n\n // Preserve any packages globs the user already has, ensuring ours are present.\n const packages = Array.from(\n new Set([...((existing.packages as string[]) ?? []), ...WORKSPACES]),\n );\n\n const allowBuilds = {\n ...(typeof existing.allowBuilds === 'object' && existing.allowBuilds\n ? (existing.allowBuilds as Record<string, unknown>)\n : {}),\n // Overwrite any non-boolean (e.g. the \"set this to true or false\"\n // placeholder) with an explicit true for the deps we trust.\n ...Object.fromEntries(PNPM_BUILT_DEPENDENCIES.map((dep) => [dep, true])),\n };\n\n // `strict` makes `pnpm add` record new deps in the catalog; it only gates\n // that flow, so pre-declared direct ranges (e.g. tslib) still install.\n // Preserve an explicit user choice.\n const catalogMode = catalogs\n ? (existing.catalogMode ?? 'strict')\n : existing.catalogMode;\n\n tree.write(\n 'pnpm-workspace.yaml',\n yaml.dump(\n {\n ...existing,\n packages,\n allowBuilds,\n onlyBuiltDependencies: PNPM_BUILT_DEPENDENCIES,\n ...(catalogMode ? { catalogMode } : {}),\n },\n { quotingType: \"'\" },\n ),\n );\n};\n\n/**\n * Configure the workspace's package manager for a monorepo layout.\n *\n * pnpm workspaces are declared in `pnpm-workspace.yaml`; every other package\n * manager reads the `workspaces` field of the root `package.json`.\n */\nconst setUpWorkspaces = (tree: Tree, catalogs: boolean) => {\n if (detectWorkspacePackageManager(tree) === 'pnpm') {\n setUpPnpmWorkspace(tree, catalogs);\n } else {\n updateJson(tree, 'package.json', (json) => {\n // The `workspaces` field may be the object form ({ \"packages\": [...] })\n // accepted by yarn and bun — extend the globs while preserving the form.\n const globs = Array.from(\n new Set([...workspaceGlobs(json.workspaces), ...WORKSPACES]),\n );\n return {\n ...json,\n workspaces:\n json.workspaces !== undefined && !Array.isArray(json.workspaces)\n ? { ...json.workspaces, packages: globs }\n : globs,\n };\n });\n }\n};\n\n/**\n * Ensure the workspace has a `tsconfig.base.json`.\n *\n * `@nx/js` `initGenerator` (with `addTsPlugin`) normally creates this, but it\n * short-circuits when the workspace already has a root `tsconfig.json` — in\n * which case no base file is written and the next project generator fails with\n * `Cannot find tsconfig.base.json`. So we create a compatible one when it's\n * absent. An existing base is left untouched: the user may have tuned it, and\n * rewriting shared compiler options can break other projects (see the\n * \"add to an existing workspace\" guide).\n */\nconst ensureBaseTsConfig = (tree: Tree) => {\n if (tree.exists('tsconfig.base.json')) {\n return;\n }\n tree.write(\n 'tsconfig.base.json',\n JSON.stringify(\n {\n compilerOptions: {\n ...BASE_TSCONFIG_COMPILER_OPTIONS,\n customConditions: [getNpmScope(tree)],\n },\n },\n null,\n 2,\n ),\n );\n};\n\n/**\n * Ensure the workspace has a root `tsconfig.json`.\n *\n * Nx's `@nx/js:typescript-sync` generator hard-fails with\n * `Missing root \"tsconfig.json\"` when it's absent. The plugin's TypeScript\n * projects reference each other via this file, so we guarantee a minimal one\n * exists (sync populates its `references`).\n */\nconst ensureRootTsConfig = (tree: Tree) => {\n if (tree.exists('tsconfig.json')) {\n return;\n }\n tree.write(\n 'tsconfig.json',\n JSON.stringify(\n {\n extends: './tsconfig.base.json',\n files: [],\n references: [],\n },\n null,\n 2,\n ),\n );\n};\n\n/**\n * Transform an Nx workspace into one ready to run `@aws/nx-plugin` generators.\n *\n * This is the deterministic core shared by the workspace preset and the `init`\n * generator. It is safe to re-run: every step is idempotent (config merges,\n * keyed nx.json / package.json entries, create-if-missing files), so running\n * it against an already-initialised workspace is a no-op.\n *\n * It preserves the workspace's module format: the root package.json `type`\n * field is owned by the preset (written from its `--module` option) and left\n * untouched here. It does NOT rewrite an existing `tsconfig.base.json`'s\n * compiler options, migrate a workspace's package manager, or restructure\n * existing projects — those are decisions for the user (see the \"add to an\n * existing workspace\" guide).\n */\nexport const applyWorkspaceInit = async <const D extends DependencyDeclaration>(\n tree: Tree,\n {\n iac,\n containers,\n mcp,\n readmeOverwriteStrategy = OverwriteStrategy.KeepExisting,\n overwriteScripts = false,\n catalogs = true,\n }: ApplyWorkspaceInitOptions,\n declaration: D & MustDeclare<typeof INIT_DEPENDENCIES, D>,\n) => {\n const resolvedContainers =\n !containers || containers === 'infer' ? inferContainers() : containers;\n\n // The catalogs flag is written explicitly (even when true) so the workspace\n // records its dependency-management choice.\n await ensureAwsNxPluginConfig(tree);\n await updateAwsNxPluginConfig(tree, {\n iac: { provider: iac },\n containers: { engine: resolvedContainers },\n packageManager: { catalogs },\n });\n\n // Set up the TypeScript plugin, base tsconfig, formatter etc. `@nx/js`\n // creates `tsconfig.base.json` when absent, but skips it when a root\n // `tsconfig.json` already exists — so we ensure both explicitly below.\n await initGenerator(tree, {\n formatter: 'none',\n addTsPlugin: true,\n });\n\n ensureBaseTsConfig(tree);\n ensureRootTsConfig(tree);\n\n setUpWorkspaces(tree, catalogs);\n\n const nxJson = readNxJson(tree);\n updateNxJson(tree, {\n ...nxJson,\n // Preserve an explicit analytics choice in an existing workspace.\n analytics: (nxJson as { analytics?: boolean }).analytics ?? false,\n targetDefaults: {\n ...nxJson.targetDefaults,\n compile: mergeTargetDefault(nxJson.targetDefaults?.compile, (base) => ({\n ...base,\n syncGenerators: [\n ...(base.syncGenerators ?? []).filter(\n (g) =>\n ![TS_SYNC_GENERATOR_NAME, NX_TYPESCRIPT_SYNC_GENERATOR].includes(\n g,\n ),\n ),\n NX_TYPESCRIPT_SYNC_GENERATOR,\n TS_SYNC_GENERATOR_NAME,\n ],\n })),\n },\n });\n\n const CONVENIENCE_SCRIPTS = {\n dev: 'nx run-many --target dev',\n build: 'nx run-many --target build',\n lint: 'nx run-many --target lint --configuration=fix',\n test: 'nx run-many --target test --all',\n // Trivy container image scanning is not part of `build` (its result\n // depends on the ever-changing vulnerability database); run it explicitly,\n // e.g. in CI.\n trivy: 'nx run-many --target trivy --all',\n 'build:skip-lint': 'nx run-many --target build --configuration=skip-lint',\n 'build:all': 'nx run-many --target build --all',\n 'affected:all': 'nx affected --target build',\n };\n updateJson(tree, 'package.json', (packageJson) => ({\n ...packageJson,\n // The root `type` field is owned by the preset (written explicitly from\n // its `--module` option). `init` preserves an existing workspace's field\n // as-is: an ESM workspace already carries `type: \"module\"` (that is how\n // the format is inferred), and introducing a `type` into a CommonJS\n // workspace that lacks one changes behaviour for frameworks that parse it\n // (e.g. Next.js starts treating the app's ESM source as CJS).\n scripts: overwriteScripts\n ? { ...packageJson.scripts, ...CONVENIENCE_SCRIPTS }\n : { ...CONVENIENCE_SCRIPTS, ...packageJson.scripts },\n }));\n\n // Pin the workspace's `nx` to the version the plugin's @nx/* packages are\n // built against. A mismatched workspace nx (even a patch apart) hoists a\n // second nested nx under @nx/js, and the two instances deadlock `nx sync`.\n // `@nx/js` must be a root dependency for the `@nx/js:typescript-sync`\n // generator registered in nx.json to resolve (npm doesn't hoist the\n // plugin's own copy reliably).\n addDependenciesToPackageJson(\n tree,\n {},\n {\n ...withVersions(forDependencies<typeof INIT_DEPENDENCIES>(declaration), [\n 'nx',\n '@nx/js',\n '@nx/workspace',\n ]),\n ...withVersions(forDependencies<typeof INIT_DEPENDENCIES>(declaration), [\n 'typescript',\n '@biomejs/biome',\n ]),\n // Declare the plugin the generators are running from, plus the MCP server\n // package the vended config runs, so both are pinned in the workspace's\n // lockfile and upgrading them upgrades what the agents use.\n ...nxPluginSelfDependency(tree),\n ...nxPluginMcpDependency(tree),\n },\n );\n\n // Write biome.json for formatting and linting\n if (!tree.exists('biome.json')) {\n tree.write(\n 'biome.json',\n JSON.stringify(getDefaultBiomeConfig(tree), null, 2),\n );\n }\n\n generateFiles(\n tree, // the virtual file system\n joinPathFragments(import.meta.dirname, '..', 'preset', 'files'),\n '.',\n {\n projectName: getNpmScope(tree),\n generators: Object.entries(GeneratorsJson.generators)\n .filter(([_, v]) => !v['hidden'])\n .map(([k, v]) => ({ name: k, description: v.description })),\n ...(() => {\n const cmds = getPackageManagerDisplayCommands();\n return {\n pkgMgrCmd: cmds.exec,\n buildCmd: `${cmds.run} build`,\n lintCmd: `${cmds.run} lint`,\n };\n })(),\n },\n {\n overwriteStrategy: readmeOverwriteStrategy,\n },\n );\n\n if (mcp !== false) {\n configureMcpServers(tree);\n }\n};\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","readNxJson","updateJson","updateNxJson","initGenerator","yaml","GeneratorsJson","type","SYNC_GENERATOR_NAME","TS_SYNC_GENERATOR_NAME","BASE_TSCONFIG_COMPILER_OPTIONS","ensureAwsNxPluginConfig","updateAwsNxPluginConfig","inferContainers","forDependencies","addDependenciesToPackageJson","detectWorkspacePackageManager","getDefaultBiomeConfig","configureMcpServers","getNpmScope","mergeTargetDefault","nxPluginMcpDependency","nxPluginSelfDependency","getPackageManagerDisplayCommands","workspaceGlobs","withVersions","WORKSPACES","NX_TYPESCRIPT_SYNC_GENERATOR","INIT_DEPENDENCIES","name","PNPM_BUILT_DEPENDENCIES","setUpPnpmWorkspace","tree","catalogs","existing","exists","load","read","packages","Array","from","Set","allowBuilds","Object","fromEntries","map","dep","catalogMode","write","dump","onlyBuiltDependencies","quotingType","setUpWorkspaces","json","globs","workspaces","undefined","isArray","ensureBaseTsConfig","JSON","stringify","compilerOptions","customConditions","ensureRootTsConfig","extends","files","references","applyWorkspaceInit","iac","containers","mcp","readmeOverwriteStrategy","KeepExisting","overwriteScripts","declaration","resolvedContainers","provider","engine","packageManager","formatter","addTsPlugin","nxJson","analytics","targetDefaults","compile","base","syncGenerators","filter","g","includes","CONVENIENCE_SCRIPTS","dev","build","lint","test","trivy","packageJson","scripts","dirname","projectName","generators","entries","_","v","k","description","cmds","pkgMgrCmd","exec","buildCmd","run","lintCmd","overwriteStrategy"],"mappings":"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"}
@@ -18,13 +18,27 @@ import { compare } from 'semver';
18
18
  * - The weekly `update-versions` PR backfills the version of the release that
19
19
  * shipped each migration, moving and re-keying it accordingly
20
20
  * (`scripts/backfill-migration-versions.ts`), so source converges on the
21
- * versions of everything already released.
21
+ * versions of everything already released. `packageJsonUpdates` entries are
22
+ * dated in place there too, since their keys never change.
22
23
  *
23
24
  * A version already in source always wins, so backfilled entries are stable.
25
+ *
26
+ * An entry marked `everyMigration: true` is never backfilled or pinned, and is
27
+ * re-stamped with each pending version, so it runs on every upgrade.
24
28
  */
25
29
  export interface MigrationsJson {
26
30
  generators?: Record<string, {
27
31
  version?: string;
32
+ everyMigration?: boolean;
33
+ } & Record<string, unknown>>;
34
+ /**
35
+ * Declarative dependency bumps `nx migrate` applies to the root manifest.
36
+ * Keyed by what the bump targets rather than the release that ships it, so an
37
+ * entry is unique from the moment it is written and one release's bump can sit
38
+ * beside the next; nx itself gates on the entry's `version`.
39
+ */
40
+ packageJsonUpdates?: Record<string, {
41
+ version: string;
28
42
  } & Record<string, unknown>>;
29
43
  }
30
44
  /** Ascending semver comparator for `Array.prototype.sort`. */
@@ -32,15 +46,19 @@ export declare const compareVersions: typeof compare;
32
46
  /** Whether a string is an exact semver version. */
33
47
  export declare const isValidVersion: (version: string) => boolean;
34
48
  /**
35
- * Map of migration key -> version of the earliest release that registers it,
36
- * resolved only for the entries still missing a `version` (one already recorded
37
- * in source wins, so its history doesn't need reading). A migration that hasn't
38
- * been released is absent.
49
+ * Map of entry key -> version of the earliest release that registers it, across
50
+ * both `generators` and `packageJsonUpdates`. Resolved only for the entries still
51
+ * missing a version (one already recorded in source wins, so its history doesn't
52
+ * need reading). An entry that hasn't been released is absent.
39
53
  *
40
54
  * Walks releases newest first and stops as soon as every entry is resolved: an
41
55
  * entry that has disappeared from a release's `migrations.json` was first
42
56
  * registered by the release after it, which is the one that shipped it.
43
57
  *
58
+ * Both sections resolve the same way and share the walk, so the release doesn't
59
+ * read tag history twice. Keys can't collide: a migration is keyed by its own
60
+ * name, an nx bump by the nx version it moves to.
61
+ *
44
62
  * @param migrations parsed source migrations.json
45
63
  * @param versions released versions in descending semver order
46
64
  * @param readReleasedMigrations reads the `migrations.json` published by a given
@@ -49,7 +67,8 @@ export declare const isValidVersion: (version: string) => boolean;
49
67
  export declare const readShippedMigrationVersions: (migrations: MigrationsJson, versions: string[], readReleasedMigrations: (version: string) => MigrationsJson | undefined) => Record<string, string>;
50
68
  /**
51
69
  * Return a copy of the migrations collection with a `version` stamped onto
52
- * every generator entry, preserving any already present.
70
+ * every generator entry, preserving any already present, and the pending version
71
+ * recorded on any `packageJsonUpdates` entry still holding `latest`.
53
72
  *
54
73
  * @param migrations parsed migrations.json to stamp
55
74
  * @param shippedVersions migration key -> version of the earliest release
@@ -5,27 +5,40 @@
5
5
  /** Ascending semver comparator for `Array.prototype.sort`. */ export const compareVersions = compare;
6
6
  /** Whether a string is an exact semver version. */ export const isValidVersion = (version)=>valid(version) !== null;
7
7
  /**
8
- * Map of migration key -> version of the earliest release that registers it,
9
- * resolved only for the entries still missing a `version` (one already recorded
10
- * in source wins, so its history doesn't need reading). A migration that hasn't
11
- * been released is absent.
8
+ * Map of entry key -> version of the earliest release that registers it, across
9
+ * both `generators` and `packageJsonUpdates`. Resolved only for the entries still
10
+ * missing a version (one already recorded in source wins, so its history doesn't
11
+ * need reading). An entry that hasn't been released is absent.
12
12
  *
13
13
  * Walks releases newest first and stops as soon as every entry is resolved: an
14
14
  * entry that has disappeared from a release's `migrations.json` was first
15
15
  * registered by the release after it, which is the one that shipped it.
16
16
  *
17
+ * Both sections resolve the same way and share the walk, so the release doesn't
18
+ * read tag history twice. Keys can't collide: a migration is keyed by its own
19
+ * name, an nx bump by the nx version it moves to.
20
+ *
17
21
  * @param migrations parsed source migrations.json
18
22
  * @param versions released versions in descending semver order
19
23
  * @param readReleasedMigrations reads the `migrations.json` published by a given
20
24
  * version, or undefined if it predates the manifest
21
25
  */ export const readShippedMigrationVersions = (migrations, versions, readReleasedMigrations)=>{
22
26
  const shippedVersions = {};
23
- let unresolved = Object.entries(migrations.generators ?? {}).filter(([, entry])=>!entry.version).map(([key])=>key);
27
+ // A `packageJsonUpdates` entry records `latest` rather than omitting its
28
+ // version, since nx requires the field.
29
+ let unresolved = [
30
+ ...Object.entries(migrations.generators ?? {}).filter(([, entry])=>!entry.version).map(([key])=>key),
31
+ ...Object.entries(migrations.packageJsonUpdates ?? {}).filter(([, entry])=>entry.version === LATEST_MIGRATIONS_DIR).map(([key])=>key)
32
+ ];
24
33
  for (const version of versions){
25
34
  if (unresolved.length === 0) {
26
35
  break;
27
36
  }
28
- const registered = new Set(Object.keys(readReleasedMigrations(version)?.generators ?? {}));
37
+ const released = readReleasedMigrations(version);
38
+ const registered = new Set([
39
+ ...Object.keys(released?.generators ?? {}),
40
+ ...Object.keys(released?.packageJsonUpdates ?? {})
41
+ ]);
29
42
  // Entries gone at this release keep the version recorded from the release
30
43
  // after it (if any) and stop being looked up.
31
44
  unresolved = unresolved.filter((key)=>registered.has(key));
@@ -37,7 +50,8 @@
37
50
  };
38
51
  /**
39
52
  * Return a copy of the migrations collection with a `version` stamped onto
40
- * every generator entry, preserving any already present.
53
+ * every generator entry, preserving any already present, and the pending version
54
+ * recorded on any `packageJsonUpdates` entry still holding `latest`.
41
55
  *
42
56
  * @param migrations parsed migrations.json to stamp
43
57
  * @param shippedVersions migration key -> version of the earliest release
@@ -46,14 +60,30 @@
46
60
  * unshipped migrations so their version is one that really shipped
47
61
  */ export const stampMigrationVersions = (migrations, shippedVersions, pendingVersion)=>({
48
62
  ...migrations,
49
- generators: Object.fromEntries(Object.entries(migrations.generators ?? {}).map(([name, entry])=>[
63
+ generators: Object.fromEntries(// `nx migrate` sorts the run ascending by version and preserves the
64
+ // manifest's order among equal versions, so emitting the every-migration
65
+ // entries last is what makes them run after the release's own migrations.
66
+ Object.entries(migrations.generators ?? {}).sort(([, a], [, b])=>Number(a.everyMigration ?? false) - Number(b.everyMigration ?? false)).map(([name, entry])=>{
67
+ // Source-only marker, stripped from what nx reads.
68
+ const { everyMigration, version: sourceVersion, ...published } = entry;
69
+ // Overrides any source version so it stays ahead of what is installed.
70
+ const version = everyMigration ? pendingVersion : sourceVersion ?? shippedVersions[name] ?? pendingVersion;
71
+ return [
50
72
  name,
51
73
  {
52
- version: shippedVersions[name] ?? pendingVersion,
53
- ...entry
74
+ version,
75
+ ...published
54
76
  }
55
- ]))
77
+ ];
78
+ })),
79
+ ...migrations.packageJsonUpdates && {
80
+ packageJsonUpdates: stampPackageJsonUpdates(migrations.packageJsonUpdates, pendingVersion)
81
+ }
56
82
  });
83
+ /**
84
+ * Version any `packageJsonUpdates` entry still holding `latest` with the release
85
+ * about to publish it, so the nx bump ships under a version `nx migrate` gates on.
86
+ */ const stampPackageJsonUpdates = (packageJsonUpdates, pendingVersion)=>resolvePackageJsonUpdateVersions(packageJsonUpdates, ()=>pendingVersion);
57
87
  /** Directory a newly scaffolded migration lands in, before a release claims it. */ export const LATEST_MIGRATIONS_DIR = 'latest';
58
88
  /** Directory holding the migrations shipped by a given release. */ export const versionMigrationsDir = (version)=>`v${version}`;
59
89
  /**
@@ -78,9 +108,13 @@ const LATEST_KEY_PREFIX = `${LATEST_MIGRATIONS_DIR}-`;
78
108
  const generators = {};
79
109
  const backfilled = [];
80
110
  const moves = [];
111
+ // Reported alongside the migrations so the update's PR says an nx bump was
112
+ // dated, and so the caller knows there is something to commit.
113
+ const backfilledUpdates = Object.entries(migrations.packageJsonUpdates ?? {}).filter(([key, entry])=>entry.version === LATEST_MIGRATIONS_DIR && shippedVersions[key]).map(([key])=>key);
81
114
  for (const [key, entry] of Object.entries(migrations.generators ?? {})){
82
115
  const version = shippedVersions[key];
83
- if (entry.version || !version) {
116
+ // Pinning an every-migration entry would stop it running on later upgrades.
117
+ if (entry.version || !version || entry.everyMigration) {
84
118
  generators[key] = entry;
85
119
  continue;
86
120
  }
@@ -118,11 +152,35 @@ const LATEST_KEY_PREFIX = `${LATEST_MIGRATIONS_DIR}-`;
118
152
  return {
119
153
  migrations: {
120
154
  ...migrations,
121
- generators
155
+ generators,
156
+ ...migrations.packageJsonUpdates && {
157
+ packageJsonUpdates: resolvePackageJsonUpdateVersions(migrations.packageJsonUpdates, (key)=>shippedVersions[key])
158
+ }
122
159
  },
123
- backfilled,
160
+ backfilled: [
161
+ ...backfilled,
162
+ ...backfilledUpdates
163
+ ],
124
164
  moves
125
165
  };
126
166
  };
167
+ /**
168
+ * Record the version each `packageJsonUpdates` entry ships under, for those still
169
+ * holding `latest`.
170
+ *
171
+ * The key already identifies the entry — an nx bump is named for the nx version
172
+ * it moves to — so only the `version` field changes. Nothing is re-keyed, which
173
+ * is what lets one release's bump sit alongside the next without either being
174
+ * overwritten before it ships.
175
+ */ const resolvePackageJsonUpdateVersions = (packageJsonUpdates, resolve)=>Object.fromEntries(Object.entries(packageJsonUpdates).map(([key, entry])=>{
176
+ const version = entry.version === LATEST_MIGRATIONS_DIR ? resolve(key) : undefined;
177
+ return [
178
+ key,
179
+ version ? {
180
+ ...entry,
181
+ version
182
+ } : entry
183
+ ];
184
+ }));
127
185
 
128
186
  //# sourceMappingURL=migration-versions.js.map