@aws/nx-plugin 1.0.0-rc.45 → 1.0.0-rc.47

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 (165) hide show
  1. package/LICENSE-THIRD-PARTY +3 -60
  2. package/generators.json +9 -9
  3. package/package.json +7 -3
  4. package/src/agentcore-gateway/generator.js +12 -2
  5. package/src/agentcore-gateway/generator.js.map +1 -1
  6. package/src/infra/app/__snapshots__/generator.spec.ts.snap +25 -31
  7. package/src/infra/app/generator.js +9 -6
  8. package/src/infra/app/generator.js.map +1 -1
  9. package/src/license/config.js +1 -1
  10. package/src/license/config.js.map +1 -1
  11. package/src/mcp-server/schema.d.ts +1 -1
  12. package/src/mcp-server/tools/general-guidance.js +5 -6
  13. package/src/mcp-server/tools/general-guidance.js.map +1 -1
  14. package/src/preset/__snapshots__/generator.spec.ts.snap +38 -7
  15. package/src/preset/generator.d.ts +1 -1
  16. package/src/preset/generator.js +4 -2
  17. package/src/preset/generator.js.map +1 -1
  18. package/src/preset/schema.d.js.map +1 -1
  19. package/src/preset/schema.d.ts +1 -0
  20. package/src/preset/schema.json +5 -0
  21. package/src/py/agent/generator.js +2 -1
  22. package/src/py/agent/generator.js.map +1 -1
  23. package/src/py/mcp-server/generator.js +2 -1
  24. package/src/py/mcp-server/generator.js.map +1 -1
  25. package/src/py/project/generator.js +2 -1
  26. package/src/py/project/generator.js.map +1 -1
  27. package/src/py/rdb/__snapshots__/generator.spec.ts.snap +1 -0
  28. package/src/py/rdb/generator.js +7 -1
  29. package/src/py/rdb/generator.js.map +1 -1
  30. package/src/smithy/ts/api/generator.js +5 -2
  31. package/src/smithy/ts/api/generator.js.map +1 -1
  32. package/src/terraform/project/generator.js +4 -1
  33. package/src/terraform/project/generator.js.map +1 -1
  34. package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +6 -6
  35. package/src/trpc/backend/generator.js +7 -5
  36. package/src/trpc/backend/generator.js.map +1 -1
  37. package/src/trpc/react/generator.js +4 -4
  38. package/src/trpc/react/generator.js.map +1 -1
  39. package/src/ts/agent/__snapshots__/generator.spec.ts.snap +2 -2
  40. package/src/ts/agent/a2a-connection/generator.js +3 -2
  41. package/src/ts/agent/a2a-connection/generator.js.map +1 -1
  42. package/src/ts/agent/gateway-connection/generator.js +4 -3
  43. package/src/ts/agent/gateway-connection/generator.js.map +1 -1
  44. package/src/ts/agent/generator.js +8 -5
  45. package/src/ts/agent/generator.js.map +1 -1
  46. package/src/ts/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +1 -1
  47. package/src/ts/agent/mcp-connection/generator.js +4 -3
  48. package/src/ts/agent/mcp-connection/generator.js.map +1 -1
  49. package/src/ts/agent/react-connection/generator.js +10 -19
  50. package/src/ts/agent/react-connection/generator.js.map +1 -1
  51. package/src/ts/astro-docs/generator.js +12 -3
  52. package/src/ts/astro-docs/generator.js.map +1 -1
  53. package/src/ts/dcr-proxy/generator.js +5 -5
  54. package/src/ts/dcr-proxy/generator.js.map +1 -1
  55. package/src/ts/dynamodb/generator.js +5 -2
  56. package/src/ts/dynamodb/generator.js.map +1 -1
  57. package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +4 -2
  58. package/src/ts/lambda-function/files/handler/__lambdaFunctionKebabCase__.ts.template +2 -1
  59. package/src/ts/lambda-function/generator.js +3 -2
  60. package/src/ts/lambda-function/generator.js.map +1 -1
  61. package/src/ts/lib/ts-project-utils.js +17 -10
  62. package/src/ts/lib/ts-project-utils.js.map +1 -1
  63. package/src/ts/lib/vitest.js +2 -1
  64. package/src/ts/lib/vitest.js.map +1 -1
  65. package/src/ts/mcp-server/generator.js +11 -11
  66. package/src/ts/mcp-server/generator.js.map +1 -1
  67. package/src/ts/nx-generator/generator.js +5 -0
  68. package/src/ts/nx-generator/generator.js.map +1 -1
  69. package/src/ts/nx-plugin/__snapshots__/generator.spec.ts.snap +5 -6
  70. package/src/ts/nx-plugin/files/mcp-server/resources/GENERAL_GUIDANCE.md.template +5 -6
  71. package/src/ts/nx-plugin/utils.js +2 -1
  72. package/src/ts/nx-plugin/utils.js.map +1 -1
  73. package/src/ts/rdb/agent-connection/generator.js +1 -2
  74. package/src/ts/rdb/agent-connection/generator.js.map +1 -1
  75. package/src/ts/rdb/generator.js +10 -6
  76. package/src/ts/rdb/generator.js.map +1 -1
  77. package/src/ts/rdb/mcp-server-connection/generator.js +1 -2
  78. package/src/ts/rdb/mcp-server-connection/generator.js.map +1 -1
  79. package/src/ts/rdb/smithy-connection/generator.js +1 -2
  80. package/src/ts/rdb/smithy-connection/generator.js.map +1 -1
  81. package/src/ts/rdb/trpc-connection/generator.js +1 -2
  82. package/src/ts/rdb/trpc-connection/generator.js.map +1 -1
  83. package/src/ts/react-website/agui/generator.js +5 -4
  84. package/src/ts/react-website/agui/generator.js.map +1 -1
  85. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +219 -79
  86. package/src/ts/react-website/app/generator.js +34 -14
  87. package/src/ts/react-website/app/generator.js.map +1 -1
  88. package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +11 -6
  89. package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +12 -2
  90. package/src/ts/react-website/cognito-auth/generator.js +3 -2
  91. package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
  92. package/src/ts/react-website/runtime-config/generator.js +2 -2
  93. package/src/ts/react-website/runtime-config/generator.js.map +1 -1
  94. package/src/ts/sync/generator.js +81 -3
  95. package/src/ts/sync/generator.js.map +1 -1
  96. package/src/utils/agent-connection/agent-connection.d.ts +1 -1
  97. package/src/utils/agent-connection/agent-connection.js +50 -1
  98. package/src/utils/agent-connection/agent-connection.js.map +1 -1
  99. package/src/utils/agent-core-constructs/agent-core-constructs.js +10 -1
  100. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  101. package/src/utils/api-constructs/api-constructs.js +15 -1
  102. package/src/utils/api-constructs/api-constructs.js.map +1 -1
  103. package/src/utils/bundle/bundle.js +2 -1
  104. package/src/utils/bundle/bundle.js.map +1 -1
  105. package/src/utils/commands.d.ts +5 -3
  106. package/src/utils/commands.js +24 -3
  107. package/src/utils/commands.js.map +1 -1
  108. package/src/utils/config/index.d.ts +16 -0
  109. package/src/utils/config/index.js.map +1 -1
  110. package/src/utils/config/utils.d.ts +3 -2
  111. package/src/utils/config/utils.js +4 -3
  112. package/src/utils/config/utils.js.map +1 -1
  113. package/src/utils/connection/open-api/react.js +3 -2
  114. package/src/utils/connection/open-api/react.js.map +1 -1
  115. package/src/utils/containers.js +1 -1
  116. package/src/utils/containers.js.map +1 -1
  117. package/src/utils/dependencies.d.ts +18 -0
  118. package/src/utils/dependencies.js +206 -0
  119. package/src/utils/dependencies.js.map +1 -0
  120. package/src/utils/files/common/shadcn/readme/README.md.template +3 -3
  121. package/src/utils/files/shadcn/components.json.template +1 -1
  122. package/src/utils/format.d.ts +20 -1
  123. package/src/utils/format.js +83 -49
  124. package/src/utils/format.js.map +1 -1
  125. package/src/utils/fs.d.ts +1 -1
  126. package/src/utils/fs.js +1 -1
  127. package/src/utils/fs.js.map +1 -1
  128. package/src/utils/iac.js +1 -1
  129. package/src/utils/iac.js.map +1 -1
  130. package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +11 -6
  131. package/src/utils/identity-constructs/identity-constructs.js +14 -3
  132. package/src/utils/identity-constructs/identity-constructs.js.map +1 -1
  133. package/src/utils/init.d.ts +7 -1
  134. package/src/utils/init.js +38 -17
  135. package/src/utils/init.js.map +1 -1
  136. package/src/utils/install.js +3 -1
  137. package/src/utils/install.js.map +1 -1
  138. package/src/utils/module-format.d.ts +5 -8
  139. package/src/utils/module-format.js +29 -12
  140. package/src/utils/module-format.js.map +1 -1
  141. package/src/utils/npm-scope.d.ts +0 -4
  142. package/src/utils/npm-scope.js +0 -5
  143. package/src/utils/npm-scope.js.map +1 -1
  144. package/src/utils/pnpm-workspace.d.ts +1 -12
  145. package/src/utils/pnpm-workspace.js +3 -30
  146. package/src/utils/pnpm-workspace.js.map +1 -1
  147. package/src/utils/project-package-json.d.ts +39 -0
  148. package/src/utils/project-package-json.js +119 -0
  149. package/src/utils/project-package-json.js.map +1 -0
  150. package/src/utils/shared-constructs.js +6 -5
  151. package/src/utils/shared-constructs.js.map +1 -1
  152. package/src/utils/shared-dynamodb-scripts.js +4 -2
  153. package/src/utils/shared-dynamodb-scripts.js.map +1 -1
  154. package/src/utils/shared-infra-scripts.js +5 -4
  155. package/src/utils/shared-infra-scripts.js.map +1 -1
  156. package/src/utils/shared-rdb-scripts.js +14 -1
  157. package/src/utils/shared-rdb-scripts.js.map +1 -1
  158. package/src/utils/shared-shadcn.js +11 -8
  159. package/src/utils/shared-shadcn.js.map +1 -1
  160. package/src/utils/test.js +8 -3
  161. package/src/utils/test.js.map +1 -1
  162. package/src/utils/versions.d.ts +4 -0
  163. package/src/utils/versions.js +8 -1
  164. package/src/utils/versions.js.map +1 -1
  165. package/src/utils/website-constructs/files/cdk/core/static-website.ts.template +3 -0
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */ import { detectPackageManager, addDependenciesToPackageJson as devkitAddDependenciesToPackageJson, getPackageManagerVersion, readJson, updateJson } from "@nx/devkit";
5
+ import yaml from "js-yaml";
6
+ import { coerce, gt, gte } from "semver";
7
+ import { readAwsNxPluginConfig } from "./config/utils.js";
8
+ // Minimum version that introduced catalog support per package manager (npm has none).
9
+ const CATALOG_SUPPORT = {
10
+ pnpm: '9.5.0',
11
+ yarn: '4.10.0',
12
+ bun: '1.2.14'
13
+ };
14
+ // Prefer tree markers over devkit's `detectPackageManager`, which reads the
15
+ // real filesystem and is nondeterministic for virtual trees in tests.
16
+ export const detectWorkspacePackageManager = (tree)=>tree.exists('pnpm-workspace.yaml') ? 'pnpm' : detectPackageManager(tree.root);
17
+ // Coerce a single simple range to a version. Rejects compound ranges
18
+ // (whitespace / `||`), which coerce would silently reduce, plus tags/protocols.
19
+ const parseSimpleRange = (version)=>{
20
+ const trimmed = version.trim();
21
+ if (/\s|\|\|/.test(trimmed)) {
22
+ return undefined;
23
+ }
24
+ return coerce(trimmed, {
25
+ includePrerelease: true
26
+ }) ?? undefined;
27
+ };
28
+ const versionAtLeast = (version, minimum)=>gte(parseSimpleRange(version) ?? '0.0.0', parseSimpleRange(minimum) ?? '0.0.0');
29
+ // Only a strict upgrade replaces an existing catalog entry, so generating a
30
+ // project never downgrades a version the user raised. Uncomparable entries
31
+ // (tags, complex ranges) are kept.
32
+ const isVersionUpgrade = (incoming, existing)=>{
33
+ const existingParsed = parseSimpleRange(existing);
34
+ const incomingParsed = parseSimpleRange(incoming);
35
+ if (!existingParsed || !incomingParsed) {
36
+ return false;
37
+ }
38
+ return gt(incomingParsed, existingParsed);
39
+ };
40
+ // Keyed by root + package manager; detecting support shells out for a version.
41
+ const catalogSupportCache = new Map();
42
+ /** Clears the catalog support cache. Only needed by tests. */ export const resetCatalogSupportCache = ()=>{
43
+ catalogSupportCache.clear();
44
+ };
45
+ // Local-project specifier: the `workspace:` protocol where supported (pnpm,
46
+ // bun, yarn berry), `*` on npm and yarn classic which reject it.
47
+ export const getLocalDependencySpecifier = (tree)=>{
48
+ const packageManager = detectWorkspacePackageManager(tree);
49
+ if (packageManager === 'npm') {
50
+ return '*';
51
+ }
52
+ if (packageManager === 'yarn') {
53
+ let major = 2;
54
+ try {
55
+ major = Number.parseInt(getPackageManagerVersion('yarn', tree.root).split('.')[0], 10);
56
+ } catch {
57
+ // Not installed (e.g. tests) — assume berry.
58
+ }
59
+ if (major < 2) {
60
+ return '*';
61
+ }
62
+ }
63
+ return 'workspace:*';
64
+ };
65
+ export const supportsCatalogs = (tree)=>{
66
+ const packageManager = detectWorkspacePackageManager(tree);
67
+ const cacheKey = `${tree.root}|${packageManager}`;
68
+ const cached = catalogSupportCache.get(cacheKey);
69
+ if (cached !== undefined) {
70
+ return cached;
71
+ }
72
+ const minimumVersion = CATALOG_SUPPORT[packageManager];
73
+ let supported = false;
74
+ if (minimumVersion) {
75
+ try {
76
+ supported = versionAtLeast(getPackageManagerVersion(packageManager, tree.root), minimumVersion);
77
+ } catch {
78
+ // Not installed (e.g. tests) — assume a modern version.
79
+ supported = true;
80
+ }
81
+ }
82
+ catalogSupportCache.set(cacheKey, supported);
83
+ return supported;
84
+ };
85
+ // True when the package manager supports catalogs and the workspace hasn't
86
+ // opted out via `packageManager.catalogs: false` in aws-nx-plugin.config.mts.
87
+ export const catalogsEnabled = (tree)=>{
88
+ if (!supportsCatalogs(tree)) {
89
+ return false;
90
+ }
91
+ const config = readAwsNxPluginConfig(tree);
92
+ return config?.packageManager?.catalogs !== false;
93
+ };
94
+ /**
95
+ * Drop-in replacement for devkit's `addDependenciesToPackageJson` that records
96
+ * versions in the package manager's catalog when enabled. Callers pass a
97
+ * project manifest path for runtime deps (so `noUndeclaredDependencies` passes)
98
+ * and the root for shared tooling.
99
+ */ export const addDependenciesToPackageJson = (tree, dependencies, devDependencies, packageJsonPath = 'package.json')=>{
100
+ const callback = devkitAddDependenciesToPackageJson(tree, dependencies, devDependencies, packageJsonPath);
101
+ if (catalogsEnabled(tree)) {
102
+ const packageNames = [
103
+ ...Object.keys(dependencies),
104
+ ...Object.keys(devDependencies)
105
+ ];
106
+ convertDependenciesToCatalog(tree, packageJsonPath, packageNames);
107
+ // Convert any matching root ranges Nx wrote behind our back (e.g.
108
+ // `@types/node`, `react`) so they don't resolve to a second copy alongside
109
+ // the catalog version. Skipped when the caller already targeted the root.
110
+ if (packageJsonPath !== 'package.json') {
111
+ convertDependenciesToCatalog(tree, 'package.json', packageNames);
112
+ }
113
+ }
114
+ return callback;
115
+ };
116
+ // Nx generators read these versions from the root manifest and coerce without
117
+ // a null guard; Nx ships no bun catalog manager, so an unresolved `catalog:`
118
+ // crashes them. Keep direct ranges on bun (react-dom pinned with react).
119
+ const BUN_INTROSPECTED_PACKAGES = new Set([
120
+ 'vite',
121
+ 'react',
122
+ 'react-dom'
123
+ ]);
124
+ const isCatalogExcluded = (tree, packageName)=>detectWorkspacePackageManager(tree) === 'bun' && BUN_INTROSPECTED_PACKAGES.has(packageName);
125
+ // Convert direct version ranges to `catalog:` references in a single manifest
126
+ // and record the range in the workspace catalog. Protocol specifiers
127
+ // (catalog:/workspace:/...) are left alone.
128
+ const convertDependenciesToCatalog = (tree, packageJsonPath, packageNames)=>{
129
+ const catalogUpdates = {};
130
+ updateJson(tree, packageJsonPath, (json)=>{
131
+ for (const field of [
132
+ 'dependencies',
133
+ 'devDependencies'
134
+ ]){
135
+ for (const packageName of packageNames){
136
+ const version = json[field]?.[packageName];
137
+ if (version && !version.includes(':') && !isCatalogExcluded(tree, packageName)) {
138
+ catalogUpdates[packageName] = version;
139
+ json[field][packageName] = 'catalog:';
140
+ }
141
+ }
142
+ }
143
+ return json;
144
+ });
145
+ if (Object.keys(catalogUpdates).length > 0) {
146
+ writeCatalogVersions(tree, catalogUpdates);
147
+ }
148
+ };
149
+ // Record ranges in the default catalog, creating it if absent. Only strict
150
+ // upgrades replace existing entries (see `isVersionUpgrade`).
151
+ const writeCatalogVersions = (tree, updates)=>{
152
+ const applyUpdates = (catalog)=>{
153
+ const existing = catalog ?? {};
154
+ const applicable = Object.fromEntries(Object.entries(updates).filter(([name, version])=>existing[name] === undefined || isVersionUpgrade(version, existing[name])));
155
+ if (Object.keys(applicable).length === 0) {
156
+ return undefined;
157
+ }
158
+ return {
159
+ ...existing,
160
+ ...applicable
161
+ };
162
+ };
163
+ switch(detectWorkspacePackageManager(tree)){
164
+ case 'pnpm':
165
+ {
166
+ const workspaceYaml = yaml.load(tree.read('pnpm-workspace.yaml', 'utf-8') ?? '') ?? {};
167
+ const catalog = applyUpdates(workspaceYaml.catalog);
168
+ if (catalog) {
169
+ tree.write('pnpm-workspace.yaml', yaml.dump({
170
+ ...workspaceYaml,
171
+ catalog
172
+ }, {
173
+ quotingType: "'"
174
+ }));
175
+ }
176
+ break;
177
+ }
178
+ case 'yarn':
179
+ {
180
+ const yarnRc = yaml.load(tree.read('.yarnrc.yml', 'utf-8') ?? '') ?? {};
181
+ const catalog = applyUpdates(yarnRc.catalog);
182
+ if (catalog) {
183
+ tree.write('.yarnrc.yml', yaml.dump({
184
+ ...yarnRc,
185
+ catalog
186
+ }, {
187
+ quotingType: "'"
188
+ }));
189
+ }
190
+ break;
191
+ }
192
+ case 'bun':
193
+ {
194
+ const catalog = applyUpdates(readJson(tree, 'package.json').catalog);
195
+ if (catalog) {
196
+ updateJson(tree, 'package.json', (json)=>({
197
+ ...json,
198
+ catalog
199
+ }));
200
+ }
201
+ break;
202
+ }
203
+ }
204
+ };
205
+
206
+ //# sourceMappingURL=dependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/dependencies.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n detectPackageManager,\n addDependenciesToPackageJson as devkitAddDependenciesToPackageJson,\n type GeneratorCallback,\n getPackageManagerVersion,\n type PackageManager,\n readJson,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport yaml from 'js-yaml';\nimport { coerce, gt, gte } from 'semver';\nimport { readAwsNxPluginConfig } from './config/utils';\n\n// Minimum version that introduced catalog support per package manager (npm has none).\nconst CATALOG_SUPPORT: Partial<Record<PackageManager, string>> = {\n pnpm: '9.5.0',\n yarn: '4.10.0',\n bun: '1.2.14',\n};\n\n// Prefer tree markers over devkit's `detectPackageManager`, which reads the\n// real filesystem and is nondeterministic for virtual trees in tests.\nexport const detectWorkspacePackageManager = (tree: Tree): PackageManager =>\n tree.exists('pnpm-workspace.yaml') ? 'pnpm' : detectPackageManager(tree.root);\n\n// Coerce a single simple range to a version. Rejects compound ranges\n// (whitespace / `||`), which coerce would silently reduce, plus tags/protocols.\nconst parseSimpleRange = (version: string) => {\n const trimmed = version.trim();\n if (/\\s|\\|\\|/.test(trimmed)) {\n return undefined;\n }\n return coerce(trimmed, { includePrerelease: true }) ?? undefined;\n};\n\nconst versionAtLeast = (version: string, minimum: string): boolean =>\n gte(\n parseSimpleRange(version) ?? '0.0.0',\n parseSimpleRange(minimum) ?? '0.0.0',\n );\n\n// Only a strict upgrade replaces an existing catalog entry, so generating a\n// project never downgrades a version the user raised. Uncomparable entries\n// (tags, complex ranges) are kept.\nconst isVersionUpgrade = (incoming: string, existing: string): boolean => {\n const existingParsed = parseSimpleRange(existing);\n const incomingParsed = parseSimpleRange(incoming);\n if (!existingParsed || !incomingParsed) {\n return false;\n }\n return gt(incomingParsed, existingParsed);\n};\n\n// Keyed by root + package manager; detecting support shells out for a version.\nconst catalogSupportCache = new Map<string, boolean>();\n\n/** Clears the catalog support cache. Only needed by tests. */\nexport const resetCatalogSupportCache = (): void => {\n catalogSupportCache.clear();\n};\n\n// Local-project specifier: the `workspace:` protocol where supported (pnpm,\n// bun, yarn berry), `*` on npm and yarn classic which reject it.\nexport const getLocalDependencySpecifier = (tree: Tree): string => {\n const packageManager = detectWorkspacePackageManager(tree);\n if (packageManager === 'npm') {\n return '*';\n }\n if (packageManager === 'yarn') {\n let major = 2;\n try {\n major = Number.parseInt(\n getPackageManagerVersion('yarn', tree.root).split('.')[0],\n 10,\n );\n } catch {\n // Not installed (e.g. tests) — assume berry.\n }\n if (major < 2) {\n return '*';\n }\n }\n return 'workspace:*';\n};\n\nexport const supportsCatalogs = (tree: Tree): boolean => {\n const packageManager = detectWorkspacePackageManager(tree);\n const cacheKey = `${tree.root}|${packageManager}`;\n const cached = catalogSupportCache.get(cacheKey);\n if (cached !== undefined) {\n return cached;\n }\n const minimumVersion = CATALOG_SUPPORT[packageManager];\n let supported = false;\n if (minimumVersion) {\n try {\n supported = versionAtLeast(\n getPackageManagerVersion(packageManager, tree.root),\n minimumVersion,\n );\n } catch {\n // Not installed (e.g. tests) — assume a modern version.\n supported = true;\n }\n }\n catalogSupportCache.set(cacheKey, supported);\n return supported;\n};\n\n// True when the package manager supports catalogs and the workspace hasn't\n// opted out via `packageManager.catalogs: false` in aws-nx-plugin.config.mts.\nexport const catalogsEnabled = (tree: Tree): boolean => {\n if (!supportsCatalogs(tree)) {\n return false;\n }\n const config = readAwsNxPluginConfig(tree);\n return config?.packageManager?.catalogs !== false;\n};\n\n/**\n * Drop-in replacement for devkit's `addDependenciesToPackageJson` that records\n * versions in the package manager's catalog when enabled. Callers pass a\n * project manifest path for runtime deps (so `noUndeclaredDependencies` passes)\n * and the root for shared tooling.\n */\nexport const addDependenciesToPackageJson = (\n tree: Tree,\n dependencies: Record<string, string>,\n devDependencies: Record<string, string>,\n packageJsonPath = 'package.json',\n): GeneratorCallback => {\n const callback = devkitAddDependenciesToPackageJson(\n tree,\n dependencies,\n devDependencies,\n packageJsonPath,\n );\n\n if (catalogsEnabled(tree)) {\n const packageNames = [\n ...Object.keys(dependencies),\n ...Object.keys(devDependencies),\n ];\n convertDependenciesToCatalog(tree, packageJsonPath, packageNames);\n // Convert any matching root ranges Nx wrote behind our back (e.g.\n // `@types/node`, `react`) so they don't resolve to a second copy alongside\n // the catalog version. Skipped when the caller already targeted the root.\n if (packageJsonPath !== 'package.json') {\n convertDependenciesToCatalog(tree, 'package.json', packageNames);\n }\n }\n\n return callback;\n};\n\n// Nx generators read these versions from the root manifest and coerce without\n// a null guard; Nx ships no bun catalog manager, so an unresolved `catalog:`\n// crashes them. Keep direct ranges on bun (react-dom pinned with react).\nconst BUN_INTROSPECTED_PACKAGES = new Set<string>([\n 'vite',\n 'react',\n 'react-dom',\n]);\n\nconst isCatalogExcluded = (tree: Tree, packageName: string): boolean =>\n detectWorkspacePackageManager(tree) === 'bun' &&\n BUN_INTROSPECTED_PACKAGES.has(packageName);\n\n// Convert direct version ranges to `catalog:` references in a single manifest\n// and record the range in the workspace catalog. Protocol specifiers\n// (catalog:/workspace:/...) are left alone.\nconst convertDependenciesToCatalog = (\n tree: Tree,\n packageJsonPath: string,\n packageNames: string[],\n): void => {\n const catalogUpdates: Record<string, string> = {};\n\n updateJson(tree, packageJsonPath, (json) => {\n for (const field of ['dependencies', 'devDependencies'] as const) {\n for (const packageName of packageNames) {\n const version = json[field]?.[packageName];\n if (\n version &&\n !version.includes(':') &&\n !isCatalogExcluded(tree, packageName)\n ) {\n catalogUpdates[packageName] = version;\n json[field][packageName] = 'catalog:';\n }\n }\n }\n return json;\n });\n\n if (Object.keys(catalogUpdates).length > 0) {\n writeCatalogVersions(tree, catalogUpdates);\n }\n};\n\n// Record ranges in the default catalog, creating it if absent. Only strict\n// upgrades replace existing entries (see `isVersionUpgrade`).\nconst writeCatalogVersions = (\n tree: Tree,\n updates: Record<string, string>,\n): void => {\n const applyUpdates = (\n catalog: Record<string, string> | undefined,\n ): Record<string, string> | undefined => {\n const existing = catalog ?? {};\n const applicable = Object.fromEntries(\n Object.entries(updates).filter(\n ([name, version]) =>\n existing[name] === undefined ||\n isVersionUpgrade(version, existing[name]),\n ),\n );\n if (Object.keys(applicable).length === 0) {\n return undefined;\n }\n return { ...existing, ...applicable };\n };\n\n switch (detectWorkspacePackageManager(tree)) {\n case 'pnpm': {\n const workspaceYaml =\n (yaml.load(tree.read('pnpm-workspace.yaml', 'utf-8') ?? '') as Record<\n string,\n unknown\n >) ?? {};\n const catalog = applyUpdates(\n workspaceYaml.catalog as Record<string, string> | undefined,\n );\n if (catalog) {\n tree.write(\n 'pnpm-workspace.yaml',\n yaml.dump({ ...workspaceYaml, catalog }, { quotingType: \"'\" }),\n );\n }\n break;\n }\n case 'yarn': {\n const yarnRc =\n (yaml.load(tree.read('.yarnrc.yml', 'utf-8') ?? '') as Record<\n string,\n unknown\n >) ?? {};\n const catalog = applyUpdates(\n yarnRc.catalog as Record<string, string> | undefined,\n );\n if (catalog) {\n tree.write(\n '.yarnrc.yml',\n yaml.dump({ ...yarnRc, catalog }, { quotingType: \"'\" }),\n );\n }\n break;\n }\n case 'bun': {\n const catalog = applyUpdates(\n readJson<{ catalog?: Record<string, string> }>(tree, 'package.json')\n .catalog,\n );\n if (catalog) {\n updateJson(tree, 'package.json', (json) => ({ ...json, catalog }));\n }\n break;\n }\n }\n};\n"],"names":["detectPackageManager","addDependenciesToPackageJson","devkitAddDependenciesToPackageJson","getPackageManagerVersion","readJson","updateJson","yaml","coerce","gt","gte","readAwsNxPluginConfig","CATALOG_SUPPORT","pnpm","yarn","bun","detectWorkspacePackageManager","tree","exists","root","parseSimpleRange","version","trimmed","trim","test","undefined","includePrerelease","versionAtLeast","minimum","isVersionUpgrade","incoming","existing","existingParsed","incomingParsed","catalogSupportCache","Map","resetCatalogSupportCache","clear","getLocalDependencySpecifier","packageManager","major","Number","parseInt","split","supportsCatalogs","cacheKey","cached","get","minimumVersion","supported","set","catalogsEnabled","config","catalogs","dependencies","devDependencies","packageJsonPath","callback","packageNames","Object","keys","convertDependenciesToCatalog","BUN_INTROSPECTED_PACKAGES","Set","isCatalogExcluded","packageName","has","catalogUpdates","json","field","includes","length","writeCatalogVersions","updates","applyUpdates","catalog","applicable","fromEntries","entries","filter","name","workspaceYaml","load","read","write","dump","quotingType","yarnRc"],"mappings":"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"}
@@ -5,9 +5,9 @@ This package centralises Shadcn UI components that are shared between your React
5
5
  - Components live under `packages/common/shadcn/src/components`
