nx 20.0.0-beta.3 → 20.0.0-beta.5

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "20.0.0-beta.3",
3
+ "version": "20.0.0-beta.5",
4
4
  "private": false,
5
5
  "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
6
6
  "repository": {
@@ -58,7 +58,6 @@
58
58
  "open": "^8.4.0",
59
59
  "semver": "^7.5.3",
60
60
  "string-width": "^4.2.3",
61
- "strong-log-transformer": "^2.1.0",
62
61
  "tar-stream": "~2.2.0",
63
62
  "tmp": "~0.2.1",
64
63
  "tsconfig-paths": "^4.1.2",
@@ -66,8 +65,7 @@
66
65
  "yargs": "^17.6.2",
67
66
  "yargs-parser": "21.1.1",
68
67
  "node-machine-id": "1.1.12",
69
- "ora": "5.3.0",
70
- "@nrwl/tao": "20.0.0-beta.3"
68
+ "ora": "5.3.0"
71
69
  },
72
70
  "peerDependencies": {
73
71
  "@swc-node/register": "^1.8.0",
@@ -82,16 +80,16 @@
82
80
  }
83
81
  },
84
82
  "optionalDependencies": {
85
- "@nx/nx-darwin-x64": "20.0.0-beta.3",
86
- "@nx/nx-darwin-arm64": "20.0.0-beta.3",
87
- "@nx/nx-linux-x64-gnu": "20.0.0-beta.3",
88
- "@nx/nx-linux-x64-musl": "20.0.0-beta.3",
89
- "@nx/nx-win32-x64-msvc": "20.0.0-beta.3",
90
- "@nx/nx-linux-arm64-gnu": "20.0.0-beta.3",
91
- "@nx/nx-linux-arm64-musl": "20.0.0-beta.3",
92
- "@nx/nx-linux-arm-gnueabihf": "20.0.0-beta.3",
93
- "@nx/nx-win32-arm64-msvc": "20.0.0-beta.3",
94
- "@nx/nx-freebsd-x64": "20.0.0-beta.3"
83
+ "@nx/nx-darwin-x64": "20.0.0-beta.5",
84
+ "@nx/nx-darwin-arm64": "20.0.0-beta.5",
85
+ "@nx/nx-linux-x64-gnu": "20.0.0-beta.5",
86
+ "@nx/nx-linux-x64-musl": "20.0.0-beta.5",
87
+ "@nx/nx-win32-x64-msvc": "20.0.0-beta.5",
88
+ "@nx/nx-linux-arm64-gnu": "20.0.0-beta.5",
89
+ "@nx/nx-linux-arm64-musl": "20.0.0-beta.5",
90
+ "@nx/nx-linux-arm-gnueabihf": "20.0.0-beta.5",
91
+ "@nx/nx-win32-arm64-msvc": "20.0.0-beta.5",
92
+ "@nx/nx-freebsd-x64": "20.0.0-beta.5"
95
93
  },
