nx 23.2.0-beta.1 → 23.2.0-beta.3

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 (85) hide show
  1. package/dist/bin/nx.js +1 -0
  2. package/dist/src/analytics/analytics.d.ts +6 -0
  3. package/dist/src/analytics/analytics.js +16 -8
  4. package/dist/src/analytics/index.d.ts +1 -1
  5. package/dist/src/analytics/index.js +2 -1
  6. package/dist/src/command-line/graph/graph.d.ts +1 -0
  7. package/dist/src/command-line/graph/graph.js +15 -6
  8. package/dist/src/command-line/init/implementation/angular/integrated-workspace.js +2 -5
  9. package/dist/src/command-line/init/implementation/angular/legacy-angular-versions.js +3 -0
  10. package/dist/src/command-line/init/implementation/dot-nx/add-nx-scripts.js +4 -1
  11. package/dist/src/command-line/migrate/migrate.js +20 -1
  12. package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +1 -1
  13. package/dist/src/command-line/nx-cloud/connect/view-logs.js +2 -0
  14. package/dist/src/command-line/release/utils/remote-release-clients/github.js +1 -1
  15. package/dist/src/command-line/release/utils/remote-release-clients/gitlab.js +1 -1
  16. package/dist/src/command-line/show/show-target/inputs.js +50 -153
  17. package/dist/src/command-line/show/show-target/outputs.js +48 -173
  18. package/dist/src/command-line/show/show-target/utils.d.ts +28 -0
  19. package/dist/src/command-line/show/show-target/utils.js +83 -3
  20. package/dist/src/command-line/yargs-utils/shared-options.d.ts +1 -1
  21. package/dist/src/config/nx-json.d.ts +4 -2
  22. package/dist/src/core/graph/main.js +1 -1
  23. package/dist/src/daemon/server/handle-tasks-execution-hooks.d.ts +1 -1
  24. package/dist/src/daemon/server/server.js +7 -4
  25. package/dist/src/devkit-internals.d.ts +1 -0
  26. package/dist/src/devkit-internals.js +5 -2
  27. package/dist/src/hasher/check-task-files.d.ts +86 -0
  28. package/dist/src/hasher/check-task-files.js +378 -0
  29. package/dist/src/native/index.d.ts +27 -4
  30. package/dist/src/native/native-bindings.js +2 -0
  31. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  32. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  33. package/dist/src/plugins/js/lock-file/utils/pnpm-normalizer.js +3 -0
  34. package/dist/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +12 -4
  35. package/dist/src/project-graph/build-project-graph.js +7 -1
  36. package/dist/src/project-graph/plugins/loaded-nx-plugin.js +1 -0
  37. package/dist/src/project-graph/project-graph.js +3 -0
  38. package/dist/src/project-graph/utils/project-configuration/name-substitution-manager.d.ts +1 -0
  39. package/dist/src/project-graph/utils/project-configuration/name-substitution-manager.js +16 -2
  40. package/dist/src/project-graph/utils/project-configuration/project-nodes-manager.d.ts +5 -8
  41. package/dist/src/project-graph/utils/project-configuration/project-nodes-manager.js +11 -14
  42. package/dist/src/project-graph/utils/project-configuration/source-maps.d.ts +12 -5
  43. package/dist/src/project-graph/utils/project-configuration/source-maps.js +21 -7
  44. package/dist/src/project-graph/utils/project-configuration/target-defaults.d.ts +1 -1
  45. package/dist/src/project-graph/utils/project-configuration/target-defaults.js +26 -27
  46. package/dist/src/project-graph/utils/project-configuration/target-merging.js +50 -8
  47. package/dist/src/project-graph/utils/project-configuration/target-normalization.js +16 -3
  48. package/dist/src/project-graph/utils/project-configuration/utils.d.ts +15 -0
  49. package/dist/src/project-graph/utils/project-configuration/utils.js +42 -6
  50. package/dist/src/project-graph/utils/project-configuration-utils.d.ts +15 -12
  51. package/dist/src/project-graph/utils/project-configuration-utils.js +79 -99
  52. package/dist/src/tasks-runner/life-cycle.d.ts +2 -2
  53. package/dist/src/tasks-runner/life-cycle.js +2 -2
  54. package/dist/src/tasks-runner/pseudo-terminal.d.ts +1 -1
  55. package/dist/src/tasks-runner/pseudo-terminal.js +2 -2
  56. package/dist/src/tasks-runner/task-env.d.ts +9 -0
  57. package/dist/src/tasks-runner/task-env.js +26 -2
  58. package/dist/src/tasks-runner/task-orchestrator.d.ts +4 -1
  59. package/dist/src/tasks-runner/task-orchestrator.js +25 -12
  60. package/dist/src/utils/acknowledge-build-scripts.js +7 -5
  61. package/dist/src/utils/analytics-prompt.d.ts +0 -6
  62. package/dist/src/utils/analytics-prompt.js +0 -51
  63. package/dist/src/utils/catalog/bun-manager-utils.d.ts +8 -0
  64. package/dist/src/utils/catalog/bun-manager-utils.js +174 -0
  65. package/dist/src/utils/catalog/bun-manager.d.ts +28 -0
  66. package/dist/src/utils/catalog/bun-manager.js +130 -0
  67. package/dist/src/utils/catalog/index.d.ts +1 -1
  68. package/dist/src/utils/catalog/index.js +1 -1
  69. package/dist/src/utils/catalog/manager-factory.js +3 -0
  70. package/dist/src/utils/catalog/manager-utils.d.ts +8 -1
  71. package/dist/src/utils/catalog/manager-utils.js +9 -4
  72. package/dist/src/utils/catalog/manager.d.ts +13 -1
  73. package/dist/src/utils/catalog/manager.js +30 -0
  74. package/dist/src/utils/catalog/pnpm-manager.d.ts +2 -1
  75. package/dist/src/utils/catalog/pnpm-manager.js +3 -0
  76. package/dist/src/utils/catalog/types.d.ts +4 -0
  77. package/dist/src/utils/catalog/yarn-manager.d.ts +6 -2
  78. package/dist/src/utils/catalog/yarn-manager.js +23 -32
  79. package/dist/src/utils/git-utils.d.ts +15 -0
  80. package/dist/src/utils/git-utils.js +64 -6
  81. package/dist/src/utils/package-manager.d.ts +3 -1
  82. package/dist/src/utils/package-manager.js +22 -2
  83. package/dist/src/utils/workspace-id.d.ts +20 -0
  84. package/dist/src/utils/workspace-id.js +54 -0
  85. package/package.json +20 -15
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readBunCatalogDefinitions = readBunCatalogDefinitions;
4
+ exports.updateBunCatalogVersionsInFile = updateBunCatalogVersionsInFile;
5
+ const jsonc_parser_1 = require("jsonc-parser");
6
+ const node_fs_1 = require("node:fs");
7
+ const node_path_1 = require("node:path");
8
+ const fileutils_1 = require("../fileutils");
9
+ const json_1 = require("../json");
10
+ const output_1 = require("../output");
11
+ // Extracts catalog definitions from a parsed bun package.json, normalizing the
12
+ // top-level and `workspaces`-nested locations into a single CatalogDefinitions.
13
+ // Bun treats the locations as all-or-nothing: when either catalog field exists
14
+ // under `workspaces`, the top-level fields are ignored entirely rather than
15
+ // merged.
16
+ function normalizeBunCatalogDefinitions(packageJson) {
17
+ const nested = packageJson.workspaces && !Array.isArray(packageJson.workspaces)
18
+ ? packageJson.workspaces
19
+ : undefined;
20
+ const source = nested?.catalog !== undefined || nested?.catalogs !== undefined
21
+ ? nested
22
+ : packageJson;
23
+ const { catalog, catalogs } = source;
24
+ if (!catalog && !catalogs) {
25
+ return null;
26
+ }
27
+ return { catalog, catalogs };
28
+ }
29
+ function readBunCatalogConfigFromFs(filename, fullPath) {
30
+ try {
31
+ return normalizeBunCatalogDefinitions((0, fileutils_1.readJsonFile)(fullPath));
32
+ }
33
+ catch (error) {
34
+ output_1.output.warn({
35
+ title: `Unable to parse ${filename}`,
36
+ bodyLines: [error.toString()],
37
+ });
38
+ return null;
39
+ }
40
+ }
41
+ function readBunCatalogConfigFromTree(filename, tree) {
42
+ const content = tree.read(filename, 'utf-8');
43
+ try {
44
+ return normalizeBunCatalogDefinitions((0, json_1.parseJson)(content));
45
+ }
46
+ catch (error) {
47
+ output_1.output.warn({
48
+ title: `Unable to parse ${filename}`,
49
+ bodyLines: [error.toString()],
50
+ });
51
+ return null;
52
+ }
53
+ }
54
+ // Mirror of readCatalogDefinitions for bun's package.json-based catalogs: the
55
+ // fs (string-root) branch is cached per pass, the Tree branch stays live.
56
+ function readBunCatalogDefinitions(filename, treeOrRoot, cache) {
57
+ if (typeof treeOrRoot === 'string') {
58
+ if (cache.has(treeOrRoot)) {
59
+ return cache.get(treeOrRoot);
60
+ }
61
+ const configPath = (0, node_path_1.join)(treeOrRoot, filename);
62
+ const defs = (0, node_fs_1.existsSync)(configPath)
63
+ ? readBunCatalogConfigFromFs(filename, configPath)
64
+ : null;
65
+ cache.set(treeOrRoot, defs);
66
+ return defs;
67
+ }
68
+ if (!treeOrRoot.exists(filename)) {
69
+ return null;
70
+ }
71
+ return readBunCatalogConfigFromTree(filename, treeOrRoot);
72
+ }
73
+ function isRecord(value) {
74
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
75
+ }
76
+ // Resolves the jsonc path a catalog update should target. Follows the same
77
+ // all-or-nothing routing as the reader: updates land in the `workspaces`
78
+ // location when it holds a catalog field, otherwise at the top level.
79
+ function resolveBunCatalogTargetPath(packageJson, packageName, catalogName) {
80
+ const nested = packageJson.workspaces && !Array.isArray(packageJson.workspaces)
81
+ ? packageJson.workspaces
82
+ : undefined;
83
+ const nestedIsActive = nested?.catalog !== undefined || nested?.catalogs !== undefined;
84
+ const prefix = nestedIsActive ? ['workspaces'] : [];
85
+ return catalogName
86
+ ? [...prefix, 'catalogs', catalogName, packageName]
87
+ : [...prefix, 'catalog', packageName];
88
+ }
89
+ // jsonc-parser's `modify` creates missing intermediate objects but throws on
90
+ // null (or other non-object) ones — the JSON counterpart of pnpm's empty
91
+ // `catalog:` placeholder. Walk the target path and, at the first non-object
92
+ // step, replace that node wholesale with the remaining path nested as fresh
93
+ // objects.
94
+ function planBunCatalogEdit(packageJson, targetPath, version) {
95
+ let node = packageJson;
96
+ for (let i = 0; i < targetPath.length - 1; i++) {
97
+ if (!isRecord(node)) {
98
+ break;
99
+ }
100
+ const next = node[targetPath[i]];
101
+ if (next !== undefined && !isRecord(next)) {
102
+ const value = targetPath
103
+ .slice(i + 1)
104
+ .reduceRight((acc, key) => ({ [key]: acc }), version);
105
+ return { path: targetPath.slice(0, i + 1), value };
106
+ }
107
+ node = next;
108
+ }
109
+ return { path: targetPath, value: version };
110
+ }
111
+ function updateBunCatalogVersionsInFile(filename, treeOrRoot, updates) {
112
+ let checkExists;
113
+ let readContent;
114
+ let writeContent;
115
+ if (typeof treeOrRoot === 'string') {
116
+ const configPath = (0, node_path_1.join)(treeOrRoot, filename);
117
+ checkExists = () => (0, node_fs_1.existsSync)(configPath);
118
+ readContent = () => (0, node_fs_1.readFileSync)(configPath, 'utf-8');
119
+ writeContent = (content) => (0, node_fs_1.writeFileSync)(configPath, content, 'utf-8');
120
+ }
121
+ else {
122
+ checkExists = () => treeOrRoot.exists(filename);
123
+ readContent = () => treeOrRoot.read(filename, 'utf-8');
124
+ writeContent = (content) => treeOrRoot.write(filename, content);
125
+ }
126
+ if (!checkExists()) {
127
+ output_1.output.warn({
128
+ title: `No ${filename} found`,
129
+ bodyLines: [
130
+ `Cannot update catalog versions without a ${filename} file.`,
131
+ `Create a ${filename} file to use catalogs.`,
132
+ ],
133
+ });
134
+ return;
135
+ }
136
+ try {
137
+ let content = readContent();
138
+ // parseJson surfaces a genuine syntax error here rather than letting a
139
+ // broken file be silently rewritten.
140
+ let packageJson = (0, json_1.parseJson)(content);
141
+ let hasChanges = false;
142
+ for (const update of updates) {
143
+ const { packageName, version, catalogName } = update;
144
+ const targetPath = resolveBunCatalogTargetPath(packageJson, packageName, catalogName);
145
+ // `modify` emits an edit even for an identical value, so check first to
146
+ // keep an already-matching file untouched.
147
+ const currentValue = targetPath.reduce((node, key) => (isRecord(node) ? node[key] : undefined), packageJson);
148
+ if (currentValue === version) {
149
+ continue;
150
+ }
151
+ const { path, value } = planBunCatalogEdit(packageJson, targetPath, version);
152
+ const edits = (0, jsonc_parser_1.modify)(content, path, value, {
153
+ formattingOptions: { insertSpaces: true, tabSize: 2 },
154
+ });
155
+ if (edits.length > 0) {
156
+ content = (0, jsonc_parser_1.applyEdits)(content, edits);
157
+ // Re-parse so the next update routes against the just-applied edit
158
+ // (e.g. a null `catalog` placeholder replaced with a fresh map).
159
+ packageJson = (0, json_1.parseJson)(content);
160
+ hasChanges = true;
161
+ }
162
+ }
163
+ if (hasChanges) {
164
+ writeContent(content);
165
+ }
166
+ }
167
+ catch (error) {
168
+ output_1.output.error({
169
+ title: 'Failed to update catalog versions',
170
+ bodyLines: [error instanceof Error ? error.message : String(error)],
171
+ });
172
+ throw error;
173
+ }
174
+ }
@@ -0,0 +1,28 @@
1
+ import type { Tree } from '../../generators/tree';
2
+ import { type CatalogManager } from './manager';
3
+ import type { CatalogDefinitions, CatalogReference, CatalogReferenceMatch } from './types';
4
+ /**
5
+ * Bun-specific catalog manager implementation.
6
+ *
7
+ * Bun declares catalogs in the root package.json `catalog`/`catalogs` fields,
8
+ * either at the top level or nested under the object form of `workspaces`.
9
+ * Unlike pnpm, the name "default" is not special: `catalog:` resolves only
10
+ * against `catalog`, and `catalog:default` against `catalogs.default`.
11
+ */
12
+ export declare class BunCatalogManager implements CatalogManager {
13
+ readonly name = "bun";
14
+ readonly catalogProtocol = "catalog:";
15
+ private definitionsByRoot;
16
+ isCatalogReference(version: string): boolean;
17
+ parseCatalogReference(version: string): CatalogReference | null;
18
+ getCatalogDefinitionFilePaths(): string[];
19
+ getCatalogDefinitions(treeOrRoot: Tree | string): CatalogDefinitions | null;
20
+ resolveCatalogReference(treeOrRoot: Tree | string, packageName: string, version: string): string | null;
21
+ getCatalogReferencesForPackage(treeOrRoot: Tree | string, packageName: string): CatalogReferenceMatch[];
22
+ validateCatalogReference(treeOrRoot: Tree | string, packageName: string, version: string): void;
23
+ updateCatalogVersions(treeOrRoot: Tree | string, updates: Array<{
24
+ packageName: string;
25
+ version: string;
26
+ catalogName?: string;
27
+ }>): void;
28
+ }
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BunCatalogManager = void 0;
4
+ const manager_1 = require("./manager");
5
+ const bun_manager_utils_1 = require("./bun-manager-utils");
6
+ const BUN_CATALOG_FILENAME = 'package.json';
7
+ /**
8
+ * Bun-specific catalog manager implementation.
9
+ *
10
+ * Bun declares catalogs in the root package.json `catalog`/`catalogs` fields,
11
+ * either at the top level or nested under the object form of `workspaces`.
12
+ * Unlike pnpm, the name "default" is not special: `catalog:` resolves only
13
+ * against `catalog`, and `catalog:default` against `catalogs.default`.
14
+ */
15
+ class BunCatalogManager {
16
+ constructor() {
17
+ this.name = 'bun';
18
+ this.catalogProtocol = 'catalog:';
19
+ // Parsed fs-root definitions, cached per pass. See readBunCatalogDefinitions.
20
+ this.definitionsByRoot = new Map();
21
+ }
22
+ isCatalogReference(version) {
23
+ return version.startsWith(this.catalogProtocol);
24
+ }
25
+ parseCatalogReference(version) {
26
+ if (!this.isCatalogReference(version)) {
27
+ return null;
28
+ }
29
+ const catalogName = version.substring(this.catalogProtocol.length).trim();
30
+ // Only an empty/whitespace name selects the default catalog; "default" is
31
+ // a regular named catalog in bun.
32
+ const isDefault = !catalogName;
33
+ return {
34
+ catalogName: isDefault ? undefined : catalogName,
35
+ isDefaultCatalog: isDefault,
36
+ };
37
+ }
38
+ getCatalogDefinitionFilePaths() {
39
+ return [BUN_CATALOG_FILENAME];
40
+ }
41
+ getCatalogDefinitions(treeOrRoot) {
42
+ return (0, bun_manager_utils_1.readBunCatalogDefinitions)(BUN_CATALOG_FILENAME, treeOrRoot, this.definitionsByRoot);
43
+ }
44
+ resolveCatalogReference(treeOrRoot, packageName, version) {
45
+ const catalogRef = this.parseCatalogReference(version);
46
+ if (!catalogRef) {
47
+ return null;
48
+ }
49
+ const catalogDefs = this.getCatalogDefinitions(treeOrRoot);
50
+ if (!catalogDefs) {
51
+ return null;
52
+ }
53
+ let catalogToUse;
54
+ if (catalogRef.isDefaultCatalog) {
55
+ catalogToUse = catalogDefs.catalog;
56
+ }
57
+ else if (catalogRef.catalogName) {
58
+ catalogToUse = catalogDefs.catalogs?.[catalogRef.catalogName];
59
+ }
60
+ return catalogToUse?.[packageName] || null;
61
+ }
62
+ getCatalogReferencesForPackage(treeOrRoot, packageName) {
63
+ return (0, manager_1.collectCatalogReferencesForPackage)(this, treeOrRoot, packageName);
64
+ }
65
+ validateCatalogReference(treeOrRoot, packageName, version) {
66
+ const catalogRef = this.parseCatalogReference(version);
67
+ if (!catalogRef) {
68
+ throw new Error(`Invalid catalog reference syntax: "${version}". Expected format: "catalog:" or "catalog:name"`);
69
+ }
70
+ const catalogDefs = this.getCatalogDefinitions(treeOrRoot);
71
+ if (!catalogDefs) {
72
+ throw new Error((0, manager_1.formatCatalogError)(`Cannot get Bun catalog definitions. No catalog defined in ${BUN_CATALOG_FILENAME}.`, [
73
+ `Add a "catalog" or "catalogs" field to ${BUN_CATALOG_FILENAME} in your workspace root`,
74
+ ]));
75
+ }
76
+ let catalogToUse;
77
+ if (catalogRef.isDefaultCatalog) {
78
+ catalogToUse = catalogDefs.catalog;
79
+ if (!catalogToUse) {
80
+ const availableCatalogs = Object.keys(catalogDefs.catalogs || {});
81
+ const suggestions = [
82
+ `Define a default catalog in ${BUN_CATALOG_FILENAME} under the "catalog" key`,
83
+ ];
84
+ if (availableCatalogs.length > 0) {
85
+ suggestions.push(`Or select from the available named catalogs: ${availableCatalogs
86
+ .map((c) => `"catalog:${c}"`)
87
+ .join(', ')}`);
88
+ }
89
+ throw new Error((0, manager_1.formatCatalogError)(`No default catalog defined in ${BUN_CATALOG_FILENAME}`, suggestions));
90
+ }
91
+ }
92
+ else if (catalogRef.catalogName) {
93
+ catalogToUse = catalogDefs.catalogs?.[catalogRef.catalogName];
94
+ if (!catalogToUse) {
95
+ const availableCatalogs = Object.keys(catalogDefs.catalogs || {});
96
+ const suggestions = [
97
+ `Define the catalog in ${BUN_CATALOG_FILENAME} under the "catalogs" key`,
98
+ ];
99
+ if (availableCatalogs.length > 0) {
100
+ suggestions.push(`Or select from the available named catalogs: ${availableCatalogs
101
+ .map((c) => `"catalog:${c}"`)
102
+ .join(', ')}`);
103
+ }
104
+ if (catalogDefs.catalog) {
105
+ suggestions.push(`Or use the default catalog ("catalog:")`);
106
+ }
107
+ throw new Error((0, manager_1.formatCatalogError)(`Catalog "${catalogRef.catalogName}" not found in ${BUN_CATALOG_FILENAME}`, suggestions));
108
+ }
109
+ }
110
+ if (!catalogToUse[packageName]) {
111
+ const catalogName = catalogRef.isDefaultCatalog
112
+ ? 'default catalog ("catalog")'
113
+ : `catalog '${catalogRef.catalogName}'`;
114
+ const availablePackages = Object.keys(catalogToUse);
115
+ const suggestions = [
116
+ `Add "${packageName}" to ${catalogName} in ${BUN_CATALOG_FILENAME}`,
117
+ ];
118
+ if (availablePackages.length > 0) {
119
+ suggestions.push(`Or select from the available packages in ${catalogName}: ${availablePackages
120
+ .map((p) => `"${p}"`)
121
+ .join(', ')}`);
122
+ }
123
+ throw new Error((0, manager_1.formatCatalogError)(`Package "${packageName}" not found in ${catalogName}`, suggestions));
124
+ }
125
+ }
126
+ updateCatalogVersions(treeOrRoot, updates) {
127
+ (0, bun_manager_utils_1.updateBunCatalogVersionsInFile)(BUN_CATALOG_FILENAME, treeOrRoot, updates);
128
+ }
129
+ }
130
+ exports.BunCatalogManager = BunCatalogManager;
@@ -4,7 +4,7 @@ import type { CatalogManager } from './manager';
4
4
  import { getCatalogManager } from './manager-factory';
