@aws/nx-plugin 1.0.0-rc.53 → 1.0.0-rc.55

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 (271) 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/order-access-log-delivery-after-bucket-policy/migration.d.ts +6 -0
  21. package/src/migrations/latest/order-access-log-delivery-after-bucket-policy/migration.js +94 -0
  22. package/src/migrations/latest/order-access-log-delivery-after-bucket-policy/migration.js.map +1 -0
  23. package/src/preset/generator.d.ts +13 -0
  24. package/src/preset/generator.js +12 -3
  25. package/src/preset/generator.js.map +1 -1
  26. package/src/py/agent/a2a-connection/generator.d.ts +24 -0
  27. package/src/py/agent/a2a-connection/generator.js +49 -20
  28. package/src/py/agent/a2a-connection/generator.js.map +1 -1
  29. package/src/py/agent/gateway-connection/generator.d.ts +23 -0
  30. package/src/py/agent/gateway-connection/generator.js +45 -11
  31. package/src/py/agent/gateway-connection/generator.js.map +1 -1
  32. package/src/py/agent/generator.d.ts +146 -1
  33. package/src/py/agent/generator.js +173 -76
  34. package/src/py/agent/generator.js.map +1 -1
  35. package/src/py/agent/mcp-connection/generator.d.ts +23 -0
  36. package/src/py/agent/mcp-connection/generator.js +45 -11
  37. package/src/py/agent/mcp-connection/generator.js.map +1 -1
  38. package/src/py/agent/react-connection/generator.d.ts +146 -0
  39. package/src/py/agent/react-connection/generator.js +27 -4
  40. package/src/py/agent/react-connection/generator.js.map +1 -1
  41. package/src/py/dynamodb/agent-connection/__snapshots__/generator.spec.ts.snap +18 -0
  42. package/src/py/dynamodb/agent-connection/generator.js +7 -1
  43. package/src/py/dynamodb/agent-connection/generator.js.map +1 -1
  44. package/src/py/dynamodb/fast-api-connection/__snapshots__/generator.spec.ts.snap +9 -0
  45. package/src/py/dynamodb/fast-api-connection/generator.js +3 -1
  46. package/src/py/dynamodb/fast-api-connection/generator.js.map +1 -1
  47. package/src/py/dynamodb/generator.d.ts +29 -0
  48. package/src/py/dynamodb/generator.js +32 -12
  49. package/src/py/dynamodb/generator.js.map +1 -1
  50. package/src/py/dynamodb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +18 -0
  51. package/src/py/dynamodb/mcp-server-connection/generator.js +7 -1
  52. package/src/py/dynamodb/mcp-server-connection/generator.js.map +1 -1
  53. package/src/py/fast-api/generator.d.ts +63 -0
  54. package/src/py/fast-api/generator.js +58 -23
  55. package/src/py/fast-api/generator.js.map +1 -1
  56. package/src/py/fast-api/react/generator.d.ts +16 -1
  57. package/src/py/fast-api/react/generator.js +15 -3
  58. package/src/py/fast-api/react/generator.js.map +1 -1
  59. package/src/py/lambda-function/generator.d.ts +21 -0
  60. package/src/py/lambda-function/generator.js +29 -10
  61. package/src/py/lambda-function/generator.js.map +1 -1
  62. package/src/py/mcp-server/generator.d.ts +60 -0
  63. package/src/py/mcp-server/generator.js +62 -25
  64. package/src/py/mcp-server/generator.js.map +1 -1
  65. package/src/py/project/generator.d.ts +13 -0
  66. package/src/py/project/generator.js +29 -10
  67. package/src/py/project/generator.js.map +1 -1
  68. package/src/py/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +19 -0
  69. package/src/py/rdb/agent-connection/generator.js +7 -1
  70. package/src/py/rdb/agent-connection/generator.js.map +1 -1
  71. package/src/py/rdb/fast-api-connection/__snapshots__/generator.spec.ts.snap +7 -0
  72. package/src/py/rdb/fast-api-connection/generator.js +3 -1
  73. package/src/py/rdb/fast-api-connection/generator.js.map +1 -1
  74. package/src/py/rdb/generator.d.ts +89 -0
  75. package/src/py/rdb/generator.js +88 -40
  76. package/src/py/rdb/generator.js.map +1 -1
  77. package/src/py/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +18 -0
  78. package/src/py/rdb/mcp-server-connection/generator.js +7 -1
  79. package/src/py/rdb/mcp-server-connection/generator.js.map +1 -1
  80. package/src/smithy/project/generator.d.ts +7 -0
  81. package/src/smithy/project/generator.js +8 -2
  82. package/src/smithy/project/generator.js.map +1 -1
  83. package/src/smithy/react-connection/generator.d.ts +15 -0
  84. package/src/smithy/react-connection/generator.js +17 -3
  85. package/src/smithy/react-connection/generator.js.map +1 -1
  86. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +1 -0
  87. package/src/smithy/ts/api/generator.d.ts +79 -0
  88. package/src/smithy/ts/api/generator.js +77 -33
  89. package/src/smithy/ts/api/generator.js.map +1 -1
  90. package/src/terraform/project/generator.d.ts +50 -0
  91. package/src/terraform/project/generator.js +63 -17
  92. package/src/terraform/project/generator.js.map +1 -1
  93. package/src/trpc/backend/generator.d.ts +84 -0
  94. package/src/trpc/backend/generator.js +98 -38
  95. package/src/trpc/backend/generator.js.map +1 -1
  96. package/src/trpc/react/generator.d.ts +37 -0
  97. package/src/trpc/react/generator.js +63 -26
  98. package/src/trpc/react/generator.js.map +1 -1
  99. package/src/ts/agent/a2a-connection/generator.d.ts +46 -0
  100. package/src/ts/agent/a2a-connection/generator.js +53 -16
  101. package/src/ts/agent/a2a-connection/generator.js.map +1 -1
  102. package/src/ts/agent/gateway-connection/generator.d.ts +37 -0
  103. package/src/ts/agent/gateway-connection/generator.js +41 -14
  104. package/src/ts/agent/gateway-connection/generator.js.map +1 -1
  105. package/src/ts/agent/generator.d.ts +162 -0
  106. package/src/ts/agent/generator.js +166 -75
  107. package/src/ts/agent/generator.js.map +1 -1
  108. package/src/ts/agent/mcp-connection/generator.d.ts +37 -0
  109. package/src/ts/agent/mcp-connection/generator.js +41 -14
  110. package/src/ts/agent/mcp-connection/generator.js.map +1 -1
  111. package/src/ts/agent/react-connection/generator.d.ts +186 -0
  112. package/src/ts/agent/react-connection/generator.js +70 -21
  113. package/src/ts/agent/react-connection/generator.js.map +1 -1
  114. package/src/ts/astro-docs/generator.d.ts +38 -0
  115. package/src/ts/astro-docs/generator.js +58 -19
  116. package/src/ts/astro-docs/generator.js.map +1 -1
  117. package/src/ts/dcr-proxy/generator.d.ts +24 -0
  118. package/src/ts/dcr-proxy/generator.js +31 -14
  119. package/src/ts/dcr-proxy/generator.js.map +1 -1
  120. package/src/ts/dynamodb/agent-connection/__snapshots__/generator.spec.ts.snap +18 -0
  121. package/src/ts/dynamodb/agent-connection/generator.js +7 -1
  122. package/src/ts/dynamodb/agent-connection/generator.js.map +1 -1
  123. package/src/ts/dynamodb/generator.d.ts +41 -0
  124. package/src/ts/dynamodb/generator.js +47 -20
  125. package/src/ts/dynamodb/generator.js.map +1 -1
  126. package/src/ts/dynamodb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +18 -0
  127. package/src/ts/dynamodb/mcp-server-connection/generator.js +7 -1
  128. package/src/ts/dynamodb/mcp-server-connection/generator.js.map +1 -1
  129. package/src/ts/dynamodb/smithy-connection/__snapshots__/generator.spec.ts.snap +9 -0
  130. package/src/ts/dynamodb/smithy-connection/generator.js +3 -1
  131. package/src/ts/dynamodb/smithy-connection/generator.js.map +1 -1
  132. package/src/ts/dynamodb/trpc-connection/__snapshots__/generator.spec.ts.snap +9 -0
  133. package/src/ts/dynamodb/trpc-connection/generator.js +3 -1
  134. package/src/ts/dynamodb/trpc-connection/generator.js.map +1 -1
  135. package/src/ts/lambda-function/generator.d.ts +38 -0
  136. package/src/ts/lambda-function/generator.js +49 -20
  137. package/src/ts/lambda-function/generator.js.map +1 -1
  138. package/src/ts/lib/generator.d.ts +7 -0
  139. package/src/ts/lib/generator.js +8 -1
  140. package/src/ts/lib/generator.js.map +1 -1
  141. package/src/ts/lib/ts-project-utils.d.ts +3 -1
  142. package/src/ts/lib/ts-project-utils.js +3 -2
  143. package/src/ts/lib/ts-project-utils.js.map +1 -1
  144. package/src/ts/lib/vitest.d.ts +10 -1
  145. package/src/ts/lib/vitest.js +14 -2
  146. package/src/ts/lib/vitest.js.map +1 -1
  147. package/src/ts/mcp-server/generator.d.ts +71 -0
  148. package/src/ts/mcp-server/generator.js +73 -36
  149. package/src/ts/mcp-server/generator.js.map +1 -1
  150. package/src/ts/nx-generator/generator.d.ts +3 -0
  151. package/src/ts/nx-generator/generator.js +8 -2
  152. package/src/ts/nx-generator/generator.js.map +1 -1
  153. package/src/ts/nx-migration/generator.d.ts +3 -0
  154. package/src/ts/nx-migration/generator.js +8 -2
  155. package/src/ts/nx-migration/generator.js.map +1 -1
  156. package/src/ts/nx-plugin/generator.d.ts +3 -0
  157. package/src/ts/nx-plugin/generator.js +8 -2
  158. package/src/ts/nx-plugin/generator.js.map +1 -1
  159. package/src/ts/nx-plugin/utils.d.ts +7 -2
  160. package/src/ts/nx-plugin/utils.js +10 -4
  161. package/src/ts/nx-plugin/utils.js.map +1 -1
  162. package/src/ts/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +10 -0
  163. package/src/ts/rdb/agent-connection/generator.js +8 -1
  164. package/src/ts/rdb/agent-connection/generator.js.map +1 -1
  165. package/src/ts/rdb/generator.d.ts +101 -0
  166. package/src/ts/rdb/generator.js +93 -41
  167. package/src/ts/rdb/generator.js.map +1 -1
  168. package/src/ts/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +10 -0
  169. package/src/ts/rdb/mcp-server-connection/generator.js +8 -1
  170. package/src/ts/rdb/mcp-server-connection/generator.js.map +1 -1
  171. package/src/ts/rdb/smithy-connection/__snapshots__/generator.spec.ts.snap +9 -0
  172. package/src/ts/rdb/smithy-connection/generator.js +4 -1
  173. package/src/ts/rdb/smithy-connection/generator.js.map +1 -1
  174. package/src/ts/rdb/trpc-connection/__snapshots__/generator.spec.ts.snap +9 -0
  175. package/src/ts/rdb/trpc-connection/generator.js +3 -1
  176. package/src/ts/rdb/trpc-connection/generator.js.map +1 -1
  177. package/src/ts/react-website/agui/generator.d.ts +86 -0
  178. package/src/ts/react-website/agui/generator.js +63 -28
  179. package/src/ts/react-website/agui/generator.js.map +1 -1
  180. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +20 -2
  181. package/src/ts/react-website/app/generator.d.ts +136 -1
  182. package/src/ts/react-website/app/generator.js +109 -40
  183. package/src/ts/react-website/app/generator.js.map +1 -1
  184. package/src/ts/react-website/cognito-auth/generator.d.ts +19 -0
  185. package/src/ts/react-website/cognito-auth/generator.js +21 -9
  186. package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
  187. package/src/utils/add-dependencies.d.ts +38 -0
  188. package/src/utils/add-dependencies.js +83 -0
  189. package/src/utils/add-dependencies.js.map +1 -0
  190. package/src/utils/agent-connection/agent-connection.d.ts +27 -6
  191. package/src/utils/agent-connection/agent-connection.js +47 -18
  192. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  193. package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +19 -1
  194. package/src/utils/agent-core-constructs/agent-core-constructs.js +26 -6
  195. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  196. package/src/utils/api-constructs/api-constructs.d.ts +21 -2
  197. package/src/utils/api-constructs/api-constructs.js +26 -5
  198. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  199. package/src/utils/bundle/bundle.d.ts +6 -1
  200. package/src/utils/bundle/bundle.js +8 -2
  201. package/src/utils/bundle/bundle.js.map +1 -1
  202. package/src/utils/commands.d.ts +5 -4
  203. package/src/utils/commands.js +2 -6
  204. package/src/utils/commands.js.map +1 -1
  205. package/src/utils/connection/open-api/react.d.ts +18 -1
  206. package/src/utils/connection/open-api/react.js +27 -3
  207. package/src/utils/connection/open-api/react.js.map +1 -1
  208. package/src/utils/declared-dependencies.d.ts +140 -0
  209. package/src/utils/declared-dependencies.js +64 -0
  210. package/src/utils/declared-dependencies.js.map +1 -0
  211. package/src/utils/docker.d.ts +10 -1
  212. package/src/utils/docker.js +7 -3
  213. package/src/utils/docker.js.map +1 -1
  214. package/src/utils/fs.d.ts +15 -4
  215. package/src/utils/fs.js +26 -13
  216. package/src/utils/fs.js.map +1 -1
  217. package/src/utils/init.d.ts +14 -1
  218. package/src/utils/init.js +25 -7
  219. package/src/utils/init.js.map +1 -1
  220. package/src/utils/migration-versions.d.ts +15 -1
  221. package/src/utils/migration-versions.js +53 -7
  222. package/src/utils/migration-versions.js.map +1 -1
  223. package/src/utils/nx.d.ts +18 -0
  224. package/src/utils/nx.js +4 -0
  225. package/src/utils/nx.js.map +1 -1
  226. package/src/utils/py.d.ts +3 -2
  227. package/src/utils/py.js +10 -10
  228. package/src/utils/py.js.map +1 -1
  229. package/src/utils/shared-constructs-constants.d.ts +39 -4
  230. package/src/utils/shared-constructs-constants.js +29 -0
  231. package/src/utils/shared-constructs-constants.js.map +1 -1
  232. package/src/utils/shared-constructs.d.ts +4 -1
  233. package/src/utils/shared-constructs.js +5 -4
  234. package/src/utils/shared-constructs.js.map +1 -1
  235. package/src/utils/shared-dynamodb-scripts.d.ts +8 -1
  236. package/src/utils/shared-dynamodb-scripts.js +11 -3
  237. package/src/utils/shared-dynamodb-scripts.js.map +1 -1
  238. package/src/utils/shared-infra-scripts.d.ts +16 -1
  239. package/src/utils/shared-infra-scripts.js +18 -3
  240. package/src/utils/shared-infra-scripts.js.map +1 -1
  241. package/src/utils/shared-rdb-scripts.d.ts +12 -1
  242. package/src/utils/shared-rdb-scripts.js +17 -3
  243. package/src/utils/shared-rdb-scripts.js.map +1 -1
  244. package/src/utils/shared-shadcn.d.ts +26 -1
  245. package/src/utils/shared-shadcn.js +31 -14
  246. package/src/utils/shared-shadcn.js.map +1 -1
  247. package/src/utils/version-upgrade-migration/migration.d.ts +14 -0
  248. package/src/utils/version-upgrade-migration/migration.js +16 -0
  249. package/src/utils/version-upgrade-migration/migration.js.map +1 -0
  250. package/src/utils/version-upgrade-migration/nx-package-updates.d.ts +35 -0
  251. package/src/utils/version-upgrade-migration/nx-package-updates.js +42 -0
  252. package/src/utils/version-upgrade-migration/nx-package-updates.js.map +1 -0
  253. package/src/utils/version-upgrade-migration/owned-dependencies.d.ts +50 -0
  254. package/src/utils/version-upgrade-migration/owned-dependencies.js +98 -0
  255. package/src/utils/version-upgrade-migration/owned-dependencies.js.map +1 -0
  256. package/src/utils/version-upgrade-migration/register.d.ts +18 -0
  257. package/src/utils/version-upgrade-migration/register.js +33 -0
  258. package/src/utils/version-upgrade-migration/register.js.map +1 -0
  259. package/src/utils/version-upgrade-migration/sync-metrics-version.d.ts +13 -0
  260. package/src/utils/version-upgrade-migration/sync-metrics-version.js +33 -0
  261. package/src/utils/version-upgrade-migration/sync-metrics-version.js.map +1 -0
  262. package/src/utils/version-upgrade-migration/sync-vended-versions.d.ts +10 -0
  263. package/src/utils/version-upgrade-migration/sync-vended-versions.js +504 -0
  264. package/src/utils/version-upgrade-migration/sync-vended-versions.js.map +1 -0
  265. package/src/utils/version-upgrade-migration/vended-upgrade.d.ts +14 -0
  266. package/src/utils/version-upgrade-migration/vended-upgrade.js +40 -0
  267. package/src/utils/version-upgrade-migration/vended-upgrade.js.map +1 -0
  268. package/src/utils/versions.d.ts +25 -5
  269. package/src/utils/versions.js +46 -4
  270. package/src/utils/versions.js.map +1 -1
  271. package/src/utils/website-constructs/files/cdk/core/static-website.ts.template +4 -0
