nx 20.5.0-beta.1 → 20.5.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 (54) hide show
  1. package/package.json +11 -11
  2. package/src/adapter/compat.d.ts +1 -1
  3. package/src/adapter/compat.js +1 -0
  4. package/src/command-line/init/command-object.js +13 -6
  5. package/src/command-line/init/implementation/add-nx-to-turborepo.d.ts +4 -0
  6. package/src/command-line/init/implementation/add-nx-to-turborepo.js +49 -0
  7. package/src/command-line/init/implementation/deduce-default-base.d.ts +1 -0
  8. package/src/command-line/init/implementation/deduce-default-base.js +53 -0
  9. package/src/command-line/init/implementation/utils.d.ts +3 -1
  10. package/src/command-line/init/implementation/utils.js +91 -42
  11. package/src/command-line/init/init-v2.js +34 -14
  12. package/src/command-line/migrate/migrate.js +21 -18
  13. package/src/config/nx-json.d.ts +3 -2
  14. package/src/core/graph/main.js +1 -1
  15. package/src/core/graph/runtime.js +1 -1
  16. package/src/core/graph/styles.css +2 -2
  17. package/src/core/graph/styles.js +1 -1
  18. package/src/daemon/client/client.d.ts +2 -1
  19. package/src/daemon/client/client.js +17 -60
  20. package/src/daemon/client/enabled.d.ts +2 -0
  21. package/src/daemon/client/enabled.js +64 -0
  22. package/src/daemon/message-types/glob.d.ts +7 -0
  23. package/src/daemon/message-types/glob.js +9 -1
  24. package/src/daemon/message-types/hash-glob.d.ts +6 -0
  25. package/src/daemon/message-types/hash-glob.js +9 -1
  26. package/src/daemon/server/handle-glob.d.ts +1 -0
  27. package/src/daemon/server/handle-glob.js +8 -0
  28. package/src/daemon/server/handle-hash-glob.d.ts +1 -0
  29. package/src/daemon/server/handle-hash-glob.js +8 -0
  30. package/src/daemon/server/server.js +6 -0
  31. package/src/devkit-exports.d.ts +1 -1
  32. package/src/devkit-exports.js +2 -2
  33. package/src/devkit-internals.d.ts +1 -1
  34. package/src/devkit-internals.js +2 -1
  35. package/src/native/index.d.ts +8 -0
  36. package/src/native/nx.wasi.cjs +7 -7
  37. package/src/native/nx.wasm32-wasi.wasm +0 -0
  38. package/src/project-graph/affected/locators/project-glob-changes.js +2 -2
  39. package/src/project-graph/error-types.js +4 -1
  40. package/src/project-graph/nx-deps-cache.js +7 -2
  41. package/src/project-graph/plugins/get-plugins.js +2 -1
  42. package/src/project-graph/plugins/isolation/plugin-worker.js +4 -0
  43. package/src/project-graph/plugins/loaded-nx-plugin.d.ts +2 -1
  44. package/src/project-graph/plugins/loaded-nx-plugin.js +6 -9
  45. package/src/project-graph/plugins/tasks-execution-hooks.js +4 -3
  46. package/src/project-graph/plugins/utils.d.ts +2 -2
  47. package/src/project-graph/plugins/utils.js +2 -2
  48. package/src/project-graph/project-graph.js +5 -2
  49. package/src/project-graph/utils/project-configuration-utils.d.ts +1 -1
  50. package/src/project-graph/utils/project-configuration-utils.js +11 -9
  51. package/src/project-graph/utils/retrieve-workspace-files.d.ts +1 -1
  52. package/src/project-graph/utils/retrieve-workspace-files.js +14 -18
  53. package/src/utils/workspace-context.d.ts +2 -0
  54. package/src/utils/workspace-context.js +16 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "20.5.0-beta.1",
3
+ "version": "20.5.0-beta.3",
4
4
  "private": false,
5
5
  "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
6
6
  "repository": {
@@ -82,16 +82,16 @@
82
82
  }
83
83
  },
