@nx/js 23.2.0-beta.0 → 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.
Files changed (82) hide show
  1. package/dist/internal.d.ts +9 -3
  2. package/dist/internal.js +28 -17
  3. package/dist/src/executors/copy-workspace-modules/copy-workspace-modules.js +122 -21
  4. package/dist/src/executors/node/lib/output-file.js +4 -4
  5. package/dist/src/executors/node/node.impl.js +9 -10
  6. package/dist/src/executors/prune-lockfile/prune-lockfile.d.ts +1 -1
  7. package/dist/src/executors/prune-lockfile/prune-lockfile.js +40 -33
  8. package/dist/src/executors/tsc/lib/batch/watch.js +3 -3
  9. package/dist/src/executors/tsc/tsc.batch-impl.d.ts +1 -1
  10. package/dist/src/executors/tsc/tsc.batch-impl.js +2 -2
  11. package/dist/src/executors/verdaccio/verdaccio.impl.js +8 -1
  12. package/dist/src/generators/init/init.js +32 -15
  13. package/dist/src/generators/init/schema.d.ts +1 -1
  14. package/dist/src/generators/init/schema.json +1 -1
  15. package/dist/src/generators/library/library.d.ts +1 -1
  16. package/dist/src/generators/library/library.js +34 -20
  17. package/dist/src/generators/library/schema.d.ts +11 -3
  18. package/dist/src/generators/library/schema.json +15 -4
  19. package/dist/src/generators/library/utils/add-release-config.js +2 -2
  20. package/dist/src/generators/setup-build/generator.js +2 -7
  21. package/dist/src/generators/typescript-sync/typescript-sync.d.ts +1 -1
  22. package/dist/src/generators/typescript-sync/typescript-sync.js +2 -2
  23. package/dist/src/index.d.ts +3 -2
  24. package/dist/src/index.js +8 -8
  25. package/dist/src/migrations/update-23-1-0/add-ignore-deprecations-for-ts6.d.ts +3 -2
  26. package/dist/src/migrations/update-23-1-0/add-ignore-deprecations-for-ts6.js +17 -11
  27. package/dist/src/migrations/update-23-2-0/add-pnpm-deploy-output-cache-inputs.d.ts +14 -0
  28. package/dist/src/migrations/update-23-2-0/add-pnpm-deploy-output-cache-inputs.js +242 -0
  29. package/dist/src/migrations/update-23-2-0/add-pnpm-deploy-output-cache-inputs.md +64 -0
  30. package/dist/src/migrations/update-23-2-0/add-pnpm-prune-lockfile-cache-config.d.ts +2 -0
  31. package/dist/src/migrations/update-23-2-0/add-pnpm-prune-lockfile-cache-config.js +305 -0
  32. package/dist/src/migrations/update-23-2-0/add-pnpm-prune-lockfile-cache-config.md +59 -0
  33. package/dist/src/plugins/typescript/plugin.js +9 -14
  34. package/dist/src/plugins/typescript/util.d.ts +1 -1
  35. package/dist/src/release/utils/update-lock-file.js +5 -7
  36. package/dist/src/release/version-actions.d.ts +12 -3
  37. package/dist/src/release/version-actions.js +236 -76
  38. package/dist/src/utils/add-linting-to-project.d.ts +46 -0
  39. package/dist/src/utils/add-linting-to-project.js +112 -0
  40. package/dist/src/utils/assets/copy-assets-handler.d.ts +1 -1
  41. package/dist/src/utils/assets/copy-assets-handler.js +2 -2
  42. package/dist/src/utils/buildable-libs-utils.js +10 -13
  43. package/dist/src/utils/find-npm-dependencies.js +7 -10
  44. package/dist/src/utils/formatter-setup.d.ts +26 -0
  45. package/dist/src/utils/formatter-setup.js +43 -0
  46. package/dist/src/utils/generate-globs.js +11 -14
  47. package/dist/src/utils/generator-prompts.d.ts +2 -1
  48. package/dist/src/utils/generator-prompts.js +23 -22
  49. package/dist/src/utils/get-main-file-dir.js +2 -2
  50. package/dist/src/utils/linter.d.ts +30 -0
  51. package/dist/src/utils/linter.js +43 -0
  52. package/dist/src/utils/npm-config.d.ts +1 -1
  53. package/dist/src/utils/nx-formatter-internals.d.ts +8 -0
  54. package/dist/src/utils/nx-formatter-internals.js +18 -0
  55. package/dist/src/utils/oxfmt.d.ts +4 -0
  56. package/dist/src/utils/oxfmt.js +35 -0
  57. package/dist/src/utils/package-json/update-package-json.d.ts +1 -1
  58. package/dist/src/utils/package-json/update-package-json.js +11 -22
  59. package/dist/src/utils/package-manager-workspaces.js +2 -2
  60. package/dist/src/utils/pnpm-deploy-output-cache-inputs.d.ts +29 -0
  61. package/dist/src/utils/pnpm-deploy-output-cache-inputs.js +177 -0
  62. package/dist/src/utils/pnpm-install-settings-inputs.d.ts +45 -0
  63. package/dist/src/utils/pnpm-install-settings-inputs.js +77 -0
  64. package/dist/src/utils/prettier.js +14 -33
  65. package/dist/src/utils/target-defaults-matching.d.ts +57 -0
  66. package/dist/src/utils/target-defaults-matching.js +126 -0
  67. package/dist/src/utils/typescript/configuration.js +3 -5
  68. package/dist/src/utils/typescript/create-ts-config.d.ts +1 -1
  69. package/dist/src/utils/typescript/create-ts-config.js +5 -5
  70. package/dist/src/utils/typescript/plugin.js +2 -2
  71. package/dist/src/utils/typescript/run-type-check.js +2 -2
  72. package/dist/src/utils/typescript/ts-config.d.ts +51 -1
  73. package/dist/src/utils/typescript/ts-config.js +114 -0
  74. package/dist/src/utils/typescript/ts-solution-setup.d.ts +1 -1
  75. package/dist/src/utils/typescript/ts-solution-setup.js +3 -3
  76. package/dist/src/utils/versions.d.ts +1 -0
  77. package/dist/src/utils/versions.js +2 -1
  78. package/dist/src/utils/watch-for-single-file-changes.js +2 -2
  79. package/dist/src/utils/workspace-module-sections.d.ts +16 -0
  80. package/dist/src/utils/workspace-module-sections.js +24 -0
  81. package/migrations.json +13 -1
  82. 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/src/daemon/client/client';
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 client_1 = require("nx/src/daemon/client/client");
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 client_1.daemonClient.registerFileWatcher({
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 project_graph_1 = require("nx/src/config/project-graph");
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, project_graph_1.isProjectGraphProjectNode)(depNode) && depNode.type === 'lib') {
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, fileutils_1.fileExists)(libPackageJsonPath)
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, project_graph_1.isProjectGraphExternalNode)(depNode)) {
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
- output_1.output.log({
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, fileutils_1.fileExists)(libPackageJsonPath)
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, project_graph_1.isProjectGraphProjectNode)(dep.node))
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, operators_1.isNpmProject)(entry.node)
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, project_graph_1.isProjectGraphProjectNode)(entry.node) &&
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, operators_1.isNpmProject)(entry.node)) {
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 task_hasher_1 = require("nx/src/hasher/task-hasher");
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, task_hasher_1.getTargetInputs)((0, configuration_1.readNxJson)(), sourceProject, buildTarget).selfInputs
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, task_hasher_1.filterUsingGlobPatterns)(sourceProject.data.root, projectFileMap[sourceProject.name] || [], inputs);
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, project_graph_1.fileDataDepTarget)(dep);
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, fileutils_1.fileExists)(packageJsonPath))
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, fileutils_1.fileExists)(swcConfigPath)
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, fileutils_1.fileExists)(resolved))
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 find_project_for_path_1 = require("nx/src/project-graph/utils/find-project-for-path");
9
+ const internal_1 = require("@nx/devkit/internal");
13
10
  function configureIgnore() {
14
11
  let ig;
15
- const pathToGitIgnore = (0, path_1.join)(workspace_root_1.workspaceRoot, '.gitignore');
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)(workspace_root_1.workspaceRoot, dirPath));
30
- const projectGraph = (0, project_graph_1.readCachedProjectGraph)();
31
- const projectRootMappings = (0, find_project_for_path_1.createProjectRootMappings)(projectGraph.nodes);
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, find_project_for_path_1.findProjectForPath)(filenameRelativeToWorkspaceRoot, projectRootMappings);
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, project_graph_utils_1.getSourceDirOfDependentProjects)(projectName, projectGraph);
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)(workspace_root_1.workspaceRoot, dirPath));
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)(workspace_root_1.workspaceRoot, childPath)).isDirectory()) {
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)(workspace_root_1.workspaceRoot, childPath, 'ng-package.json'))) {
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)(workspace_root_1.workspaceRoot, (0, devkit_1.joinPathFragments)(sourceDir, fileGlobPattern)));
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
- export declare function normalizeLinterOption(tree: Tree, linter: undefined | 'none' | 'eslint'): Promise<'none' | 'eslint'>;
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
- const isTsSolutionSetup = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
12
- const choices = isTsSolutionSetup
13
- ? [{ name: 'none' }, { name: 'eslint' }]
14
- : [{ name: 'eslint' }, { name: 'none' }];
15
- const defaultValue = isTsSolutionSetup ? 'none' : 'eslint';
16
- return await (0, internal_1.promptWhenInteractive)({
17
- type: 'autocomplete',
18
- name: 'linter',
19
- message: `Which linter would you like to use?`,
20
- choices,
21
- initial: 0,
22
- }, { linter: defaultValue }).then(({ linter }) => linter);
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 await (0, internal_1.promptWhenInteractive)({
34
- type: 'autocomplete',
35
- name: 'unitTestRunner',
36
- message: `Which unit test runner would you like to use?`,
37
- choices,
38
- initial: 0,
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 path_2 = require("nx/src/utils/path");
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, path_2.normalizePath)((0, path_1.relative)(projectRoot, dir));
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
+ }