nx 14.3.6 → 14.4.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/package.json +4 -4
  3. package/schemas/nx-schema.json +65 -0
  4. package/schemas/project-schema.json +67 -0
  5. package/src/adapter/compat.js +7 -2
  6. package/src/adapter/compat.js.map +1 -1
  7. package/src/command-line/affected.js +6 -6
  8. package/src/command-line/affected.js.map +1 -1
  9. package/src/command-line/format.js +6 -6
  10. package/src/command-line/format.js.map +1 -1
  11. package/src/command-line/generate.js +7 -3
  12. package/src/command-line/generate.js.map +1 -1
  13. package/src/command-line/print-affected.d.ts +4 -2
  14. package/src/command-line/print-affected.js.map +1 -1
  15. package/src/command-line/read-environment.d.ts +3 -0
  16. package/src/command-line/read-environment.js +3 -0
  17. package/src/command-line/read-environment.js.map +1 -1
  18. package/src/command-line/run-many.js +4 -4
  19. package/src/command-line/run-many.js.map +1 -1
  20. package/src/command-line/run-one.js +7 -7
  21. package/src/command-line/run-one.js.map +1 -1
  22. package/src/command-line/run.d.ts +2 -1
  23. package/src/command-line/run.js +4 -3
  24. package/src/command-line/run.js.map +1 -1
  25. package/src/config/configuration.d.ts +3 -0
  26. package/src/config/configuration.js +3 -0
  27. package/src/config/configuration.js.map +1 -1
  28. package/src/config/nx-json.d.ts +8 -1
  29. package/src/config/project-graph.d.ts +7 -0
  30. package/src/config/project-graph.js.map +1 -1
  31. package/src/config/task-graph.d.ts +3 -3
  32. package/src/config/workspace-json-project-json.d.ts +14 -0
  33. package/src/config/workspaces.js +4 -2
  34. package/src/config/workspaces.js.map +1 -1
  35. package/src/core/dep-graph/environment.js +1 -0
  36. package/src/core/dep-graph/favicon.ico +0 -0
  37. package/src/daemon/client/client.js +1 -1
  38. package/src/daemon/client/client.js.map +1 -1
  39. package/src/generators/utils/project-configuration.js +2 -1
  40. package/src/generators/utils/project-configuration.js.map +1 -1
  41. package/src/hasher/hasher.d.ts +44 -25
  42. package/src/hasher/hasher.js +330 -265
  43. package/src/hasher/hasher.js.map +1 -1
  44. package/src/project-graph/affected/affected-project-graph-models.d.ts +4 -3
  45. package/src/project-graph/affected/affected-project-graph.d.ts +2 -2
  46. package/src/project-graph/affected/affected-project-graph.js +4 -4
  47. package/src/project-graph/affected/affected-project-graph.js.map +1 -1
  48. package/src/project-graph/affected/locators/workspace-json-changes.js +3 -3
  49. package/src/project-graph/affected/locators/workspace-json-changes.js.map +1 -1
  50. package/src/project-graph/affected/locators/workspace-projects.js +4 -4
  51. package/src/project-graph/affected/locators/workspace-projects.js.map +1 -1
  52. package/src/project-graph/build-dependencies/explicit-package-json-dependencies.js +2 -1
  53. package/src/project-graph/build-dependencies/explicit-package-json-dependencies.js.map +1 -1
  54. package/src/project-graph/build-project-graph.d.ts +1 -1
  55. package/src/project-graph/build-project-graph.js +12 -12
  56. package/src/project-graph/build-project-graph.js.map +1 -1
  57. package/src/project-graph/file-utils.d.ts +4 -2
  58. package/src/project-graph/file-utils.js +14 -5
  59. package/src/project-graph/file-utils.js.map +1 -1
  60. package/src/project-graph/project-graph.d.ts +4 -1
  61. package/src/project-graph/project-graph.js +17 -1
  62. package/src/project-graph/project-graph.js.map +1 -1
  63. package/src/tasks-runner/batch/run-batch.js +3 -2
  64. package/src/tasks-runner/batch/run-batch.js.map +1 -1
  65. package/src/tasks-runner/task-orchestrator.d.ts +1 -0
  66. package/src/tasks-runner/task-orchestrator.js +5 -3
  67. package/src/tasks-runner/task-orchestrator.js.map +1 -1
  68. package/src/tasks-runner/tasks-schedule.d.ts +3 -1
  69. package/src/tasks-runner/tasks-schedule.js +9 -7
  70. package/src/tasks-runner/tasks-schedule.js.map +1 -1
  71. package/src/tasks-runner/utils.d.ts +4 -3
  72. package/src/tasks-runner/utils.js +7 -8
  73. package/src/tasks-runner/utils.js.map +1 -1
  74. package/src/utils/command-line-utils.d.ts +2 -1
  75. package/src/utils/command-line-utils.js +2 -4
  76. package/src/utils/command-line-utils.js.map +1 -1
  77. package/src/utils/package-json.d.ts +1 -0
  78. package/src/utils/params.js +6 -1
  79. package/src/utils/params.js.map +1 -1
  80. package/src/utils/path.d.ts +10 -0
  81. package/src/utils/path.js +19 -1
  82. package/src/utils/path.js.map +1 -1
  83. package/src/utils/project-graph-utils.d.ts +2 -2
  84. package/src/utils/versions.d.ts +1 -1
  85. package/src/utils/versions.js +1 -1
