@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
@@ -1,4 +1,4 @@
1
- import { PackageJson } from 'nx/src/utils/package-json';
1
+ import { PackageJson } from '@nx/devkit/internal';
2
2
  export declare function parseRegistryOptions(cwd: string, pkg: {
3
3
  packageRoot: string;
4
4
  packageJson: PackageJson;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * `@nx/js` inherits `@nx/devkit`'s `nx` peer, which spans a major either
3
+ * side, so an older nx without these helpers can legally be installed. A
4
+ * missing CommonJS named export arrives as `undefined`, so the first use
5
+ * would otherwise be a bare `undefined.every` naming neither package nor
6
+ * cause.
7
+ */
8
+ export declare function assertNxSupportsFormatters(): void;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertNxSupportsFormatters = assertNxSupportsFormatters;
4
+ const internal_1 = require("@nx/devkit/internal");
5
+ /**
6
+ * `@nx/js` inherits `@nx/devkit`'s `nx` peer, which spans a major either
7
+ * side, so an older nx without these helpers can legally be installed. A
8
+ * missing CommonJS named export arrives as `undefined`, so the first use
9
+ * would otherwise be a bare `undefined.every` naming neither package nor
10
+ * cause.
11
+ */
12
+ function assertNxSupportsFormatters() {
13
+ if (internal_1.detectFormatterInTree && internal_1.oxfmtConfigFiles && internal_1.prettierConfigFiles) {
14
+ return;
15
+ }
16
+ throw new Error('The installed version of nx does not export the formatter helpers that @nx/js needs to detect and set up a formatter. ' +
17
+ 'This happens when nx and @nx/js are on different major versions. Run `nx migrate latest` to bring them into line.');
18
+ }
@@ -0,0 +1,4 @@
1
+ import { type GeneratorCallback, type Tree } from '@nx/devkit';
2
+ export declare function generateOxfmtSetup(tree: Tree, options: {
3
+ skipPackageJson?: boolean;
4
+ }): GeneratorCallback;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateOxfmtSetup = generateOxfmtSetup;
4
+ const devkit_1 = require("@nx/devkit");
5
+ // Imported rather than copied: detection ("is this workspace using oxfmt?")
6
+ // and setup ("should a config be written?") have to agree on the same list, or
7
+ // a workspace that already has a config gets a second, redundant one.
8
+ const internal_1 = require("@nx/devkit/internal");
9
+ const nx_formatter_internals_1 = require("./nx-formatter-internals");
10
+ const versions_1 = require("./versions");
11
+ function generateOxfmtSetup(tree, options) {
12
+ (0, nx_formatter_internals_1.assertNxSupportsFormatters)();
13
+ if (internal_1.oxfmtConfigFiles.every((name) => !tree.exists(name))) {
14
+ // oxfmt defaults to double quotes and we prefer single, so that is the one
15
+ // option worth setting. Line width is left at oxfmt's default.
16
+ (0, devkit_1.writeJson)(tree, '.oxfmtrc.json', { singleQuote: true });
17
+ }
18
+ // The oxc extension is what drives oxfmt in the editor, so recommend it for
19
+ // the same reason the prettier setup recommends its own. Only when the file
20
+ // is already there - creating it would push an editor choice on a workspace
21
+ // that has not made one.
22
+ if (tree.exists('.vscode/extensions.json')) {
23
+ (0, devkit_1.updateJson)(tree, '.vscode/extensions.json', (json) => {
24
+ json.recommendations ??= [];
25
+ const extension = 'oxc.oxc-vscode';
26
+ if (!json.recommendations.includes(extension)) {
27
+ json.recommendations.push(extension);
28
+ }
29
+ return json;
30
+ });
31
+ }
32
+ return options.skipPackageJson
33
+ ? () => { }
34
+ : (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { oxfmt: versions_1.oxfmtVersion });
35
+ }
@@ -1,6 +1,6 @@
1
+ import { type PackageJson } from '@nx/devkit/internal';
1
2
  import { ExecutorContext, ProjectFileMap, ProjectGraphProjectNode } from '@nx/devkit';
2
3
  import { DependentBuildableProjectNode } from '../buildable-libs-utils';
3
- import type { PackageJson } from 'nx/src/utils/package-json';
4
4
  export type SupportedFormat = 'cjs' | 'esm';
5
5
  export interface UpdatePackageJsonOption {
6
6
  rootDir?: string;
@@ -4,24 +4,19 @@ exports.updatePackageJson = updatePackageJson;
4
4
  exports.getExports = getExports;
5
5
  exports.getUpdatedPackageJsonContent = getUpdatedPackageJsonContent;
6
6
  exports.getOutputDir = getOutputDir;
7
- // eslint-disable-next-line @typescript-eslint/no-restricted-imports
8
- const lock_file_1 = require("nx/src/plugins/js/lock-file/lock-file");
9
- // eslint-disable-next-line @typescript-eslint/no-restricted-imports
10
- const create_package_json_1 = require("nx/src/plugins/js/package-json/create-package-json");
7
+ const internal_1 = require("@nx/devkit/internal");
11
8
  const devkit_1 = require("@nx/devkit");
12
9
  const node_fs_1 = require("node:fs");
13
10
  const path_1 = require("path");
14
- const fileutils_1 = require("nx/src/utils/fileutils");
15
- const nx_deps_cache_1 = require("nx/src/project-graph/nx-deps-cache");
16
11
  const get_main_file_dir_1 = require("../get-main-file-dir");
17
12
  const strip_glob_to_base_dir_1 = require("../strip-glob-to-base-dir");
18
13
  function updatePackageJson(options, context, target, dependencies, fileMap = null) {
19
14
  let packageJson;
20
15
  if (fileMap == null) {
21
- fileMap = (0, nx_deps_cache_1.readFileMapCache)()?.fileMap?.projectFileMap || {};
16
+ fileMap = (0, internal_1.readFileMapCache)()?.fileMap?.projectFileMap || {};
22
17
  }
23
18
  if (options.updateBuildableProjectDepsInPackageJson) {
24
- packageJson = (0, create_package_json_1.createPackageJson)(context.projectName, context.projectGraph, {
19
+ packageJson = (0, internal_1.createPackageJson)(context.projectName, context.projectGraph, {
25
20
  target: context.targetName,
26
21
  root: context.root,
27
22
  // By default we remove devDependencies since this is a production build.
@@ -34,7 +29,7 @@ function updatePackageJson(options, context, target, dependencies, fileMap = nul
34
29
  }
35
30
  else {
36
31
  const pathToPackageJson = (0, path_1.join)(context.root, options.projectRoot, 'package.json');
37
- packageJson = (0, fileutils_1.fileExists)(pathToPackageJson)
32
+ packageJson = (0, internal_1.fileExists)(pathToPackageJson)
38
33
  ? (0, devkit_1.readJsonFile)(pathToPackageJson)
39
34
  : { name: context.projectName, version: '0.0.1' };
40
35
  }
@@ -50,22 +45,16 @@ function updatePackageJson(options, context, target, dependencies, fileMap = nul
50
45
  }
51
46
  options.format = ['cjs'];
52
47
  }
53
- // update package specific settings
54
48
  packageJson = getUpdatedPackageJsonContent(packageJson, options);
55
- // save files
56
- (0, devkit_1.writeJsonFile)(`${options.outputPath}/package.json`, packageJson);
49
+ const packageManager = (0, devkit_1.detectPackageManager)(context.root);
57
50
  if (options.generateLockfile) {
58
- const packageManager = (0, devkit_1.detectPackageManager)(context.root);
59
- if (packageManager === 'bun') {
60
- devkit_1.logger.warn(`Bun lockfile generation is unsupported. Remove "generateLockfile" option or set it to false.`);
61
- }
62
- else {
63
- const lockFile = (0, lock_file_1.createLockFile)(packageJson, context.projectGraph, packageManager);
64
- (0, node_fs_1.writeFileSync)(`${options.outputPath}/${(0, lock_file_1.getLockFileName)(packageManager)}`, lockFile, {
65
- encoding: 'utf-8',
66
- });
67
- }
51
+ (0, internal_1.generatePrunedDeployOutput)(packageJson, context.projectGraph, options.projectRoot, {
52
+ outputDirectory: options.outputPath,
53
+ packageManager,
54
+ workspaceRoot: context.root,
55
+ });
68
56
  }
57
+ (0, devkit_1.writeJsonFile)(`${options.outputPath}/package.json`, packageJson);
69
58
  }
70
59
  function isNpmNode(node, graph) {
71
60
  return !!(graph.externalNodes[node.name]?.type === 'npm');
@@ -8,8 +8,8 @@ exports.getProjectPackageManagerWorkspaceStateWarningTask = getProjectPackageMan
8
8
  const devkit_1 = require("@nx/devkit");
9
9
  const picomatch = require("picomatch");
10
10
  const posix_1 = require("node:path/posix");
11
- const package_json_1 = require("nx/src/plugins/package-json");
12
11
  const semver_1 = require("semver");
12
+ const internal_1 = require("@nx/devkit/internal");
13
13
  function getProjectPackageManagerWorkspaceState(tree, projectRoot) {
14
14
  if (!isUsingPackageManagerWorkspaces(tree)) {
15
15
  return 'no-workspaces';
@@ -19,7 +19,7 @@ function getProjectPackageManagerWorkspaceState(tree, projectRoot) {
19
19
  return isIncluded ? 'included' : 'excluded';
20
20
  }
21
21
  function getPackageManagerWorkspacesPatterns(tree) {
22
- return (0, package_json_1.getGlobPatternsFromPackageManagerWorkspaces)(tree.root, (path) => (0, devkit_1.readJson)(tree, path, { expectComments: true }), (path) => {
22
+ return (0, internal_1.getGlobPatternsFromPackageManagerWorkspaces)(tree.root, (path) => (0, devkit_1.readJson)(tree, path, { expectComments: true }), (path) => {
23
23
  const content = tree.read(path, 'utf-8');
24
24
  const { load } = require('@zkochan/js-yaml');
25
25
  return load(content, { filename: path });
@@ -0,0 +1,29 @@
1
+ import type { TargetDefaults } from '@nx/devkit';
2
+ import { type MatchedTargetRef } from './target-defaults-matching';
3
+ /**
4
+ * Adds the missing `PNPM_INSTALL_SETTINGS_INPUTS` to the layer whose `inputs`
5
+ * array the runtime actually uses for this target: the target's own `inputs`
6
+ * when it declares them (its array replaces the defaults' rather than merging
7
+ * with it), otherwise the matching `targetDefaults` entry supplying the array
8
+ * it inherits, and otherwise the target itself with nx's own default spelled
9
+ * out first, so nothing that was hashed stops being hashed. Sources the
10
+ * effective inputs already hash, including via a whole-file root package.json
11
+ * fileset or a `json` input covering the settings fields, are left alone; no
12
+ * `'...'` is ever authored. Returns which layer was mutated, or null when
13
+ * nothing was missing.
14
+ */
15
+ export declare function addPnpmDeployOutputCacheInputs(ref: MatchedTargetRef, targetDefaults: TargetDefaults | undefined, executor: string): 'target' | 'defaults' | null;
16
+ /**
17
+ * Variant for a plugin-inferred target, whose generated `inputs` already carry
18
+ * the settings sources (the runtime probe only while the root manifest has no
19
+ * valid pnpm pin): a repair is only needed when an overlay (a project-level
20
+ * target entry, exact or glob key, or a matching `targetDefaults` entry)
21
+ * supplies a replacing `inputs` array that discards them. The repair appends
22
+ * the full set, probe included, because it runs once and the pin can be
23
+ * removed later. The inferred layer is modeled as an array of exactly the
24
+ * settings inputs: enough for the missing check, and it makes an overlay-less
25
+ * target come back as nothing missing, so the fallback that would narrow the
26
+ * plugin's richer array to `DEFAULT_INPUTS` can never be reached: with no
27
+ * replacing supplier there is nothing to mutate.
28
+ */
29
+ export declare function addPnpmDeployOutputCacheInputsToInferredTargetOverlay(ref: MatchedTargetRef, targetDefaults: TargetDefaults | undefined): 'target' | 'defaults' | null;
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addPnpmDeployOutputCacheInputs = addPnpmDeployOutputCacheInputs;
4
+ exports.addPnpmDeployOutputCacheInputsToInferredTargetOverlay = addPnpmDeployOutputCacheInputsToInferredTargetOverlay;
5
+ const internal_1 = require("@nx/devkit/internal");
6
+ const pnpm_install_settings_inputs_1 = require("./pnpm-install-settings-inputs");
7
+ const target_defaults_matching_1 = require("./target-defaults-matching");
8
+ const ROOT_MANIFEST = '{workspaceRoot}/package.json';
9
+ const MANIFEST_SETTINGS_FIELDS = new Set(pnpm_install_settings_inputs_1.PNPM_INSTALL_SETTINGS_INPUTS.filter((input) => typeof input !== 'string' && 'json' in input).flatMap((input) => input.fields ?? []));
10
+ /**
11
+ * Adds the missing `PNPM_INSTALL_SETTINGS_INPUTS` to the layer whose `inputs`
12
+ * array the runtime actually uses for this target: the target's own `inputs`
13
+ * when it declares them (its array replaces the defaults' rather than merging
14
+ * with it), otherwise the matching `targetDefaults` entry supplying the array
15
+ * it inherits, and otherwise the target itself with nx's own default spelled
16
+ * out first, so nothing that was hashed stops being hashed. Sources the
17
+ * effective inputs already hash, including via a whole-file root package.json
18
+ * fileset or a `json` input covering the settings fields, are left alone; no
19
+ * `'...'` is ever authored. Returns which layer was mutated, or null when
20
+ * nothing was missing.
21
+ */
22
+ function addPnpmDeployOutputCacheInputs(ref, targetDefaults, executor) {
23
+ const selectedKey = targetDefaults
24
+ ? (0, target_defaults_matching_1.selectDefaultsKey)(ref, targetDefaults, executor)
25
+ : null;
26
+ const entries = (0, target_defaults_matching_1.compatibleDefaultsEntries)(ref, selectedKey, targetDefaults);
27
+ const defaults = entries.length
28
+ ? (0, internal_1.readTargetDefaultsForTarget)(ref.targetName, { [selectedKey]: entries }, ref.matcherExecutor, {
29
+ projectName: ref.projectName,
30
+ projectNode: ref.projectNode,
31
+ sourcePlugin: ref.sourcePlugin,
32
+ })
33
+ : null;
34
+ const effective = (0, internal_1.mergeTargetConfigurations)(ref.target, defaults ?? {});
35
+ const missing = missingSettingsInputs(effective.inputs);
36
+ if (missing.length === 0) {
37
+ return null;
38
+ }
39
+ if (ref.target.inputs !== undefined) {
40
+ appendInputs(ref.target, missing);
41
+ return 'target';
42
+ }
43
+ const supplier = (0, target_defaults_matching_1.lastMatchingInputsSupplier)(ref, selectedKey, entries);
44
+ if (supplier) {
45
+ appendInputs(supplier, missing);
46
+ return 'defaults';
47
+ }
48
+ appendInputs(ref.target, missing);
49
+ return 'target';
50
+ }
51
+ /**
52
+ * Variant for a plugin-inferred target, whose generated `inputs` already carry
53
+ * the settings sources (the runtime probe only while the root manifest has no
54
+ * valid pnpm pin): a repair is only needed when an overlay (a project-level
55
+ * target entry, exact or glob key, or a matching `targetDefaults` entry)
56
+ * supplies a replacing `inputs` array that discards them. The repair appends
57
+ * the full set, probe included, because it runs once and the pin can be
58
+ * removed later. The inferred layer is modeled as an array of exactly the
59
+ * settings inputs: enough for the missing check, and it makes an overlay-less
60
+ * target come back as nothing missing, so the fallback that would narrow the
61
+ * plugin's richer array to `DEFAULT_INPUTS` can never be reached: with no
62
+ * replacing supplier there is nothing to mutate.
63
+ */
64
+ function addPnpmDeployOutputCacheInputsToInferredTargetOverlay(ref, targetDefaults) {
65
+ const selectedKey = targetDefaults
66
+ ? (0, target_defaults_matching_1.selectDefaultsKey)(ref, targetDefaults, ref.matcherExecutor)
67
+ : null;
68
+ const entries = (0, target_defaults_matching_1.compatibleDefaultsEntries)(ref, selectedKey, targetDefaults);
69
+ const defaults = entries.length
70
+ ? (0, internal_1.readTargetDefaultsForTarget)(ref.targetName, { [selectedKey]: entries }, ref.matcherExecutor, {
71
+ projectName: ref.projectName,
72
+ projectNode: ref.projectNode,
73
+ sourcePlugin: ref.sourcePlugin,
74
+ })
75
+ : null;
76
+ const inferredLayer = {
77
+ inputs: [...pnpm_install_settings_inputs_1.PNPM_INSTALL_SETTINGS_INPUTS],
78
+ };
79
+ const effective = (0, internal_1.mergeTargetConfigurations)(ref.target, (0, internal_1.mergeTargetConfigurations)(defaults ?? {}, inferredLayer));
80
+ const missing = missingSettingsInputs(effective.inputs);
81
+ if (missing.length === 0) {
82
+ return null;
83
+ }
84
+ if (ref.target.inputs !== undefined) {
85
+ appendInputs(ref.target, missing);
86
+ return 'target';
87
+ }
88
+ const supplier = (0, target_defaults_matching_1.lastMatchingInputsSupplier)(ref, selectedKey, entries);
89
+ if (supplier) {
90
+ appendInputs(supplier, missing);
91
+ return 'defaults';
92
+ }
93
+ return null;
94
+ }
95
+ /**
96
+ * The settings sources the effective inputs do not hash yet. The manifest
97
+ * counts as covered by a whole-file fileset no negative pattern can cancel,
98
+ * or by an existing `json` input that hashes all the settings fields (`json`
99
+ * inputs are immune to fileset negations); the workspace yaml by its fileset
100
+ * (a negative pattern cancelling that fileset has no input-level counter, so
101
+ * it is left to the author who wrote it); the runtime probe by an identical
102
+ * `runtime` entry.
103
+ */
104
+ function missingSettingsInputs(inputs) {
105
+ const filesets = (0, target_defaults_matching_1.namedFilesets)(inputs);
106
+ const missing = [];
107
+ for (const input of pnpm_install_settings_inputs_1.PNPM_INSTALL_SETTINGS_INPUTS) {
108
+ if (typeof input === 'string') {
109
+ if (!filesets.has(input)) {
110
+ missing.push(input);
111
+ }
112
+ }
113
+ else if ('runtime' in input) {
114
+ if (!(inputs ?? []).some((existing) => typeof existing === 'object' &&
115
+ existing !== null &&
116
+ 'runtime' in existing &&
117
+ existing.runtime === input.runtime)) {
118
+ missing.push(input);
119
+ }
120
+ }
121
+ else if (!(filesets.has(ROOT_MANIFEST) && !negationMayCancel(inputs)) &&
122
+ !(inputs ?? []).some((existing) => typeof existing === 'object' &&
123
+ existing !== null &&
124
+ 'json' in existing &&
125
+ existing.json === ROOT_MANIFEST &&
126
+ [...MANIFEST_SETTINGS_FIELDS].every((field) => jsonInputCoversField(existing, field)))) {
127
+ missing.push(input);
128
+ }
129
+ }
130
+ return missing;
131
+ }
132
+ /**
133
+ * Whether a negative fileset entry could remove the source from the hash. Any
134
+ * workspace-root-scoped negation counts, in the string or `{ fileset }` form:
135
+ * nx's pattern syntax (globs, extglobs) is not re-evaluated here, and an
136
+ * extra input for a source the negation does not actually touch is harmless.
137
+ * Project-relative negations never match a workspace-root file.
138
+ */
139
+ function negationMayCancel(inputs) {
140
+ return (inputs ?? []).some((existing) => {
141
+ const pattern = typeof existing === 'string'
142
+ ? existing
143
+ : typeof existing === 'object' &&
144
+ existing !== null &&
145
+ 'fileset' in existing
146
+ ? existing.fileset
147
+ : undefined;
148
+ return (typeof pattern === 'string' &&
149
+ pattern.startsWith('!') &&
150
+ pattern.includes('{workspaceRoot}'));
151
+ });
152
+ }
153
+ /**
154
+ * Whether an existing `json` input hashes `field`: selected by the allowlist
155
+ * (an entry covers its whole subtree) and not touched by the denylist, which
156
+ * the hasher applies after selection. A denylist entry below the field only
157
+ * removes part of its subtree, but that part is then unhashed, so it
158
+ * disqualifies coverage too.
159
+ */
160
+ function jsonInputCoversField(input, field) {
161
+ const selected = input.fields === undefined ||
162
+ input.fields.some((path) => path === field || field.startsWith(`${path}.`));
163
+ if (!selected) {
164
+ return false;
165
+ }
166
+ return !(input.excludeFields ?? []).some((path) => path === field ||
167
+ field.startsWith(`${path}.`) ||
168
+ path.startsWith(`${field}.`));
169
+ }
170
+ /**
171
+ * Appends to an array that already exists, or writes nx's default as the base
172
+ * when no layer declares one, so the configuration is never narrowed to the
173
+ * settings sources alone.
174
+ */
175
+ function appendInputs(config, missing) {
176
+ config.inputs = [...(config.inputs ?? target_defaults_matching_1.DEFAULT_INPUTS), ...missing];
177
+ }
@@ -0,0 +1,45 @@
1
+ import { type PackageManager } from '@nx/devkit';
2
+ import { type JsonInput } from '@nx/devkit/internal';
3
+ /**
4
+ * Task inputs covering the sources of the pnpm install settings a pruned
5
+ * deploy output carries (build-script approvals, `supportedArchitectures`,
6
+ * `patchedDependencies`). Nothing else in a build target's default hash moves
7
+ * when an approval is revoked, so a target that emits the deploy output must
8
+ * hash these or a cached run replays an output that still grants it. The
9
+ * manifest is narrowed to the fields the output is built from so dependency
10
+ * bumps in the root package.json do not invalidate every build.
11
+ *
12
+ * The pnpm major selects which emitted file carries the settings (pnpm 11+
13
+ * reads them from pnpm-workspace.yaml, pnpm <=10 from the emitted
14
+ * package.json). The manifest's `packageManager` field pins it when it
15
+ * parses to a pnpm version; the runtime probe covers the ambient binary that
16
+ * decides it otherwise, printing only the major so pnpm patch and minor
17
+ * releases do not move the hash, and a sentinel when the binary is missing
18
+ * (the hasher records the probe's output without checking its exit status,
19
+ * so a missing binary does not fail the hash). The full set keeps the probe
20
+ * even under a valid pin: the generator and the migrations write inputs
21
+ * once, and the pin can be removed later. Plugins re-infer on every graph
22
+ * build, so they use {@link pnpmInstallSettingsInputsForInferredTarget} to
23
+ * add the probe only while no valid pin exists.
24
+ *
25
+ * The contents of vendored non-workspace local-path dependencies also ship in
26
+ * the deploy output but are not covered: their set is derived from the
27
+ * lockfile at build time, so no static input list stays correct as
28
+ * dependencies change. Covering them needs content hashing at the graph level
29
+ * (the pnpm parser's directory/link external nodes hash only name and path).
30
+ */
31
+ export declare const PNPM_MAJOR_RUNTIME_INPUT: {
32
+ runtime: string;
33
+ };
34
+ export declare const PNPM_INSTALL_SETTINGS_INPUTS: (string | JsonInput | {
35
+ runtime: string;
36
+ })[];
37
+ export declare function pnpmInstallSettingsInputsForInferredTarget(includePnpmMajorRuntimeInput: boolean): (string | JsonInput | {
38
+ runtime: string;
39
+ })[];
40
+ /**
41
+ * Whether an inferred build target needs the runtime probe: the workspace uses
42
+ * pnpm and the root `packageManager` field does not pin a pnpm version. A
43
+ * missing or unreadable root manifest cannot pin one, so it counts as no pin.
44
+ */
45
+ export declare function shouldIncludePnpmMajorRuntimeInput(packageManager: PackageManager, workspaceRoot: string): boolean;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PNPM_INSTALL_SETTINGS_INPUTS = exports.PNPM_MAJOR_RUNTIME_INPUT = void 0;
4
+ exports.pnpmInstallSettingsInputsForInferredTarget = pnpmInstallSettingsInputsForInferredTarget;
5
+ exports.shouldIncludePnpmMajorRuntimeInput = shouldIncludePnpmMajorRuntimeInput;
6
+ const devkit_1 = require("@nx/devkit");
7
+ const internal_1 = require("@nx/devkit/internal");
8
+ const path_1 = require("path");
9
+ /**
10
+ * Task inputs covering the sources of the pnpm install settings a pruned
11
+ * deploy output carries (build-script approvals, `supportedArchitectures`,
12
+ * `patchedDependencies`). Nothing else in a build target's default hash moves
13
+ * when an approval is revoked, so a target that emits the deploy output must
14
+ * hash these or a cached run replays an output that still grants it. The
15
+ * manifest is narrowed to the fields the output is built from so dependency
16
+ * bumps in the root package.json do not invalidate every build.
17
+ *
18
+ * The pnpm major selects which emitted file carries the settings (pnpm 11+
19
+ * reads them from pnpm-workspace.yaml, pnpm <=10 from the emitted
20
+ * package.json). The manifest's `packageManager` field pins it when it
21
+ * parses to a pnpm version; the runtime probe covers the ambient binary that
22
+ * decides it otherwise, printing only the major so pnpm patch and minor
23
+ * releases do not move the hash, and a sentinel when the binary is missing
24
+ * (the hasher records the probe's output without checking its exit status,
25
+ * so a missing binary does not fail the hash). The full set keeps the probe
26
+ * even under a valid pin: the generator and the migrations write inputs
27
+ * once, and the pin can be removed later. Plugins re-infer on every graph
28
+ * build, so they use {@link pnpmInstallSettingsInputsForInferredTarget} to
29
+ * add the probe only while no valid pin exists.
30
+ *
31
+ * The contents of vendored non-workspace local-path dependencies also ship in
32
+ * the deploy output but are not covered: their set is derived from the
33
+ * lockfile at build time, so no static input list stays correct as
34
+ * dependencies change. Covering them needs content hashing at the graph level
35
+ * (the pnpm parser's directory/link external nodes hash only name and path).
36
+ */
37
+ exports.PNPM_MAJOR_RUNTIME_INPUT = {
38
+ runtime: `node -e "try{console.log('pnpm major '+require('child_process').execSync('pnpm --version',{stdio:['ignore','pipe','ignore']}).toString().trim().split('.')[0])}catch{console.log('pnpm major unavailable')}"`,
39
+ };
40
+ const PNPM_INSTALL_SETTINGS_FILE_INPUTS = [
41
+ '{workspaceRoot}/pnpm-workspace.yaml',
42
+ {
43
+ json: '{workspaceRoot}/package.json',
44
+ fields: [
45
+ 'packageManager',
46
+ 'pnpm.onlyBuiltDependencies',
47
+ 'pnpm.neverBuiltDependencies',
48
+ 'pnpm.allowBuilds',
49
+ 'pnpm.supportedArchitectures',
50
+ 'pnpm.patchedDependencies',
51
+ ],
52
+ },
53
+ ];
54
+ exports.PNPM_INSTALL_SETTINGS_INPUTS = [...PNPM_INSTALL_SETTINGS_FILE_INPUTS, exports.PNPM_MAJOR_RUNTIME_INPUT];
55
+ function pnpmInstallSettingsInputsForInferredTarget(includePnpmMajorRuntimeInput) {
56
+ return includePnpmMajorRuntimeInput
57
+ ? [...PNPM_INSTALL_SETTINGS_FILE_INPUTS, exports.PNPM_MAJOR_RUNTIME_INPUT]
58
+ : [...PNPM_INSTALL_SETTINGS_FILE_INPUTS];
59
+ }
60
+ /**
61
+ * Whether an inferred build target needs the runtime probe: the workspace uses
62
+ * pnpm and the root `packageManager` field does not pin a pnpm version. A
63
+ * missing or unreadable root manifest cannot pin one, so it counts as no pin.
64
+ */
65
+ function shouldIncludePnpmMajorRuntimeInput(packageManager, workspaceRoot) {
66
+ if (packageManager !== 'pnpm') {
67
+ return false;
68
+ }
69
+ let field;
70
+ try {
71
+ field = (0, devkit_1.readJsonFile)((0, path_1.join)(workspaceRoot, 'package.json'))?.packageManager;
72
+ }
73
+ catch {
74
+ field = undefined;
75
+ }
76
+ return ((0, internal_1.parseVersionFromPackageManagerField)('pnpm', typeof field === 'string' ? field : undefined) === null);
77
+ }
@@ -4,6 +4,8 @@ exports.resolveUserExistingPrettierConfig = resolveUserExistingPrettierConfig;
4
4
  exports.generatePrettierSetup = generatePrettierSetup;
5
5
  exports.resolvePrettierConfigPath = resolvePrettierConfigPath;
6
6
  const devkit_1 = require("@nx/devkit");
7
+ const internal_1 = require("@nx/devkit/internal");
8
+ const nx_formatter_internals_1 = require("./nx-formatter-internals");
7
9
  const versions_1 = require("./versions");
8
10
  // Prettier v3 (ESM) exposes its API as named exports; v2 (CJS) exposes it under
9
11
  // `.default` when loaded via `import()`. Return whichever carries the API, or
@@ -44,22 +46,11 @@ async function resolveUserExistingPrettierConfig() {
44
46
  }
45
47
  }
46
48
  function generatePrettierSetup(tree, options) {
47
- // https://prettier.io/docs/en/configuration.html
48
- const prettierrcNameOptions = [
49
- '.prettierrc',
50
- '.prettierrc.json',
51
- '.prettierrc.yml',
52
- '.prettierrc.yaml',
53
- '.prettierrc.json5',
54
- '.prettierrc.js',
55
- '.prettierrc.cjs',
56
- '.prettierrc.mjs',
57
- '.prettierrc.toml',
58
- 'prettier.config.js',
59
- 'prettier.config.cjs',
60
- 'prettier.config.mjs',
61
- ];
62
- if (prettierrcNameOptions.every((name) => !tree.exists(name))) {
49
+ (0, nx_formatter_internals_1.assertNxSupportsFormatters)();
50
+ // Imported rather than copied: detection and setup have to agree on this
51
+ // list, or a workspace whose config format is missing from one side gets a
52
+ // second, redundant `.prettierrc` written beside the one it already has.
53
+ if (internal_1.prettierConfigFiles.every((name) => !tree.exists(name))) {
63
54
  (0, devkit_1.writeJson)(tree, '.prettierrc', { singleQuote: true });
64
55
  }
65
56
  if (!tree.exists('.prettierignore')) {
@@ -68,6 +59,7 @@ function generatePrettierSetup(tree, options) {
68
59
  /coverage
69
60
  /.nx/cache
70
61
  /.nx/workspace-data
62
+ ${(0, internal_1.getLockFileName)((0, devkit_1.detectPackageManager)(tree.root))}
71
63
  `);
72
64
  }
73
65
  if (tree.exists('.vscode/extensions.json')) {
@@ -85,6 +77,7 @@ function generatePrettierSetup(tree, options) {
85
77
  : (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { prettier: versions_1.prettierVersion });
86
78
  }
87
79
  async function resolvePrettierConfigPath(tree) {
80
+ (0, nx_formatter_internals_1.assertNxSupportsFormatters)();
88
81
  const prettier = await importPrettier();
89
82
  if (!prettier) {
90
83
  return null;
@@ -96,23 +89,11 @@ async function resolvePrettierConfigPath(tree) {
96
89
  if (!tree) {
97
90
  return null;
98
91
  }
99
- // if we haven't find a config file in the file system, we try to find it in the virtual tree
100
- // https://prettier.io/docs/en/configuration.html
101
- const prettierrcNameOptions = [
102
- '.prettierrc',
103
- '.prettierrc.json',
104
- '.prettierrc.yml',
105
- '.prettierrc.yaml',
106
- '.prettierrc.json5',
107
- '.prettierrc.js',
108
- '.prettierrc.cjs',
109
- '.prettierrc.mjs',
110
- '.prettierrc.toml',
111
- 'prettier.config.js',
112
- 'prettier.config.cjs',
113
- 'prettier.config.mjs',
114
- ];
115
- const filePath = prettierrcNameOptions.find((file) => tree.exists(file));
92
+ // Same shared list as the setup above, so a config this can't see is one the
93
+ // setup would overwrite. The copy this replaced was missing the `.ts`,
94
+ // `.mts` and `.cts` forms.
95
+ // https://prettier.io/docs/configuration
96
+ const filePath = internal_1.prettierConfigFiles.find((file) => tree.exists(file));
116
97
  if (filePath) {
117
98
  return filePath;
118
99
  }
@@ -0,0 +1,57 @@
1
+ import type { ProjectGraphProjectNode, TargetConfiguration, TargetDefaultArrayEntry, TargetDefaults } from '@nx/devkit';
2
+ export declare const DEFAULT_INPUTS: string[];
3
+ /** Everything the runtime's `targetDefaults` matcher needs to resolve a target. */
4
+ export interface DefaultsMatchContext {
5
+ targetName: string;
6
+ projectName: string;
7
+ projectNode: ProjectGraphProjectNode;
8
+ matcherExecutor: string | undefined;
9
+ sourcePlugin?: string;
10
+ }
11
+ export interface MatchedTargetRef extends DefaultsMatchContext {
12
+ target: TargetConfiguration;
13
+ }
14
+ /**
15
+ * A matched target with the `targetDefaults` key the runtime would resolve for
16
+ * it, carried together so the two cannot fall out of step.
17
+ */
18
+ export interface KeyedTargetRef {
19
+ ref: MatchedTargetRef;
20
+ selectedKey: string | null;
21
+ }
22
+ /**
23
+ * The `targetDefaults` entries under the selected key that survive nx's own
24
+ * per-entry compatibility guard. Graph construction selects the key, then drops
25
+ * each entry whose identity is incompatible with the target's *original* one and
26
+ * keeps the compatible siblings (`createTargetDefaultsResults` in nx's
27
+ * target-defaults). Reading the key unfiltered instead would let a
28
+ * foreign-executor entry contribute outputs the target never gets.
29
+ */
30
+ export declare function compatibleDefaultsEntries(ref: MatchedTargetRef, selectedKey: string | null, targetDefaults: TargetDefaults | undefined): TargetDefaultArrayEntry[];
31
+ /**
32
+ * The last entry under the selected key that both matches the target (the
33
+ * entry's own filter included) and declares `inputs`: the runtime merge makes
34
+ * that entry's array the one the target inherits. A later entry that declares
35
+ * `inputs` behind a filter not matching this target supplies some other
36
+ * target's array, so it cannot be the layer to mutate.
37
+ */
38
+ export declare function lastMatchingInputsSupplier(ref: MatchedTargetRef, selectedKey: string, entries: TargetDefaultArrayEntry[]): TargetDefaultArrayEntry | undefined;
39
+ /** The plain filesets an inputs array names, for a containment check. */
40
+ export declare function namedFilesets(inputs: TargetConfiguration['inputs']): ReadonlySet<string>;
41
+ /**
42
+ * The executor an executor-less target ends up with after its selected
43
+ * defaults key applies. Each matching entry's identity is resolved like the
44
+ * runtime does at merge time: a `command` payload means nx:run-commands, and
45
+ * a later entry's identity replaces an earlier, incompatible one (the reader's
46
+ * merged view keeps the first executor instead, so it cannot be used here).
47
+ */
48
+ export declare function resolveDefaultsExecutor(targetName: string, projectName: string, projectNode: ProjectGraphProjectNode, targetDefaults: TargetDefaults | undefined, executorKeyCandidate?: string): string | undefined;
49
+ /**
50
+ * The `targetDefaults` key nx's runtime would select for this target: keys
51
+ * are tried as the executor key, the exact-name key, then glob keys longest
52
+ * first, and the first whose entries produce a match wins; the rest are
53
+ * shadowed. Resolution per key goes through nx's own reader. Non-matching
54
+ * keys never resolve, so sorting all remaining keys by length stands in for
55
+ * the runtime's glob-only ordering.
56
+ */
57
+ export declare function selectDefaultsKey(ref: DefaultsMatchContext, targetDefaults: TargetDefaults, executorKeyCandidate?: string): string | null;