@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/js",
3
- "version": "20.0.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.0",
43
- "@nx/workspace": "20.0.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: true,
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: true,
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: true,
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: true,
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: true,
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: true,
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: true });
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: true })
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: true });
133
- (0, child_process_1.execSync)(`npm config set //localhost:${options.port}/:_authToken="secretVerdaccioToken" --location ${options.location}`, { env, windowsHide: true });
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: true })
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: true });
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: true,
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: true });
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: true,
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: true });
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: true });
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: true }).toString().trim()) === 1;
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: true,
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: true });
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: true })
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: true,
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: true });
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: true,
124
+ windowsHide: false,
125
125
  }, (error, stdout, stderr) => {
126
126
  if (error) {
127
127
  return reject(error);
@@ -89,7 +89,7 @@ function execLockFileUpdate(command, cwd, env = {}) {
89
89
  ...process.env,
90
90
  ...env,
91
91
  },
92
- windowsHide: true,
92
+ windowsHide: false,
93
93
  });
94
94
  }
95
95
  catch (e) {
@@ -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: true,
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.exists(rootTsconfigPath)) {
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 rawTsconfigContentsCache = new Map();
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, rawTsconfigContentsCache, projectTsconfigPath);
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, rawTsconfigContentsCache, path);
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, rawTsconfigContentsCache, resolvedRefPath)) {
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, tsconfigHasCompositeEnabledCache, (0, devkit_1.joinPathFragments)(ref, 'tsconfig.json')))
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, rawTsconfigContentsCache, rootTsconfigPath, updatedReferences);
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, rawTsconfigContentsCache, sourceProjectTsconfigPath)) {
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, rawTsconfigContentsCache, runtimeTsConfigPath)) {
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, rawTsconfigContentsCache, tsconfigHasCompositeEnabledCache, runtimeTsConfigPath, dependencies, sourceProjectNode.data.root, projectRoots, runtimeTsConfigFileName, runtimeTsConfigFileNames) || hasChanges;
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, rawTsconfigContentsCache, tsconfigHasCompositeEnabledCache, sourceProjectTsconfigPath, dependencies, sourceProjectNode.data.root, projectRoots) || hasChanges;
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, rawTsconfigContentsCache, tsconfigPath) {
142
- if (!rawTsconfigContentsCache.has(tsconfigPath)) {
143
- rawTsconfigContentsCache.set(tsconfigPath, tree.read(tsconfigPath, 'utf-8'));
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 rawTsconfigContentsCache.get(tsconfigPath);
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, rawTsconfigContentsCache, tsconfigPath) {
152
- return rawTsconfigContentsCache.has(tsconfigPath)
153
- ? true
154
- : tree.exists(tsconfigPath);
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, rawTsconfigContentsCache, tsconfigHasCompositeEnabledCache, tsConfigPath, dependencies, projectRoot, projectRoots, runtimeTsConfigFileName, possibleRuntimeTsConfigFileNames) {
157
- const stringifiedJsonContents = readRawTsconfigContents(tree, rawTsconfigContentsCache, tsConfigPath);
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, rawTsconfigContentsCache, resolvedRefPath, projectRoot, projectRoots) ||
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, rawTsconfigContentsCache, runtimeTsConfigPath)) {
196
+ if (tsconfigExists(tree, tsconfigInfoCaches, runtimeTsConfigPath)) {
189
197
  // Check composite is true in the dependency runtime tsconfig file before proceeding
190
- if (!hasCompositeEnabled(tsSysFromTree, tsconfigHasCompositeEnabledCache, runtimeTsConfigPath)) {
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, rawTsconfigContentsCache, possibleRuntimeTsConfigPath)) {
209
+ if (tsconfigExists(tree, tsconfigInfoCaches, possibleRuntimeTsConfigPath)) {
202
210
  // Check composite is true in the dependency runtime tsconfig file before proceeding
203
- if (!hasCompositeEnabled(tsSysFromTree, tsconfigHasCompositeEnabledCache, possibleRuntimeTsConfigPath)) {
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, tsconfigHasCompositeEnabledCache, (0, devkit_1.joinPathFragments)(dep.data.root, 'tsconfig.json'))) {
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, rawTsconfigContentsCache, tsConfigPath, references);
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, rawTsconfigContentsCache, refTsConfigPath, projectRoot, projectRoots) {
277
- let currentPath = getTsConfigDirName(tree, rawTsconfigContentsCache, refTsConfigPath);
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, rawTsconfigContentsCache, tsConfigPath) {
304
- return (rawTsconfigContentsCache.has(tsConfigPath)
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.isFile(resolvedRefPath)
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, rawTsconfigContentsCache, tsconfigPath, updatedReferences) {
321
- const stringifiedJsonContents = readRawTsconfigContents(tree, rawTsconfigContentsCache, tsconfigPath);
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, tsconfigHasCompositeEnabledCache, tsconfigPath) {
328
- if (!tsconfigHasCompositeEnabledCache.has(tsconfigPath)) {
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
- const enabledVal = parsed.options.composite === true;
331
- tsconfigHasCompositeEnabledCache.set(tsconfigPath, enabledVal);
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
- return tsconfigHasCompositeEnabledCache.get(tsconfigPath);
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: true,
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: true,
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
- return createNodesInternal(configFilePath, normalizedOptions, context, {});
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
- const nodeHash = await (0, calculate_hash_for_create_nodes_1.calculateHashForCreateNodes)(projectRoot, options, context, [(0, lock_file_1.getLockFileName)((0, devkit_1.detectPackageManager)(context.workspaceRoot))]);
75
- // The hash is calculated at the node/project level, so we add the config file path to avoid conflicts when caching
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];
@@ -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: true }, (error, stdout, stderr) => {
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: true,
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: true,
102
+ windowsHide: false,
103
103
  });
104
104
  processOnExit = () => {
105
105
  swcWatcher.kill();