@@ -1,24 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Hasher = void 0;
3
+ exports.expandNamedInput = exports.splitInputsIntoSelfAndDependencies = exports.Hasher = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const workspaces_1 = require("../config/workspaces");
6
5
  const child_process_1 = require("child_process");
7
- const fs_1 = require("fs");
8
6
  const minimatch = require("minimatch");
9
- const path_1 = require("path");
10
- const perf_hooks_1 = require("perf_hooks");
7
+ const fs_1 = require("fs");
11
8
  const typescript_1 = require("../utils/typescript");
12
- const workspace_root_1 = require("../utils/workspace-root");
13
- const file_utils_1 = require("../project-graph/file-utils");
14
9
  const hashing_impl_1 = require("./hashing-impl");
15
10
  const fileutils_1 = require("../utils/fileutils");
11
+ const path_1 = require("../utils/path");
12
+ const workspace_root_1 = require("../utils/workspace-root");
13
+ const path_2 = require("path");
16
14
  /**
17
15
  * The default hasher used by executors.
18
16
  */
19
17
  class Hasher {
20
18
  constructor(projectGraph, nxJson, options, hashing = undefined) {
21
- var _a;
19
+ var _a, _b;
22
20
  this.projectGraph = projectGraph;
23
21
  this.nxJson = nxJson;
24
22
  this.options = options;
@@ -29,34 +27,56 @@ class Hasher {
29
27
  // this is only used for testing
30
28
  this.hashing = hashing;
31
29
  }
32
- this.projectHashes = new ProjectHasher(this.projectGraph, this.hashing, {
33
- selectivelyHashTsConfig: (_a = this.options.selectivelyHashTsConfig) !== null && _a !== void 0 ? _a : false,
34
- });
30
+ const legacyRuntimeInputs = (this.options && this.options.runtimeCacheInputs
31
+ ? this.options.runtimeCacheInputs
32
+ : []).map((r) => ({ runtime: r }));
33
+ const legacyFilesetInputs = [
34
+ ...Object.keys((_a = this.nxJson.implicitDependencies) !== null && _a !== void 0 ? _a : {}),
35
+ 'nx.json',
36
+ //TODO: vsavkin move the special cases into explicit ts support
37
+ 'package-lock.json',
38
+ 'yarn.lock',
39
+ 'pnpm-lock.yaml',
40
+ // ignore files will change the set of inputs to the hasher
41
+ '.gitignore',
42
+ '.nxignore',
43
+ ].map((d) => ({ fileset: `{workspaceRoot}/${d}` }));
44
+ this.taskHasher = new TaskHasher(nxJson, legacyRuntimeInputs, legacyFilesetInputs, this.projectGraph, this.readTsConfig(), this.hashing, { selectivelyHashTsConfig: (_b = this.options.selectivelyHashTsConfig) !== null && _b !== void 0 ? _b : false });
35
45
  }
36
- hashTaskWithDepsAndContext(task, filter = 'all-files') {
46
+ hashTask(task) {
37
47
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
48
+ const res = yield this.taskHasher.hashTask(task, [task.target.project]);
38
49
  const command = this.hashCommand(task);
39
- const values = (yield Promise.all([
40
- this.projectHashes.hashProject(task.target.project, [task.target.project], filter),
41
- this.implicitDepsHash(),
42
- this.runtimeInputsHash(),
43
- ]));
44
- const value = this.hashing.hashArray([
45
- Hasher.version,
46
- command,
47
- ...values.map((v) => v.value),
48
- ]);
49
50
  return {
50
- value,
51
+ value: this.hashArray([res.value, command]),
51
52
  details: {
52
53
  command,
53
- nodes: values[0].nodes,
54
- implicitDeps: values[1].files,
55
- runtime: values[2].runtime,
54
+ nodes: res.details,
55
+ implicitDeps: {},
56
+ runtime: {},
56
57
  },
57
58
  };
58
59
  });
59
60
  }