5
5
  export { type CatalogManager, getCatalogManager };
6
6
  /**
7
- * Dereferences a pnpm/yarn catalog reference to a concrete version spec. Returns
7
+ * Dereferences a pnpm/yarn/bun catalog reference to a concrete version spec. Returns
8
8
  * the input unchanged when it is not a catalog reference (or no catalog manager
9
9
  * applies). Throws when the reference cannot be resolved.
10
10
  */
@@ -9,7 +9,7 @@ const workspace_root_1 = require("../workspace-root");
9
9
  const manager_factory_1 = require("./manager-factory");
10
10
  Object.defineProperty(exports, "getCatalogManager", { enumerable: true, get: function () { return manager_factory_1.getCatalogManager; } });
11
11
  /**
12
- * Dereferences a pnpm/yarn catalog reference to a concrete version spec. Returns
12
+ * Dereferences a pnpm/yarn/bun catalog reference to a concrete version spec. Returns
13
13
  * the input unchanged when it is not a catalog reference (or no catalog manager
14
14
  * applies). Throws when the reference cannot be resolved.
15
15
  */
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getCatalogManager = getCatalogManager;
4
4
  const package_manager_1 = require("../package-manager");
5
+ const bun_manager_1 = require("./bun-manager");
5
6
  const pnpm_manager_1 = require("./pnpm-manager");