84
84
  "optionalDependencies": {
85
- "@nx/nx-darwin-arm64": "20.5.0-beta.1",
86
- "@nx/nx-darwin-x64": "20.5.0-beta.1",
87
- "@nx/nx-freebsd-x64": "20.5.0-beta.1",
88
- "@nx/nx-linux-arm-gnueabihf": "20.5.0-beta.1",
89
- "@nx/nx-linux-arm64-gnu": "20.5.0-beta.1",
90
- "@nx/nx-linux-arm64-musl": "20.5.0-beta.1",
91
- "@nx/nx-linux-x64-gnu": "20.5.0-beta.1",
92
- "@nx/nx-linux-x64-musl": "20.5.0-beta.1",
93
- "@nx/nx-win32-arm64-msvc": "20.5.0-beta.1",
94
- "@nx/nx-win32-x64-msvc": "20.5.0-beta.1"
85
+ "@nx/nx-darwin-arm64": "20.5.0-beta.3",
86
+ "@nx/nx-darwin-x64": "20.5.0-beta.3",
87
+ "@nx/nx-freebsd-x64": "20.5.0-beta.3",
88
+ "@nx/nx-linux-arm-gnueabihf": "20.5.0-beta.3",
89
+ "@nx/nx-linux-arm64-gnu": "20.5.0-beta.3",
90
+ "@nx/nx-linux-arm64-musl": "20.5.0-beta.3",
91
+ "@nx/nx-linux-x64-gnu": "20.5.0-beta.3",
92
+ "@nx/nx-linux-x64-musl": "20.5.0-beta.3",
93
+ "@nx/nx-win32-arm64-msvc": "20.5.0-beta.3",
94
+ "@nx/nx-win32-x64-msvc": "20.5.0-beta.3"
95
95
  },
