@nx/js 22.1.0-beta.7 → 22.1.0-beta.8

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": "22.1.0-beta.7",
3
+ "version": "22.1.0-beta.8",
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": "22.1.0-beta.7",
43
- "@nx/workspace": "22.1.0-beta.7",
42
+ "@nx/devkit": "22.1.0-beta.8",
43
+ "@nx/workspace": "22.1.0-beta.8",
44
44
  "@zkochan/js-yaml": "0.0.7",
45
45
  "babel-plugin-const-enum": "^1.0.1",
46
46
  "babel-plugin-macros": "^3.1.0",
@@ -60,7 +60,7 @@
60
60
  "tslib": "^2.3.0"
61
61
  },
62
62
  "devDependencies": {
63
- "nx": "22.1.0-beta.7"
63
+ "nx": "22.1.0-beta.8"
64
64
  },
65
65
  "peerDependencies": {
66
66
  "verdaccio": "^6.0.5"
@@ -1 +1 @@
1
- {"version":3,"file":"library.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/generators/library/library.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,iBAAiB,EAYjB,IAAI,EAKL,MAAM,YAAY,CAAC;AAyCpB,OAAO,KAAK,EAEV,sBAAsB,EACtB,iCAAiC,EAClC,MAAM,UAAU,CAAC;AASlB,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,sBAAsB,8BAO/B;AAED,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,sBAAsB,8BA6K/B;AA2HD,MAAM,MAAM,cAAc,GAAG,IAAI,CAC/B,iCAAiC,EAC/B,MAAM,GACN,QAAQ,GACR,aAAa,GACb,gBAAgB,GAChB,IAAI,GACJ,yBAAyB,GACzB,aAAa,GACb,SAAS,GACT,WAAW,GACX,yBAAyB,CAC5B,CAAC;AAEF,wBAAsB,OAAO,CAC3B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,iBAAiB,CAAC,CA4G5B;AA6uBD,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"library.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/generators/library/library.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,iBAAiB,EAUjB,IAAI,EAKL,MAAM,YAAY,CAAC;AAyCpB,OAAO,KAAK,EAEV,sBAAsB,EACtB,iCAAiC,EAClC,MAAM,UAAU,CAAC;AASlB,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,sBAAsB,8BAO/B;AAED,wBAAsB,wBAAwB,CAC5C,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,sBAAsB,8BA+K/B;AA2HD,MAAM,MAAM,cAAc,GAAG,IAAI,CAC/B,iCAAiC,EAC/B,MAAM,GACN,QAAQ,GACR,aAAa,GACb,gBAAgB,GAChB,IAAI,GACJ,yBAAyB,GACzB,aAAa,GACb,SAAS,GACT,WAAW,GACX,yBAAyB,CAC5B,CAAC;AAEF,wBAAsB,OAAO,CAC3B,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,iBAAiB,CAAC,CA4G5B;AA6uBD,eAAe,gBAAgB,CAAC"}
@@ -99,7 +99,9 @@ async function libraryGeneratorInternal(tree, schema) {
99
99
  options.bundler !== 'vite' // Test would have been set up already
100
100
  ) {
101
101
  const { createOrEditViteConfig } = (0, devkit_1.ensurePackage)('@nx/vite', versions_1.nxVersion);
102
- const { configurationGenerator } = (0, devkit_1.ensurePackage)('@nx/vitest', versions_1.nxVersion);
102
+ (0, devkit_1.ensurePackage)('@nx/vitest', versions_1.nxVersion);
103
+ // nx-ignore-next-line
104
+ const { configurationGenerator } = require('@nx/vitest/generators');
103
105
  const vitestTask = await configurationGenerator(tree, {
104
106
  project: options.name,
105
107
  uiFramework: 'none',
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/plugins/typescript/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,kBAAkB,EAEvB,KAAK,aAAa,EAInB,MAAM,YAAY,CAAC;AAiCpB,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EACN,OAAO,GACP;QACE,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACN,KAAK,CAAC,EACF,OAAO,GACP;QACE,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;IACN,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAyFD;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,kBAEhC,CAAC;AAEF,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAI/C,eAAO,MAAM,aAAa,EAAE,aAAa,CAAC,gBAAgB,CA6DzD,CAAC;AAEF,eAAO,MAAM,WAAW,iCAAgB,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../../../../packages/js/src/plugins/typescript/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,kBAAkB,EAEvB,KAAK,aAAa,EAInB,MAAM,YAAY,CAAC;AAgCpB,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EACN,OAAO,GACP;QACE,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC;IACN,KAAK,CAAC,EACF,OAAO,GACP;QACE,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B,CAAC;IACN,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAkKD;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,kBAEhC,CAAC;AAEF,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAI/C,eAAO,MAAM,aAAa,EAAE,aAAa,CAAC,gBAAgB,CA6EzD,CAAC;AAEF,eAAO,MAAM,WAAW,iCAAgB,CAAC"}
@@ -59,6 +59,39 @@ function writeTsConfigCache(data) {
59
59
  data,
60
60
  });
61
61
  }
62
+ function createConfigContext(configFilePath, workspaceRoot, projectContext) {
63
+ const absolutePath = (0, node_path_1.join)(workspaceRoot, configFilePath);
64
+ return {
65
+ originalPath: configFilePath,
66
+ absolutePath,
67
+ relativePath: posix.relative(workspaceRoot, absolutePath),
68
+ basename: (0, node_path_1.basename)(configFilePath),
69
+ basenameNoExt: (0, node_path_1.basename)(configFilePath, '.json'),
70
+ dirname: (0, node_path_1.dirname)(absolutePath),
71
+ project: projectContext,
72
+ };
73
+ }
74
+ function getConfigContext(configPath, workspaceRoot) {
75
+ const absolutePath = configPath.startsWith('/') || configPath.startsWith(workspaceRoot)
76
+ ? (0, node_path_1.normalize)(configPath)
77
+ : (0, node_path_1.join)(workspaceRoot, configPath);
78
+ let context = cache.configContexts.get(absolutePath);
79
+ if (context) {
80
+ return context;
81
+ }
82
+ const relativePath = (0, node_path_1.relative)(workspaceRoot, absolutePath);
83
+ const projectRoot = (0, node_path_1.dirname)(relativePath);
84
+ if (!cache.projectContexts.has(projectRoot)) {
85
+ cache.projectContexts.set(projectRoot, {
86
+ root: projectRoot,
87
+ normalized: posix.normalize(projectRoot),
88
+ absolute: (0, node_path_1.join)(workspaceRoot, projectRoot),
89
+ });
90
+ }
91
+ const newContext = createConfigContext(relativePath, workspaceRoot, cache.projectContexts.get(projectRoot));
92
+ cache.configContexts.set(absolutePath, newContext);
93
+ return newContext;
94
+ }
62
95
  /**
63
96
  * @deprecated The 'createDependencies' function is now a no-op. This functionality is included in 'createNodesV2'.
64
97
  */
@@ -74,16 +107,26 @@ exports.createNodesV2 = [
74
107
  const optionsHash = (0, file_hasher_1.hashObject)(options);
75
108
  const targetsCachePath = (0, node_path_1.join)(cache_directory_1.workspaceDataDirectory, `tsc-${optionsHash}.hash`);
76
109
  const targetsCache = readFromCache(targetsCachePath);
77
- cache = { fileHashes: {}, rawFiles: {}, isExternalProjectReference: {} };
110
+ cache = {
111
+ fileHashes: {},
112
+ rawFiles: {},
113
+ picomatchMatchers: {},
114
+ extendedFilesHashes: new Map(),
115
+ configOwners: new Map(),
116
+ projectContexts: new Map(),
117
+ configContexts: new Map(),
118
+ };
78
119
  initializeTsConfigCache(configFilePaths, context.workspaceRoot);
79
120
  const normalizedOptions = normalizePluginOptions(options);
80
- const { configFilePaths: validConfigFilePaths, hashes, projectRoots, } = await resolveValidConfigFilesAndHashes(configFilePaths, optionsHash, context);
121
+ const { configFilePaths: validConfigFilePaths, hashes, projectRoots, } = await resolveValidConfigFilesAndHashes(configFilePaths, normalizedOptions, optionsHash, context);
81
122
  try {
82
123
  return await (0, devkit_1.createNodesFromFiles)((configFilePath, options, context, idx) => {
83
124
  const projectRoot = projectRoots[idx];
84
125
  const hash = hashes[idx];
85
126
  const cacheKey = `${hash}_${configFilePath}`;
86
- targetsCache[cacheKey] ??= buildTscTargets((0, node_path_1.join)(context.workspaceRoot, configFilePath), projectRoot, options, context, validConfigFilePaths);
127
+ const absolutePath = (0, node_path_1.join)(context.workspaceRoot, configFilePath);
128
+ const configContext = getConfigContext(absolutePath, context.workspaceRoot);
129
+ targetsCache[cacheKey] ??= buildTscTargets(configContext, options, context, validConfigFilePaths);
87
130
  const { targets } = targetsCache[cacheKey];
88
131
  return {
89
132
  projects: {
@@ -97,23 +140,33 @@ exports.createNodesV2 = [
97
140
  finally {
98
141
  writeToCache(targetsCachePath, targetsCache);
99
142
  writeTsConfigCache(toRelativePaths(tsConfigCacheData, context.workspaceRoot));
143
+ // Release memory after plugin invocation
144
+ cache = null;
100
145
  }
101
146
  },
102
147
  ];
103
148
  exports.createNodes = exports.createNodesV2;
104
- async function resolveValidConfigFilesAndHashes(configFilePaths, optionsHash, context) {
149
+ async function resolveValidConfigFilesAndHashes(configFilePaths, options, optionsHash, context) {
105
150
  const lockFileHash = (0, file_hasher_1.hashFile)((0, node_path_1.join)(context.workspaceRoot, (0, lock_file_1.getLockFileName)((0, devkit_1.detectPackageManager)(context.workspaceRoot)))) ?? '';
106
151
  const validConfigFilePaths = [];
107
152
  const hashes = [];
108
153
  const projectRoots = [];
109
154
  for await (const configFilePath of configFilePaths) {
110
155
  const projectRoot = (0, node_path_1.dirname)(configFilePath);
111
- if (!checkIfConfigFileShouldBeProject(configFilePath, projectRoot, context)) {
156
+ const absolutePath = (0, node_path_1.join)(context.workspaceRoot, configFilePath);
157
+ const configContext = getConfigContext(absolutePath, context.workspaceRoot);
158
+ // Skip configs that can't produce any targets based on plugin options
159
+ const isTypecheckConfig = configContext.basename === 'tsconfig.json';
160
+ const isBuildConfig = options.build && configContext.basename === options.build.configName;
161
+ if (!isTypecheckConfig && !isBuildConfig) {
162
+ continue;
163
+ }
164
+ if (!checkIfConfigFileShouldBeProject(configContext)) {
112
165
  continue;
113
166
  }
114
167
  projectRoots.push(projectRoot);
115
168
  validConfigFilePaths.push(configFilePath);
116
- hashes.push(await getConfigFileHash(configFilePath, context.workspaceRoot, projectRoot, optionsHash, lockFileHash));
169
+ hashes.push(await getConfigFileHash(configFilePath, context.workspaceRoot, configContext.project, optionsHash, lockFileHash));
117
170
  }
118
171
  return { configFilePaths: validConfigFilePaths, hashes, projectRoots };
119
172
  }
@@ -129,15 +182,15 @@ async function resolveValidConfigFilesAndHashes(configFilePaths, optionsHash, co
129
182
  * - hash of the plugin options
130
183
  * - current config file path
131
184
  */
132
- async function getConfigFileHash(configFilePath, workspaceRoot, projectRoot, optionsHash, lockFileHash) {
185
+ async function getConfigFileHash(configFilePath, workspaceRoot, project, optionsHash, lockFileHash) {
133
186
  const fullConfigPath = (0, node_path_1.join)(workspaceRoot, configFilePath);
134
187
  const tsConfig = retrieveTsConfigFromCache(fullConfigPath, workspaceRoot);
135
188
  const extendedConfigFiles = getExtendedConfigFiles(tsConfig, workspaceRoot);
136
- const internalReferencedFiles = resolveInternalProjectReferences(tsConfig, workspaceRoot, projectRoot);
137
- const externalProjectReferences = resolveShallowExternalProjectReferences(tsConfig, workspaceRoot, projectRoot);
189
+ const internalReferencedFiles = resolveInternalProjectReferences(tsConfig, workspaceRoot, project);
190
+ const externalProjectReferences = resolveShallowExternalProjectReferences(tsConfig, workspaceRoot, project);
138
191
  let packageJson = null;
139
192
  try {
140
- packageJson = (0, devkit_1.readJsonFile)((0, node_path_1.join)(workspaceRoot, projectRoot, 'package.json'));
193
+ packageJson = (0, devkit_1.readJsonFile)((0, node_path_1.join)(workspaceRoot, project.root, 'package.json'));
141
194
  }
142
195
  catch { }
143
196
  return (0, file_hasher_1.hashArray)([
@@ -153,19 +206,20 @@ async function getConfigFileHash(configFilePath, workspaceRoot, projectRoot, opt
153
206
  ...(packageJson ? [(0, file_hasher_1.hashObject)(packageJson)] : []),
154
207
  ]);
155
208
  }
156
- function checkIfConfigFileShouldBeProject(configFilePath, projectRoot, context) {
209
+ function checkIfConfigFileShouldBeProject(config) {
157
210
  // Do not create a project for the workspace root tsconfig files.
158
- if (projectRoot === '.') {
211
+ if (config.project.root === '.') {
159
212
  return false;
160
213
  }
161
214
  // Do not create a project if package.json and project.json isn't there.
162
- const siblingFiles = (0, node_fs_1.readdirSync)((0, node_path_1.join)(context.workspaceRoot, projectRoot));
215
+ const siblingFiles = (0, node_fs_1.readdirSync)(config.project.absolute);
163
216
  if (!siblingFiles.includes('package.json') &&
164
217
  !siblingFiles.includes('project.json')) {
165
218
  return false;
166
219
  }
220
+ cache.configOwners.set(config.relativePath, config.project.normalized);
167
221
  // Do not create a project if it's not a tsconfig.json and there is no tsconfig.json in the same directory
168
- if ((0, node_path_1.basename)(configFilePath) !== 'tsconfig.json' &&
222
+ if (config.basename !== 'tsconfig.json' &&
169
223
  !siblingFiles.includes('tsconfig.json')) {
170
224
  return false;
171
225
  }
@@ -179,17 +233,16 @@ function checkIfConfigFileShouldBeProject(configFilePath, projectRoot, context)
179
233
  }
180
234
  return true;
181
235
  }
182
- function buildTscTargets(configFilePath, projectRoot, options, context, configFiles) {
236
+ function buildTscTargets(config, options, context, configFiles) {
183
237
  const targets = {};
184
- const namedInputs = (0, get_named_inputs_1.getNamedInputs)(projectRoot, context);
185
- const tsConfig = retrieveTsConfigFromCache(configFilePath, context.workspaceRoot);
238
+ const namedInputs = (0, get_named_inputs_1.getNamedInputs)(config.project.root, context);
239
+ const tsConfig = retrieveTsConfigFromCache(config.absolutePath, context.workspaceRoot);
186
240
  let internalProjectReferences;
187
- // Typecheck target
188
- if ((0, node_path_1.basename)(configFilePath) === 'tsconfig.json' &&
241
+ if (config.basename === 'tsconfig.json' &&
189
242
  options.typecheck &&
190
243
  tsConfig.raw?.['nx']?.addTypecheckTarget !== false) {
191
- internalProjectReferences = resolveInternalProjectReferences(tsConfig, context.workspaceRoot, projectRoot);
192
- const externalProjectReferences = resolveShallowExternalProjectReferences(tsConfig, context.workspaceRoot, projectRoot);
244
+ internalProjectReferences = resolveInternalProjectReferences(tsConfig, context.workspaceRoot, config.project);
245
+ const externalProjectReferences = resolveShallowExternalProjectReferences(tsConfig, context.workspaceRoot, config.project);
193
246
  const targetName = options.typecheck.targetName;
194
247
  if (!targets[targetName]) {
195
248
  let command = `tsc --build --emitDeclarationOnly${options.verboseOutput ? ' --verbose' : ''}`;
@@ -206,20 +259,20 @@ function buildTscTargets(configFilePath, projectRoot, options, context, configFi
206
259
  }
207
260
  else if (options.build) {
208
261
  // check if the project will have a build target
209
- const buildConfigPath = (0, devkit_1.joinPathFragments)(projectRoot, options.build.configName);
262
+ const buildConfigPath = (0, devkit_1.joinPathFragments)(config.project.root, options.build.configName);
210
263
  if (configFiles.some((f) => f === buildConfigPath) &&
211
264
  (options.build.skipBuildCheck ||
212
- (0, util_1.isValidPackageJsonBuildConfig)(retrieveTsConfigFromCache(buildConfigPath, context.workspaceRoot), context.workspaceRoot, projectRoot))) {
265
+ (0, util_1.isValidPackageJsonBuildConfig)(retrieveTsConfigFromCache(buildConfigPath, context.workspaceRoot), context.workspaceRoot, config.project.root))) {
213
266
  dependsOn.unshift(options.build.targetName);
214
267
  }
215
268
  }
216
269
  targets[targetName] = {
217
270
  dependsOn,
218
271
  command,
219
- options: { cwd: projectRoot },
272
+ options: { cwd: config.project.root },
220
273
  cache: true,
221
- inputs: getInputs(namedInputs, configFilePath, tsConfig, internalProjectReferences, context.workspaceRoot, projectRoot),
222
- outputs: getOutputs(configFilePath, tsConfig, internalProjectReferences, context.workspaceRoot, projectRoot,
274
+ inputs: getInputs(namedInputs, config, tsConfig, internalProjectReferences, context.workspaceRoot),
275
+ outputs: getOutputs(config, tsConfig, internalProjectReferences, context.workspaceRoot,
223
276
  /* emitDeclarationOnly */ true),
224
277
  syncGenerators: ['@nx/js:typescript-sync'],
225
278
  metadata: {
@@ -237,18 +290,18 @@ function buildTscTargets(configFilePath, projectRoot, options, context, configFi
237
290
  }
238
291
  // Build target
239
292
  if (options.build &&
240
- (0, node_path_1.basename)(configFilePath) === options.build.configName &&
293
+ config.basename === options.build.configName &&
241
294
  (options.build.skipBuildCheck ||
242
- (0, util_1.isValidPackageJsonBuildConfig)(tsConfig, context.workspaceRoot, projectRoot))) {
243
- internalProjectReferences ??= resolveInternalProjectReferences(tsConfig, context.workspaceRoot, projectRoot);
295
+ (0, util_1.isValidPackageJsonBuildConfig)(tsConfig, context.workspaceRoot, config.project.root))) {
296
+ internalProjectReferences ??= resolveInternalProjectReferences(tsConfig, context.workspaceRoot, config.project);
244
297
  const targetName = options.build.targetName;
245
298
  targets[targetName] = {
246
299
  dependsOn: [`^${targetName}`],
247
300
  command: `tsc --build ${options.build.configName}${options.verboseOutput ? ' --verbose' : ''}`,
248
- options: { cwd: projectRoot },
301
+ options: { cwd: config.project.root },
249
302
  cache: true,
250
- inputs: getInputs(namedInputs, configFilePath, tsConfig, internalProjectReferences, context.workspaceRoot, projectRoot),
251
- outputs: getOutputs(configFilePath, tsConfig, internalProjectReferences, context.workspaceRoot, projectRoot,
303
+ inputs: getInputs(namedInputs, config, tsConfig, internalProjectReferences, context.workspaceRoot),
304
+ outputs: getOutputs(config, tsConfig, internalProjectReferences, context.workspaceRoot,
252
305
  // should be false for build target, but providing it just in case is set to true
253
306
  tsConfig.options.emitDeclarationOnly),
254
307
  syncGenerators: ['@nx/js:typescript-sync'],
@@ -263,14 +316,14 @@ function buildTscTargets(configFilePath, projectRoot, options, context, configFi
263
316
  },
264
317
  },
265
318
  };
266
- (0, util_1.addBuildAndWatchDepsTargets)(context.workspaceRoot, projectRoot, targets, {
319
+ (0, util_1.addBuildAndWatchDepsTargets)(context.workspaceRoot, config.project.root, targets, {
267
320
  buildDepsTargetName: options.build.buildDepsName,
268
321
  watchDepsTargetName: options.build.watchDepsName,
269
322
  }, pmc);
270
323
  }
271
324
  return { targets };
272
325
  }
273
- function getInputs(namedInputs, configFilePath, tsConfig, internalProjectReferences, workspaceRoot, projectRoot) {
326
+ function getInputs(namedInputs, config, tsConfig, internalProjectReferences, workspaceRoot) {
274
327
  const configFiles = new Set();
275
328
  // TODO(leo): temporary disable external dependencies until we support hashing
276
329
  // glob patterns from external dependencies
@@ -283,10 +336,10 @@ function getInputs(namedInputs, configFilePath, tsConfig, internalProjectReferen
283
336
  const includePaths = new Set();
284
337
  const excludePaths = new Set();
285
338
  const projectTsConfigFiles = [
286
- [configFilePath, tsConfig],
339
+ [config.originalPath, tsConfig],
287
340
  ...Object.entries(internalProjectReferences),
288
341
  ];
289
- const absoluteProjectRoot = (0, node_path_1.join)(workspaceRoot, projectRoot);
342
+ const absoluteProjectRoot = config.project.absolute;
290
343
  if (!ts) {
291
344
  ts = require('typescript');
292
345
  }
@@ -333,14 +386,21 @@ function getInputs(namedInputs, configFilePath, tsConfig, internalProjectReferen
333
386
  };
334
387
  const configDirTemplate = '${configDir}';
335
388
  const substituteConfigDir = (p) => p.startsWith(configDirTemplate) ? p.replace(configDirTemplate, './') : p;
336
- projectTsConfigFiles.forEach(([configPath, config]) => {
389
+ // Helper function to get or create cached picomatch matchers
390
+ const getOrCreateMatcher = (pattern) => {
391
+ if (!cache.picomatchMatchers[pattern]) {
392
+ cache.picomatchMatchers[pattern] = picomatch(pattern);
393
+ }
394
+ return cache.picomatchMatchers[pattern];
395
+ };
396
+ projectTsConfigFiles.forEach(([configPath, tsconfig]) => {
337
397
  configFiles.add(configPath);
338
398
  const offset = (0, node_path_1.relative)(absoluteProjectRoot, (0, node_path_1.dirname)(configPath));
339
- (config.raw?.include ?? []).forEach((p) => {
340
- const normalized = normalizeInput((0, node_path_1.join)(offset, substituteConfigDir(p)), config);
399
+ (tsconfig.raw?.include ?? []).forEach((p) => {
400
+ const normalized = normalizeInput((0, node_path_1.join)(offset, substituteConfigDir(p)), tsconfig);
341
401
  normalized.forEach((input) => includePaths.add(input));
342
402
  });
343
- if (config.raw?.exclude) {
403
+ if (tsconfig.raw?.exclude) {
344
404
  /**
345
405
  * We need to filter out the exclude paths that are already included in
346
406
  * other tsconfig files. If they are not included in other tsconfig files,
@@ -353,10 +413,16 @@ function getInputs(namedInputs, configFilePath, tsConfig, internalProjectReferen
353
413
  }
354
414
  });
355
415
  const normalize = (p) => (p.startsWith('./') ? p.slice(2) : p);
356
- config.raw.exclude.forEach((e) => {
416
+ tsconfig.raw.exclude.forEach((e) => {
357
417
  const excludePath = substituteConfigDir(e);
358
- if (!otherFilesInclude.some((includePath) => picomatch(normalize(excludePath))(normalize(includePath)) ||
359
- picomatch(normalize(includePath))(normalize(excludePath)))) {
418
+ const normalizedExclude = normalize(excludePath);
419
+ const excludeMatcher = getOrCreateMatcher(normalizedExclude);
420
+ if (!otherFilesInclude.some((includePath) => {
421
+ const normalizedInclude = normalize(includePath);
422
+ const includeMatcher = getOrCreateMatcher(normalizedInclude);
423
+ return (excludeMatcher(normalizedInclude) ||
424
+ includeMatcher(normalizedExclude));
425
+ })) {
360
426
  excludePaths.add(excludePath);
361
427
  }
362
428
  });
@@ -364,10 +430,10 @@ function getInputs(namedInputs, configFilePath, tsConfig, internalProjectReferen
364
430
  });
365
431
  const inputs = [];
366
432
  if (includePaths.size) {
367
- if ((0, node_fs_1.existsSync)((0, node_path_1.join)(workspaceRoot, projectRoot, 'package.json'))) {
433
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(workspaceRoot, config.project.root, 'package.json'))) {
368
434
  inputs.push('{projectRoot}/package.json');
369
435
  }
370
- inputs.push(...Array.from(configFiles).map((p) => pathToInputOrOutput(p, workspaceRoot, projectRoot)), ...Array.from(includePaths).map((p) => pathToInputOrOutput((0, devkit_1.joinPathFragments)(projectRoot, p), workspaceRoot, projectRoot)));
436
+ inputs.push(...Array.from(configFiles).map((p) => pathToInputOrOutput(p, workspaceRoot, config.project)), ...Array.from(includePaths).map((p) => pathToInputOrOutput((0, devkit_1.joinPathFragments)(config.project.root, p), workspaceRoot, config.project)));
371
437
  }
372
438
  else {
373
439
  // If we couldn't identify any include paths, we default to the default
@@ -375,9 +441,9 @@ function getInputs(namedInputs, configFilePath, tsConfig, internalProjectReferen
375
441
  inputs.push('production' in namedInputs ? 'production' : 'default');
376
442
  }
377
443
  if (excludePaths.size) {
378
- inputs.push(...Array.from(excludePaths).map((p) => `!${pathToInputOrOutput((0, devkit_1.joinPathFragments)(projectRoot, p), workspaceRoot, projectRoot)}`));
444
+ inputs.push(...Array.from(excludePaths).map((p) => `!${pathToInputOrOutput((0, devkit_1.joinPathFragments)(config.project.root, p), workspaceRoot, config.project)}`));
379
445
  }
380
- if (hasExternalProjectReferences(configFilePath, tsConfig, workspaceRoot, projectRoot)) {
446
+ if (hasExternalProjectReferences(config.originalPath, tsConfig, workspaceRoot, config.project)) {
381
447
  // Importing modules from a referenced project will load its output declaration files (d.ts)
382
448
  // https://www.typescriptlang.org/docs/handbook/project-references.html#what-is-a-project-reference
383
449
  inputs.push({ dependentTasksOutputFiles: '**/*.d.ts' });
@@ -388,58 +454,59 @@ function getInputs(namedInputs, configFilePath, tsConfig, internalProjectReferen
388
454
  // inputs.push({ externalDependencies });
389
455
  return inputs;
390
456
  }
391
- function getOutputs(configFilePath, tsConfig, internalProjectReferences, workspaceRoot, projectRoot, emitDeclarationOnly) {
457
+ function getOutputs(config, tsConfig, internalProjectReferences, workspaceRoot, emitDeclarationOnly) {
392
458
  const outputs = new Set();
393
459
  // We could have more surgical outputs based on the tsconfig options, but the
394
460
  // user could override them through the command line and that wouldn't be
395
461
  // reflected in the outputs. So, we just include everything that could be
396
462
  // produced by the tsc command.
397
- [tsConfig, ...Object.values(internalProjectReferences)].forEach((config) => {
398
- if (config.options.outFile) {
399
- const outFileName = (0, node_path_1.basename)(config.options.outFile, '.js');
400
- const outFileDir = (0, node_path_1.dirname)(config.options.outFile);
401
- outputs.add(pathToInputOrOutput(config.options.outFile, workspaceRoot, projectRoot));
463
+ [tsConfig, ...Object.values(internalProjectReferences)].forEach((tsconfig) => {
464
+ if (tsconfig.options.outFile) {
465
+ const outFileName = (0, node_path_1.basename)(tsconfig.options.outFile, '.js');
466
+ const outFileDir = (0, node_path_1.dirname)(tsconfig.options.outFile);
467
+ outputs.add(pathToInputOrOutput(tsconfig.options.outFile, workspaceRoot, config.project));
402
468
  // outFile is not be used with .cjs, .mjs, .jsx, so the list is simpler
403
469
  const outDir = (0, node_path_1.relative)(workspaceRoot, outFileDir);
404
- outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(outDir, `${outFileName}.js.map`), workspaceRoot, projectRoot));
405
- outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(outDir, `${outFileName}.d.ts`), workspaceRoot, projectRoot));
406
- outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(outDir, `${outFileName}.d.ts.map`), workspaceRoot, projectRoot));
470
+ outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(outDir, `${outFileName}.js.map`), workspaceRoot, config.project));
471
+ outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(outDir, `${outFileName}.d.ts`), workspaceRoot, config.project));
472
+ outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(outDir, `${outFileName}.d.ts.map`), workspaceRoot, config.project));
407
473
  // https://www.typescriptlang.org/tsconfig#tsBuildInfoFile
408
474
  outputs.add(tsConfig.options.tsBuildInfoFile
409
- ? pathToInputOrOutput(tsConfig.options.tsBuildInfoFile, workspaceRoot, projectRoot)
410
- : pathToInputOrOutput((0, devkit_1.joinPathFragments)(outDir, `${outFileName}.tsbuildinfo`), workspaceRoot, projectRoot));
475
+ ? pathToInputOrOutput(tsConfig.options.tsBuildInfoFile, workspaceRoot, config.project)
476
+ : pathToInputOrOutput((0, devkit_1.joinPathFragments)(outDir, `${outFileName}.tsbuildinfo`), workspaceRoot, config.project));
411
477
  }
412
- else if (config.options.outDir) {
478
+ else if (tsconfig.options.outDir) {
413
479
  if (emitDeclarationOnly) {
414
- outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(config.options.outDir, '**/*.d.ts'), workspaceRoot, projectRoot));
480
+ outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(tsconfig.options.outDir, '**/*.d.ts'), workspaceRoot, config.project));
415
481
  if (tsConfig.options.declarationMap) {
416
- outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(config.options.outDir, '**/*.d.ts.map'), workspaceRoot, projectRoot));
482
+ outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(tsconfig.options.outDir, '**/*.d.ts.map'), workspaceRoot, config.project));
417
483
  }
418
484
  }
419
485
  else {
420
- outputs.add(pathToInputOrOutput(config.options.outDir, workspaceRoot, projectRoot));
486
+ outputs.add(pathToInputOrOutput(tsconfig.options.outDir, workspaceRoot, config.project));
421
487
  }
422
- if (config.options.tsBuildInfoFile) {
488
+ if (tsconfig.options.tsBuildInfoFile) {
423
489
  if (emitDeclarationOnly ||
424
- !(0, node_path_1.normalize)(config.options.tsBuildInfoFile).startsWith(`${(0, node_path_1.normalize)(config.options.outDir)}${node_path_1.sep}`)) {
490
+ !(0, node_path_1.normalize)(tsconfig.options.tsBuildInfoFile).startsWith(`${(0, node_path_1.normalize)(tsconfig.options.outDir)}${node_path_1.sep}`)) {
425
491
  // https://www.typescriptlang.org/tsconfig#tsBuildInfoFile
426
- outputs.add(pathToInputOrOutput(config.options.tsBuildInfoFile, workspaceRoot, projectRoot));
492
+ outputs.add(pathToInputOrOutput(tsconfig.options.tsBuildInfoFile, workspaceRoot, config.project));
427
493
  }
428
494
  }
429
- else if (config.options.rootDir && config.options.rootDir !== '.') {
495
+ else if (tsconfig.options.rootDir &&
496
+ tsconfig.options.rootDir !== '.') {
430
497
  // If rootDir is set, then the tsbuildinfo file will be outside the outDir so we need to add it.
431
- const relativeRootDir = (0, node_path_1.relative)(config.options.rootDir, (0, node_path_1.join)(workspaceRoot, projectRoot));
432
- outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(config.options.outDir, relativeRootDir, `*.tsbuildinfo`), workspaceRoot, projectRoot));
498
+ const relativeRootDir = (0, node_path_1.relative)(tsconfig.options.rootDir, (0, node_path_1.join)(workspaceRoot, config.project.root));
499
+ outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(tsconfig.options.outDir, relativeRootDir, `*.tsbuildinfo`), workspaceRoot, config.project));
433
500
  }
434
501
  else if (emitDeclarationOnly) {
435
502
  // https://www.typescriptlang.org/tsconfig#tsBuildInfoFile
436
- const name = (0, node_path_1.basename)(configFilePath, '.json');
437
- outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(config.options.outDir, `${name}.tsbuildinfo`), workspaceRoot, projectRoot));
503
+ const name = config.basenameNoExt;
504
+ outputs.add(pathToInputOrOutput((0, devkit_1.joinPathFragments)(tsconfig.options.outDir, `${name}.tsbuildinfo`), workspaceRoot, config.project));
438
505
  }
439
506
  }
440
- else if (config.raw?.include?.length ||
441
- config.raw?.files?.length ||
442
- (!config.raw?.include && !config.raw?.files)) {
507
+ else if (tsconfig.raw?.include?.length ||
508
+ tsconfig.raw?.files?.length ||
509
+ (!tsconfig.raw?.include && !tsconfig.raw?.files)) {
443
510
  // tsc produce files in place when no outDir or outFile is set
444
511
  outputs.add((0, devkit_1.joinPathFragments)('{projectRoot}', '**/*.js'));
445
512
  outputs.add((0, devkit_1.joinPathFragments)('{projectRoot}', '**/*.cjs'));
@@ -454,16 +521,16 @@ function getOutputs(configFilePath, tsConfig, internalProjectReferences, workspa
454
521
  outputs.add((0, devkit_1.joinPathFragments)('{projectRoot}', '**/*.d.cts.map'));
455
522
  outputs.add((0, devkit_1.joinPathFragments)('{projectRoot}', '**/*.d.mts.map'));
456
523
  // https://www.typescriptlang.org/tsconfig#tsBuildInfoFile
457
- const name = (0, node_path_1.basename)(configFilePath, '.json');
524
+ const name = config.basenameNoExt;
458
525
  outputs.add(tsConfig.options.tsBuildInfoFile
459
- ? pathToInputOrOutput(tsConfig.options.tsBuildInfoFile, workspaceRoot, projectRoot)
526
+ ? pathToInputOrOutput(tsConfig.options.tsBuildInfoFile, workspaceRoot, config.project)
460
527
  : (0, devkit_1.joinPathFragments)('{projectRoot}', `${name}.tsbuildinfo`));
461
528
  }
462
529
  });
463
530
  return Array.from(outputs);
464
531
  }
465
- function pathToInputOrOutput(path, workspaceRoot, projectRoot) {
466
- const fullProjectRoot = (0, node_path_1.resolve)(workspaceRoot, projectRoot);
532
+ function pathToInputOrOutput(path, workspaceRoot, project) {
533
+ const fullProjectRoot = project.absolute;
467
534
  const fullPath = (0, node_path_1.resolve)(workspaceRoot, path);
468
535
  const pathRelativeToProjectRoot = (0, devkit_1.normalizePath)((0, node_path_1.relative)(fullProjectRoot, fullPath));
469
536
  if (pathRelativeToProjectRoot.startsWith('..')) {
@@ -486,55 +553,53 @@ function getExtendedConfigFiles(tsConfig, workspaceRoot, extendedConfigFiles = n
486
553
  packages: Array.from(extendedExternalPackages),
487
554
  };
488
555
  }
489
- function resolveInternalProjectReferences(tsConfig, workspaceRoot, projectRoot, projectReferences = {}) {
556
+ function resolveInternalProjectReferences(tsConfig, workspaceRoot, project, projectReferences = {}) {
490
557
  if (!tsConfig.projectReferences?.length) {
491
558
  return {};
492
559
  }
493
560
  for (const ref of tsConfig.projectReferences) {
494
561
  let refConfigPath = ref.path;
495
562
  if (projectReferences[refConfigPath]) {
496
- // Already resolved
497
563
  continue;
498
564
  }
499
565
  if (!(0, node_fs_1.existsSync)(refConfigPath)) {
500
- // the referenced tsconfig doesn't exist, ignore it
501
- continue;
502
- }
503
- if (isExternalProjectReference(refConfigPath, workspaceRoot, projectRoot)) {
504
566
  continue;
505
567
  }
506
568
  if (!refConfigPath.endsWith('.json')) {
507
569
  refConfigPath = (0, node_path_1.join)(refConfigPath, 'tsconfig.json');
508
570
  }
571
+ const refContext = getConfigContext(refConfigPath, workspaceRoot);
572
+ if (isExternalProjectReference(refContext, project, workspaceRoot)) {
573
+ continue;
574
+ }
509
575
  projectReferences[refConfigPath] = retrieveTsConfigFromCache(refConfigPath, workspaceRoot);
510
- resolveInternalProjectReferences(projectReferences[refConfigPath], workspaceRoot, projectRoot, projectReferences);
576
+ resolveInternalProjectReferences(projectReferences[refConfigPath], workspaceRoot, project, projectReferences);
511
577
  }
512
578
  return projectReferences;
513
579
  }
514
- function resolveShallowExternalProjectReferences(tsConfig, workspaceRoot, projectRoot, projectReferences = {}) {
580
+ function resolveShallowExternalProjectReferences(tsConfig, workspaceRoot, project, projectReferences = {}) {
515
581
  if (!tsConfig.projectReferences?.length) {
516
582
  return projectReferences;
517
583
  }
518
584
  for (const ref of tsConfig.projectReferences) {
519
585
  let refConfigPath = ref.path;
520
586
  if (projectReferences[refConfigPath]) {
521
- // Already resolved
522
587
  continue;
523
588
  }
524
589
  if (!(0, node_fs_1.existsSync)(refConfigPath)) {
525
- // the referenced tsconfig doesn't exist, ignore it
526
590
  continue;
527
591
  }
528
- if (isExternalProjectReference(refConfigPath, workspaceRoot, projectRoot)) {
529
- if (!refConfigPath.endsWith('.json')) {
530
- refConfigPath = (0, node_path_1.join)(refConfigPath, 'tsconfig.json');
531
- }
592
+ if (!refConfigPath.endsWith('.json')) {
593
+ refConfigPath = (0, node_path_1.join)(refConfigPath, 'tsconfig.json');
594
+ }
595
+ const refContext = getConfigContext(refConfigPath, workspaceRoot);
596
+ if (isExternalProjectReference(refContext, project, workspaceRoot)) {
532
597
  projectReferences[refConfigPath] = retrieveTsConfigFromCache(refConfigPath, workspaceRoot);
533
598
  }
534
599
  }
535
600
  return projectReferences;
536
601
  }
537
- function hasExternalProjectReferences(tsConfigPath, tsConfig, workspaceRoot, projectRoot, seen = new Set()) {
602
+ function hasExternalProjectReferences(tsConfigPath, tsConfig, workspaceRoot, project, seen = new Set()) {
538
603
  if (!tsConfig.projectReferences?.length) {
539
604
  return false;
540
605
  }
@@ -542,57 +607,46 @@ function hasExternalProjectReferences(tsConfigPath, tsConfig, workspaceRoot, pro
542
607
  for (const ref of tsConfig.projectReferences) {
543
608
  let refConfigPath = ref.path;
544
609
  if (seen.has(refConfigPath)) {
545
- // Already seen
546
610
  continue;
547
611
  }
548
612
  if (!(0, node_fs_1.existsSync)(refConfigPath)) {
549
- // the referenced tsconfig doesn't exist, ignore it
550
613
  continue;
551
614
  }
552
- if (isExternalProjectReference(refConfigPath, workspaceRoot, projectRoot)) {
553
- return true;
554
- }
555
615
  if (!refConfigPath.endsWith('.json')) {
556
616
  refConfigPath = (0, node_path_1.join)(refConfigPath, 'tsconfig.json');
557
617
  }
618
+ const refContext = getConfigContext(refConfigPath, workspaceRoot);
619
+ if (isExternalProjectReference(refContext, project, workspaceRoot)) {
620
+ return true;
621
+ }
558
622
  const refTsConfig = retrieveTsConfigFromCache(refConfigPath, workspaceRoot);
559
- const result = hasExternalProjectReferences(refConfigPath, refTsConfig, workspaceRoot, projectRoot, seen);
623
+ const result = hasExternalProjectReferences(refConfigPath, refTsConfig, workspaceRoot, project, seen);
560
624
  if (result) {
561
625
  return true;
562
626
  }
563
627
  }
564
628
  return false;
565
629
  }
566
- function isExternalProjectReference(refTsConfigPath, workspaceRoot, projectRoot) {
567
- const relativePath = posixRelative(workspaceRoot, refTsConfigPath);
568
- if (cache.isExternalProjectReference[relativePath] !== undefined) {
569
- return cache.isExternalProjectReference[relativePath];
570
- }
571
- const absoluteProjectRoot = (0, node_path_1.join)(workspaceRoot, projectRoot);
572
- let currentPath = getTsConfigDirName(refTsConfigPath);
573
- if ((0, node_path_1.relative)(absoluteProjectRoot, currentPath).startsWith('..')) {
574
- // it's outside of the project root, so it's an external project reference
575
- cache.isExternalProjectReference[relativePath] = true;
630
+ function isExternalProjectReference(refConfig, project, workspaceRoot) {
631
+ const owner = cache.configOwners.get(refConfig.relativePath);
632
+ if (owner !== undefined) {
633
+ return owner !== project.normalized;
634
+ }
635
+ let currentPath = refConfig.dirname;
636
+ if ((0, node_path_1.relative)(project.absolute, currentPath).startsWith('..')) {
576
637
  return true;
577
638
  }
578
- while (currentPath !== absoluteProjectRoot) {
639
+ while (currentPath !== project.absolute) {
579
640
  if ((0, node_fs_1.existsSync)((0, node_path_1.join)(currentPath, 'package.json')) ||
580
641
  (0, node_fs_1.existsSync)((0, node_path_1.join)(currentPath, 'project.json'))) {
581
- // it's inside a nested project root, so it's and external project reference
582
- cache.isExternalProjectReference[relativePath] = true;
583
- return true;
642
+ const owner = posixRelative(workspaceRoot, currentPath);
643
+ cache.configOwners.set(refConfig.relativePath, owner);
644
+ return owner !== project.normalized;
584
645
  }
585
646
  currentPath = (0, node_path_1.dirname)(currentPath);
586
647
  }
587
- // it's inside the project root, so it's an internal project reference
588
- cache.isExternalProjectReference[relativePath] = false;
589
648
  return false;
590
649
  }
591
- function getTsConfigDirName(tsConfigPath) {
592
- return (0, node_fs_1.statSync)(tsConfigPath).isFile()
593
- ? (0, node_path_1.dirname)(tsConfigPath)
594
- : (0, node_path_1.normalize)(tsConfigPath);
595
- }
596
650
  function retrieveTsConfigFromCache(tsConfigPath, workspaceRoot) {
597
651
  const relativePath = posixRelative(workspaceRoot, tsConfigPath);
598
652
  // we don't need to check the hash if it's in the cache, because we've already
@@ -647,10 +701,19 @@ function readTsConfigAndCache(tsConfigPath, workspaceRoot) {
647
701
  return tsConfigCacheData[relativePath].data;
648
702
  }
649
703
  function getExtendedFilesHash(extendedConfigFiles, workspaceRoot) {
650
- const hashes = [];
651
704
  if (!extendedConfigFiles.length) {
652
705
  return '';
653
706
  }
707
+ // Create a stable cache key from sorted file paths
708
+ const cacheKey = extendedConfigFiles
709
+ .map((f) => f.filePath || f.externalPackage)
710
+ .filter(Boolean)
711
+ .sort()
712
+ .join('|');
713
+ if (cache.extendedFilesHashes.has(cacheKey)) {
714
+ return cache.extendedFilesHashes.get(cacheKey);
715
+ }
716
+ const hashes = [];
654
717
  for (const extendedConfigFile of extendedConfigFiles) {
655
718
  if (extendedConfigFile.externalPackage) {
656
719
  hashes.push(extendedConfigFile.externalPackage);
@@ -661,7 +724,9 @@ function getExtendedFilesHash(extendedConfigFiles, workspaceRoot) {
661
724
  .extendedConfigFiles, workspaceRoot));
662
725
  }
663
726
  }
664
- return hashes.join('|');
727
+ const hash = hashes.join('|');
728
+ cache.extendedFilesHashes.set(cacheKey, hash);
729
+ return hash;
665
730
  }
666
731
  function readTsConfig(tsConfigPath, workspaceRoot) {
667
732
  if (!ts) {