61
+ /**
62
+ * @deprecated use hashTask instead
63
+ */
64
+ hashTaskWithDepsAndContext(task) {
65
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
66
+ return this.hashTask(task);
67
+ });
68
+ }
69
+ /**
70
+ * @deprecated hashTask will hash runtime inputs and global files
71
+ */
72
+ hashContext() {
73
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
74
+ return {
75
+ implicitDeps: '',
76
+ runtime: '',
77
+ };
78
+ });
79
+ }
60
80
  hashCommand(task) {
61
81
  var _a, _b, _c;
62
82
  const overrides = Object.assign({}, task.overrides);
@@ -72,21 +92,13 @@ class Hasher {
72
92
  JSON.stringify(sortedOverrides),
73
93
  ]);
74
94
  }
75
- hashContext() {
76
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
77
- const values = (yield Promise.all([
78
- this.implicitDepsHash(),
79
- this.runtimeInputsHash(),
80
- ]));
81
- return {
82
- implicitDeps: values[0],
83
- runtime: values[1],
84
- };
85
- });
86
- }
95
+ /**
96
+ * @deprecated use hashTask
97
+ */
87
98
  hashSource(task) {
88
99
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
89
- return this.projectHashes.hashProjectNodeSource(task.target.project, 'all-files');
100
+ const hash = yield this.taskHasher.hashTask(task, [task.target.project]);
101
+ return hash.details[`${task.target.project}:$filesets`];
90
102
  });
91
103
  }
