nx 19.1.0-beta.0 → 19.1.0-beta.2

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 (34) hide show
  1. package/.eslintrc.json +2 -1
  2. package/bin/init-local.js +1 -1
  3. package/package.json +18 -15
  4. package/schemas/nx-schema.json +1 -1
  5. package/src/adapter/ngcli-adapter.js +6 -3
  6. package/src/command-line/format/format.js +47 -25
  7. package/src/command-line/init/implementation/angular/legacy-angular-versions.js +2 -1
  8. package/src/command-line/init/implementation/angular/standalone-workspace.js +0 -2
  9. package/src/command-line/init/implementation/react/index.js +1 -0
  10. package/src/command-line/migrate/migrate.js +16 -6
  11. package/src/command-line/release/utils/github.js +1 -1
  12. package/src/command-line/release/utils/shared.js +5 -3
  13. package/src/command-line/run/executor-utils.js +5 -0
  14. package/src/config/misc-interfaces.d.ts +2 -1
  15. package/src/config/workspace-json-project-json.d.ts +1 -0
  16. package/src/core/graph/main.js +1 -1
  17. package/src/daemon/server/server.js +1 -1
  18. package/src/generators/tree.d.ts +0 -1
  19. package/src/generators/utils/json.js +2 -1
  20. package/src/plugins/js/index.js +7 -2
  21. package/src/plugins/js/lock-file/lock-file.js +31 -1
  22. package/src/plugins/js/lock-file/npm-parser.js +10 -1
  23. package/src/plugins/js/lock-file/utils/pnpm-normalizer.js +3 -3
  24. package/src/plugins/target-defaults/target-defaults-plugin.d.ts +31 -0
  25. package/src/plugins/target-defaults/target-defaults-plugin.js +9 -0
  26. package/src/utils/ab-testing.js +5 -0
  27. package/src/utils/fileutils.d.ts +0 -1
  28. package/src/utils/find-matching-projects.js +1 -13
  29. package/src/utils/json.js +1 -1
  30. package/src/utils/package-json.d.ts +1 -1
  31. package/src/utils/package-json.js +8 -2
  32. package/src/utils/package-manager.d.ts +3 -3
  33. package/src/utils/package-manager.js +61 -18
  34. package/src/utils/plugins/plugin-capabilities.js +24 -1
@@ -198,7 +198,7 @@ const handleWorkspaceChanges = async (err, changeEvents) => {
198
198
  });
199
199
  return;
200
200
  }