6
7
  const yarn_manager_1 = require("./yarn-manager");
7
8
  /**
@@ -14,6 +15,8 @@ function getCatalogManager(workspaceRoot) {
14
15
  return new pnpm_manager_1.PnpmCatalogManager();
15
16
  case 'yarn':
16
17
  return new yarn_manager_1.YarnCatalogManager();
18
+ case 'bun':
19
+ return new bun_manager_1.BunCatalogManager();
17
20
  default:
18
21
  return null;
19
22
  }
@@ -5,4 +5,11 @@ export declare function updateCatalogVersionsInFile(filename: string, treeOrRoot
5
5
  packageName: string;
6
6
  version: string;
7
7
  catalogName?: string;
8
- }>): void;
8
+ }>, options?: {
9
+ /**
10
+ * Treat "default" as an alias for the `catalog` field and route default
11
+ * updates through a populated `catalogs.default` (pnpm semantics). When
12
+ * false, "default" is an ordinary named catalog (yarn semantics).
13
+ */
14
+ aliasDefaultCatalog?: boolean;
15
+ }): void;
@@ -136,7 +136,8 @@ function readCatalogDefinitions(filename, treeOrRoot, cache) {
136
136
  }
137
137
  return readCatalogConfigFromTree(filename, treeOrRoot);