@@ -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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"}
@@ -21,10 +21,22 @@ import { compare } from 'semver';
21
21
  * versions of everything already released.
22
22
  *
23
23
  * A version already in source always wins, so backfilled entries are stable.
24
+ *
25
+ * An entry marked `everyMigration: true` is never backfilled or pinned, and is
26
+ * re-stamped with each pending version, so it runs on every upgrade.
24
27
  */
25
28
  export interface MigrationsJson {
26
29
  generators?: Record<string, {
27
30
  version?: string;
31
+ everyMigration?: boolean;
32
+ } & Record<string, unknown>>;
33
+ /**
34
+ * Declarative dependency bumps `nx migrate` applies to the root manifest.
35
+ * Keyed `<dir>-<name>` like the migrations so entries from different releases
36
+ * can't collide; nx itself gates on the entry's `version`.
37
+ */
38
+ packageJsonUpdates?: Record<string, {
39
+ version: string;
28
40
  } & Record<string, unknown>>;
29
41
  }
30
42
  /** Ascending semver comparator for `Array.prototype.sort`. */
@@ -49,7 +61,9 @@ export declare const isValidVersion: (version: string) => boolean;
49
61
  export declare const readShippedMigrationVersions: (migrations: MigrationsJson, versions: string[], readReleasedMigrations: (version: string) => MigrationsJson | undefined) => Record<string, string>;
50
62
  /**
51
63
  * Return a copy of the migrations collection with a `version` stamped onto
52
- * every generator entry, preserving any already present.
64
+ * every generator entry, preserving any already present, and any
65
+ * `packageJsonUpdates` entry still keyed `latest` re-keyed to the version it
66
+ * ships under.
53
67
  *
54
68
  * @param migrations parsed migrations.json to stamp
55
69
  * @param shippedVersions migration key -> version of the earliest release
@@ -37,7 +37,9 @@
37
37
  };
38
38
  /**
39
39
  * Return a copy of the migrations collection with a `version` stamped onto
40
- * every generator entry, preserving any already present.
40
+ * every generator entry, preserving any already present, and any
41
+ * `packageJsonUpdates` entry still keyed `latest` re-keyed to the version it
42
+ * ships under.
41
43
  *
42
44
  * @param migrations parsed migrations.json to stamp
43
45
  * @param shippedVersions migration key -> version of the earliest release
@@ -46,14 +48,40 @@
46
48
  * unshipped migrations so their version is one that really shipped
47
49
  */ export const stampMigrationVersions = (migrations, shippedVersions, pendingVersion)=>({
48
50
  ...migrations,
49
- generators: Object.fromEntries(Object.entries(migrations.generators ?? {}).map(([name, entry])=>[
51
+ generators: Object.fromEntries(// `nx migrate` sorts the run ascending by version and preserves the
52
+ // manifest's order among equal versions, so emitting the every-migration
53
+ // entries last is what makes them run after the release's own migrations.
54
+ Object.entries(migrations.generators ?? {}).sort(([, a], [, b])=>Number(a.everyMigration ?? false) - Number(b.everyMigration ?? false)).map(([name, entry])=>{
55
+ // Source-only marker, stripped from what nx reads.
56
+ const { everyMigration, version: sourceVersion, ...published } = entry;
57
+ // Overrides any source version so it stays ahead of what is installed.
58
+ const version = everyMigration ? pendingVersion : sourceVersion ?? shippedVersions[name] ?? pendingVersion;
59
+ return [
50
60
  name,
51
61
  {
52
- version: shippedVersions[name] ?? pendingVersion,
53
- ...entry
62
+ version,
63
+ ...published
54
64
  }
55
- ]))
65
+ ];
66
+ })),
67
+ ...migrations.packageJsonUpdates && {
68
+ packageJsonUpdates: stampPackageJsonUpdates(migrations.packageJsonUpdates, pendingVersion)
69
+ }
56
70
  });
71
+ /**
72
+ * Version any unreleased `packageJsonUpdates` entry and re-key it out of
73
+ * `latest`, so the nx bump ships under the same version as its migrations.
74
+ */ const stampPackageJsonUpdates = (packageJsonUpdates, pendingVersion)=>Object.fromEntries(Object.entries(packageJsonUpdates).map(([key, entry])=>entry.version === LATEST_MIGRATIONS_DIR ? [
75
+ reKeyToVersion(key, pendingVersion),
76
+ {
77
+ ...entry,
78
+ version: pendingVersion
79
+ }
80
+ ] : [
81
+ key,
82
+ entry
83
+ ]));
84
+ /** Swap a `latest-<name>` key for the release that ships it. */ const reKeyToVersion = (key, version)=>key.startsWith(LATEST_KEY_PREFIX) ? migrationKey(versionMigrationsDir(version), key.slice(LATEST_KEY_PREFIX.length)) : key;
57
85
  /** Directory a newly scaffolded migration lands in, before a release claims it. */ export const LATEST_MIGRATIONS_DIR = 'latest';
58
86
  /** Directory holding the migrations shipped by a given release. */ export const versionMigrationsDir = (version)=>`v${version}`;
59
87
  /**
@@ -80,7 +108,8 @@ const LATEST_KEY_PREFIX = `${LATEST_MIGRATIONS_DIR}-`;
80
108
  const moves = [];
81
109
  for (const [key, entry] of Object.entries(migrations.generators ?? {})){
82
110
  const version = shippedVersions[key];
83
- if (entry.version || !version) {
111
+ // Pinning an every-migration entry would stop it running on later upgrades.
112
+ if (entry.version || !version || entry.everyMigration) {
84
113
  generators[key] = entry;
85
114
  continue;
86
115
  }
@@ -118,11 +147,28 @@ const LATEST_KEY_PREFIX = `${LATEST_MIGRATIONS_DIR}-`;
118
147
  return {
119
148
  migrations: {
120
149
  ...migrations,
121
- generators
150
+ generators,
151
+ ...migrations.packageJsonUpdates && {
152
+ packageJsonUpdates: backfillPackageJsonUpdates(migrations.packageJsonUpdates, // Re-keyed with the earliest release it shipped alongside.
153
+ backfilled.map((key)=>shippedVersions[key]).sort(compareVersions)[0])
154
+ }
122
155
  },
123
156
  backfilled,
124
157
  moves
125
158
  };
126
159
  };
160
+ /**
161
+ * Record the release that shipped an unreleased `packageJsonUpdates` entry,
162
+ * re-keying it out of `latest`, and leave it alone until one has.
163
+ */ const backfillPackageJsonUpdates = (packageJsonUpdates, shippedVersion)=>Object.fromEntries(Object.entries(packageJsonUpdates).map(([key, entry])=>entry.version === LATEST_MIGRATIONS_DIR && shippedVersion ? [
164
+ reKeyToVersion(key, shippedVersion),
165
+ {
166
+ ...entry,
167
+ version: shippedVersion
168
+ }
169
+ ] : [
170
+ key,
171
+ entry
172
+ ]));
127
173
 
