Repository navigation
Expand file tree
/
Copy pathnx.ts
More file actions
278 lines (246 loc) · 8 KB
/
Copy pathnx.ts
File metadata and controls
278 lines (246 loc) · 8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
#!/usr/bin/env node
import {
findWorkspaceRoot,
WorkspaceTypeAndRoot,
} from '../src/utils/find-workspace-root';
import * as chalk from 'chalk';
import { loadRootEnvFiles } from '../src/utils/dotenv';
import { initLocal } from './init-local';
import { output } from '../src/utils/output';
import {
getNxInstallationPath,
getNxRequirePaths,
} from '../src/utils/installation-directory';
import { major } from 'semver';
import { stripIndents } from '../src/utils/strip-indents';
import { readModulePackageJson } from '../src/utils/package-json';
import { execSync } from 'child_process';
import { join } from 'path';
import { assertSupportedPlatform } from '../src/native/assert-supported-platform';
import { performance } from 'perf_hooks';
import { setupWorkspaceContext } from '../src/utils/workspace-context';
import { daemonClient } from '../src/daemon/client/client';
function main() {
if (
process.argv[2] !== 'report' &&
process.argv[2] !== '--version' &&
process.argv[2] !== '--help' &&
process.argv[2] !== 'reset'
) {
assertSupportedPlatform();
}
require('nx/src/utils/perf-logging');
const workspace = findWorkspaceRoot(process.cwd());
performance.mark('loading dotenv files:start');
if (workspace) {
loadRootEnvFiles(workspace.dir);
}
performance.mark('loading dotenv files:end');
performance.measure(
'loading dotenv files',
'loading dotenv files:start',
'loading dotenv files:end'
);
// new is a special case because there is no local workspace to load
if (
process.argv[2] === 'new' ||
process.argv[2] === '_migrate' ||
process.argv[2] === 'init' ||
(process.argv[2] === 'graph' && !workspace)
) {
process.env.NX_DAEMON = 'false';
require('nx/src/command-line/nx-commands').commandsObject.argv;
} else {
if (!daemonClient.enabled() && workspace !== null) {
setupWorkspaceContext(workspace.dir);
}
// polyfill rxjs observable to avoid issues with multiple version of Observable installed in node_modules
// https://twitter.com/BenLesh/status/1192478226385428483?s=20
if (!(Symbol as any).observable)
(Symbol as any).observable = Symbol('observable polyfill');
// Make sure that a local copy of Nx exists in workspace
let localNx: string;
try {
localNx = workspace && resolveNx(workspace);
} catch {
localNx = null;
}
const isLocalInstall = localNx === resolveNx(null);
const { LOCAL_NX_VERSION, GLOBAL_NX_VERSION } = determineNxVersions(
localNx,
workspace,
isLocalInstall
);
if (process.argv[2] === '--version') {
handleNxVersionCommand(LOCAL_NX_VERSION, GLOBAL_NX_VERSION);
}
if (!workspace) {
handleNoWorkspace(GLOBAL_NX_VERSION);
}
if (!localNx) {
handleMissingLocalInstallation();
}
// this file is already in the local workspace
if (isLocalInstall) {
initLocal(workspace);
} else {
// Nx is being run from globally installed CLI - hand off to the local
warnIfUsingOutdatedGlobalInstall(GLOBAL_NX_VERSION, LOCAL_NX_VERSION);
if (localNx.includes('.nx')) {
const nxWrapperPath = localNx.replace(/\.nx.*/, '.nx/') + 'nxw.js';
require(nxWrapperPath);
} else {
require(localNx);
}
}
}
}
function handleNoWorkspace(globalNxVersion?: string) {
output.log({
title: `The current directory isn't part of an Nx workspace.`,
bodyLines: [
`To create a workspace run:`,
chalk.bold.white(`npx create-nx-workspace@latest <workspace name>`),
'',
`To add Nx to an existing workspace with a workspace-specific nx.json, run:`,
chalk.bold.white(`npx nx@latest init`),
],
});
output.note({
title: `For more information please visit https://nx.dev/`,
});
warnIfUsingOutdatedGlobalInstall(globalNxVersion);
process.exit(1);
}
function handleNxVersionCommand(
LOCAL_NX_VERSION: string,
GLOBAL_NX_VERSION: string
) {
console.log(stripIndents`Nx Version:
- Local: ${LOCAL_NX_VERSION ? 'v' + LOCAL_NX_VERSION : 'Not found'}
- Global: ${GLOBAL_NX_VERSION ? 'v' + GLOBAL_NX_VERSION : 'Not found'}`);
process.exit(0);
}
function determineNxVersions(
localNx: string,
workspace: WorkspaceTypeAndRoot,
isLocalInstall: boolean
) {
const LOCAL_NX_VERSION: string | null = localNx
? getLocalNxVersion(workspace)
: null;
const GLOBAL_NX_VERSION: string | null = isLocalInstall
? null
: require('../package.json').version;
globalThis.GLOBAL_NX_VERSION ??= GLOBAL_NX_VERSION;
return { LOCAL_NX_VERSION, GLOBAL_NX_VERSION };
}
function resolveNx(workspace: WorkspaceTypeAndRoot | null) {
// root relative to location of the nx bin
const globalsRoot = join(__dirname, '../../../');
// prefer Nx installed in .nx/installation
try {
return require.resolve('nx/bin/nx.js', {
paths: [getNxInstallationPath(workspace ? workspace.dir : globalsRoot)],
});
} catch {}
// check for root install
try {
return require.resolve('nx/bin/nx.js', {
paths: [workspace ? workspace.dir : globalsRoot],
});
} catch {
// TODO(v17): Remove this
// fallback for old CLI install setup
// nx-ignore-next-line
return require.resolve('@nrwl/cli/bin/nx.js', {
paths: [workspace ? workspace.dir : globalsRoot],
});
}
}
function handleMissingLocalInstallation() {
output.error({
title: `Could not find Nx modules in this workspace.`,
bodyLines: [`Have you run ${chalk.bold.white(`npm/yarn install`)}?`],
});
process.exit(1);
}
/**
* Assumes currently running Nx is global install.
* Warns if out of date by 1 major version or more.
*/
function warnIfUsingOutdatedGlobalInstall(
globalNxVersion: string,
localNxVersion?: string
) {
// Never display this warning if Nx is already running via Nx
if (process.env.NX_CLI_SET) {
return;
}
const isOutdatedGlobalInstall = checkOutdatedGlobalInstallation(
globalNxVersion,
localNxVersion
);
// Using a global Nx Install
if (isOutdatedGlobalInstall) {
const bodyLines = localNxVersion
? [
`Your repository uses a higher version of Nx (${localNxVersion}) than your global CLI version (${globalNxVersion})`,
]
: [];
bodyLines.push(
'For more information, see https://nx.dev/more-concepts/global-nx'
);
output.warn({
title: `It's time to update Nx 🎉`,
bodyLines,
});
}
}
function checkOutdatedGlobalInstallation(
globalNxVersion?: string,
localNxVersion?: string
) {
// We aren't running a global install, so we can't know if its outdated.
if (!globalNxVersion) {
return false;
}
if (localNxVersion) {
// If the global Nx install is at least a major version behind the local install, warn.
return major(globalNxVersion) < major(localNxVersion);
}
// No local installation was detected. This can happen if the user is running a global install
// that contains an older version of Nx, which is unable to detect the local installation. The most
// recent case where this would have happened would be when we stopped generating workspace.json by default,
// as older global installations used it to determine the workspace root. This only be hit in rare cases,
// but can provide valuable insights for troubleshooting.
const latestVersionOfNx = getLatestVersionOfNx();
if (latestVersionOfNx && major(globalNxVersion) < major(latestVersionOfNx)) {
return true;
}
}
function getLocalNxVersion(workspace: WorkspaceTypeAndRoot): string | null {
try {
const { packageJson } = readModulePackageJson(
'nx',
getNxRequirePaths(workspace.dir)
);
return packageJson.version;
} catch {}
}
function _getLatestVersionOfNx(): string {
try {
return execSync('npm view nx@latest version').toString().trim();
} catch {
try {
return execSync('pnpm view nx@latest version').toString().trim();
} catch {
return null;
}
}
}
const getLatestVersionOfNx = ((fn: () => string) => {
let cache: string = null;
return () => cache || (cache = fn());
})(_getLatestVersionOfNx);
main();