@nx/js 23.2.0-beta.1 → 23.2.0-beta.10
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/dist/internal.d.ts +9 -3
- package/dist/internal.js +28 -17
- package/dist/src/executors/copy-workspace-modules/copy-workspace-modules.js +122 -21
- package/dist/src/executors/node/lib/output-file.js +4 -4
- package/dist/src/executors/node/node.impl.js +9 -10
- package/dist/src/executors/prune-lockfile/prune-lockfile.d.ts +1 -1
- package/dist/src/executors/prune-lockfile/prune-lockfile.js +40 -33
- package/dist/src/executors/tsc/lib/batch/watch.js +3 -3
- package/dist/src/executors/tsc/tsc.batch-impl.d.ts +1 -1
- package/dist/src/executors/tsc/tsc.batch-impl.js +2 -2
- package/dist/src/executors/verdaccio/verdaccio.impl.js +8 -1
- package/dist/src/generators/init/init.js +32 -15
- package/dist/src/generators/init/schema.d.ts +1 -1
- package/dist/src/generators/init/schema.json +1 -1
- package/dist/src/generators/library/library.d.ts +1 -1
- package/dist/src/generators/library/library.js +34 -20
- package/dist/src/generators/library/schema.d.ts +11 -3
- package/dist/src/generators/library/schema.json +15 -4
- package/dist/src/generators/library/utils/add-release-config.js +2 -2
- package/dist/src/generators/setup-build/generator.js +2 -7
- package/dist/src/generators/typescript-sync/typescript-sync.d.ts +1 -1
- package/dist/src/generators/typescript-sync/typescript-sync.js +2 -2
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.js +8 -8
- package/dist/src/migrations/update-23-1-0/add-ignore-deprecations-for-ts6.d.ts +3 -2
- package/dist/src/migrations/update-23-1-0/add-ignore-deprecations-for-ts6.js +17 -11
- package/dist/src/migrations/update-23-2-0/add-pnpm-deploy-output-cache-inputs.d.ts +14 -0
- package/dist/src/migrations/update-23-2-0/add-pnpm-deploy-output-cache-inputs.js +242 -0
- package/dist/src/migrations/update-23-2-0/add-pnpm-deploy-output-cache-inputs.md +64 -0
- package/dist/src/migrations/update-23-2-0/add-pnpm-prune-lockfile-cache-config.d.ts +2 -0
- package/dist/src/migrations/update-23-2-0/add-pnpm-prune-lockfile-cache-config.js +305 -0
- package/dist/src/migrations/update-23-2-0/add-pnpm-prune-lockfile-cache-config.md +59 -0
- package/dist/src/plugins/typescript/plugin.js +9 -14
- package/dist/src/plugins/typescript/util.d.ts +1 -1
- package/dist/src/release/utils/update-lock-file.js +5 -7
- package/dist/src/release/version-actions.d.ts +12 -3
- package/dist/src/release/version-actions.js +236 -76
- package/dist/src/utils/add-linting-to-project.d.ts +46 -0
- package/dist/src/utils/add-linting-to-project.js +112 -0
- package/dist/src/utils/assets/copy-assets-handler.d.ts +1 -1
- package/dist/src/utils/assets/copy-assets-handler.js +2 -2
- package/dist/src/utils/buildable-libs-utils.js +10 -13
- package/dist/src/utils/find-npm-dependencies.js +7 -10
- package/dist/src/utils/formatter-setup.d.ts +26 -0
- package/dist/src/utils/formatter-setup.js +43 -0
- package/dist/src/utils/generate-globs.js +11 -14
- package/dist/src/utils/generator-prompts.d.ts +2 -1
- package/dist/src/utils/generator-prompts.js +23 -22
- package/dist/src/utils/get-main-file-dir.js +2 -2
- package/dist/src/utils/linter.d.ts +30 -0
- package/dist/src/utils/linter.js +43 -0
- package/dist/src/utils/npm-config.d.ts +1 -1
- package/dist/src/utils/nx-formatter-internals.d.ts +8 -0
- package/dist/src/utils/nx-formatter-internals.js +18 -0
- package/dist/src/utils/oxfmt.d.ts +4 -0
- package/dist/src/utils/oxfmt.js +35 -0
- package/dist/src/utils/package-json/update-package-json.d.ts +1 -1
- package/dist/src/utils/package-json/update-package-json.js +11 -22
- package/dist/src/utils/package-manager-workspaces.js +2 -2
- package/dist/src/utils/pnpm-deploy-output-cache-inputs.d.ts +29 -0
- package/dist/src/utils/pnpm-deploy-output-cache-inputs.js +177 -0
- package/dist/src/utils/pnpm-install-settings-inputs.d.ts +45 -0
- package/dist/src/utils/pnpm-install-settings-inputs.js +77 -0
- package/dist/src/utils/prettier.js +14 -33
- package/dist/src/utils/target-defaults-matching.d.ts +57 -0
- package/dist/src/utils/target-defaults-matching.js +126 -0
- package/dist/src/utils/typescript/configuration.js +3 -5
- package/dist/src/utils/typescript/create-ts-config.d.ts +1 -1
- package/dist/src/utils/typescript/create-ts-config.js +5 -5
- package/dist/src/utils/typescript/plugin.js +2 -2
- package/dist/src/utils/typescript/run-type-check.js +2 -2
- package/dist/src/utils/typescript/ts-config.d.ts +51 -1
- package/dist/src/utils/typescript/ts-config.js +114 -0
- package/dist/src/utils/typescript/ts-solution-setup.d.ts +1 -1
- package/dist/src/utils/typescript/ts-solution-setup.js +3 -3
- package/dist/src/utils/versions.d.ts +1 -0
- package/dist/src/utils/versions.js +2 -1
- package/dist/src/utils/watch-for-single-file-changes.js +2 -2
- package/dist/src/utils/workspace-module-sections.d.ts +16 -0
- package/dist/src/utils/workspace-module-sections.js +24 -0
- package/migrations.json +13 -1
- package/package.json +12 -5
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { GeneratorCallback, Tree } from '@nx/devkit';
|
|
2
|
+
import { type LinterType } from './linter';
|
|
3
|
+
export interface AddLintingToProjectOptions {
|
|
4
|
+
/** Required, but `undefined` still reaches here — see the normalization below. */
|
|
5
|
+
linter: LinterType | undefined;
|
|
6
|
+
project: string;
|
|
7
|
+
skipPackageJson?: boolean;
|
|
8
|
+
keepExistingVersions?: boolean;
|
|
9
|
+
addPlugin?: boolean;
|
|
10
|
+
/** ESLint-only. Ignored by other linters. */
|
|
11
|
+
tsConfigPaths?: string[];
|
|
12
|
+
unitTestRunner?: string;
|
|
13
|
+
/** ESLint-only. Ignored by other linters. */
|
|
14
|
+
rootProject?: boolean;
|
|
15
|
+
/** ESLint-only. Ignored by other linters. */
|
|
16
|
+
enableTypedLinting?: boolean;
|
|
17
|
+
/** ESLint-only. Oxlint is inference-only, so it writes no explicit target. */
|
|
18
|
+
addExplicitTargets?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* ESLint-only. The `@nx/dependency-checks` rule lints `package.json`, which
|
|
21
|
+
* Oxlint cannot read.
|
|
22
|
+
*/
|
|
23
|
+
addPackageJsonDependencyChecks?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Oxlint plugins to enable for this project, e.g. `['react', 'jsx-a11y']`.
|
|
26
|
+
* Ignored by other linters, which express framework presets differently.
|
|
27
|
+
*/
|
|
28
|
+
oxlintPlugins?: string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Sets a project's linter up, dispatching to whichever linter the workspace
|
|
32
|
+
* asked for. Consumers call this instead of importing `lintProjectGenerator`
|
|
33
|
+
* from `@nx/eslint` directly, so adding a linter does not mean editing every
|
|
34
|
+
* generator. The two arms name different generators on purpose: `@nx/eslint`
|
|
35
|
+
* writes a lint target, while `@nx/oxlint` is inference-only and only
|
|
36
|
+
* configures the project.
|
|
37
|
+
*
|
|
38
|
+
* Scope is deliberately narrow: registering the linter and its project target.
|
|
39
|
+
* Linter-specific config shaping — ESLint framework presets, `extends`, ignore
|
|
40
|
+
* entries — stays at the call site guarded on `linter`, because none of it has
|
|
41
|
+
* a cross-linter equivalent.
|
|
42
|
+
*
|
|
43
|
+
* Both plugins are loaded through `ensurePackage`; a static import would be
|
|
44
|
+
* circular, since both depend on `@nx/js`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function addLintingToProject(tree: Tree, options: AddLintingToProjectOptions): Promise<GeneratorCallback>;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addLintingToProject = addLintingToProject;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
6
|
+
const versions_1 = require("./versions");
|
|
7
|
+
const linter_1 = require("./linter");
|
|
8
|
+
/**
|
|
9
|
+
* Sets a project's linter up, dispatching to whichever linter the workspace
|
|
10
|
+
* asked for. Consumers call this instead of importing `lintProjectGenerator`
|
|
11
|
+
* from `@nx/eslint` directly, so adding a linter does not mean editing every
|
|
12
|
+
* generator. The two arms name different generators on purpose: `@nx/eslint`
|
|
13
|
+
* writes a lint target, while `@nx/oxlint` is inference-only and only
|
|
14
|
+
* configures the project.
|
|
15
|
+
*
|
|
16
|
+
* Scope is deliberately narrow: registering the linter and its project target.
|
|
17
|
+
* Linter-specific config shaping — ESLint framework presets, `extends`, ignore
|
|
18
|
+
* entries — stays at the call site guarded on `linter`, because none of it has
|
|
19
|
+
* a cross-linter equivalent.
|
|
20
|
+
*
|
|
21
|
+
* Both plugins are loaded through `ensurePackage`; a static import would be
|
|
22
|
+
* circular, since both depend on `@nx/js`.
|
|
23
|
+
*/
|
|
24
|
+
async function addLintingToProject(tree, options) {
|
|
25
|
+
// Callers should resolve this themselves, since their own guards need a
|
|
26
|
+
// concrete value. Resolving again here keeps a caller that forgets from
|
|
27
|
+
// silently getting ESLint in a workspace that uses something else.
|
|
28
|
+
const linter = options.linter ?? (0, linter_1.detectLinters)(tree)[0] ?? 'none';
|
|
29
|
+
if (linter === 'none') {
|
|
30
|
+
return () => { };
|
|
31
|
+
}
|
|
32
|
+
if (linter === 'oxlint') {
|
|
33
|
+
// `ensurePackage` installs by package name, so the subpath is required
|
|
34
|
+
// separately. `nx-ignore-next-line` keeps this out of the import graph, so
|
|
35
|
+
// the dependency stays a devDependency of this package rather than a runtime
|
|
36
|
+
// one. That devDependency is what makes the `js` <-> `@nx/oxlint` cycle,
|
|
37
|
+
// which is deliberate and recorded in `ignoredCircularDependencies` in the
|
|
38
|
+
// root eslint config.
|
|
39
|
+
(0, devkit_1.ensurePackage)('@nx/oxlint', versions_1.nxVersion);
|
|
40
|
+
// `@nx/oxlint` is the only ESM package under `packages/` and its
|
|
41
|
+
// `./generators` subpath has no `require` condition, so a bare `require()`
|
|
42
|
+
// throws ERR_REQUIRE_ESM below Node 20.19 / 22.12.
|
|
43
|
+
//
|
|
44
|
+
// Resolve to an absolute path before importing. `ensurePackage` exposes an
|
|
45
|
+
// on-demand install by adding a temp dir to NODE_PATH, which `require.resolve`
|
|
46
|
+
// honours and the ESM loader does not — so handing `import()` a bare specifier
|
|
47
|
+
// fails with ERR_MODULE_NOT_FOUND on exactly the Node band this indirection
|
|
48
|
+
// exists for. `load-resolved-plugin.ts` calls `handleImport` the same way.
|
|
49
|
+
// nx-ignore-next-line
|
|
50
|
+
const generatorsPath = require.resolve('@nx/oxlint/generators', {
|
|
51
|
+
paths: [devkit_1.workspaceRoot, __dirname],
|
|
52
|
+
});
|
|
53
|
+
const { configurationGenerator } = await (0, internal_1.handleImport)(generatorsPath);
|
|
54
|
+
return configurationGenerator(tree, {
|
|
55
|
+
project: options.project,
|
|
56
|
+
plugins: [
|
|
57
|
+
...(options.oxlintPlugins ?? []),
|
|
58
|
+
...oxlintTestPlugins(options.unitTestRunner),
|
|
59
|
+
],
|
|
60
|
+
skipFormat: true,
|
|
61
|
+
skipPackageJson: options.skipPackageJson,
|
|
62
|
+
keepExistingVersions: options.keepExistingVersions,
|
|
63
|
+
// No `addPlugin`: `@nx/oxlint` is inference-only, so it always registers.
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if (linter === 'eslint') {
|
|
67
|
+
const { lintProjectGenerator } = (0, devkit_1.ensurePackage)('@nx/eslint', versions_1.nxVersion);
|
|
68
|
+
return lintProjectGenerator(tree, {
|
|
69
|
+
linter,
|
|
70
|
+
project: options.project,
|
|
71
|
+
tsConfigPaths: options.tsConfigPaths,
|
|
72
|
+
unitTestRunner: options.unitTestRunner,
|
|
73
|
+
rootProject: options.rootProject,
|
|
74
|
+
enableTypedLinting: options.enableTypedLinting,
|
|
75
|
+
addExplicitTargets: options.addExplicitTargets,
|
|
76
|
+
addPackageJsonDependencyChecks: options.addPackageJsonDependencyChecks,
|
|
77
|
+
skipFormat: true,
|
|
78
|
+
skipPackageJson: options.skipPackageJson,
|
|
79
|
+
keepExistingVersions: options.keepExistingVersions,
|
|
80
|
+
addPlugin: options.addPlugin,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
// Spelling ESLint out as its own branch rather than letting it be the
|
|
84
|
+
// fallthrough: a new `LinterType` member then fails to compile here instead of
|
|
85
|
+
// silently getting an ESLint setup.
|
|
86
|
+
const unhandled = linter;
|
|
87
|
+
throw new Error(`Unsupported linter: ${unhandled}`);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Which Oxlint plugins a test runner needs is the runner package's knowledge,
|
|
91
|
+
* so it is read from there rather than hardcoded here — this only maps the
|
|
92
|
+
* runner name to its package. Matched loosely because runners arrive with
|
|
93
|
+
* suffixes, e.g. Angular's `vitest-analog`. Both packages are already installed
|
|
94
|
+
* by the time the runner's own generator runs; `ensurePackage` keeps them out
|
|
95
|
+
* of the import graph, since both depend on `@nx/js`.
|
|
96
|
+
*/
|
|
97
|
+
function oxlintTestPlugins(unitTestRunner) {
|
|
98
|
+
const pkg = unitTestRunner?.includes('vitest')
|
|
99
|
+
? '@nx/vitest'
|
|
100
|
+
: unitTestRunner?.includes('jest')
|
|
101
|
+
? '@nx/jest'
|
|
102
|
+
: undefined;
|
|
103
|
+
if (!pkg) {
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
// `ensurePackage` installs by package name, so the `internal` subpath is
|
|
107
|
+
// required separately. Plain `require` holds only while both runners are CJS;
|
|
108
|
+
// `@nx/oxlint` is ESM, which is why the arm above needs `handleImport`.
|
|
109
|
+
(0, devkit_1.ensurePackage)(pkg, versions_1.nxVersion);
|
|
110
|
+
const { oxlintPlugins } = require(`${pkg}/internal`);
|
|
111
|
+
return oxlintPlugins ?? [];
|
|
112
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AssetGlob } from './assets';
|
|
2
2
|
import { normalizeAssets, getAssetOutputPath, NormalizedAssetEntry as AssetEntry } from './normalize-assets';
|
|
3
|
-
import { ChangedFile } from 'nx/
|
|
3
|
+
import { ChangedFile } from '@nx/devkit/internal';
|
|
4
4
|
export type { AssetEntry };
|
|
5
5
|
export { normalizeAssets, getAssetOutputPath };
|
|
6
6
|
export type FileEventType = 'create' | 'update' | 'delete';
|
|
@@ -12,7 +12,7 @@ const normalize_assets_1 = require("./normalize-assets");
|
|
|
12
12
|
Object.defineProperty(exports, "normalizeAssets", { enumerable: true, get: function () { return normalize_assets_1.normalizeAssets; } });
|
|
13
13
|
Object.defineProperty(exports, "getAssetOutputPath", { enumerable: true, get: function () { return normalize_assets_1.getAssetOutputPath; } });
|
|
14
14
|
const devkit_1 = require("@nx/devkit");
|
|
15
|
-
const
|
|
15
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
16
16
|
const picocolors_1 = require("picocolors");
|
|
17
17
|
const defaultFileEventHandler = (events) => {
|
|
18
18
|
const dirs = new Set(events.map((event) => path.dirname(event.dest)));
|
|
@@ -93,7 +93,7 @@ class CopyAssetsHandler {
|
|
|
93
93
|
return ['**/node_modules/**', '**/.git/**'];
|
|
94
94
|
}
|
|
95
95
|
async watchAndProcessOnAssetChange() {
|
|
96
|
-
const unregisterFileWatcher = await
|
|
96
|
+
const unregisterFileWatcher = await internal_1.daemonClient.registerFileWatcher({
|
|
97
97
|
watchProjects: 'all',
|
|
98
98
|
includeGlobalWorkspaceFiles: true,
|
|
99
99
|
}, (err, data) => {
|
|
@@ -9,14 +9,11 @@ exports.updatePaths = updatePaths;
|
|
|
9
9
|
exports.updateBuildableProjectPackageJsonDependencies = updateBuildableProjectPackageJsonDependencies;
|
|
10
10
|
const devkit_1 = require("@nx/devkit");
|
|
11
11
|
const fs_1 = require("fs");
|
|
12
|
-
const operators_1 = require("nx/src/project-graph/operators");
|
|
13
|
-
const fileutils_1 = require("nx/src/utils/fileutils");
|
|
14
|
-
const output_1 = require("nx/src/utils/output");
|
|
15
12
|
const path_1 = require("path");
|
|
16
13
|
const ts_config_1 = require("./typescript/ts-config");
|
|
17
14
|
const strip_glob_to_base_dir_1 = require("./strip-glob-to-base-dir");
|
|
18
15
|
const crypto_1 = require("crypto");
|
|
19
|
-
const
|
|
16
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
20
17
|
function isBuildable(target, node) {
|
|
21
18
|
return (node.data.targets &&
|
|
22
19
|
node.data.targets[target] &&
|
|
@@ -49,11 +46,11 @@ function calculateProjectDependencies(projGraph, root, projectName, targetName,
|
|
|
49
46
|
.map(({ name: dep, isTopLevel }) => {
|
|
50
47
|
let project = null;
|
|
51
48
|
const depNode = projGraph.nodes[dep] || projGraph.externalNodes[dep];
|
|
52
|
-
if ((0,
|
|
49
|
+
if ((0, internal_1.isProjectGraphProjectNode)(depNode) && depNode.type === 'lib') {
|
|
53
50
|
if (isBuildable(targetName, depNode)) {
|
|
54
51
|
const libPackageJsonPath = (0, path_1.join)(root, depNode.data.root, 'package.json');
|
|
55
52
|
project = {
|
|
56
|
-
name: (0,
|
|
53
|
+
name: (0, internal_1.fileExists)(libPackageJsonPath)
|
|
57
54
|
? (0, devkit_1.readJsonFile)(libPackageJsonPath).name // i.e. @workspace/mylib
|
|
58
55
|
: dep,
|
|
59
56
|
outputs: (0, devkit_1.getOutputsForTargetAndConfiguration)({
|
|
@@ -68,7 +65,7 @@ function calculateProjectDependencies(projGraph, root, projectName, targetName,
|
|
|
68
65
|
nonBuildableDependencies.push(dep);
|
|
69
66
|
}
|
|
70
67
|
}
|
|
71
|
-
else if ((0,
|
|
68
|
+
else if ((0, internal_1.isProjectGraphExternalNode)(depNode)) {
|
|
72
69
|
project = {
|
|
73
70
|
name: depNode.data.packageName,
|
|
74
71
|
outputs: [],
|
|
@@ -130,7 +127,7 @@ function readTsConfigWithRemappedPaths(originalTsconfigPath, generatedTsconfigPa
|
|
|
130
127
|
}
|
|
131
128
|
generatedTsConfig.compilerOptions.paths = paths;
|
|
132
129
|
if (process.env.NX_VERBOSE_LOGGING_PATH_MAPPINGS === 'true') {
|
|
133
|
-
|
|
130
|
+
devkit_1.output.log({
|
|
134
131
|
title: 'TypeScript path mappings have been rewritten.',
|
|
135
132
|
});
|
|
136
133
|
console.log(JSON.stringify(generatedTsConfig.compilerOptions.paths, null, 2));
|
|
@@ -158,7 +155,7 @@ function calculateDependenciesFromTaskGraph(taskGraph, projectGraph, root, proje
|
|
|
158
155
|
}
|
|
159
156
|
const libPackageJsonPath = (0, path_1.join)(root, depProjectNode.data.root, 'package.json');
|
|
160
157
|
project = {
|
|
161
|
-
name: (0,
|
|
158
|
+
name: (0, internal_1.fileExists)(libPackageJsonPath)
|
|
162
159
|
? (0, devkit_1.readJsonFile)(libPackageJsonPath).name // i.e. @workspace/mylib
|
|
163
160
|
: depTask.target.project,
|
|
164
161
|
outputs,
|
|
@@ -264,7 +261,7 @@ function updatePaths(dependencies, paths) {
|
|
|
264
261
|
const pathsKeys = Object.keys(paths);
|
|
265
262
|
// For each registered dependency
|
|
266
263
|
dependencies
|
|
267
|
-
.filter((dep) => (0,
|
|
264
|
+
.filter((dep) => (0, internal_1.isProjectGraphProjectNode)(dep.node))
|
|
268
265
|
.forEach((dep) => {
|
|
269
266
|
// If there are outputs
|
|
270
267
|
if (dep.outputs && dep.outputs.length > 0) {
|
|
@@ -335,7 +332,7 @@ function updateBuildableProjectPackageJsonDependencies(root, projectName, target
|
|
|
335
332
|
packageJson.peerDependencies = packageJson.peerDependencies || {};
|
|
336
333
|
let updatePackageJson = false;
|
|
337
334
|
dependencies.forEach((entry) => {
|
|
338
|
-
const packageName = (0,
|
|
335
|
+
const packageName = (0, internal_1.isNpmProject)(entry.node)
|
|
339
336
|
? entry.node.data.packageName
|
|
340
337
|
: entry.name;
|
|
341
338
|
if (!hasDependency(packageJson, 'dependencies', packageName) &&
|
|
@@ -343,7 +340,7 @@ function updateBuildableProjectPackageJsonDependencies(root, projectName, target
|
|
|
343
340
|
!hasDependency(packageJson, 'peerDependencies', packageName)) {
|
|
344
341
|
try {
|
|
345
342
|
let depVersion;
|
|
346
|
-
if ((0,
|
|
343
|
+
if ((0, internal_1.isProjectGraphProjectNode)(entry.node) &&
|
|
347
344
|
entry.node.type === 'lib') {
|
|
348
345
|
const outputs = (0, devkit_1.getOutputsForTargetAndConfiguration)({
|
|
349
346
|
project: projectName,
|
|
@@ -354,7 +351,7 @@ function updateBuildableProjectPackageJsonDependencies(root, projectName, target
|
|
|
354
351
|
depVersion = (0, devkit_1.readJsonFile)(depPackageJsonPath).version;
|
|
355
352
|
packageJson[typeOfDependency][packageName] = depVersion;
|
|
356
353
|
}
|
|
357
|
-
else if ((0,
|
|
354
|
+
else if ((0, internal_1.isNpmProject)(entry.node)) {
|
|
358
355
|
// If an npm dep is part of the workspace devDependencies, do not include it the library
|
|
359
356
|
if (!!workspacePackageJson.devDependencies?.[entry.node.data.packageName]) {
|
|
360
357
|
return;
|
|
@@ -2,12 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.findNpmDependencies = findNpmDependencies;
|
|
4
4
|
const path_1 = require("path");
|
|
5
|
-
const configuration_1 = require("nx/src/config/configuration");
|
|
6
5
|
const devkit_1 = require("@nx/devkit");
|
|
7
|
-
const fileutils_1 = require("nx/src/utils/fileutils");
|
|
8
|
-
const project_graph_1 = require("nx/src/config/project-graph");
|
|
9
6
|
const ts_config_1 = require("./typescript/ts-config");
|
|
10
|
-
const
|
|
7
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
11
8
|
/**
|
|
12
9
|
* Finds all npm dependencies and their expected versions for a given project.
|
|
13
10
|
*/
|
|
@@ -44,14 +41,14 @@ function collectDependenciesFromFileMap(workspaceRoot, sourceProject, projectGra
|
|
|
44
41
|
// If build target does not exist in project, use all files as input.
|
|
45
42
|
// This is needed for transitive dependencies for apps -- where libs may not be buildable.
|
|
46
43
|
const inputs = sourceProject.data.targets[buildTarget]
|
|
47
|
-
? (0,
|
|
44
|
+
? (0, internal_1.getTargetInputs)((0, internal_1.readNxJsonFromDisk)(), sourceProject, buildTarget).selfInputs
|
|
48
45
|
: ['{projectRoot}/**/*'];
|
|
49
46
|
if (ignoredFiles) {
|
|
50
47
|
for (const pattern of ignoredFiles) {
|
|
51
48
|
inputs.push(`!${pattern}`);
|
|
52
49
|
}
|
|
53
50
|
}
|
|
54
|
-
const files = (0,
|
|
51
|
+
const files = (0, internal_1.filterUsingGlobPatterns)(sourceProject.data.root, projectFileMap[sourceProject.name] || [], inputs);
|
|
55
52
|
for (const fileData of files) {
|
|
56
53
|
if (!fileData.deps ||
|
|
57
54
|
fileData.file ===
|
|
@@ -59,7 +56,7 @@ function collectDependenciesFromFileMap(workspaceRoot, sourceProject, projectGra
|
|
|
59
56
|
continue;
|
|
60
57
|
}
|
|
61
58
|
for (const dep of fileData.deps) {
|
|
62
|
-
const target = (0,
|
|
59
|
+
const target = (0, internal_1.fileDataDepTarget)(dep);
|
|
63
60
|
// If the node is external, then read package info from `data`.
|
|
64
61
|
const externalDep = projectGraph.externalNodes[target];
|
|
65
62
|
if (externalDep?.type === 'npm') {
|
|
@@ -110,7 +107,7 @@ function collectDependenciesFromFileMap(workspaceRoot, sourceProject, projectGra
|
|
|
110
107
|
}
|
|
111
108
|
function readPackageJson(project, workspaceRoot) {
|
|
112
109
|
const packageJsonPath = (0, path_1.join)(workspaceRoot, project.data.root, 'package.json');
|
|
113
|
-
if ((0,
|
|
110
|
+
if ((0, internal_1.fileExists)(packageJsonPath))
|
|
114
111
|
return (0, devkit_1.readJsonFile)(packageJsonPath);
|
|
115
112
|
return null;
|
|
116
113
|
}
|
|
@@ -139,7 +136,7 @@ function collectHelperDependencies(workspaceRoot, sourceProject, projectGraph, b
|
|
|
139
136
|
const swcConfigPath = target.options.swcrc
|
|
140
137
|
? (0, path_1.join)(workspaceRoot, target.options.swcrc)
|
|
141
138
|
: (0, path_1.join)(workspaceRoot, sourceProject.data.root, '.swcrc');
|
|
142
|
-
const swcConfig = (0,
|
|
139
|
+
const swcConfig = (0, internal_1.fileExists)(swcConfigPath)
|
|
143
140
|
? (0, devkit_1.readJsonFile)(swcConfigPath)
|
|
144
141
|
: {};
|
|
145
142
|
if (swcConfig?.jsc?.externalHelpers &&
|
|
@@ -169,7 +166,7 @@ function resolveTsConfigForRunCommandsTarget(workspaceRoot, sourceProject, targe
|
|
|
169
166
|
const resolved = (0, path_1.isAbsolute)(commandTsConfig)
|
|
170
167
|
? commandTsConfig
|
|
171
168
|
: (0, path_1.join)(cwdAbsolute, commandTsConfig);
|
|
172
|
-
if ((0,
|
|
169
|
+
if ((0, internal_1.fileExists)(resolved))
|
|
173
170
|
return resolved;
|
|
174
171
|
}
|
|
175
172
|
// Preserves prior behavior when the tsconfig can't be determined from the command.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { GeneratorCallback, Tree } from '@nx/devkit';
|
|
2
|
+
type FormatterSetup = {
|
|
3
|
+
setUp: (tree: Tree, options: {
|
|
4
|
+
skipPackageJson?: boolean;
|
|
5
|
+
}) => GeneratorCallback;
|
|
6
|
+
version: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* The setup for a formatter name that came from a schema, or `undefined` for
|
|
10
|
+
* `'none'` and anything unrecognised.
|
|
11
|
+
*
|
|
12
|
+
* `hasOwnProperty` rather than `in`, which would answer `true` for inherited
|
|
13
|
+
* members like `'constructor'` and hand back an `Object.prototype` function.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getFormatterSetup(formatter: string | undefined): FormatterSetup | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Writes the chosen formatter's config and queues its install.
|
|
18
|
+
*
|
|
19
|
+
* For callers that only need the formatter configured - a preset that creates
|
|
20
|
+
* an empty workspace, say - rather than the whole of `@nx/js:init`. Does
|
|
21
|
+
* nothing for `'none'` or an unrecognised value.
|
|
22
|
+
*/
|
|
23
|
+
export declare function setUpFormatter(tree: Tree, formatter: string | undefined, options?: {
|
|
24
|
+
skipPackageJson?: boolean;
|
|
25
|
+
}): GeneratorCallback;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getFormatterSetup = getFormatterSetup;
|
|
4
|
+
exports.setUpFormatter = setUpFormatter;
|
|
5
|
+
const oxfmt_1 = require("./oxfmt");
|
|
6
|
+
const prettier_1 = require("./prettier");
|
|
7
|
+
const versions_1 = require("./versions");
|
|
8
|
+
/**
|
|
9
|
+
* Not `Partial`, so a new `FormatterType` member fails to compile here until it
|
|
10
|
+
* is set up - but only after `packages/nx` is rebuilt, since the type comes
|
|
11
|
+
* from its emitted declarations. The guard must stay structural: under
|
|
12
|
+
* `strict: false` an untyped lookup yields `any` instead of an error.
|
|
13
|
+
*
|
|
14
|
+
* The key doubles as the npm package name; callers install by it.
|
|
15
|
+
*/
|
|
16
|
+
const formatterSetups = {
|
|
17
|
+
prettier: { setUp: prettier_1.generatePrettierSetup, version: versions_1.prettierVersion },
|
|
18
|
+
oxfmt: { setUp: oxfmt_1.generateOxfmtSetup, version: versions_1.oxfmtVersion },
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* The setup for a formatter name that came from a schema, or `undefined` for
|
|
22
|
+
* `'none'` and anything unrecognised.
|
|
23
|
+
*
|
|
24
|
+
* `hasOwnProperty` rather than `in`, which would answer `true` for inherited
|
|
25
|
+
* members like `'constructor'` and hand back an `Object.prototype` function.
|
|
26
|
+
*/
|
|
27
|
+
function getFormatterSetup(formatter) {
|
|
28
|
+
return formatter !== undefined &&
|
|
29
|
+
Object.prototype.hasOwnProperty.call(formatterSetups, formatter)
|
|
30
|
+
? formatterSetups[formatter]
|
|
31
|
+
: undefined;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Writes the chosen formatter's config and queues its install.
|
|
35
|
+
*
|
|
36
|
+
* For callers that only need the formatter configured - a preset that creates
|
|
37
|
+
* an empty workspace, say - rather than the whole of `@nx/js:init`. Does
|
|
38
|
+
* nothing for `'none'` or an unrecognised value.
|
|
39
|
+
*/
|
|
40
|
+
function setUpFormatter(tree, formatter, options = {}) {
|
|
41
|
+
const setup = getFormatterSetup(formatter);
|
|
42
|
+
return setup ? setup.setUp(tree, options) : () => { };
|
|
43
|
+
}
|
|
@@ -3,16 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.createGlobPatternsForDependencies = createGlobPatternsForDependencies;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const devkit_1 = require("@nx/devkit");
|
|
6
|
-
const workspace_root_1 = require("nx/src/utils/workspace-root");
|
|
7
6
|
const path_1 = require("path");
|
|
8
|
-
const project_graph_1 = require("nx/src/project-graph/project-graph");
|
|
9
|
-
const project_graph_utils_1 = require("nx/src/utils/project-graph-utils");
|
|
10
7
|
const fs_1 = require("fs");
|
|
11
8
|
const ignore_1 = tslib_1.__importDefault(require("ignore"));
|
|
12
|
-
const
|
|
9
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
13
10
|
function configureIgnore() {
|
|
14
11
|
let ig;
|
|
15
|
-
const pathToGitIgnore = (0, path_1.join)(
|
|
12
|
+
const pathToGitIgnore = (0, path_1.join)(devkit_1.workspaceRoot, '.gitignore');
|
|
16
13
|
if ((0, fs_1.existsSync)(pathToGitIgnore)) {
|
|
17
14
|
ig = (0, ignore_1.default)();
|
|
18
15
|
ig.add((0, fs_1.readFileSync)(pathToGitIgnore, { encoding: 'utf-8' }));
|
|
@@ -26,13 +23,13 @@ function configureIgnore() {
|
|
|
26
23
|
*/
|
|
27
24
|
function createGlobPatternsForDependencies(dirPath, fileGlobPattern) {
|
|
28
25
|
let ig = configureIgnore();
|
|
29
|
-
const filenameRelativeToWorkspaceRoot = (0, devkit_1.normalizePath)((0, path_1.relative)(
|
|
30
|
-
const projectGraph = (0,
|
|
31
|
-
const projectRootMappings = (0,
|
|
26
|
+
const filenameRelativeToWorkspaceRoot = (0, devkit_1.normalizePath)((0, path_1.relative)(devkit_1.workspaceRoot, dirPath));
|
|
27
|
+
const projectGraph = (0, devkit_1.readCachedProjectGraph)();
|
|
28
|
+
const projectRootMappings = (0, internal_1.createProjectRootMappings)(projectGraph.nodes);
|
|
32
29
|
// find the project
|
|
33
30
|
let projectName;
|
|
34
31
|
try {
|
|
35
|
-
projectName = (0,
|
|
32
|
+
projectName = (0, internal_1.findProjectForPath)(filenameRelativeToWorkspaceRoot, projectRootMappings);
|
|
36
33
|
if (!projectName) {
|
|
37
34
|
throw new Error(`createGlobPatternsForDependencies: Could not find any project containing the file "${filenameRelativeToWorkspaceRoot}" among it's project files`);
|
|
38
35
|
}
|
|
@@ -42,17 +39,17 @@ function createGlobPatternsForDependencies(dirPath, fileGlobPattern) {
|
|
|
42
39
|
}
|
|
43
40
|
// generate the glob
|
|
44
41
|
try {
|
|
45
|
-
const [projectDirs, warnings] = (0,
|
|
42
|
+
const [projectDirs, warnings] = (0, internal_1.getSourceDirOfDependentProjects)(projectName, projectGraph);
|
|
46
43
|
const dirsToUse = [];
|
|
47
44
|
const recursiveScanDirs = (dirPath) => {
|
|
48
|
-
const children = (0, fs_1.readdirSync)((0, path_1.resolve)(
|
|
45
|
+
const children = (0, fs_1.readdirSync)((0, path_1.resolve)(devkit_1.workspaceRoot, dirPath));
|
|
49
46
|
for (const child of children) {
|
|
50
47
|
const childPath = (0, path_1.join)(dirPath, child);
|
|
51
48
|
if (ig?.ignores(childPath) ||
|
|
52
|
-
!(0, fs_1.lstatSync)((0, path_1.resolve)(
|
|
49
|
+
!(0, fs_1.lstatSync)((0, path_1.resolve)(devkit_1.workspaceRoot, childPath)).isDirectory()) {
|
|
53
50
|
continue;
|
|
54
51
|
}
|
|
55
|
-
if ((0, fs_1.existsSync)((0, path_1.join)(
|
|
52
|
+
if ((0, fs_1.existsSync)((0, path_1.join)(devkit_1.workspaceRoot, childPath, 'ng-package.json'))) {
|
|
56
53
|
dirsToUse.push(childPath);
|
|
57
54
|
}
|
|
58
55
|
else {
|
|
@@ -72,7 +69,7 @@ ${warnings.join('\n- ')}\n
|
|
|
72
69
|
due to missing "sourceRoot" in the dependencies' project configuration
|
|
73
70
|
`);
|
|
74
71
|
}
|
|
75
|
-
return dirsToUse.map((sourceDir) => (0, path_1.resolve)(
|
|
72
|
+
return dirsToUse.map((sourceDir) => (0, path_1.resolve)(devkit_1.workspaceRoot, (0, devkit_1.joinPathFragments)(sourceDir, fileGlobPattern)));
|
|
76
73
|
}
|
|
77
74
|
catch (e) {
|
|
78
75
|
throw new Error(`createGlobPatternsForDependencies: Error when generating globs.\n${e?.message}`);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { Tree } from '@nx/devkit';
|
|
2
|
-
|
|
2
|
+
import { type LinterType } from './linter';
|
|
3
|
+
export declare function normalizeLinterOption(tree: Tree, linter: undefined | LinterType): Promise<LinterType>;
|
|
3
4
|
export declare function normalizeUnitTestRunnerOption<T extends 'none' | 'jest' | 'vitest'>(tree: Tree, unitTestRunner: undefined | T, testRunners?: Array<'jest' | 'vitest'>): Promise<T>;
|
|
@@ -4,37 +4,38 @@ exports.normalizeLinterOption = normalizeLinterOption;
|
|
|
4
4
|
exports.normalizeUnitTestRunnerOption = normalizeUnitTestRunnerOption;
|
|
5
5
|
const internal_1 = require("@nx/devkit/internal");
|
|
6
6
|
const ts_solution_setup_1 = require("./typescript/ts-solution-setup");
|
|
7
|
+
const linter_1 = require("./linter");
|
|
7
8
|
async function normalizeLinterOption(tree, linter) {
|
|
8
9
|
if (linter) {
|
|
9
10
|
return linter;
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
// Following the workspace is not a question. When it already has a linter,
|
|
13
|
+
// use it — including in a hybrid workspace, where `detectLinters` puts the
|
|
14
|
+
// one being migrated *to* first. Pass `--linter` to choose something else.
|
|
15
|
+
const [detected] = (0, linter_1.detectLinters)(tree);
|
|
16
|
+
if (detected) {
|
|
17
|
+
return detected;
|
|
18
|
+
}
|
|
19
|
+
// Nothing to follow, so this is a real choice. `none` is the non-interactive
|
|
20
|
+
// answer, and leads the list so the interactive default matches it.
|
|
21
|
+
return (0, internal_1.isInteractive)()
|
|
22
|
+
? (0, internal_1.selectPrompt)({
|
|
23
|
+
message: `Which linter would you like to use?`,
|
|
24
|
+
choices: [{ value: 'none' }, { value: 'eslint' }, { value: 'oxlint' }],
|
|
25
|
+
})
|
|
26
|
+
: 'none';
|
|
23
27
|
}
|
|
24
28
|
async function normalizeUnitTestRunnerOption(tree, unitTestRunner, testRunners = ['jest', 'vitest']) {
|
|
25
29
|
if (unitTestRunner) {
|
|
26
30
|
return unitTestRunner;
|
|
27
31
|
}
|
|
28
32
|
const isTsSolutionSetup = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
|
|
29
|
-
const choices = isTsSolutionSetup
|
|
30
|
-
? [{ name: 'none' }, ...testRunners.map((runner) => ({ name: runner }))]
|
|
31
|
-
: [...testRunners.map((runner) => ({ name: runner })), { name: 'none' }];
|
|
33
|
+
const choices = (isTsSolutionSetup ? ['none', ...testRunners] : [...testRunners, 'none']).map((value) => ({ value: value }));
|
|
32
34
|
const defaultValue = (isTsSolutionSetup ? 'none' : testRunners[0]);
|
|
33
|
-
return
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}, { unitTestRunner: defaultValue }).then(({ unitTestRunner }) => unitTestRunner);
|
|
35
|
+
return (0, internal_1.isInteractive)()
|
|
36
|
+
? (0, internal_1.selectPrompt)({
|
|
37
|
+
message: `Which unit test runner would you like to use?`,
|
|
38
|
+
choices,
|
|
39
|
+
})
|
|
40
|
+
: defaultValue;
|
|
40
41
|
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getRelativeDirectoryToProjectRoot = getRelativeDirectoryToProjectRoot;
|
|
4
4
|
const path_1 = require("path");
|
|
5
|
-
const
|
|
5
|
+
const devkit_1 = require("@nx/devkit");
|
|
6
6
|
function getRelativeDirectoryToProjectRoot(file, projectRoot) {
|
|
7
7
|
const dir = (0, path_1.dirname)(file);
|
|
8
|
-
const relativeDir = (0,
|
|
8
|
+
const relativeDir = (0, devkit_1.normalizePath)((0, path_1.relative)(projectRoot, dir));
|
|
9
9
|
return relativeDir === '' ? `./` : `./${relativeDir}/`;
|
|
10
10
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type Tree } from '@nx/devkit';
|
|
2
|
+
/**
|
|
3
|
+
* The linters Nx generators can set up for a project.
|
|
4
|
+
*
|
|
5
|
+
* Canonical home. `@nx/eslint` re-exports this for back-compat. Two standalone
|
|
6
|
+
* copies exist because neither package can depend on `@nx/js`: `@nx/workspace`
|
|
7
|
+
* (which `@nx/js` itself depends on) and `LINTERS` in `create-nx-workspace`.
|
|
8
|
+
* The assertion below pins the first; `create-nx-workspace` has no edge to
|
|
9
|
+
* assert across, so that one is still kept in sync by hand.
|
|
10
|
+
*/
|
|
11
|
+
export type LinterType = 'eslint' | 'oxlint' | 'none';
|
|
12
|
+
/**
|
|
13
|
+
* Every linter the workspace has installed, most-preferred first — so `[0]` is
|
|
14
|
+
* the one a generator should follow when it was not told which to set up, and
|
|
15
|
+
* `.includes(x)` answers whether the workspace uses `x` at all. Those differ in
|
|
16
|
+
* a workspace part-way through a migration: it has both, and a project
|
|
17
|
+
* generated for Oxlint still lives under the root ESLint config.
|
|
18
|
+
*
|
|
19
|
+
* Oxlint sorts first when both are present. A workspace with both has adopted
|
|
20
|
+
* Oxlint alongside its existing ESLint setup, and new projects should follow
|
|
21
|
+
* the direction of travel rather than the setup being migrated away from.
|
|
22
|
+
*
|
|
23
|
+
* Empty means the workspace opted out of linting; callers that need a concrete
|
|
24
|
+
* answer should read that as `none` rather than inferring ESLint for it.
|
|
25
|
+
*
|
|
26
|
+
* Reads the tree, never the generator's own module resolution: `eslint` is a
|
|
27
|
+
* peer dependency of several first-party plugins, so it resolves from disk in
|
|
28
|
+
* workspaces that do not use it.
|
|
29
|
+
*/
|
|
30
|
+
export declare function detectLinters(tree: Tree): Exclude<LinterType, 'none'>[];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectLinters = detectLinters;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
function hasPlugin(tree, plugin) {
|
|
6
|
+
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
7
|
+
return !!nxJson?.plugins?.some((p) => typeof p === 'string' ? p === plugin : p.plugin === plugin);
|
|
8
|
+
}
|
|
9
|
+
function hasAnyDependency(tree, packages) {
|
|
10
|
+
return packages.some((pkg) => Boolean((0, devkit_1.getDependencyVersionFromPackageJson)(tree, pkg)));
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Every linter the workspace has installed, most-preferred first — so `[0]` is
|
|
14
|
+
* the one a generator should follow when it was not told which to set up, and
|
|
15
|
+
* `.includes(x)` answers whether the workspace uses `x` at all. Those differ in
|
|
16
|
+
* a workspace part-way through a migration: it has both, and a project
|
|
17
|
+
* generated for Oxlint still lives under the root ESLint config.
|
|
18
|
+
*
|
|
19
|
+
* Oxlint sorts first when both are present. A workspace with both has adopted
|
|
20
|
+
* Oxlint alongside its existing ESLint setup, and new projects should follow
|
|
21
|
+
* the direction of travel rather than the setup being migrated away from.
|
|
22
|
+
*
|
|
23
|
+
* Empty means the workspace opted out of linting; callers that need a concrete
|
|
24
|
+
* answer should read that as `none` rather than inferring ESLint for it.
|
|
25
|
+
*
|
|
26
|
+
* Reads the tree, never the generator's own module resolution: `eslint` is a
|
|
27
|
+
* peer dependency of several first-party plugins, so it resolves from disk in
|
|
28
|
+
* workspaces that do not use it.
|
|
29
|
+
*/
|
|
30
|
+
function detectLinters(tree) {
|
|
31
|
+
const linters = [];
|
|
32
|
+
if (hasPlugin(tree, '@nx/oxlint') ||
|
|
33
|
+
hasAnyDependency(tree, ['@nx/oxlint', 'oxlint'])) {
|
|
34
|
+
linters.push('oxlint');
|
|
35
|
+
}
|
|
36
|
+
// `@nx/eslint` registers its inference plugin as `@nx/eslint/plugin`, unlike
|
|
37
|
+
// `@nx/oxlint`, which registers under its bare package name.
|
|
38
|
+
if (hasPlugin(tree, '@nx/eslint/plugin') ||
|
|
39
|
+
hasAnyDependency(tree, ['@nx/eslint', 'eslint'])) {
|
|
40
|
+
linters.push('eslint');
|
|
41
|
+
}
|
|
42
|
+
return linters;
|
|
43
|
+
}
|