128
174
  //# sourceMappingURL=migration-versions.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/migration-versions.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { compare, valid } from 'semver';\n\n/**\n * Version stamping for migrations.\n *\n * A new migration is committed with no `version` — releases are calculated from\n * conventional commits and written only to `dist/` and a git tag, so versions\n * reach the published `migrations.json` two ways:\n *\n * - At release time (`scripts/stamp-migrations.ts`) entries still missing a\n * version are stamped into the compiled `migrations.json`: an already shipped\n * one gets the earliest release tag registering it, and a net-new one gets the\n * version the release is about to publish, which the release job passes in\n * after `nx release version` writes it to the dist manifests.\n * - The weekly `update-versions` PR backfills the version of the release that\n * shipped each migration, moving and re-keying it accordingly\n * (`scripts/backfill-migration-versions.ts`), so source converges on the\n * versions of everything already released.\n *\n * A version already in source always wins, so backfilled entries are stable.\n */\n\nexport interface MigrationsJson {\n generators?: Record<string, { version?: string } & Record<string, unknown>>;\n}\n\n/** Ascending semver comparator for `Array.prototype.sort`. */\nexport const compareVersions = compare;\n\n/** Whether a string is an exact semver version. */\nexport const isValidVersion = (version: string): boolean =>\n valid(version) !== null;\n\n/**\n * Map of migration key -> version of the earliest release that registers it,\n * resolved only for the entries still missing a `version` (one already recorded\n * in source wins, so its history doesn't need reading). A migration that hasn't\n * been released is absent.\n *\n * Walks releases newest first and stops as soon as every entry is resolved: an\n * entry that has disappeared from a release's `migrations.json` was first\n * registered by the release after it, which is the one that shipped it.\n *\n * @param migrations parsed source migrations.json\n * @param versions released versions in descending semver order\n * @param readReleasedMigrations reads the `migrations.json` published by a given\n * version, or undefined if it predates the manifest\n */\nexport const readShippedMigrationVersions = (\n migrations: MigrationsJson,\n versions: string[],\n readReleasedMigrations: (version: string) => MigrationsJson | undefined,\n): Record<string, string> => {\n const shippedVersions: Record<string, string> = {};\n let unresolved = Object.entries(migrations.generators ?? {})\n .filter(([, entry]) => !entry.version)\n .map(([key]) => key);\n\n for (const version of versions) {\n if (unresolved.length === 0) {\n break;\n }\n const registered = new Set(\n Object.keys(readReleasedMigrations(version)?.generators ?? {}),\n );\n // Entries gone at this release keep the version recorded from the release\n // after it (if any) and stop being looked up.\n unresolved = unresolved.filter((key) => registered.has(key));\n for (const key of unresolved) {\n shippedVersions[key] = version;\n }\n }\n\n return shippedVersions;\n};\n\n/**\n * Return a copy of the migrations collection with a `version` stamped onto\n * every generator entry, preserving any already present.\n *\n * @param migrations parsed migrations.json to stamp\n * @param shippedVersions migration key -> version of the earliest release\n * tag that registers it (absent for migrations that haven't shipped)\n * @param pendingVersion version the release is about to publish, stamped onto\n * unshipped migrations so their version is one that really shipped\n */\nexport const stampMigrationVersions = (\n migrations: MigrationsJson,\n shippedVersions: Record<string, string>,\n pendingVersion: string,\n): MigrationsJson => ({\n ...migrations,\n generators: Object.fromEntries(\n Object.entries(migrations.generators ?? {}).map(([name, entry]) => [\n name,\n { version: shippedVersions[name] ?? pendingVersion, ...entry },\n ]),\n ),\n});\n\n/** Directory a newly scaffolded migration lands in, before a release claims it. */\nexport const LATEST_MIGRATIONS_DIR = 'latest';\n\n/** Directory holding the migrations shipped by a given release. */\nexport const versionMigrationsDir = (version: string) => `v${version}`;\n\n/**\n * Key a migration is registered under in `migrations.json`. Prefixed with its\n * directory so reusing a name in a later release can't silently overwrite the\n * one that already shipped.\n */\nexport const migrationKey = (dir: string, name: string) => `${dir}-${name}`;\n\nconst LATEST_KEY_PREFIX = `${LATEST_MIGRATIONS_DIR}-`;\n\n/** A migration directory move the caller needs to make on disk. */\nexport interface MigrationDirMove {\n name: string;\n version: string;\n from: string;\n to: string;\n}\n\n/**\n * Record the release that shipped each migration on entries without a version,\n * re-keying them and re-pointing their paths at that release's folder, and\n * return the collection alongside the keys that changed and the directory moves\n * to make on disk.\n *\n * Unlike `stampMigrationVersions` this only records already-released versions,\n * leaving the release to decide what a net-new migration gets.\n *\n * @param migrations parsed migrations.json to backfill\n * @param shippedVersions migration key -> version of the earliest release tag\n * that registers it (absent for migrations that haven't shipped)\n */\nexport const backfillMigrationVersions = (\n migrations: MigrationsJson,\n shippedVersions: Record<string, string>,\n): {\n migrations: MigrationsJson;\n backfilled: string[];\n moves: MigrationDirMove[];\n} => {\n const generators: NonNullable<MigrationsJson['generators']> = {};\n const backfilled: string[] = [];\n const moves: MigrationDirMove[] = [];\n\n for (const [key, entry] of Object.entries(migrations.generators ?? {})) {\n const version = shippedVersions[key];\n if (entry.version || !version) {\n generators[key] = entry;\n continue;\n }\n\n const name = key.startsWith(LATEST_KEY_PREFIX)\n ? key.slice(LATEST_KEY_PREFIX.length)\n : key;\n const versionDir = versionMigrationsDir(version);\n const latestSegment = `/${LATEST_MIGRATIONS_DIR}/${name}/`;\n const versionSegment = `/${versionDir}/${name}/`;\n\n // Re-point each path field at the version folder, recording the move the\n // caller needs to make on disk the first time one is found.\n const repointed: Record<string, unknown> = {};\n let moved = false;\n for (const [field, value] of Object.entries(entry)) {\n if (typeof value !== 'string' || !value.includes(latestSegment)) {\n repointed[field] = value;\n continue;\n }\n repointed[field] = value.replace(latestSegment, versionSegment);\n if (!moved) {\n moved = true;\n const dir = value.slice(0, value.indexOf(latestSegment));\n moves.push({\n name,\n version,\n from: `${dir}${latestSegment}`.replace(/^\\.\\/|\\/$/g, ''),\n to: `${dir}${versionSegment}`.replace(/^\\.\\/|\\/$/g, ''),\n });\n }\n }\n\n generators[migrationKey(versionDir, name)] = { version, ...repointed };\n backfilled.push(key);\n }\n\n return { migrations: { ...migrations, generators }, backfilled, moves };\n};\n"],"names":["compare","valid","compareVersions","isValidVersion","version","readShippedMigrationVersions","migrations","versions","readReleasedMigrations","shippedVersions","unresolved","Object","entries","generators","filter","entry","map","key","length","registered","Set","keys","has","stampMigrationVersions","pendingVersion","fromEntries","name","LATEST_MIGRATIONS_DIR","versionMigrationsDir","migrationKey","dir","LATEST_KEY_PREFIX","backfillMigrationVersions","backfilled","moves","startsWith","slice","versionDir","latestSegment","versionSegment","repointed","moved","field","value","includes","replace","indexOf","push","from","to"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/migration-versions.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { compare, valid } from 'semver';\n\n/**\n * Version stamping for migrations.\n *\n * A new migration is committed with no `version` — releases are calculated from\n * conventional commits and written only to `dist/` and a git tag, so versions\n * reach the published `migrations.json` two ways:\n *\n * - At release time (`scripts/stamp-migrations.ts`) entries still missing a\n * version are stamped into the compiled `migrations.json`: an already shipped\n * one gets the earliest release tag registering it, and a net-new one gets the\n * version the release is about to publish, which the release job passes in\n * after `nx release version` writes it to the dist manifests.\n * - The weekly `update-versions` PR backfills the version of the release that\n * shipped each migration, moving and re-keying it accordingly\n * (`scripts/backfill-migration-versions.ts`), so source converges on the\n * versions of everything already released.\n *\n * A version already in source always wins, so backfilled entries are stable.\n *\n * An entry marked `everyMigration: true` is never backfilled or pinned, and is\n * re-stamped with each pending version, so it runs on every upgrade.\n */\n\nexport interface MigrationsJson {\n generators?: Record<\n string,\n { version?: string; everyMigration?: boolean } & Record<string, unknown>\n >;\n /**\n * Declarative dependency bumps `nx migrate` applies to the root manifest.\n * Keyed `<dir>-<name>` like the migrations so entries from different releases\n * can't collide; nx itself gates on the entry's `version`.\n */\n packageJsonUpdates?: Record<\n string,\n { version: string } & Record<string, unknown>\n >;\n}\n\n/** Ascending semver comparator for `Array.prototype.sort`. */\nexport const compareVersions = compare;\n\n/** Whether a string is an exact semver version. */\nexport const isValidVersion = (version: string): boolean =>\n valid(version) !== null;\n\n/**\n * Map of migration key -> version of the earliest release that registers it,\n * resolved only for the entries still missing a `version` (one already recorded\n * in source wins, so its history doesn't need reading). A migration that hasn't\n * been released is absent.\n *\n * Walks releases newest first and stops as soon as every entry is resolved: an\n * entry that has disappeared from a release's `migrations.json` was first\n * registered by the release after it, which is the one that shipped it.\n *\n * @param migrations parsed source migrations.json\n * @param versions released versions in descending semver order\n * @param readReleasedMigrations reads the `migrations.json` published by a given\n * version, or undefined if it predates the manifest\n */\nexport const readShippedMigrationVersions = (\n migrations: MigrationsJson,\n versions: string[],\n readReleasedMigrations: (version: string) => MigrationsJson | undefined,\n): Record<string, string> => {\n const shippedVersions: Record<string, string> = {};\n let unresolved = Object.entries(migrations.generators ?? {})\n .filter(([, entry]) => !entry.version)\n .map(([key]) => key);\n\n for (const version of versions) {\n if (unresolved.length === 0) {\n break;\n }\n const registered = new Set(\n Object.keys(readReleasedMigrations(version)?.generators ?? {}),\n );\n // Entries gone at this release keep the version recorded from the release\n // after it (if any) and stop being looked up.\n unresolved = unresolved.filter((key) => registered.has(key));\n for (const key of unresolved) {\n shippedVersions[key] = version;\n }\n }\n\n return shippedVersions;\n};\n\n/**\n * Return a copy of the migrations collection with a `version` stamped onto\n * every generator entry, preserving any already present, and any\n * `packageJsonUpdates` entry still keyed `latest` re-keyed to the version it\n * ships under.\n *\n * @param migrations parsed migrations.json to stamp\n * @param shippedVersions migration key -> version of the earliest release\n * tag that registers it (absent for migrations that haven't shipped)\n * @param pendingVersion version the release is about to publish, stamped onto\n * unshipped migrations so their version is one that really shipped\n */\nexport const stampMigrationVersions = (\n migrations: MigrationsJson,\n shippedVersions: Record<string, string>,\n pendingVersion: string,\n): MigrationsJson => ({\n ...migrations,\n generators: Object.fromEntries(\n // `nx migrate` sorts the run ascending by version and preserves the\n // manifest's order among equal versions, so emitting the every-migration\n // entries last is what makes them run after the release's own migrations.\n Object.entries(migrations.generators ?? {})\n .sort(\n ([, a], [, b]) =>\n Number(a.everyMigration ?? false) - Number(b.everyMigration ?? false),\n )\n .map(([name, entry]) => {\n // Source-only marker, stripped from what nx reads.\n const { everyMigration, version: sourceVersion, ...published } = entry;\n // Overrides any source version so it stays ahead of what is installed.\n const version = everyMigration\n ? pendingVersion\n : (sourceVersion ?? shippedVersions[name] ?? pendingVersion);\n return [name, { version, ...published }];\n }),\n ),\n ...(migrations.packageJsonUpdates && {\n packageJsonUpdates: stampPackageJsonUpdates(\n migrations.packageJsonUpdates,\n pendingVersion,\n ),\n }),\n});\n\n/**\n * Version any unreleased `packageJsonUpdates` entry and re-key it out of\n * `latest`, so the nx bump ships under the same version as its migrations.\n */\nconst stampPackageJsonUpdates = (\n packageJsonUpdates: NonNullable<MigrationsJson['packageJsonUpdates']>,\n pendingVersion: string,\n): NonNullable<MigrationsJson['packageJsonUpdates']> =>\n Object.fromEntries(\n Object.entries(packageJsonUpdates).map(([key, entry]) =>\n entry.version === LATEST_MIGRATIONS_DIR\n ? [\n reKeyToVersion(key, pendingVersion),\n { ...entry, version: pendingVersion },\n ]\n : [key, entry],\n ),\n );\n\n/** Swap a `latest-<name>` key for the release that ships it. */\nconst reKeyToVersion = (key: string, version: string): string =>\n key.startsWith(LATEST_KEY_PREFIX)\n ? migrationKey(\n versionMigrationsDir(version),\n key.slice(LATEST_KEY_PREFIX.length),\n )\n : key;\n\n/** Directory a newly scaffolded migration lands in, before a release claims it. */\nexport const LATEST_MIGRATIONS_DIR = 'latest';\n\n/** Directory holding the migrations shipped by a given release. */\nexport const versionMigrationsDir = (version: string) => `v${version}`;\n\n/**\n * Key a migration is registered under in `migrations.json`. Prefixed with its\n * directory so reusing a name in a later release can't silently overwrite the\n * one that already shipped.\n */\nexport const migrationKey = (dir: string, name: string) => `${dir}-${name}`;\n\nconst LATEST_KEY_PREFIX = `${LATEST_MIGRATIONS_DIR}-`;\n\n/** A migration directory move the caller needs to make on disk. */\nexport interface MigrationDirMove {\n name: string;\n version: string;\n from: string;\n to: string;\n}\n\n/**\n * Record the release that shipped each migration on entries without a version,\n * re-keying them and re-pointing their paths at that release's folder, and\n * return the collection alongside the keys that changed and the directory moves\n * to make on disk.\n *\n * Unlike `stampMigrationVersions` this only records already-released versions,\n * leaving the release to decide what a net-new migration gets.\n *\n * @param migrations parsed migrations.json to backfill\n * @param shippedVersions migration key -> version of the earliest release tag\n * that registers it (absent for migrations that haven't shipped)\n */\nexport const backfillMigrationVersions = (\n migrations: MigrationsJson,\n shippedVersions: Record<string, string>,\n): {\n migrations: MigrationsJson;\n backfilled: string[];\n moves: MigrationDirMove[];\n} => {\n const generators: NonNullable<MigrationsJson['generators']> = {};\n const backfilled: string[] = [];\n const moves: MigrationDirMove[] = [];\n\n for (const [key, entry] of Object.entries(migrations.generators ?? {})) {\n const version = shippedVersions[key];\n // Pinning an every-migration entry would stop it running on later upgrades.\n if (entry.version || !version || entry.everyMigration) {\n generators[key] = entry;\n continue;\n }\n\n const name = key.startsWith(LATEST_KEY_PREFIX)\n ? key.slice(LATEST_KEY_PREFIX.length)\n : key;\n const versionDir = versionMigrationsDir(version);\n const latestSegment = `/${LATEST_MIGRATIONS_DIR}/${name}/`;\n const versionSegment = `/${versionDir}/${name}/`;\n\n // Re-point each path field at the version folder, recording the move the\n // caller needs to make on disk the first time one is found.\n const repointed: Record<string, unknown> = {};\n let moved = false;\n for (const [field, value] of Object.entries(entry)) {\n if (typeof value !== 'string' || !value.includes(latestSegment)) {\n repointed[field] = value;\n continue;\n }\n repointed[field] = value.replace(latestSegment, versionSegment);\n if (!moved) {\n moved = true;\n const dir = value.slice(0, value.indexOf(latestSegment));\n moves.push({\n name,\n version,\n from: `${dir}${latestSegment}`.replace(/^\\.\\/|\\/$/g, ''),\n to: `${dir}${versionSegment}`.replace(/^\\.\\/|\\/$/g, ''),\n });\n }\n }\n\n generators[migrationKey(versionDir, name)] = { version, ...repointed };\n backfilled.push(key);\n }\n\n return {\n migrations: {\n ...migrations,\n generators,\n ...(migrations.packageJsonUpdates && {\n packageJsonUpdates: backfillPackageJsonUpdates(\n migrations.packageJsonUpdates,\n // Re-keyed with the earliest release it shipped alongside.\n backfilled\n .map((key) => shippedVersions[key])\n .sort(compareVersions)[0],\n ),\n }),\n },\n backfilled,\n moves,\n };\n};\n\n/**\n * Record the release that shipped an unreleased `packageJsonUpdates` entry,\n * re-keying it out of `latest`, and leave it alone until one has.\n */\nconst backfillPackageJsonUpdates = (\n packageJsonUpdates: NonNullable<MigrationsJson['packageJsonUpdates']>,\n shippedVersion: string | undefined,\n): NonNullable<MigrationsJson['packageJsonUpdates']> =>\n Object.fromEntries(\n Object.entries(packageJsonUpdates).map(([key, entry]) =>\n entry.version === LATEST_MIGRATIONS_DIR && shippedVersion\n ? [\n reKeyToVersion(key, shippedVersion),\n { ...entry, version: shippedVersion },\n ]\n : [key, entry],\n ),\n );\n"],"names":["compare","valid","compareVersions","isValidVersion","version","readShippedMigrationVersions","migrations","versions","readReleasedMigrations","shippedVersions","unresolved","Object","entries","generators","filter","entry","map","key","length","registered","Set","keys","has","stampMigrationVersions","pendingVersion","fromEntries","sort","a","b","Number","everyMigration","name","sourceVersion","published","packageJsonUpdates","stampPackageJsonUpdates","LATEST_MIGRATIONS_DIR","reKeyToVersion","startsWith","LATEST_KEY_PREFIX","migrationKey","versionMigrationsDir","slice","dir","backfillMigrationVersions","backfilled","moves","versionDir","latestSegment","versionSegment","repointed","moved","field","value","includes","replace","indexOf","push","from","to","backfillPackageJsonUpdates","shippedVersion"],"mappings":"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"}