6
6
  - Utilities live under `packages/common/shadcn/src/lib`
7
7
  - Hooks live under `packages/common/shadcn/src/hooks`
8
- - Global styles are defined in `packages/common/shadcn/src/styles.css`
8
+ - Global styles are defined in `packages/common/shadcn/src/styles/globals.css`
9
9
 
10
- The repository root contains a `components.json` configured to target this package, so you can add new components with:
10
+ This package contains a `components.json`, so you can add new components by running the following from `packages/common/shadcn`:
11
11
 
12
12
  With npm:
13
13
  ```bash
@@ -29,4 +29,4 @@ With bun:
29
29
  bunx --bun shadcn@latest add <component>
30
30
  ```
31
31
 
32
- Run the command from the repository root (not `packages/common/shadcn`) so it picks up the root `components.json`.
32
+ Running from this directory means any dependencies a component needs are installed into this package's `package.json`.
@@ -5,7 +5,7 @@
5
5
  "tsx": true,
6
6
  "tailwind": {
7
7
  "config": "",
8
- "css": "packages/common/shadcn/src/styles/globals.css",
8
+ "css": "src/styles/globals.css",
9
9
  "baseColor": "zinc",
10
10
  "cssVariables": true
11
11
  },
@@ -3,7 +3,13 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import { type Tree } from '@nx/devkit';
6
- export declare const DEFAULT_BIOME_CONFIG: {
6
+ /**
7
+ * The biome.json vended into a new workspace. The pnpm catalog resolver is only
8
+ * included on pnpm workspaces, since `experimentalPnpmCatalogs` is Biome's only
9
+ * catalog resolver and reads `pnpm-workspace.yaml` exclusively — it does nothing
10
+ * for yarn or bun catalogs, so vending it there would be misleading.
11
+ */
12
+ export declare const getDefaultBiomeConfig: (tree: Tree) => {
7
13
  $schema: string;
8
14
  root: boolean;
9
15
  formatter: {
@@ -13,6 +19,9 @@ export declare const DEFAULT_BIOME_CONFIG: {
13
19
  lineWidth: number;
14
20
  };
15
21
  javascript: {
22
+ resolver?: {
23
+ experimentalPnpmCatalogs: boolean;
24
+ };
16
25
  formatter: {
17
26
  quoteStyle: string;
18
27
  trailingCommas: string;
@@ -45,6 +54,16 @@ export declare const DEFAULT_BIOME_CONFIG: {
45
54
  files: {
46
55
  includes: string[];
47
56
  };
57
+ overrides: {
58
+ includes: string[];
59
+ linter: {
60
+ rules: {
61
+ correctness: {
62
+ noUndeclaredDependencies: string;
63
+ };
64
+ };
65
+ };
66
+ }[];
48
67
  };
49
68
  /**
50
69
  * Format files in the given directory within the tree.
@@ -11,60 +11,94 @@ import { uvxCommand } from "./py.js";
11
11
  import { readToml } from "./toml.js";
12
12
  import { TS_VERSIONS } from "./versions.js";
13
13
  const require = createRequire(import.meta.url);
14
- export const DEFAULT_BIOME_CONFIG = {
15
- $schema: `https://biomejs.dev/schemas/${TS_VERSIONS['@biomejs/biome']}/schema.json`,
16
- root: true,
17
- formatter: {
18
- enabled: true,
19
- indentStyle: 'space',
20
- indentWidth: 2,
21
- lineWidth: 80
22
- },
23
- javascript: {
24
- formatter: {
25
- quoteStyle: 'single',
26
- trailingCommas: 'all'
27
- }
28
- },
29
- css: {
14
+ /**
15
+ * The biome.json vended into a new workspace. The pnpm catalog resolver is only
16
+ * included on pnpm workspaces, since `experimentalPnpmCatalogs` is Biome's only
17
+ * catalog resolver and reads `pnpm-workspace.yaml` exclusively — it does nothing
18
+ * for yarn or bun catalogs, so vending it there would be misleading.
19
+ */ export const getDefaultBiomeConfig = (tree)=>({
20
+ $schema: `https://biomejs.dev/schemas/${TS_VERSIONS['@biomejs/biome']}/schema.json`,
21
+ root: true,
30
22
  formatter: {
31
- quoteStyle: 'single'
23
+ enabled: true,
24
+ indentStyle: 'space',
25
+ indentWidth: 2,
26
+ lineWidth: 80
27
+ },
28
+ javascript: {
29
+ formatter: {
30
+ quoteStyle: 'single',
31
+ trailingCommas: 'all'
32
+ },
33
+ // Resolve `catalog:` versions from pnpm-workspace.yaml (pnpm workspaces only).
34
+ ...tree.exists('pnpm-workspace.yaml') ? {
35
+ resolver: {
36
+ experimentalPnpmCatalogs: true
37
+ }
38
+ } : {}
39
+ },
40
+ css: {
41
+ formatter: {
42
+ quoteStyle: 'single'
43
+ },
44
+ linter: {
45
+ enabled: false
46
+ }
32
47
  },
33
48
  linter: {
34
- enabled: false
35
- }
36
- },
37
- linter: {
38
- enabled: true,
39
- rules: {
40
- preset: 'none',
41
- correctness: {
42
- noUndeclaredDependencies: 'warn'
49
+ enabled: true,
50
+ rules: {
51
+ preset: 'none',
52
+ correctness: {
53
+ // Every project must declare the third-party dependencies its source
54
+ // code imports in its own package.json.
55
+ noUndeclaredDependencies: 'error'
56
+ }
43
57
  }
44
- }
45
- },
46
- assist: {
47
- actions: {
48
- source: {
49
- organizeImports: 'on'
58
+ },
59
+ assist: {
60
+ actions: {
61
+ source: {
62
+ organizeImports: 'on'
63
+ }
64
+ }
65
+ },
66
+ files: {
67
+ includes: [
68
+ '**',
69
+ '!**/dist',
70
+ '!**/out-tsc',
71
+ '!**/node_modules',
72
+ '!**/.nx',
73
+ '!**/.venv',
74
+ // GritQL codemod cache written by generators — its sample sources
75
+ // otherwise pollute a bare `biome check .` with parse errors.
76
+ '!**/.grit',
77
+ '!**/*.css',
78
+ '!**/*.gen.*',
79
+ '!**/generated/**',
80
+ '!**/tsconfig*.json'
81
+ ]
82
+ },
83
+ // Config files, build scripts and tests use root tooling rather than
84
+ // declaring it per-project, so the undeclared-dependency rule is off for them.
85
+ overrides: [
86
+ {
87
+ includes: [
88
+ '**/*.config.{ts,mts,cts,js,mjs,cjs}',
89
+ '**/*.{spec,test}.{ts,tsx,mts,cts,js,jsx,mjs,cjs}',
90
+ '**/*.stories.{ts,tsx}'
91
+ ],
92
+ linter: {
93
+ rules: {
94
+ correctness: {
95
+ noUndeclaredDependencies: 'off'
96
+ }
97
+ }
98
+ }
50
99
  }
51
- }
52
- },
53
- files: {
54
- includes: [
55
- '**',
56
- '!**/dist',
57
- '!**/out-tsc',
58
- '!**/node_modules',
59
- '!**/.nx',
60
- '!**/.venv',
61
- '!**/*.css',
62
- '!**/*.gen.*',
63
- '!**/generated/**',
64
- '!**/tsconfig*.json'
65
100
  ]
66
- }
67
- };
101
+ });
68
102
  const BIOME_FORMATTABLE_EXTENSIONS = new Set([
69
103
  '.ts',
70
104
  '.tsx',
@@ -155,7 +189,7 @@ const BIOME_FORMATTABLE_EXTENSIONS = new Set([
155
189
  const { projectKey } = biome.openProject();
156
190
  // Apply the workspace biome.json if it exists in the tree, otherwise the defaults.
157
191
  const treeConfig = tree.read('biome.json', 'utf-8');
158
- biome.applyConfiguration(projectKey, treeConfig ? JSON.parse(treeConfig) : DEFAULT_BIOME_CONFIG);
192
+ biome.applyConfiguration(projectKey, treeConfig ? JSON.parse(treeConfig) : getDefaultBiomeConfig(tree));
159
193
  for (const file of files){
160
194
  try {
161
195
  const { content } = biome.formatContent(projectKey, file.content?.toString('utf-8') ?? '', {
@@ -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 { execFileSync, execSync } from 'child_process';\nimport { existsSync, readFileSync } from 'fs';\nimport { createRequire } from 'module';\nimport path from 'path';\nimport { uvxCommand } from './py';\nimport { readToml } from './toml';\nimport { TS_VERSIONS } from './versions';\n\nconst require = createRequire(import.meta.url);\n\nexport const DEFAULT_BIOME_CONFIG = {\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 },\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 noUndeclaredDependencies: 'warn',\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 '!**/node_modules',\n '!**/.nx',\n '!**/.venv',\n '!**/*.css',\n '!**/*.gen.*',\n '!**/generated/**',\n '!**/tsconfig*.json',\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\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): Promise<void> {\n const changedFiles = tree\n .listChanges()\n .filter((file) => file.type !== 'DELETE')\n .filter((file) => (dir ? file.path.startsWith(dir) : true));\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 hasRuffConfigOnDisk(tree, file.path),\n getOwningProjectRuffConfig(file.path, pythonProjectConfigs),\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 // Use the workspace's own Biome CLI (its version and config) when biome.json\n // exists on disk; otherwise format via the bundled library API with the\n // in-memory tree config. The CLI path does not see in-tree config changes.\n if (existsSync(path.join(tree.root, 'biome.json'))) {\n formatWithBiomeCli(tree, otherFiles);\n } else {\n formatWithBiomeApi(tree, otherFiles);\n }\n}\n\n/**\n * Format files via the workspace's Biome CLI, run from the workspace root so it\n * discovers the on-disk biome.json.\n */\nfunction formatWithBiomeCli(\n tree: Tree,\n files: { path: string; content: Buffer | null }[],\n): void {\n const biome = getBiomeCommand(tree.root);\n if (!biome) {\n // Fall back to the library API if the CLI cannot be resolved\n formatWithBiomeApi(tree, files);\n return;\n }\n\n for (const file of files) {\n try {\n const content = execFileSync(\n biome.command,\n [...biome.args, 'format', `--stdin-file-path=${file.path}`],\n {\n input: file.content?.toString('utf-8') ?? '',\n encoding: 'utf-8',\n cwd: tree.root,\n stdio: ['pipe', 'pipe', 'pipe'],\n },\n );\n tree.write(file.path, content);\n } catch {\n // Leave individual files that fail to format untouched\n }\n }\n}\n\n/**\n * Format files via the bundled Biome library API, applying the in-memory tree\n * config.\n */\nfunction formatWithBiomeApi(\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 // Apply the workspace biome.json if it exists in the tree, otherwise the defaults.\n const treeConfig = tree.read('biome.json', 'utf-8');\n biome.applyConfiguration(\n projectKey,\n treeConfig ? JSON.parse(treeConfig) : DEFAULT_BIOME_CONFIG,\n );\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\ninterface BiomeCommand {\n command: string;\n args: string[];\n}\n\n/**\n * Resolve the `@biomejs/biome` CLI from the user's workspace, falling back to a\n * `biome` binary on the PATH.\n */\nconst _biomeCommands = new Map<string, BiomeCommand | null>();\nfunction getBiomeCommand(root: string): BiomeCommand | undefined {\n if (_biomeCommands.has(root)) {\n return _biomeCommands.get(root) ?? undefined;\n }\n\n // Run via node for cross-platform execution of the bin shim.\n try {\n const pkgJsonPath = require.resolve('@biomejs/biome/package.json', {\n paths: [root, import.meta.dirname],\n });\n const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));\n const binRelative =\n typeof pkgJson.bin === 'string' ? pkgJson.bin : pkgJson.bin?.biome;\n if (binRelative) {\n const binPath = path.join(path.dirname(pkgJsonPath), binRelative);\n const command = { command: process.execPath, args: [binPath] };\n _biomeCommands.set(root, command);\n return command;\n }\n } catch {\n // Fall back to a biome binary on the PATH\n }\n\n try {\n execSync('biome --version', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n const command = { command: 'biome', args: [] };\n _biomeCommands.set(root, command);\n return command;\n } catch {\n _biomeCommands.set(root, null);\n return undefined;\n }\n}\n\n/**\n * Find the ruff command: `uvx --from ruff==<version> ruff`. uvx works\n * regardless of workspace resolution state (unlike `uv run ruff`, which fails\n * while installs are deferred), and the version pin matches the project's\n * `format` target (PY_VERSIONS) so generation and check format identically.\n * Only a successful probe is cached — ruff can become available mid-run in the\n * long-lived Nx daemon, so a cached failure would skip formatting thereafter.\n */\nlet _ruffCommand: string | undefined;\nfunction getRuffCommand(): string | undefined {\n if (_ruffCommand) {\n return _ruffCommand;\n }\n const cmd = uvxCommand('ruff');\n try {\n execSync(`${cmd} --version`, {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n _ruffCommand = cmd;\n return cmd;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Whether ruff would discover a config on disk for a file, by walking from its\n * directory up to the workspace root looking for `.ruff.toml`, `ruff.toml`, or a\n * `pyproject.toml` with a `[tool.ruff]` section — the same files ruff itself\n * resolves. The walk stops at `tree.root` so a stray config in a parent of the\n * workspace (or the home directory) is never treated as the project's. Used to\n * decide whether to nudge ruff towards import sorting (see\n * {@link ruffFixAndFormat}).\n */\nfunction hasRuffConfigOnDisk(tree: Tree, filePath: string): boolean {\n const root = path.resolve(tree.root);\n let dir = path.resolve(root, path.dirname(filePath));\n while (true) {\n if (\n existsSync(path.join(dir, '.ruff.toml')) ||\n existsSync(path.join(dir, 'ruff.toml'))\n ) {\n return true;\n }\n const pyproject = path.join(dir, 'pyproject.toml');\n if (\n existsSync(pyproject) &&\n readFileSync(pyproject, 'utf-8').includes('[tool.ruff')\n ) {\n return true;\n }\n const parent = path.dirname(dir);\n // Stop once the workspace root has been checked (or we hit the FS root).\n if (dir === root || parent === dir) {\n return false;\n }\n dir = parent;\n }\n}\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}\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`) and its `[tool.ruff].line-length`.\n */\nfunction getPythonProjectRuffConfigs(tree: Tree): PythonProjectRuffConfig[] {\n const configs: PythonProjectRuffConfig[] = [];\n\n for (const project of getProjects(tree).values()) {\n const pyprojectPath = path.join(project.root, 'pyproject.toml');\n if (tree.exists(pyprojectPath)) {\n try {\n const pyproject = readToml(tree, pyprojectPath) as any;\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 if (modules.length || typeof lineLength === 'number' || targetVersion) {\n configs.push({\n root: project.root.split(path.sep).join('/'),\n modules,\n lineLength: typeof lineLength === 'number' ? lineLength : undefined,\n targetVersion,\n });\n }\n } catch {\n // Skip projects whose pyproject.toml cannot be parsed\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 * Run ruff check --fix and ruff format on Python file content via stdin.\n * Applies all configured lint fixes (including import sorting) and formatting.\n *\n * When no ruff config exists on disk (`hasConfig` false) ruff falls back to its\n * defaults, which omit isort — but generated projects enable rule `I` and their\n * build fails on unsorted imports (I001). In that case we add `--extend-select\n * I` so import sorting matches what the build enforces. When a config does\n * exist we defer to it entirely, honouring the user's rule selection.\n *\n * `projectConfig` carries the owning project's ruff settings, which ruff cannot\n * detect from the filesystem during generation because the project lives only\n * in the tree. We pass them via `--config` so in-tree formatting matches the\n * on-disk build: `known-first-party` (the project's own modules) keeps its\n * imports in their own group, and `line-length` keeps wrapping consistent (the\n * generated config raises it above ruff's default of 88). These are additive to\n * any on-disk config, so they are safe to pass regardless of `hasConfig`.\n */\nfunction ruffFixAndFormat(\n content: string,\n filePath: string,\n hasConfig: boolean,\n projectConfig?: PythonProjectRuffConfig,\n): string {\n const ruff = getRuffCommand();\n if (!ruff) return content;\n\n const extendSelect = hasConfig ? '' : ' --extend-select I';\n const configArgs: string[] = [];\n if (projectConfig?.modules.length) {\n configArgs.push(\n `lint.isort.known-first-party = ${JSON.stringify(projectConfig.modules)}`,\n );\n }\n if (typeof projectConfig?.lineLength === 'number') {\n configArgs.push(`line-length = ${projectConfig.lineLength}`);\n }\n if (projectConfig?.targetVersion) {\n configArgs.push(`target-version = \"${projectConfig.targetVersion}\"`);\n }\n const config = configArgs\n .map((arg) => ` --config ${JSON.stringify(arg)}`)\n .join('');\n\n // First apply lint fixes (import sorting, unused imports, etc.)\n try {\n const result = execSync(\n `${ruff} check --fix${extendSelect}${config} --stdin-filename ${filePath} -`,\n { input: content, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] },\n );\n content = result;\n } catch (e: any) {\n // ruff check exits non-zero when it finds unfixable issues,\n // but stdout still contains the fixed content\n if (e.stdout) {\n content = e.stdout;\n }\n }\n\n // Then apply formatting\n try {\n content = execSync(\n `${ruff} format${config} --stdin-filename ${filePath} -`,\n {\n input: content,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n },\n );\n } catch {\n // Fall through with whatever content we have\n }\n\n return content;\n}\n"],"names":["Biome","getProjects","execFileSync","execSync","existsSync","readFileSync","createRequire","path","uvxCommand","readToml","TS_VERSIONS","require","url","DEFAULT_BIOME_CONFIG","$schema","root","formatter","enabled","indentStyle","indentWidth","lineWidth","javascript","quoteStyle","trailingCommas","css","linter","rules","preset","correctness","noUndeclaredDependencies","assist","actions","source","organizeImports","files","includes","BIOME_FORMATTABLE_EXTENSIONS","Set","isTsConfig","filePath","test","formatFilesInSubtree","tree","dir","changedFiles","listChanges","filter","file","type","startsWith","pyFiles","endsWith","otherFiles","has","extname","pythonProjectConfigs","length","getPythonProjectRuffConfigs","content","ruffFixAndFormat","toString","hasRuffConfigOnDisk","getOwningProjectRuffConfig","write","join","formatWithBiomeCli","formatWithBiomeApi","biome","getBiomeCommand","command","args","input","encoding","cwd","stdio","projectKey","openProject","treeConfig","read","applyConfiguration","JSON","parse","formatContent","_biomeCommands","Map","get","undefined","pkgJsonPath","resolve","paths","dirname","pkgJson","binRelative","bin","binPath","process","execPath","set","_ruffCommand","getRuffCommand","cmd","pyproject","parent","requiresPythonToRuffTarget","requiresPython","min","match","matchAll","major","Number","minor","configs","project","values","pyprojectPath","exists","wheelPackages","tool","hatch","build","targets","wheel","packages","modules","Array","isArray","pkg","map","split","lineLength","ruff","targetVersion","push","sep","owner","config","hasConfig","projectConfig","extendSelect","configArgs","stringify","arg","result","e","stdout"],"mappings":"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"}
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 { execFileSync, execSync } from 'child_process';\nimport { existsSync, readFileSync } from 'fs';\nimport { createRequire } from 'module';\nimport path from 'path';\nimport { uvxCommand } from './py';\nimport { readToml } from './toml';\nimport { TS_VERSIONS } from './versions';\n\nconst require = createRequire(import.meta.url);\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 '!**/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\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): Promise<void> {\n const changedFiles = tree\n .listChanges()\n .filter((file) => file.type !== 'DELETE')\n .filter((file) => (dir ? file.path.startsWith(dir) : true));\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 hasRuffConfigOnDisk(tree, file.path),\n getOwningProjectRuffConfig(file.path, pythonProjectConfigs),\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 // Use the workspace's own Biome CLI (its version and config) when biome.json\n // exists on disk; otherwise format via the bundled library API with the\n // in-memory tree config. The CLI path does not see in-tree config changes.\n if (existsSync(path.join(tree.root, 'biome.json'))) {\n formatWithBiomeCli(tree, otherFiles);\n } else {\n formatWithBiomeApi(tree, otherFiles);\n }\n}\n\n/**\n * Format files via the workspace's Biome CLI, run from the workspace root so it\n * discovers the on-disk biome.json.\n */\nfunction formatWithBiomeCli(\n tree: Tree,\n files: { path: string; content: Buffer | null }[],\n): void {\n const biome = getBiomeCommand(tree.root);\n if (!biome) {\n // Fall back to the library API if the CLI cannot be resolved\n formatWithBiomeApi(tree, files);\n return;\n }\n\n for (const file of files) {\n try {\n const content = execFileSync(\n biome.command,\n [...biome.args, 'format', `--stdin-file-path=${file.path}`],\n {\n input: file.content?.toString('utf-8') ?? '',\n encoding: 'utf-8',\n cwd: tree.root,\n stdio: ['pipe', 'pipe', 'pipe'],\n },\n );\n tree.write(file.path, content);\n } catch {\n // Leave individual files that fail to format untouched\n }\n }\n}\n\n/**\n * Format files via the bundled Biome library API, applying the in-memory tree\n * config.\n */\nfunction formatWithBiomeApi(\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 // Apply the workspace biome.json if it exists in the tree, otherwise the defaults.\n const treeConfig = tree.read('biome.json', 'utf-8');\n biome.applyConfiguration(\n projectKey,\n treeConfig ? JSON.parse(treeConfig) : getDefaultBiomeConfig(tree),\n );\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\ninterface BiomeCommand {\n command: string;\n args: string[];\n}\n\n/**\n * Resolve the `@biomejs/biome` CLI from the user's workspace, falling back to a\n * `biome` binary on the PATH.\n */\nconst _biomeCommands = new Map<string, BiomeCommand | null>();\nfunction getBiomeCommand(root: string): BiomeCommand | undefined {\n if (_biomeCommands.has(root)) {\n return _biomeCommands.get(root) ?? undefined;\n }\n\n // Run via node for cross-platform execution of the bin shim.\n try {\n const pkgJsonPath = require.resolve('@biomejs/biome/package.json', {\n paths: [root, import.meta.dirname],\n });\n const pkgJson = JSON.parse(readFileSync(pkgJsonPath, 'utf-8'));\n const binRelative =\n typeof pkgJson.bin === 'string' ? pkgJson.bin : pkgJson.bin?.biome;\n if (binRelative) {\n const binPath = path.join(path.dirname(pkgJsonPath), binRelative);\n const command = { command: process.execPath, args: [binPath] };\n _biomeCommands.set(root, command);\n return command;\n }\n } catch {\n // Fall back to a biome binary on the PATH\n }\n\n try {\n execSync('biome --version', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n const command = { command: 'biome', args: [] };\n _biomeCommands.set(root, command);\n return command;\n } catch {\n _biomeCommands.set(root, null);\n return undefined;\n }\n}\n\n/**\n * Find the ruff command: `uvx --from ruff==<version> ruff`. uvx works\n * regardless of workspace resolution state (unlike `uv run ruff`, which fails\n * while installs are deferred), and the version pin matches the project's\n * `format` target (PY_VERSIONS) so generation and check format identically.\n * Only a successful probe is cached — ruff can become available mid-run in the\n * long-lived Nx daemon, so a cached failure would skip formatting thereafter.\n */\nlet _ruffCommand: string | undefined;\nfunction getRuffCommand(): string | undefined {\n if (_ruffCommand) {\n return _ruffCommand;\n }\n const cmd = uvxCommand('ruff');\n try {\n execSync(`${cmd} --version`, {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n _ruffCommand = cmd;\n return cmd;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Whether ruff would discover a config on disk for a file, by walking from its\n * directory up to the workspace root looking for `.ruff.toml`, `ruff.toml`, or a\n * `pyproject.toml` with a `[tool.ruff]` section — the same files ruff itself\n * resolves. The walk stops at `tree.root` so a stray config in a parent of the\n * workspace (or the home directory) is never treated as the project's. Used to\n * decide whether to nudge ruff towards import sorting (see\n * {@link ruffFixAndFormat}).\n */\nfunction hasRuffConfigOnDisk(tree: Tree, filePath: string): boolean {\n const root = path.resolve(tree.root);\n let dir = path.resolve(root, path.dirname(filePath));\n while (true) {\n if (\n existsSync(path.join(dir, '.ruff.toml')) ||\n existsSync(path.join(dir, 'ruff.toml'))\n ) {\n return true;\n }\n const pyproject = path.join(dir, 'pyproject.toml');\n if (\n existsSync(pyproject) &&\n readFileSync(pyproject, 'utf-8').includes('[tool.ruff')\n ) {\n return true;\n }\n const parent = path.dirname(dir);\n // Stop once the workspace root has been checked (or we hit the FS root).\n if (dir === root || parent === dir) {\n return false;\n }\n dir = parent;\n }\n}\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}\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`) and its `[tool.ruff].line-length`.\n */\nfunction getPythonProjectRuffConfigs(tree: Tree): PythonProjectRuffConfig[] {\n const configs: PythonProjectRuffConfig[] = [];\n\n for (const project of getProjects(tree).values()) {\n const pyprojectPath = path.join(project.root, 'pyproject.toml');\n if (tree.exists(pyprojectPath)) {\n try {\n const pyproject = readToml(tree, pyprojectPath) as any;\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 if (modules.length || typeof lineLength === 'number' || targetVersion) {\n configs.push({\n root: project.root.split(path.sep).join('/'),\n modules,\n lineLength: typeof lineLength === 'number' ? lineLength : undefined,\n targetVersion,\n });\n }\n } catch {\n // Skip projects whose pyproject.toml cannot be parsed\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 * Run ruff check --fix and ruff format on Python file content via stdin.\n * Applies all configured lint fixes (including import sorting) and formatting.\n *\n * When no ruff config exists on disk (`hasConfig` false) ruff falls back to its\n * defaults, which omit isort — but generated projects enable rule `I` and their\n * build fails on unsorted imports (I001). In that case we add `--extend-select\n * I` so import sorting matches what the build enforces. When a config does\n * exist we defer to it entirely, honouring the user's rule selection.\n *\n * `projectConfig` carries the owning project's ruff settings, which ruff cannot\n * detect from the filesystem during generation because the project lives only\n * in the tree. We pass them via `--config` so in-tree formatting matches the\n * on-disk build: `known-first-party` (the project's own modules) keeps its\n * imports in their own group, and `line-length` keeps wrapping consistent (the\n * generated config raises it above ruff's default of 88). These are additive to\n * any on-disk config, so they are safe to pass regardless of `hasConfig`.\n */\nfunction ruffFixAndFormat(\n content: string,\n filePath: string,\n hasConfig: boolean,\n projectConfig?: PythonProjectRuffConfig,\n): string {\n const ruff = getRuffCommand();\n if (!ruff) return content;\n\n const extendSelect = hasConfig ? '' : ' --extend-select I';\n const configArgs: string[] = [];\n if (projectConfig?.modules.length) {\n configArgs.push(\n `lint.isort.known-first-party = ${JSON.stringify(projectConfig.modules)}`,\n );\n }\n if (typeof projectConfig?.lineLength === 'number') {\n configArgs.push(`line-length = ${projectConfig.lineLength}`);\n }\n if (projectConfig?.targetVersion) {\n configArgs.push(`target-version = \"${projectConfig.targetVersion}\"`);\n }\n const config = configArgs\n .map((arg) => ` --config ${JSON.stringify(arg)}`)\n .join('');\n\n // First apply lint fixes (import sorting, unused imports, etc.)\n try {\n const result = execSync(\n `${ruff} check --fix${extendSelect}${config} --stdin-filename ${filePath} -`,\n { input: content, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] },\n );\n content = result;\n } catch (e: any) {\n // ruff check exits non-zero when it finds unfixable issues,\n // but stdout still contains the fixed content\n if (e.stdout) {\n content = e.stdout;\n }\n }\n\n // Then apply formatting\n try {\n content = execSync(\n `${ruff} format${config} --stdin-filename ${filePath} -`,\n {\n input: content,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n },\n );\n } catch {\n // Fall through with whatever content we have\n }\n\n return content;\n}\n"],"names":["Biome","getProjects","execFileSync","execSync","existsSync","readFileSync","createRequire","path","uvxCommand","readToml","TS_VERSIONS","require","url","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","formatFilesInSubtree","dir","changedFiles","listChanges","filter","file","type","startsWith","pyFiles","endsWith","otherFiles","has","extname","pythonProjectConfigs","length","getPythonProjectRuffConfigs","content","ruffFixAndFormat","toString","hasRuffConfigOnDisk","getOwningProjectRuffConfig","write","join","formatWithBiomeCli","formatWithBiomeApi","biome","getBiomeCommand","command","args","input","encoding","cwd","stdio","projectKey","openProject","treeConfig","read","applyConfiguration","JSON","parse","formatContent","_biomeCommands","Map","get","undefined","pkgJsonPath","resolve","paths","dirname","pkgJson","binRelative","bin","binPath","process","execPath","set","_ruffCommand","getRuffCommand","cmd","pyproject","parent","requiresPythonToRuffTarget","requiresPython","min","match","matchAll","major","Number","minor","configs","project","values","pyprojectPath","wheelPackages","tool","hatch","build","targets","wheel","packages","modules","Array","isArray","pkg","map","split","lineLength","ruff","targetVersion","push","sep","owner","config","hasConfig","projectConfig","extendSelect","configArgs","stringify","arg","result","e","stdout"],"mappings":"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"}
package/src/utils/fs.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- import { type Tree } from '@nx/devkit';
5
+ import type { Tree } from '@nx/devkit';
6
6
  /**
7
7
  * Utility class for creating platform agnostic commands for filesystem operations.
8
8
  * Adds the required dependencies to the root package json
package/src/utils/fs.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
- */ import { addDependenciesToPackageJson } from "@nx/devkit";
4
+ */ import { addDependenciesToPackageJson } from "./dependencies.js";
5
5
  import { withVersions } from "./versions.js";
6
6
  /**
7
7
  * Utility class for creating platform agnostic commands for filesystem operations.
@@ -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 { addDependenciesToPackageJson, type Tree } from '@nx/devkit';\nimport { withVersions } from './versions';\n\n/**\n * Utility class for creating platform agnostic commands for filesystem operations.\n * Adds the required dependencies to the root package json\n */\nexport class FsCommands {\n private tree: Tree;\n\n constructor(tree: Tree) {\n this.tree = tree;\n }\n\n public cp(src: string, dst: string) {\n addDependenciesToPackageJson(this.tree, {}, withVersions(['ncp']));\n return `ncp ${src} ${dst}`;\n }\n\n public rm(dir: string) {\n addDependenciesToPackageJson(this.tree, {}, withVersions(['rimraf']));\n return `rimraf ${dir}`;\n }\n\n public mkdir(dir: string) {\n addDependenciesToPackageJson(this.tree, {}, withVersions(['make-dir-cli']));\n return `make-dir ${dir}`;\n }\n}\n"],"names":["addDependenciesToPackageJson","withVersions","FsCommands","tree","cp","src","dst","rm","dir","mkdir"],"mappings":"AAAA;;;CAGC,GACD,SAASA,4BAA4B,QAAmB,aAAa;AACrE,SAASC,YAAY,QAAQ,gBAAa;AAE1C;;;CAGC,GACD,OAAO,MAAMC;IACHC,KAAW;IAEnB,YAAYA,IAAU,CAAE;QACtB,IAAI,CAACA,IAAI,GAAGA;IACd;IAEOC,GAAGC,GAAW,EAAEC,GAAW,EAAE;QAClCN,6BAA6B,IAAI,CAACG,IAAI,EAAE,CAAC,GAAGF,aAAa;YAAC;SAAM;QAChE,OAAO,CAAC,IAAI,EAAEI,IAAI,CAAC,EAAEC,KAAK;IAC5B;IAEOC,GAAGC,GAAW,EAAE;QACrBR,6BAA6B,IAAI,CAACG,IAAI,EAAE,CAAC,GAAGF,aAAa;YAAC;SAAS;QACnE,OAAO,CAAC,OAAO,EAAEO,KAAK;IACxB;IAEOC,MAAMD,GAAW,EAAE;QACxBR,6BAA6B,IAAI,CAACG,IAAI,EAAE,CAAC,GAAGF,aAAa;YAAC;SAAe;QACzE,OAAO,CAAC,SAAS,EAAEO,KAAK;IAC1B;AACF"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/fs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Tree } from '@nx/devkit';\nimport { addDependenciesToPackageJson } from './dependencies';\nimport { withVersions } from './versions';\n\n/**\n * Utility class for creating platform agnostic commands for filesystem operations.\n * Adds the required dependencies to the root package json\n */\nexport class FsCommands {\n private tree: Tree;\n\n constructor(tree: Tree) {\n this.tree = tree;\n }\n\n public cp(src: string, dst: string) {\n addDependenciesToPackageJson(this.tree, {}, withVersions(['ncp']));\n return `ncp ${src} ${dst}`;\n }\n\n public rm(dir: string) {\n addDependenciesToPackageJson(this.tree, {}, withVersions(['rimraf']));\n return `rimraf ${dir}`;\n }\n\n public mkdir(dir: string) {\n addDependenciesToPackageJson(this.tree, {}, withVersions(['make-dir-cli']));\n return `make-dir ${dir}`;\n }\n}\n"],"names":["addDependenciesToPackageJson","withVersions","FsCommands","tree","cp","src","dst","rm","dir","mkdir"],"mappings":"AAAA;;;CAGC,GAED,SAASA,4BAA4B,QAAQ,oBAAiB;AAC9D,SAASC,YAAY,QAAQ,gBAAa;AAE1C;;;CAGC,GACD,OAAO,MAAMC;IACHC,KAAW;IAEnB,YAAYA,IAAU,CAAE;QACtB,IAAI,CAACA,IAAI,GAAGA;IACd;IAEOC,GAAGC,GAAW,EAAEC,GAAW,EAAE;QAClCN,6BAA6B,IAAI,CAACG,IAAI,EAAE,CAAC,GAAGF,aAAa;YAAC;SAAM;QAChE,OAAO,CAAC,IAAI,EAAEI,IAAI,CAAC,EAAEC,KAAK;IAC5B;IAEOC,GAAGC,GAAW,EAAE;QACrBR,6BAA6B,IAAI,CAACG,IAAI,EAAE,CAAC,GAAGF,aAAa;YAAC;SAAS;QACnE,OAAO,CAAC,OAAO,EAAEO,KAAK;IACxB;IAEOC,MAAMD,GAAW,EAAE;QACxBR,6BAA6B,IAAI,CAACG,IAAI,EAAE,CAAC,GAAGF,aAAa;YAAC;SAAe;QACzE,OAAO,CAAC,SAAS,EAAEO,KAAK;IAC1B;AACF"}