92
104
  hashArray(values) {
@@ -95,277 +107,330 @@ class Hasher {
95
107
  hashFile(path) {
96
108
  return this.hashing.hashFile(path);
97
109
  }
98
- runtimeInputsHash() {
99
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
100
- if (this.runtimeInputs)
101
- return this.runtimeInputs;
102
- perf_hooks_1.performance.mark('hasher:runtime inputs hash:start');
103
- this.runtimeInputs = new Promise((res, rej) => tslib_1.__awaiter(this, void 0, void 0, function* () {
104
- const inputs = this.options && this.options.runtimeCacheInputs
105
- ? this.options.runtimeCacheInputs
106
- : [];
107
- if (inputs.length > 0) {
108
- try {
109
- const values = (yield Promise.all(inputs.map((input) => new Promise((res, rej) => {
110
- (0, child_process_1.exec)(input, (err, stdout, stderr) => {
111
- if (err) {
112
- rej(err);
113
- }
114
- else {
115
- res({ input, value: `${stdout}${stderr}`.trim() });
116
- }
117
- });
118
- }))));
119
- const value = this.hashing.hashArray(values.map((v) => v.value));
120
- const runtime = values.reduce((m, c) => ((m[c.input] = c.value), m), {});
121
- perf_hooks_1.performance.mark('hasher:runtime inputs hash:end');
122
- perf_hooks_1.performance.measure('hasher:runtime inputs hash', 'hasher:runtime inputs hash:start', 'hasher:runtime inputs hash:end');
123
- res({ value, runtime });
124
- }
125
- catch (e) {
126
- rej(new Error(`Nx failed to execute runtimeCacheInputs defined in nx.json failed:\n${e.message}`));
127
- }
128
- }
129
- else {
130
- res({ value: '', runtime: {} });
131
- }
132
- }));
133
- return this.runtimeInputs;
134
- });
135
- }
136
- implicitDepsHash() {
137
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
138
- if (this.implicitDependencies)
139
- return this.implicitDependencies;
140
- perf_hooks_1.performance.mark('hasher:implicit deps hash:start');
141
- this.implicitDependencies = new Promise((res) => {
142
- var _a, _b;
143
- const implicitDeps = Object.keys((_a = this.nxJson.implicitDependencies) !== null && _a !== void 0 ? _a : {});
144
- const filesWithoutPatterns = implicitDeps.filter((p) => p.indexOf('*') === -1);
145
- const patterns = implicitDeps.filter((p) => p.indexOf('*') !== -1);
146
- const implicitDepsFromPatterns = patterns.length > 0
147
- ? ((_b = this.projectGraph.allWorkspaceFiles) !== null && _b !== void 0 ? _b : [])
148
- .filter((f) => !!patterns.find((pattern) => minimatch(f.file, pattern)))
149
- .map((f) => f.file)
150
- : [];
151
- const fileNames = [
152
- ...filesWithoutPatterns,
153
- ...implicitDepsFromPatterns,
154
- //TODO: vsavkin move the special cases into explicit ts support
155
- 'package-lock.json',
156
- 'yarn.lock',
157
- 'pnpm-lock.yaml',
158
- // ignore files will change the set of inputs to the hasher
159
- '.gitignore',
160
- '.nxignore',
161
- ];
162
- const fileHashes = [
163
- ...fileNames
164
- .map((maybeRelativePath) => {
165
- // Normalize the path to always be absolute and starting with workspaceRoot so we can check it exists
166
- if (!maybeRelativePath.startsWith(workspace_root_1.workspaceRoot)) {
167
- return (0, path_1.join)(workspace_root_1.workspaceRoot, maybeRelativePath);
168
- }
169
- return maybeRelativePath;
170
- })
171
- .filter((file) => (0, fs_1.existsSync)(file))
172
- .map((file) => {
173
- // we should use default file hasher here
174
- const hash = this.hashing.hashFile(file);
175
- return { file, hash };
176
- }),
177
- ...this.hashNxJson(),
178
- ];
179
- const combinedHash = this.hashing.hashArray(fileHashes.map((v) => v.hash));
180
- perf_hooks_1.performance.mark('hasher:implicit deps hash:end');
181
- perf_hooks_1.performance.measure('hasher:implicit deps hash', 'hasher:implicit deps hash:start', 'hasher:implicit deps hash:end');
182
- res({
183
- value: combinedHash,
184
- files: fileHashes.reduce((m, c) => ((m[c.file] = c.hash), m), {}),
185
- });
186
- });
187
- return this.implicitDependencies;
188
- });
189
- }
190
- hashNxJson() {
191
- const nxJsonPath = (0, path_1.join)(workspace_root_1.workspaceRoot, 'nx.json');
192
- if (!(0, fs_1.existsSync)(nxJsonPath)) {
193
- return [];
194
- }
195
- let nxJsonContents = '{}';
110
+ readTsConfig() {
111
+ var _a;
112
+ var _b;
196
113
  try {
197
- const nxJson = (0, fileutils_1.readJsonFile)(nxJsonPath);
198
- delete nxJson.projects;
199
- nxJsonContents = JSON.stringify(nxJson);
114
+ const res = (0, fileutils_1.readJsonFile)((0, typescript_1.getRootTsConfigFileName)());
115
+ (_a = (_b = res.compilerOptions).paths) !== null && _a !== void 0 ? _a : (_b.paths = {});
116
+ return res;
117
+ }
118
+ catch (_c) {
119
+ return {
120
+ compilerOptions: { paths: {} },
121
+ };
200
122
  }
201
- catch (_a) { }
202
- return [
203
- {
204
- hash: this.hashing.hashArray([nxJsonContents]),
205
- file: 'nx.json',
206
- },
207
- ];
208
123
  }
209
124
  }
210
125
  exports.Hasher = Hasher;
