@nx/js 20.0.0 → 20.0.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.
- package/package.json +3 -3
- package/src/executors/node/lib/kill-tree.js +3 -3
- package/src/executors/release-publish/release-publish.impl.js +3 -3
- package/src/executors/verdaccio/verdaccio.impl.js +22 -20
- package/src/generators/release-version/release-version.js +1 -1
- package/src/generators/release-version/utils/update-lock-file.js +1 -1
- package/src/generators/setup-verdaccio/generator.js +1 -1
- package/src/generators/typescript-sync/typescript-sync.js +64 -47
- package/src/plugins/jest/start-local-registry.js +2 -2
- package/src/plugins/typescript/plugin.js +19 -6
- package/src/utils/npm-config.js +1 -1
- package/src/utils/swc/compile-swc.js +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/js",
|
|
3
|
-
"version": "20.0.
|
|
3
|
+
"version": "20.0.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The JS plugin for Nx contains executors and generators that provide the best experience for developing JavaScript and TypeScript projects. ",
|
|
6
6
|
"repository": {
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"@babel/preset-env": "^7.23.2",
|
|
40
40
|
"@babel/preset-typescript": "^7.22.5",
|
|
41
41
|
"@babel/runtime": "^7.22.6",
|
|
42
|
-
"@nx/devkit": "20.0.
|
|
43
|
-
"@nx/workspace": "20.0.
|
|
42
|
+
"@nx/devkit": "20.0.2",
|
|
43
|
+
"@nx/workspace": "20.0.2",
|
|
44
44
|
"@zkochan/js-yaml": "0.0.7",
|
|
45
45
|
"babel-plugin-const-enum": "^1.0.1",
|
|
46
46
|
"babel-plugin-macros": "^2.8.0",
|
|
@@ -20,7 +20,7 @@ async function killTree(pid, signal) {
|
|
|
20
20
|
switch (process.platform) {
|
|
21
21
|
case 'win32':
|
|
22
22
|
(0, child_process_1.exec)('taskkill /pid ' + pid + ' /T /F', {
|
|
23
|
-
windowsHide:
|
|
23
|
+
windowsHide: false,
|
|
24
24
|
}, (error) => {
|
|
25
25
|
// Ignore Fatal errors (128) because it might be due to the process already being killed.
|
|
26
26
|
// On Linux/Mac we can check ESRCH (no such process), but on Windows we can't.
|
|
@@ -30,7 +30,7 @@ async function killTree(pid, signal) {
|
|
|
30
30
|
case 'darwin':
|
|
31
31
|
buildProcessTree(pid, tree, pidsToProcess, function (parentPid) {
|
|
32
32
|
return (0, child_process_1.spawn)('pgrep', ['-P', parentPid], {
|
|
33
|
-
windowsHide:
|
|
33
|
+
windowsHide: false,
|
|
34
34
|
});
|
|
35
35
|
}, function () {
|
|
36
36
|
killAll(tree, signal, callback);
|
|
@@ -39,7 +39,7 @@ async function killTree(pid, signal) {
|
|
|
39
39
|
default: // Linux
|
|
40
40
|
buildProcessTree(pid, tree, pidsToProcess, function (parentPid) {
|
|
41
41
|
return (0, child_process_1.spawn)('ps', ['-o', 'pid', '--no-headers', '--ppid', parentPid], {
|
|
42
|
-
windowsHide:
|
|
42
|
+
windowsHide: false,
|
|
43
43
|
});
|
|
44
44
|
}, function () {
|
|
45
45
|
killAll(tree, signal, callback);
|
|
@@ -96,7 +96,7 @@ Please update the local dependency on "${depName}" to be a valid semantic versio
|
|
|
96
96
|
env: processEnv(true),
|
|
97
97
|
cwd: context.root,
|
|
98
98
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
99
|
-
windowsHide:
|
|
99
|
+
windowsHide: false,
|
|
100
100
|
});
|
|
101
101
|
const resultJson = JSON.parse(result.toString());
|
|
102
102
|
const distTags = resultJson['dist-tags'] || {};
|
|
@@ -117,7 +117,7 @@ Please update the local dependency on "${depName}" to be a valid semantic versio
|
|
|
117
117
|
env: processEnv(true),
|
|
118
118
|
cwd: context.root,
|
|
119
119
|
stdio: 'ignore',
|
|
120
|
-
windowsHide:
|
|
120
|
+
windowsHide: false,
|
|
121
121
|
});
|
|
122
122
|
console.log(`Added the dist-tag ${tag} to v${currentVersion} for registry ${registry}.\n`);
|
|
123
123
|
}
|
|
@@ -204,7 +204,7 @@ Please update the local dependency on "${depName}" to be a valid semantic versio
|
|
|
204
204
|
env: processEnv(true),
|
|
205
205
|
cwd: context.root,
|
|
206
206
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
207
|
-
windowsHide:
|
|
207
|
+
windowsHide: false,
|
|
208
208
|
});
|
|
209
209
|
/**
|
|
210
210
|
* We cannot JSON.parse the output directly because if the user is using lifecycle scripts, npm/pnpm will mix its publish output with the JSON output all on stdout.
|
|
@@ -38,12 +38,12 @@ async function verdaccioExecutor(options, context) {
|
|
|
38
38
|
}
|
|
39
39
|
const cleanupFunctions = options.location === 'none' ? [] : [setupNpm(options), setupYarn(options)];
|
|
40
40
|
const processExitListener = (signal) => {
|
|
41
|
-
if (childProcess) {
|
|
42
|
-
childProcess.kill(signal);
|
|
43
|
-
}
|
|
44
41
|
for (const fn of cleanupFunctions) {
|
|
45
42
|
fn();
|
|
46
43
|
}
|
|
44
|
+
if (childProcess) {
|
|
45
|
+
childProcess.kill(signal);
|
|
46
|
+
}
|
|
47
47
|
};
|
|
48
48
|
process.on('exit', processExitListener);
|
|
49
49
|
process.on('SIGTERM', processExitListener);
|
|
@@ -113,7 +113,7 @@ function createVerdaccioOptions(options, workspaceRoot) {
|
|
|
113
113
|
}
|
|
114
114
|
function setupNpm(options) {
|
|
115
115
|
try {
|
|
116
|
-
(0, child_process_1.execSync)('npm --version', { env, windowsHide:
|
|
116
|
+
(0, child_process_1.execSync)('npm --version', { env, windowsHide: false });
|
|
117
117
|
}
|
|
118
118
|
catch (e) {
|
|
119
119
|
return () => { };
|
|
@@ -124,13 +124,13 @@ function setupNpm(options) {
|
|
|
124
124
|
scopes.forEach((scope) => {
|
|
125
125
|
const registryName = scope ? `${scope}:registry` : 'registry';
|
|
126
126
|
try {
|
|
127
|
-
npmRegistryPaths.push((0, child_process_1.execSync)(`npm config get ${registryName} --location ${options.location}`, { env, windowsHide:
|
|
127
|
+
npmRegistryPaths.push((0, child_process_1.execSync)(`npm config get ${registryName} --location ${options.location}`, { env, windowsHide: false })
|
|
128
128
|
?.toString()
|
|
129
129
|
?.trim()
|
|
130
130
|
?.replace('\u001b[2K\u001b[1G', '') // strip out ansi codes
|
|
131
131
|
);
|
|
132
|
-
(0, child_process_1.execSync)(`npm config set ${registryName} http://localhost:${options.port}/ --location ${options.location}`, { env, windowsHide:
|
|
133
|
-
(0, child_process_1.execSync)(`npm config set //localhost:${options.port}/:_authToken="secretVerdaccioToken" --location ${options.location}`, { env, windowsHide:
|
|
132
|
+
(0, child_process_1.execSync)(`npm config set ${registryName} http://localhost:${options.port}/ --location ${options.location}`, { env, windowsHide: false });
|
|
133
|
+
(0, child_process_1.execSync)(`npm config set //localhost:${options.port}/:_authToken="secretVerdaccioToken" --location ${options.location}`, { env, windowsHide: false });
|
|
134
134
|
devkit_1.logger.info(`Set npm ${registryName} to http://localhost:${options.port}/`);
|
|
135
135
|
}
|
|
136
136
|
catch (e) {
|
|
@@ -139,7 +139,7 @@ function setupNpm(options) {
|
|
|
139
139
|
});
|
|
140
140
|
return () => {
|
|
141
141
|
try {
|
|
142
|
-
const currentNpmRegistryPath = (0, child_process_1.execSync)(`npm config get registry --location ${options.location}`, { env, windowsHide:
|
|
142
|
+
const currentNpmRegistryPath = (0, child_process_1.execSync)(`npm config get registry --location ${options.location}`, { env, windowsHide: false })
|
|
143
143
|
?.toString()
|
|
144
144
|
?.trim()
|
|
145
145
|
?.replace('\u001b[2K\u001b[1G', ''); // strip out ansi codes
|
|
@@ -147,18 +147,18 @@ function setupNpm(options) {
|
|
|
147
147
|
const registryName = scope ? `${scope}:registry` : 'registry';
|
|
148
148
|
if (npmRegistryPaths[index] &&
|
|
149
149
|
currentNpmRegistryPath.includes('localhost')) {
|
|
150
|
-
(0, child_process_1.execSync)(`npm config set ${registryName} ${npmRegistryPaths[index]} --location ${options.location}`, { env, windowsHide:
|
|
150
|
+
(0, child_process_1.execSync)(`npm config set ${registryName} ${npmRegistryPaths[index]} --location ${options.location}`, { env, windowsHide: false });
|
|
151
151
|
devkit_1.logger.info(`Reset npm ${registryName} to ${npmRegistryPaths[index]}`);
|
|
152
152
|
}
|
|
153
153
|
else {
|
|
154
154
|
(0, child_process_1.execSync)(`npm config delete ${registryName} --location ${options.location}`, {
|
|
155
155
|
env,
|
|
156
|
-
windowsHide:
|
|
156
|
+
windowsHide: false,
|
|
157
157
|
});
|
|
158
158
|
devkit_1.logger.info('Cleared custom npm registry');
|
|
159
159
|
}
|
|
160
160
|
});
|
|
161
|
-
(0, child_process_1.execSync)(`npm config delete //localhost:${options.port}/:_authToken --location ${options.location}`, { env, windowsHide:
|
|
161
|
+
(0, child_process_1.execSync)(`npm config delete //localhost:${options.port}/:_authToken --location ${options.location}`, { env, windowsHide: false });
|
|
162
162
|
}
|
|
163
163
|
catch (e) {
|
|
164
164
|
throw new Error(`Failed to reset npm registry: ${e.message}`);
|
|
@@ -173,17 +173,17 @@ function getYarnUnsafeHttpWhitelist(isYarnV1) {
|
|
|
173
173
|
return !isYarnV1
|
|
174
174
|
? new Set(JSON.parse((0, child_process_1.execSync)(`yarn config get unsafeHttpWhitelist --json`, {
|
|
175
175
|
env,
|
|
176
|
-
windowsHide:
|
|
176
|
+
windowsHide: false,
|
|
177
177
|
}).toString()))
|
|
178
178
|
: null;
|
|
179
179
|
}
|
|
180
180
|
function setYarnUnsafeHttpWhitelist(currentWhitelist, options) {
|
|
181
181
|
if (currentWhitelist.size > 0) {
|
|
182
|
-
(0, child_process_1.execSync)(`yarn config set unsafeHttpWhitelist --json '${JSON.stringify(Array.from(currentWhitelist))}'` + (options.location === 'user' ? ' --home' : ''), { env, windowsHide:
|
|
182
|
+
(0, child_process_1.execSync)(`yarn config set unsafeHttpWhitelist --json '${JSON.stringify(Array.from(currentWhitelist))}'` + (options.location === 'user' ? ' --home' : ''), { env, windowsHide: false });
|
|
183
183
|
}
|
|
184
184
|
else {
|
|
185
185
|
(0, child_process_1.execSync)(`yarn config unset unsafeHttpWhitelist` +
|
|
186
|
-
(options.location === 'user' ? ' --home' : ''), { env, windowsHide:
|
|
186
|
+
(options.location === 'user' ? ' --home' : ''), { env, windowsHide: false });
|
|
187
187
|
}
|
|
188
188
|
}
|
|
189
189
|
function setupYarn(options) {
|
|
@@ -192,7 +192,9 @@ function setupYarn(options) {
|
|
|
192
192
|
const scopes = ['', ...(options.scopes || [])];
|
|
193
193
|
try {
|
|
194
194
|
isYarnV1 =
|
|
195
|
-
(0, semver_1.major)((0, child_process_1.execSync)('yarn --version', { env, windowsHide:
|
|
195
|
+
(0, semver_1.major)((0, child_process_1.execSync)('yarn --version', { env, windowsHide: false })
|
|
196
|
+
.toString()
|
|
197
|
+
.trim()) === 1;
|
|
196
198
|
}
|
|
197
199
|
catch {
|
|
198
200
|
// This would fail if yarn is not installed which is okay
|
|
@@ -204,14 +206,14 @@ function setupYarn(options) {
|
|
|
204
206
|
const scopeName = scope ? `${scope}:` : '';
|
|
205
207
|
yarnRegistryPaths.push((0, child_process_1.execSync)(`yarn config get ${scopeName}${registryConfigName}`, {
|
|
206
208
|
env,
|
|
207
|
-
windowsHide:
|
|
209
|
+
windowsHide: false,
|
|
208
210
|
})
|
|
209
211
|
?.toString()
|
|
210
212
|
?.trim()
|
|
211
213
|
?.replace('\u001b[2K\u001b[1G', '') // strip out ansi codes
|
|
212
214
|
);
|
|
213
215
|
(0, child_process_1.execSync)(`yarn config set ${scopeName}${registryConfigName} http://localhost:${options.port}/` +
|
|
214
|
-
(options.location === 'user' ? ' --home' : ''), { env, windowsHide:
|
|
216
|
+
(options.location === 'user' ? ' --home' : ''), { env, windowsHide: false });
|
|
215
217
|
devkit_1.logger.info(`Set yarn ${scopeName}registry to http://localhost:${options.port}/`);
|
|
216
218
|
});
|
|
217
219
|
const currentWhitelist = getYarnUnsafeHttpWhitelist(isYarnV1);
|
|
@@ -224,7 +226,7 @@ function setupYarn(options) {
|
|
|
224
226
|
}
|
|
225
227
|
return () => {
|
|
226
228
|
try {
|
|
227
|
-
const currentYarnRegistryPath = (0, child_process_1.execSync)(`yarn config get ${registryConfigName}`, { env, windowsHide:
|
|
229
|
+
const currentYarnRegistryPath = (0, child_process_1.execSync)(`yarn config get ${registryConfigName}`, { env, windowsHide: false })
|
|
228
230
|
?.toString()
|
|
229
231
|
?.trim()
|
|
230
232
|
?.replace('\u001b[2K\u001b[1G', ''); // strip out ansi codes
|
|
@@ -237,13 +239,13 @@ function setupYarn(options) {
|
|
|
237
239
|
(0, child_process_1.execSync)(`yarn config set ${registryName} ${yarnRegistryPaths[index]}` +
|
|
238
240
|
(options.location === 'user' ? ' --home' : ''), {
|
|
239
241
|
env,
|
|
240
|
-
windowsHide:
|
|
242
|
+
windowsHide: false,
|
|
241
243
|
});
|
|
242
244
|
devkit_1.logger.info(`Reset yarn ${registryName} to ${yarnRegistryPaths[index]}`);
|
|
243
245
|
}
|
|
244
246
|
else {
|
|
245
247
|
(0, child_process_1.execSync)(`yarn config ${isYarnV1 ? 'delete' : 'unset'} ${registryName}` +
|
|
246
|
-
(options.location === 'user' ? ' --home' : ''), { env, windowsHide:
|
|
248
|
+
(options.location === 'user' ? ' --home' : ''), { env, windowsHide: false });
|
|
247
249
|
devkit_1.logger.info(`Cleared custom yarn ${registryConfigName}`);
|
|
248
250
|
}
|
|
249
251
|
});
|
|
@@ -121,7 +121,7 @@ To fix this you will either need to add a package.json file at that location, or
|
|
|
121
121
|
// Must be non-blocking async to allow spinner to render
|
|
122
122
|
currentVersion = await new Promise((resolve, reject) => {
|
|
123
123
|
(0, node_child_process_1.exec)(`npm view ${packageName} version --"${registryConfigKey}=${registry}" --tag=${tag}`, {
|
|
124
|
-
windowsHide:
|
|
124
|
+
windowsHide: false,
|
|
125
125
|
}, (error, stdout, stderr) => {
|
|
126
126
|
if (error) {
|
|
127
127
|
return reject(error);
|
|
@@ -10,7 +10,7 @@ async function setupVerdaccio(tree, options) {
|
|
|
10
10
|
if (!tree.exists('.verdaccio/config.yml')) {
|
|
11
11
|
(0, devkit_1.generateFiles)(tree, path.join(__dirname, 'files'), '.verdaccio', {
|
|
12
12
|
npmUplinkRegistry: (0, child_process_1.execSync)('npm config get registry', {
|
|
13
|
-
windowsHide:
|
|
13
|
+
windowsHide: false,
|
|
14
14
|
})
|
|
15
15
|
?.toString()
|
|
16
16
|
?.trim() ?? 'https://registry.npmjs.org',
|
|
@@ -30,28 +30,35 @@ async function syncGenerator(tree) {
|
|
|
30
30
|
`The "${plugin_1.PLUGIN_NAME}" plugin must be added to the "plugins" array in "nx.json" in order to sync the project graph information to the TypeScript configuration files.`,
|
|
31
31
|
]);
|
|
32
32
|
}
|
|
33
|
+
const tsconfigInfoCaches = {
|
|
34
|
+
composite: new Map(),
|
|
35
|
+
content: new Map(),
|
|
36
|
+
exists: new Map(),
|
|
37
|
+
isFile: new Map(),
|
|
38
|
+
};
|
|
33
39
|
// Root tsconfig containing project references for the whole workspace
|
|
34
40
|
const rootTsconfigPath = 'tsconfig.json';
|
|
35
|
-
if (!tree
|
|
41
|
+
if (!tsconfigExists(tree, tsconfigInfoCaches, rootTsconfigPath)) {
|
|
36
42
|
throw new sync_generators_1.SyncError('Missing root "tsconfig.json"', [
|
|
37
43
|
`A "tsconfig.json" file must exist in the workspace root in order to sync the project graph information to the TypeScript configuration files.`,
|
|
38
44
|
]);
|
|
39
45
|
}
|
|
40
|
-
const
|
|
41
|
-
const stringifiedRootJsonContents = readRawTsconfigContents(tree, rawTsconfigContentsCache, rootTsconfigPath);
|
|
46
|
+
const stringifiedRootJsonContents = readRawTsconfigContents(tree, tsconfigInfoCaches, rootTsconfigPath);
|
|
42
47
|
const rootTsconfig = (0, devkit_1.parseJson)(stringifiedRootJsonContents);
|
|
43
48
|
const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
|
|
44
49
|
const projectRoots = new Set();
|
|
45
|
-
const tsconfigHasCompositeEnabledCache = new Map();
|
|
46
50
|
const tsconfigProjectNodeValues = Object.values(projectGraph.nodes).filter((node) => {
|
|
47
51
|
projectRoots.add(node.data.root);
|
|
48
52
|
const projectTsconfigPath = (0, devkit_1.joinPathFragments)(node.data.root, 'tsconfig.json');
|
|
49
|
-
return tsconfigExists(tree,
|
|
53
|
+
return tsconfigExists(tree, tsconfigInfoCaches, projectTsconfigPath);
|
|
50
54
|
});
|
|
51
55
|
const tsSysFromTree = {
|
|
52
56
|
...ts.sys,
|
|
57
|
+
fileExists(path) {
|
|
58
|
+
return tsconfigExists(tree, tsconfigInfoCaches, path);
|
|
59
|
+
},
|
|
53
60
|
readFile(path) {
|
|
54
|
-
return readRawTsconfigContents(tree,
|
|
61
|
+
return readRawTsconfigContents(tree, tsconfigInfoCaches, path);
|
|
55
62
|
},
|
|
56
63
|
};
|
|
57
64
|
// Track if any changes were made to the tsconfig files. We check the changes
|
|
@@ -63,8 +70,8 @@ async function syncGenerator(tree) {
|
|
|
63
70
|
const referencesSet = new Set();
|
|
64
71
|
for (const ref of rootTsconfig.references ?? []) {
|
|
65
72
|
// reference path is relative to the tsconfig file
|
|
66
|
-
const resolvedRefPath = getTsConfigPathFromReferencePath(tree, rootTsconfigPath, ref.path);
|
|
67
|
-
if (tsconfigExists(tree,
|
|
73
|
+
const resolvedRefPath = getTsConfigPathFromReferencePath(tree, rootTsconfigPath, ref.path, tsconfigInfoCaches);
|
|
74
|
+
if (tsconfigExists(tree, tsconfigInfoCaches, resolvedRefPath)) {
|
|
68
75
|
// we only keep the references that still exist
|
|
69
76
|
referencesSet.add(normalizeReferencePath(ref.path));
|
|
70
77
|
}
|
|
@@ -83,11 +90,11 @@ async function syncGenerator(tree) {
|
|
|
83
90
|
if (hasChanges) {
|
|
84
91
|
const updatedReferences = Array.from(referencesSet)
|
|
85
92
|
// Check composite is true in the internal reference before proceeding
|
|
86
|
-
.filter((ref) => hasCompositeEnabled(tsSysFromTree,
|
|
93
|
+
.filter((ref) => hasCompositeEnabled(tsSysFromTree, tsconfigInfoCaches, (0, devkit_1.joinPathFragments)(ref, 'tsconfig.json')))
|
|
87
94
|
.map((ref) => ({
|
|
88
95
|
path: `./${ref}`,
|
|
89
96
|
}));
|
|
90
|
-
patchTsconfigJsonReferences(tree,
|
|
97
|
+
patchTsconfigJsonReferences(tree, tsconfigInfoCaches, rootTsconfigPath, updatedReferences);
|
|
91
98
|
}
|
|
92
99
|
}
|
|
93
100
|
const userOptions = nxJson.sync?.generatorOptions?.['@nx/js:typescript-sync'];
|
|
@@ -105,7 +112,7 @@ async function syncGenerator(tree) {
|
|
|
105
112
|
const sourceProjectNode = projectGraph.nodes[projectName];
|
|
106
113
|
// Find the relevant tsconfig file for the source project
|
|
107
114
|
const sourceProjectTsconfigPath = (0, devkit_1.joinPathFragments)(sourceProjectNode.data.root, 'tsconfig.json');
|
|
108
|
-
if (!tsconfigExists(tree,
|
|
115
|
+
if (!tsconfigExists(tree, tsconfigInfoCaches, sourceProjectTsconfigPath)) {
|
|
109
116
|
if (process.env.NX_VERBOSE_LOGGING === 'true') {
|
|
110
117
|
devkit_1.logger.warn(`Skipping project "${projectName}" as there is no tsconfig.json file found in the project root "${sourceProjectNode.data.root}".`);
|
|
111
118
|
}
|
|
@@ -115,16 +122,16 @@ async function syncGenerator(tree) {
|
|
|
115
122
|
const dependencies = collectProjectDependencies(tree, projectName, projectGraph, collectedDependencies);
|
|
116
123
|
for (const runtimeTsConfigFileName of runtimeTsConfigFileNames) {
|
|
117
124
|
const runtimeTsConfigPath = (0, devkit_1.joinPathFragments)(sourceProjectNode.data.root, runtimeTsConfigFileName);
|
|
118
|
-
if (!tsconfigExists(tree,
|
|
125
|
+
if (!tsconfigExists(tree, tsconfigInfoCaches, runtimeTsConfigPath)) {
|
|
119
126
|
continue;
|
|
120
127
|
}
|
|
121
128
|
// Update project references for the runtime tsconfig
|
|
122
129
|
hasChanges =
|
|
123
|
-
updateTsConfigReferences(tree, tsSysFromTree,
|
|
130
|
+
updateTsConfigReferences(tree, tsSysFromTree, tsconfigInfoCaches, runtimeTsConfigPath, dependencies, sourceProjectNode.data.root, projectRoots, runtimeTsConfigFileName, runtimeTsConfigFileNames) || hasChanges;
|
|
124
131
|
}
|
|
125
132
|
// Update project references for the tsconfig.json file
|
|
126
133
|
hasChanges =
|
|
127
|
-
updateTsConfigReferences(tree, tsSysFromTree,
|
|
134
|
+
updateTsConfigReferences(tree, tsSysFromTree, tsconfigInfoCaches, sourceProjectTsconfigPath, dependencies, sourceProjectNode.data.root, projectRoots) || hasChanges;
|
|
128
135
|
}
|
|
129
136
|
if (hasChanges) {
|
|
130
137
|
await (0, devkit_1.formatFiles)(tree);
|
|
@@ -138,23 +145,24 @@ exports.default = syncGenerator;
|
|
|
138
145
|
* Within the context of a sync generator, performance is a key concern,
|
|
139
146
|
* so avoid FS interactions whenever possible.
|
|
140
147
|
*/
|
|
141
|
-
function readRawTsconfigContents(tree,
|
|
142
|
-
if (!
|
|
143
|
-
|
|
148
|
+
function readRawTsconfigContents(tree, tsconfigInfoCaches, tsconfigPath) {
|
|
149
|
+
if (!tsconfigInfoCaches.content.has(tsconfigPath)) {
|
|
150
|
+
tsconfigInfoCaches.content.set(tsconfigPath, tree.read(tsconfigPath, 'utf-8'));
|
|
144
151
|
}
|
|
145
|
-
return
|
|
152
|
+
return tsconfigInfoCaches.content.get(tsconfigPath);
|
|
146
153
|
}
|
|
147
154
|
/**
|
|
148
155
|
* Within the context of a sync generator, performance is a key concern,
|
|
149
156
|
* so avoid FS interactions whenever possible.
|
|
150
157
|
*/
|
|
151
|
-
function tsconfigExists(tree,
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
158
|
+
function tsconfigExists(tree, tsconfigInfoCaches, tsconfigPath) {
|
|
159
|
+
if (!tsconfigInfoCaches.exists.has(tsconfigPath)) {
|
|
160
|
+
tsconfigInfoCaches.exists.set(tsconfigPath, tree.exists(tsconfigPath));
|
|
161
|
+
}
|
|
162
|
+
return tsconfigInfoCaches.exists.get(tsconfigPath);
|
|
155
163
|
}
|
|
156
|
-
function updateTsConfigReferences(tree, tsSysFromTree,
|
|
157
|
-
const stringifiedJsonContents = readRawTsconfigContents(tree,
|
|
164
|
+
function updateTsConfigReferences(tree, tsSysFromTree, tsconfigInfoCaches, tsConfigPath, dependencies, projectRoot, projectRoots, runtimeTsConfigFileName, possibleRuntimeTsConfigFileNames) {
|
|
165
|
+
const stringifiedJsonContents = readRawTsconfigContents(tree, tsconfigInfoCaches, tsConfigPath);
|
|
158
166
|
const tsConfig = (0, devkit_1.parseJson)(stringifiedJsonContents);
|
|
159
167
|
const ignoredReferences = new Set(tsConfig.nx?.sync?.ignoredReferences ?? []);
|
|
160
168
|
// We have at least one dependency so we can safely set it to an empty array if not already set
|
|
@@ -171,8 +179,8 @@ function updateTsConfigReferences(tree, tsSysFromTree, rawTsconfigContentsCache,
|
|
|
171
179
|
continue;
|
|
172
180
|
}
|
|
173
181
|
// reference path is relative to the tsconfig file
|
|
174
|
-
const resolvedRefPath = getTsConfigPathFromReferencePath(tree, tsConfigPath, ref.path);
|
|
175
|
-
if (isProjectReferenceWithinNxProject(tree,
|
|
182
|
+
const resolvedRefPath = getTsConfigPathFromReferencePath(tree, tsConfigPath, ref.path, tsconfigInfoCaches);
|
|
183
|
+
if (isProjectReferenceWithinNxProject(tree, tsconfigInfoCaches, resolvedRefPath, projectRoot, projectRoots) ||
|
|
176
184
|
isProjectReferenceIgnored(tree, resolvedRefPath)) {
|
|
177
185
|
// we keep all references within the current Nx project or that are ignored
|
|
178
186
|
references.push(ref);
|
|
@@ -185,9 +193,9 @@ function updateTsConfigReferences(tree, tsSysFromTree, rawTsconfigContentsCache,
|
|
|
185
193
|
let referencePath = dep.data.root;
|
|
186
194
|
if (runtimeTsConfigFileName) {
|
|
187
195
|
const runtimeTsConfigPath = (0, devkit_1.joinPathFragments)(dep.data.root, runtimeTsConfigFileName);
|
|
188
|
-
if (tsconfigExists(tree,
|
|
196
|
+
if (tsconfigExists(tree, tsconfigInfoCaches, runtimeTsConfigPath)) {
|
|
189
197
|
// Check composite is true in the dependency runtime tsconfig file before proceeding
|
|
190
|
-
if (!hasCompositeEnabled(tsSysFromTree,
|
|
198
|
+
if (!hasCompositeEnabled(tsSysFromTree, tsconfigInfoCaches, runtimeTsConfigPath)) {
|
|
191
199
|
continue;
|
|
192
200
|
}
|
|
193
201
|
referencePath = runtimeTsConfigPath;
|
|
@@ -198,9 +206,9 @@ function updateTsConfigReferences(tree, tsSysFromTree, rawTsconfigContentsCache,
|
|
|
198
206
|
for (const possibleRuntimeTsConfigFileName of possibleRuntimeTsConfigFileNames ??
|
|
199
207
|
[]) {
|
|
200
208
|
const possibleRuntimeTsConfigPath = (0, devkit_1.joinPathFragments)(dep.data.root, possibleRuntimeTsConfigFileName);
|
|
201
|
-
if (tsconfigExists(tree,
|
|
209
|
+
if (tsconfigExists(tree, tsconfigInfoCaches, possibleRuntimeTsConfigPath)) {
|
|
202
210
|
// Check composite is true in the dependency runtime tsconfig file before proceeding
|
|
203
|
-
if (!hasCompositeEnabled(tsSysFromTree,
|
|
211
|
+
if (!hasCompositeEnabled(tsSysFromTree, tsconfigInfoCaches, possibleRuntimeTsConfigPath)) {
|
|
204
212
|
continue;
|
|
205
213
|
}
|
|
206
214
|
referencePath = possibleRuntimeTsConfigPath;
|
|
@@ -211,7 +219,7 @@ function updateTsConfigReferences(tree, tsSysFromTree, rawTsconfigContentsCache,
|
|
|
211
219
|
}
|
|
212
220
|
else {
|
|
213
221
|
// Check composite is true in the dependency tsconfig.json file before proceeding
|
|
214
|
-
if (!hasCompositeEnabled(tsSysFromTree,
|
|
222
|
+
if (!hasCompositeEnabled(tsSysFromTree, tsconfigInfoCaches, (0, devkit_1.joinPathFragments)(dep.data.root, 'tsconfig.json'))) {
|
|
215
223
|
continue;
|
|
216
224
|
}
|
|
217
225
|
}
|
|
@@ -227,7 +235,7 @@ function updateTsConfigReferences(tree, tsSysFromTree, rawTsconfigContentsCache,
|
|
|
227
235
|
}
|
|
228
236
|
hasChanges ||= newReferencesSet.size !== originalReferencesSet.size;
|
|
229
237
|
if (hasChanges) {
|
|
230
|
-
patchTsconfigJsonReferences(tree,
|
|
238
|
+
patchTsconfigJsonReferences(tree, tsconfigInfoCaches, tsConfigPath, references);
|
|
231
239
|
}
|
|
232
240
|
return hasChanges;
|
|
233
241
|
}
|
|
@@ -273,8 +281,8 @@ function normalizeReferencePath(path) {
|
|
|
273
281
|
.replace(/\/tsconfig.json$/, '')
|
|
274
282
|
.replace(/^\.\//, '');
|
|
275
283
|
}
|
|
276
|
-
function isProjectReferenceWithinNxProject(tree,
|
|
277
|
-
let currentPath = getTsConfigDirName(tree,
|
|
284
|
+
function isProjectReferenceWithinNxProject(tree, tsconfigInfoCaches, refTsConfigPath, projectRoot, projectRoots) {
|
|
285
|
+
let currentPath = getTsConfigDirName(tree, tsconfigInfoCaches, refTsConfigPath);
|
|
278
286
|
if ((0, posix_1.relative)(projectRoot, currentPath).startsWith('..')) {
|
|
279
287
|
// it's outside of the project root, so it's an external project reference
|
|
280
288
|
return false;
|
|
@@ -300,16 +308,14 @@ function isProjectReferenceIgnored(tree, refTsConfigPath) {
|
|
|
300
308
|
}
|
|
301
309
|
return ig.ignores(refTsConfigPath);
|
|
302
310
|
}
|
|
303
|
-
function getTsConfigDirName(tree,
|
|
304
|
-
return (
|
|
305
|
-
? true
|
|
306
|
-
: tree.isFile(tsConfigPath))
|
|
311
|
+
function getTsConfigDirName(tree, tsconfigInfoCaches, tsConfigPath) {
|
|
312
|
+
return tsconfigIsFile(tree, tsconfigInfoCaches, tsConfigPath)
|
|
307
313
|
? (0, posix_1.dirname)(tsConfigPath)
|
|
308
314
|
: (0, posix_1.normalize)(tsConfigPath);
|
|
309
315
|
}
|
|
310
|
-
function getTsConfigPathFromReferencePath(tree, ownerTsConfigPath, referencePath) {
|
|
316
|
+
function getTsConfigPathFromReferencePath(tree, ownerTsConfigPath, referencePath, tsconfigInfoCaches) {
|
|
311
317
|
const resolvedRefPath = (0, devkit_1.joinPathFragments)((0, posix_1.dirname)(ownerTsConfigPath), referencePath);
|
|
312
|
-
return tree
|
|
318
|
+
return tsconfigIsFile(tree, tsconfigInfoCaches, resolvedRefPath)
|
|
313
319
|
? resolvedRefPath
|
|
314
320
|
: (0, devkit_1.joinPathFragments)(resolvedRefPath, 'tsconfig.json');
|
|
315
321
|
}
|
|
@@ -317,18 +323,29 @@ function getTsConfigPathFromReferencePath(tree, ownerTsConfigPath, referencePath
|
|
|
317
323
|
* Minimally patch just the "references" property within the tsconfig file at a given path.
|
|
318
324
|
* This allows comments in other sections of the file to remain intact when syncing is run.
|
|
319
325
|
*/
|
|
320
|
-
function patchTsconfigJsonReferences(tree,
|
|
321
|
-
const stringifiedJsonContents = readRawTsconfigContents(tree,
|
|
326
|
+
function patchTsconfigJsonReferences(tree, tsconfigInfoCaches, tsconfigPath, updatedReferences) {
|
|
327
|
+
const stringifiedJsonContents = readRawTsconfigContents(tree, tsconfigInfoCaches, tsconfigPath);
|
|
322
328
|
const edits = (0, jsonc_parser_1.modify)(stringifiedJsonContents, ['references'], updatedReferences, {});
|
|
323
329
|
const updatedJsonContents = (0, jsonc_parser_1.applyEdits)(stringifiedJsonContents, edits);
|
|
324
330
|
// The final contents will be formatted by formatFiles() later
|
|
325
331
|
tree.write(tsconfigPath, updatedJsonContents);
|
|
326
332
|
}
|
|
327
|
-
function hasCompositeEnabled(tsSysFromTree,
|
|
328
|
-
if (!
|
|
333
|
+
function hasCompositeEnabled(tsSysFromTree, tsconfigInfoCaches, tsconfigPath) {
|
|
334
|
+
if (!tsconfigInfoCaches.composite.has(tsconfigPath)) {
|
|
329
335
|
const parsed = ts.parseJsonConfigFileContent(ts.readConfigFile(tsconfigPath, tsSysFromTree.readFile).config, tsSysFromTree, (0, posix_1.dirname)(tsconfigPath));
|
|
330
|
-
|
|
331
|
-
|
|
336
|
+
tsconfigInfoCaches.composite.set(tsconfigPath, parsed.options.composite === true);
|
|
337
|
+
}
|
|
338
|
+
return tsconfigInfoCaches.composite.get(tsconfigPath);
|
|
339
|
+
}
|
|
340
|
+
function tsconfigIsFile(tree, tsconfigInfoCaches, tsconfigPath) {
|
|
341
|
+
if (tsconfigInfoCaches.isFile.has(tsconfigPath)) {
|
|
342
|
+
return tsconfigInfoCaches.isFile.get(tsconfigPath);
|
|
343
|
+
}
|
|
344
|
+
if (tsconfigInfoCaches.content.has(tsconfigPath)) {
|
|
345
|
+
// if it has content, it's a file
|
|
346
|
+
tsconfigInfoCaches.isFile.set(tsconfigPath, true);
|
|
347
|
+
return true;
|
|
332
348
|
}
|
|
333
|
-
|
|
349
|
+
tsconfigInfoCaches.isFile.set(tsconfigPath, tree.isFile(tsconfigPath));
|
|
350
|
+
return tsconfigInfoCaches.isFile.get(tsconfigPath);
|
|
334
351
|
}
|
|
@@ -28,7 +28,7 @@ function startLocalRegistry({ localRegistryTarget, storage, verbose, clearStorag
|
|
|
28
28
|
const registry = `http://localhost:${port}`;
|
|
29
29
|
process.env.npm_config_registry = registry;
|
|
30
30
|
(0, child_process_1.execSync)(`npm config set //localhost:${port}/:_authToken "secretVerdaccioToken"`, {
|
|
31
|
-
windowsHide:
|
|
31
|
+
windowsHide: false,
|
|
32
32
|
});
|
|
33
33
|
// yarnv1
|
|
34
34
|
process.env.YARN_REGISTRY = registry;
|
|
@@ -39,7 +39,7 @@ function startLocalRegistry({ localRegistryTarget, storage, verbose, clearStorag
|
|
|
39
39
|
resolve(() => {
|
|
40
40
|
childProcess.kill();
|
|
41
41
|
(0, child_process_1.execSync)(`npm config delete //localhost:${port}/:_authToken`, {
|
|
42
|
-
windowsHide:
|
|
42
|
+
windowsHide: false,
|
|
43
43
|
});
|
|
44
44
|
});
|
|
45
45
|
childProcess?.stdout?.off('data', listener);
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createNodes = exports.createNodesV2 = exports.PLUGIN_NAME = exports.createDependencies = void 0;
|
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
|
5
|
-
const calculate_hash_for_create_nodes_1 = require("@nx/devkit/src/utils/calculate-hash-for-create-nodes");
|
|
6
5
|
const get_named_inputs_1 = require("@nx/devkit/src/utils/get-named-inputs");
|
|
7
6
|
const minimatch_1 = require("minimatch");
|
|
8
7
|
const node_fs_1 = require("node:fs");
|
|
@@ -37,8 +36,9 @@ exports.createNodesV2 = [
|
|
|
37
36
|
const cachePath = (0, node_path_1.join)(cache_directory_1.workspaceDataDirectory, `tsc-${optionsHash}.hash`);
|
|
38
37
|
const targetsCache = readTargetsCache(cachePath);
|
|
39
38
|
const normalizedOptions = normalizePluginOptions(options);
|
|
39
|
+
const lockFileName = (0, lock_file_1.getLockFileName)((0, devkit_1.detectPackageManager)(context.workspaceRoot));
|
|
40
40
|
try {
|
|
41
|
-
return await (0, devkit_1.createNodesFromFiles)((configFile, options, context) => createNodesInternal(configFile, options, context, targetsCache), configFilePaths, normalizedOptions, context);
|
|
41
|
+
return await (0, devkit_1.createNodesFromFiles)((configFile, options, context) => createNodesInternal(configFile, options, context, lockFileName, targetsCache), configFilePaths, normalizedOptions, context);
|
|
42
42
|
}
|
|
43
43
|
finally {
|
|
44
44
|
writeTargetsToCache(cachePath, targetsCache);
|
|
@@ -50,10 +50,11 @@ exports.createNodes = [
|
|
|
50
50
|
async (configFilePath, options, context) => {
|
|
51
51
|
devkit_1.logger.warn('`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will change to the createNodesV2 API.');
|
|
52
52
|
const normalizedOptions = normalizePluginOptions(options);
|
|
53
|
-
|
|
53
|
+
const lockFileName = (0, lock_file_1.getLockFileName)((0, devkit_1.detectPackageManager)(context.workspaceRoot));
|
|
54
|
+
return createNodesInternal(configFilePath, normalizedOptions, context, lockFileName, {});
|
|
54
55
|
},
|
|
55
56
|
];
|
|
56
|
-
async function createNodesInternal(configFilePath, options, context, targetsCache) {
|
|
57
|
+
async function createNodesInternal(configFilePath, options, context, lockFileName, targetsCache) {
|
|
57
58
|
const projectRoot = (0, node_path_1.dirname)(configFilePath);
|
|
58
59
|
const fullConfigPath = (0, devkit_1.joinPathFragments)(context.workspaceRoot, configFilePath);
|
|
59
60
|
// Do not create a project for the workspace root tsconfig files.
|
|
@@ -71,8 +72,20 @@ async function createNodesInternal(configFilePath, options, context, targetsCach
|
|
|
71
72
|
!siblingFiles.includes('tsconfig.json')) {
|
|
72
73
|
return {};
|
|
73
74
|
}
|
|
74
|
-
|
|
75
|
-
|
|
75
|
+
/**
|
|
76
|
+
* The cache key is composed by:
|
|
77
|
+
* - hashes of the content of the relevant files that can affect what's inferred by the plugin:
|
|
78
|
+
* - current config file
|
|
79
|
+
* - config files extended by the current config file (recursively up to the root config file)
|
|
80
|
+
* - lock file
|
|
81
|
+
* - hash of the plugin options
|
|
82
|
+
* - current config file path
|
|
83
|
+
*/
|
|
84
|
+
const extendedConfigFiles = getExtendedConfigFiles(fullConfigPath, readCachedTsConfig(fullConfigPath));
|
|
85
|
+
const nodeHash = (0, file_hasher_1.hashArray)([
|
|
86
|
+
...[configFilePath, ...extendedConfigFiles, lockFileName].map(file_hasher_1.hashFile),
|
|
87
|
+
(0, file_hasher_1.hashObject)(options),
|
|
88
|
+
]);
|
|
76
89
|
const cacheKey = `${nodeHash}_${configFilePath}`;
|
|
77
90
|
targetsCache[cacheKey] ??= buildTscTargets(fullConfigPath, projectRoot, options, context);
|
|
78
91
|
const { targets } = targetsCache[cacheKey];
|
package/src/utils/npm-config.js
CHANGED
|
@@ -76,7 +76,7 @@ async function getNpmConfigValue(key, cwd) {
|
|
|
76
76
|
async function execAsync(command, cwd) {
|
|
77
77
|
// Must be non-blocking async to allow spinner to render
|
|
78
78
|
return new Promise((resolve, reject) => {
|
|
79
|
-
(0, child_process_1.exec)(command, { cwd, windowsHide:
|
|
79
|
+
(0, child_process_1.exec)(command, { cwd, windowsHide: false }, (error, stdout, stderr) => {
|
|
80
80
|
if (error) {
|
|
81
81
|
return reject(error);
|
|
82
82
|
}
|
|
@@ -62,7 +62,7 @@ async function compileSwc(context, normalizedOptions, postCompilationCallback) {
|
|
|
62
62
|
const swcCmdLog = (0, node_child_process_1.execSync)(getSwcCmd(normalizedOptions), {
|
|
63
63
|
encoding: 'utf8',
|
|
64
64
|
cwd: normalizedOptions.swcCliOptions.swcCwd,
|
|
65
|
-
windowsHide:
|
|
65
|
+
windowsHide: false,
|
|
66
66
|
});
|
|
67
67
|
devkit_1.logger.log(swcCmdLog.replace(/\n/, ''));
|
|
68
68
|
const isCompileSuccess = swcCmdLog.includes('Successfully compiled');
|
|
@@ -99,7 +99,7 @@ async function* compileSwcWatch(context, normalizedOptions, postCompilationCallb
|
|
|
99
99
|
let watcherOnExit;
|
|
100
100
|
const swcWatcher = (0, node_child_process_1.exec)(getSwcCmd(normalizedOptions, true), {
|
|
101
101
|
cwd: normalizedOptions.swcCliOptions.swcCwd,
|
|
102
|
-
windowsHide:
|
|
102
|
+
windowsHide: false,
|
|
103
103
|
});
|
|
104
104
|
processOnExit = () => {
|
|
105
105
|
swcWatcher.kill();
|