96
94
  "nx-migrations": {
97
95
  "migrations": "./migrations.json",
@@ -6,15 +6,20 @@ const path_1 = require("path");
6
6
  async function prepareSourceRepo(gitClient, ref, source, relativeDestination, tempImportBranch, sourceRemoteUrl) {
7
7
  const spinner = createSpinner().start(`Fetching ${ref} from ${sourceRemoteUrl}`);
8
8
  const relativeSourceDir = (0, path_1.relative)(gitClient.root, (0, path_1.join)(gitClient.root, source));
9
+ const message = relativeSourceDir.trim()
10
+ ? `Filtering git history to only include files in ${relativeSourceDir}`
11
+ : `Filtering git history`;
9
12
  if (await gitClient.hasFilterRepoInstalled()) {
10
- spinner.start(`Filtering git history to only include files in ${relativeSourceDir}`);
13
+ spinner.start(message);
11
14
  await gitClient.filterRepo(relativeSourceDir, relativeDestination);
12
15
  }
13
16
  else {
14
- spinner.start(`Filtering git history to only include files in ${relativeSourceDir} (this might take a few minutes -- install git-filter-repo for faster performance)`);
17
+ spinner.start(`${message} (this might take a few minutes -- install git-filter-repo for faster performance)`);
15
18
  await gitClient.filterBranch(relativeSourceDir, relativeDestination, tempImportBranch);
16
19
  }
17
- spinner.succeed(`Filtered git history to only include files in ${relativeSourceDir}`);
20
+ spinner.succeed(relativeSourceDir.trim()
21
+ ? `Filtered git history to only include files in ${relativeSourceDir}`
22
+ : `Filtered git history`);
18
23
  spinner.succeed(`${sourceRemoteUrl} has been prepared to be imported into this workspace on a temporary branch: ${tempImportBranch} in ${gitClient.root}`);
19
24
  }
20
25
  function wait(ms) {
@@ -37,16 +37,16 @@ async function resetHandler(args) {
37
37
  try {
38
38
  await killDaemon();
39
39
  }
40
- catch {
41
- errors.push('Failed to stop the Nx Daemon.');
40
+ catch (e) {
41
+ errors.push('Failed to stop the Nx Daemon.', e.toString());
42
42
  }
43
43
  }
44
44
  if (all || args.onlyCache) {
45
45
  try {
46
46
  await cleanupCacheEntries();
47
47
  }
48
- catch {
49
- errors.push('Failed to clean up the cache directory.');
48
+ catch (e) {
49
+ errors.push('Failed to clean up the cache directory.', e.toString());
50
50
  }
51
51
  }
52
52
  if (all || args.onlyWorkspaceData) {
@@ -59,12 +59,17 @@ async function resetHandler(args) {
59
59
  try {
60
60
  await cleanupWorkspaceData();
61
61
  }
62
- catch {
63
- errors.push('Failed to clean up the workspace data directory.');
62
+ catch (e) {
63
+ errors.push('Failed to clean up the workspace data directory.', e.toString());
64
64
  }
65
65
  }
66
66
  if (all || args.onlyCloud) {
67
- await resetCloudClient();
67
+ try {
68
+ await resetCloudClient();
69
+ }
70
+ catch (e) {
71
+ errors.push('Failed to reset the Nx Cloud client.', e.toString());
72
+ }
68
73
  }
69
74
  if (errors.length > 0) {
70
75
  output_1.output.error({
@@ -79,8 +84,10 @@ async function resetHandler(args) {
79
84
  });
80
85
  }
81
86
  }
82
- function killDaemon() {
83
- return client_1.daemonClient.stop();
87
+ async function killDaemon() {
88
+ if (client_1.daemonClient.enabled()) {
89
+ return client_1.daemonClient.stop();
90
+ }
84
91
  }
85
92
  async function resetCloudClient() {
86
93
  // Remove nx cloud marker files. This helps if the use happens to run `nx-cloud start-ci-run` or
@@ -25,7 +25,7 @@ async function handleHashTasks(payload) {
25
25
  const nxJson = (0, configuration_1.readNxJson)();
26
26
  if (projectGraph !== storedProjectGraph) {
27
27
  storedProjectGraph = projectGraph;
28
- storedHasher = new task_hasher_1.InProcessTaskHasher(fileMap?.projectFileMap, allWorkspaceFiles, projectGraph, nxJson, rustReferences, payload.runnerOptions);
28
+ storedHasher = new task_hasher_1.InProcessTaskHasher(projectGraph, nxJson, rustReferences, payload.runnerOptions);
29
29
  }
30
30
  const response = JSON.stringify(await storedHasher.hashTasks(payload.tasks, payload.taskGraph, payload.env));
31
31
  return {
@@ -16,22 +16,11 @@ let pseudoTerminal;
16
16
  const childProcesses = new Set();
17
17
  function loadEnvVarsFile(path, env = {}) {
18
18
  (0, task_env_1.unloadDotEnvFile)(path, env);
19
- const result = (0, task_env_1.loadAndExpandDotEnvFile)(path, env, true);
19
+ const result = (0, task_env_1.loadAndExpandDotEnvFile)(path, env);
20
20
  if (result.error) {
21
21
  throw result.error;
22
22
  }
23
23
  }
24
- function loadEnvVars(path, env = {}) {
25
- if (path) {
26
- loadEnvVarsFile(path, env);
27
- }
28
- else {
29
- try {
30
- loadEnvVarsFile('.env', env);
31
- }
32
- catch { }
33
- }
34
- }
35
24
  const propKeys = [
36
25
  'command',
37
26
  'commands',
@@ -292,20 +281,24 @@ function calculateCwd(cwd, context) {
292
281
  return cwd;
293
282
  return path.join(context.root, cwd);
294
283
  }
295
- function processEnv(color, cwd, env, envFile) {
296
- const localEnv = (0, npm_run_path_1.env)({ cwd: cwd ?? process.cwd() });
297
- let res = {
284
+ /**
285
+ * Env variables are processed in the following order:
286
+ * - env option from executor options
287
+ * - env file from envFile option if provided
288
+ * - local env variables
289
+ */
290
+ function processEnv(color, cwd, envOptionFromExecutor, envFile) {
291
+ let localEnv = (0, npm_run_path_1.env)({ cwd: cwd ?? process.cwd() });
292
+ localEnv = {
298
293
  ...process.env,
299
294
  ...localEnv,
300
295
  };
301
- // env file from envFile option takes priority over process env
302
- if (process.env.NX_LOAD_DOT_ENV_FILES !== 'false') {
303
- loadEnvVars(envFile, res);
296
+ if (process.env.NX_LOAD_DOT_ENV_FILES !== 'false' && envFile) {
297
+ loadEnvVarsFile(envFile, localEnv);
304
298
  }
305
- // env variables from env option takes priority over everything else
306
- res = {
307
- ...res,
308
- ...env,
299
+ let res = {
300
+ ...localEnv,
301
+ ...envOptionFromExecutor,
309
302
  };
310
303
  // need to override PATH to make sure we are using the local node_modules
311
304
  if (localEnv.PATH)
@@ -69,7 +69,8 @@ function updateProjectConfiguration(tree, projectName, projectConfiguration) {
69
69
  function updateProjectConfigurationInPackageJson(tree, projectName, projectConfiguration) {
70
70
  const packageJsonFile = (0, path_2.joinPathFragments)(projectConfiguration.root, 'package.json');
71
71
  const packageJson = (0, json_1.readJson)(tree, packageJsonFile);
72
- if (packageJson.name === projectConfiguration.name ?? projectName) {
72
+ projectConfiguration.name = projectName;
73
+ if (packageJson.name === projectConfiguration.name) {
73
74
  delete projectConfiguration.name;
74
75
  }
75
76
  if (projectConfiguration.targets &&
@@ -10,6 +10,6 @@ function createTaskHasher(projectGraph, nxJson, runnerOptions) {
10
10
  }
11
11
  else {
12
12
  const { fileMap, allWorkspaceFiles, rustReferences } = (0, build_project_graph_1.getFileMap)();
13
- return new task_hasher_1.InProcessTaskHasher(fileMap?.projectFileMap, allWorkspaceFiles, projectGraph, nxJson, rustReferences, runnerOptions);
13
+ return new task_hasher_1.InProcessTaskHasher(projectGraph, nxJson, rustReferences, runnerOptions);
14
14
  }
15
15
  }
@@ -2,5 +2,7 @@ import { Task, TaskGraph } from '../config/task-graph';
2
2
  import { TaskHasher } from './task-hasher';
3
3
  import { ProjectGraph } from '../config/project-graph';
4
4
  import { NxJsonConfiguration } from '../config/nx-json';
5
- export declare function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher: TaskHasher, projectGraph: ProjectGraph, taskGraph: TaskGraph, nxJson: NxJsonConfiguration): Promise<void>;
6
- export declare function hashTask(hasher: TaskHasher, projectGraph: ProjectGraph, taskGraph: TaskGraph, task: Task, env: NodeJS.ProcessEnv): Promise<void>;
5
+ import { TaskDetails } from '../native';
6
+ export declare function getTaskDetails(): TaskDetails | null;
7
+ export declare function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher: TaskHasher, projectGraph: ProjectGraph, taskGraph: TaskGraph, nxJson: NxJsonConfiguration, tasksDetails: TaskDetails | null): Promise<void>;
8
+ export declare function hashTask(hasher: TaskHasher, projectGraph: ProjectGraph, taskGraph: TaskGraph, task: Task, env: NodeJS.ProcessEnv, taskDetails: TaskDetails | null): Promise<void>;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTaskDetails = getTaskDetails;
3
4
  exports.hashTasksThatDoNotDependOnOutputsOfOtherTasks = hashTasksThatDoNotDependOnOutputsOfOtherTasks;
4
5
  exports.hashTask = hashTask;
5
6
  const utils_1 = require("../tasks-runner/utils");
@@ -19,9 +20,8 @@ function getTaskDetails() {
19
20
  }
20
21
  return taskDetails;
21
22
  }
22
- async function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher, projectGraph, taskGraph, nxJson) {
23
+ async function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher, projectGraph, taskGraph, nxJson, tasksDetails) {
23
24
  performance.mark('hashMultipleTasks:start');
24
- const taskDetails = getTaskDetails();
25
25
  const tasks = Object.values(taskGraph.tasks);
26
26
  const tasksWithHashers = await Promise.all(tasks.map(async (task) => {
27
27
  const customHasher = (0, utils_1.getCustomHasher)(task, projectGraph);
@@ -42,9 +42,8 @@ async function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher, projectGrap
42
42
  tasksToHash[i].hash = hashes[i].value;
43
43
  tasksToHash[i].hashDetails = hashes[i].details;
44
44
  }
45
- // TODO: Remove if when sqlite is always on
46
- if (taskDetails) {
47
- taskDetails.recordTaskDetails(tasksToHash.map((task) => ({
45
+ if (tasksDetails?.recordTaskDetails) {
46
+ tasksDetails.recordTaskDetails(tasksToHash.map((task) => ({
48
47
  hash: task.hash,
49
48
  project: task.target.project,
50
49
  target: task.target.target,
@@ -54,9 +53,8 @@ async function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher, projectGrap
54
53
  performance.mark('hashMultipleTasks:end');
55
54
  performance.measure('hashMultipleTasks', 'hashMultipleTasks:start', 'hashMultipleTasks:end');
56
55
  }
57
- async function hashTask(hasher, projectGraph, taskGraph, task, env) {
56
+ async function hashTask(hasher, projectGraph, taskGraph, task, env, taskDetails) {
58
57
  performance.mark('hashSingleTask:start');
59
- const taskDetails = getTaskDetails();
60
58
  const customHasher = (0, utils_1.getCustomHasher)(task, projectGraph);
61
59
  const projectsConfigurations = (0, project_graph_1.readProjectsConfigurationFromProjectGraph)(projectGraph);
62
60
  const { value, details } = await (customHasher
@@ -72,8 +70,7 @@ async function hashTask(hasher, projectGraph, taskGraph, task, env) {
72
70
  : hasher.hashTask(task, taskGraph, env));
73
71
  task.hash = value;
74
72
  task.hashDetails = details;
75
- // TODO: Remove if when wasm supports sqlite
76
- if (taskDetails) {
73
+ if (taskDetails?.recordTaskDetails) {
77
74
  taskDetails.recordTaskDetails([
78
75
  {
79
76
  hash: task.hash,
@@ -1,4 +1,4 @@
1
- import { FileData, ProjectFileMap, ProjectGraph, ProjectGraphProjectNode } from '../config/project-graph';
1
+ import { FileData, ProjectGraph, ProjectGraphProjectNode } from '../config/project-graph';
2
2
  import { NxJsonConfiguration } from '../config/nx-json';
3
3
  import { Task, TaskGraph } from '../config/task-graph';
4
4
  import { DaemonClient } from '../daemon/client/client';
@@ -66,16 +66,12 @@ export declare class DaemonBasedTaskHasher implements TaskHasher {
66
66
  hashTask(task: Task, taskGraph?: TaskGraph, env?: NodeJS.ProcessEnv): Promise<Hash>;
67
67
  }
68
68
  export declare class InProcessTaskHasher implements TaskHasher {
69
- private readonly projectFileMap;
70
- private readonly allWorkspaceFiles;
71
69
  private readonly projectGraph;
72
70
  private readonly nxJson;
73
71
  private readonly externalRustReferences;
74
72
  private readonly options;
75
- static version: string;
76
73
  private taskHasher;
77
- private useNativeTaskHasher;
78
- constructor(projectFileMap: ProjectFileMap, allWorkspaceFiles: FileData[], projectGraph: ProjectGraph, nxJson: NxJsonConfiguration, externalRustReferences: NxWorkspaceFilesExternals | null, options: any);
74
+ constructor(projectGraph: ProjectGraph, nxJson: NxJsonConfiguration, externalRustReferences: NxWorkspaceFilesExternals | null, options: any);
79
75
  hashTasks(tasks: Task[], taskGraph?: TaskGraph, env?: NodeJS.ProcessEnv): Promise<Hash[]>;
80
76
  hashTask(task: Task, taskGraph?: TaskGraph, env?: NodeJS.ProcessEnv): Promise<Hash>;
81
77
  private createHashDetails;
@@ -11,7 +11,6 @@ exports.expandSingleProjectInputs = expandSingleProjectInputs;
11
11
  exports.expandNamedInput = expandNamedInput;
12
12
  exports.filterUsingGlobPatterns = filterUsingGlobPatterns;
13
13
  const file_hasher_1 = require("./file-hasher");
14
- const node_task_hasher_impl_1 = require("./node-task-hasher-impl");
15
14
  const minimatch_1 = require("minimatch");
16
15
  const native_task_hasher_impl_1 = require("./native-task-hasher-impl");
17
16
  const workspace_root_1 = require("../utils/workspace-root");
@@ -29,42 +28,18 @@ class DaemonBasedTaskHasher {
29
28
  }
30
29
  exports.DaemonBasedTaskHasher = DaemonBasedTaskHasher;
31
30
  class InProcessTaskHasher {
32
- constructor(projectFileMap, allWorkspaceFiles, projectGraph, nxJson, externalRustReferences, options) {
33
- this.projectFileMap = projectFileMap;
34
- this.allWorkspaceFiles = allWorkspaceFiles;
31
+ constructor(projectGraph, nxJson, externalRustReferences, options) {
35
32
  this.projectGraph = projectGraph;
36
33
  this.nxJson = nxJson;
37
34
  this.externalRustReferences = externalRustReferences;
38
35
  this.options = options;
39
- this.useNativeTaskHasher = process.env.NX_NATIVE_TASK_HASHER !== 'false';
40
- const legacyRuntimeInputs = (this.options && this.options.runtimeCacheInputs
41
- ? this.options.runtimeCacheInputs
42
- : []).map((r) => ({ runtime: r }));
43
- if (process.env.NX_CLOUD_ENCRYPTION_KEY) {
44
- legacyRuntimeInputs.push({ env: 'NX_CLOUD_ENCRYPTION_KEY' });
45
- }
46
- const legacyFilesetInputs = [
47
- 'nx.json',
48
- // ignore files will change the set of inputs to the hasher
49
- '.gitignore',
50
- '.nxignore',
51
- ].map((d) => ({ fileset: `{workspaceRoot}/${d}` }));
52
- this.taskHasher = !this.useNativeTaskHasher
53
- ? new node_task_hasher_impl_1.NodeTaskHasherImpl(nxJson, legacyRuntimeInputs, legacyFilesetInputs, this.projectFileMap, this.allWorkspaceFiles, this.projectGraph, {
54
- selectivelyHashTsConfig: this.options?.selectivelyHashTsConfig ?? false,
55
- })
56
- : new native_task_hasher_impl_1.NativeTaskHasherImpl(workspace_root_1.workspaceRoot, nxJson, this.projectGraph, this.externalRustReferences, {
57
- selectivelyHashTsConfig: this.options?.selectivelyHashTsConfig ?? false,
58
- });
36
+ this.taskHasher = new native_task_hasher_impl_1.NativeTaskHasherImpl(workspace_root_1.workspaceRoot, this.nxJson, this.projectGraph, this.externalRustReferences, {
37
+ selectivelyHashTsConfig: this.options?.selectivelyHashTsConfig ?? false,
38
+ });
59
39
  }
60
40
  async hashTasks(tasks, taskGraph, env) {
61
- if (this.useNativeTaskHasher) {
62
- const hashes = await this.taskHasher.hashTasks(tasks, taskGraph, env ?? process.env);
63
- return tasks.map((task, index) => this.createHashDetails(task, hashes[index]));
64
- }
65
- else {
66
- return await Promise.all(tasks.map((t) => this.hashTask(t, taskGraph, env)));
67
- }
41
+ const hashes = await this.taskHasher.hashTasks(tasks, taskGraph, env ?? process.env);
42
+ return tasks.map((task, index) => this.createHashDetails(task, hashes[index]));
68
43
  }
69
44
  async hashTask(task, taskGraph, env) {
70
45
  const res = await this.taskHasher.hashTask(task, taskGraph, env ?? process.env);
@@ -98,7 +73,6 @@ class InProcessTaskHasher {
98
73
  }
99
74
  }
100
75
  exports.InProcessTaskHasher = InProcessTaskHasher;
101
- InProcessTaskHasher.version = '3.0';
102
76
  const DEFAULT_INPUTS = [
103
77
  {
104
78
  fileset: '{projectRoot}/**/*',
Binary file
@@ -4,7 +4,6 @@ exports.ForkedProcessTaskRunner = void 0;
4
4
  const fs_1 = require("fs");
5
5
  const child_process_1 = require("child_process");
6
6
  const chalk = require("chalk");
7
- const logTransformer = require("strong-log-transformer");
8
7
  const output_1 = require("../utils/output");
9
8
  const utils_1 = require("./utils");
10
9
  const path_1 = require("path");
@@ -208,16 +207,16 @@ class ForkedProcessTaskRunner {
208
207
  const prefixText = `${task.target.project}:`;
209
208
  p.stdout
210
209
  .pipe(logClearLineToPrefixTransformer(color.bold(prefixText) + ' '))
211
- .pipe(logTransformer({ tag: color.bold(prefixText) }))
210
+ .pipe(addPrefixTransformer(color.bold(prefixText)))
212
211
  .pipe(process.stdout);
213
212
  p.stderr
214
213
  .pipe(logClearLineToPrefixTransformer(color(prefixText) + ' '))
215
- .pipe(logTransformer({ tag: color(prefixText) }))
214
+ .pipe(addPrefixTransformer(color(prefixText)))
216
215
  .pipe(process.stderr);
217
216
  }
218
217
  else {
219
- p.stdout.pipe(logTransformer()).pipe(process.stdout);
220
- p.stderr.pipe(logTransformer()).pipe(process.stderr);
218
+ p.stdout.pipe(addPrefixTransformer()).pipe(process.stdout);
219
+ p.stderr.pipe(addPrefixTransformer()).pipe(process.stderr);
221
220
  }
222
221
  }
223
222
  let outWithErr = [];
@@ -403,3 +402,15 @@ function logClearLineToPrefixTransformer(prefix) {
403
402
  },
404
403
  });
405
404
  }
405
+ function addPrefixTransformer(prefix) {
406
+ const newLineSeparator = process.platform.startsWith('win') ? '\r\n' : '\n';
407
+ return new stream_1.Transform({
408
+ transform(chunk, _encoding, callback) {
409
+ const list = chunk.toString().split(/\r\n|[\n\v\f\r\x85\u2028\u2029]/g);
410
+ list
411
+ .filter(Boolean)
412
+ .forEach((m) => this.push(prefix ? prefix + ' ' + m + newLineSeparator : m + newLineSeparator));
413
+ callback();
414
+ },
415
+ });
416
+ }
@@ -363,12 +363,14 @@ function setEnvVarsBasedOnArgs(nxArgs, loadDotEnvFiles) {
363
363
  }
364
364
  async function invokeTasksRunner({ tasks, projectGraph, taskGraph, lifeCycle, nxJson, nxArgs, loadDotEnvFiles, initiatingProject, }) {
365
365
  setEnvVarsBasedOnArgs(nxArgs, loadDotEnvFiles);
366
+ // this needs to be done before we start to run the tasks
367
+ const taskDetails = (0, hash_task_1.getTaskDetails)();
366
368
  const { tasksRunner, runnerOptions } = getRunner(nxArgs, nxJson);
367
369
  let hasher = (0, create_task_hasher_1.createTaskHasher)(projectGraph, nxJson, runnerOptions);
368
370
  // this is used for two reasons: to fetch all remote cache hits AND
369
371
  // to submit everything that is known in advance to Nx Cloud to run in
370
372
  // a distributed fashion
371
- await (0, hash_task_1.hashTasksThatDoNotDependOnOutputsOfOtherTasks)(hasher, projectGraph, taskGraph, nxJson);
373
+ await (0, hash_task_1.hashTasksThatDoNotDependOnOutputsOfOtherTasks)(hasher, projectGraph, taskGraph, nxJson, taskDetails);
372
374
  const taskResultsLifecycle = new task_results_life_cycle_1.TaskResultsLifeCycle();
373
375
  const compositedLifeCycle = new life_cycle_1.CompositeLifeCycle([
374
376
  ...constructLifeCycles(lifeCycle),
@@ -15,6 +15,7 @@ export declare class TaskOrchestrator {
15
15
  private readonly bail;
16
16
  private readonly daemon;
17
17
  private readonly outputStyle;
18
+ private taskDetails;
18
19
  private cache;
19
20
  private forkedProcessTaskRunner;
20
21
  private tasksSchedule;
@@ -27,6 +27,7 @@ class TaskOrchestrator {
27
27
  this.bail = bail;
28
28
  this.daemon = daemon;
29
29
  this.outputStyle = outputStyle;
30
+ this.taskDetails = (0, hash_task_1.getTaskDetails)();
30
31
  this.cache = (0, cache_1.getCache)(this.nxJson, this.options);
31
32
  this.forkedProcessTaskRunner = new forked_process_task_runner_1.ForkedProcessTaskRunner(this.options);
32
33
  this.tasksSchedule = new tasks_schedule_1.TasksSchedule(this.projectGraph, this.taskGraph, this.options);
@@ -93,7 +94,7 @@ class TaskOrchestrator {
93
94
  const task = this.taskGraph.tasks[taskId];
94
95
  const taskSpecificEnv = (0, task_env_1.getTaskSpecificEnv)(task);
95
96
  if (!task.hash) {
96
- await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, taskSpecificEnv);
97
+ await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, taskSpecificEnv, this.taskDetails);
97
98
  }
98
99
  await this.options.lifeCycle.scheduleTask(task);
99
100
  return taskSpecificEnv;
@@ -101,7 +102,7 @@ class TaskOrchestrator {
101
102
  async processScheduledBatch(batch) {
102
103
  await Promise.all(Object.values(batch.taskGraph.tasks).map(async (task) => {
103
104
  if (!task.hash) {
104
- await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, this.batchEnv);
105
+ await (0, hash_task_1.hashTask)(this.hasher, this.projectGraph, this.taskGraph, task, this.batchEnv, this.taskDetails);
105
106
  }
106
107
  await this.options.lifeCycle.scheduleTask(task);
107
108
  }));
@@ -321,6 +322,9 @@ class TaskOrchestrator {
321
322
  };
322
323
  }
323
324
  catch (e) {
325
+ if (process.env.NX_VERBOSE_LOGGING === 'true') {
326
+ console.error(e);
327
+ }
324
328
  return {
325
329
  code: 1,
326
330
  };
@@ -19,6 +19,7 @@ export declare class TasksSchedule {
19
19
  private completedTasks;
20
20
  private scheduleRequestsExecutionChain;
21
21
  private estimatedTaskTimings;
22
+ private projectDependencies;
22
23
  constructor(projectGraph: ProjectGraph, taskGraph: TaskGraph, options: DefaultTasksRunnerOptions);
23
24
  init(): Promise<void>;
24
25
  scheduleNextTasks(): Promise<void>;
@@ -20,12 +20,16 @@ class TasksSchedule {
20
20
  this.completedTasks = new Set();
21
21
  this.scheduleRequestsExecutionChain = Promise.resolve();
22
22
  this.estimatedTaskTimings = {};
23
+ this.projectDependencies = {};
23
24
  }
24
25
  async init() {
25
26
  if (this.taskHistory) {
26
27
  this.estimatedTaskTimings =
27
28
  await this.taskHistory.getEstimatedTaskTimings(Object.values(this.taskGraph.tasks).map((t) => t.target));
28
29
  }
30
+ for (const project of Object.values(this.taskGraph.tasks).map((t) => t.target.project)) {
31
+ this.projectDependencies[project] ??= (0, project_graph_utils_1.findAllProjectNodeDependencies)(project, this.reverseProjectGraph).length;
32
+ }
29
33
  }
30
34
  async scheduleNextTasks() {
31
35
  this.scheduleRequestsExecutionChain =
@@ -90,8 +94,8 @@ class TasksSchedule {
90
94
  // Most likely tasks with no dependencies such as test
91
95
  const project1 = this.taskGraph.tasks[taskId1].target.project;
92
96
  const project2 = this.taskGraph.tasks[taskId2].target.project;
93
- const project1NodeDependencies = (0, project_graph_utils_1.findAllProjectNodeDependencies)(project1, this.reverseProjectGraph).length;
94
- const project2NodeDependencies = (0, project_graph_utils_1.findAllProjectNodeDependencies)(project2, this.reverseProjectGraph).length;
97
+ const project1NodeDependencies = this.projectDependencies[project1];
98
+ const project2NodeDependencies = this.projectDependencies[project2];
95
99
  const dependenciesDiff = project2NodeDependencies - project1NodeDependencies;
96
100
  if (dependenciesDiff !== 0) {
97
101
  return dependenciesDiff;
@@ -52,6 +52,7 @@ export interface PackageJson {
52
52
  packages: string[];
53
53
  };
54
54
  publishConfig?: Record<string, string>;
55
+ files?: string[];
55
56
  nx?: NxProjectPackageJsonConfiguration;
56
57
  generators?: string;
57
58
  schematics?: string;
@@ -47,7 +47,7 @@ function listAlsoAvailableCorePlugins(installedPlugins) {
47
47
  }
48
48
  }
49
49
  function listPowerpackPlugins() {
50
- const powerpackLink = 'https://nx.dev/plugin-registry';
50
+ const powerpackLink = 'https://nx.dev/plugin-registry#powerpack';
51
51
  output_1.output.log({
52
52
  title: `Available Powerpack Plugins: ${powerpackLink}`,
53
53
  });
@@ -1,48 +0,0 @@
1
- import { NxJsonConfiguration } from '../config/nx-json';
2
- import { FileData, ProjectFileMap, ProjectGraph } from '../config/project-graph';
3
- import { Task, TaskGraph } from '../config/task-graph';
4
- import { PartialHash, TaskHasherImpl } from './task-hasher';
5
- export declare class NodeTaskHasherImpl implements TaskHasherImpl {
6
- private readonly nxJson;
7
- private readonly legacyRuntimeInputs;
8
- private readonly legacyFilesetInputs;
9
- private readonly projectFileMap;
10
- private readonly allWorkspaceFiles;
11
- private readonly projectGraph;
12
- private readonly options;
13
- private filesetHashes;
14
- private runtimeHashes;
15
- private externalDependencyHashes;
16
- private allExternalDependenciesHash;
17
- private projectRootMappings;
18
- constructor(nxJson: NxJsonConfiguration, legacyRuntimeInputs: {
19
- runtime: string;
20
- }[], legacyFilesetInputs: {
21
- fileset: string;
22
- }[], projectFileMap: ProjectFileMap, allWorkspaceFiles: FileData[], projectGraph: ProjectGraph, options: {
23
- selectivelyHashTsConfig: boolean;
24
- });
25
- hashTasks(tasks: Task[], taskGraph: TaskGraph, env: NodeJS.ProcessEnv): Promise<PartialHash[]>;
26
- hashTask(task: Task, taskGraph: TaskGraph, env: NodeJS.ProcessEnv, visited?: string[]): Promise<PartialHash>;
27
- private hashNamedInputForDependencies;
28
- private hashSelfAndDepsInputs;
29
- private combinePartialHashes;
30
- private hashDepsInputs;
31
- private hashDepsOutputs;
32
- private hashDepOuputs;
33
- private hashFiles;
34
- private getExternalDependencyHash;
35
- private hashSingleExternalDependency;
36
- private hashExternalDependency;
37
- private hashTarget;
38
- private findExternalDependencyNodeName;
39
- private hashSingleProjectInputs;
40
- private hashProjectInputs;
41
- private hashRootFilesets;
42
- private hashProjectConfig;
43
- private hashTsConfig;
44
- private hashProjectFileset;
45
- private hashRuntime;
46
- private hashEnv;
47
- private calculateExternalDependencyHashes;
48
- }
@@ -1,449 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NodeTaskHasherImpl = void 0;
4
- const find_project_for_path_1 = require("../project-graph/utils/find-project-for-path");
5
- const file_hasher_1 = require("./file-hasher");
6
- const utils_1 = require("../tasks-runner/utils");
7
- const workspace_root_1 = require("../utils/workspace-root");
8
- const minimatch_1 = require("minimatch");
9
- const path_1 = require("path");
10
- const native_1 = require("../native");
11
- const project_graph_utils_1 = require("../utils/project-graph-utils");
12
- const find_matching_projects_1 = require("../utils/find-matching-projects");
13
- const child_process_1 = require("child_process");
14
- const task_hasher_1 = require("./task-hasher");
15
- const hasher_1 = require("../plugins/js/hasher/hasher");
16
- class NodeTaskHasherImpl {
17
- constructor(nxJson, legacyRuntimeInputs, legacyFilesetInputs, projectFileMap, allWorkspaceFiles, projectGraph, options) {
18
- this.nxJson = nxJson;
19
- this.legacyRuntimeInputs = legacyRuntimeInputs;
20
- this.legacyFilesetInputs = legacyFilesetInputs;
21
- this.projectFileMap = projectFileMap;
22
- this.allWorkspaceFiles = allWorkspaceFiles;
23
- this.projectGraph = projectGraph;
24
- this.options = options;
25
- this.filesetHashes = {};
26
- this.runtimeHashes = {};
27
- this.externalDependencyHashes = new Map();
28
- this.projectRootMappings = (0, find_project_for_path_1.createProjectRootMappings)(this.projectGraph.nodes);
29
- // External Dependencies are all calculated up front in a deterministic order
30
- this.calculateExternalDependencyHashes();
31
- }
32
- hashTasks(tasks, taskGraph, env) {
33
- return Promise.all(tasks.map((t) => this.hashTask(t, taskGraph, env, [])));
34
- }
35
- async hashTask(task, taskGraph, env, visited = []) {
36
- return Promise.resolve().then(async () => {
37
- const { selfInputs, depsInputs, depsOutputs, projectInputs } = (0, task_hasher_1.getInputs)(task, this.projectGraph, this.nxJson);
38
- const selfAndInputs = await this.hashSelfAndDepsInputs(task.target.project, task, selfInputs, depsInputs, depsOutputs, projectInputs, taskGraph, env, visited);
39
- const target = this.hashTarget(task.target.project, task.target.target, selfInputs);
40
- if (target) {
41
- return this.combinePartialHashes([selfAndInputs, target]);
42
- }
43
- return selfAndInputs;
44
- });
45
- }
46
- async hashNamedInputForDependencies(projectName, task, namedInput, taskGraph, env, visited) {
47
- const projectNode = this.projectGraph.nodes[projectName];
48
- const namedInputs = {
49
- default: [{ fileset: '{projectRoot}/**/*' }],
50
- ...this.nxJson.namedInputs,
51
- ...projectNode.data.namedInputs,
52
- };
53
- const expandedInputs = (0, task_hasher_1.expandNamedInput)(namedInput, namedInputs);
54
- const selfInputs = expandedInputs.filter(task_hasher_1.isSelfInput);
55
- const depsOutputs = expandedInputs.filter(task_hasher_1.isDepsOutput);
56
- const depsInputs = [{ input: namedInput, dependencies: true }]; // true is boolean by default
57
- return this.hashSelfAndDepsInputs(projectName, task, selfInputs, depsInputs, depsOutputs, [], taskGraph, env, visited);
58
- }
59
- async hashSelfAndDepsInputs(projectName, task, selfInputs, depsInputs, depsOutputs, projectInputs, taskGraph, env, visited) {
60
- const projectGraphDeps = this.projectGraph.dependencies[projectName] ?? [];
61
- // we don't want random order of dependencies to change the hash
62
- projectGraphDeps.sort((a, b) => a.target.localeCompare(b.target));
63
- const self = await this.hashSingleProjectInputs(projectName, selfInputs, env);
64
- const deps = await this.hashDepsInputs(task, depsInputs, projectGraphDeps, taskGraph, env, visited);
65
- const depsOut = await this.hashDepsOutputs(task, depsOutputs, taskGraph);
66
- const projects = await this.hashProjectInputs(projectInputs, env);
67
- return this.combinePartialHashes([
68
- ...self,
69
- ...deps,
70
- ...projects,
71
- ...depsOut,
72
- ]);
73
- }
74
- combinePartialHashes(partialHashes) {
75
- if (partialHashes.length === 1) {
76
- return partialHashes[0];
77
- }
78
- const details = {};
79
- const hashValues = [];
80
- for (const partial of partialHashes) {
81
- hashValues.push(partial.value);
82
- Object.assign(details, partial.details);
83
- }
84
- const value = (0, file_hasher_1.hashArray)(hashValues);
85
- return { value, details };
86
- }
87
- async hashDepsInputs(task, inputs, projectGraphDeps, taskGraph, env, visited) {
88
- return (await Promise.all(inputs.map(async (input) => {
89
- return await Promise.all(projectGraphDeps.map(async (d) => {
90
- if (visited.indexOf(d.target) > -1) {
91
- return null;
92
- }
93
- else {
94
- visited.push(d.target);
95
- if (this.projectGraph.nodes[d.target]) {
96
- return await this.hashNamedInputForDependencies(d.target, task, input.input || 'default', taskGraph, env, visited);
97
- }
98
- else {
99
- return this.getExternalDependencyHash(d.target);
100
- }
101
- }
102
- }));
103
- })))
104
- .flat()
105
- .filter((r) => !!r);
106
- }
107
- async hashDepsOutputs(task, depsOutputs, taskGraph) {
108
- if (depsOutputs.length === 0) {
109
- return [];
110
- }
111
- const result = [];
112
- for (const { dependentTasksOutputFiles, transitive } of depsOutputs) {
113
- result.push(...(await this.hashDepOuputs(task, dependentTasksOutputFiles, taskGraph, transitive)));
114
- }
115
- return result;
116
- }
117
- async hashDepOuputs(task, dependentTasksOutputFiles, taskGraph, transitive) {
118
- // task has no dependencies
119
- if (!taskGraph.dependencies[task.id]) {
120
- return [];
121
- }
122
- const partialHashes = [];
123
- for (const d of taskGraph.dependencies[task.id]) {
124
- const childTask = taskGraph.tasks[d];
125
- const outputs = (0, utils_1.getOutputsForTargetAndConfiguration)(childTask.target, childTask.overrides, this.projectGraph.nodes[childTask.target.project]);
126
- const { getFilesForOutputs } = require('../native');
127
- const outputFiles = getFilesForOutputs(workspace_root_1.workspaceRoot, outputs);
128
- const filteredFiles = outputFiles.filter((p) => p === dependentTasksOutputFiles ||
129
- (0, minimatch_1.minimatch)(p, dependentTasksOutputFiles, { dot: true }));
130
- const hashDetails = {};
131
- const hashes = [];
132
- for (const [file, hash] of this.hashFiles(filteredFiles.map((p) => (0, path_1.join)(workspace_root_1.workspaceRoot, p)))) {
133
- hashes.push(hash);
134
- }
135
- let hash = (0, file_hasher_1.hashArray)(hashes);
136
- partialHashes.push({
137
- value: hash,
138
- details: {
139
- [`${dependentTasksOutputFiles}:${outputs.join(',')}`]: hash,
140
- },
141
- });
142
- if (transitive) {
143
- partialHashes.push(...(await this.hashDepOuputs(childTask, dependentTasksOutputFiles, taskGraph, transitive)));
144
- }
145
- }
146
- return partialHashes;
147
- }
148
- hashFiles(files) {
149
- const r = new Map();
150
- for (let f of files) {
151
- r.set(f, (0, native_1.hashFile)(f));
152
- }
153
- return r;
154
- }
155
- getExternalDependencyHash(externalNodeName) {
156
- const combinedHash = this.combinePartialHashes(this.externalDependencyHashes.get(externalNodeName));
157
- // Set the combined hash into the hashes so it's not recalculated next time
158
- this.externalDependencyHashes.set(externalNodeName, [combinedHash]);
159
- return combinedHash;
160
- }
161
- hashSingleExternalDependency(externalNodeName) {
162
- const node = this.projectGraph.externalNodes[externalNodeName];
163
- if (node.data.hash) {
164
- // we already know the hash of this dependency
165
- return {
166
- value: node.data.hash,
167
- details: {
168
- [externalNodeName]: node.data.hash,
169
- },
170
- };
171
- }
172
- else {
173
- // we take version as a hash
174
- return {
175
- value: node.data.version,
176
- details: {
177
- [externalNodeName]: node.data.version,
178
- },
179
- };
180
- }
181
- }
182
- hashExternalDependency(externalNodeName) {
183
- const partialHashes = new Set();
184
- partialHashes.add(this.hashSingleExternalDependency(externalNodeName));
185
- const deps = (0, project_graph_utils_1.findAllProjectNodeDependencies)(externalNodeName, this.projectGraph, true);
186
- for (const dep of deps) {
187
- partialHashes.add(this.hashSingleExternalDependency(dep));
188
- }
189
- return Array.from(partialHashes);
190
- }
191
- hashTarget(projectName, targetName, selfInputs) {
192
- const projectNode = this.projectGraph.nodes[projectName];
193
- const target = projectNode.data.targets[targetName];
194
- if (!target) {
195
- return;
196
- }
197
- let hash;
198
- // we can only vouch for @nx packages's executor dependencies
199
- // if it's "run commands" or third-party we skip traversing since we have no info what this command depends on
200
- if (target.executor.startsWith(`@nrwl/`) ||
201
- target.executor.startsWith(`@nx/`)) {
202
- const executorPackage = target.executor.split(':')[0];
203
- const executorNodeName = this.findExternalDependencyNodeName(executorPackage);
204
- // This is either a local plugin or a non-existent executor
205
- if (!executorNodeName) {
206
- // TODO: This should not return null if it is a local plugin's executor
207
- return null;
208
- }
209
- return this.getExternalDependencyHash(executorNodeName);
210
- }
211
- else {
212
- // use command external dependencies if available to construct the hash
213
- const partialHashes = [];
214
- let hasCommandExternalDependencies = false;
215
- for (const input of selfInputs) {
216
- if (input['externalDependencies']) {
217
- // if we have externalDependencies with empty array we still want to override the default hash
218
- hasCommandExternalDependencies = true;
219
- const externalDependencies = input['externalDependencies'];
220
- for (let dep of externalDependencies) {
221
- dep = this.findExternalDependencyNodeName(dep);
222
- if (!dep) {
223
- throw new Error(`The externalDependency "${dep}" for "${projectName}:${targetName}" could not be found`);
224
- }
225
- partialHashes.push(this.getExternalDependencyHash(dep));
226
- }
227
- }
228
- }
229
- if (hasCommandExternalDependencies) {
230
- return this.combinePartialHashes(partialHashes);
231
- }
232
- else {
233
- // cache the hash of the entire external dependencies tree
234
- if (this.allExternalDependenciesHash) {
235
- return this.allExternalDependenciesHash;
236
- }
237
- else {
238
- hash = (0, file_hasher_1.hashObject)(this.projectGraph.externalNodes);
239
- this.allExternalDependenciesHash = {
240
- value: hash,
241
- details: {
242
- AllExternalDependencies: hash,
243
- },
244
- };
245
- return this.allExternalDependenciesHash;
246
- }
247
- }
248
- }
249
- }
250
- findExternalDependencyNodeName(packageName) {
251
- if (this.projectGraph.externalNodes[packageName]) {
252
- return packageName;
253
- }
254
- if (this.projectGraph.externalNodes[`npm:${packageName}`]) {
255
- return `npm:${packageName}`;
256
- }
257
- for (const node of Object.values(this.projectGraph.externalNodes)) {
258
- if (node.data.packageName === packageName) {
259
- return node.name;
260
- }
261
- }
262
- // not found
263
- return null;
264
- }
265
- async hashSingleProjectInputs(projectName, inputs, env) {
266
- const filesets = (0, task_hasher_1.extractPatternsFromFileSets)(inputs);
267
- const projectFilesets = [];
268
- const workspaceFilesets = [];
269
- let invalidFilesetNoPrefix = null;
270
- let invalidFilesetWorkspaceRootNegative = null;
271
- for (let f of filesets) {
272
- if (f.startsWith('{projectRoot}/') || f.startsWith('!{projectRoot}/')) {
273
- projectFilesets.push(f);
274
- }
275
- else if (f.startsWith('{workspaceRoot}/') ||
276
- f.startsWith('!{workspaceRoot}/')) {
277
- workspaceFilesets.push(f);
278
- }
279
- else {
280
- invalidFilesetNoPrefix = f;
281
- }
282
- }
283
- if (invalidFilesetNoPrefix) {
284
- throw new Error([
285
- `"${invalidFilesetNoPrefix}" is an invalid fileset.`,
286
- 'All filesets have to start with either {workspaceRoot} or {projectRoot}.',
287
- 'For instance: "!{projectRoot}/**/*.spec.ts" or "{workspaceRoot}/package.json".',
288
- `If "${invalidFilesetNoPrefix}" is a named input, make sure it is defined in, for instance, nx.json.`,
289
- ].join('\n'));
290
- }
291
- if (invalidFilesetWorkspaceRootNegative) {
292
- throw new Error([
293
- `"${invalidFilesetWorkspaceRootNegative}" is an invalid fileset.`,
294
- 'It is not possible to negative filesets starting with {workspaceRoot}.',
295
- ].join('\n'));
296
- }
297
- const notFilesets = inputs.filter((r) => !r['fileset']);
298
- return Promise.all([
299
- this.hashProjectFileset(projectName, projectFilesets),
300
- this.hashProjectConfig(projectName),
301
- this.hashTsConfig(projectName),
302
- ...(workspaceFilesets.length
303
- ? [this.hashRootFilesets(workspaceFilesets)]
304
- : []),
305
- this.hashRootFilesets(this.legacyFilesetInputs.map((r) => r.fileset)),
306
- ...[...notFilesets, ...this.legacyRuntimeInputs].map((r) => r['runtime']
307
- ? this.hashRuntime(env, r['runtime'])
308
- : this.hashEnv(env, r['env'])),
309
- ]);
310
- }
311
- async hashProjectInputs(projectInputs, env) {
312
- const partialHashes = [];
313
- for (const input of projectInputs) {
314
- const projects = (0, find_matching_projects_1.findMatchingProjects)(input.projects, this.projectGraph.nodes);
315
- for (const project of projects) {
316
- const namedInputs = (0, task_hasher_1.getNamedInputs)(this.nxJson, this.projectGraph.nodes[project]);
317
- const expandedInput = (0, task_hasher_1.expandSingleProjectInputs)([{ input: input.input }], namedInputs);
318
- partialHashes.push(this.hashSingleProjectInputs(project, expandedInput, env));
319
- }
320
- }
321
- return Promise.all(partialHashes).then((hashes) => hashes.flat());
322
- }
323
- async hashRootFilesets(filesets) {
324
- const mapKey = `workspace:[${filesets.join(',')}]`;
325
- if (!this.filesetHashes[mapKey]) {
326
- this.filesetHashes[mapKey] = new Promise(async (res) => {
327
- const parts = [];
328
- const negativePatterns = [];
329
- const positivePatterns = [];
330
- for (const fileset of filesets) {
331
- if (fileset.startsWith('!')) {
332
- negativePatterns.push(fileset.substring(17));
333
- }
334
- else {
335
- positivePatterns.push(fileset.substring(16));
336
- }
337
- }
338
- for (const fileset of positivePatterns) {
339
- const withoutWorkspaceRoot = fileset;
340
- // Used to shortcut minimatch if not necessary
341
- const matchingFile = this.allWorkspaceFiles.find((t) => t.file === withoutWorkspaceRoot);
342
- // shortcut because there is a direct match
343
- if (matchingFile) {
344
- if (!negativePatterns.some((p) => (0, minimatch_1.minimatch)(matchingFile.file, p))) {
345
- parts.push(matchingFile.hash);
346
- }
347
- // No direct match, check if pattern matched
348
- }
349
- else {
350
- this.allWorkspaceFiles
351
- .filter((f) => (0, minimatch_1.minimatch)(f.file, withoutWorkspaceRoot) &&
352
- !negativePatterns.some((p) => (0, minimatch_1.minimatch)(f.file, p)))
353
- .forEach((f) => {
354
- parts.push(f.hash);
355
- });
356
- }
357
- }
358
- const value = (0, file_hasher_1.hashArray)(parts);
359
- res({
360
- value,
361
- details: { [mapKey]: value },
362
- });
363
- });
364
- }
365
- return this.filesetHashes[mapKey];
366
- }
367
- hashProjectConfig(projectName) {
368
- const p = this.projectGraph.nodes[projectName];
369
- const projectConfig = (0, file_hasher_1.hashArray)([
370
- JSON.stringify({ ...p.data, files: undefined }),
371
- ]);
372
- return {
373
- value: projectConfig,
374
- details: {
375
- [`${projectName}:ProjectConfiguration`]: projectConfig,
376
- },
377
- };
378
- }
379
- hashTsConfig(projectName) {
380
- const p = this.projectGraph.nodes[projectName];
381
- const tsConfig = (0, file_hasher_1.hashArray)([
382
- (0, hasher_1.hashTsConfig)(p, this.projectRootMappings, this.options),
383
- ]);
384
- return {
385
- value: tsConfig,
386
- details: {
387
- [`${projectName}:TsConfig`]: tsConfig,
388
- },
389
- };
390
- }
391
- async hashProjectFileset(projectName, filesetPatterns) {
392
- const mapKey = `${projectName}:${filesetPatterns.join(',')}`;
393
- if (!this.filesetHashes[mapKey]) {
394
- this.filesetHashes[mapKey] = new Promise(async (res) => {
395
- const p = this.projectGraph.nodes[projectName];
396
- const filteredFiles = (0, task_hasher_1.filterUsingGlobPatterns)(p.data.root, this.projectFileMap[projectName] || [], filesetPatterns);
397
- const files = [];
398
- for (const { file, hash } of filteredFiles) {
399
- files.push(file, hash);
400
- }
401
- const value = (0, file_hasher_1.hashArray)(files);
402
- res({
403
- value,
404
- details: { [mapKey]: value },
405
- });
406
- });
407
- }
408
- return this.filesetHashes[mapKey];
409
- }
410
- async hashRuntime(env, runtime) {
411
- const env_key = JSON.stringify(env);
412
- const mapKey = `runtime:${runtime}-${env_key}`;
413
- if (!this.runtimeHashes[mapKey]) {
414
- this.runtimeHashes[mapKey] = new Promise((res, rej) => {
415
- (0, child_process_1.exec)(runtime, {
416
- windowsHide: true,
417
- cwd: workspace_root_1.workspaceRoot,
418
- env,
419
- }, (err, stdout, stderr) => {
420
- if (err) {
421
- rej(new Error(`Nx failed to execute {runtime: '${runtime}'}. ${err}.`));
422
- }
423
- else {
424
- const value = (0, file_hasher_1.hashArray)([`${stdout}${stderr}`.trim()]);
425
- res({
426
- details: { [`runtime:${runtime}`]: value },
427
- value,
428
- });
429
- }
430
- });
431
- });
432
- }
433
- return this.runtimeHashes[mapKey];
434
- }
435
- async hashEnv(env, envVarName) {
436
- const value = (0, file_hasher_1.hashArray)([env[envVarName] ?? '']);
437
- return {
438
- details: { [`env:${envVarName}`]: value },
439
- value,
440
- };
441
- }
442
- calculateExternalDependencyHashes() {
443
- const keys = Object.keys(this.projectGraph.externalNodes);
444
- for (const externalNodeName of keys) {
445
- this.externalDependencyHashes.set(externalNodeName, this.hashExternalDependency(externalNodeName));
446
- }
447
- }
448
- }
449
- exports.NodeTaskHasherImpl = NodeTaskHasherImpl;