211
- Hasher.version = '2.0';
212
- class ProjectHasher {
213
- constructor(projectGraph, hashing, options) {
126
+ Hasher.version = '3.0';
127
+ const DEFAULT_INPUTS = [
128
+ {
129
+ projects: 'self',
130
+ fileset: 'default',
131
+ },
132
+ {
133
+ projects: 'dependencies',
134
+ input: 'default',
135
+ },
136
+ ];
137
+ class TaskHasher {
138
+ constructor(nxJson, legacyRuntimeInputs, legacyFilesetInputs, projectGraph, tsConfigJson, hashing, options) {
139
+ this.nxJson = nxJson;
140
+ this.legacyRuntimeInputs = legacyRuntimeInputs;
141
+ this.legacyFilesetInputs = legacyFilesetInputs;
214
142
  this.projectGraph = projectGraph;
143
+ this.tsConfigJson = tsConfigJson;
215
144
  this.hashing = hashing;
216
145
  this.options = options;
217
- this.sourceHashes = {};
218
- this.workspaceJson = this.readWorkspaceConfigFile((0, file_utils_1.workspaceFileName)());
219
- this.nxJson = this.readNxJsonConfigFile('nx.json');
220
- this.tsConfigJson = this.readTsConfig();
146
+ this.filesetHashes = {};
147
+ this.runtimeHashes = {};
221
148
  }
222
- hashProject(projectName, visited, filter) {
149
+ hashTask(task, visited) {
223
150
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
224
151
  return Promise.resolve().then(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
225
152
  var _a;
226
- const deps = (_a = this.projectGraph.dependencies[projectName]) !== null && _a !== void 0 ? _a : [];
227
- const depHashes = (yield Promise.all(deps.map((d) => tslib_1.__awaiter(this, void 0, void 0, function* () {
153
+ const projectNode = this.projectGraph.nodes[task.target.project];
154
+ if (!projectNode) {
155
+ return this.hashExternalDependency(task);
156
+ }
157
+ const projectGraphDeps = (_a = this.projectGraph.dependencies[task.target.project]) !== null && _a !== void 0 ? _a : [];
158
+ const { selfInputs, depsInputs } = this.inputs(task, projectNode);
159
+ const self = yield this.hashSelfInputs(task, selfInputs);
160
+ const deps = yield this.hashDepsTasks(depsInputs, projectGraphDeps, visited);
161
+ let details = {};
162
+ for (const s of self) {
163
+ details = Object.assign(Object.assign({}, details), s.details);
164
+ }
165
+ for (const s of deps) {
166
+ details = Object.assign(Object.assign({}, details), s.details);
167
+ }
168
+ const value = this.hashing.hashArray([
169
+ ...self.map((d) => d.value),
170
+ ...deps.map((d) => d.value),
171
+ ]);
172
+ return { value, details };
173
+ }));
174
+ });
175
+ }
176
+ hashDepsTasks(inputs, projectGraphDeps, visited) {
177
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
178
+ return (yield Promise.all(inputs.map((input) => tslib_1.__awaiter(this, void 0, void 0, function* () {
179
+ return yield Promise.all(projectGraphDeps.map((d) => tslib_1.__awaiter(this, void 0, void 0, function* () {
228
180
  if (visited.indexOf(d.target) > -1) {
229
181
  return null;
230
182
  }
231
183
  else {
232
184
  visited.push(d.target);
233
- return yield this.hashProject(d.target, visited, filter);
185
+ return yield this.hashTask({
186
+ id: `${d.target}:$input:${input.input}`,
187
+ target: {
188
+ project: d.target,
189
+ target: '$input',
190
+ configuration: input.input,
191
+ },
192
+ overrides: {},
193
+ }, visited);
234
194
  }
235
- })))).filter((r) => !!r);
236
- const filterForProject = filter === 'all-files'
237
- ? 'all-files'
238
- : filter === 'exclude-tests-of-deps' && visited[0] === projectName
239
- ? 'all-files'
240
- : 'exclude-tests';
241
- const projectHash = yield this.hashProjectNodeSource(projectName, filterForProject);
242
- const nodes = depHashes.reduce((m, c) => {
243
- return Object.assign(Object.assign({}, m), c.nodes);
244
- }, { [projectName]: projectHash });
245
- const value = this.hashing.hashArray([
246
- ...depHashes.map((d) => d.value),
247
- projectHash,
248
- ]);
249
- return { value, nodes };
250
- }));
195
+ })));
196
+ }))))
197
+ .flat()
198
+ .filter((r) => !!r);
199
+ });
200
+ }
201
+ inputs(task, projectNode) {
202
+ if (task.target.target === '$input') {
203
+ return {
204
+ depsInputs: [{ input: task.target.configuration }],
205
+ selfInputs: expandNamedInput(task.target.configuration, Object.assign(Object.assign({}, this.nxJson.namedInputs), projectNode.data.namedInputs)),
206
+ };
207
+ }
208
+ else {
209
+ const targetData = projectNode.data.targets[task.target.target];
210
+ const targetDefaults = (this.nxJson.targetDefaults || {})[task.target.target];
211
+ // task from TaskGraph can be added here
212
+ return splitInputsIntoSelfAndDependencies(targetData.inputs || (targetDefaults === null || targetDefaults === void 0 ? void 0 : targetDefaults.inputs) || DEFAULT_INPUTS, Object.assign(Object.assign({}, this.nxJson.namedInputs), projectNode.data.namedInputs));
213
+ }
214
+ }
215
+ hashExternalDependency(task) {
216
+ var _a;
217
+ const n = this.projectGraph.externalNodes[task.target.project];
218
+ const version = (_a = n === null || n === void 0 ? void 0 : n.data) === null || _a === void 0 ? void 0 : _a.version;
219
+ let hash;
220
+ if (version) {
221
+ hash = this.hashing.hashArray([version]);
222
+ }
223
+ else {
224
+ // unknown dependency
225
+ // this may occur if a file has a dependency to a npm package
226
+ // which is not directly registestered in package.json
227
+ // but only indirectly through dependencies of registered
228
+ // npm packages
229
+ // when it is at a later stage registered in package.json
230
+ // the cache project graph will not know this module but
231
+ // the new project graph will know it
232
+ // The actual checksum added here is of no importance as
233
+ // the version is unknown and may only change when some
234
+ // other change occurs in package.json and/or package-lock.json
235
+ hash = `__${task.target.project}__`;
236
+ }
237
+ return {
238
+ value: hash,
239
+ details: {
240
+ [task.target.project]: version || hash,
241
+ },
242
+ };
243
+ }
244
+ hashSelfInputs(task, inputs) {
245
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
246
+ const filesets = inputs
247
+ .filter((r) => !!r['fileset'])
248
+ .map((r) => r['fileset']);
249
+ const projectFilesets = filesets.filter((r) => !r.startsWith('{workspaceRoot}'));
250
+ const rootFilesets = filesets.filter((r) => r.startsWith('{workspaceRoot}/'));
251
+ return Promise.all([
252
+ this.hashTaskFileset(task, projectFilesets),
253
+ ...[
254
+ ...rootFilesets,
255
+ ...this.legacyFilesetInputs.map((r) => r.fileset),
256
+ ].map((fileset) => this.hashRootFileset(fileset)),
257
+ ...[...inputs, ...this.legacyRuntimeInputs]
258
+ .filter((r) => !r['fileset'])
259
+ .map((r) => r['runtime'] ? this.hashRuntime(r['runtime']) : this.hashEnv(r['env'])),
260
+ ]);
251
261
  });
