@aws/nx-plugin 1.0.0-rc.93 → 1.0.0-rc.95

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 (150) hide show
  1. package/migrations.json +36 -1
  2. package/package.json +1 -1
  3. package/src/agentcore-harness/generator.d.ts +1 -1
  4. package/src/infra/app/__snapshots__/generator.spec.ts.snap +5 -5
  5. package/src/infra/app/generator.d.ts +1 -1
  6. package/src/infra/app/generator.js +5 -3
  7. package/src/infra/app/generator.js.map +1 -1
  8. package/src/init/generator.d.ts +1 -1
  9. package/src/migrations/latest/agent-connection-pin-strands-peers/metadata.json +3 -0
  10. package/src/migrations/latest/agent-connection-pin-strands-peers/migration.d.ts +18 -0
  11. package/src/migrations/latest/agent-connection-pin-strands-peers/migration.js +38 -0
  12. package/src/migrations/latest/agent-connection-pin-strands-peers/migration.js.map +1 -0
  13. package/src/migrations/latest/agent-core-vendor-target/metadata.json +3 -0
  14. package/src/migrations/latest/agent-core-vendor-target/migration.d.ts +6 -0
  15. package/src/migrations/latest/agent-core-vendor-target/migration.js +98 -0
  16. package/src/migrations/latest/agent-core-vendor-target/migration.js.map +1 -0
  17. package/src/migrations/latest/ignore-package-manager-temp-files/metadata.json +3 -0
  18. package/src/migrations/latest/ignore-package-manager-temp-files/migration.d.ts +12 -0
  19. package/src/migrations/latest/ignore-package-manager-temp-files/migration.js +25 -0
  20. package/src/migrations/latest/ignore-package-manager-temp-files/migration.js.map +1 -0
  21. package/src/migrations/latest/infra-deploy-express-mode/metadata.json +3 -0
  22. package/src/migrations/latest/infra-deploy-express-mode/migration.d.ts +6 -0
  23. package/src/migrations/latest/infra-deploy-express-mode/migration.js +83 -0
  24. package/src/migrations/latest/infra-deploy-express-mode/migration.js.map +1 -0
  25. package/src/migrations/latest/rolldown-config-bundle-transient/metadata.json +3 -0
  26. package/src/migrations/latest/rolldown-config-bundle-transient/migration.d.ts +6 -0
  27. package/src/migrations/latest/rolldown-config-bundle-transient/migration.js +80 -0
  28. package/src/migrations/latest/rolldown-config-bundle-transient/migration.js.map +1 -0
  29. package/src/migrations/latest/shadcn-package-imports-exports/metadata.json +3 -0
  30. package/src/migrations/latest/shadcn-package-imports-exports/migration.d.ts +6 -0
  31. package/src/migrations/latest/shadcn-package-imports-exports/migration.js +184 -0
  32. package/src/migrations/latest/shadcn-package-imports-exports/migration.js.map +1 -0
  33. package/src/migrations/latest/shx-fs-commands/metadata.json +3 -0
  34. package/src/migrations/latest/shx-fs-commands/migration.d.ts +6 -0
  35. package/src/migrations/latest/shx-fs-commands/migration.js +216 -0
  36. package/src/migrations/latest/shx-fs-commands/migration.js.map +1 -0
  37. package/src/open-api/ts-client/__snapshots__/generator.complex-types.spec.ts.snap +18 -12
  38. package/src/open-api/ts-client/__snapshots__/generator.edge-cases.spec.ts.snap +5 -2
  39. package/src/open-api/utils/codegen-data/types.d.ts +6 -0
  40. package/src/open-api/utils/codegen-data/types.js.map +1 -1
  41. package/src/open-api/utils/codegen-data.js +32 -7
  42. package/src/open-api/utils/codegen-data.js.map +1 -1
  43. package/src/open-api/utils/normalise.js +39 -14
  44. package/src/open-api/utils/normalise.js.map +1 -1
  45. package/src/open-api/utils/parser.js +51 -5
  46. package/src/open-api/utils/parser.js.map +1 -1
  47. package/src/preset/__snapshots__/generator.spec.ts.snap +5 -1
  48. package/src/preset/generator.d.ts +1 -1
  49. package/src/py/agent/a2a-connection/generator.d.ts +1 -1
  50. package/src/py/agent/gateway-connection/generator.d.ts +1 -1
  51. package/src/py/agent/generator.d.ts +2 -26
  52. package/src/py/agent/generator.js +2 -2
  53. package/src/py/agent/generator.js.map +1 -1
  54. package/src/py/agent/mcp-connection/generator.d.ts +1 -1
  55. package/src/py/agent/react-connection/generator.d.ts +1 -1
  56. package/src/py/fast-api/generator.d.ts +1 -13
  57. package/src/py/fast-api/generator.js +1 -1
  58. package/src/py/fast-api/generator.js.map +1 -1
  59. package/src/py/fast-api/react/generator.d.ts +1 -1
  60. package/src/py/mcp-server/generator.d.ts +2 -26
  61. package/src/py/mcp-server/generator.js +2 -2
  62. package/src/py/mcp-server/generator.js.map +1 -1
  63. package/src/py/rdb/generator.d.ts +2 -26
  64. package/src/py/rdb/generator.js +6 -6
  65. package/src/py/rdb/generator.js.map +1 -1
  66. package/src/smithy/project/__snapshots__/generator.spec.ts.snap +24 -20
  67. package/src/smithy/project/generator.d.ts +2 -14
  68. package/src/smithy/project/generator.js +2 -1
  69. package/src/smithy/project/generator.js.map +1 -1
  70. package/src/smithy/react-connection/generator.d.ts +1 -1
  71. package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +12 -8
  72. package/src/smithy/ts/api/generator.d.ts +1 -13
  73. package/src/smithy/ts/api/generator.js +1 -1
  74. package/src/smithy/ts/api/generator.js.map +1 -1
  75. package/src/terraform/project/generator.d.ts +2 -2
  76. package/src/terraform/project/generator.js +4 -4
  77. package/src/terraform/project/generator.js.map +1 -1
  78. package/src/trpc/react/generator.d.ts +1 -1
  79. package/src/ts/agent/a2a-connection/generator.d.ts +5 -1
  80. package/src/ts/agent/gateway-connection/generator.d.ts +5 -1
  81. package/src/ts/agent/generator.d.ts +5 -37
  82. package/src/ts/agent/generator.js +1 -1
  83. package/src/ts/agent/generator.js.map +1 -1
  84. package/src/ts/agent/mcp-connection/generator.d.ts +5 -1
  85. package/src/ts/agent/react-connection/generator.d.ts +1 -1
  86. package/src/ts/astro-docs/generator.d.ts +1 -1
  87. package/src/ts/dcr-proxy/generator.d.ts +1 -1
  88. package/src/ts/dynamodb/generator.d.ts +1 -1
  89. package/src/ts/lambda-function/generator.d.ts +1 -1
  90. package/src/ts/lib/generator.d.ts +1 -1
  91. package/src/ts/mcp-server/generator.d.ts +3 -39
  92. package/src/ts/mcp-server/generator.js +1 -1
  93. package/src/ts/mcp-server/generator.js.map +1 -1
  94. package/src/ts/nx-generator/generator.d.ts +1 -1
  95. package/src/ts/nx-migration/generator.d.ts +1 -1
  96. package/src/ts/nx-plugin/generator.d.ts +1 -1
  97. package/src/ts/rdb/generator.d.ts +3 -27
  98. package/src/ts/rdb/generator.js +3 -3
  99. package/src/ts/rdb/generator.js.map +1 -1
  100. package/src/ts/react-website/agui/generator.d.ts +1 -1
  101. package/src/ts/react-website/agui/generator.js +2 -1
  102. package/src/ts/react-website/agui/generator.js.map +1 -1
  103. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +2 -0
  104. package/src/ts/react-website/app/generator.js +2 -1
  105. package/src/ts/react-website/app/generator.js.map +1 -1
  106. package/src/utils/agent-connection/agent-connection.d.ts +2 -0
  107. package/src/utils/agent-connection/agent-connection.js +11 -4
  108. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  109. package/src/utils/agent-core-packaging.d.ts +25 -12
  110. package/src/utils/agent-core-packaging.js +47 -11
  111. package/src/utils/agent-core-packaging.js.map +1 -1
  112. package/src/utils/bundle/bundle.js +10 -0
  113. package/src/utils/bundle/bundle.js.map +1 -1
  114. package/src/utils/docker.d.ts +1 -7
  115. package/src/utils/docker.js +1 -1
  116. package/src/utils/docker.js.map +1 -1
  117. package/src/utils/files/common/shadcn/src/components/ui/alert.tsx.template +1 -1
  118. package/src/utils/files/common/shadcn/src/components/ui/avatar.tsx.template +1 -1
  119. package/src/utils/files/common/shadcn/src/components/ui/breadcrumb.tsx.template +1 -1
  120. package/src/utils/files/common/shadcn/src/components/ui/button.tsx.template +1 -1
  121. package/src/utils/files/common/shadcn/src/components/ui/card.tsx.template +1 -1
  122. package/src/utils/files/common/shadcn/src/components/ui/input.tsx.template +1 -1
  123. package/src/utils/files/common/shadcn/src/components/ui/separator.tsx.template +1 -1
  124. package/src/utils/files/common/shadcn/src/components/ui/sheet.tsx.template +1 -1
  125. package/src/utils/files/common/shadcn/src/components/ui/sidebar.tsx.template +8 -8
  126. package/src/utils/files/common/shadcn/src/components/ui/skeleton.tsx.template +1 -1
  127. package/src/utils/files/common/shadcn/src/components/ui/spinner.tsx.template +1 -1
  128. package/src/utils/files/common/shadcn/src/components/ui/textarea.tsx.template +1 -1
  129. package/src/utils/files/common/shadcn/src/components/ui/tooltip.tsx.template +1 -1
  130. package/src/utils/files/shadcn/components.json.template +5 -5
  131. package/src/utils/format.d.ts +21 -0
  132. package/src/utils/format.js +20 -0
  133. package/src/utils/format.js.map +1 -1
  134. package/src/utils/fs.d.ts +21 -11
  135. package/src/utils/fs.js +30 -22
  136. package/src/utils/fs.js.map +1 -1
  137. package/src/utils/init.js +11 -4
  138. package/src/utils/init.js.map +1 -1
  139. package/src/utils/pnpm-workspace.d.ts +5 -5
  140. package/src/utils/pnpm-workspace.js +5 -5
  141. package/src/utils/pnpm-workspace.js.map +1 -1
  142. package/src/utils/shared-shadcn.d.ts +9 -0
  143. package/src/utils/shared-shadcn.js +36 -26
  144. package/src/utils/shared-shadcn.js.map +1 -1
  145. package/src/utils/version-lockstep/lockstep.d.ts +27 -0
  146. package/src/utils/version-lockstep/lockstep.js +46 -0
  147. package/src/utils/version-lockstep/lockstep.js.map +1 -0
  148. package/src/utils/versions.d.ts +9 -4
  149. package/src/utils/versions.js +24 -4
  150. package/src/utils/versions.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/format.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { Biome } from '@biomejs/js-api/nodejs';\nimport { getProjects, type Tree } from '@nx/devkit';\nimport path from 'path';\nimport { type RuffOptions, ruffFixAndFormat } from './ruff.js';\nimport { tryReadToml } from './toml.js';\nimport { TS_VERSIONS } from './versions.js';\n\n/**\n * Excludes test reports — including the vendored scripts vitest's coverage HTML\n * reporter writes — from formatting and linting.\n */\nexport const BIOME_TEST_OUTPUT_EXCLUDE = '!**/test-output';\n\n/**\n * The biome.json vended into a new workspace. The pnpm catalog resolver is only\n * included on pnpm workspaces, since `experimentalPnpmCatalogs` is Biome's only\n * catalog resolver and reads `pnpm-workspace.yaml` exclusively — it does nothing\n * for yarn or bun catalogs, so vending it there would be misleading.\n */\nexport const getDefaultBiomeConfig = (tree: Tree) => ({\n $schema: `https://biomejs.dev/schemas/${TS_VERSIONS['@biomejs/biome']}/schema.json`,\n root: true,\n formatter: {\n enabled: true,\n indentStyle: 'space',\n indentWidth: 2,\n lineWidth: 80,\n },\n javascript: {\n formatter: {\n quoteStyle: 'single',\n trailingCommas: 'all',\n },\n // Resolve `catalog:` versions from pnpm-workspace.yaml (pnpm workspaces only).\n ...(tree.exists('pnpm-workspace.yaml')\n ? { resolver: { experimentalPnpmCatalogs: true } }\n : {}),\n },\n css: {\n formatter: {\n quoteStyle: 'single',\n },\n linter: {\n enabled: false,\n },\n },\n linter: {\n enabled: true,\n rules: {\n preset: 'none',\n correctness: {\n // Every project must declare the third-party dependencies its source\n // code imports in its own package.json.\n noUndeclaredDependencies: 'error',\n },\n },\n },\n assist: {\n actions: {\n source: {\n organizeImports: 'on',\n },\n },\n },\n files: {\n includes: [\n '**',\n '!**/dist',\n '!**/out-tsc',\n BIOME_TEST_OUTPUT_EXCLUDE,\n '!**/node_modules',\n '!**/.nx',\n '!**/.venv',\n // GritQL codemod cache written by generators — its sample sources\n // otherwise pollute a bare `biome check .` with parse errors.\n '!**/.grit',\n '!**/*.css',\n '!**/*.gen.*',\n '!**/generated/**',\n '!**/tsconfig*.json',\n ],\n },\n // Config files, build scripts and tests use root tooling rather than\n // declaring it per-project, so the undeclared-dependency rule is off for them.\n overrides: [\n {\n includes: [\n '**/*.config.{ts,mts,cts,js,mjs,cjs}',\n '**/*.{spec,test}.{ts,tsx,mts,cts,js,jsx,mjs,cjs}',\n '**/*.stories.{ts,tsx}',\n ],\n linter: {\n rules: {\n correctness: {\n noUndeclaredDependencies: 'off',\n },\n },\n },\n },\n ],\n});\n\nconst BIOME_FORMATTABLE_EXTENSIONS = new Set([\n '.ts',\n '.tsx',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n '.mts',\n '.cts',\n '.json',\n '.jsonc',\n '.css',\n]);\n\n/** Matches `tsconfig.json` and variants like `tsconfig.lib.json`. */\nconst isTsConfig = (filePath: string): boolean =>\n /(^|\\/)tsconfig[^/]*\\.json$/.test(filePath);\n\nexport interface FormatFilesInSubtreeOptions {\n /**\n * Paths, relative to the workspace root, to leave untouched.\n *\n * For files another tool owns the formatting of: formatting them here makes\n * generation non-idempotent, since the tool rewrites them in its own shape on\n * the next run and the workspace flips between the two forms.\n */\n readonly ignore?: readonly string[];\n}\n\n/**\n * Paths declared ignored for a tree, which stay ignored for every later call.\n *\n * A call formats every change pending in the tree, not only the ones its caller\n * made, so the list cannot be scoped to the call that passes it: generators\n * composing on one tree would reformat a file an earlier generator had excluded.\n * Once the generator that owns a file declares it ignored, it stays ignored for\n * the rest of the run.\n */\nconst treeIgnoredPaths = new WeakMap<Tree, Set<string>>();\n\n/**\n * Tree paths are workspace-relative and forward-slash separated. Normalise so a\n * caller building a path with `path.join` on Windows still matches.\n */\nconst normalizeTreePath = (filePath: string): string =>\n filePath.split(path.sep).join('/').replace(/^\\.\\//, '');\n\n/**\n * Format files in the given directory within the tree.\n * Handles both TypeScript/JavaScript/JSON (via biome) and Python (via ruff) files.\n * See https://github.com/nrwl/nx/blob/4cd640a9187954505d12de5b6d76a90d8ce4c2eb/packages/devkit/src/generators/format-files.ts#L11\n */\nexport async function formatFilesInSubtree(\n tree: Tree,\n dir?: string,\n options?: FormatFilesInSubtreeOptions,\n): Promise<void> {\n let ignored = treeIgnoredPaths.get(tree);\n if (options?.ignore?.length) {\n if (!ignored) {\n ignored = new Set();\n treeIgnoredPaths.set(tree, ignored);\n }\n for (const filePath of options.ignore) {\n ignored.add(normalizeTreePath(filePath));\n }\n }\n const changedFiles = tree\n .listChanges()\n .filter((file) => file.type !== 'DELETE')\n .filter((file) => (dir ? file.path.startsWith(dir) : true))\n .filter((file) => !ignored?.has(normalizeTreePath(file.path)));\n\n const pyFiles = changedFiles.filter((file) => file.path.endsWith('.py'));\n const otherFiles = changedFiles.filter(\n (file) =>\n BIOME_FORMATTABLE_EXTENSIONS.has(path.extname(file.path)) &&\n // tsconfigs are not biome-managed: they're excluded from the vended\n // format target (Nx's typescript-sync rewrites them without formatting),\n // so formatting them at generation would only diverge from the form\n // written on later runs. Leave them as updateJson/writeJson emit them so\n // repeated generation stays idempotent.\n !isTsConfig(file.path),\n );\n\n // Resolve each project's ruff settings (module names, line-length) so files\n // are formatted to match the on-disk build (see getPythonProjectRuffConfigs).\n const pythonProjectConfigs = pyFiles.length\n ? getPythonProjectRuffConfigs(tree)\n : [];\n\n // Format Python files with ruff (lint fixes + formatting)\n for (const file of pyFiles) {\n try {\n const content = ruffFixAndFormat(\n file.content.toString('utf-8'),\n file.path,\n resolveRuffOptions(\n readRuffConfig(tree, file.path),\n getOwningProjectRuffConfig(file.path, pythonProjectConfigs),\n ),\n );\n tree.write(file.path, content);\n } catch {\n // Silently skip ruff formatting failures\n }\n }\n\n if (otherFiles.length === 0) return;\n\n formatWithBiome(tree, otherFiles);\n}\n\n/**\n * The Biome configuration to format with: the workspace's own `biome.json`, else\n * the config we vend.\n *\n * Read through the tree, which falls back to disk for a file it doesn't hold. So\n * this resolves the most current config either way — the workspace's on-disk one,\n * or the version a generator has just written to the tree and not yet flushed,\n * which shelling out to the CLI could never see.\n */\nfunction readBiomeConfig(tree: Tree): unknown {\n const config = tree.read('biome.json', 'utf-8');\n if (config) {\n try {\n return JSON.parse(config);\n } catch {\n // Malformed config — fall through to the config we vend\n }\n }\n return getDefaultBiomeConfig(tree);\n}\n\n/**\n * Format files with Biome in-process, reusing one instance across the batch.\n *\n * Replaces one `biome format --stdin-file-path` process per file, which\n * dominated generation at ~70ms each: `formatFilesInSubtree` formats every\n * change accumulated in the tree, not only the ones its caller made, so\n * generators sharing a tree reformat the same files once per call. In-process is\n * ~0.5ms per file. Output was verified byte-identical across the plugin's whole\n * source tree, except that the CLI corrupts control characters passed through\n * stdin (a NUL in a template literal) where formatting in-process preserves them.\n */\nfunction formatWithBiome(\n tree: Tree,\n files: { path: string; content: Buffer | null }[],\n): void {\n try {\n const biome = new Biome();\n const { projectKey } = biome.openProject();\n biome.applyConfiguration(projectKey, readBiomeConfig(tree));\n\n for (const file of files) {\n try {\n const { content } = biome.formatContent(\n projectKey,\n file.content?.toString('utf-8') ?? '',\n { filePath: file.path },\n );\n tree.write(file.path, content);\n } catch {\n // Leave individual files that fail to format untouched\n }\n }\n } catch {\n // Silently skip formatting failures\n }\n}\n\n/**\n * Read the ruff config for a file, by walking from its directory up to the\n * workspace root looking for `.ruff.toml`, `ruff.toml`, or a `pyproject.toml`\n * with a `[tool.ruff]` section — the same files, in the same order, that ruff\n * itself resolves. The walk stops at the workspace root so a stray config in a\n * parent of the workspace (or the home directory) is never treated as the\n * project's.\n *\n * The settings are read rather than merely detected because formatting runs\n * in-process against tree content, so ruff never sees the file's location and\n * cannot resolve the config itself (see {@link resolveRuffOptions}).\n *\n * Reads go through the tree, which falls through to disk for files this run has\n * not touched, so a config the generator has just written in memory is picked up\n * as well as one already on disk.\n */\nfunction readRuffConfig(tree: Tree, filePath: string): RuffOptions | undefined {\n let dir = path.dirname(filePath);\n while (true) {\n for (const name of ['.ruff.toml', 'ruff.toml']) {\n const config = tryReadToml(tree, path.join(dir, name));\n if (config) {\n return config as RuffOptions;\n }\n }\n const ruff = (tryReadToml(tree, path.join(dir, 'pyproject.toml')) as any)\n ?.tool?.ruff;\n if (ruff) {\n return ruff as RuffOptions;\n }\n // Stop once the workspace root ('.') has been checked.\n if (dir === '.' || dir === '' || dir === path.dirname(dir)) {\n return undefined;\n }\n dir = path.dirname(dir);\n }\n}\n\n/**\n * The `[tool.ruff.lint].select` generated Python projects vend. Generation\n * formats before that config lands on disk, so it is pinned here to keep\n * generated files clean under the project's own `lint` target rather than under\n * whatever ruff's defaults happen to be for the pinned release.\n */\nconst DEFAULT_RUFF_SELECT = ['E', 'F', 'UP', 'B', 'SIM', 'I'];\n\ninterface PythonProjectRuffConfig {\n /** Project root, normalised to use forward slashes. */\n readonly root: string;\n /** Top-level importable module names declared by the project. */\n readonly modules: string[];\n /** The project's `[tool.ruff].line-length`, if set. */\n readonly lineLength?: number;\n /**\n * Ruff `target-version` (eg `py314`) derived from `[project].requires-python`.\n * Generation formats via stdin with no pyproject, so it must be passed\n * explicitly — ruff's formatting differs by target.\n */\n readonly targetVersion?: string;\n /** The project's `[tool.ruff.lint].select`, if set. */\n readonly select?: string[];\n}\n\n/**\n * Derive ruff's `target-version` (eg `py314`) from a PEP 508\n * `requires-python` specifier (eg `>=3.14`). Ruff targets the minimum\n * supported version, so take the lowest `major.minor` mentioned.\n */\nexport const requiresPythonToRuffTarget = (\n requiresPython: unknown,\n): string | undefined => {\n if (typeof requiresPython !== 'string') {\n return undefined;\n }\n let min: { major: number; minor: number } | undefined;\n for (const match of requiresPython.matchAll(/(\\d+)\\.(\\d+)/g)) {\n const major = Number(match[1]);\n const minor = Number(match[2]);\n if (\n !min ||\n major < min.major ||\n (major === min.major && minor < min.minor)\n ) {\n min = { major, minor };\n }\n }\n return min ? `py${min.major}${min.minor}` : undefined;\n};\n\n/**\n * Map each Nx project with a `pyproject.toml` to the ruff settings the on-disk\n * build enforces for it: its top-level module names (from\n * `[tool.hatch.build.targets.wheel].packages`), its `[tool.ruff].line-length`\n * and its `[tool.ruff.lint].select`.\n */\nfunction getPythonProjectRuffConfigs(tree: Tree): PythonProjectRuffConfig[] {\n const configs: PythonProjectRuffConfig[] = [];\n\n for (const project of getProjects(tree).values()) {\n // Projects without a pyproject.toml, or whose one cannot be parsed, have no\n // ruff settings to contribute.\n const pyproject = tryReadToml(\n tree,\n path.join(project.root, 'pyproject.toml'),\n ) as any;\n if (!pyproject) {\n continue;\n }\n const wheelPackages: unknown =\n pyproject?.tool?.hatch?.build?.targets?.wheel?.packages;\n // Record the top-level module segment (`pkg/sub` -> `pkg`), which is\n // all `known-first-party` keys off.\n const modules = Array.isArray(wheelPackages)\n ? wheelPackages\n .filter((pkg): pkg is string => typeof pkg === 'string' && !!pkg)\n .map((pkg) => pkg.split('/')[0])\n : [];\n const lineLength: unknown = pyproject?.tool?.ruff?.['line-length'];\n const targetVersion = requiresPythonToRuffTarget(\n pyproject?.project?.['requires-python'],\n );\n const selected: unknown = pyproject?.tool?.ruff?.lint?.select;\n const select = Array.isArray(selected)\n ? selected.filter(\n (rule): rule is string => typeof rule === 'string' && !!rule,\n )\n : undefined;\n if (\n modules.length ||\n typeof lineLength === 'number' ||\n targetVersion ||\n select?.length\n ) {\n configs.push({\n root: project.root.split(path.sep).join('/'),\n modules,\n lineLength: typeof lineLength === 'number' ? lineLength : undefined,\n targetVersion,\n select: select?.length ? select : undefined,\n });\n }\n }\n\n return configs;\n}\n\n/**\n * Resolve the ruff config for the project that owns a file (the project with\n * the longest root that is a prefix of the file path). Ruff runs per-project on\n * disk, so a file's settings come from its own project — only its own module is\n * first-party (sibling workspace packages are third-party) and its own\n * line-length applies — and scoping this way keeps in-tree formatting\n * consistent with the on-disk build.\n */\nfunction getOwningProjectRuffConfig(\n filePath: string,\n configs: PythonProjectRuffConfig[],\n): PythonProjectRuffConfig | undefined {\n let owner: PythonProjectRuffConfig | undefined;\n for (const config of configs) {\n if (\n (filePath === config.root || filePath.startsWith(`${config.root}/`)) &&\n (!owner || config.root.length > owner.root.length)\n ) {\n owner = config;\n }\n }\n return owner;\n}\n\n/**\n * Resolve the ruff settings to format a Python file with, mirroring what the\n * file's build enforces.\n *\n * Ruff's own config discovery never runs: settings are passed to the linter\n * directly rather than resolved from the file's location, which it never sees.\n * That also means a stray config above the workspace (or in the home directory)\n * can never be picked up.\n *\n * `config` is the file's nearest ruff config, whose rule selection is honoured\n * as-is. Without one, ruff would fall back to its own defaults, which change\n * between releases — 0.16 widened them from `E` and `F` to 36 rule prefixes — so\n * generation would apply fixes the project's build never asks for (eg `RUF022`\n * reordering `__all__`). Instead the project's own `lint.select` is pinned, so\n * generation enforces exactly what `lint` does and nothing more.\n *\n * `projectConfig` layers on the settings derived from the owning project rather\n * than declared under `[tool.ruff]`: `known-first-party` (the project's own\n * modules, from its wheel packages) keeps its imports in their own group, and\n * `target-version` (from its `requires-python`) matches the formatting the build\n * produces.\n */\nfunction resolveRuffOptions(\n config: RuffOptions | undefined,\n projectConfig?: PythonProjectRuffConfig,\n): RuffOptions {\n const lint: Record<string, unknown> = { ...config?.lint };\n // Pin the rule selection only when deferring to ruff's defaults would\n // otherwise apply rules the project's build does not enforce.\n if (!config) {\n lint.select = projectConfig?.select ?? DEFAULT_RUFF_SELECT;\n }\n if (projectConfig?.modules.length) {\n lint.isort = {\n ...(lint.isort as object | undefined),\n 'known-first-party': projectConfig.modules,\n };\n }\n return {\n ...config,\n ...(typeof projectConfig?.lineLength === 'number'\n ? { 'line-length': projectConfig.lineLength }\n : {}),\n ...(projectConfig?.targetVersion\n ? { 'target-version': projectConfig.targetVersion }\n : {}),\n lint,\n };\n}\n"],"names":["Biome","getProjects","path","ruffFixAndFormat","tryReadToml","TS_VERSIONS","BIOME_TEST_OUTPUT_EXCLUDE","getDefaultBiomeConfig","tree","$schema","root","formatter","enabled","indentStyle","indentWidth","lineWidth","javascript","quoteStyle","trailingCommas","exists","resolver","experimentalPnpmCatalogs","css","linter","rules","preset","correctness","noUndeclaredDependencies","assist","actions","source","organizeImports","files","includes","overrides","BIOME_FORMATTABLE_EXTENSIONS","Set","isTsConfig","filePath","test","treeIgnoredPaths","WeakMap","normalizeTreePath","split","sep","join","replace","formatFilesInSubtree","dir","options","ignored","get","ignore","length","set","add","changedFiles","listChanges","filter","file","type","startsWith","has","pyFiles","endsWith","otherFiles","extname","pythonProjectConfigs","getPythonProjectRuffConfigs","content","toString","resolveRuffOptions","readRuffConfig","getOwningProjectRuffConfig","write","formatWithBiome","readBiomeConfig","config","read","JSON","parse","biome","projectKey","openProject","applyConfiguration","formatContent","dirname","name","ruff","tool","undefined","DEFAULT_RUFF_SELECT","requiresPythonToRuffTarget","requiresPython","min","match","matchAll","major","Number","minor","configs","project","values","pyproject","wheelPackages","hatch","build","targets","wheel","packages","modules","Array","isArray","pkg","map","lineLength","targetVersion","selected","lint","select","rule","push","owner","projectConfig","isort"],"mappings":"AAAA;;;CAGC,GAED,SAASA,KAAK,QAAQ,yBAAyB;AAC/C,SAASC,WAAW,QAAmB,aAAa;AACpD,OAAOC,UAAU,OAAO;AACxB,SAA2BC,gBAAgB,QAAQ,YAAY;AAC/D,SAASC,WAAW,QAAQ,YAAY;AACxC,SAASC,WAAW,QAAQ,gBAAgB;AAE5C;;;CAGC,GACD,OAAO,MAAMC,4BAA4B,kBAAkB;AAE3D;;;;;CAKC,GACD,OAAO,MAAMC,wBAAwB,CAACC,OAAgB,CAAA;QACpDC,SAAS,CAAC,4BAA4B,EAAEJ,WAAW,CAAC,iBAAiB,CAAC,YAAY,CAAC;QACnFK,MAAM;QACNC,WAAW;YACTC,SAAS;YACTC,aAAa;YACbC,aAAa;YACbC,WAAW;QACb;QACAC,YAAY;YACVL,WAAW;gBACTM,YAAY;gBACZC,gBAAgB;YAClB;YACA,+EAA+E;YAC/E,GAAIV,KAAKW,MAAM,CAAC,yBACZ;gBAAEC,UAAU;oBAAEC,0BAA0B;gBAAK;YAAE,IAC/C,CAAC,CAAC;QACR;QACAC,KAAK;YACHX,WAAW;gBACTM,YAAY;YACd;YACAM,QAAQ;gBACNX,SAAS;YACX;QACF;QACAW,QAAQ;YACNX,SAAS;YACTY,OAAO;gBACLC,QAAQ;gBACRC,aAAa;oBACX,qEAAqE;oBACrE,wCAAwC;oBACxCC,0BAA0B;gBAC5B;YACF;QACF;QACAC,QAAQ;YACNC,SAAS;gBACPC,QAAQ;oBACNC,iBAAiB;gBACnB;YACF;QACF;QACAC,OAAO;YACLC,UAAU;gBACR;gBACA;gBACA;gBACA3B;gBACA;gBACA;gBACA;gBACA,kEAAkE;gBAClE,8DAA8D;gBAC9D;gBACA;gBACA;gBACA;gBACA;aACD;QACH;QACA,qEAAqE;QACrE,+EAA+E;QAC/E4B,WAAW;YACT;gBACED,UAAU;oBACR;oBACA;oBACA;iBACD;gBACDV,QAAQ;oBACNC,OAAO;wBACLE,aAAa;4BACXC,0BAA0B;wBAC5B;oBACF;gBACF;YACF;SACD;IACH,CAAA,EAAG;AAEH,MAAMQ,+BAA+B,IAAIC,IAAI;IAC3C;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,mEAAmE,GACnE,MAAMC,aAAa,CAACC,WAClB,6BAA6BC,IAAI,CAACD;AAapC;;;;;;;;CAQC,GACD,MAAME,mBAAmB,IAAIC;AAE7B;;;CAGC,GACD,MAAMC,oBAAoB,CAACJ,WACzBA,SAASK,KAAK,CAACzC,KAAK0C,GAAG,EAAEC,IAAI,CAAC,KAAKC,OAAO,CAAC,SAAS;AAEtD;;;;CAIC,GACD,OAAO,eAAeC,qBACpBvC,IAAU,EACVwC,GAAY,EACZC,OAAqC;IAErC,IAAIC,UAAUV,iBAAiBW,GAAG,CAAC3C;IACnC,IAAIyC,SAASG,QAAQC,QAAQ;QAC3B,IAAI,CAACH,SAAS;YACZA,UAAU,IAAId;YACdI,iBAAiBc,GAAG,CAAC9C,MAAM0C;QAC7B;QACA,KAAK,MAAMZ,YAAYW,QAAQG,MAAM,CAAE;YACrCF,QAAQK,GAAG,CAACb,kBAAkBJ;QAChC;IACF;IACA,MAAMkB,eAAehD,KAClBiD,WAAW,GACXC,MAAM,CAAC,CAACC,OAASA,KAAKC,IAAI,KAAK,UAC/BF,MAAM,CAAC,CAACC,OAAUX,MAAMW,KAAKzD,IAAI,CAAC2D,UAAU,CAACb,OAAO,MACpDU,MAAM,CAAC,CAACC,OAAS,CAACT,SAASY,IAAIpB,kBAAkBiB,KAAKzD,IAAI;IAE7D,MAAM6D,UAAUP,aAAaE,MAAM,CAAC,CAACC,OAASA,KAAKzD,IAAI,CAAC8D,QAAQ,CAAC;IACjE,MAAMC,aAAaT,aAAaE,MAAM,CACpC,CAACC,OACCxB,6BAA6B2B,GAAG,CAAC5D,KAAKgE,OAAO,CAACP,KAAKzD,IAAI,MACvD,oEAAoE;QACpE,yEAAyE;QACzE,oEAAoE;QACpE,yEAAyE;QACzE,wCAAwC;QACxC,CAACmC,WAAWsB,KAAKzD,IAAI;IAGzB,4EAA4E;IAC5E,8EAA8E;IAC9E,MAAMiE,uBAAuBJ,QAAQV,MAAM,GACvCe,4BAA4B5D,QAC5B,EAAE;IAEN,0DAA0D;IAC1D,KAAK,MAAMmD,QAAQI,QAAS;QAC1B,IAAI;YACF,MAAMM,UAAUlE,iBACdwD,KAAKU,OAAO,CAACC,QAAQ,CAAC,UACtBX,KAAKzD,IAAI,EACTqE,mBACEC,eAAehE,MAAMmD,KAAKzD,IAAI,GAC9BuE,2BAA2Bd,KAAKzD,IAAI,EAAEiE;YAG1C3D,KAAKkE,KAAK,CAACf,KAAKzD,IAAI,EAAEmE;QACxB,EAAE,OAAM;QACN,yCAAyC;QAC3C;IACF;IAEA,IAAIJ,WAAWZ,MAAM,KAAK,GAAG;IAE7BsB,gBAAgBnE,MAAMyD;AACxB;AAEA;;;;;;;;CAQC,GACD,SAASW,gBAAgBpE,IAAU;IACjC,MAAMqE,SAASrE,KAAKsE,IAAI,CAAC,cAAc;IACvC,IAAID,QAAQ;QACV,IAAI;YACF,OAAOE,KAAKC,KAAK,CAACH;QACpB,EAAE,OAAM;QACN,wDAAwD;QAC1D;IACF;IACA,OAAOtE,sBAAsBC;AAC/B;AAEA;;;;;;;;;;CAUC,GACD,SAASmE,gBACPnE,IAAU,EACVwB,KAAiD;IAEjD,IAAI;QACF,MAAMiD,QAAQ,IAAIjF;QAClB,MAAM,EAAEkF,UAAU,EAAE,GAAGD,MAAME,WAAW;QACxCF,MAAMG,kBAAkB,CAACF,YAAYN,gBAAgBpE;QAErD,KAAK,MAAMmD,QAAQ3B,MAAO;YACxB,IAAI;gBACF,MAAM,EAAEqC,OAAO,EAAE,GAAGY,MAAMI,aAAa,CACrCH,YACAvB,KAAKU,OAAO,EAAEC,SAAS,YAAY,IACnC;oBAAEhC,UAAUqB,KAAKzD,IAAI;gBAAC;gBAExBM,KAAKkE,KAAK,CAACf,KAAKzD,IAAI,EAAEmE;YACxB,EAAE,OAAM;YACN,uDAAuD;YACzD;QACF;IACF,EAAE,OAAM;IACN,oCAAoC;IACtC;AACF;AAEA;;;;;;;;;;;;;;;CAeC,GACD,SAASG,eAAehE,IAAU,EAAE8B,QAAgB;IAClD,IAAIU,MAAM9C,KAAKoF,OAAO,CAAChD;IACvB,MAAO,KAAM;QACX,KAAK,MAAMiD,QAAQ;YAAC;YAAc;SAAY,CAAE;YAC9C,MAAMV,SAASzE,YAAYI,MAAMN,KAAK2C,IAAI,CAACG,KAAKuC;YAChD,IAAIV,QAAQ;gBACV,OAAOA;YACT;QACF;QACA,MAAMW,OAAQpF,YAAYI,MAAMN,KAAK2C,IAAI,CAACG,KAAK,oBAC3CyC,MAAMD;QACV,IAAIA,MAAM;YACR,OAAOA;QACT;QACA,uDAAuD;QACvD,IAAIxC,QAAQ,OAAOA,QAAQ,MAAMA,QAAQ9C,KAAKoF,OAAO,CAACtC,MAAM;YAC1D,OAAO0C;QACT;QACA1C,MAAM9C,KAAKoF,OAAO,CAACtC;IACrB;AACF;AAEA;;;;;CAKC,GACD,MAAM2C,sBAAsB;IAAC;IAAK;IAAK;IAAM;IAAK;IAAO;CAAI;AAmB7D;;;;CAIC,GACD,OAAO,MAAMC,6BAA6B,CACxCC;IAEA,IAAI,OAAOA,mBAAmB,UAAU;QACtC,OAAOH;IACT;IACA,IAAII;IACJ,KAAK,MAAMC,SAASF,eAAeG,QAAQ,CAAC,iBAAkB;QAC5D,MAAMC,QAAQC,OAAOH,KAAK,CAAC,EAAE;QAC7B,MAAMI,QAAQD,OAAOH,KAAK,CAAC,EAAE;QAC7B,IACE,CAACD,OACDG,QAAQH,IAAIG,KAAK,IAChBA,UAAUH,IAAIG,KAAK,IAAIE,QAAQL,IAAIK,KAAK,EACzC;YACAL,MAAM;gBAAEG;gBAAOE;YAAM;QACvB;IACF;IACA,OAAOL,MAAM,CAAC,EAAE,EAAEA,IAAIG,KAAK,GAAGH,IAAIK,KAAK,EAAE,GAAGT;AAC9C,EAAE;AAEF;;;;;CAKC,GACD,SAAStB,4BAA4B5D,IAAU;IAC7C,MAAM4F,UAAqC,EAAE;IAE7C,KAAK,MAAMC,WAAWpG,YAAYO,MAAM8F,MAAM,GAAI;QAChD,4EAA4E;QAC5E,+BAA+B;QAC/B,MAAMC,YAAYnG,YAChBI,MACAN,KAAK2C,IAAI,CAACwD,QAAQ3F,IAAI,EAAE;QAE1B,IAAI,CAAC6F,WAAW;YACd;QACF;QACA,MAAMC,gBACJD,WAAWd,MAAMgB,OAAOC,OAAOC,SAASC,OAAOC;QACjD,qEAAqE;QACrE,oCAAoC;QACpC,MAAMC,UAAUC,MAAMC,OAAO,CAACR,iBAC1BA,cACG9C,MAAM,CAAC,CAACuD,MAAuB,OAAOA,QAAQ,YAAY,CAAC,CAACA,KAC5DC,GAAG,CAAC,CAACD,MAAQA,IAAItE,KAAK,CAAC,IAAI,CAAC,EAAE,IACjC,EAAE;QACN,MAAMwE,aAAsBZ,WAAWd,MAAMD,MAAM,CAAC,cAAc;QAClE,MAAM4B,gBAAgBxB,2BACpBW,WAAWF,SAAS,CAAC,kBAAkB;QAEzC,MAAMgB,WAAoBd,WAAWd,MAAMD,MAAM8B,MAAMC;QACvD,MAAMA,SAASR,MAAMC,OAAO,CAACK,YACzBA,SAAS3D,MAAM,CACb,CAAC8D,OAAyB,OAAOA,SAAS,YAAY,CAAC,CAACA,QAE1D9B;QACJ,IACEoB,QAAQzD,MAAM,IACd,OAAO8D,eAAe,YACtBC,iBACAG,QAAQlE,QACR;YACA+C,QAAQqB,IAAI,CAAC;gBACX/G,MAAM2F,QAAQ3F,IAAI,CAACiC,KAAK,CAACzC,KAAK0C,GAAG,EAAEC,IAAI,CAAC;gBACxCiE;gBACAK,YAAY,OAAOA,eAAe,WAAWA,aAAazB;gBAC1D0B;gBACAG,QAAQA,QAAQlE,SAASkE,SAAS7B;YACpC;QACF;IACF;IAEA,OAAOU;AACT;AAEA;;;;;;;CAOC,GACD,SAAS3B,2BACPnC,QAAgB,EAChB8D,OAAkC;IAElC,IAAIsB;IACJ,KAAK,MAAM7C,UAAUuB,QAAS;QAC5B,IACE,AAAC9D,CAAAA,aAAauC,OAAOnE,IAAI,IAAI4B,SAASuB,UAAU,CAAC,GAAGgB,OAAOnE,IAAI,CAAC,CAAC,CAAC,CAAA,KACjE,CAAA,CAACgH,SAAS7C,OAAOnE,IAAI,CAAC2C,MAAM,GAAGqE,MAAMhH,IAAI,CAAC2C,MAAM,AAAD,GAChD;YACAqE,QAAQ7C;QACV;IACF;IACA,OAAO6C;AACT;AAEA;;;;;;;;;;;;;;;;;;;;;CAqBC,GACD,SAASnD,mBACPM,MAA+B,EAC/B8C,aAAuC;IAEvC,MAAML,OAAgC;QAAE,GAAGzC,QAAQyC,IAAI;IAAC;IACxD,sEAAsE;IACtE,8DAA8D;IAC9D,IAAI,CAACzC,QAAQ;QACXyC,KAAKC,MAAM,GAAGI,eAAeJ,UAAU5B;IACzC;IACA,IAAIgC,eAAeb,QAAQzD,QAAQ;QACjCiE,KAAKM,KAAK,GAAG;YACX,GAAIN,KAAKM,KAAK;YACd,qBAAqBD,cAAcb,OAAO;QAC5C;IACF;IACA,OAAO;QACL,GAAGjC,MAAM;QACT,GAAI,OAAO8C,eAAeR,eAAe,WACrC;YAAE,eAAeQ,cAAcR,UAAU;QAAC,IAC1C,CAAC,CAAC;QACN,GAAIQ,eAAeP,gBACf;YAAE,kBAAkBO,cAAcP,aAAa;QAAC,IAChD,CAAC,CAAC;QACNE;IACF;AACF"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/format.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { Biome } from '@biomejs/js-api/nodejs';\nimport { getProjects, type Tree } from '@nx/devkit';\nimport { createRequire } from 'module';\nimport path from 'path';\nimport { type RuffOptions, ruffFixAndFormat } from './ruff.js';\nimport { tryReadToml } from './toml.js';\nimport { TS_VERSIONS } from './versions.js';\n\n/**\n * The Biome release the wasm bindings are built from. Must match\n * `TS_VERSIONS['@biomejs/biome']`, the CLI the vended targets run.\n */\nexport const BIOME_WASM_VERSION: string = createRequire(import.meta.url)(\n '@biomejs/wasm-nodejs/package.json',\n).version;\n\n/**\n * Excludes test reports — including the vendored scripts vitest's coverage HTML\n * reporter writes — from formatting and linting.\n */\nexport const BIOME_TEST_OUTPUT_EXCLUDE = '!**/test-output';\n\n/**\n * The transient bundle rolldown writes beside a `rolldown.config.ts` while\n * loading it.\n *\n * Loading a TypeScript config bundles it to `rolldown.config.<hash>.js` in the\n * config's own directory, imports it, then unlinks it. That file exists for as\n * long as the bundle takes, so a `format` or `lint` target running concurrently\n * in the same project sees a machine-generated file — reported unformatted,\n * failing the target for no fault of the source.\n *\n * `.*js` rather than `.js`, since the extension follows the config's own: a\n * `.mts` config bundles to `.mjs`, a `.cts` one to `.cjs`.\n */\nexport const ROLLDOWN_CONFIG_BUNDLE_GLOB = '**/rolldown.config.*.*js';\n\n/** Keeps rolldown's transient config bundle out of formatting and linting. */\nexport const BIOME_ROLLDOWN_CONFIG_BUNDLE_EXCLUDE = `!${ROLLDOWN_CONFIG_BUNDLE_GLOB}`;\n\n/**\n * The biome.json vended into a new workspace. The pnpm catalog resolver is only\n * included on pnpm workspaces, since `experimentalPnpmCatalogs` is Biome's only\n * catalog resolver and reads `pnpm-workspace.yaml` exclusively — it does nothing\n * for yarn or bun catalogs, so vending it there would be misleading.\n */\nexport const getDefaultBiomeConfig = (tree: Tree) => ({\n $schema: `https://biomejs.dev/schemas/${TS_VERSIONS['@biomejs/biome']}/schema.json`,\n root: true,\n formatter: {\n enabled: true,\n indentStyle: 'space',\n indentWidth: 2,\n lineWidth: 80,\n },\n javascript: {\n formatter: {\n quoteStyle: 'single',\n trailingCommas: 'all',\n },\n // Resolve `catalog:` versions from pnpm-workspace.yaml (pnpm workspaces only).\n ...(tree.exists('pnpm-workspace.yaml')\n ? { resolver: { experimentalPnpmCatalogs: true } }\n : {}),\n },\n css: {\n formatter: {\n quoteStyle: 'single',\n },\n linter: {\n enabled: false,\n },\n },\n linter: {\n enabled: true,\n rules: {\n preset: 'none',\n correctness: {\n // Every project must declare the third-party dependencies its source\n // code imports in its own package.json.\n noUndeclaredDependencies: 'error',\n },\n },\n },\n assist: {\n actions: {\n source: {\n organizeImports: 'on',\n },\n },\n },\n files: {\n includes: [\n '**',\n '!**/dist',\n '!**/out-tsc',\n BIOME_TEST_OUTPUT_EXCLUDE,\n BIOME_ROLLDOWN_CONFIG_BUNDLE_EXCLUDE,\n '!**/node_modules',\n '!**/.nx',\n '!**/.venv',\n // GritQL codemod cache written by generators — its sample sources\n // otherwise pollute a bare `biome check .` with parse errors.\n '!**/.grit',\n '!**/*.css',\n '!**/*.gen.*',\n '!**/generated/**',\n '!**/tsconfig*.json',\n ],\n },\n // Config files, build scripts and tests use root tooling rather than\n // declaring it per-project, so the undeclared-dependency rule is off for them.\n overrides: [\n {\n includes: [\n '**/*.config.{ts,mts,cts,js,mjs,cjs}',\n '**/*.{spec,test}.{ts,tsx,mts,cts,js,jsx,mjs,cjs}',\n '**/*.stories.{ts,tsx}',\n ],\n linter: {\n rules: {\n correctness: {\n noUndeclaredDependencies: 'off',\n },\n },\n },\n },\n ],\n});\n\nconst BIOME_FORMATTABLE_EXTENSIONS = new Set([\n '.ts',\n '.tsx',\n '.js',\n '.jsx',\n '.mjs',\n '.cjs',\n '.mts',\n '.cts',\n '.json',\n '.jsonc',\n '.css',\n]);\n\n/** Matches `tsconfig.json` and variants like `tsconfig.lib.json`. */\nconst isTsConfig = (filePath: string): boolean =>\n /(^|\\/)tsconfig[^/]*\\.json$/.test(filePath);\n\nexport interface FormatFilesInSubtreeOptions {\n /**\n * Paths, relative to the workspace root, to leave untouched.\n *\n * For files another tool owns the formatting of: formatting them here makes\n * generation non-idempotent, since the tool rewrites them in its own shape on\n * the next run and the workspace flips between the two forms.\n */\n readonly ignore?: readonly string[];\n}\n\n/**\n * Paths declared ignored for a tree, which stay ignored for every later call.\n *\n * A call formats every change pending in the tree, not only the ones its caller\n * made, so the list cannot be scoped to the call that passes it: generators\n * composing on one tree would reformat a file an earlier generator had excluded.\n * Once the generator that owns a file declares it ignored, it stays ignored for\n * the rest of the run.\n */\nconst treeIgnoredPaths = new WeakMap<Tree, Set<string>>();\n\n/**\n * Tree paths are workspace-relative and forward-slash separated. Normalise so a\n * caller building a path with `path.join` on Windows still matches.\n */\nconst normalizeTreePath = (filePath: string): string =>\n filePath.split(path.sep).join('/').replace(/^\\.\\//, '');\n\n/**\n * Format files in the given directory within the tree.\n * Handles both TypeScript/JavaScript/JSON (via biome) and Python (via ruff) files.\n * See https://github.com/nrwl/nx/blob/4cd640a9187954505d12de5b6d76a90d8ce4c2eb/packages/devkit/src/generators/format-files.ts#L11\n */\nexport async function formatFilesInSubtree(\n tree: Tree,\n dir?: string,\n options?: FormatFilesInSubtreeOptions,\n): Promise<void> {\n let ignored = treeIgnoredPaths.get(tree);\n if (options?.ignore?.length) {\n if (!ignored) {\n ignored = new Set();\n treeIgnoredPaths.set(tree, ignored);\n }\n for (const filePath of options.ignore) {\n ignored.add(normalizeTreePath(filePath));\n }\n }\n const changedFiles = tree\n .listChanges()\n .filter((file) => file.type !== 'DELETE')\n .filter((file) => (dir ? file.path.startsWith(dir) : true))\n .filter((file) => !ignored?.has(normalizeTreePath(file.path)));\n\n const pyFiles = changedFiles.filter((file) => file.path.endsWith('.py'));\n const otherFiles = changedFiles.filter(\n (file) =>\n BIOME_FORMATTABLE_EXTENSIONS.has(path.extname(file.path)) &&\n // tsconfigs are not biome-managed: they're excluded from the vended\n // format target (Nx's typescript-sync rewrites them without formatting),\n // so formatting them at generation would only diverge from the form\n // written on later runs. Leave them as updateJson/writeJson emit them so\n // repeated generation stays idempotent.\n !isTsConfig(file.path),\n );\n\n // Resolve each project's ruff settings (module names, line-length) so files\n // are formatted to match the on-disk build (see getPythonProjectRuffConfigs).\n const pythonProjectConfigs = pyFiles.length\n ? getPythonProjectRuffConfigs(tree)\n : [];\n\n // Format Python files with ruff (lint fixes + formatting)\n for (const file of pyFiles) {\n try {\n const content = ruffFixAndFormat(\n file.content.toString('utf-8'),\n file.path,\n resolveRuffOptions(\n readRuffConfig(tree, file.path),\n getOwningProjectRuffConfig(file.path, pythonProjectConfigs),\n ),\n );\n tree.write(file.path, content);\n } catch {\n // Silently skip ruff formatting failures\n }\n }\n\n if (otherFiles.length === 0) return;\n\n formatWithBiome(tree, otherFiles);\n}\n\n/**\n * The Biome configuration to format with: the workspace's own `biome.json`, else\n * the config we vend.\n *\n * Read through the tree, which falls back to disk for a file it doesn't hold. So\n * this resolves the most current config either way — the workspace's on-disk one,\n * or the version a generator has just written to the tree and not yet flushed,\n * which shelling out to the CLI could never see.\n */\nfunction readBiomeConfig(tree: Tree): unknown {\n const config = tree.read('biome.json', 'utf-8');\n if (config) {\n try {\n return JSON.parse(config);\n } catch {\n // Malformed config — fall through to the config we vend\n }\n }\n return getDefaultBiomeConfig(tree);\n}\n\n/**\n * Format files with Biome in-process, reusing one instance across the batch.\n *\n * Replaces one `biome format --stdin-file-path` process per file, which\n * dominated generation at ~70ms each: `formatFilesInSubtree` formats every\n * change accumulated in the tree, not only the ones its caller made, so\n * generators sharing a tree reformat the same files once per call. In-process is\n * ~0.5ms per file. Output was verified byte-identical across the plugin's whole\n * source tree, except that the CLI corrupts control characters passed through\n * stdin (a NUL in a template literal) where formatting in-process preserves them.\n */\nfunction formatWithBiome(\n tree: Tree,\n files: { path: string; content: Buffer | null }[],\n): void {\n try {\n const biome = new Biome();\n const { projectKey } = biome.openProject();\n biome.applyConfiguration(projectKey, readBiomeConfig(tree));\n\n for (const file of files) {\n try {\n const { content } = biome.formatContent(\n projectKey,\n file.content?.toString('utf-8') ?? '',\n { filePath: file.path },\n );\n tree.write(file.path, content);\n } catch {\n // Leave individual files that fail to format untouched\n }\n }\n } catch {\n // Silently skip formatting failures\n }\n}\n\n/**\n * Read the ruff config for a file, by walking from its directory up to the\n * workspace root looking for `.ruff.toml`, `ruff.toml`, or a `pyproject.toml`\n * with a `[tool.ruff]` section — the same files, in the same order, that ruff\n * itself resolves. The walk stops at the workspace root so a stray config in a\n * parent of the workspace (or the home directory) is never treated as the\n * project's.\n *\n * The settings are read rather than merely detected because formatting runs\n * in-process against tree content, so ruff never sees the file's location and\n * cannot resolve the config itself (see {@link resolveRuffOptions}).\n *\n * Reads go through the tree, which falls through to disk for files this run has\n * not touched, so a config the generator has just written in memory is picked up\n * as well as one already on disk.\n */\nfunction readRuffConfig(tree: Tree, filePath: string): RuffOptions | undefined {\n let dir = path.dirname(filePath);\n while (true) {\n for (const name of ['.ruff.toml', 'ruff.toml']) {\n const config = tryReadToml(tree, path.join(dir, name));\n if (config) {\n return config as RuffOptions;\n }\n }\n const ruff = (tryReadToml(tree, path.join(dir, 'pyproject.toml')) as any)\n ?.tool?.ruff;\n if (ruff) {\n return ruff as RuffOptions;\n }\n // Stop once the workspace root ('.') has been checked.\n if (dir === '.' || dir === '' || dir === path.dirname(dir)) {\n return undefined;\n }\n dir = path.dirname(dir);\n }\n}\n\n/**\n * The `[tool.ruff.lint].select` generated Python projects vend. Generation\n * formats before that config lands on disk, so it is pinned here to keep\n * generated files clean under the project's own `lint` target rather than under\n * whatever ruff's defaults happen to be for the pinned release.\n */\nconst DEFAULT_RUFF_SELECT = ['E', 'F', 'UP', 'B', 'SIM', 'I'];\n\ninterface PythonProjectRuffConfig {\n /** Project root, normalised to use forward slashes. */\n readonly root: string;\n /** Top-level importable module names declared by the project. */\n readonly modules: string[];\n /** The project's `[tool.ruff].line-length`, if set. */\n readonly lineLength?: number;\n /**\n * Ruff `target-version` (eg `py314`) derived from `[project].requires-python`.\n * Generation formats via stdin with no pyproject, so it must be passed\n * explicitly — ruff's formatting differs by target.\n */\n readonly targetVersion?: string;\n /** The project's `[tool.ruff.lint].select`, if set. */\n readonly select?: string[];\n}\n\n/**\n * Derive ruff's `target-version` (eg `py314`) from a PEP 508\n * `requires-python` specifier (eg `>=3.14`). Ruff targets the minimum\n * supported version, so take the lowest `major.minor` mentioned.\n */\nexport const requiresPythonToRuffTarget = (\n requiresPython: unknown,\n): string | undefined => {\n if (typeof requiresPython !== 'string') {\n return undefined;\n }\n let min: { major: number; minor: number } | undefined;\n for (const match of requiresPython.matchAll(/(\\d+)\\.(\\d+)/g)) {\n const major = Number(match[1]);\n const minor = Number(match[2]);\n if (\n !min ||\n major < min.major ||\n (major === min.major && minor < min.minor)\n ) {\n min = { major, minor };\n }\n }\n return min ? `py${min.major}${min.minor}` : undefined;\n};\n\n/**\n * Map each Nx project with a `pyproject.toml` to the ruff settings the on-disk\n * build enforces for it: its top-level module names (from\n * `[tool.hatch.build.targets.wheel].packages`), its `[tool.ruff].line-length`\n * and its `[tool.ruff.lint].select`.\n */\nfunction getPythonProjectRuffConfigs(tree: Tree): PythonProjectRuffConfig[] {\n const configs: PythonProjectRuffConfig[] = [];\n\n for (const project of getProjects(tree).values()) {\n // Projects without a pyproject.toml, or whose one cannot be parsed, have no\n // ruff settings to contribute.\n const pyproject = tryReadToml(\n tree,\n path.join(project.root, 'pyproject.toml'),\n ) as any;\n if (!pyproject) {\n continue;\n }\n const wheelPackages: unknown =\n pyproject?.tool?.hatch?.build?.targets?.wheel?.packages;\n // Record the top-level module segment (`pkg/sub` -> `pkg`), which is\n // all `known-first-party` keys off.\n const modules = Array.isArray(wheelPackages)\n ? wheelPackages\n .filter((pkg): pkg is string => typeof pkg === 'string' && !!pkg)\n .map((pkg) => pkg.split('/')[0])\n : [];\n const lineLength: unknown = pyproject?.tool?.ruff?.['line-length'];\n const targetVersion = requiresPythonToRuffTarget(\n pyproject?.project?.['requires-python'],\n );\n const selected: unknown = pyproject?.tool?.ruff?.lint?.select;\n const select = Array.isArray(selected)\n ? selected.filter(\n (rule): rule is string => typeof rule === 'string' && !!rule,\n )\n : undefined;\n if (\n modules.length ||\n typeof lineLength === 'number' ||\n targetVersion ||\n select?.length\n ) {\n configs.push({\n root: project.root.split(path.sep).join('/'),\n modules,\n lineLength: typeof lineLength === 'number' ? lineLength : undefined,\n targetVersion,\n select: select?.length ? select : undefined,\n });\n }\n }\n\n return configs;\n}\n\n/**\n * Resolve the ruff config for the project that owns a file (the project with\n * the longest root that is a prefix of the file path). Ruff runs per-project on\n * disk, so a file's settings come from its own project — only its own module is\n * first-party (sibling workspace packages are third-party) and its own\n * line-length applies — and scoping this way keeps in-tree formatting\n * consistent with the on-disk build.\n */\nfunction getOwningProjectRuffConfig(\n filePath: string,\n configs: PythonProjectRuffConfig[],\n): PythonProjectRuffConfig | undefined {\n let owner: PythonProjectRuffConfig | undefined;\n for (const config of configs) {\n if (\n (filePath === config.root || filePath.startsWith(`${config.root}/`)) &&\n (!owner || config.root.length > owner.root.length)\n ) {\n owner = config;\n }\n }\n return owner;\n}\n\n/**\n * Resolve the ruff settings to format a Python file with, mirroring what the\n * file's build enforces.\n *\n * Ruff's own config discovery never runs: settings are passed to the linter\n * directly rather than resolved from the file's location, which it never sees.\n * That also means a stray config above the workspace (or in the home directory)\n * can never be picked up.\n *\n * `config` is the file's nearest ruff config, whose rule selection is honoured\n * as-is. Without one, ruff would fall back to its own defaults, which change\n * between releases — 0.16 widened them from `E` and `F` to 36 rule prefixes — so\n * generation would apply fixes the project's build never asks for (eg `RUF022`\n * reordering `__all__`). Instead the project's own `lint.select` is pinned, so\n * generation enforces exactly what `lint` does and nothing more.\n *\n * `projectConfig` layers on the settings derived from the owning project rather\n * than declared under `[tool.ruff]`: `known-first-party` (the project's own\n * modules, from its wheel packages) keeps its imports in their own group, and\n * `target-version` (from its `requires-python`) matches the formatting the build\n * produces.\n */\nfunction resolveRuffOptions(\n config: RuffOptions | undefined,\n projectConfig?: PythonProjectRuffConfig,\n): RuffOptions {\n const lint: Record<string, unknown> = { ...config?.lint };\n // Pin the rule selection only when deferring to ruff's defaults would\n // otherwise apply rules the project's build does not enforce.\n if (!config) {\n lint.select = projectConfig?.select ?? DEFAULT_RUFF_SELECT;\n }\n if (projectConfig?.modules.length) {\n lint.isort = {\n ...(lint.isort as object | undefined),\n 'known-first-party': projectConfig.modules,\n };\n }\n return {\n ...config,\n ...(typeof projectConfig?.lineLength === 'number'\n ? { 'line-length': projectConfig.lineLength }\n : {}),\n ...(projectConfig?.targetVersion\n ? { 'target-version': projectConfig.targetVersion }\n : {}),\n lint,\n };\n}\n"],"names":["Biome","getProjects","createRequire","path","ruffFixAndFormat","tryReadToml","TS_VERSIONS","BIOME_WASM_VERSION","url","version","BIOME_TEST_OUTPUT_EXCLUDE","ROLLDOWN_CONFIG_BUNDLE_GLOB","BIOME_ROLLDOWN_CONFIG_BUNDLE_EXCLUDE","getDefaultBiomeConfig","tree","$schema","root","formatter","enabled","indentStyle","indentWidth","lineWidth","javascript","quoteStyle","trailingCommas","exists","resolver","experimentalPnpmCatalogs","css","linter","rules","preset","correctness","noUndeclaredDependencies","assist","actions","source","organizeImports","files","includes","overrides","BIOME_FORMATTABLE_EXTENSIONS","Set","isTsConfig","filePath","test","treeIgnoredPaths","WeakMap","normalizeTreePath","split","sep","join","replace","formatFilesInSubtree","dir","options","ignored","get","ignore","length","set","add","changedFiles","listChanges","filter","file","type","startsWith","has","pyFiles","endsWith","otherFiles","extname","pythonProjectConfigs","getPythonProjectRuffConfigs","content","toString","resolveRuffOptions","readRuffConfig","getOwningProjectRuffConfig","write","formatWithBiome","readBiomeConfig","config","read","JSON","parse","biome","projectKey","openProject","applyConfiguration","formatContent","dirname","name","ruff","tool","undefined","DEFAULT_RUFF_SELECT","requiresPythonToRuffTarget","requiresPython","min","match","matchAll","major","Number","minor","configs","project","values","pyproject","wheelPackages","hatch","build","targets","wheel","packages","modules","Array","isArray","pkg","map","lineLength","targetVersion","selected","lint","select","rule","push","owner","projectConfig","isort"],"mappings":"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"}
package/src/utils/fs.d.ts CHANGED
@@ -6,13 +6,7 @@ import type { Tree } from '@nx/devkit';
6
6
  import { type DependencyDeclaration, type MustDeclare } from './declared-dependencies.js';
7
7
  /** Dependencies a caller must declare to use `FsCommands`. */
8
8
  export declare const FS_DEPENDENCIES: readonly [{
9
- readonly name: "ncp";
10
- }, {
11
- readonly name: "rimraf";
12
- }, {
13
- readonly name: "make-dir-cli";
14
- }, {
15
- readonly name: "cpy-cli";
9
+ readonly name: "shx";
16
10
  }];
17
11
  /**
18
12
  * Platform agnostic commands for filesystem operations, adding the CLIs they
@@ -22,13 +16,29 @@ export declare class FsCommands<D extends DependencyDeclaration> {
22
16
  private tree;
23
17
  private declaration;
24
18
  constructor(tree: Tree, declaration: D & MustDeclare<typeof FS_DEPENDENCIES, D>);
25
- cp(src: string, dst: string): string;
19
+ /** Copy a single file to `dst`, which names the file rather than a directory. */
20
+ cpFile(src: string, dst: string): string;
21
+ /**
22
+ * Copy a directory's contents into `dst`, merging into whatever is already
23
+ * there.
24
+ *
25
+ * The trailing `/.` is load bearing: `shx cp -R src dst` follows POSIX `cp`,
26
+ * which nests `src` *inside* an existing `dst` rather than merging into it, so
27
+ * without it a copy into a directory a preceding `mkdir` had just created
28
+ * would land a level too deep. `src/.` copies the contents, and unlike a
29
+ * `src/*` glob it includes dotfiles — which `node_modules/.bin` depends on.
30
+ */
31
+ cpDir(src: string, dst: string): string;
26
32
  rm(dir: string): string;
27
33
  mkdir(dir: string): string;
28
34
  /**
29
- * Copy the single file a glob matches to `dst`, for an artifact whose producer
30
- * names it — the Smithy OpenAPI plugin writes `<ServiceShape>.openapi.json`.
31
- * Fails rather than silently doing nothing when the glob matches nothing.
35
+ * Copy the single file a glob matches to `dstDir/dstFileName`, for an artifact
36
+ * whose producer names it — the Smithy OpenAPI plugin writes
37
+ * `<ServiceShape>.openapi.json`. Fails rather than silently doing nothing when
38
+ * the glob matches nothing, or when it matches more than one file.
39
+ *
40
+ * The caller must {@link mkdir} `dstDir` first: `shx cp` writes through to a
41
+ * named destination file and fails if its parent is missing.
32
42
  */
33
43
  cpGlobToFile(srcGlob: string, dstDir: string, dstFileName: string): string;
34
44
  private add;
package/src/utils/fs.js CHANGED
@@ -6,16 +6,7 @@ import { addDependenciesToPackageJson } from "./dependencies.js";
6
6
  import { withVersions } from "./versions.js";
7
7
  /** Dependencies a caller must declare to use `FsCommands`. */ export const FS_DEPENDENCIES = [
8
8
  {
9
- name: 'ncp'
10
- },
11
- {
12
- name: 'rimraf'
13
- },
14
- {
15
- name: 'make-dir-cli'
16
- },
17
- {
18
- name: 'cpy-cli'
9
+ name: 'shx'
19
10
  }
20
11
  ];
21
12
  /**
@@ -28,25 +19,42 @@ import { withVersions } from "./versions.js";
28
19
  this.tree = tree;
29
20
  this.declaration = declaration;
30
21
  }
31
- cp(src, dst) {
32
- this.add('ncp');
33
- return `ncp ${src} ${dst}`;
22
+ /** Copy a single file to `dst`, which names the file rather than a directory. */ cpFile(src, dst) {
23
+ this.add('shx');
24
+ return `shx cp ${src} ${dst}`;
25
+ }
26
+ /**
27
+ * Copy a directory's contents into `dst`, merging into whatever is already
28
+ * there.
29
+ *
30
+ * The trailing `/.` is load bearing: `shx cp -R src dst` follows POSIX `cp`,
31
+ * which nests `src` *inside* an existing `dst` rather than merging into it, so
32
+ * without it a copy into a directory a preceding `mkdir` had just created
33
+ * would land a level too deep. `src/.` copies the contents, and unlike a
34
+ * `src/*` glob it includes dotfiles — which `node_modules/.bin` depends on.
35
+ */ cpDir(src, dst) {
36
+ this.add('shx');
37
+ return `shx cp -R ${src}/. ${dst}`;
34
38
  }
35
39
  rm(dir) {
36
- this.add('rimraf');
37
- return `rimraf ${dir}`;
40
+ this.add('shx');
41
+ return `shx rm -rf ${dir}`;
38
42
  }
39
43
  mkdir(dir) {
40
- this.add('make-dir-cli');
41
- return `make-dir ${dir}`;
44
+ this.add('shx');
45
+ return `shx mkdir -p ${dir}`;
42
46
  }
43
47
  /**
44
- * Copy the single file a glob matches to `dst`, for an artifact whose producer
45
- * names it — the Smithy OpenAPI plugin writes `<ServiceShape>.openapi.json`.
46
- * Fails rather than silently doing nothing when the glob matches nothing.
48
+ * Copy the single file a glob matches to `dstDir/dstFileName`, for an artifact
49
+ * whose producer names it — the Smithy OpenAPI plugin writes
50
+ * `<ServiceShape>.openapi.json`. Fails rather than silently doing nothing when
51
+ * the glob matches nothing, or when it matches more than one file.
52
+ *
53
+ * The caller must {@link mkdir} `dstDir` first: `shx cp` writes through to a
54
+ * named destination file and fails if its parent is missing.
47
55
  */ cpGlobToFile(srcGlob, dstDir, dstFileName) {
48
- this.add('cpy-cli');
49
- return `cpy "${srcGlob}" ${dstDir} --flat --rename=${dstFileName}`;
56
+ this.add('shx');
57
+ return `shx cp "${srcGlob}" ${dstDir}/${dstFileName}`;
50
58
  }
51
59
  add(dep) {
52
60
  addDependenciesToPackageJson(this.tree, {}, withVersions(forDependencies(this.declaration), [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/fs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Tree } from '@nx/devkit';\nimport {\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from './declared-dependencies.js';\nimport { addDependenciesToPackageJson } from './dependencies.js';\nimport { type ITsDepVersion, withVersions } from './versions.js';\n\n/** Dependencies a caller must declare to use `FsCommands`. */\nexport const FS_DEPENDENCIES = [\n { name: 'ncp' },\n { name: 'rimraf' },\n { name: 'make-dir-cli' },\n { name: 'cpy-cli' },\n] as const satisfies readonly { name: ITsDepVersion }[];\n\n/**\n * Platform agnostic commands for filesystem operations, adding the CLIs they\n * need to the root package.json.\n */\nexport class FsCommands<D extends DependencyDeclaration> {\n private tree: Tree;\n private declaration: D;\n\n constructor(\n tree: Tree,\n declaration: D & MustDeclare<typeof FS_DEPENDENCIES, D>,\n ) {\n this.tree = tree;\n this.declaration = declaration;\n }\n\n public cp(src: string, dst: string) {\n this.add('ncp');\n return `ncp ${src} ${dst}`;\n }\n\n public rm(dir: string) {\n this.add('rimraf');\n return `rimraf ${dir}`;\n }\n\n public mkdir(dir: string) {\n this.add('make-dir-cli');\n return `make-dir ${dir}`;\n }\n\n /**\n * Copy the single file a glob matches to `dst`, for an artifact whose producer\n * names it — the Smithy OpenAPI plugin writes `<ServiceShape>.openapi.json`.\n * Fails rather than silently doing nothing when the glob matches nothing.\n */\n public cpGlobToFile(srcGlob: string, dstDir: string, dstFileName: string) {\n this.add('cpy-cli');\n return `cpy \"${srcGlob}\" ${dstDir} --flat --rename=${dstFileName}`;\n }\n\n private add(dep: (typeof FS_DEPENDENCIES)[number]['name']) {\n addDependenciesToPackageJson(\n this.tree,\n {},\n withVersions(forDependencies<typeof FS_DEPENDENCIES>(this.declaration), [\n dep,\n ]),\n );\n }\n}\n"],"names":["forDependencies","addDependenciesToPackageJson","withVersions","FS_DEPENDENCIES","name","FsCommands","tree","declaration","cp","src","dst","add","rm","dir","mkdir","cpGlobToFile","srcGlob","dstDir","dstFileName","dep"],"mappings":"AAAA;;;CAGC,GAED,SAEEA,eAAe,QAEV,6BAA6B;AACpC,SAASC,4BAA4B,QAAQ,oBAAoB;AACjE,SAA6BC,YAAY,QAAQ,gBAAgB;AAEjE,4DAA4D,GAC5D,OAAO,MAAMC,kBAAkB;IAC7B;QAAEC,MAAM;IAAM;IACd;QAAEA,MAAM;IAAS;IACjB;QAAEA,MAAM;IAAe;IACvB;QAAEA,MAAM;IAAU;CACnB,CAAuD;AAExD;;;CAGC,GACD,OAAO,MAAMC;IACHC,KAAW;IACXC,YAAe;IAEvB,YACED,IAAU,EACVC,WAAuD,CACvD;QACA,IAAI,CAACD,IAAI,GAAGA;QACZ,IAAI,CAACC,WAAW,GAAGA;IACrB;IAEOC,GAAGC,GAAW,EAAEC,GAAW,EAAE;QAClC,IAAI,CAACC,GAAG,CAAC;QACT,OAAO,CAAC,IAAI,EAAEF,IAAI,CAAC,EAAEC,KAAK;IAC5B;IAEOE,GAAGC,GAAW,EAAE;QACrB,IAAI,CAACF,GAAG,CAAC;QACT,OAAO,CAAC,OAAO,EAAEE,KAAK;IACxB;IAEOC,MAAMD,GAAW,EAAE;QACxB,IAAI,CAACF,GAAG,CAAC;QACT,OAAO,CAAC,SAAS,EAAEE,KAAK;IAC1B;IAEA;;;;GAIC,GACD,AAAOE,aAAaC,OAAe,EAAEC,MAAc,EAAEC,WAAmB,EAAE;QACxE,IAAI,CAACP,GAAG,CAAC;QACT,OAAO,CAAC,KAAK,EAAEK,QAAQ,EAAE,EAAEC,OAAO,iBAAiB,EAAEC,aAAa;IACpE;IAEQP,IAAIQ,GAA6C,EAAE;QACzDlB,6BACE,IAAI,CAACK,IAAI,EACT,CAAC,GACDJ,aAAaF,gBAAwC,IAAI,CAACO,WAAW,GAAG;YACtEY;SACD;IAEL;AACF"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/fs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Tree } from '@nx/devkit';\nimport {\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from './declared-dependencies.js';\nimport { addDependenciesToPackageJson } from './dependencies.js';\nimport { type ITsDepVersion, withVersions } from './versions.js';\n\n/** Dependencies a caller must declare to use `FsCommands`. */\nexport const FS_DEPENDENCIES = [{ name: 'shx' }] as const satisfies readonly {\n name: ITsDepVersion;\n}[];\n\n/**\n * Platform agnostic commands for filesystem operations, adding the CLIs they\n * need to the root package.json.\n */\nexport class FsCommands<D extends DependencyDeclaration> {\n private tree: Tree;\n private declaration: D;\n\n constructor(\n tree: Tree,\n declaration: D & MustDeclare<typeof FS_DEPENDENCIES, D>,\n ) {\n this.tree = tree;\n this.declaration = declaration;\n }\n\n /** Copy a single file to `dst`, which names the file rather than a directory. */\n public cpFile(src: string, dst: string) {\n this.add('shx');\n return `shx cp ${src} ${dst}`;\n }\n\n /**\n * Copy a directory's contents into `dst`, merging into whatever is already\n * there.\n *\n * The trailing `/.` is load bearing: `shx cp -R src dst` follows POSIX `cp`,\n * which nests `src` *inside* an existing `dst` rather than merging into it, so\n * without it a copy into a directory a preceding `mkdir` had just created\n * would land a level too deep. `src/.` copies the contents, and unlike a\n * `src/*` glob it includes dotfiles — which `node_modules/.bin` depends on.\n */\n public cpDir(src: string, dst: string) {\n this.add('shx');\n return `shx cp -R ${src}/. ${dst}`;\n }\n\n public rm(dir: string) {\n this.add('shx');\n return `shx rm -rf ${dir}`;\n }\n\n public mkdir(dir: string) {\n this.add('shx');\n return `shx mkdir -p ${dir}`;\n }\n\n /**\n * Copy the single file a glob matches to `dstDir/dstFileName`, for an artifact\n * whose producer names it — the Smithy OpenAPI plugin writes\n * `<ServiceShape>.openapi.json`. Fails rather than silently doing nothing when\n * the glob matches nothing, or when it matches more than one file.\n *\n * The caller must {@link mkdir} `dstDir` first: `shx cp` writes through to a\n * named destination file and fails if its parent is missing.\n */\n public cpGlobToFile(srcGlob: string, dstDir: string, dstFileName: string) {\n this.add('shx');\n return `shx cp \"${srcGlob}\" ${dstDir}/${dstFileName}`;\n }\n\n private add(dep: (typeof FS_DEPENDENCIES)[number]['name']) {\n addDependenciesToPackageJson(\n this.tree,\n {},\n withVersions(forDependencies<typeof FS_DEPENDENCIES>(this.declaration), [\n dep,\n ]),\n );\n }\n}\n"],"names":["forDependencies","addDependenciesToPackageJson","withVersions","FS_DEPENDENCIES","name","FsCommands","tree","declaration","cpFile","src","dst","add","cpDir","rm","dir","mkdir","cpGlobToFile","srcGlob","dstDir","dstFileName","dep"],"mappings":"AAAA;;;CAGC,GAED,SAEEA,eAAe,QAEV,6BAA6B;AACpC,SAASC,4BAA4B,QAAQ,oBAAoB;AACjE,SAA6BC,YAAY,QAAQ,gBAAgB;AAEjE,4DAA4D,GAC5D,OAAO,MAAMC,kBAAkB;IAAC;QAAEC,MAAM;IAAM;CAAE,CAE5C;AAEJ;;;CAGC,GACD,OAAO,MAAMC;IACHC,KAAW;IACXC,YAAe;IAEvB,YACED,IAAU,EACVC,WAAuD,CACvD;QACA,IAAI,CAACD,IAAI,GAAGA;QACZ,IAAI,CAACC,WAAW,GAAGA;IACrB;IAEA,+EAA+E,GAC/E,AAAOC,OAAOC,GAAW,EAAEC,GAAW,EAAE;QACtC,IAAI,CAACC,GAAG,CAAC;QACT,OAAO,CAAC,OAAO,EAAEF,IAAI,CAAC,EAAEC,KAAK;IAC/B;IAEA;;;;;;;;;GASC,GACD,AAAOE,MAAMH,GAAW,EAAEC,GAAW,EAAE;QACrC,IAAI,CAACC,GAAG,CAAC;QACT,OAAO,CAAC,UAAU,EAAEF,IAAI,GAAG,EAAEC,KAAK;IACpC;IAEOG,GAAGC,GAAW,EAAE;QACrB,IAAI,CAACH,GAAG,CAAC;QACT,OAAO,CAAC,WAAW,EAAEG,KAAK;IAC5B;IAEOC,MAAMD,GAAW,EAAE;QACxB,IAAI,CAACH,GAAG,CAAC;QACT,OAAO,CAAC,aAAa,EAAEG,KAAK;IAC9B;IAEA;;;;;;;;GAQC,GACD,AAAOE,aAAaC,OAAe,EAAEC,MAAc,EAAEC,WAAmB,EAAE;QACxE,IAAI,CAACR,GAAG,CAAC;QACT,OAAO,CAAC,QAAQ,EAAEM,QAAQ,EAAE,EAAEC,OAAO,CAAC,EAAEC,aAAa;IACvD;IAEQR,IAAIS,GAA6C,EAAE;QACzDnB,6BACE,IAAI,CAACK,IAAI,EACT,CAAC,GACDJ,aAAaF,gBAAwC,IAAI,CAACO,WAAW,GAAG;YACtEa;SACD;IAEL;AACF"}
package/src/utils/init.js CHANGED
@@ -12,6 +12,7 @@ import { forDependencies } from "./declared-dependencies.js";
12
12
  import { addDependenciesToPackageJson, detectWorkspacePackageManager } from "./dependencies.js";
13
13
  import { getDefaultBiomeConfig } from "./format.js";
14
14
  import { describeGeneratorForCatalogue, generatorsJsonEntries } from "./generators.js";
15
+ import { updateGitIgnore } from "./git.js";
15
16
  import { configureMcpServers } from "./mcp.js";
16
17
  import { getNpmScope } from "./npm-scope.js";
17
18
  import { mergeTargetDefault, nxPluginMcpDependency, nxPluginSelfDependency } from "./nx.js";
@@ -41,10 +42,11 @@ export const DEFAULT_PARALLEL = 8;
41
42
  }
42
43
  ];
43
44
  // Built dependencies whose install scripts the generated workspace trusts.
44
- // `onlyBuiltDependencies` is the pnpm 10 key (silently ignored by pnpm 11);
45
- // pnpm 11 reads `allowBuilds` instead. Any dep NOT in this allowlist will
46
- // have its install scripts skipped with a warning — matching pnpm 10's
47
- // default behaviour. The user can opt-in later via `pnpm approve-builds`.
45
+ // `onlyBuiltDependencies` is the pnpm 10 key (silently ignored from pnpm 11
46
+ // onwards); pnpm 11 and above read `allowBuilds` instead. Any dep NOT in this
47
+ // allowlist will have its install scripts skipped with a warning — matching
48
+ // pnpm 10's default behaviour. The user can opt-in later via
49
+ // `pnpm approve-builds`.
48
50
  export const PNPM_BUILT_DEPENDENCIES = [
49
51
  '@swc/core',
50
52
  'esbuild',
@@ -101,6 +103,11 @@ export const PNPM_BUILT_DEPENDENCIES = [
101
103
  */ const setUpWorkspaces = (tree, catalogs)=>{
102
104
  if (detectWorkspacePackageManager(tree) === 'pnpm') {
103
105
  setUpPnpmWorkspace(tree, catalogs);
106
+ // pnpm creates these at the workspace root while it materialises packages.
107
+ updateGitIgnore(tree, '.', (patterns)=>[
108
+ ...patterns,
109
+ '_tmp_*'
110
+ ]);
104
111
  } else {
105
112
  updateJson(tree, 'package.json', (json)=>{
106
113
  // The `workspaces` field may be the object form ({ "packages": [...] })
@@ -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 { SYNC_GENERATOR_NAME as TS_SYNC_GENERATOR_NAME } from '../ts/sync/generator.js';\nimport { BASE_TSCONFIG_COMPILER_OPTIONS } from './base-tsconfig.js';\nimport {\n ensureAwsNxPluginConfig,\n updateAwsNxPluginConfig,\n} from './config/utils.js';\nimport { type Containers, inferContainers } from './containers.js';\nimport {\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from './declared-dependencies.js';\nimport {\n addDependenciesToPackageJson,\n detectWorkspacePackageManager,\n} from './dependencies.js';\nimport { getDefaultBiomeConfig } from './format.js';\nimport {\n describeGeneratorForCatalogue,\n generatorsJsonEntries,\n} from './generators.js';\nimport type { Iac } from './iac.js';\nimport { configureMcpServers } from './mcp.js';\nimport { getNpmScope } from './npm-scope.js';\nimport {\n mergeTargetDefault,\n nxPluginMcpDependency,\n nxPluginSelfDependency,\n} from './nx.js';\nimport { getPackageManagerDisplayCommands } from './pkg-manager.js';\nimport { workspaceGlobs } from './project-package-json.js';\nimport { type ITsDepVersion, withVersions } from './versions.js';\n\nconst WORKSPACES = ['packages/*'];\nconst NX_TYPESCRIPT_SYNC_GENERATOR = '@nx/js:typescript-sync';\n\nexport const DEFAULT_PARALLEL = 8;\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 parallel: nxJson.parallel ?? DEFAULT_PARALLEL,\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(generatorsJsonEntries)\n .filter(([, info]) => !info.hidden)\n .map(([id, info]) => ({\n name: id,\n description: describeGeneratorForCatalogue(info),\n })),\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","SYNC_GENERATOR_NAME","TS_SYNC_GENERATOR_NAME","BASE_TSCONFIG_COMPILER_OPTIONS","ensureAwsNxPluginConfig","updateAwsNxPluginConfig","inferContainers","forDependencies","addDependenciesToPackageJson","detectWorkspacePackageManager","getDefaultBiomeConfig","describeGeneratorForCatalogue","generatorsJsonEntries","configureMcpServers","getNpmScope","mergeTargetDefault","nxPluginMcpDependency","nxPluginSelfDependency","getPackageManagerDisplayCommands","workspaceGlobs","withVersions","WORKSPACES","NX_TYPESCRIPT_SYNC_GENERATOR","DEFAULT_PARALLEL","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","parallel","targetDefaults","compile","base","syncGenerators","filter","g","includes","CONVENIENCE_SCRIPTS","dev","build","lint","test","trivy","packageJson","scripts","dirname","projectName","generators","entries","info","hidden","id","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 { SYNC_GENERATOR_NAME as TS_SYNC_GENERATOR_NAME } from '../ts/sync/generator.js';\nimport { BASE_TSCONFIG_COMPILER_OPTIONS } from './base-tsconfig.js';\nimport {\n ensureAwsNxPluginConfig,\n updateAwsNxPluginConfig,\n} from './config/utils.js';\nimport { type Containers, inferContainers } from './containers.js';\nimport {\n type DependencyDeclaration,\n forDependencies,\n type MustDeclare,\n} from './declared-dependencies.js';\nimport {\n addDependenciesToPackageJson,\n detectWorkspacePackageManager,\n} from './dependencies.js';\nimport { getDefaultBiomeConfig } from './format.js';\nimport {\n describeGeneratorForCatalogue,\n generatorsJsonEntries,\n} from './generators.js';\nimport { updateGitIgnore } from './git.js';\nimport type { Iac } from './iac.js';\nimport { configureMcpServers } from './mcp.js';\nimport { getNpmScope } from './npm-scope.js';\nimport {\n mergeTargetDefault,\n nxPluginMcpDependency,\n nxPluginSelfDependency,\n} from './nx.js';\nimport { getPackageManagerDisplayCommands } from './pkg-manager.js';\nimport { workspaceGlobs } from './project-package-json.js';\nimport { type ITsDepVersion, withVersions } from './versions.js';\n\nconst WORKSPACES = ['packages/*'];\nconst NX_TYPESCRIPT_SYNC_GENERATOR = '@nx/js:typescript-sync';\n\nexport const DEFAULT_PARALLEL = 8;\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 from pnpm 11\n// onwards); pnpm 11 and above read `allowBuilds` instead. Any dep NOT in this\n// allowlist will have its install scripts skipped with a warning — matching\n// pnpm 10's default behaviour. The user can opt-in later via\n// `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 // pnpm creates these at the workspace root while it materialises packages.\n updateGitIgnore(tree, '.', (patterns) => [...patterns, '_tmp_*']);\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 parallel: nxJson.parallel ?? DEFAULT_PARALLEL,\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(generatorsJsonEntries)\n .filter(([, info]) => !info.hidden)\n .map(([id, info]) => ({\n name: id,\n description: describeGeneratorForCatalogue(info),\n })),\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","SYNC_GENERATOR_NAME","TS_SYNC_GENERATOR_NAME","BASE_TSCONFIG_COMPILER_OPTIONS","ensureAwsNxPluginConfig","updateAwsNxPluginConfig","inferContainers","forDependencies","addDependenciesToPackageJson","detectWorkspacePackageManager","getDefaultBiomeConfig","describeGeneratorForCatalogue","generatorsJsonEntries","updateGitIgnore","configureMcpServers","getNpmScope","mergeTargetDefault","nxPluginMcpDependency","nxPluginSelfDependency","getPackageManagerDisplayCommands","workspaceGlobs","withVersions","WORKSPACES","NX_TYPESCRIPT_SYNC_GENERATOR","DEFAULT_PARALLEL","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","patterns","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","parallel","targetDefaults","compile","base","syncGenerators","filter","g","includes","CONVENIENCE_SCRIPTS","dev","build","lint","test","trivy","packageJson","scripts","dirname","projectName","generators","entries","info","hidden","id","description","cmds","pkgMgrCmd","exec","buildCmd","run","lintCmd","overwriteStrategy"],"mappings":"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"}
@@ -4,14 +4,14 @@
4
4
  */
5
5
  import type { Tree } from '@nx/devkit';
6
6
  /**
7
- * Merge `allowBuilds` (pnpm 11) / `onlyBuiltDependencies` (pnpm 10) entries
8
- * into the generated workspace's `pnpm-workspace.yaml`. No-op for non-pnpm
9
- * workspaces.
7
+ * Merge `allowBuilds` (pnpm 11 and above) / `onlyBuiltDependencies` (pnpm 10)
8
+ * entries into the generated workspace's `pnpm-workspace.yaml`. No-op for
9
+ * non-pnpm workspaces.
10
10
  *
11
11
  * Generators call this when they introduce a dependency whose install
12
- * script pnpm would otherwise reject under pnpm 11's default
12
+ * script pnpm would otherwise reject under the default
13
13
  * `strictDepBuilds=true`. Keeping the allowlist explicit — rather than
14
- * globally disabling strictness — preserves the supply-chain audit pnpm 11
14
+ * globally disabling strictness — preserves the supply-chain audit pnpm
15
15
  * intends: each build-script dep is reviewed by the generator author and
16
16
  * entered as either `true` (run the script) or `false` (known dep we
17
17
  * don't want to run but have seen).
@@ -5,14 +5,14 @@
5
5
  import { detectWorkspacePackageManager } from "./dependencies.js";
6
6
  const WORKSPACE_FILE = 'pnpm-workspace.yaml';
7
7
  /**
8
- * Merge `allowBuilds` (pnpm 11) / `onlyBuiltDependencies` (pnpm 10) entries
9
- * into the generated workspace's `pnpm-workspace.yaml`. No-op for non-pnpm
10
- * workspaces.
8
+ * Merge `allowBuilds` (pnpm 11 and above) / `onlyBuiltDependencies` (pnpm 10)
9
+ * entries into the generated workspace's `pnpm-workspace.yaml`. No-op for
10
+ * non-pnpm workspaces.
11
11
  *
12
12
  * Generators call this when they introduce a dependency whose install
13
- * script pnpm would otherwise reject under pnpm 11's default
13
+ * script pnpm would otherwise reject under the default
14
14
  * `strictDepBuilds=true`. Keeping the allowlist explicit — rather than
15
- * globally disabling strictness — preserves the supply-chain audit pnpm 11
15
+ * globally disabling strictness — preserves the supply-chain audit pnpm
16
16
  * intends: each build-script dep is reviewed by the generator author and
17
17
  * entered as either `true` (run the script) or `false` (known dep we
18
18
  * don't want to run but have seen).
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/pnpm-workspace.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Tree } from '@nx/devkit';\nimport yaml from 'js-yaml';\nimport { detectWorkspacePackageManager } from './dependencies.js';\n\nconst WORKSPACE_FILE = 'pnpm-workspace.yaml';\n\ninterface PnpmWorkspaceYaml {\n allowBuilds?: Record<string, boolean>;\n onlyBuiltDependencies?: string[];\n [key: string]: unknown;\n}\n\n/**\n * Merge `allowBuilds` (pnpm 11) / `onlyBuiltDependencies` (pnpm 10) entries\n * into the generated workspace's `pnpm-workspace.yaml`. No-op for non-pnpm\n * workspaces.\n *\n * Generators call this when they introduce a dependency whose install\n * script pnpm would otherwise reject under pnpm 11's default\n * `strictDepBuilds=true`. Keeping the allowlist explicit — rather than\n * globally disabling strictness — preserves the supply-chain audit pnpm 11\n * intends: each build-script dep is reviewed by the generator author and\n * entered as either `true` (run the script) or `false` (known dep we\n * don't want to run but have seen).\n *\n * Only `true` entries are also added to `onlyBuiltDependencies` (pnpm 10's\n * allowlist has no equivalent of the `false` decision).\n */\nexport const registerPnpmBuiltDependencies = (\n tree: Tree,\n entries: Record<string, boolean>,\n): void => {\n if (detectWorkspacePackageManager(tree) !== 'pnpm') {\n return;\n }\n if (!tree.exists(WORKSPACE_FILE)) {\n return;\n }\n\n const original = tree.read(WORKSPACE_FILE, 'utf-8') ?? '';\n const parsed = (yaml.load(original) as PnpmWorkspaceYaml | null) ?? {};\n\n const allowBuilds = { ...(parsed.allowBuilds ?? {}) };\n const onlyBuiltDependencies = new Set(parsed.onlyBuiltDependencies ?? []);\n let changed = false;\n\n for (const [pkg, decision] of Object.entries(entries)) {\n if (allowBuilds[pkg] !== decision) {\n allowBuilds[pkg] = decision;\n changed = true;\n }\n if (decision === true && !onlyBuiltDependencies.has(pkg)) {\n onlyBuiltDependencies.add(pkg);\n changed = true;\n }\n }\n\n if (!changed) {\n return;\n }\n\n parsed.allowBuilds = allowBuilds;\n parsed.onlyBuiltDependencies = [...onlyBuiltDependencies];\n\n tree.write(WORKSPACE_FILE, yaml.dump(parsed, { quotingType: \"'\" }));\n};\n"],"names":["yaml","detectWorkspacePackageManager","WORKSPACE_FILE","registerPnpmBuiltDependencies","tree","entries","exists","original","read","parsed","load","allowBuilds","onlyBuiltDependencies","Set","changed","pkg","decision","Object","has","add","write","dump","quotingType"],"mappings":"AAAA;;;CAGC,GAED,OAAOA,UAAU,UAAU;AAC3B,SAASC,6BAA6B,QAAQ,oBAAoB;AAElE,MAAMC,iBAAiB;AAQvB;;;;;;;;;;;;;;;CAeC,GACD,OAAO,MAAMC,gCAAgC,CAC3CC,MACAC;IAEA,IAAIJ,8BAA8BG,UAAU,QAAQ;QAClD;IACF;IACA,IAAI,CAACA,KAAKE,MAAM,CAACJ,iBAAiB;QAChC;IACF;IAEA,MAAMK,WAAWH,KAAKI,IAAI,CAACN,gBAAgB,YAAY;IACvD,MAAMO,SAAS,AAACT,KAAKU,IAAI,CAACH,aAA0C,CAAC;IAErE,MAAMI,cAAc;QAAE,GAAIF,OAAOE,WAAW,IAAI,CAAC,CAAC;IAAE;IACpD,MAAMC,wBAAwB,IAAIC,IAAIJ,OAAOG,qBAAqB,IAAI,EAAE;IACxE,IAAIE,UAAU;IAEd,KAAK,MAAM,CAACC,KAAKC,SAAS,IAAIC,OAAOZ,OAAO,CAACA,SAAU;QACrD,IAAIM,WAAW,CAACI,IAAI,KAAKC,UAAU;YACjCL,WAAW,CAACI,IAAI,GAAGC;YACnBF,UAAU;QACZ;QACA,IAAIE,aAAa,QAAQ,CAACJ,sBAAsBM,GAAG,CAACH,MAAM;YACxDH,sBAAsBO,GAAG,CAACJ;YAC1BD,UAAU;QACZ;IACF;IAEA,IAAI,CAACA,SAAS;QACZ;IACF;IAEAL,OAAOE,WAAW,GAAGA;IACrBF,OAAOG,qBAAqB,GAAG;WAAIA;KAAsB;IAEzDR,KAAKgB,KAAK,CAAClB,gBAAgBF,KAAKqB,IAAI,CAACZ,QAAQ;QAAEa,aAAa;IAAI;AAClE,EAAE"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/pnpm-workspace.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Tree } from '@nx/devkit';\nimport yaml from 'js-yaml';\nimport { detectWorkspacePackageManager } from './dependencies.js';\n\nconst WORKSPACE_FILE = 'pnpm-workspace.yaml';\n\ninterface PnpmWorkspaceYaml {\n allowBuilds?: Record<string, boolean>;\n onlyBuiltDependencies?: string[];\n [key: string]: unknown;\n}\n\n/**\n * Merge `allowBuilds` (pnpm 11 and above) / `onlyBuiltDependencies` (pnpm 10)\n * entries into the generated workspace's `pnpm-workspace.yaml`. No-op for\n * non-pnpm workspaces.\n *\n * Generators call this when they introduce a dependency whose install\n * script pnpm would otherwise reject under the default\n * `strictDepBuilds=true`. Keeping the allowlist explicit — rather than\n * globally disabling strictness — preserves the supply-chain audit pnpm\n * intends: each build-script dep is reviewed by the generator author and\n * entered as either `true` (run the script) or `false` (known dep we\n * don't want to run but have seen).\n *\n * Only `true` entries are also added to `onlyBuiltDependencies` (pnpm 10's\n * allowlist has no equivalent of the `false` decision).\n */\nexport const registerPnpmBuiltDependencies = (\n tree: Tree,\n entries: Record<string, boolean>,\n): void => {\n if (detectWorkspacePackageManager(tree) !== 'pnpm') {\n return;\n }\n if (!tree.exists(WORKSPACE_FILE)) {\n return;\n }\n\n const original = tree.read(WORKSPACE_FILE, 'utf-8') ?? '';\n const parsed = (yaml.load(original) as PnpmWorkspaceYaml | null) ?? {};\n\n const allowBuilds = { ...(parsed.allowBuilds ?? {}) };\n const onlyBuiltDependencies = new Set(parsed.onlyBuiltDependencies ?? []);\n let changed = false;\n\n for (const [pkg, decision] of Object.entries(entries)) {\n if (allowBuilds[pkg] !== decision) {\n allowBuilds[pkg] = decision;\n changed = true;\n }\n if (decision === true && !onlyBuiltDependencies.has(pkg)) {\n onlyBuiltDependencies.add(pkg);\n changed = true;\n }\n }\n\n if (!changed) {\n return;\n }\n\n parsed.allowBuilds = allowBuilds;\n parsed.onlyBuiltDependencies = [...onlyBuiltDependencies];\n\n tree.write(WORKSPACE_FILE, yaml.dump(parsed, { quotingType: \"'\" }));\n};\n"],"names":["yaml","detectWorkspacePackageManager","WORKSPACE_FILE","registerPnpmBuiltDependencies","tree","entries","exists","original","read","parsed","load","allowBuilds","onlyBuiltDependencies","Set","changed","pkg","decision","Object","has","add","write","dump","quotingType"],"mappings":"AAAA;;;CAGC,GAED,OAAOA,UAAU,UAAU;AAC3B,SAASC,6BAA6B,QAAQ,oBAAoB;AAElE,MAAMC,iBAAiB;AAQvB;;;;;;;;;;;;;;;CAeC,GACD,OAAO,MAAMC,gCAAgC,CAC3CC,MACAC;IAEA,IAAIJ,8BAA8BG,UAAU,QAAQ;QAClD;IACF;IACA,IAAI,CAACA,KAAKE,MAAM,CAACJ,iBAAiB;QAChC;IACF;IAEA,MAAMK,WAAWH,KAAKI,IAAI,CAACN,gBAAgB,YAAY;IACvD,MAAMO,SAAS,AAACT,KAAKU,IAAI,CAACH,aAA0C,CAAC;IAErE,MAAMI,cAAc;QAAE,GAAIF,OAAOE,WAAW,IAAI,CAAC,CAAC;IAAE;IACpD,MAAMC,wBAAwB,IAAIC,IAAIJ,OAAOG,qBAAqB,IAAI,EAAE;IACxE,IAAIE,UAAU;IAEd,KAAK,MAAM,CAACC,KAAKC,SAAS,IAAIC,OAAOZ,OAAO,CAACA,SAAU;QACrD,IAAIM,WAAW,CAACI,IAAI,KAAKC,UAAU;YACjCL,WAAW,CAACI,IAAI,GAAGC;YACnBF,UAAU;QACZ;QACA,IAAIE,aAAa,QAAQ,CAACJ,sBAAsBM,GAAG,CAACH,MAAM;YACxDH,sBAAsBO,GAAG,CAACJ;YAC1BD,UAAU;QACZ;IACF;IAEA,IAAI,CAACA,SAAS;QACZ;IACF;IAEAL,OAAOE,WAAW,GAAGA;IACrBF,OAAOG,qBAAqB,GAAG;WAAIA;KAAsB;IAEzDR,KAAKgB,KAAK,CAAClB,gBAAgBF,KAAKqB,IAAI,CAACZ,QAAQ;QAAEa,aAAa;IAAI;AAClE,EAAE"}
@@ -28,4 +28,13 @@ export declare const SHADCN_DEPENDENCIES: readonly [{
28
28
  }, {
29
29
  readonly name: "@vitest/coverage-v8";
30
30
  }];
31
+ /** The shared shadcn package's fully-qualified npm name for this workspace. */
32
+ export declare const getSharedShadcnFullyQualifiedName: (tree: Tree) => string;
33
+ /**
34
+ * Declares a `workspace:*` dependency on the shared shadcn package in a
35
+ * consumer's own package.json, so it resolves through the shared package's
36
+ * `exports` map (real package resolution) rather than a tsconfig `paths`
37
+ * alias - see `sharedShadcnGenerator` for why.
38
+ */
39
+ export declare const addSharedShadcnDependency: (tree: Tree, consumerDir: string) => void;
31
40
  export declare function sharedShadcnGenerator<const D extends DependencyDeclaration>(tree: Tree, declaration: D & MustDeclare<typeof SHADCN_DEPENDENCIES, D>): Promise<void>;
@@ -6,7 +6,7 @@ import tsProjectGenerator from "../ts/lib/generator.js";
6
6
  import { configureTsProject } from "../ts/lib/ts-project-utils.js";
7
7
  import { VITEST_DEPENDENCIES } from "../ts/lib/vitest.js";
8
8
  import { declaredNames, forDependencies } from "./declared-dependencies.js";
9
- import { addDependenciesToPackageJson } from "./dependencies.js";
9
+ import { addDependenciesToPackageJson, getLocalDependencySpecifier } from "./dependencies.js";
10
10
  import { formatFilesInSubtree } from "./format.js";
11
11
  import { esmVars } from "./module-format.js";
12
12
  import { getNpmScopePrefix } from "./npm-scope.js";
@@ -39,11 +39,19 @@ import { withVersions } from "./versions.js";
39
39
  },
40
40
  ...VITEST_DEPENDENCIES
41
41
  ];
42
+ /** The shared shadcn package's fully-qualified npm name for this workspace. */ export const getSharedShadcnFullyQualifiedName = (tree)=>`${getNpmScopePrefix(tree)}${SHARED_SHADCN_NAME}`;
43
+ /**
44
+ * Declares a `workspace:*` dependency on the shared shadcn package in a
45
+ * consumer's own package.json, so it resolves through the shared package's
46
+ * `exports` map (real package resolution) rather than a tsconfig `paths`
47
+ * alias - see `sharedShadcnGenerator` for why.
48
+ */ export const addSharedShadcnDependency = (tree, consumerDir)=>{
49
+ addDependenciesToPackageJson(tree, {
50
+ [getSharedShadcnFullyQualifiedName(tree)]: getLocalDependencySpecifier(tree)
51
+ }, {}, joinPathFragments(consumerDir, 'package.json'));
52
+ };
42
53
  export async function sharedShadcnGenerator(tree, declaration) {
43
- const npmScopePrefix = getNpmScopePrefix(tree);
44
- const scopeAlias = npmScopePrefix;
45
- const sharedShadcnAlias = `${scopeAlias}${SHARED_SHADCN_NAME}`;
46
- const fullyQualifiedName = `${npmScopePrefix}${SHARED_SHADCN_NAME}`;
54
+ const fullyQualifiedName = getSharedShadcnFullyQualifiedName(tree);
47
55
  const libraryRoot = joinPathFragments(PACKAGES_DIR, SHARED_SHADCN_DIR);
48
56
  const shadcnSrcRoot = joinPathFragments(libraryRoot, 'src');
49
57
  if (!tree.exists(joinPathFragments(libraryRoot, 'project.json'))) {
@@ -53,15 +61,11 @@ export async function sharedShadcnGenerator(tree, declaration) {
53
61
  subDirectory: SHARED_SHADCN_DIR
54
62
  });
55
63
  tree.delete(shadcnSrcRoot);
56
- generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', SHARED_SHADCN_DIR, 'src'), shadcnSrcRoot, {
57
- scopeAlias,
58
- ...esmVars(tree)
59
- }, {
64
+ generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', SHARED_SHADCN_DIR, 'src'), shadcnSrcRoot, esmVars(tree), {
60
65
  overwriteStrategy: OverwriteStrategy.KeepExisting
61
66
  });
62
67
  generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', SHARED_SHADCN_DIR, 'readme'), libraryRoot, {
63
- fullyQualifiedName,
64
- scopeAlias
68
+ fullyQualifiedName
65
69
  }, {
66
70
  overwriteStrategy: OverwriteStrategy.Overwrite
67
71
  });
@@ -87,25 +91,31 @@ export async function sharedShadcnGenerator(tree, declaration) {
87
91
  ]))
88
92
  }));
89
93
  addDependenciesToPackageJson(tree, withVersions(forDependencies(declaration), declaredNames(SHADCN_DEPENDENCIES)), {}, joinPathFragments(libraryRoot, 'package.json'));
90
- }
91
- updateJson(tree, 'tsconfig.base.json', (json)=>({
92
- ...json,
93
- compilerOptions: {
94
- ...json.compilerOptions,
95
- paths: {
96
- ...json.compilerOptions?.paths ?? {},
97
- [`${sharedShadcnAlias}/*`]: [
98
- `./${joinPathFragments(libraryRoot, 'src', '*')}`
99
- ]
94
+ // shadcn 4.x's CLI resolves the `components.json` alias via `imports`/
95
+ // `exports` (Node's package resolution), not a tsconfig `paths` alias.
96
+ // `imports` covers this package's own internal component-to-component
97
+ // references (aliased in components.json below); `exports` covers every
98
+ // other consumer.
99
+ updateJson(tree, joinPathFragments(libraryRoot, 'package.json'), (packageJson)=>({
100
+ ...packageJson,
101
+ imports: {
102
+ '#components/*': './src/components/*.tsx',
103
+ '#lib/*': './src/lib/*.ts',
104
+ '#hooks/*': './src/hooks/*.ts'
105
+ },
106
+ exports: {
107
+ '.': './src/index.ts',
108
+ './styles/*': './src/styles/*',
109
+ './components/*': './src/components/*.tsx',
110
+ './lib/*': './src/lib/*.ts',
111
+ './hooks/*': './src/hooks/*.ts'
100
112
  }
101
- }
102
- }));
113
+ }));
114
+ }
103
115
  // components.json lives in the package so `shadcn add` runs there and
104
116
  // installs component dependencies into the package's own manifest.
105
117
  if (!tree.exists(joinPathFragments(libraryRoot, 'components.json'))) {
106
- generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'shadcn'), libraryRoot, {
107
- sharedShadcnAlias
108
- }, {
118
+ generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'shadcn'), libraryRoot, {}, {
109
119
  overwriteStrategy: OverwriteStrategy.KeepExisting
110
120
  });
111
121
  }