201
- if (err || !changeEvents || !changeEvents.length) {
201
+ if (err) {
202
202
  let error = typeof err === 'string' ? new Error(err) : err;
203
203
  logger_1.serverLogger.watcherLog('Unexpected workspace watcher error', error.message);
204
204
  console.error(error);
@@ -1,5 +1,4 @@
1
1
  /// <reference types="node" />
2
- /// <reference types="@types/node/ts4.8/fs" />
3
2
  /// <reference types="node" />
4
3
  import type { Mode } from 'fs';
5
4
  /**
@@ -30,7 +30,8 @@ exports.readJson = readJson;
30
30
  * @param options Optional JSON Serialize Options
31
31
  */
32
32
  function writeJson(tree, path, value, options) {
33
- tree.write(path, (0, json_1.serializeJson)(value, options));
33
+ const serialized = (0, json_1.serializeJson)(value, options);
34
+ tree.write(path, `${serialized}\n`);
34
35
  }
35
36
  exports.writeJson = writeJson;
36
37
  /**
@@ -14,6 +14,7 @@ const file_hasher_1 = require("../../hasher/file-hasher");
14
14
  const package_manager_1 = require("../../utils/package-manager");
15
15
  const workspace_root_1 = require("../../utils/workspace-root");
16
16
  const versions_1 = require("../../utils/versions");
17
+ const child_process_1 = require("child_process");
17
18
  exports.name = 'nx/js/dependencies-and-lockfile';
18
19
  let parsedLockFile = {};
19
20
  exports.createNodes = [
@@ -30,7 +31,9 @@ exports.createNodes = [
30
31
  return {};
31
32
  }
32
33
  const lockFilePath = (0, path_1.join)(workspace_root_1.workspaceRoot, lockFile);
33
- const lockFileContents = (0, fs_1.readFileSync)(lockFilePath).toString();
34
+ const lockFileContents = packageManager !== 'bun'
35
+ ? (0, fs_1.readFileSync)(lockFilePath).toString()
36
+ : (0, child_process_1.execSync)(`bun ${lockFilePath}`).toString();
34
37
  const lockFileHash = getLockFileHash(lockFileContents);
35
38
  if (!lockFileNeedsReprocessing(lockFileHash)) {
36
39
  const nodes = readCachedParsedLockFile().externalNodes;
@@ -55,7 +58,9 @@ const createDependencies = (_, ctx) => {
55
58
  (0, lock_file_1.lockFileExists)(packageManager) &&
56
59
  parsedLockFile.externalNodes) {
57
60
  const lockFilePath = (0, path_1.join)(workspace_root_1.workspaceRoot, (0, lock_file_1.getLockFileName)(packageManager));
58
- const lockFileContents = (0, fs_1.readFileSync)(lockFilePath).toString();
61
+ const lockFileContents = packageManager !== 'bun'
62
+ ? (0, fs_1.readFileSync)(lockFilePath).toString()
63
+ : (0, child_process_1.execSync)(`bun ${lockFilePath}`).toString();
59
64
  const lockFileHash = getLockFileHash(lockFileContents);
60
65
  if (!lockFileNeedsReprocessing(lockFileHash)) {
61
66
  lockfileDependencies = readCachedParsedLockFile().dependencies ?? [];
@@ -19,10 +19,17 @@ const fileutils_1 = require("../../../utils/fileutils");
19
19
  const YARN_LOCK_FILE = 'yarn.lock';
20
20
  const NPM_LOCK_FILE = 'package-lock.json';
21
21
  const PNPM_LOCK_FILE = 'pnpm-lock.yaml';
22
- exports.LOCKFILES = [YARN_LOCK_FILE, NPM_LOCK_FILE, PNPM_LOCK_FILE];
22
+ const BUN_LOCK_FILE = 'bun.lockb';
23
+ exports.LOCKFILES = [
24
+ YARN_LOCK_FILE,
25
+ NPM_LOCK_FILE,
26
+ PNPM_LOCK_FILE,
27
+ BUN_LOCK_FILE,
28
+ ];
23
29
  const YARN_LOCK_PATH = (0, path_1.join)(workspace_root_1.workspaceRoot, YARN_LOCK_FILE);
24
30
  const NPM_LOCK_PATH = (0, path_1.join)(workspace_root_1.workspaceRoot, NPM_LOCK_FILE);
25
31
  const PNPM_LOCK_PATH = (0, path_1.join)(workspace_root_1.workspaceRoot, PNPM_LOCK_FILE);
32
+ const BUN_LOCK_PATH = (0, path_1.join)(workspace_root_1.workspaceRoot, BUN_LOCK_FILE);
26
33
  /**
27
34
  * Parses lock file and maps dependencies and metadata to {@link LockFileGraph}
28
35
  */
@@ -38,6 +45,11 @@ function getLockFileNodes(packageManager, contents, lockFileHash, context) {
38
45
  if (packageManager === 'npm') {
39
46
  return (0, npm_parser_1.getNpmLockfileNodes)(contents, lockFileHash);
40
47
  }
48
+ if (packageManager === 'bun') {
49
+ // bun uses yarn v1 for the file format
50
+ const packageJson = (0, fileutils_1.readJsonFile)('package.json');
51
+ return (0, yarn_parser_1.getYarnLockfileNodes)(contents, lockFileHash, packageJson);
52
+ }
41
53
  }
42
54
  catch (e) {
43
55
  if (!isPostInstallProcess()) {
@@ -65,6 +77,10 @@ function getLockFileDependencies(packageManager, contents, lockFileHash, context
65
77
  if (packageManager === 'npm') {
66
78
  return (0, npm_parser_1.getNpmLockfileDependencies)(contents, lockFileHash, context);
67
79
  }
80
+ if (packageManager === 'bun') {
81
+ // bun uses yarn v1 for the file format
82
+ return (0, yarn_parser_1.getYarnLockfileDependencies)(contents, lockFileHash, context);
83
+ }
68
84
  }
69
85
  catch (e) {
70
86
  if (!isPostInstallProcess()) {
@@ -88,6 +104,9 @@ function lockFileExists(packageManager) {
88
104
  if (packageManager === 'npm') {
89
105
  return (0, fs_1.existsSync)(NPM_LOCK_PATH);
90
106
  }
107
+ if (packageManager === 'bun') {
108
+ return (0, fs_1.existsSync)(BUN_LOCK_PATH);
109
+ }
91
110
  throw new Error(`Unknown package manager ${packageManager} or lock file missing`);
92
111
  }
93
112
  exports.lockFileExists = lockFileExists;
@@ -106,6 +125,9 @@ function getLockFileName(packageManager) {
106
125
  if (packageManager === 'npm') {
107
126
  return NPM_LOCK_FILE;
108
127
  }
128
+ if (packageManager === 'bun') {
129
+ return BUN_LOCK_FILE;
130
+ }
109
131
  throw new Error(`Unknown package manager: ${packageManager}`);
110
132
  }
111
133
  exports.getLockFileName = getLockFileName;
@@ -119,6 +141,9 @@ function getLockFilePath(packageManager) {
119
141
  if (packageManager === 'npm') {
120
142
  return NPM_LOCK_PATH;
121
143
  }
144
+ if (packageManager === 'bun') {
145
+ return BUN_LOCK_PATH;
146
+ }
122
147
  throw new Error(`Unknown package manager: ${packageManager}`);
123
148
  }
124
149
  /**
@@ -145,6 +170,11 @@ function createLockFile(packageJson, graph, packageManager = (0, package_manager
145
170
  const prunedGraph = (0, project_graph_pruning_1.pruneProjectGraph)(graph, packageJson);
146
171
  return (0, npm_parser_1.stringifyNpmLockfile)(prunedGraph, content, normalizedPackageJson);
147
172
  }
173
+ if (packageManager === 'bun') {
174
+ output_1.output.log({
175
+ title: "Unable to create bun lock files. Run bun install it's just as quick",
176
+ });
177
+ }
148
178
  }
149
179
  catch (e) {
150
180
  if (!isPostInstallProcess()) {
@@ -175,7 +175,16 @@ function findTarget(sourcePath, keyMap, targetName, versionRange) {
175
175
  const searchPath = `${sourcePath}node_modules/${targetName}`;
176
176
  if (keyMap.has(searchPath)) {
177
177
  const child = keyMap.get(searchPath);
178
- if (child.data.version === versionRange ||
178
+ // if the version is alias to another package we need to parse the versions to compare
179
+ if (child.data.version.startsWith('npm:') &&
180
+ versionRange.startsWith('npm:')) {
181
+ const nodeVersion = child.data.version.slice(child.data.version.indexOf('@', 5) + 1);
182
+ const depVersion = versionRange.slice(versionRange.indexOf('@', 5) + 1);
183
+ if (nodeVersion === depVersion || (0, semver_1.satisfies)(nodeVersion, depVersion)) {
184
+ return child;
185
+ }
186
+ }
187
+ else if (child.data.version === versionRange ||
179
188
  (0, semver_1.satisfies)(child.data.version, versionRange)) {
180
189
  return child;
181
190
  }
@@ -16,7 +16,7 @@ function loadPnpmHoistedDepsDefinition() {
16
16
  const fullPath = `${workspace_root_1.workspaceRoot}/node_modules/.modules.yaml`;
17
17
  if ((0, fs_1.existsSync)(fullPath)) {
18
18
  const content = (0, fs_1.readFileSync)(fullPath, 'utf-8');
19
- const { load } = require('@zkochan/js-yaml');
19
+ const { load } = require('js-yaml');
20
20
  return load(content)?.hoistedDependencies ?? {};
21
21
  }
22
22
  else {
@@ -32,7 +32,7 @@ exports.loadPnpmHoistedDepsDefinition = loadPnpmHoistedDepsDefinition;
32
32
  * https://github.com/pnpm/pnpm/blob/af3e5559d377870d4c3d303429b3ed1a4e64fedc/lockfile/lockfile-file/src/read.ts#L91
33
33
  */
34
34
  function parseAndNormalizePnpmLockfile(content) {
35
- const { load } = require('@zkochan/js-yaml');
35
+ const { load } = require('js-yaml');
36
36
  const lockFileData = load(content);
37
37
  return revertFromInlineSpecifiersFormatIfNecessary(convertFromLockfileFileMutable(lockFileData));
38
38
  }
@@ -77,7 +77,7 @@ function stringifyToPnpmYaml(lockfile) {
77
77
  const adaptedLockfile = isLockfileV6
78
78
  ? convertToInlineSpecifiersFormat(lockfile)
79
79
  : lockfile;
80
- const { dump } = require('@zkochan/js-yaml');
80
+ const { dump } = require('js-yaml');
81
81
  return dump(sortLockfileKeys(normalizeLockfile(adaptedLockfile, isLockfileV6)), LOCKFILE_YAML_FORMAT);
82
82
  }
83
83
  exports.stringifyToPnpmYaml = stringifyToPnpmYaml;
@@ -13,6 +13,11 @@ export default TargetDefaultsPlugin;
13
13
  */
14
14
  export declare function getTargetInfo(target: string, projectJsonTargets: Record<string, TargetConfiguration>, packageJsonTargets: Record<string, TargetConfiguration>): {
15
15
  command: string;
16
+ metadata: {
17
+ [x: string]: any;
18
+ description?: string;
19
+ technologies?: string[];
20
+ };
16
21
  executor?: undefined;
17
22
  options?: undefined;
18
23
  } | {
@@ -22,6 +27,11 @@ export declare function getTargetInfo(target: string, projectJsonTargets: Record
22
27
  commands?: undefined;
23
28
  script?: undefined;
24
29
  };
30
+ metadata: {
31
+ [x: string]: any;
32
+ description?: string;
33
+ technologies?: string[];
34
+ };
25
35
  command?: undefined;
26
36
  } | {
27
37
  executor: string;
@@ -30,9 +40,19 @@ export declare function getTargetInfo(target: string, projectJsonTargets: Record
30
40
  command?: undefined;
31
41
  script?: undefined;
32
42
  };
43
+ metadata: {
44
+ [x: string]: any;
45
+ description?: string;
46
+ technologies?: string[];
47
+ };
33
48
  command?: undefined;
34
49
  } | {
35
50
  executor: string;
51
+ metadata: {
52
+ [x: string]: any;
53
+ description?: string;
54
+ technologies?: string[];
55
+ };
36
56
  command?: undefined;
37
57
  options?: undefined;
38
58
  } | {
@@ -42,9 +62,20 @@ export declare function getTargetInfo(target: string, projectJsonTargets: Record
42
62
  command?: undefined;
43
63
  commands?: undefined;
44
64
  };
65
+ metadata: {
66
+ [x: string]: any;
67
+ description?: string;
68
+ technologies?: string[];
69
+ };
45
70
  command?: undefined;
71
+ } | {
72
+ executor: string;
73
+ command?: undefined;
74
+ metadata?: undefined;
75
+ options?: undefined;
46
76
  } | {
47
77
  command?: undefined;
78
+ metadata?: undefined;
48
79
  executor?: undefined;
49
80
  options?: undefined;
50
81
  };
@@ -111,9 +111,14 @@ function getTargetInfo(target, projectJsonTargets, packageJsonTargets) {
111
111
  ...packageJsonTarget?.options,
112
112
  ...projectJsonTarget?.options,
113
113
  };
114
+ const metadata = {
115
+ ...packageJsonTarget?.metadata,
116
+ ...projectJsonTarget?.metadata,
117
+ };
114
118
  if (projectJsonTarget?.command) {
115
119
  return {
116
120
  command: projectJsonTarget?.command,
121
+ metadata,
117
122
  };
118
123
  }
119
124
  if (executor === 'nx:run-commands') {
@@ -123,6 +128,7 @@ function getTargetInfo(target, projectJsonTargets, packageJsonTargets) {
123
128
  options: {
124
129
  command: targetOptions?.command,
125
130
  },
131
+ metadata,
126
132
  };
127
133
  }
128
134
  else if (targetOptions?.commands) {
@@ -131,10 +137,12 @@ function getTargetInfo(target, projectJsonTargets, packageJsonTargets) {
131
137
  options: {
132
138
  commands: targetOptions.commands,
133
139
  },
140
+ metadata,
134
141
  };
135
142
  }
136
143
  return {
137
144
  executor: 'nx:run-commands',
145
+ metadata,
138
146
  };
139
147
  }
140
148
  if (executor === 'nx:run-script') {
@@ -143,6 +151,7 @@ function getTargetInfo(target, projectJsonTargets, packageJsonTargets) {
143
151
  options: {
144
152
  script: targetOptions?.script ?? target,
145
153
  },
154
+ metadata,
146
155
  };
147
156
  }
148
157
  if (executor) {
@@ -90,6 +90,11 @@ async function recordStat(opts) {
90
90
  exports.recordStat = recordStat;
91
91
  function shouldRecordStats() {
92
92
  const pmc = (0, package_manager_1.getPackageManagerCommand)();
93
+ if (!pmc.getRegistryUrl) {
94
+ // Fallback on true as Package management doesn't support reading config for registry.
95
+ // currently Bun doesn't support fetching config settings https://github.com/oven-sh/bun/issues/7140
96
+ return true;
97
+ }
93
98
  try {
94
99
  const stdout = (0, node_child_process_1.execSync)(pmc.getRegistryUrl, { encoding: 'utf-8' });
95
100
  const url = new URL(stdout.trim());
@@ -1,5 +1,4 @@
1
1
  /// <reference types="node" />
2
- /// <reference types="@types/node/ts4.8/fs" />
3
2
  import type { JsonParseOptions, JsonSerializeOptions } from './json';
4
3
  import { PathLike } from 'fs';
5
4
  export interface JsonReadOptions extends JsonParseOptions {
@@ -22,15 +22,6 @@ function findMatchingProjects(patterns = [], projects) {
22
22
  }
23
23
  const projectNames = Object.keys(projects);
24
24
  const matchedProjects = new Set();
25
- // If the first pattern is an exclude pattern,
26
- // we add a wildcard pattern at the first to select
27
- // all projects, except the ones that match the exclude pattern.
28
- // e.g. ['!tag:someTag', 'project2'] will match all projects except
29
- // the ones with the tag 'someTag', and also match the project 'project2',
30
- // regardless of its tags.
31
- if (isExcludePattern(patterns[0])) {
32
- patterns.unshift('*');
33
- }
34
25
  for (const stringPattern of patterns) {
35
26
  if (!stringPattern.length) {
36
27
  continue;
@@ -148,11 +139,8 @@ function addMatchingProjectsByTag(projectNames, projects, pattern, matchedProjec
148
139
  }
149
140
  }
150
141
  }
151
- function isExcludePattern(pattern) {
152
- return pattern.startsWith('!');
153
- }
154
142
  function parseStringPattern(pattern, projects) {
155
- const isExclude = isExcludePattern(pattern);
143
+ const isExclude = pattern.startsWith('!');
156
144
  // Support for things like: `!{type}:value`
157
145
  if (isExclude) {
158
146
  pattern = pattern.substring(1);
package/src/utils/json.js CHANGED
@@ -57,6 +57,6 @@ function formatParseError(input, parseError) {
57
57
  * @returns the formatted JSON representation of the object
58
58
  */
59
59
  function serializeJson(input, options) {
60
- return JSON.stringify(input, null, options?.spaces ?? 2) + '\n';
60
+ return JSON.stringify(input, null, options?.spaces ?? 2);
61
61
  }
62
62
  exports.serializeJson = serializeJson;
@@ -65,7 +65,7 @@ export declare function normalizePackageGroup(packageGroup: PackageGroup): Array
65
65
  export declare function readNxMigrateConfig(json: Partial<PackageJson>): NxMigrationsConfiguration & {
66
66
  packageGroup?: ArrayPackageGroup;
67
67
  };
68
- export declare function buildTargetFromScript(script: string): TargetConfiguration;
68
+ export declare function buildTargetFromScript(script: string, scripts?: Record<string, string>): TargetConfiguration;
69
69
  export declare function readTargetsFromPackageJson(packageJson: PackageJson): Record<string, TargetConfiguration<any>>;
70
70
  /**
71
71
  * Uses `require.resolve` to read the package.json for a module.
@@ -6,6 +6,7 @@ const path_1 = require("path");
6
6
  const project_configuration_utils_1 = require("../project-graph/utils/project-configuration-utils");
7
7
  const fileutils_1 = require("./fileutils");
8
8
  const installation_directory_1 = require("./installation-directory");
9
+ const package_manager_1 = require("./package-manager");
9
10
  function normalizePackageGroup(packageGroup) {
10
11
  return Array.isArray(packageGroup)
11
12
  ? packageGroup.map((x) => typeof x === 'string' ? { package: x, version: '*' } : x)
@@ -38,12 +39,17 @@ function readNxMigrateConfig(json) {
38
39
  };
39
40
  }
40
41
  exports.readNxMigrateConfig = readNxMigrateConfig;
41
- function buildTargetFromScript(script) {
42
+ function buildTargetFromScript(script, scripts = {}) {
43
+ const packageManagerCommand = (0, package_manager_1.getPackageManagerCommand)();
42
44
  return {
43
45
  executor: 'nx:run-script',
44
46
  options: {
45
47
  script,
46
48
  },
49
+ metadata: {
50
+ scriptContent: scripts[script],
51
+ runCommand: packageManagerCommand.run(script),
52
+ },
47
53
  };
48
54
  }
49
55
  exports.buildTargetFromScript = buildTargetFromScript;
@@ -53,7 +59,7 @@ function readTargetsFromPackageJson(packageJson) {
53
59
  const includedScripts = nx?.includedScripts || Object.keys(scripts ?? {});
54
60
  //
55
61
  for (const script of includedScripts) {
56
- res[script] = buildTargetFromScript(script);
62
+ res[script] = buildTargetFromScript(script, scripts);
57
63
  }
58
64
  for (const targetName in nx?.targets) {
59
65
  res[targetName] = (0, project_configuration_utils_1.mergeTargetConfigurations)(nx?.targets[targetName], res[targetName]);
@@ -1,4 +1,4 @@
1
- export type PackageManager = 'yarn' | 'pnpm' | 'npm';
1
+ export type PackageManager = 'yarn' | 'pnpm' | 'npm' | 'bun';
2
2
  export interface PackageManagerCommands {
3
3
  preInstall?: string;
4
4
  install: string;
@@ -10,8 +10,8 @@ export interface PackageManagerCommands {
10
10
  exec: string;
11
11
  dlx: string;
12
12
  list: string;
13
- run: (script: string, args: string) => string;
14
- getRegistryUrl: string;
13
+ run: (script: string, args?: string) => string;
14
+ getRegistryUrl?: string;
15
15
  }
16
16
  /**
17
17
  * Detects which package manager is used in the workspace based on the lock file.
@@ -20,11 +20,13 @@ const execAsync = (0, util_1.promisify)(child_process_1.exec);
20
20
  function detectPackageManager(dir = '') {
21
21
  const nxJson = (0, configuration_1.readNxJson)();
22
22
  return (nxJson.cli?.packageManager ??
23
- ((0, fs_1.existsSync)((0, path_1.join)(dir, 'yarn.lock'))
24
- ? 'yarn'
25
- : (0, fs_1.existsSync)((0, path_1.join)(dir, 'pnpm-lock.yaml'))
26
- ? 'pnpm'
27
- : 'npm'));
23
+ ((0, fs_1.existsSync)((0, path_1.join)(dir, 'bun.lockb'))
24
+ ? 'bun'
25
+ : (0, fs_1.existsSync)((0, path_1.join)(dir, 'yarn.lock'))
26
+ ? 'yarn'
27
+ : (0, fs_1.existsSync)((0, path_1.join)(dir, 'pnpm-lock.yaml'))
28
+ ? 'pnpm'
29
+ : 'npm'));
28
30
  }
29
31
  exports.detectPackageManager = detectPackageManager;
30
32
  /**
@@ -74,7 +76,7 @@ function getPackageManagerCommand(packageManager = detectPackageManager(), root
74
76
  rm: 'yarn remove',
75
77
  exec: 'yarn',
76
78
  dlx: useBerry ? 'yarn dlx' : 'yarn',
77
- run: (script, args) => `yarn ${script} ${args}`,
79
+ run: (script, args) => `yarn ${script}${args ? ` ${args}` : ''}`,
78
80
  list: useBerry ? 'yarn info --name-only' : 'yarn list',
79
81
  getRegistryUrl: useBerry
80
82
  ? 'yarn config get npmRegistryServer'
@@ -95,9 +97,11 @@ function getPackageManagerCommand(packageManager = detectPackageManager(), root
95
97
  rm: 'pnpm rm',
96
98
  exec: modernPnpm ? 'pnpm exec' : 'pnpx',
97
99
  dlx: modernPnpm ? 'pnpm dlx' : 'pnpx',
98
- run: (script, args) => includeDoubleDashBeforeArgs
99
- ? `pnpm run ${script} -- ${args}`
100
- : `pnpm run ${script} ${args}`,
100
+ run: (script, args) => `pnpm run ${script}${args
101
+ ? includeDoubleDashBeforeArgs
102
+ ? ' -- ' + args
103
+ : ` ${args}`
104
+ : ''}`,
101
105
  list: 'pnpm ls --depth 100',
102
106
  getRegistryUrl: 'pnpm config get registry',
103
107
  };
@@ -114,11 +118,26 @@ function getPackageManagerCommand(packageManager = detectPackageManager(), root
114
118
  rm: 'npm rm',
115
119
  exec: 'npx',
116
120
  dlx: 'npx',
117
- run: (script, args) => `npm run ${script} -- ${args}`,
121
+ run: (script, args) => `npm run ${script}${args ? ' -- ' + args : ''}`,
118
122
  list: 'npm ls',
119
123
  getRegistryUrl: 'npm config get registry',
120
124
  };
121
125
  },
126
+ bun: () => {
127
+ // bun doesn't current support programatically reading config https://github.com/oven-sh/bun/issues/7140
128
+ return {
129
+ install: 'bun install',
130
+ ciInstall: 'bun install --no-cache',
131
+ updateLockFile: 'bun install --frozen-lockfile',
132
+ add: 'bun install',
133
+ addDev: 'bun install -D',
134
+ rm: 'bun rm',
135
+ exec: 'bun',
136
+ dlx: 'bunx',
137
+ run: (script, args) => `bun run ${script} -- ${args}`,
138
+ list: 'bun pm ls',
139
+ };
140
+ },
122
141
  };
123
142
  return commands[packageManager]();
124
143
  }
@@ -193,7 +212,12 @@ function modifyYarnRcToFitNewDirectory(contents) {
193
212
  }
194
213
  exports.modifyYarnRcToFitNewDirectory = modifyYarnRcToFitNewDirectory;
195
214
  function copyPackageManagerConfigurationFiles(root, destination) {
196
- for (const packageManagerConfigFile of ['.npmrc', '.yarnrc', '.yarnrc.yml']) {
215
+ for (const packageManagerConfigFile of [
216
+ '.npmrc',
217
+ '.yarnrc',
218
+ '.yarnrc.yml',
219
+ 'bunfig.toml',
220
+ ]) {
197
221
  // f is an absolute path, including the {workspaceRoot}.
198
222
  const f = findFileInPackageJsonDirectory(packageManagerConfigFile, root);
199
223
  if (f) {
@@ -216,6 +240,10 @@ function copyPackageManagerConfigurationFiles(root, destination) {
216
240
  (0, fs_1.writeFileSync)(destinationPath, updated);
217
241
  break;
218
242
  }
243
+ case 'bunfig.toml': {
244
+ (0, fs_1.copyFileSync)(f, destinationPath);
245
+ break;
246
+ }
219
247
  }
220
248
  }
221
249
  }
@@ -254,11 +282,20 @@ async function resolvePackageVersionUsingRegistry(packageName, version) {
254
282
  if (!result) {
255
283
  throw new Error(`Unable to resolve version ${packageName}@${version}.`);
256
284
  }
257
- // get the last line of the output, strip the package version and quotes
258
- const resolvedVersion = result
259
- .split('\n')
260
- .pop()
261
- .split(' ')
285
+ const lines = result.split('\n');
286
+ if (lines.length === 1) {
287
+ return lines[0];
288
+ }
289
+ /**
290
+ * The output contains multiple lines ordered by release date, so the last
291
+ * version might not be the last one in the list. We need to sort it. Each
292
+ * line looks like:
293
+ *
294
+ * <package>@<version> '<version>'
295
+ */
296
+ const resolvedVersion = lines
297
+ .map((line) => line.split(' ')[1])
298
+ .sort()
262
299
  .pop()
263
300
  .replace(/'/g, '');
264
301
  return resolvedVersion;
@@ -288,12 +325,16 @@ async function resolvePackageVersionUsingInstallation(packageName, version) {
288
325
  exports.resolvePackageVersionUsingInstallation = resolvePackageVersionUsingInstallation;
289
326
  async function packageRegistryView(pkg, version, args) {
290
327
  let pm = detectPackageManager();
291
- if (pm === 'yarn') {
328
+ if (pm === 'yarn' || pm === 'bun') {
292
329
  /**
293
330
  * yarn has `yarn info` but it behaves differently than (p)npm,
294
331
  * which makes it's usage unreliable
295
332
  *
296
333
  * @see https://github.com/nrwl/nx/pull/9667#discussion_r842553994
334
+ *
335
+ * Bun has a pm ls function but it only relates to its lockfile
336
+ * and acts differently from all other package managers
337
+ * from Jarred: "it probably would be bun pm view <package-name>"
297
338
  */
298
339
  pm = 'npm';
299
340
  }
@@ -303,13 +344,15 @@ async function packageRegistryView(pkg, version, args) {
303
344
  exports.packageRegistryView = packageRegistryView;
304
345
  async function packageRegistryPack(cwd, pkg, version) {
305
346
  let pm = detectPackageManager();
306
- if (pm === 'yarn') {
347
+ if (pm === 'yarn' || pm === 'bun') {
307
348
  /**
308
349
  * `(p)npm pack` will download a tarball of the specified version,
309
350
  * whereas `yarn` pack creates a tarball of the active workspace, so it
310
351
  * does not work for getting the content of a library.
311
352
  *
312
353
  * @see https://github.com/nrwl/nx/pull/9667#discussion_r842553994
354
+ *
355
+ * bun doesn't currently support pack
313
356
  */
314
357
  pm = 'npm';
315
358
  }
@@ -114,7 +114,7 @@ async function listPluginCapabilities(pluginName, projects) {
114
114
  if (hasBuilders) {
115
115
  bodyLines.push(chalk.bold(chalk.green('EXECUTORS/BUILDERS')));
116
116
  bodyLines.push('');
117
- bodyLines.push(...Object.keys(plugin.executors).map((name) => `${chalk.bold(name)} : ${plugin.executors[name].description}`));
117
+ bodyLines.push(...Object.keys(plugin.executors).map((name) => `${chalk.bold(name)} : ${resolveExecutorDescription(plugin.executors[name], projects)}`));
118
118
  }
119
119
  if (hasProjectGraphExtension) {
120
120
  bodyLines.push(`✔️ Project Graph Extension`);
@@ -128,3 +128,26 @@ async function listPluginCapabilities(pluginName, projects) {
128
128
  });
129
129
  }
130
130
  exports.listPluginCapabilities = listPluginCapabilities;
131
+ function resolveExecutorDescription(executorJsonEntry, projects) {
132
+ try {
133
+ if (typeof executorJsonEntry === 'string') {
134
+ // it points to another executor, resolve it
135
+ const [pkgName, executor] = executorJsonEntry.split(':');
136
+ const collection = loadExecutorsCollection(workspace_root_1.workspaceRoot, pkgName, projects);
137
+ return resolveExecutorDescription(collection[executor], projects);
138
+ }
139
+ return executorJsonEntry.description;
140
+ }
141
+ catch {
142
+ return 'No description available';
143
+ }
144
+ }
145
+ function loadExecutorsCollection(workspaceRoot, pluginName, projects) {
146
+ const { json: packageJson, path: packageJsonPath } = (0, plugins_1.readPluginPackageJson)(pluginName, projects, (0, installation_directory_1.getNxRequirePaths)(workspaceRoot));
147
+ return {
148
+ ...tryGetCollection(packageJsonPath, packageJson.builders, 'builders'),
149
+ ...tryGetCollection(packageJsonPath, packageJson.executors, 'builders'),
150
+ ...tryGetCollection(packageJsonPath, packageJson.builders, 'executors'),
151
+ ...tryGetCollection(packageJsonPath, packageJson.executors, 'executors'),
152
+ };
153
+ }