252
262
  }
253
- hashProjectNodeSource(projectName, filter) {
263
+ hashRootFileset(fileset) {
254
264
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
255
- const mapKey = `${projectName}-${filter}`;
256
- if (!this.sourceHashes[mapKey]) {
257
- this.sourceHashes[mapKey] = new Promise((res) => tslib_1.__awaiter(this, void 0, void 0, function* () {
258
- var _a, _b;
259
- const p = this.projectGraph.nodes[projectName];
260
- if (!p) {
261
- const n = this.projectGraph.externalNodes[projectName];
262
- const version = (_a = n === null || n === void 0 ? void 0 : n.data) === null || _a === void 0 ? void 0 : _a.version;
263
- let hash;
264
- if (version) {
265
- hash = this.hashing.hashArray([version]);
266
- }
267
- else {
268
- // unknown dependency
269
- // this may occur if a file has a dependency to a npm package
270
- // which is not directly registestered in package.json
271
- // but only indirectly through dependencies of registered
272
- // npm packages
273
- // when it is at a later stage registered in package.json
274
- // the cache project graph will not know this module but
275
- // the new project graph will know it
276
- // The actual checksum added here is of no importance as
277
- // the version is unknown and may only change when some
278
- // other change occurs in package.json and/or package-lock.json
279
- hash = `__${projectName}__`;
265
+ const mapKey = fileset;
266
+ const withoutWorkspaceRoot = fileset.substring(16);
267
+ if (!this.filesetHashes[mapKey]) {
268
+ this.filesetHashes[mapKey] = new Promise((res) => tslib_1.__awaiter(this, void 0, void 0, function* () {
269
+ const parts = [];
270
+ if (fileset.indexOf('*') > -1) {
271
+ this.projectGraph.allWorkspaceFiles
272
+ .filter((f) => minimatch(f.file, withoutWorkspaceRoot))
273
+ .forEach((f) => {
274
+ parts.push(this.hashing.hashFile((0, path_2.join)(workspace_root_1.workspaceRoot, f.file)));
275
+ });
276
+ }
277
+ else {
278
+ if ((0, fs_1.existsSync)((0, path_2.join)(workspace_root_1.workspaceRoot, withoutWorkspaceRoot))) {
279
+ parts.push(this.hashing.hashFile((0, path_2.join)(workspace_root_1.workspaceRoot, withoutWorkspaceRoot)));
280
280
  }
281
- res(hash);
282
- return;
283
281
  }
284
- const filteredFiles = filter === 'all-files'
285
- ? p.data.files
286
- : p.data.files.filter((f) => !this.isSpec(f.file));
282
+ const value = this.hashing.hashArray(parts);
283
+ res({
284
+ value,
285
+ details: { [mapKey]: value },
286
+ });
287
+ }));
288
+ }
289
+ return this.filesetHashes[mapKey];
290
+ });
291
+ }
292
+ hashTaskFileset(task, filesetPatterns) {
293
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
294
+ const mapKey = `${task.target.project}:$filesets`;
295
+ if (!this.filesetHashes[mapKey]) {
296
+ this.filesetHashes[mapKey] = new Promise((res) => tslib_1.__awaiter(this, void 0, void 0, function* () {
297
+ const p = this.projectGraph.nodes[task.target.project];
298
+ const filteredFiles = this.filterFiles(p.data.files, filesetPatterns);
287
299
  const fileNames = filteredFiles.map((f) => f.file);
288
300
  const values = filteredFiles.map((f) => f.hash);
289
- const workspaceJson = JSON.stringify((_b = this.workspaceJson.projects[projectName]) !== null && _b !== void 0 ? _b : '');
290
301
  let tsConfig;
291
- if (this.options.selectivelyHashTsConfig) {
292
- tsConfig = this.removeOtherProjectsPathRecords(projectName);
293
- }
294
- else {
295
- tsConfig = JSON.stringify(this.tsConfigJson);
296
- }
297
- res(this.hashing.hashArray([
302
+ tsConfig = this.hashTsConfig(p);
303
+ const value = this.hashing.hashArray([
298
304
  ...fileNames,
299
305
  ...values,
300
- workspaceJson,
306
+ JSON.stringify(Object.assign(Object.assign({}, p.data), { files: undefined })),
301
307
  tsConfig,
302
- ]));
308
+ ]);
309
+ res({
310
+ value,
311
+ details: { [mapKey]: value },
312
+ });
303
313
  }));
304
314
  }
305
- return this.sourceHashes[mapKey];
315
+ return this.filesetHashes[mapKey];
316
+ });
317
+ }
318
+ hashRuntime(runtime) {
319
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
320
+ const mapKey = `runtime:${runtime}`;
321
+ if (!this.runtimeHashes[mapKey]) {
322
+ this.runtimeHashes[mapKey] = new Promise((res, rej) => {
323
+ (0, child_process_1.exec)(runtime, (err, stdout, stderr) => {
324
+ if (err) {
325
+ rej(new Error(`Nx failed to execute {runtime: '${runtime}'}. ${err}.`));
326
+ }
327
+ else {
328
+ const value = `${stdout}${stderr}`.trim();
329
+ res({
330
+ details: { [`runtime:${runtime}`]: value },
331
+ value,
332
+ });
333
+ }
334
+ });
335
+ });
336
+ }
337
+ return this.runtimeHashes[mapKey];
306
338
  });
307
339
  }
308
- isSpec(file) {
309
- return (file.endsWith('.spec.tsx') ||
310
- file.endsWith('.test.tsx') ||
311
- file.endsWith('-test.tsx') ||
312
- file.endsWith('-spec.tsx') ||
313
- file.endsWith('.spec.ts') ||
314
- file.endsWith('.test.ts') ||
315
- file.endsWith('-test.ts') ||
316
- file.endsWith('-spec.ts') ||
317
- file.endsWith('.spec.js') ||
318
- file.endsWith('.test.js') ||
319
- file.endsWith('-test.js') ||
320
- file.endsWith('-spec.js'));
340
+ hashEnv(envVarName) {
341
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
342
+ const value = this.hashing.hashArray([process.env[envVarName]]);
343
+ return {
344
+ details: { [`runtime:${envVarName}`]: value },
345
+ value,
346
+ };
347
+ });
321
348
  }
