@aws/nx-plugin 1.0.0-rc.49 → 1.0.0-rc.50
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.
- package/LICENSE-THIRD-PARTY +436 -29
- package/migrations.json +17 -1
- package/package.json +2 -1
- package/src/migrations/latest/modernize-function-props-cast/migration.d.ts +6 -0
- package/src/migrations/latest/modernize-function-props-cast/migration.js +66 -0
- package/src/migrations/latest/modernize-function-props-cast/migration.js.map +1 -0
- package/src/migrations/latest/restrict-cors-to-custom-domains/migration.d.ts +6 -0
- package/src/migrations/latest/restrict-cors-to-custom-domains/migration.js +110 -0
- package/src/migrations/latest/restrict-cors-to-custom-domains/migration.js.map +1 -0
- package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.d.ts +6 -0
- package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.js +129 -0
- package/src/migrations/latest/terraform-bootstrap-adopt-existing-bucket/migration.js.map +1 -0
- package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +1 -0
- package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +25 -15
- package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +1 -0
- package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +26 -16
- package/src/terraform/project/files/application/scripts/bootstrap.ts.template +40 -1
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +75 -45
- package/src/ts/agent/__snapshots__/generator.spec.ts.snap +1 -0
- package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +1 -0
- package/src/ts/nx-migration/files/migration.ts.template +6 -0
- package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +1 -0
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +43 -0
- package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +11 -14
- package/src/utils/__snapshots__/shared-constructs.spec.ts.snap +21 -0
- package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +12 -7
- package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +13 -8
- package/src/utils/files/common/constructs/src/core/cloudfront.ts.template +14 -0
- package/src/utils/files/common/constructs/src/core/index.ts.template +1 -0
- package/src/utils/format.js +118 -240
- package/src/utils/format.js.map +1 -1
- package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +7 -14
- package/src/utils/ruff.d.ts +59 -0
- package/src/utils/ruff.js +140 -0
- package/src/utils/ruff.js.map +1 -0
- package/src/utils/toml.d.ts +5 -0
- package/src/utils/toml.js +10 -0
- package/src/utils/toml.js.map +1 -1
- package/src/utils/warm-ruff-cache.d.ts +0 -8
- package/src/utils/warm-ruff-cache.js +0 -30
- package/src/utils/warm-ruff-cache.js.map +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from './app<% if (esm) { %>.js<% } %>';
|
|
2
2
|
export * from './checkov<% if (esm) { %>.js<% } %>';
|
|
3
|
+
export * from './cloudfront<% if (esm) { %>.js<% } %>';
|
|
3
4
|
export * from './runtime-config<% if (esm) { %>.js<% } %>';
|
|
4
5
|
export * from './workspace<% if (esm) { %>.js<% } %>';
|
package/src/utils/format.js
CHANGED
|
@@ -3,14 +3,10 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/ import { Biome } from "@biomejs/js-api/nodejs";
|
|
5
5
|
import { getProjects } from "@nx/devkit";
|
|
6
|
-
import { execFileSync, execSync } from "child_process";
|
|
7
|
-
import { existsSync, readFileSync } from "fs";
|
|
8
|
-
import { createRequire } from "module";
|
|
9
6
|
import path from "path";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
7
|
+
import { ruffFixAndFormat } from "./ruff.js";
|
|
8
|
+
import { tryReadToml } from "./toml.js";
|
|
12
9
|
import { TS_VERSIONS } from "./versions.js";
|
|
13
|
-
const require = createRequire(import.meta.url);
|
|
14
10
|
/**
|
|
15
11
|
* The biome.json vended into a new workspace. The pnpm catalog resolver is only
|
|
16
12
|
* included on pnpm workspaces, since `experimentalPnpmCatalogs` is Biome's only
|
|
@@ -129,71 +125,52 @@ const BIOME_FORMATTABLE_EXTENSIONS = new Set([
|
|
|
129
125
|
// Resolve each project's ruff settings (module names, line-length) so files
|
|
130
126
|
// are formatted to match the on-disk build (see getPythonProjectRuffConfigs).
|
|
131
127
|
const pythonProjectConfigs = pyFiles.length ? getPythonProjectRuffConfigs(tree) : [];
|
|
132
|
-
// Run ruff from the workspace root so it resolves the same on-disk config
|
|
133
|
-
// hasRuffConfigOnDisk probed for. An in-memory tree has no root on disk, in
|
|
134
|
-
// which case there is no config to find and the process cwd is left alone.
|
|
135
|
-
const ruffCwd = pyFiles.length && existsSync(tree.root) ? tree.root : undefined;
|
|
136
128
|
// Format Python files with ruff (lint fixes + formatting)
|
|
137
129
|
for (const file of pyFiles){
|
|
138
130
|
try {
|
|
139
|
-
const content = ruffFixAndFormat(file.content.toString('utf-8'), file.path,
|
|
131
|
+
const content = ruffFixAndFormat(file.content.toString('utf-8'), file.path, resolveRuffOptions(readRuffConfig(tree, file.path), getOwningProjectRuffConfig(file.path, pythonProjectConfigs)));
|
|
140
132
|
tree.write(file.path, content);
|
|
141
133
|
} catch {
|
|
142
134
|
// Silently skip ruff formatting failures
|
|
143
135
|
}
|
|
144
136
|
}
|
|
145
137
|
if (otherFiles.length === 0) return;
|
|
146
|
-
|
|
147
|
-
// exists on disk; otherwise format via the bundled library API with the
|
|
148
|
-
// in-memory tree config. The CLI path does not see in-tree config changes.
|
|
149
|
-
if (existsSync(path.join(tree.root, 'biome.json'))) {
|
|
150
|
-
formatWithBiomeCli(tree, otherFiles);
|
|
151
|
-
} else {
|
|
152
|
-
formatWithBiomeApi(tree, otherFiles);
|
|
153
|
-
}
|
|
138
|
+
formatWithBiome(tree, otherFiles);
|
|
154
139
|
}
|
|
155
140
|
/**
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
141
|
+
* The Biome configuration to format with: the workspace's own `biome.json`, else
|
|
142
|
+
* the config we vend.
|
|
143
|
+
*
|
|
144
|
+
* Read through the tree, which falls back to disk for a file it doesn't hold. So
|
|
145
|
+
* this resolves the most current config either way — the workspace's on-disk one,
|
|
146
|
+
* or the version a generator has just written to the tree and not yet flushed,
|
|
147
|
+
* which shelling out to the CLI could never see.
|
|
148
|
+
*/ function readBiomeConfig(tree) {
|
|
149
|
+
const config = tree.read('biome.json', 'utf-8');
|
|
150
|
+
if (config) {
|
|
166
151
|
try {
|
|
167
|
-
|
|
168
|
-
...biome.args,
|
|
169
|
-
'format',
|
|
170
|
-
`--stdin-file-path=${file.path}`
|
|
171
|
-
], {
|
|
172
|
-
input: file.content?.toString('utf-8') ?? '',
|
|
173
|
-
encoding: 'utf-8',
|
|
174
|
-
cwd: tree.root,
|
|
175
|
-
stdio: [
|
|
176
|
-
'pipe',
|
|
177
|
-
'pipe',
|
|
178
|
-
'pipe'
|
|
179
|
-
]
|
|
180
|
-
});
|
|
181
|
-
tree.write(file.path, content);
|
|
152
|
+
return JSON.parse(config);
|
|
182
153
|
} catch {
|
|
183
|
-
//
|
|
154
|
+
// Malformed config — fall through to the config we vend
|
|
184
155
|
}
|
|
185
156
|
}
|
|
157
|
+
return getDefaultBiomeConfig(tree);
|
|
186
158
|
}
|
|
187
159
|
/**
|
|
188
|
-
* Format files
|
|
189
|
-
*
|
|
190
|
-
|
|
160
|
+
* Format files with Biome in-process, reusing one instance across the batch.
|
|
161
|
+
*
|
|
162
|
+
* Replaces one `biome format --stdin-file-path` process per file, which
|
|
163
|
+
* dominated generation at ~70ms each: `formatFilesInSubtree` formats every
|
|
164
|
+
* change accumulated in the tree, not only the ones its caller made, so
|
|
165
|
+
* generators sharing a tree reformat the same files once per call. In-process is
|
|
166
|
+
* ~0.5ms per file. Output was verified byte-identical across the plugin's whole
|
|
167
|
+
* source tree, except that the CLI corrupts control characters passed through
|
|
168
|
+
* stdin (a NUL in a template literal) where formatting in-process preserves them.
|
|
169
|
+
*/ function formatWithBiome(tree, files) {
|
|
191
170
|
try {
|
|
192
171
|
const biome = new Biome();
|
|
193
172
|
const { projectKey } = biome.openProject();
|
|
194
|
-
|
|
195
|
-
const treeConfig = tree.read('biome.json', 'utf-8');
|
|
196
|
-
biome.applyConfiguration(projectKey, treeConfig ? JSON.parse(treeConfig) : getDefaultBiomeConfig(tree));
|
|
173
|
+
biome.applyConfiguration(projectKey, readBiomeConfig(tree));
|
|
197
174
|
for (const file of files){
|
|
198
175
|
try {
|
|
199
176
|
const { content } = biome.formatContent(projectKey, file.content?.toString('utf-8') ?? '', {
|
|
@@ -209,110 +186,41 @@ const BIOME_FORMATTABLE_EXTENSIONS = new Set([
|
|
|
209
186
|
}
|
|
210
187
|
}
|
|
211
188
|
/**
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const binRelative = typeof pkgJson.bin === 'string' ? pkgJson.bin : pkgJson.bin?.biome;
|
|
229
|
-
if (binRelative) {
|
|
230
|
-
const binPath = path.join(path.dirname(pkgJsonPath), binRelative);
|
|
231
|
-
const command = {
|
|
232
|
-
command: process.execPath,
|
|
233
|
-
args: [
|
|
234
|
-
binPath
|
|
235
|
-
]
|
|
236
|
-
};
|
|
237
|
-
_biomeCommands.set(root, command);
|
|
238
|
-
return command;
|
|
239
|
-
}
|
|
240
|
-
} catch {
|
|
241
|
-
// Fall back to a biome binary on the PATH
|
|
242
|
-
}
|
|
243
|
-
try {
|
|
244
|
-
execSync('biome --version', {
|
|
245
|
-
encoding: 'utf-8',
|
|
246
|
-
stdio: [
|
|
247
|
-
'pipe',
|
|
248
|
-
'pipe',
|
|
249
|
-
'pipe'
|
|
250
|
-
]
|
|
251
|
-
});
|
|
252
|
-
const command = {
|
|
253
|
-
command: 'biome',
|
|
254
|
-
args: []
|
|
255
|
-
};
|
|
256
|
-
_biomeCommands.set(root, command);
|
|
257
|
-
return command;
|
|
258
|
-
} catch {
|
|
259
|
-
_biomeCommands.set(root, null);
|
|
260
|
-
return undefined;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Find the ruff command: `uvx --from ruff==<version> ruff`. uvx works
|
|
265
|
-
* regardless of workspace resolution state (unlike `uv run ruff`, which fails
|
|
266
|
-
* while installs are deferred), and the version pin matches the project's
|
|
267
|
-
* `format` target (PY_VERSIONS) so generation and check format identically.
|
|
268
|
-
* Only a successful probe is cached — ruff can become available mid-run in the
|
|
269
|
-
* long-lived Nx daemon, so a cached failure would skip formatting thereafter.
|
|
270
|
-
*/ let _ruffCommand;
|
|
271
|
-
function getRuffCommand() {
|
|
272
|
-
if (_ruffCommand) {
|
|
273
|
-
return _ruffCommand;
|
|
274
|
-
}
|
|
275
|
-
const cmd = uvxCommand('ruff');
|
|
276
|
-
try {
|
|
277
|
-
execSync(`${cmd} --version`, {
|
|
278
|
-
encoding: 'utf-8',
|
|
279
|
-
stdio: [
|
|
280
|
-
'pipe',
|
|
281
|
-
'pipe',
|
|
282
|
-
'pipe'
|
|
283
|
-
]
|
|
284
|
-
});
|
|
285
|
-
_ruffCommand = cmd;
|
|
286
|
-
return cmd;
|
|
287
|
-
} catch {
|
|
288
|
-
return undefined;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* Whether ruff would discover a config on disk for a file, by walking from its
|
|
293
|
-
* directory up to the workspace root looking for `.ruff.toml`, `ruff.toml`, or a
|
|
294
|
-
* `pyproject.toml` with a `[tool.ruff]` section — the same files ruff itself
|
|
295
|
-
* resolves. The walk stops at `tree.root` so a stray config in a parent of the
|
|
296
|
-
* workspace (or the home directory) is never treated as the project's. Used to
|
|
297
|
-
* decide whether to nudge ruff towards import sorting (see
|
|
298
|
-
* {@link ruffFixAndFormat}).
|
|
299
|
-
*/ function hasRuffConfigOnDisk(tree, filePath) {
|
|
300
|
-
const root = path.resolve(tree.root);
|
|
301
|
-
let dir = path.resolve(root, path.dirname(filePath));
|
|
189
|
+
* Read the ruff config for a file, by walking from its directory up to the
|
|
190
|
+
* workspace root looking for `.ruff.toml`, `ruff.toml`, or a `pyproject.toml`
|
|
191
|
+
* with a `[tool.ruff]` section — the same files, in the same order, that ruff
|
|
192
|
+
* itself resolves. The walk stops at the workspace root so a stray config in a
|
|
193
|
+
* parent of the workspace (or the home directory) is never treated as the
|
|
194
|
+
* project's.
|
|
195
|
+
*
|
|
196
|
+
* The settings are read rather than merely detected because formatting runs
|
|
197
|
+
* in-process against tree content, so ruff never sees the file's location and
|
|
198
|
+
* cannot resolve the config itself (see {@link resolveRuffOptions}).
|
|
199
|
+
*
|
|
200
|
+
* Reads go through the tree, which falls through to disk for files this run has
|
|
201
|
+
* not touched, so a config the generator has just written in memory is picked up
|
|
202
|
+
* as well as one already on disk.
|
|
203
|
+
*/ function readRuffConfig(tree, filePath) {
|
|
204
|
+
let dir = path.dirname(filePath);
|
|
302
205
|
while(true){
|
|
303
|
-
|
|
304
|
-
|
|
206
|
+
for (const name of [
|
|
207
|
+
'.ruff.toml',
|
|
208
|
+
'ruff.toml'
|
|
209
|
+
]){
|
|
210
|
+
const config = tryReadToml(tree, path.join(dir, name));
|
|
211
|
+
if (config) {
|
|
212
|
+
return config;
|
|
213
|
+
}
|
|
305
214
|
}
|
|
306
|
-
const
|
|
307
|
-
if (
|
|
308
|
-
return
|
|
215
|
+
const ruff = tryReadToml(tree, path.join(dir, 'pyproject.toml'))?.tool?.ruff;
|
|
216
|
+
if (ruff) {
|
|
217
|
+
return ruff;
|
|
309
218
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
return false;
|
|
219
|
+
// Stop once the workspace root ('.') has been checked.
|
|
220
|
+
if (dir === '.' || dir === '' || dir === path.dirname(dir)) {
|
|
221
|
+
return undefined;
|
|
314
222
|
}
|
|
315
|
-
dir =
|
|
223
|
+
dir = path.dirname(dir);
|
|
316
224
|
}
|
|
317
225
|
}
|
|
318
226
|
/**
|
|
@@ -357,30 +265,28 @@ function getRuffCommand() {
|
|
|
357
265
|
*/ function getPythonProjectRuffConfigs(tree) {
|
|
358
266
|
const configs = [];
|
|
359
267
|
for (const project of getProjects(tree).values()){
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}
|
|
382
|
-
// Skip projects whose pyproject.toml cannot be parsed
|
|
383
|
-
}
|
|
268
|
+
// Projects without a pyproject.toml, or whose one cannot be parsed, have no
|
|
269
|
+
// ruff settings to contribute.
|
|
270
|
+
const pyproject = tryReadToml(tree, path.join(project.root, 'pyproject.toml'));
|
|
271
|
+
if (!pyproject) {
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
const wheelPackages = pyproject?.tool?.hatch?.build?.targets?.wheel?.packages;
|
|
275
|
+
// Record the top-level module segment (`pkg/sub` -> `pkg`), which is
|
|
276
|
+
// all `known-first-party` keys off.
|
|
277
|
+
const modules = Array.isArray(wheelPackages) ? wheelPackages.filter((pkg)=>typeof pkg === 'string' && !!pkg).map((pkg)=>pkg.split('/')[0]) : [];
|
|
278
|
+
const lineLength = pyproject?.tool?.ruff?.['line-length'];
|
|
279
|
+
const targetVersion = requiresPythonToRuffTarget(pyproject?.project?.['requires-python']);
|
|
280
|
+
const selected = pyproject?.tool?.ruff?.lint?.select;
|
|
281
|
+
const select = Array.isArray(selected) ? selected.filter((rule)=>typeof rule === 'string' && !!rule) : undefined;
|
|
282
|
+
if (modules.length || typeof lineLength === 'number' || targetVersion || select?.length) {
|
|
283
|
+
configs.push({
|
|
284
|
+
root: project.root.split(path.sep).join('/'),
|
|
285
|
+
modules,
|
|
286
|
+
lineLength: typeof lineLength === 'number' ? lineLength : undefined,
|
|
287
|
+
targetVersion,
|
|
288
|
+
select: select?.length ? select : undefined
|
|
289
|
+
});
|
|
384
290
|
}
|
|
385
291
|
}
|
|
386
292
|
return configs;
|
|
@@ -402,79 +308,51 @@ function getRuffCommand() {
|
|
|
402
308
|
return owner;
|
|
403
309
|
}
|
|
404
310
|
/**
|
|
405
|
-
*
|
|
406
|
-
*
|
|
311
|
+
* Resolve the ruff settings to format a Python file with, mirroring what the
|
|
312
|
+
* file's build enforces.
|
|
407
313
|
*
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
* `--isolated` with the project's own `lint.select` pinned, so generation
|
|
413
|
-
* enforces exactly what `lint` does and nothing more. `--isolated` also stops
|
|
414
|
-
* ruff walking above the workspace to a stray config on the host.
|
|
314
|
+
* Ruff's own config discovery never runs: settings are passed to the linter
|
|
315
|
+
* directly rather than resolved from the file's location, which it never sees.
|
|
316
|
+
* That also means a stray config above the workspace (or in the home directory)
|
|
317
|
+
* can never be picked up.
|
|
415
318
|
*
|
|
416
|
-
*
|
|
417
|
-
*
|
|
319
|
+
* `config` is the file's nearest ruff config, whose rule selection is honoured
|
|
320
|
+
* as-is. Without one, ruff would fall back to its own defaults, which change
|
|
321
|
+
* between releases — 0.16 widened them from `E` and `F` to 36 rule prefixes — so
|
|
322
|
+
* generation would apply fixes the project's build never asks for (eg `RUF022`
|
|
323
|
+
* reordering `__all__`). Instead the project's own `lint.select` is pinned, so
|
|
324
|
+
* generation enforces exactly what `lint` does and nothing more.
|
|
418
325
|
*
|
|
419
|
-
* `projectConfig`
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
*
|
|
423
|
-
*
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
if (!ruff) return content;
|
|
429
|
-
const configArgs = [];
|
|
326
|
+
* `projectConfig` layers on the settings derived from the owning project rather
|
|
327
|
+
* than declared under `[tool.ruff]`: `known-first-party` (the project's own
|
|
328
|
+
* modules, from its wheel packages) keeps its imports in their own group, and
|
|
329
|
+
* `target-version` (from its `requires-python`) matches the formatting the build
|
|
330
|
+
* produces.
|
|
331
|
+
*/ function resolveRuffOptions(config, projectConfig) {
|
|
332
|
+
const lint = {
|
|
333
|
+
...config?.lint
|
|
334
|
+
};
|
|
430
335
|
// Pin the rule selection only when deferring to ruff's defaults would
|
|
431
336
|
// otherwise apply rules the project's build does not enforce.
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
configArgs.push(`lint.select = ${JSON.stringify(projectConfig?.select ?? DEFAULT_RUFF_SELECT)}`);
|
|
337
|
+
if (!config) {
|
|
338
|
+
lint.select = projectConfig?.select ?? DEFAULT_RUFF_SELECT;
|
|
435
339
|
}
|
|
436
340
|
if (projectConfig?.modules.length) {
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
}
|
|
442
|
-
if (projectConfig?.targetVersion) {
|
|
443
|
-
configArgs.push(`target-version = "${projectConfig.targetVersion}"`);
|
|
444
|
-
}
|
|
445
|
-
const config = configArgs.map((arg)=>` --config ${JSON.stringify(arg)}`).join('');
|
|
446
|
-
const flags = `${isolated ? ' --isolated' : ''}${config}`;
|
|
447
|
-
// Built per invocation: `input` carries the content the previous step emitted.
|
|
448
|
-
const options = (input)=>({
|
|
449
|
-
input,
|
|
450
|
-
encoding: 'utf-8',
|
|
451
|
-
stdio: [
|
|
452
|
-
'pipe',
|
|
453
|
-
'pipe',
|
|
454
|
-
'pipe'
|
|
455
|
-
],
|
|
456
|
-
...cwd ? {
|
|
457
|
-
cwd
|
|
458
|
-
} : {}
|
|
459
|
-
});
|
|
460
|
-
// First apply lint fixes (import sorting, unused imports, etc.)
|
|
461
|
-
try {
|
|
462
|
-
const result = execSync(`${ruff} check --fix${flags} --stdin-filename ${filePath} -`, options(content));
|
|
463
|
-
content = result;
|
|
464
|
-
} catch (e) {
|
|
465
|
-
// ruff check exits non-zero when it finds unfixable issues,
|
|
466
|
-
// but stdout still contains the fixed content
|
|
467
|
-
if (e.stdout) {
|
|
468
|
-
content = e.stdout;
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
// Then apply formatting
|
|
472
|
-
try {
|
|
473
|
-
content = execSync(`${ruff} format${flags} --stdin-filename ${filePath} -`, options(content));
|
|
474
|
-
} catch {
|
|
475
|
-
// Fall through with whatever content we have
|
|
341
|
+
lint.isort = {
|
|
342
|
+
...lint.isort,
|
|
343
|
+
'known-first-party': projectConfig.modules
|
|
344
|
+
};
|
|
476
345
|
}
|
|
477
|
-
return
|
|
346
|
+
return {
|
|
347
|
+
...config,
|
|
348
|
+
...typeof projectConfig?.lineLength === 'number' ? {
|
|
349
|
+
'line-length': projectConfig.lineLength
|
|
350
|
+
} : {},
|
|
351
|
+
...projectConfig?.targetVersion ? {
|
|
352
|
+
'target-version': projectConfig.targetVersion
|
|
353
|
+
} : {},
|
|
354
|
+
lint
|
|
355
|
+
};
|
|
478
356
|
}
|
|
479
357
|
|
|
480
358
|
//# sourceMappingURL=format.js.map
|
package/src/utils/format.js.map
CHANGED
|
@@ -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 {\n type ExecSyncOptionsWithStringEncoding,\n execFileSync,\n execSync,\n} 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 // Run ruff from the workspace root so it resolves the same on-disk config\n // hasRuffConfigOnDisk probed for. An in-memory tree has no root on disk, in\n // which case there is no config to find and the process cwd is left alone.\n const ruffCwd =\n pyFiles.length && existsSync(tree.root) ? tree.root : undefined;\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 ruffCwd,\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\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 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 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 } 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 would fall back to\n * its own defaults, which change between releases — 0.16 widened them from `E`\n * and `F` to 36 rule prefixes — so generation would apply fixes the project's\n * build never asks for (eg `RUF022` reordering `__all__`). Instead run\n * `--isolated` with the project's own `lint.select` pinned, so generation\n * enforces exactly what `lint` does and nothing more. `--isolated` also stops\n * ruff walking above the workspace to a stray config on the host.\n *\n * When a config does exist we defer to it entirely, honouring the user's rule\n * selection, and run from `tree.root` so ruff discovers it.\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 cwd: string | undefined,\n projectConfig?: PythonProjectRuffConfig,\n): string {\n const ruff = getRuffCommand();\n if (!ruff) return content;\n\n const configArgs: string[] = [];\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 const isolated = !hasConfig;\n if (isolated) {\n configArgs.push(\n `lint.select = ${JSON.stringify(projectConfig?.select ?? DEFAULT_RUFF_SELECT)}`,\n );\n }\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 const flags = `${isolated ? ' --isolated' : ''}${config}`;\n // Built per invocation: `input` carries the content the previous step emitted.\n const options = (input: string): ExecSyncOptionsWithStringEncoding => ({\n input,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n ...(cwd ? { cwd } : {}),\n });\n\n // First apply lint fixes (import sorting, unused imports, etc.)\n try {\n const result = execSync(\n `${ruff} check --fix${flags} --stdin-filename ${filePath} -`,\n options(content),\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${flags} --stdin-filename ${filePath} -`,\n options(content),\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","ruffCwd","undefined","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","pkgJsonPath","resolve","paths","dirname","pkgJson","binRelative","bin","binPath","process","execPath","set","_ruffCommand","getRuffCommand","cmd","pyproject","parent","DEFAULT_RUFF_SELECT","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","selected","lint","select","rule","push","sep","owner","config","hasConfig","projectConfig","configArgs","isolated","stringify","arg","flags","options","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 path from 'path';\nimport { type RuffOptions, ruffFixAndFormat } from './ruff';\nimport { tryReadToml } from './toml';\nimport { TS_VERSIONS } from './versions';\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 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","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","toString","resolveRuffOptions","readRuffConfig","getOwningProjectRuffConfig","write","formatWithBiome","readBiomeConfig","config","read","JSON","parse","biome","projectKey","openProject","applyConfiguration","formatContent","dirname","name","join","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","split","lineLength","targetVersion","selected","lint","select","rule","push","sep","owner","projectConfig","isort"],"mappings":"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"}
|
|
@@ -30,7 +30,8 @@ import {
|
|
|
30
30
|
import { LogGroup, RetentionDays } from 'aws-cdk-lib/aws-logs';
|
|
31
31
|
import { Construct } from 'constructs';
|
|
32
32
|
import { RuntimeConfig } from './runtime-config<% if (esm) { %>.js<% } %>';
|
|
33
|
-
import {
|
|
33
|
+
import { Distribution } from 'aws-cdk-lib/aws-cloudfront';
|
|
34
|
+
import { findCloudFrontDomainNames } from './cloudfront<% if (esm) { %>.js<% } %>';
|
|
34
35
|
import { suppressRules } from './checkov<% if (esm) { %>.js<% } %>';
|
|
35
36
|
|
|
36
37
|
const WEB_CLIENT_ID = 'WebClient';
|
|
@@ -242,7 +243,11 @@ export class UserIdentity extends Construct {
|
|
|
242
243
|
const lazilyComputedCallbackUrls = Lazy.list({
|
|
243
244
|
produce: () =>
|
|
244
245
|
['http://localhost:4200', 'http://localhost:4300'].concat(
|
|
245
|
-
|
|
246
|
+
Stack.of(this)
|
|
247
|
+
.node.findAll()
|
|
248
|
+
.filter((child): child is Distribution => child instanceof Distribution)
|
|
249
|
+
.flatMap(findCloudFrontDomainNames)
|
|
250
|
+
.map((domain) => `https://${domain}`)
|
|
246
251
|
),
|
|
247
252
|
});
|
|
248
253
|
|
|
@@ -291,16 +296,4 @@ export class UserIdentity extends Construct {
|
|
|
291
296
|
useCognitoProvidedValues: true,
|
|
292
297
|
}).node.addDependency(userPoolClient, userPool, userPoolDomain);
|
|
293
298
|
};
|
|
294
|
-
|
|
295
|
-
// Includes each distribution's default domain name plus any custom domain names (aliases) configured on it.
|
|
296
|
-
private findCloudFrontDomainNames = (): string[] =>
|
|
297
|
-
Stack.of(this)
|
|
298
|
-
.node.findAll()
|
|
299
|
-
.filter((child): child is Distribution => child instanceof Distribution)
|
|
300
|
-
.flatMap((d) => {
|
|
301
|
-
const cfnDistribution = d.node.defaultChild as CfnDistribution;
|
|
302
|
-
const distributionConfig =
|
|
303
|
-
cfnDistribution.distributionConfig as CfnDistribution.DistributionConfigProperty;
|
|
304
|
-
return [d.domainName, ...(distributionConfig.aliases ?? [])];
|
|
305
|
-
});
|
|
306
299
|
}
|