nx 20.0.0-beta.4 → 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.4",
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": {
@@ -65,8 +65,7 @@
65
65
  "yargs": "^17.6.2",
66
66
  "yargs-parser": "21.1.1",
67
67
  "node-machine-id": "1.1.12",
68
- "ora": "5.3.0",
69
- "@nrwl/tao": "20.0.0-beta.4"
68
+ "ora": "5.3.0"
70
69
  },
71
70
  "peerDependencies": {
72
71
  "@swc-node/register": "^1.8.0",
@@ -81,16 +80,16 @@
81
80
  }
82
81
  },
83
82
  "optionalDependencies": {
84
- "@nx/nx-darwin-x64": "20.0.0-beta.4",
85
- "@nx/nx-darwin-arm64": "20.0.0-beta.4",
86
- "@nx/nx-linux-x64-gnu": "20.0.0-beta.4",
87
- "@nx/nx-linux-x64-musl": "20.0.0-beta.4",
88
- "@nx/nx-win32-x64-msvc": "20.0.0-beta.4",
89
- "@nx/nx-linux-arm64-gnu": "20.0.0-beta.4",
90
- "@nx/nx-linux-arm64-musl": "20.0.0-beta.4",
91
- "@nx/nx-linux-arm-gnueabihf": "20.0.0-beta.4",
92
- "@nx/nx-win32-arm64-msvc": "20.0.0-beta.4",
93
- "@nx/nx-freebsd-x64": "20.0.0-beta.4"
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"
94
93
  },
95
94
  "nx-migrations": {
96
95
  "migrations": "./migrations.json",
@@ -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)
@@ -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
  }
@@ -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
@@ -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;