322
- removeOtherProjectsPathRecords(projectName) {
323
- var _a;
324
- const _b = this.tsConfigJson.compilerOptions, { paths } = _b, compilerOptions = tslib_1.__rest(_b, ["paths"]);
325
- const rootPath = this.workspaceJson.projects[projectName].root.split('/');
349
+ filterFiles(files, patterns) {
350
+ patterns = patterns.filter((p) => p !== 'default');
351
+ if (patterns.length === 0)
352
+ return files;
353
+ return files.filter((f) => !!patterns.find((pattern) => minimatch(f.file, pattern)));
354
+ }
355
+ hashTsConfig(p) {
356
+ if (this.options.selectivelyHashTsConfig) {
357
+ return this.removeOtherProjectsPathRecords(p);
358
+ }
359
+ else {
360
+ return JSON.stringify(this.tsConfigJson);
361
+ }
362
+ }
363
+ removeOtherProjectsPathRecords(p) {
364
+ var _a, _b;
365
+ const _c = this.tsConfigJson.compilerOptions, { paths } = _c, compilerOptions = tslib_1.__rest(_c, ["paths"]);
366
+ const rootPath = p.data.root.split('/');
326
367
  rootPath.shift();
327
- const pathAlias = `@${this.nxJson.npmScope}/${rootPath.join('/')}`;
368
+ const pathAlias = (0, path_1.getImportPath)((_a = this.nxJson) === null || _a === void 0 ? void 0 : _a.npmScope, rootPath.join('/'));
328
369
  return JSON.stringify({
329
370
  compilerOptions: Object.assign(Object.assign({}, compilerOptions), { paths: {
330
- [pathAlias]: (_a = paths[pathAlias]) !== null && _a !== void 0 ? _a : [],
371
+ [pathAlias]: (_b = paths[pathAlias]) !== null && _b !== void 0 ? _b : [],
331
372
  } }),
332
373
  });
333
374
  }
334
- readTsConfig() {
335
- var _a;
336
- var _b;
337
- try {
338
- const res = (0, fileutils_1.readJsonFile)((0, typescript_1.getRootTsConfigFileName)());
339
- (_a = (_b = res.compilerOptions).paths) !== null && _a !== void 0 ? _a : (_b.paths = {});
340
- return res;
341
- }
342
- catch (_c) {
343
- return {
344
- compilerOptions: { paths: {} },
345
- };
346
- }
347
- }
348
- readWorkspaceConfigFile(path) {
349
- var _a;
350
- try {
351
- const res = (0, fileutils_1.readJsonFile)(path);
352
- (_a = res.projects) !== null && _a !== void 0 ? _a : (res.projects = {});
353
- return (0, workspaces_1.resolveNewFormatWithInlineProjects)(res);
375
+ }
376
+ function splitInputsIntoSelfAndDependencies(inputs, namedInputs) {
377
+ const depsInputs = [];
378
+ const selfInputs = [];
379
+ for (const d of inputs) {
380
+ if (typeof d === 'string') {
381
+ if (d.startsWith('^')) {
382
+ depsInputs.push({ input: d.substring(1) });
383
+ }
384
+ else {
385
+ selfInputs.push(d);
386
+ }
354
387
  }
355
- catch (_b) {
356
- return { projects: {}, version: 2 };
388
+ else {
389
+ if (d.projects === 'dependencies') {
390
+ depsInputs.push(d);
391
+ }
392
+ else {
393
+ selfInputs.push(d);
394
+ }
357
395
  }
358
396
  }
359
- readNxJsonConfigFile(path) {
360
- var _a;
361
- try {
362
- const res = (0, fileutils_1.readJsonFile)(path);
363
- (_a = res.projects) !== null && _a !== void 0 ? _a : (res.projects = {});
364
- return res;
397
+ return { depsInputs, selfInputs: expandSelfInputs(selfInputs, namedInputs) };
398
+ }
399
+ exports.splitInputsIntoSelfAndDependencies = splitInputsIntoSelfAndDependencies;
400
+ function expandSelfInputs(inputs, namedInputs) {
401
+ const expanded = [];
402
+ for (const d of inputs) {
403
+ if (typeof d === 'string') {
404
+ if (d.startsWith('^'))
405
+ throw new Error(`namedInputs definitions cannot start with ^`);
406
+ if (namedInputs[d]) {
407
+ expanded.push(...expandNamedInput(d, namedInputs));
408
+ }
409
+ else {
410
+ expanded.push({ fileset: d });
411
+ }
365
412
  }
366
- catch (_b) {
367
- return {};
413
+ else {
414
+ if (d.projects === 'dependencies') {
415
+ throw new Error(`namedInputs definitions cannot contain any inputs with projects == 'dependencies'`);
416
+ }
417
+ if (d.fileset || d.env || d.runtime) {
418
+ expanded.push(d);
419
+ }
420
+ else {
421
+ expanded.push(...expandNamedInput(d.input, namedInputs));
422
+ }
368
423
  }
369
424
  }
425
+ return expanded;
426
+ }
427
+ function expandNamedInput(input, namedInputs) {
428
+ if (input === 'default')
429
+ return [{ fileset: 'default' }];
430
+ namedInputs || (namedInputs = {});
431
+ if (!namedInputs[input])
432
+ throw new Error(`Input '${input}' is not defined`);
433
+ return expandSelfInputs(namedInputs[input], namedInputs);
370
434
  }
435
+ exports.expandNamedInput = expandNamedInput;
371
436
  //# sourceMappingURL=hasher.js.map