138
138
  }
139
- function updateCatalogVersionsInFile(filename, treeOrRoot, updates) {
139
+ function updateCatalogVersionsInFile(filename, treeOrRoot, updates, options) {
140
+ const aliasDefaultCatalog = options?.aliasDefaultCatalog ?? true;
140
141
  let checkExists;
141
142
  let readYaml;
142
143
  let writeYaml;
@@ -194,13 +195,17 @@ function updateCatalogVersionsInFile(filename, treeOrRoot, updates) {
194
195
  let hasChanges = false;
195
196
  for (const update of updates) {
196
197
  const { packageName, version, catalogName } = update;
197
- const normalizedCatalogName = catalogName === 'default' ? undefined : catalogName;
198
+ const normalizedCatalogName = aliasDefaultCatalog && catalogName === 'default'
199
+ ? undefined
200
+ : catalogName;
198
201
  let targetPath;
199
202
  if (!normalizedCatalogName) {
200
203
  // An empty `catalog:` placeholder must not claim the default route
201
204
  // when `catalogs.default` is populated; that would create a
202
- // duplicate-default config rejected by pnpm.
203
- if (isMapAt(doc, ['catalog'])) {
205
+ // duplicate-default config rejected by pnpm. Without the alias,
206
+ // "default" is an ordinary named catalog and the default route is
207
+ // always the `catalog` field.
208
+ if (!aliasDefaultCatalog || isMapAt(doc, ['catalog'])) {
204
209
  targetPath = ['catalog', packageName];
205
210
  }
206
211
  else if (existsAt(doc, ['catalogs', 'default'])) {
@@ -1,6 +1,12 @@
1
1
  import type { Tree } from '../../generators/tree';
2
- import type { CatalogDefinitions, CatalogReference } from './types';
2
+ import type { CatalogDefinitions, CatalogReference, CatalogReferenceMatch } from './types';
3
3
  export declare function formatCatalogError(error: string, suggestions: string[]): string;
4
+ /**
5
+ * Shared implementation of getCatalogReferencesForPackage: enumerates the
6
+ * default and named catalog references and keeps those the manager resolves,
7
+ * so per-manager default-catalog semantics apply without duplication.
8
+ */
9
+ export declare function collectCatalogReferencesForPackage(manager: CatalogManager, treeOrRoot: Tree | string, packageName: string): CatalogReferenceMatch[];
4
10
  /**
5
11
  * Interface for catalog managers that handle package manager-specific catalog implementations.
6
12
  */
@@ -19,6 +25,12 @@ export interface CatalogManager {
19
25
  */
20
26
  resolveCatalogReference(workspaceRoot: string, packageName: string, version: string): string | null;
21
27
  resolveCatalogReference(tree: Tree, packageName: string, version: string): string | null;
28
+ /**
29
+ * Get every catalog reference that resolves to a version for a package,
30
+ * following the package manager's own default-catalog semantics.
31
+ */
32
+ getCatalogReferencesForPackage(workspaceRoot: string, packageName: string): CatalogReferenceMatch[];
33
+ getCatalogReferencesForPackage(tree: Tree, packageName: string): CatalogReferenceMatch[];
22
34
  /**
23
35
  * Check that a catalog reference is valid.
24
36
  */
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.formatCatalogError = formatCatalogError;
4
+ exports.collectCatalogReferencesForPackage = collectCatalogReferencesForPackage;
4
5
  function formatCatalogError(error, suggestions) {
5
6
  let message = error;
6
7
  if (suggestions.length > 0) {
@@ -11,3 +12,32 @@ function formatCatalogError(error, suggestions) {
11
12
  }
12
13
  return message;
13
14
  }
15
+ /**
16
+ * Shared implementation of getCatalogReferencesForPackage: enumerates the
17
+ * default and named catalog references and keeps those the manager resolves,
18
+ * so per-manager default-catalog semantics apply without duplication.
19
+ */
20
+ function collectCatalogReferencesForPackage(manager, treeOrRoot, packageName) {
21
+ // The overload pairs don't accept the Tree | string union directly.
22
+ const source = treeOrRoot;
23
+ const catalogDefs = manager.getCatalogDefinitions(source);
24
+ if (!catalogDefs) {
25
+ return [];
26
+ }
27
+ const catalogRefs = ['catalog:'];
28
+ for (const name of Object.keys(catalogDefs.catalogs ?? {})) {
29
+ // Skip names the manager treats as the default catalog (e.g. pnpm's
30
+ // "default") — already covered by the `catalog:` candidate.
31
+ if (!manager.parseCatalogReference(`catalog:${name}`)?.isDefaultCatalog) {
32
+ catalogRefs.push(`catalog:${name}`);
33
+ }
34
+ }
35
+ const matches = [];
36
+ for (const catalogRef of catalogRefs) {
37
+ const versionSpec = manager.resolveCatalogReference(source, packageName, catalogRef);
38
+ if (versionSpec) {
39
+ matches.push({ catalogRef, versionSpec });
40
+ }
41
+ }
42
+ return matches;
43
+ }
@@ -1,6 +1,6 @@
1
1
  import type { Tree } from '../../generators/tree';
2
2
  import { type CatalogManager } from './manager';
3
- import type { CatalogDefinitions, CatalogReference } from './types';
3
+ import type { CatalogDefinitions, CatalogReference, CatalogReferenceMatch } from './types';
4
4
  /**
5
5
  * PNPM-specific catalog manager implementation
6
6
  */
@@ -13,6 +13,7 @@ export declare class PnpmCatalogManager implements CatalogManager {
13
13
  getCatalogDefinitionFilePaths(): string[];
14
14
  getCatalogDefinitions(treeOrRoot: Tree | string): CatalogDefinitions | null;
15
15
  resolveCatalogReference(treeOrRoot: Tree | string, packageName: string, version: string): string | null;
16
+ getCatalogReferencesForPackage(treeOrRoot: Tree | string, packageName: string): CatalogReferenceMatch[];
16
17
  validateCatalogReference(treeOrRoot: Tree | string, packageName: string, version: string): void;
17
18
  updateCatalogVersions(treeOrRoot: Tree | string, updates: Array<{
18
19
  packageName: string;
@@ -54,6 +54,9 @@ class PnpmCatalogManager {
54
54
  }
55
55
  return catalogToUse?.[packageName] || null;
56
56
  }
57
+ getCatalogReferencesForPackage(treeOrRoot, packageName) {
58
+ return (0, manager_1.collectCatalogReferencesForPackage)(this, treeOrRoot, packageName);
59
+ }
57
60
  validateCatalogReference(treeOrRoot, packageName, version) {
58
61
  const catalogRef = this.parseCatalogReference(version);
59
62
  if (!catalogRef) {
@@ -2,6 +2,10 @@ export interface CatalogReference {
2
2
  catalogName?: string;
3
3
  isDefaultCatalog: boolean;
4
4
  }
5
+ export interface CatalogReferenceMatch {
6
+ catalogRef: string;
7
+ versionSpec: string;
8
+ }
5
9
  export interface CatalogEntry {
6
10
  [packageName: string]: string;
7
11
  }
@@ -1,8 +1,11 @@
1
1
  import type { Tree } from '../../generators/tree';
2
2
  import { type CatalogManager } from './manager';
3
- import type { CatalogDefinitions, CatalogReference } from './types';
3
+ import type { CatalogDefinitions, CatalogReference, CatalogReferenceMatch } from './types';
4
4
  /**
5
- * Yarn Berry (v4+) catalog manager implementation
5
+ * Yarn Berry (v4.10+) catalog manager implementation.
6
+ *
7
+ * Unlike pnpm, the name "default" is not special: `catalog:` resolves only
8
+ * against `catalog`, and `catalog:default` against `catalogs.default`.
6
9
  */
7
10
  export declare class YarnCatalogManager implements CatalogManager {
8
11
  readonly name = "yarn";
@@ -13,6 +16,7 @@ export declare class YarnCatalogManager implements CatalogManager {
13
16
  getCatalogDefinitionFilePaths(): string[];
14
17
  getCatalogDefinitions(treeOrRoot: Tree | string): CatalogDefinitions | null;
15
18
  resolveCatalogReference(treeOrRoot: Tree | string, packageName: string, version: string): string | null;
19
+ getCatalogReferencesForPackage(treeOrRoot: Tree | string, packageName: string): CatalogReferenceMatch[];
16
20
  validateCatalogReference(treeOrRoot: Tree | string, packageName: string, version: string): void;
17
21
  updateCatalogVersions(treeOrRoot: Tree | string, updates: Array<{
18
22
  packageName: string;
@@ -5,7 +5,10 @@ const manager_1 = require("./manager");
5
5
  const manager_utils_1 = require("./manager-utils");
6
6
  const YARNRC_FILENAME = '.yarnrc.yml';
7
7
  /**
8
- * Yarn Berry (v4+) catalog manager implementation
8
+ * Yarn Berry (v4.10+) catalog manager implementation.
9
+ *
10
+ * Unlike pnpm, the name "default" is not special: `catalog:` resolves only
11
+ * against `catalog`, and `catalog:default` against `catalogs.default`.
9
12
  */
10
13
  class YarnCatalogManager {
11
14
  constructor() {
@@ -22,8 +25,9 @@ class YarnCatalogManager {
22
25
  return null;
23
26
  }
24
27
  const catalogName = version.substring(this.catalogProtocol.length);
25
- // Normalize both "catalog:" and "catalog:default" to the same representation
26
- const isDefault = !catalogName || catalogName === 'default';
28
+ // Only an empty name selects the default catalog; unlike pnpm, "default"
29
+ // is a regular named catalog in yarn.
30
+ const isDefault = !catalogName;
27
31
  return {
28
32
  catalogName: isDefault ? undefined : catalogName,
29
33
  isDefaultCatalog: isDefault,
@@ -46,14 +50,16 @@ class YarnCatalogManager {
46
50
  }
47
51
  let catalogToUse;
48
52
  if (catalogRef.isDefaultCatalog) {
49
- // Check both locations for default catalog
50
- catalogToUse = catalogDefs.catalog ?? catalogDefs.catalogs?.default;
53
+ catalogToUse = catalogDefs.catalog;
51
54
  }
52
55
  else if (catalogRef.catalogName) {
53
56
  catalogToUse = catalogDefs.catalogs?.[catalogRef.catalogName];
54
57
  }
55
58
  return catalogToUse?.[packageName] || null;
56
59
  }
60
+ getCatalogReferencesForPackage(treeOrRoot, packageName) {
61
+ return (0, manager_1.collectCatalogReferencesForPackage)(this, treeOrRoot, packageName);
62
+ }
57
63
  validateCatalogReference(treeOrRoot, packageName, version) {
58
64
  const catalogRef = this.parseCatalogReference(version);
59
65
  if (!catalogRef) {
@@ -65,13 +71,9 @@ class YarnCatalogManager {
65
71
  }
66
72
  let catalogToUse;
67
73
  if (catalogRef.isDefaultCatalog) {
68
- const hasCatalog = !!catalogDefs.catalog;
69
- const hasCatalogsDefault = !!catalogDefs.catalogs?.default;
70
- // Error if both defined
71
- if (hasCatalog && hasCatalogsDefault) {
72
- throw new Error("The 'default' catalog was defined multiple times. Use the 'catalog' field or 'catalogs.default', but not both.");
73
- }
74
- catalogToUse = catalogDefs.catalog ?? catalogDefs.catalogs?.default;
74
+ // Yarn's default catalog is only the `catalog` field; unlike pnpm,
75
+ // `catalogs.default` does not act as a fallback.
76
+ catalogToUse = catalogDefs.catalog;
75
77
  if (!catalogToUse) {
76
78
  const availableCatalogs = Object.keys(catalogDefs.catalogs || {});
77
79
  const suggestions = [
@@ -88,12 +90,7 @@ class YarnCatalogManager {
88
90
  else if (catalogRef.catalogName) {
89
91
  catalogToUse = catalogDefs.catalogs?.[catalogRef.catalogName];
90
92
  if (!catalogToUse) {
91
- const availableCatalogs = Object.keys(catalogDefs.catalogs || {}).filter((c) => c !== 'default');
92
- const defaultCatalog = !!catalogDefs.catalog
93
- ? 'catalog'
94
- : !catalogDefs.catalogs?.default
95
- ? 'catalogs.default'
96
- : null;
93
+ const availableCatalogs = Object.keys(catalogDefs.catalogs || {});
97
94
  const suggestions = [
98
95
  `Define the catalog in ${YARNRC_FILENAME} under the "catalogs" key`,
99
96
  ];
@@ -102,24 +99,16 @@ class YarnCatalogManager {
102
99
  .map((c) => `"catalog:${c}"`)
103
100
  .join(', ')}`);
104
101
  }
105
- if (defaultCatalog) {
106
- suggestions.push(`Or use the default catalog ("${defaultCatalog}")`);
102
+ if (catalogDefs.catalog) {
103
+ suggestions.push(`Or use the default catalog ("catalog:")`);
107
104
  }
108
105
  throw new Error((0, manager_1.formatCatalogError)(`Catalog "${catalogRef.catalogName}" not found in ${YARNRC_FILENAME}`, suggestions));
109
106
  }
110
107
  }
111
108
  if (!catalogToUse[packageName]) {
112
- let catalogName;
113
- if (catalogRef.isDefaultCatalog) {
114
- // Context-aware messaging based on which location exists
115
- const hasCatalog = !!catalogDefs.catalog;
116
- catalogName = hasCatalog
117
- ? 'default catalog ("catalog")'
118
- : 'default catalog ("catalogs.default")';
119
- }
120
- else {
121
- catalogName = `catalog '${catalogRef.catalogName}'`;
122
- }
109
+ const catalogName = catalogRef.isDefaultCatalog
110
+ ? 'default catalog ("catalog")'
111
+ : `catalog '${catalogRef.catalogName}'`;
123
112
  const availablePackages = Object.keys(catalogToUse);
124
113
  const suggestions = [
125
114
  `Add "${packageName}" to ${catalogName} in ${YARNRC_FILENAME}`,
@@ -133,7 +122,9 @@ class YarnCatalogManager {
133
122
  }
134
123
  }
135
124
  updateCatalogVersions(treeOrRoot, updates) {
136
- (0, manager_utils_1.updateCatalogVersionsInFile)(YARNRC_FILENAME, treeOrRoot, updates);
125
+ (0, manager_utils_1.updateCatalogVersionsInFile)(YARNRC_FILENAME, treeOrRoot, updates, {
126
+ aliasDefaultCatalog: false,
127
+ });
137
128
  }
138
129
  }
139
130
  exports.YarnCatalogManager = YarnCatalogManager;