96
96
  "nx-migrations": {
97
97
  "migrations": "./migrations.json",
@@ -1,2 +1,2 @@
1
1
  export declare const allowedProjectExtensions: readonly ["tags", "implicitDependencies", "configFilePath", "$schema", "generators", "namedInputs", "name", "files", "root", "sourceRoot", "projectType", "release", "includedScripts", "metadata"];
2
- export declare const allowedWorkspaceExtensions: readonly ["implicitDependencies", "affected", "defaultBase", "tasksRunnerOptions", "workspaceLayout", "plugins", "targetDefaults", "files", "generators", "namedInputs", "extends", "cli", "pluginsConfig", "defaultProject", "installation", "release", "nxCloudAccessToken", "nxCloudId", "nxCloudUrl", "nxCloudEncryptionKey", "parallel", "cacheDirectory", "useDaemonProcess", "useInferencePlugins", "neverConnectToCloud", "sync", "useLegacyCache"];
2
+ export declare const allowedWorkspaceExtensions: readonly ["$schema", "implicitDependencies", "affected", "defaultBase", "tasksRunnerOptions", "workspaceLayout", "plugins", "targetDefaults", "files", "generators", "namedInputs", "extends", "cli", "pluginsConfig", "defaultProject", "installation", "release", "nxCloudAccessToken", "nxCloudId", "nxCloudUrl", "nxCloudEncryptionKey", "parallel", "cacheDirectory", "useDaemonProcess", "useInferencePlugins", "neverConnectToCloud", "sync", "useLegacyCache"];
@@ -37,6 +37,7 @@ exports.allowedProjectExtensions = [
37
37
  // There are some props in here (root) that angular already knows about,
38
38
  // but it doesn't hurt to have them in here as well to help static analysis.
39
39
  exports.allowedWorkspaceExtensions = [
40
+ '$schema',
40
41
  'implicitDependencies',
41
42
  'affected',
42
43
  'defaultBase',
@@ -7,14 +7,21 @@ exports.yargsInitCommand = {
7
7
  describe: 'Adds Nx to any type of workspace. It installs nx, creates an nx.json configuration file and optionally sets up remote caching. For more info, check https://nx.dev/recipes/adopting-nx.',
8
8
  builder: (yargs) => withInitOptions(yargs),
9
9
  handler: async (args) => {
10
- const useV2 = await isInitV2();
11
- if (useV2) {
12
- await require('./init-v2').initHandler(args);
10
+ try {
11
+ const useV2 = await isInitV2();
12
+ if (useV2) {
13
+ await require('./init-v2').initHandler(args);
14
+ }
15
+ else {
16
+ await require('./init-v1').initHandler(args);
17
+ }
18
+ process.exit(0);
13
19
  }
14
- else {
15
- await require('./init-v1').initHandler(args);
20
+ catch {
21
+ // Ensure the cursor is always restored just in case the user has bailed during interactive prompts
22
+ process.stdout.write('\x1b[?25h');
23
+ process.exit(1);
16
24
  }
17
- process.exit(0);
18
25
  },
19
26
  };
20
27
  async function isInitV2() {
@@ -0,0 +1,4 @@
1
+ import { InitArgs } from '../init-v1';
2
+ type Options = Pick<InitArgs, 'nxCloud' | 'interactive'>;
3
+ export declare function addNxToTurborepo(_options: Options): Promise<void>;
4
+ export {};
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addNxToTurborepo = addNxToTurborepo;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const fileutils_1 = require("../../../utils/fileutils");
7
+ const output_1 = require("../../../utils/output");
8
+ const package_manager_1 = require("../../../utils/package-manager");
9
+ const utils_1 = require("./utils");
10
+ async function addNxToTurborepo(_options) {
11
+ const repoRoot = process.cwd();
12
+ output_1.output.log({
13
+ title: 'Initializing Nx based on your old Turborepo configuration',
14
+ });
15
+ output_1.output.log({
16
+ title: '💡 Did you know?',
17
+ bodyLines: [
18
+ '- Turborepo requires you to maintain all your common scripts like "build", "lint", "test" in all your packages, as well as their applicable cache inputs and outputs.',
19
+ `- Nx is extensible and has plugins for the tools you use to infer all of this for you purely based on that tool's configuration file within your packages.`,
20
+ '',
21
+ ' - E.g. the `@nx/vite` plugin will infer the "build" script based on the existence of a vite.config.js file.',
22
+ ' - Therefore with zero package level config, `nx build my-app` knows to run the `vite build` CLI directly, with all Nx cache inputs and outputs automatically inferred.',
23
+ '',
24
+ `NOTE: None of your existing package.json scripts will be modified as part of this initialization process, you can already use them as-is with Nx, but you can learn more about the benefits of Nx's inferred tasks at https://nx.dev/concepts/inferred-tasks`,
25
+ ],
26
+ });
27
+ let nxJson = (0, utils_1.createNxJsonFromTurboJson)((0, fileutils_1.readJsonFile)('turbo.json'));
28
+ const nxJsonPath = (0, node_path_1.join)(repoRoot, 'nx.json');
29
+ // Turborepo workspaces usually have prettier installed, so try and match the formatting before writing the file
30
+ try {
31
+ const prettier = await Promise.resolve().then(() => require('prettier'));
32
+ const config = await prettier.resolveConfig(repoRoot);
33
+ (0, node_fs_1.writeFileSync)(nxJsonPath,
34
+ // @ts-ignore - Always await prettier.format, in modern versions it's async
35
+ await prettier.format(JSON.stringify(nxJson, null, 2), {
36
+ ...(config ?? {}),
37
+ parser: 'json',
38
+ }));
39
+ }
40
+ catch (err) {
41
+ // Apply fallback JSON write
42
+ (0, fileutils_1.writeJsonFile)(nxJsonPath, nxJson);
43
+ }
44
+ const pmc = (0, package_manager_1.getPackageManagerCommand)();
45
+ (0, utils_1.updateGitIgnore)(repoRoot);
46
+ (0, utils_1.addDepsToPackageJson)(repoRoot);
47
+ output_1.output.log({ title: '📦 Installing dependencies' });
48
+ (0, utils_1.runInstall)(repoRoot, pmc);
49
+ }
@@ -0,0 +1 @@
1
+ export declare function deduceDefaultBase(): string;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deduceDefaultBase = deduceDefaultBase;
4
+ const node_child_process_1 = require("node:child_process");
5
+ const default_base_1 = require("../../../utils/default-base");
6
+ function deduceDefaultBase() {
7
+ try {
8
+ (0, node_child_process_1.execSync)(`git rev-parse --verify main`, {
9
+ stdio: ['ignore', 'ignore', 'ignore'],
10
+ windowsHide: false,
11
+ });
12
+ return 'main';
13
+ }
14
+ catch {
15
+ try {
16
+ (0, node_child_process_1.execSync)(`git rev-parse --verify dev`, {
17
+ stdio: ['ignore', 'ignore', 'ignore'],
18
+ windowsHide: false,
19
+ });
20
+ return 'dev';
21
+ }
22
+ catch {
23
+ try {
24
+ (0, node_child_process_1.execSync)(`git rev-parse --verify develop`, {
25
+ stdio: ['ignore', 'ignore', 'ignore'],
26
+ windowsHide: false,
27
+ });
28
+ return 'develop';
29
+ }
30
+ catch {
31
+ try {
32
+ (0, node_child_process_1.execSync)(`git rev-parse --verify next`, {
33
+ stdio: ['ignore', 'ignore', 'ignore'],
34
+ windowsHide: false,
35
+ });
36
+ return 'next';
37
+ }
38
+ catch {
39
+ try {
40
+ (0, node_child_process_1.execSync)(`git rev-parse --verify master`, {
41
+ stdio: ['ignore', 'ignore', 'ignore'],
42
+ windowsHide: false,
43
+ });
44
+ return 'master';
45
+ }
46
+ catch {
47
+ return (0, default_base_1.deduceDefaultBase)();
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
@@ -1,12 +1,14 @@
1
+ import { NxJsonConfiguration } from '../../../config/nx-json';
1
2
  import { PackageJson } from '../../../utils/package-json';
2
3
  import { PackageManagerCommands } from '../../../utils/package-manager';
3
4
  export declare function createNxJsonFile(repoRoot: string, topologicalTargets: string[], cacheableOperations: string[], scriptOutputs: {
4
5
  [name: string]: string;
5
6
  }): void;
7
+ export declare function createNxJsonFromTurboJson(turboJson: Record<string, any>): NxJsonConfiguration;
6
8
  export declare function addDepsToPackageJson(repoRoot: string, additionalPackages?: string[]): void;
7
9
  export declare function updateGitIgnore(root: string): void;
8
10
  export declare function runInstall(repoRoot: string, pmc?: PackageManagerCommands): void;
9
- export declare function initCloud(installationSource: 'nx-init' | 'nx-init-angular' | 'nx-init-cra' | 'nx-init-monorepo' | 'nx-init-nest' | 'nx-init-npm-repo'): Promise<void>;
11
+ export declare function initCloud(installationSource: 'nx-init' | 'nx-init-angular' | 'nx-init-cra' | 'nx-init-monorepo' | 'nx-init-nest' | 'nx-init-npm-repo' | 'nx-init-turborepo'): Promise<void>;
10
12
  export declare function addVsCodeRecommendedExtensions(repoRoot: string, extensions: string[]): void;
11
13
  export declare function markRootPackageJsonAsNxProjectLegacy(repoRoot: string, cacheableScripts: string[], pmc: PackageManagerCommands): void;
12
14
  export declare function markPackageJsonAsNxProject(packageJsonPath: string): void;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createNxJsonFile = createNxJsonFile;
4
+ exports.createNxJsonFromTurboJson = createNxJsonFromTurboJson;
4
5
  exports.addDepsToPackageJson = addDepsToPackageJson;
5
6
  exports.updateGitIgnore = updateGitIgnore;
6
7
  exports.runInstall = runInstall;
@@ -21,7 +22,7 @@ const fs_1 = require("fs");
21
22
  const connect_to_nx_cloud_1 = require("../../../nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud");
22
23
  const url_shorten_1 = require("../../../nx-cloud/utilities/url-shorten");
23
24
  const connect_to_nx_cloud_2 = require("../../connect/connect-to-nx-cloud");
24
- const default_base_1 = require("../../../utils/default-base");
25
+ const deduce_default_base_1 = require("./deduce-default-base");
25
26
  function createNxJsonFile(repoRoot, topologicalTargets, cacheableOperations, scriptOutputs) {
26
27
  const nxJsonPath = (0, path_2.joinPathFragments)(repoRoot, 'nx.json');
27
28
  let nxJson = {};
@@ -53,56 +54,104 @@ function createNxJsonFile(repoRoot, topologicalTargets, cacheableOperations, scr
53
54
  if (Object.keys(nxJson.targetDefaults).length === 0) {
54
55
  delete nxJson.targetDefaults;
55
56
  }
56
- nxJson.defaultBase ??= deduceDefaultBase();
57
+ const defaultBase = (0, deduce_default_base_1.deduceDefaultBase)();
58
+ // Do not add defaultBase if it is inferred to be the Nx default value of main
59
+ if (defaultBase !== 'main') {
60
+ nxJson.defaultBase ??= defaultBase;
61
+ }
57
62
  (0, fileutils_1.writeJsonFile)(nxJsonPath, nxJson);
58
63
  }
59
- function deduceDefaultBase() {
60
- try {
61
- (0, child_process_1.execSync)(`git rev-parse --verify main`, {
62
- stdio: ['ignore', 'ignore', 'ignore'],
63
- windowsHide: false,
64
- });
65
- return 'main';
66
- }
67
- catch {
68
- try {
69
- (0, child_process_1.execSync)(`git rev-parse --verify dev`, {
70
- stdio: ['ignore', 'ignore', 'ignore'],
71
- windowsHide: false,
72
- });
73
- return 'dev';
64
+ function createNxJsonFromTurboJson(turboJson) {
65
+ const nxJson = {
66
+ $schema: './node_modules/nx/schemas/nx-schema.json',
67
+ };
68
+ // Handle global dependencies
69
+ if (turboJson.globalDependencies?.length > 0) {
70
+ nxJson.namedInputs = {
71
+ sharedGlobals: turboJson.globalDependencies.map((dep) => `{workspaceRoot}/${dep}`),
72
+ default: ['{projectRoot}/**/*', 'sharedGlobals'],
73
+ };
74
+ }
75
+ // Handle global env vars
76
+ if (turboJson.globalEnv?.length > 0) {
77
+ nxJson.namedInputs = nxJson.namedInputs || {};
78
+ nxJson.namedInputs.sharedGlobals = nxJson.namedInputs.sharedGlobals || [];
79
+ nxJson.namedInputs.sharedGlobals.push(...turboJson.globalEnv.map((env) => ({ env })));
80
+ nxJson.namedInputs.default = nxJson.namedInputs.default || [];
81
+ if (!nxJson.namedInputs.default.includes('{projectRoot}/**/*')) {
82
+ nxJson.namedInputs.default.push('{projectRoot}/**/*');
74
83
  }
75
- catch {
76
- try {
77
- (0, child_process_1.execSync)(`git rev-parse --verify develop`, {
78
- stdio: ['ignore', 'ignore', 'ignore'],
79
- windowsHide: false,
80
- });
81
- return 'develop';
84
+ if (!nxJson.namedInputs.default.includes('sharedGlobals')) {
85
+ nxJson.namedInputs.default.push('sharedGlobals');
86
+ }
87
+ }
88
+ // Handle task configurations
89
+ if (turboJson.tasks) {
90
+ nxJson.targetDefaults = {};
91
+ for (const [taskName, taskConfig] of Object.entries(turboJson.tasks)) {
92
+ // Skip project-specific tasks (containing #)
93
+ if (taskName.includes('#'))
94
+ continue;
95
+ const config = taskConfig;
96
+ nxJson.targetDefaults[taskName] = {};
97
+ // Handle dependsOn
98
+ if (config.dependsOn?.length > 0) {
99
+ nxJson.targetDefaults[taskName].dependsOn = config.dependsOn;
82
100
  }
83
- catch {
84
- try {
85
- (0, child_process_1.execSync)(`git rev-parse --verify next`, {
86
- stdio: ['ignore', 'ignore', 'ignore'],
87
- windowsHide: false,
88
- });
89
- return 'next';
90
- }
91
- catch {
92
- try {
93
- (0, child_process_1.execSync)(`git rev-parse --verify master`, {
94
- stdio: ['ignore', 'ignore', 'ignore'],
95
- windowsHide: false,
96
- });
97
- return 'master';
101
+ // Handle inputs
102
+ if (config.inputs?.length > 0) {
103
+ nxJson.targetDefaults[taskName].inputs = config.inputs
104
+ .map((input) => {
105
+ if (input === '$TURBO_DEFAULT$') {
106
+ return '{projectRoot}/**/*';
98
107
  }
99
- catch {
100
- return (0, default_base_1.deduceDefaultBase)();
108
+ // Don't add projectRoot if it's already there or if it's an env var
109
+ if (input.startsWith('{projectRoot}/') ||
110
+ input.startsWith('{env.') ||
111
+ input.startsWith('$'))
112
+ return input;
113
+ return `{projectRoot}/${input}`;
114
+ })
115
+ .map((input) => {
116
+ // Don't add projectRoot if it's already there or if it's an env var
117
+ if (input.startsWith('{projectRoot}/') ||
118
+ input.startsWith('{env.') ||
119
+ input.startsWith('$'))
120
+ return input;
121
+ return `{projectRoot}/${input}`;
122
+ });
123
+ }
124
+ // Handle outputs
125
+ if (config.outputs?.length > 0) {
126
+ nxJson.targetDefaults[taskName].outputs = config.outputs.map((output) => {
127
+ // Don't add projectRoot if it's already there
128
+ if (output.startsWith('{projectRoot}/'))
129
+ return output;
130
+ // Handle negated patterns by adding projectRoot after the !
131
+ if (output.startsWith('!')) {
132
+ return `!{projectRoot}/${output.slice(1)}`;
101
133
  }
102
- }
134
+ return `{projectRoot}/${output}`;
135
+ });
103
136
  }
137
+ // Handle cache setting - true by default in Turbo
138
+ nxJson.targetDefaults[taskName].cache = config.cache !== false;
104
139
  }
105
140
  }
141
+ /**
142
+ * The fact that cacheDir was in use suggests the user had a reason for deviating from the default.
143
+ * We can't know what that reason was, nor if it would still be applicable in Nx, but we can at least
144
+ * improve discoverability of the relevant Nx option by explicitly including it with its default value.
145
+ */
146
+ if (turboJson.cacheDir) {
147
+ nxJson.cacheDirectory = '.nx/cache';
148
+ }
149
+ const defaultBase = (0, deduce_default_base_1.deduceDefaultBase)();
150
+ // Do not add defaultBase if it is inferred to be the Nx default value of main
151
+ if (defaultBase !== 'main') {
152
+ nxJson.defaultBase ??= defaultBase;
153
+ }
154
+ return nxJson;
106
155
  }
107
156
  function addDepsToPackageJson(repoRoot, additionalPackages) {
108
157
  const path = (0, path_2.joinPathFragments)(repoRoot, `package.json`);
@@ -3,23 +3,24 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.initHandler = initHandler;
4
4
  exports.detectPlugins = detectPlugins;
5
5
  const fs_1 = require("fs");
6
+ const enquirer_1 = require("enquirer");
6
7
  const semver_1 = require("semver");
7
- const output_1 = require("../../utils/output");
8
- const package_manager_1 = require("../../utils/package-manager");
9
- const add_nx_scripts_1 = require("./implementation/dot-nx/add-nx-scripts");
8
+ const nx_json_1 = require("../../config/nx-json");
10
9
  const child_process_1 = require("../../utils/child-process");
11
10
  const fileutils_1 = require("../../utils/fileutils");
11
+ const get_package_name_from_import_path_1 = require("../../utils/get-package-name-from-import-path");
12
+ const output_1 = require("../../utils/output");
13
+ const package_manager_1 = require("../../utils/package-manager");
12
14
  const versions_1 = require("../../utils/versions");
13
- const utils_1 = require("./implementation/utils");
14
- const enquirer_1 = require("enquirer");
15
- const angular_1 = require("./implementation/angular");
16
15
  const workspace_context_1 = require("../../utils/workspace-context");
17
16
  const connect_to_nx_cloud_1 = require("../connect/connect-to-nx-cloud");
18
- const add_nx_to_npm_repo_1 = require("./implementation/add-nx-to-npm-repo");
19
- const add_nx_to_monorepo_1 = require("./implementation/add-nx-to-monorepo");
20
- const nx_json_1 = require("../../config/nx-json");
21
- const get_package_name_from_import_path_1 = require("../../utils/get-package-name-from-import-path");
22
17
  const configure_plugins_1 = require("./configure-plugins");
18
+ const add_nx_to_monorepo_1 = require("./implementation/add-nx-to-monorepo");
19
+ const add_nx_to_npm_repo_1 = require("./implementation/add-nx-to-npm-repo");
20
+ const add_nx_to_turborepo_1 = require("./implementation/add-nx-to-turborepo");
21
+ const angular_1 = require("./implementation/angular");
22
+ const add_nx_scripts_1 = require("./implementation/dot-nx/add-nx-scripts");
23
+ const utils_1 = require("./implementation/utils");
23
24
  async function initHandler(options) {
24
25
  process.env.NX_RUNNING_NX_INIT = 'true';
25
26
  const version = process.env.NX_VERSION ?? ((0, semver_1.prerelease)(versions_1.nxVersion) ? 'next' : 'latest');
@@ -57,7 +58,29 @@ async function initHandler(options) {
57
58
  return;
58
59
  }
59
60
  const packageJson = (0, fileutils_1.readJsonFile)('package.json');
60
- if ((0, utils_1.isMonorepo)(packageJson)) {
61
+ const _isTurborepo = (0, fs_1.existsSync)('turbo.json');
62
+ const _isMonorepo = (0, utils_1.isMonorepo)(packageJson);
63
+ const learnMoreLink = _isTurborepo
64
+ ? 'https://nx.dev/recipes/adopting-nx/from-turborepo'
65
+ : _isMonorepo
66
+ ? 'https://nx.dev/getting-started/tutorials/npm-workspaces-tutorial'
67
+ : 'https://nx.dev/recipes/adopting-nx/adding-to-existing-project';
68
+ /**
69
+ * Turborepo users must have set up individual scripts already, and we keep the transition as minimal as possible.
70
+ * We log a message during the conversion process in addNxToTurborepo about how they can learn more about the power
71
+ * of Nx plugins and how it would allow them to infer all the relevant scripts automatically, including all cache
72
+ * inputs and outputs.
73
+ */
74
+ if (_isTurborepo) {
75
+ await (0, add_nx_to_turborepo_1.addNxToTurborepo)({
76
+ interactive: options.interactive,
77
+ });
78
+ (0, utils_1.printFinalMessage)({
79
+ learnMoreLink,
80
+ });
81
+ return;
82
+ }
83
+ if (_isMonorepo) {
61
84
  await (0, add_nx_to_monorepo_1.addNxToMonorepo)({
62
85
  interactive: options.interactive,
63
86
  nxCloud: false,
@@ -69,9 +92,6 @@ async function initHandler(options) {
69
92
  nxCloud: false,
70
93
  });
71
94
  }
72
- const learnMoreLink = (0, utils_1.isMonorepo)(packageJson)
73
- ? 'https://nx.dev/getting-started/tutorials/npm-workspaces-tutorial'
74
- : 'https://nx.dev/recipes/adopting-nx/adding-to-existing-project';
75
95
  const useNxCloud = options.nxCloud ??
76
96
  (options.interactive ? await (0, connect_to_nx_cloud_1.connectExistingRepoToNxCloudPrompt)() : false);
77
97
  const repoRoot = process.cwd();
@@ -118,10 +118,10 @@ class Migrator {
118
118
  const packagesToCheck = await this.populatePackageJsonUpdatesAndGetPackagesToCheck(targetPackage, target);
119
119
  for (const packageToCheck of packagesToCheck) {
120
120
  const filteredUpdates = {};
121
- for (const packageUpdate of packageToCheck.updates) {
121
+ for (const [packageUpdateKey, packageUpdate] of Object.entries(packageToCheck.updates)) {
122
122
  if (this.areRequirementsMet(packageUpdate.requires) &&
123
123
  (!this.interactive ||
124
- (await this.runPackageJsonUpdatesConfirmationPrompt(packageUpdate)))) {
124
+ (await this.runPackageJsonUpdatesConfirmationPrompt(packageUpdate, packageUpdateKey, packageToCheck.package)))) {
125
125
  Object.entries(packageUpdate.packages).forEach(([name, update]) => {
126
126
  filteredUpdates[name] = update;
127
127
  this.packageUpdates[name] = update;
@@ -166,15 +166,15 @@ class Migrator {
166
166
  addToPackageJson: target.addToPackageJson || false,
167
167
  });
168
168
  const { packageJsonUpdates, packageGroupOrder } = this.getPackageJsonUpdatesFromMigrationConfig(targetPackage, targetVersion, migrationConfig);
169
- if (!packageJsonUpdates.length) {
169
+ if (!Object.keys(packageJsonUpdates).length) {
170
170
  return [];
171
171
  }
172
- const shouldCheckUpdates = packageJsonUpdates.some((packageJsonUpdate) => (this.interactive && packageJsonUpdate['x-prompt']) ||
172
+ const shouldCheckUpdates = Object.values(packageJsonUpdates).some((packageJsonUpdate) => (this.interactive && packageJsonUpdate['x-prompt']) ||
173
173
  Object.keys(packageJsonUpdate.requires ?? {}).length);
174
174
  if (shouldCheckUpdates) {
175
175
  return [{ package: targetPackage, updates: packageJsonUpdates }];
176
176
  }
177
- const packageUpdatesToApply = packageJsonUpdates.reduce((m, c) => ({ ...m, ...c.packages }), {});
177
+ const packageUpdatesToApply = Object.values(packageJsonUpdates).reduce((m, c) => ({ ...m, ...c.packages }), {});
178
178
  return (await Promise.all(Object.entries(packageUpdatesToApply).map(([packageName, packageUpdate]) => this.populatePackageJsonUpdatesAndGetPackagesToCheck(packageName, packageUpdate))))
179
179
  .filter((pkgs) => pkgs.length)
180
180
  .flat()
@@ -185,7 +185,7 @@ class Migrator {
185
185
  const packageGroupOrder = this.getPackageJsonUpdatesFromPackageGroup(packageName, targetVersion, migrationConfig);
186
186
  if (!migrationConfig.packageJsonUpdates ||
187
187
  !this.getPkgVersion(packageName)) {
188
- return { packageJsonUpdates: [], packageGroupOrder };
188
+ return { packageJsonUpdates: {}, packageGroupOrder };
189
189
  }
190
190
  const packageJsonUpdates = this.filterPackageJsonUpdates(migrationConfig.packageJsonUpdates, packageName, targetVersion);
191
191
  return { packageJsonUpdates, packageGroupOrder };
@@ -228,8 +228,8 @@ class Migrator {
228
228
  return packageGroupOrder;
229
229
  }
230
230
  filterPackageJsonUpdates(packageJsonUpdates, packageName, targetVersion) {
231
- const filteredPackageJsonUpdates = [];
232
- for (const packageJsonUpdate of Object.values(packageJsonUpdates)) {
231
+ const filteredPackageJsonUpdates = {};
232
+ for (const [packageJsonUpdateKey, packageJsonUpdate] of Object.entries(packageJsonUpdates)) {
233
233
  if (!packageJsonUpdate.packages ||
234
234
  this.lt(packageJsonUpdate.version, this.getPkgVersion(packageName)) ||
235
235
  this.gt(packageJsonUpdate.version, targetVersion)) {
@@ -254,7 +254,7 @@ class Migrator {
254
254
  }
255
255
  if (Object.keys(filtered).length) {
256
256
  packageJsonUpdate.packages = filtered;
257
- filteredPackageJsonUpdates.push(packageJsonUpdate);
257
+ filteredPackageJsonUpdates[packageJsonUpdateKey] = packageJsonUpdate;
258
258
  }
259
259
  }
260
260
  return filteredPackageJsonUpdates;
@@ -313,7 +313,7 @@ class Migrator {
313
313
  includePrerelease: true,
314
314
  }));
315
315
  }
316
- async runPackageJsonUpdatesConfirmationPrompt(packageUpdate) {
316
+ async runPackageJsonUpdatesConfirmationPrompt(packageUpdate, packageUpdateKey, packageName) {
317
317
  if (!packageUpdate['x-prompt']) {
318
318
  return Promise.resolve(true);
319
319
  }
@@ -322,14 +322,17 @@ class Migrator {
322
322
  // a same prompt was already answered, skip
323
323
  return Promise.resolve(false);
324
324
  }
325
- return await (0, enquirer_1.prompt)([
326
- {
327
- name: 'shouldApply',
328
- type: 'confirm',
329
- message: packageUpdate['x-prompt'],
330
- initial: true,
331
- },
332
- ]).then(({ shouldApply }) => {
325
+ const promptConfig = {
326
+ name: 'shouldApply',
327
+ type: 'confirm',
328
+ message: packageUpdate['x-prompt'],
329
+ initial: true,
330
+ };
331
+ if (packageName.startsWith('@nx/')) {
332
+ // @ts-expect-error -- enquirer types aren't correct, footer does exist
333
+ promptConfig.footer = () => chalk.dim(` View migration details at https://nx.dev/nx-api/${packageName.replace('@nx/', '')}#${packageUpdateKey.replace(/[-\.]/g, '')}packageupdates`);
334
+ }
335
+ return await (0, enquirer_1.prompt)([promptConfig]).then(({ shouldApply }) => {
333
336
  this.promptAnswers[promptKey] = shouldApply;
334
337
  if (!shouldApply &&
335
338
  (!this.minVersionWithSkippedUpdates ||
@@ -1,6 +1,6 @@
1
1
  import type { ChangelogRenderOptions } from '../../release/changelog-renderer';
2
- import { PackageManager } from '../utils/package-manager';
3
- import { InputDefinition, TargetConfiguration, TargetDependencyConfig } from './workspace-json-project-json';
2
+ import type { PackageManager } from '../utils/package-manager';
3
+ import type { InputDefinition, TargetConfiguration, TargetDependencyConfig } from './workspace-json-project-json';
4
4
  export type ImplicitDependencyEntry<T = '*' | string[]> = {
5
5
  [key: string]: T | ImplicitJsonSubsetDependency<T>;
6
6
  };
@@ -321,6 +321,7 @@ export interface NxSyncConfiguration {
321
321
  * @note: when adding properties here add them to `allowedWorkspaceExtensions` in adapter/compat.ts
322
322
  */
323
323
  export interface NxJsonConfiguration<T = '*' | string[]> {
324
+ $schema?: string;
324
325
  /**
325
326
  * Optional (additional) Nx.json configuration file which becomes a base for this one
326
327
  */