package/src/utils/nx.d.ts CHANGED
@@ -57,11 +57,29 @@ export declare const addGeneratorMetadata: (tree: Tree, projectName: string, inf
57
57
  export interface ComponentMetadata {
58
58
  readonly generator: string;
59
59
  readonly name?: string;
60
+ /**
61
+ * What this entry wires up. For a connection that is the target — the thing
62
+ * being connected to — paired with `sourcePath` below.
63
+ */
60
64
  readonly path?: string;
65
+ /**
66
+ * The component the connection is made *from*, when both ends are components
67
+ * of a project rather than whole projects.
68
+ *
69
+ * A connection records the project it lives on and the target it reaches, which
70
+ * alone can't tell which of several components on that project is wired up.
71
+ * Recorded as a path for the same reason `path` is: it identifies a component
72
+ * within its project without depending on a name that may repeat.
73
+ */
74
+ readonly sourcePath?: string;
61
75
  [key: string]: any;
62
76
  }
63
77
  /**
64
78
  * Add metadata about the generator that generated the component to the project.json
79
+ *
80
+ * A connection between two components passes the source's path as
81
+ * `additionalMetadata.sourcePath`, so the pair is identifiable rather than just
82
+ * the two projects.
65
83
  */
66
84
  export declare const addComponentGeneratorMetadata: (tree: Tree, projectName: string, info: {
67
85
  id: string;
package/src/utils/nx.js CHANGED
@@ -105,6 +105,10 @@ export const getPackageVersion = ()=>{
105
105
  };
106
106
  /**
107
107
  * Add metadata about the generator that generated the component to the project.json
108
+ *
109
+ * A connection between two components passes the source's path as
110
+ * `additionalMetadata.sourcePath`, so the pair is identifiable rather than just
111
+ * the two projects.
108
112
  */ export const addComponentGeneratorMetadata = (tree, projectName, info, componentPath, componentName, additionalMetadata)=>{
109
113
  const config = readProjectConfigurationUnqualified(tree, projectName);
110
114
  const existingComponents = config?.metadata?.components ?? [];
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/nx.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n type ProjectConfiguration,\n readJson,\n readProjectConfiguration,\n type TargetConfiguration,\n type TargetDefaultValue,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport * as path from 'path';\nimport PackageJson from '../../package.json' with { type: 'json' };\nimport { NX_PLUGIN_MCP_PACKAGE_NAME } from './mcp';\nimport { toSnakeCase } from './names';\nimport { getNpmScope, getNpmScopePrefix } from './npm-scope';\n\nexport type { GeneratorInfo, NxGeneratorInfo } from './generators';\nexport { buildGeneratorInfoList } from './generators';\n\nimport { buildGeneratorInfoList, type GeneratorInfo } from './generators';\n\nconst GENERATORS = buildGeneratorInfoList(\n path.resolve(import.meta.dirname, '..', '..'),\n);\n\n/**\n * List Nx Plugin for AWS generators\n * @param includeHidden include hidden generators (default false)\n */\nexport const listGenerators = (includeHidden = false) =>\n GENERATORS.filter((g) => includeHidden || !g.hidden);\n\n/**\n * Return generator information. Call this from a generator method with import.meta.filename\n */\nexport const getGeneratorInfo = (generatorFileName: string): GeneratorInfo => {\n const { dir, name } = path.parse(path.resolve(generatorFileName));\n const resolvedFactoryPath = path.join(dir, name);\n return GENERATORS.find(\n (generatorInfo) =>\n generatorInfo.resolvedFactoryPath === resolvedFactoryPath,\n );\n};\n\nexport const getPackageVersion = () => {\n return PackageJson.version;\n};\n\n/**\n * True inside the plugin's own monorepo, where the plugin is the source rather\n * than a dependency.\n */\nexport const isNxPluginForAwsWorkspace = (tree: Tree): boolean => {\n const rootPackageJson = tree.exists('package.json')\n ? readJson(tree, 'package.json')\n : undefined;\n return rootPackageJson?.name === '@aws/nx-plugin-source';\n};\n\n/**\n * The `@aws/nx-plugin` devDependency entry for a workspace the plugin generates\n * into, keyed to the version the running generators come from. Empty inside the\n * plugin's own monorepo.\n */\nexport const nxPluginSelfDependency = (tree: Tree): Record<string, string> =>\n isNxPluginForAwsWorkspace(tree)\n ? {}\n : { [PackageJson.name]: `^${PackageJson.version}` };\n\n/**\n * The `@aws/nx-plugin-mcp` devDependency entry, keyed to the running generators'\n * version — the two packages are released in lockstep. Declaring it pins the MCP\n * server the vended config runs in the workspace's lockfile, so upgrading it\n * upgrades the server. Empty inside the plugin's own monorepo.\n */\nexport const nxPluginMcpDependency = (tree: Tree): Record<string, string> =>\n isNxPluginForAwsWorkspace(tree)\n ? {}\n : { [NX_PLUGIN_MCP_PACKAGE_NAME]: `^${PackageJson.version}` };\n\n/**\n * Read a project configuration where the project name may not be fully qualified (ie may omit the scope prefix)\n */\nexport const readProjectConfigurationUnqualified = (\n tree: Tree,\n projectName: string,\n) => {\n try {\n return readProjectConfiguration(tree, projectName);\n } catch (e) {\n // Attempt to find the project without the scope\n const project = [...getProjects(tree).values()].find(\n (p) =>\n p.name &&\n (p.name === `${getNpmScopePrefix(tree)}${projectName}` || // TypeScript fully-qualified name\n p.name === `${toSnakeCase(getNpmScope(tree))}.${projectName}`), // Python fully-qualified name\n );\n if (project) {\n return project;\n }\n throw e;\n }\n};\n\n/**\n * Returns whether a project with the given name already exists in the workspace.\n * The project name may be unqualified (ie may omit the scope prefix).\n */\nexport const projectExists = (tree: Tree, projectName: string): boolean => {\n try {\n readProjectConfigurationUnqualified(tree, projectName);\n return true;\n } catch {\n return false;\n }\n};\n\n/**\n * Add metadata about the generator that generated the project to the project.json\n */\nexport const addGeneratorMetadata = (\n tree: Tree,\n projectName: string,\n info: { id: string },\n additionalMetadata?: { [key: string]: any },\n) => {\n const config = readProjectConfigurationUnqualified(tree, projectName);\n const metadata = {\n ...config?.metadata,\n generator: info.id,\n ...additionalMetadata,\n };\n // Skip the write when nothing changed so re-running doesn't reserialize\n // project.json. metadata is plain JSON built in a fixed key order, so a\n // stringify comparison is exact here.\n if (JSON.stringify(config?.metadata) === JSON.stringify(metadata)) {\n return;\n }\n // Place metadata immediately before targets so the serialized key order is\n // identical whether or not metadata already existed (matching the order Nx\n // normalizes a read config to), keeping the change a pure metadata insert.\n const { targets, ...rest } = config;\n updateProjectConfiguration(tree, config.name, {\n ...rest,\n metadata: metadata as any,\n ...(targets ? { targets } : {}),\n });\n};\n\n/**\n * Represents a component entry in project metadata\n */\nexport interface ComponentMetadata {\n readonly generator: string;\n readonly name?: string;\n readonly path?: string;\n [key: string]: any;\n}\n\n/**\n * Add metadata about the generator that generated the component to the project.json\n */\nexport const addComponentGeneratorMetadata = (\n tree: Tree,\n projectName: string,\n info: { id: string },\n componentPath: string,\n componentName?: string,\n additionalMetadata?: { [key: string]: any },\n) => {\n const config = readProjectConfigurationUnqualified(tree, projectName);\n\n const existingComponents = (config?.metadata as any)?.components ?? [];\n const alreadyAdded = existingComponents.filter(\n (c: any) => c.generator === info.id && c.name === componentName,\n );\n\n if (alreadyAdded.length === 0) {\n const componentMetadata: ComponentMetadata = {\n generator: info.id,\n path: componentPath,\n ...(componentName ? { name: componentName } : {}),\n ...additionalMetadata,\n };\n // Place metadata before targets for a stable serialized key order.\n const { targets, ...rest } = config;\n updateProjectConfiguration(tree, config.name, {\n ...rest,\n metadata: {\n ...config?.metadata,\n components: [...existingComponents, componentMetadata],\n } as any,\n ...(targets ? { targets } : {}),\n });\n }\n};\n\n/**\n * Merge a generator's own config into an `nx.json` `targetDefaults` value,\n * preserving whatever the workspace already had. `apply` receives the config to\n * layer onto and returns the merged config (e.g. `(base) => ({ cache: true,\n * ...base })`); it must be idempotent so re-running the generator is a no-op.\n *\n * Nx 23.1 widened each value to either a config object or an ordered array of\n * filtered entries. The plugin only contributes unfiltered (catch-all) config,\n * so the input's shape is preserved: an object (or unset) stays an object;\n * an array keeps the user's filtered entries and `apply` merges into its first\n * unfiltered entry, prepending one as the base if none exists (Nx layers later\n * matches on top, so our catch-all must stay first to not override a filter).\n */\nexport const mergeTargetDefault = (\n value: TargetDefaultValue | undefined,\n apply: (base: Partial<TargetConfiguration>) => Partial<TargetConfiguration>,\n): TargetDefaultValue => {\n if (!Array.isArray(value)) {\n return apply(value ?? {});\n }\n const catchAllIndex = value.findIndex((entry) => entry.filter === undefined);\n if (catchAllIndex === -1) {\n return [apply({}), ...value];\n }\n return value.map((entry, index) =>\n index === catchAllIndex ? apply(entry) : entry,\n );\n};\n\n/**\n * A single entry in an Nx `dependsOn` array.\n * Matches the shape accepted by Nx without requiring a devkit type import.\n */\nexport type TargetDependency =\n | string\n | {\n projects?: string | string[];\n target: string;\n params?: 'ignore' | 'forward';\n };\n\nconst targetDependencyEquals = (a: TargetDependency, b: TargetDependency) => {\n if (typeof a === 'string' || typeof b === 'string') {\n return a === b;\n }\n if (a.target !== b.target || a.params !== b.params) {\n return false;\n }\n const aProjects = Array.isArray(a.projects)\n ? a.projects\n : a.projects !== undefined\n ? [a.projects]\n : [];\n const bProjects = Array.isArray(b.projects)\n ? b.projects\n : b.projects !== undefined\n ? [b.projects]\n : [];\n if (aProjects.length !== bProjects.length) {\n return false;\n }\n return aProjects.every((p, i) => p === bProjects[i]);\n};\n\n// The order target properties are authored in. Nx preserves a target's\n// authored key order when it reads then rewrites an existing project.json,\n// except `options` and `configurations`, which it always moves to the end (in\n// that order). Keeping `options`/`configurations` last here therefore makes a\n// generator's first-run output byte-identical to subsequent runs (idempotency);\n// the remaining keys are ordered to read intuitively.\nconst NX_TARGET_KEY_ORDER = [\n 'executor',\n 'dependsOn',\n 'continuous',\n 'cache',\n 'inputs',\n 'outputs',\n 'metadata',\n 'defaultConfiguration',\n 'options',\n 'configurations',\n];\n\n/**\n * Reorder a target's keys to match Nx's own serialization order. Nx reorders\n * target properties when it rewrites an existing project.json, so applying the\n * same order when first authoring a target keeps generators idempotent.\n */\nexport const normalizeTargetKeyOrder = <T extends object>(target: T): T =>\n Object.fromEntries(\n Object.entries(target as Record<string, unknown>).sort(([a], [b]) => {\n const ai = NX_TARGET_KEY_ORDER.indexOf(a);\n const bi = NX_TARGET_KEY_ORDER.indexOf(b);\n return (\n (ai === -1 ? NX_TARGET_KEY_ORDER.length : ai) -\n (bi === -1 ? NX_TARGET_KEY_ORDER.length : bi)\n );\n }),\n ) as T;\n\n/**\n * Mutate the project to add the dependency to the target if not already present\n * Adds the target if not present.\n *\n * Accepts either a string target name (e.g. `'build'`) or a dependency config\n * object (e.g. `{ projects: ['foo'], target: 'dev' }`). Deduplicates\n * using deep equality so re-running a generator does not grow `dependsOn`.\n */\nexport const addDependencyToTargetIfNotPresent = (\n project: ProjectConfiguration,\n target: string,\n dependency: TargetDependency,\n) => {\n project.targets ??= {};\n project.targets[target] ??= {};\n project.targets[target].dependsOn ??= [];\n const dependsOn = project.targets[target].dependsOn;\n // Leave existing dependencies in place so re-running does not reorder them;\n // only append when the dependency is genuinely absent.\n if (!dependsOn.some((d) => targetDependencyEquals(d, dependency))) {\n dependsOn.push(dependency);\n }\n // Keep key order aligned with Nx's so first run matches subsequent runs.\n project.targets[target] = normalizeTargetKeyOrder(project.targets[target]);\n};\n\n/**\n * Register a component's `<name>-dev` target under the project-level `dev`\n * target, so `nx run <project>:dev` starts every component in the project.\n *\n * Component generators author their own continuous `<name>-dev` runner and call\n * this to aggregate it. Every component added to the project accumulates its\n * `<name>-dev` under `dev`. Nx keys tasks by `project:target`, so any\n * dependencies shared between components run exactly once.\n */\nexport const addComponentDevTarget = (\n targets: Record<string, ProjectConfiguration['targets'][string]>,\n componentDevTargetName: string,\n) => {\n targets['dev'] ??= { continuous: true, dependsOn: [] };\n const projectDev = targets['dev'];\n projectDev.continuous = true;\n projectDev.dependsOn ??= [];\n // Append in component-creation order; dedupe keeps re-runs idempotent.\n if (!projectDev.dependsOn.includes(componentDevTargetName)) {\n projectDev.dependsOn.push(componentDevTargetName);\n }\n targets['dev'] = normalizeTargetKeyOrder(projectDev);\n};\n"],"names":["getProjects","readJson","readProjectConfiguration","updateProjectConfiguration","path","PackageJson","type","NX_PLUGIN_MCP_PACKAGE_NAME","toSnakeCase","getNpmScope","getNpmScopePrefix","buildGeneratorInfoList","GENERATORS","resolve","dirname","listGenerators","includeHidden","filter","g","hidden","getGeneratorInfo","generatorFileName","dir","name","parse","resolvedFactoryPath","join","find","generatorInfo","getPackageVersion","version","isNxPluginForAwsWorkspace","tree","rootPackageJson","exists","undefined","nxPluginSelfDependency","nxPluginMcpDependency","readProjectConfigurationUnqualified","projectName","e","project","values","p","projectExists","addGeneratorMetadata","info","additionalMetadata","config","metadata","generator","id","JSON","stringify","targets","rest","addComponentGeneratorMetadata","componentPath","componentName","existingComponents","components","alreadyAdded","c","length","componentMetadata","mergeTargetDefault","value","apply","Array","isArray","catchAllIndex","findIndex","entry","map","index","targetDependencyEquals","a","b","target","params","aProjects","projects","bProjects","every","i","NX_TARGET_KEY_ORDER","normalizeTargetKeyOrder","Object","fromEntries","entries","sort","ai","indexOf","bi","addDependencyToTargetIfNotPresent","dependency","dependsOn","some","d","push","addComponentDevTarget","componentDevTargetName","continuous","projectDev","includes"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/nx.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n type ProjectConfiguration,\n readJson,\n readProjectConfiguration,\n type TargetConfiguration,\n type TargetDefaultValue,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport * as path from 'path';\nimport PackageJson from '../../package.json' with { type: 'json' };\nimport { NX_PLUGIN_MCP_PACKAGE_NAME } from './mcp';\nimport { toSnakeCase } from './names';\nimport { getNpmScope, getNpmScopePrefix } from './npm-scope';\n\nexport type { GeneratorInfo, NxGeneratorInfo } from './generators';\nexport { buildGeneratorInfoList } from './generators';\n\nimport { buildGeneratorInfoList, type GeneratorInfo } from './generators';\n\nconst GENERATORS = buildGeneratorInfoList(\n path.resolve(import.meta.dirname, '..', '..'),\n);\n\n/**\n * List Nx Plugin for AWS generators\n * @param includeHidden include hidden generators (default false)\n */\nexport const listGenerators = (includeHidden = false) =>\n GENERATORS.filter((g) => includeHidden || !g.hidden);\n\n/**\n * Return generator information. Call this from a generator method with import.meta.filename\n */\nexport const getGeneratorInfo = (generatorFileName: string): GeneratorInfo => {\n const { dir, name } = path.parse(path.resolve(generatorFileName));\n const resolvedFactoryPath = path.join(dir, name);\n return GENERATORS.find(\n (generatorInfo) =>\n generatorInfo.resolvedFactoryPath === resolvedFactoryPath,\n );\n};\n\nexport const getPackageVersion = () => {\n return PackageJson.version;\n};\n\n/**\n * True inside the plugin's own monorepo, where the plugin is the source rather\n * than a dependency.\n */\nexport const isNxPluginForAwsWorkspace = (tree: Tree): boolean => {\n const rootPackageJson = tree.exists('package.json')\n ? readJson(tree, 'package.json')\n : undefined;\n return rootPackageJson?.name === '@aws/nx-plugin-source';\n};\n\n/**\n * The `@aws/nx-plugin` devDependency entry for a workspace the plugin generates\n * into, keyed to the version the running generators come from. Empty inside the\n * plugin's own monorepo.\n */\nexport const nxPluginSelfDependency = (tree: Tree): Record<string, string> =>\n isNxPluginForAwsWorkspace(tree)\n ? {}\n : { [PackageJson.name]: `^${PackageJson.version}` };\n\n/**\n * The `@aws/nx-plugin-mcp` devDependency entry, keyed to the running generators'\n * version — the two packages are released in lockstep. Declaring it pins the MCP\n * server the vended config runs in the workspace's lockfile, so upgrading it\n * upgrades the server. Empty inside the plugin's own monorepo.\n */\nexport const nxPluginMcpDependency = (tree: Tree): Record<string, string> =>\n isNxPluginForAwsWorkspace(tree)\n ? {}\n : { [NX_PLUGIN_MCP_PACKAGE_NAME]: `^${PackageJson.version}` };\n\n/**\n * Read a project configuration where the project name may not be fully qualified (ie may omit the scope prefix)\n */\nexport const readProjectConfigurationUnqualified = (\n tree: Tree,\n projectName: string,\n) => {\n try {\n return readProjectConfiguration(tree, projectName);\n } catch (e) {\n // Attempt to find the project without the scope\n const project = [...getProjects(tree).values()].find(\n (p) =>\n p.name &&\n (p.name === `${getNpmScopePrefix(tree)}${projectName}` || // TypeScript fully-qualified name\n p.name === `${toSnakeCase(getNpmScope(tree))}.${projectName}`), // Python fully-qualified name\n );\n if (project) {\n return project;\n }\n throw e;\n }\n};\n\n/**\n * Returns whether a project with the given name already exists in the workspace.\n * The project name may be unqualified (ie may omit the scope prefix).\n */\nexport const projectExists = (tree: Tree, projectName: string): boolean => {\n try {\n readProjectConfigurationUnqualified(tree, projectName);\n return true;\n } catch {\n return false;\n }\n};\n\n/**\n * Add metadata about the generator that generated the project to the project.json\n */\nexport const addGeneratorMetadata = (\n tree: Tree,\n projectName: string,\n info: { id: string },\n additionalMetadata?: { [key: string]: any },\n) => {\n const config = readProjectConfigurationUnqualified(tree, projectName);\n const metadata = {\n ...config?.metadata,\n generator: info.id,\n ...additionalMetadata,\n };\n // Skip the write when nothing changed so re-running doesn't reserialize\n // project.json. metadata is plain JSON built in a fixed key order, so a\n // stringify comparison is exact here.\n if (JSON.stringify(config?.metadata) === JSON.stringify(metadata)) {\n return;\n }\n // Place metadata immediately before targets so the serialized key order is\n // identical whether or not metadata already existed (matching the order Nx\n // normalizes a read config to), keeping the change a pure metadata insert.\n const { targets, ...rest } = config;\n updateProjectConfiguration(tree, config.name, {\n ...rest,\n metadata: metadata as any,\n ...(targets ? { targets } : {}),\n });\n};\n\n/**\n * Represents a component entry in project metadata\n */\nexport interface ComponentMetadata {\n readonly generator: string;\n readonly name?: string;\n /**\n * What this entry wires up. For a connection that is the target — the thing\n * being connected to — paired with `sourcePath` below.\n */\n readonly path?: string;\n /**\n * The component the connection is made *from*, when both ends are components\n * of a project rather than whole projects.\n *\n * A connection records the project it lives on and the target it reaches, which\n * alone can't tell which of several components on that project is wired up.\n * Recorded as a path for the same reason `path` is: it identifies a component\n * within its project without depending on a name that may repeat.\n */\n readonly sourcePath?: string;\n [key: string]: any;\n}\n\n/**\n * Add metadata about the generator that generated the component to the project.json\n *\n * A connection between two components passes the source's path as\n * `additionalMetadata.sourcePath`, so the pair is identifiable rather than just\n * the two projects.\n */\nexport const addComponentGeneratorMetadata = (\n tree: Tree,\n projectName: string,\n info: { id: string },\n componentPath: string,\n componentName?: string,\n additionalMetadata?: { [key: string]: any },\n) => {\n const config = readProjectConfigurationUnqualified(tree, projectName);\n\n const existingComponents = (config?.metadata as any)?.components ?? [];\n const alreadyAdded = existingComponents.filter(\n (c: any) => c.generator === info.id && c.name === componentName,\n );\n\n if (alreadyAdded.length === 0) {\n const componentMetadata: ComponentMetadata = {\n generator: info.id,\n path: componentPath,\n ...(componentName ? { name: componentName } : {}),\n ...additionalMetadata,\n };\n // Place metadata before targets for a stable serialized key order.\n const { targets, ...rest } = config;\n updateProjectConfiguration(tree, config.name, {\n ...rest,\n metadata: {\n ...config?.metadata,\n components: [...existingComponents, componentMetadata],\n } as any,\n ...(targets ? { targets } : {}),\n });\n }\n};\n\n/**\n * Merge a generator's own config into an `nx.json` `targetDefaults` value,\n * preserving whatever the workspace already had. `apply` receives the config to\n * layer onto and returns the merged config (e.g. `(base) => ({ cache: true,\n * ...base })`); it must be idempotent so re-running the generator is a no-op.\n *\n * Nx 23.1 widened each value to either a config object or an ordered array of\n * filtered entries. The plugin only contributes unfiltered (catch-all) config,\n * so the input's shape is preserved: an object (or unset) stays an object;\n * an array keeps the user's filtered entries and `apply` merges into its first\n * unfiltered entry, prepending one as the base if none exists (Nx layers later\n * matches on top, so our catch-all must stay first to not override a filter).\n */\nexport const mergeTargetDefault = (\n value: TargetDefaultValue | undefined,\n apply: (base: Partial<TargetConfiguration>) => Partial<TargetConfiguration>,\n): TargetDefaultValue => {\n if (!Array.isArray(value)) {\n return apply(value ?? {});\n }\n const catchAllIndex = value.findIndex((entry) => entry.filter === undefined);\n if (catchAllIndex === -1) {\n return [apply({}), ...value];\n }\n return value.map((entry, index) =>\n index === catchAllIndex ? apply(entry) : entry,\n );\n};\n\n/**\n * A single entry in an Nx `dependsOn` array.\n * Matches the shape accepted by Nx without requiring a devkit type import.\n */\nexport type TargetDependency =\n | string\n | {\n projects?: string | string[];\n target: string;\n params?: 'ignore' | 'forward';\n };\n\nconst targetDependencyEquals = (a: TargetDependency, b: TargetDependency) => {\n if (typeof a === 'string' || typeof b === 'string') {\n return a === b;\n }\n if (a.target !== b.target || a.params !== b.params) {\n return false;\n }\n const aProjects = Array.isArray(a.projects)\n ? a.projects\n : a.projects !== undefined\n ? [a.projects]\n : [];\n const bProjects = Array.isArray(b.projects)\n ? b.projects\n : b.projects !== undefined\n ? [b.projects]\n : [];\n if (aProjects.length !== bProjects.length) {\n return false;\n }\n return aProjects.every((p, i) => p === bProjects[i]);\n};\n\n// The order target properties are authored in. Nx preserves a target's\n// authored key order when it reads then rewrites an existing project.json,\n// except `options` and `configurations`, which it always moves to the end (in\n// that order). Keeping `options`/`configurations` last here therefore makes a\n// generator's first-run output byte-identical to subsequent runs (idempotency);\n// the remaining keys are ordered to read intuitively.\nconst NX_TARGET_KEY_ORDER = [\n 'executor',\n 'dependsOn',\n 'continuous',\n 'cache',\n 'inputs',\n 'outputs',\n 'metadata',\n 'defaultConfiguration',\n 'options',\n 'configurations',\n];\n\n/**\n * Reorder a target's keys to match Nx's own serialization order. Nx reorders\n * target properties when it rewrites an existing project.json, so applying the\n * same order when first authoring a target keeps generators idempotent.\n */\nexport const normalizeTargetKeyOrder = <T extends object>(target: T): T =>\n Object.fromEntries(\n Object.entries(target as Record<string, unknown>).sort(([a], [b]) => {\n const ai = NX_TARGET_KEY_ORDER.indexOf(a);\n const bi = NX_TARGET_KEY_ORDER.indexOf(b);\n return (\n (ai === -1 ? NX_TARGET_KEY_ORDER.length : ai) -\n (bi === -1 ? NX_TARGET_KEY_ORDER.length : bi)\n );\n }),\n ) as T;\n\n/**\n * Mutate the project to add the dependency to the target if not already present\n * Adds the target if not present.\n *\n * Accepts either a string target name (e.g. `'build'`) or a dependency config\n * object (e.g. `{ projects: ['foo'], target: 'dev' }`). Deduplicates\n * using deep equality so re-running a generator does not grow `dependsOn`.\n */\nexport const addDependencyToTargetIfNotPresent = (\n project: ProjectConfiguration,\n target: string,\n dependency: TargetDependency,\n) => {\n project.targets ??= {};\n project.targets[target] ??= {};\n project.targets[target].dependsOn ??= [];\n const dependsOn = project.targets[target].dependsOn;\n // Leave existing dependencies in place so re-running does not reorder them;\n // only append when the dependency is genuinely absent.\n if (!dependsOn.some((d) => targetDependencyEquals(d, dependency))) {\n dependsOn.push(dependency);\n }\n // Keep key order aligned with Nx's so first run matches subsequent runs.\n project.targets[target] = normalizeTargetKeyOrder(project.targets[target]);\n};\n\n/**\n * Register a component's `<name>-dev` target under the project-level `dev`\n * target, so `nx run <project>:dev` starts every component in the project.\n *\n * Component generators author their own continuous `<name>-dev` runner and call\n * this to aggregate it. Every component added to the project accumulates its\n * `<name>-dev` under `dev`. Nx keys tasks by `project:target`, so any\n * dependencies shared between components run exactly once.\n */\nexport const addComponentDevTarget = (\n targets: Record<string, ProjectConfiguration['targets'][string]>,\n componentDevTargetName: string,\n) => {\n targets['dev'] ??= { continuous: true, dependsOn: [] };\n const projectDev = targets['dev'];\n projectDev.continuous = true;\n projectDev.dependsOn ??= [];\n // Append in component-creation order; dedupe keeps re-runs idempotent.\n if (!projectDev.dependsOn.includes(componentDevTargetName)) {\n projectDev.dependsOn.push(componentDevTargetName);\n }\n targets['dev'] = normalizeTargetKeyOrder(projectDev);\n};\n"],"names":["getProjects","readJson","readProjectConfiguration","updateProjectConfiguration","path","PackageJson","type","NX_PLUGIN_MCP_PACKAGE_NAME","toSnakeCase","getNpmScope","getNpmScopePrefix","buildGeneratorInfoList","GENERATORS","resolve","dirname","listGenerators","includeHidden","filter","g","hidden","getGeneratorInfo","generatorFileName","dir","name","parse","resolvedFactoryPath","join","find","generatorInfo","getPackageVersion","version","isNxPluginForAwsWorkspace","tree","rootPackageJson","exists","undefined","nxPluginSelfDependency","nxPluginMcpDependency","readProjectConfigurationUnqualified","projectName","e","project","values","p","projectExists","addGeneratorMetadata","info","additionalMetadata","config","metadata","generator","id","JSON","stringify","targets","rest","addComponentGeneratorMetadata","componentPath","componentName","existingComponents","components","alreadyAdded","c","length","componentMetadata","mergeTargetDefault","value","apply","Array","isArray","catchAllIndex","findIndex","entry","map","index","targetDependencyEquals","a","b","target","params","aProjects","projects","bProjects","every","i","NX_TARGET_KEY_ORDER","normalizeTargetKeyOrder","Object","fromEntries","entries","sort","ai","indexOf","bi","addDependencyToTargetIfNotPresent","dependency","dependsOn","some","d","push","addComponentDevTarget","componentDevTargetName","continuous","projectDev","includes"],"mappings":"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"}
package/src/utils/py.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import { type Tree } from '@nx/devkit';
2
+ import type { DeclaredPy, DependencyDeclaration } from './declared-dependencies';
2
3
  import { type IPyDepVersion } from './versions';
3
4
  /**
4
5
  * Add dependencies to a pyproject.toml file
5
6
  */
6
- export declare const addDependenciesToPyProjectToml: (tree: Tree, projectRoot: string, deps: IPyDepVersion[]) => void;
7
- export declare const addDependenciesToDependencyGroupInPyProjectToml: (tree: Tree, projectRoot: string, group: string, deps: IPyDepVersion[]) => void;
7
+ export declare const addDependenciesToPyProjectToml: <const D extends DependencyDeclaration>(tree: Tree, projectRoot: string, declaration: D, deps: readonly DeclaredPy<D>[]) => void;
8
+ export declare const addDependenciesToDependencyGroupInPyProjectToml: <const D extends DependencyDeclaration>(tree: Tree, projectRoot: string, group: string, declaration: D, deps: readonly DeclaredPy<D>[]) => void;
8
9
  export interface UvxWithDep {
9
10
  dep: string;
10
11
  version: string;
package/src/utils/py.js CHANGED
@@ -6,7 +6,7 @@ import { joinPathFragments } from "@nx/devkit";
6
6
  import { parsePipRequirementsLine } from "pip-requirements-js";
7
7
  import { normalizeDistributionName } from "./names.js";
8
8
  import { readToml, updateToml } from "./toml.js";
9
- import { withPyVersions } from "./versions.js";
9
+ import { PY_VERSIONS, withPyVersions } from "./versions.js";
10
10
  // Dedup key that distinguishes bare packages from the same package with
11
11
  // extras (e.g. `foo` vs `foo[bar]`), so adding a bare dep doesn't drop a
12
12
  // previously-added variant with extras.
@@ -20,11 +20,11 @@ const depKey = (dep)=>{
20
20
  ].sort().join(',');
21
21
  return extras ? `${parsed.name}[${extras}]` : parsed.name;
22
22
  };
23
- const mergeDeps = (existing, deps)=>{
23
+ const mergeDeps = (declaration, existing, deps)=>{
24
24
  // Update deps in place by key so re-running does not reorder the list:
25
25
  // existing deps keep their position (with their version refreshed), and only
26
26
  // genuinely-new deps are appended.
27
- const incoming = new Map(withPyVersions(deps).map((d)=>[
27
+ const incoming = new Map(withPyVersions(declaration, deps).map((d)=>[
28
28
  depKey(d),
29
29
  d
30
30
  ]));
@@ -39,16 +39,16 @@ const mergeDeps = (existing, deps)=>{
39
39
  };
40
40
  /**
41
41
  * Add dependencies to a pyproject.toml file
42
- */ export const addDependenciesToPyProjectToml = (tree, projectRoot, deps)=>{
42
+ */ export const addDependenciesToPyProjectToml = (tree, projectRoot, declaration, deps)=>{
43
43
  const projectToml = parse(tree.read(joinPathFragments(projectRoot, 'pyproject.toml'), 'utf8'));
44
- projectToml.project.dependencies = mergeDeps(projectToml.project?.dependencies, deps);
44
+ projectToml.project.dependencies = mergeDeps(declaration, projectToml.project?.dependencies, deps);
45
45
  tree.write(joinPathFragments(projectRoot, 'pyproject.toml'), stringify(projectToml));
46
46
  };
47
- export const addDependenciesToDependencyGroupInPyProjectToml = (tree, projectRoot, group, deps)=>{
47
+ export const addDependenciesToDependencyGroupInPyProjectToml = (tree, projectRoot, group, declaration, deps)=>{
48
48
  const projectToml = parse(tree.read(joinPathFragments(projectRoot, 'pyproject.toml'), 'utf8'));
49
49
  projectToml['dependency-groups'] = {
50
50
  ...projectToml['dependency-groups'],
51
- [group]: mergeDeps(projectToml['dependency-groups']?.[group], deps)
51
+ [group]: mergeDeps(declaration, projectToml['dependency-groups']?.[group], deps)
52
52
  };
53
53
  tree.write(joinPathFragments(projectRoot, 'pyproject.toml'), stringify(projectToml));
54
54
  };
@@ -57,9 +57,9 @@ export const addDependenciesToDependencyGroupInPyProjectToml = (tree, projectRoo
57
57
  * Pins the version to the one specified in versions.ts
58
58
  * Optionally specify withDeps to render uvx --with dep==version
59
59
  */ export const uvxCommand = (dep, args, withDeps)=>{
60
- return `uvx --from ${withPyVersions([
61
- dep
62
- ])[0]} ${withDeps ? `${withDeps.map(({ dep, version, specifier })=>`--with ${dep}${specifier ?? '=='}${version}`).join(' ')} ` : ''}${dep}${args ? ` ${args}` : ''}`;
60
+ // Pins the tool for a one-off invocation; nothing is added to a manifest, so
61
+ // this needs no declaration.
62
+ return `uvx --from ${dep}${PY_VERSIONS[dep]} ${withDeps ? `${withDeps.map(({ dep, version, specifier })=>`--with ${dep}${specifier ?? '=='}${version}`).join(' ')} ` : ''}${dep}${args ? ` ${args}` : ''}`;
63
63
  };
64
64
  /**
65
65
  * Resolve the PEP 503 distribution name of a Python project from its
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/py.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { parse, stringify } from '@iarna/toml';\nimport { joinPathFragments, type Tree } from '@nx/devkit';\nimport { parsePipRequirementsLine } from 'pip-requirements-js';\nimport { normalizeDistributionName } from './names';\nimport type { UVPyprojectToml } from './nxlv-python';\nimport { readToml, updateToml } from './toml';\nimport { type IPyDepVersion, withPyVersions } from './versions';\n\n// Dedup key that distinguishes bare packages from the same package with\n// extras (e.g. `foo` vs `foo[bar]`), so adding a bare dep doesn't drop a\n// previously-added variant with extras.\nconst depKey = (dep: string): string => {\n const parsed = parsePipRequirementsLine(dep);\n if (parsed?.type !== 'ProjectName') {\n return dep;\n }\n const extras = [...(parsed.extras ?? [])].sort().join(',');\n return extras ? `${parsed.name}[${extras}]` : parsed.name;\n};\n\nconst mergeDeps = (\n existing: readonly string[] | undefined,\n deps: IPyDepVersion[],\n): string[] => {\n // Update deps in place by key so re-running does not reorder the list:\n // existing deps keep their position (with their version refreshed), and only\n // genuinely-new deps are appended.\n const incoming = new Map(withPyVersions(deps).map((d) => [depKey(d), d]));\n const merged = (existing ?? []).map(\n (dep) => incoming.get(depKey(dep)) ?? dep,\n );\n const existingKeys = new Set((existing ?? []).map(depKey));\n for (const [key, dep] of incoming) {\n if (!existingKeys.has(key)) {\n merged.push(dep);\n }\n }\n return merged;\n};\n\n/**\n * Add dependencies to a pyproject.toml file\n */\nexport const addDependenciesToPyProjectToml = (\n tree: Tree,\n projectRoot: string,\n deps: IPyDepVersion[],\n) => {\n const projectToml = parse(\n tree.read(joinPathFragments(projectRoot, 'pyproject.toml'), 'utf8'),\n ) as UVPyprojectToml;\n projectToml.project.dependencies = mergeDeps(\n projectToml.project?.dependencies,\n deps,\n );\n tree.write(\n joinPathFragments(projectRoot, 'pyproject.toml'),\n stringify(projectToml),\n );\n};\n\nexport const addDependenciesToDependencyGroupInPyProjectToml = (\n tree: Tree,\n projectRoot: string,\n group: string,\n deps: IPyDepVersion[],\n) => {\n const projectToml = parse(\n tree.read(joinPathFragments(projectRoot, 'pyproject.toml'), 'utf8'),\n ) as UVPyprojectToml;\n projectToml['dependency-groups'] = {\n ...projectToml['dependency-groups'],\n [group]: mergeDeps(projectToml['dependency-groups']?.[group], deps),\n };\n tree.write(\n joinPathFragments(projectRoot, 'pyproject.toml'),\n stringify(projectToml),\n );\n};\n\nexport interface UvxWithDep {\n dep: string;\n version: string;\n specifier?: string;\n}\n\n/**\n * Render a uvx command for a given dependency\n * Pins the version to the one specified in versions.ts\n * Optionally specify withDeps to render uvx --with dep==version\n */\nexport const uvxCommand = (\n dep: IPyDepVersion,\n args?: string,\n withDeps?: UvxWithDep[],\n): string => {\n return `uvx --from ${withPyVersions([dep])[0]} ${\n withDeps\n ? `${withDeps\n .map(\n ({ dep, version, specifier }) =>\n `--with ${dep}${specifier ?? '=='}${version}`,\n )\n .join(' ')} `\n : ''\n }${dep}${args ? ` ${args}` : ''}`;\n};\n\n/**\n * Resolve the PEP 503 distribution name of a Python project from its\n * `pyproject.toml` `[project].name`, falling back to normalising the supplied\n * Nx project id when the project has no readable pyproject yet.\n *\n * This is the authoritative name uv writes into `uv.lock`, so it is the value\n * that must appear in a dependent's `[project].dependencies` /\n * `[tool.uv.sources]` for `@nxlv/python` to infer the workspace dependency\n * edge. Always normalised so the result is a valid distribution name even if\n * an older project still carries a dotted `[project].name`.\n */\nconst getPyDistributionName = (\n tree: Tree,\n project: { name?: string; root: string },\n): string => {\n const pyprojectPath = joinPathFragments(project.root, 'pyproject.toml');\n const projectName = tree.exists(pyprojectPath)\n ? (readToml(tree, pyprojectPath) as unknown as UVPyprojectToml).project\n ?.name\n : undefined;\n return normalizeDistributionName(projectName ?? project.name ?? '');\n};\n\n/**\n * Add a workspace dependency from one Python project to another.\n * Adds the dependency to [project].dependencies and [tool.uv.sources].\n *\n * Both projects are passed as Nx project configurations (not names): the\n * dependency's PEP 503 distribution name is derived from its own\n * `pyproject.toml` here, so callers cannot accidentally pass the dotted Nx id\n * (which @nxlv/python splits on `.` and drops, losing the project-graph edge).\n * This is the single entry point all generators use to wire a Python workspace\n * dependency.\n */\nexport const addWorkspaceDependencyToPyProject = (\n tree: Tree,\n dependentProject: { name?: string; root: string },\n dependencyProject: { name?: string; root: string },\n): void => {\n const pyprojectPath = joinPathFragments(\n dependentProject.root,\n 'pyproject.toml',\n );\n if (!tree.exists(pyprojectPath)) {\n return;\n }\n\n const distributionName = getPyDistributionName(tree, dependencyProject);\n\n updateToml(tree, pyprojectPath, (toml: UVPyprojectToml) => {\n // Add to [project].dependencies if not already present\n const deps = toml.project?.dependencies ?? [];\n if (\n !deps.some(\n (d) =>\n d === distributionName ||\n d.startsWith(`${distributionName}>=`) ||\n d.startsWith(`${distributionName}==`),\n )\n ) {\n toml.project.dependencies = [...deps, distributionName];\n }\n\n // Add to [tool.uv.sources] with workspace = true\n toml.tool = toml.tool ?? {};\n (toml.tool as any).uv = (toml.tool as any).uv ?? {};\n (toml.tool as any).uv.sources = (toml.tool as any).uv.sources ?? {};\n (toml.tool as any).uv.sources[distributionName] = {\n workspace: true,\n };\n\n return toml;\n });\n};\n"],"names":["parse","stringify","joinPathFragments","parsePipRequirementsLine","normalizeDistributionName","readToml","updateToml","withPyVersions","depKey","dep","parsed","type","extras","sort","join","name","mergeDeps","existing","deps","incoming","Map","map","d","merged","get","existingKeys","Set","key","has","push","addDependenciesToPyProjectToml","tree","projectRoot","projectToml","read","project","dependencies","write","addDependenciesToDependencyGroupInPyProjectToml","group","uvxCommand","args","withDeps","version","specifier","getPyDistributionName","pyprojectPath","root","projectName","exists","undefined","addWorkspaceDependencyToPyProject","dependentProject","dependencyProject","distributionName","toml","some","startsWith","tool","uv","sources","workspace"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/py.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { parse, stringify } from '@iarna/toml';\nimport { joinPathFragments, type Tree } from '@nx/devkit';\nimport { parsePipRequirementsLine } from 'pip-requirements-js';\nimport type {\n DeclaredPy,\n DependencyDeclaration,\n} from './declared-dependencies';\nimport { normalizeDistributionName } from './names';\nimport type { UVPyprojectToml } from './nxlv-python';\nimport { readToml, updateToml } from './toml';\nimport { type IPyDepVersion, PY_VERSIONS, withPyVersions } from './versions';\n\n// Dedup key that distinguishes bare packages from the same package with\n// extras (e.g. `foo` vs `foo[bar]`), so adding a bare dep doesn't drop a\n// previously-added variant with extras.\nconst depKey = (dep: string): string => {\n const parsed = parsePipRequirementsLine(dep);\n if (parsed?.type !== 'ProjectName') {\n return dep;\n }\n const extras = [...(parsed.extras ?? [])].sort().join(',');\n return extras ? `${parsed.name}[${extras}]` : parsed.name;\n};\n\nconst mergeDeps = (\n declaration: DependencyDeclaration,\n existing: readonly string[] | undefined,\n deps: readonly IPyDepVersion[],\n): string[] => {\n // Update deps in place by key so re-running does not reorder the list:\n // existing deps keep their position (with their version refreshed), and only\n // genuinely-new deps are appended.\n const incoming = new Map(\n withPyVersions(declaration, deps).map((d) => [depKey(d), d]),\n );\n const merged = (existing ?? []).map(\n (dep) => incoming.get(depKey(dep)) ?? dep,\n );\n const existingKeys = new Set((existing ?? []).map(depKey));\n for (const [key, dep] of incoming) {\n if (!existingKeys.has(key)) {\n merged.push(dep);\n }\n }\n return merged;\n};\n\n/**\n * Add dependencies to a pyproject.toml file\n */\nexport const addDependenciesToPyProjectToml = <\n const D extends DependencyDeclaration,\n>(\n tree: Tree,\n projectRoot: string,\n declaration: D,\n deps: readonly DeclaredPy<D>[],\n) => {\n const projectToml = parse(\n tree.read(joinPathFragments(projectRoot, 'pyproject.toml'), 'utf8'),\n ) as UVPyprojectToml;\n projectToml.project.dependencies = mergeDeps(\n declaration,\n projectToml.project?.dependencies,\n deps,\n );\n tree.write(\n joinPathFragments(projectRoot, 'pyproject.toml'),\n stringify(projectToml),\n );\n};\n\nexport const addDependenciesToDependencyGroupInPyProjectToml = <\n const D extends DependencyDeclaration,\n>(\n tree: Tree,\n projectRoot: string,\n group: string,\n declaration: D,\n deps: readonly DeclaredPy<D>[],\n) => {\n const projectToml = parse(\n tree.read(joinPathFragments(projectRoot, 'pyproject.toml'), 'utf8'),\n ) as UVPyprojectToml;\n projectToml['dependency-groups'] = {\n ...projectToml['dependency-groups'],\n [group]: mergeDeps(\n declaration,\n projectToml['dependency-groups']?.[group],\n deps,\n ),\n };\n tree.write(\n joinPathFragments(projectRoot, 'pyproject.toml'),\n stringify(projectToml),\n );\n};\n\nexport interface UvxWithDep {\n dep: string;\n version: string;\n specifier?: string;\n}\n\n/**\n * Render a uvx command for a given dependency\n * Pins the version to the one specified in versions.ts\n * Optionally specify withDeps to render uvx --with dep==version\n */\nexport const uvxCommand = (\n dep: IPyDepVersion,\n args?: string,\n withDeps?: UvxWithDep[],\n): string => {\n // Pins the tool for a one-off invocation; nothing is added to a manifest, so\n // this needs no declaration.\n return `uvx --from ${dep}${PY_VERSIONS[dep]} ${\n withDeps\n ? `${withDeps\n .map(\n ({ dep, version, specifier }) =>\n `--with ${dep}${specifier ?? '=='}${version}`,\n )\n .join(' ')} `\n : ''\n }${dep}${args ? ` ${args}` : ''}`;\n};\n\n/**\n * Resolve the PEP 503 distribution name of a Python project from its\n * `pyproject.toml` `[project].name`, falling back to normalising the supplied\n * Nx project id when the project has no readable pyproject yet.\n *\n * This is the authoritative name uv writes into `uv.lock`, so it is the value\n * that must appear in a dependent's `[project].dependencies` /\n * `[tool.uv.sources]` for `@nxlv/python` to infer the workspace dependency\n * edge. Always normalised so the result is a valid distribution name even if\n * an older project still carries a dotted `[project].name`.\n */\nconst getPyDistributionName = (\n tree: Tree,\n project: { name?: string; root: string },\n): string => {\n const pyprojectPath = joinPathFragments(project.root, 'pyproject.toml');\n const projectName = tree.exists(pyprojectPath)\n ? (readToml(tree, pyprojectPath) as unknown as UVPyprojectToml).project\n ?.name\n : undefined;\n return normalizeDistributionName(projectName ?? project.name ?? '');\n};\n\n/**\n * Add a workspace dependency from one Python project to another.\n * Adds the dependency to [project].dependencies and [tool.uv.sources].\n *\n * Both projects are passed as Nx project configurations (not names): the\n * dependency's PEP 503 distribution name is derived from its own\n * `pyproject.toml` here, so callers cannot accidentally pass the dotted Nx id\n * (which @nxlv/python splits on `.` and drops, losing the project-graph edge).\n * This is the single entry point all generators use to wire a Python workspace\n * dependency.\n */\nexport const addWorkspaceDependencyToPyProject = (\n tree: Tree,\n dependentProject: { name?: string; root: string },\n dependencyProject: { name?: string; root: string },\n): void => {\n const pyprojectPath = joinPathFragments(\n dependentProject.root,\n 'pyproject.toml',\n );\n if (!tree.exists(pyprojectPath)) {\n return;\n }\n\n const distributionName = getPyDistributionName(tree, dependencyProject);\n\n updateToml(tree, pyprojectPath, (toml: UVPyprojectToml) => {\n // Add to [project].dependencies if not already present\n const deps = toml.project?.dependencies ?? [];\n if (\n !deps.some(\n (d) =>\n d === distributionName ||\n d.startsWith(`${distributionName}>=`) ||\n d.startsWith(`${distributionName}==`),\n )\n ) {\n toml.project.dependencies = [...deps, distributionName];\n }\n\n // Add to [tool.uv.sources] with workspace = true\n toml.tool = toml.tool ?? {};\n (toml.tool as any).uv = (toml.tool as any).uv ?? {};\n (toml.tool as any).uv.sources = (toml.tool as any).uv.sources ?? {};\n (toml.tool as any).uv.sources[distributionName] = {\n workspace: true,\n };\n\n return toml;\n });\n};\n"],"names":["parse","stringify","joinPathFragments","parsePipRequirementsLine","normalizeDistributionName","readToml","updateToml","PY_VERSIONS","withPyVersions","depKey","dep","parsed","type","extras","sort","join","name","mergeDeps","declaration","existing","deps","incoming","Map","map","d","merged","get","existingKeys","Set","key","has","push","addDependenciesToPyProjectToml","tree","projectRoot","projectToml","read","project","dependencies","write","addDependenciesToDependencyGroupInPyProjectToml","group","uvxCommand","args","withDeps","version","specifier","getPyDistributionName","pyprojectPath","root","projectName","exists","undefined","addWorkspaceDependencyToPyProject","dependentProject","dependencyProject","distributionName","toml","some","startsWith","tool","uv","sources","workspace"],"mappings":"AAAA;;;CAGC,GACD,SAASA,KAAK,EAAEC,SAAS,QAAQ,cAAc;AAC/C,SAASC,iBAAiB,QAAmB,aAAa;AAC1D,SAASC,wBAAwB,QAAQ,sBAAsB;AAK/D,SAASC,yBAAyB,QAAQ,aAAU;AAEpD,SAASC,QAAQ,EAAEC,UAAU,QAAQ,YAAS;AAC9C,SAA6BC,WAAW,EAAEC,cAAc,QAAQ,gBAAa;AAE7E,wEAAwE;AACxE,yEAAyE;AACzE,wCAAwC;AACxC,MAAMC,SAAS,CAACC;IACd,MAAMC,SAASR,yBAAyBO;IACxC,IAAIC,QAAQC,SAAS,eAAe;QAClC,OAAOF;IACT;IACA,MAAMG,SAAS;WAAKF,OAAOE,MAAM,IAAI,EAAE;KAAE,CAACC,IAAI,GAAGC,IAAI,CAAC;IACtD,OAAOF,SAAS,GAAGF,OAAOK,IAAI,CAAC,CAAC,EAAEH,OAAO,CAAC,CAAC,GAAGF,OAAOK,IAAI;AAC3D;AAEA,MAAMC,YAAY,CAChBC,aACAC,UACAC;IAEA,uEAAuE;IACvE,6EAA6E;IAC7E,mCAAmC;IACnC,MAAMC,WAAW,IAAIC,IACnBd,eAAeU,aAAaE,MAAMG,GAAG,CAAC,CAACC,IAAM;YAACf,OAAOe;YAAIA;SAAE;IAE7D,MAAMC,SAAS,AAACN,CAAAA,YAAY,EAAE,AAAD,EAAGI,GAAG,CACjC,CAACb,MAAQW,SAASK,GAAG,CAACjB,OAAOC,SAASA;IAExC,MAAMiB,eAAe,IAAIC,IAAI,AAACT,CAAAA,YAAY,EAAE,AAAD,EAAGI,GAAG,CAACd;IAClD,KAAK,MAAM,CAACoB,KAAKnB,IAAI,IAAIW,SAAU;QACjC,IAAI,CAACM,aAAaG,GAAG,CAACD,MAAM;YAC1BJ,OAAOM,IAAI,CAACrB;QACd;IACF;IACA,OAAOe;AACT;AAEA;;CAEC,GACD,OAAO,MAAMO,iCAAiC,CAG5CC,MACAC,aACAhB,aACAE;IAEA,MAAMe,cAAcnC,MAClBiC,KAAKG,IAAI,CAAClC,kBAAkBgC,aAAa,mBAAmB;IAE9DC,YAAYE,OAAO,CAACC,YAAY,GAAGrB,UACjCC,aACAiB,YAAYE,OAAO,EAAEC,cACrBlB;IAEFa,KAAKM,KAAK,CACRrC,kBAAkBgC,aAAa,mBAC/BjC,UAAUkC;AAEd,EAAE;AAEF,OAAO,MAAMK,kDAAkD,CAG7DP,MACAC,aACAO,OACAvB,aACAE;IAEA,MAAMe,cAAcnC,MAClBiC,KAAKG,IAAI,CAAClC,kBAAkBgC,aAAa,mBAAmB;IAE9DC,WAAW,CAAC,oBAAoB,GAAG;QACjC,GAAGA,WAAW,CAAC,oBAAoB;QACnC,CAACM,MAAM,EAAExB,UACPC,aACAiB,WAAW,CAAC,oBAAoB,EAAE,CAACM,MAAM,EACzCrB;IAEJ;IACAa,KAAKM,KAAK,CACRrC,kBAAkBgC,aAAa,mBAC/BjC,UAAUkC;AAEd,EAAE;AAQF;;;;CAIC,GACD,OAAO,MAAMO,aAAa,CACxBhC,KACAiC,MACAC;IAEA,6EAA6E;IAC7E,6BAA6B;IAC7B,OAAO,CAAC,WAAW,EAAElC,MAAMH,WAAW,CAACG,IAAI,CAAC,CAAC,EAC3CkC,WACI,GAAGA,SACArB,GAAG,CACF,CAAC,EAAEb,GAAG,EAAEmC,OAAO,EAAEC,SAAS,EAAE,GAC1B,CAAC,OAAO,EAAEpC,MAAMoC,aAAa,OAAOD,SAAS,EAEhD9B,IAAI,CAAC,KAAK,CAAC,CAAC,GACf,KACHL,MAAMiC,OAAO,CAAC,CAAC,EAAEA,MAAM,GAAG,IAAI;AACnC,EAAE;AAEF;;;;;;;;;;CAUC,GACD,MAAMI,wBAAwB,CAC5Bd,MACAI;IAEA,MAAMW,gBAAgB9C,kBAAkBmC,QAAQY,IAAI,EAAE;IACtD,MAAMC,cAAcjB,KAAKkB,MAAM,CAACH,iBAC5B,AAAC3C,SAAS4B,MAAMe,eAA8CX,OAAO,EACjErB,OACJoC;IACJ,OAAOhD,0BAA0B8C,eAAeb,QAAQrB,IAAI,IAAI;AAClE;AAEA;;;;;;;;;;CAUC,GACD,OAAO,MAAMqC,oCAAoC,CAC/CpB,MACAqB,kBACAC;IAEA,MAAMP,gBAAgB9C,kBACpBoD,iBAAiBL,IAAI,EACrB;IAEF,IAAI,CAAChB,KAAKkB,MAAM,CAACH,gBAAgB;QAC/B;IACF;IAEA,MAAMQ,mBAAmBT,sBAAsBd,MAAMsB;IAErDjD,WAAW2B,MAAMe,eAAe,CAACS;QAC/B,uDAAuD;QACvD,MAAMrC,OAAOqC,KAAKpB,OAAO,EAAEC,gBAAgB,EAAE;QAC7C,IACE,CAAClB,KAAKsC,IAAI,CACR,CAAClC,IACCA,MAAMgC,oBACNhC,EAAEmC,UAAU,CAAC,GAAGH,iBAAiB,EAAE,CAAC,KACpChC,EAAEmC,UAAU,CAAC,GAAGH,iBAAiB,EAAE,CAAC,IAExC;YACAC,KAAKpB,OAAO,CAACC,YAAY,GAAG;mBAAIlB;gBAAMoC;aAAiB;QACzD;QAEA,iDAAiD;QACjDC,KAAKG,IAAI,GAAGH,KAAKG,IAAI,IAAI,CAAC;QACzBH,KAAKG,IAAI,CAASC,EAAE,GAAG,AAACJ,KAAKG,IAAI,CAASC,EAAE,IAAI,CAAC;QACjDJ,KAAKG,IAAI,CAASC,EAAE,CAACC,OAAO,GAAG,AAACL,KAAKG,IAAI,CAASC,EAAE,CAACC,OAAO,IAAI,CAAC;QACjEL,KAAKG,IAAI,CAASC,EAAE,CAACC,OAAO,CAACN,iBAAiB,GAAG;YAChDO,WAAW;QACb;QAEA,OAAON;IACT;AACF,EAAE"}