1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.updateBuildableProjectPackageJsonDependencies = exports.updatePaths = exports.findMissingBuildDependencies = exports.checkDependentProjectsHaveBeenBuilt = exports.createTmpTsConfig = exports.computeCompilerOptionsPaths = exports.calculateProjectDependencies = void 0;
|
4 | const path_1 = require("path");
|
5 | const fileutils_1 = require("./fileutils");
|
6 | const devkit_1 = require("@nrwl/devkit");
|
7 | const fs_1 = require("fs");
|
8 | const output_1 = require("./output");
|
9 | const operators_1 = require("nx/src/project-graph/operators");
|
10 | const typescript_1 = require("./typescript");
|
11 | let tsModule;
|
12 | function isBuildable(target, node) {
|
13 | return (node.data.targets &&
|
14 | node.data.targets[target] &&
|
15 | node.data.targets[target].executor !== '');
|
16 | }
|
17 | function calculateProjectDependencies(projGraph, root, projectName, targetName, configurationName, shallow) {
|
18 | const target = projGraph.nodes[projectName];
|
19 |
|
20 | const nonBuildableDependencies = [];
|
21 | const topLevelDependencies = [];
|
22 | const collectedDeps = collectDependencies(projectName, projGraph, [], shallow);
|
23 | const missing = collectedDeps.reduce((missing, { name: dep }) => {
|
24 | const depNode = projGraph.nodes[dep] || projGraph.externalNodes[dep];
|
25 | if (!depNode) {
|
26 | missing = missing || [];
|
27 | missing.push(dep);
|
28 | }
|
29 | return missing;
|
30 | }, null);
|
31 | if (missing) {
|
32 | throw new Error(`Unable to find ${missing.join(', ')} in project graph.`);
|
33 | }
|
34 | const dependencies = collectedDeps
|
35 | .map(({ name: dep, isTopLevel }) => {
|
36 | let project = null;
|
37 | const depNode = projGraph.nodes[dep] || projGraph.externalNodes[dep];
|
38 | if (depNode.type === 'lib') {
|
39 | if (isBuildable(targetName, depNode)) {
|
40 | const libPackageJsonPath = (0, path_1.join)(root, depNode.data.root, 'package.json');
|
41 | project = {
|
42 | name: (0, fileutils_1.fileExists)(libPackageJsonPath)
|
43 | ? (0, devkit_1.readJsonFile)(libPackageJsonPath).name
|
44 | : dep,
|
45 | outputs: (0, devkit_1.getOutputsForTargetAndConfiguration)({
|
46 | overrides: {},
|
47 | target: {
|
48 | project: projectName,
|
49 | target: targetName,
|
50 | configuration: configurationName,
|
51 | },
|
52 | }, depNode),
|
53 | node: depNode,
|
54 | };
|
55 | }
|
56 | else {
|
57 | nonBuildableDependencies.push(dep);
|
58 | }
|
59 | }
|
60 | else if (depNode.type === 'npm') {
|
61 | project = {
|
62 | name: depNode.data.packageName,
|
63 | outputs: [],
|
64 | node: depNode,
|
65 | };
|
66 | }
|
67 | if (project && isTopLevel) {
|
68 | topLevelDependencies.push(project);
|
69 | }
|
70 | return project;
|
71 | })
|
72 | .filter((x) => !!x);
|
73 | dependencies.sort((a, b) => (a.name > b.name ? 1 : b.name > a.name ? -1 : 0));
|
74 | return {
|
75 | target,
|
76 | dependencies,
|
77 | nonBuildableDependencies,
|
78 | topLevelDependencies,
|
79 | };
|
80 | }
|
81 | exports.calculateProjectDependencies = calculateProjectDependencies;
|
82 | function collectDependencies(project, projGraph, acc, shallow, areTopLevelDeps = true) {
|
83 | (projGraph.dependencies[project] || []).forEach((dependency) => {
|
84 | if (!acc.some((dep) => dep.name === dependency.target)) {
|
85 |
|
86 |
|
87 | if (dependency.target.startsWith('npm:') &&
|
88 | !projGraph.externalNodes[dependency.target])
|
89 | return;
|
90 | acc.push({ name: dependency.target, isTopLevel: areTopLevelDeps });
|
91 | const isInternalTarget = projGraph.nodes[dependency.target];
|
92 | if (!shallow && isInternalTarget) {
|
93 | collectDependencies(dependency.target, projGraph, acc, shallow, false);
|
94 | }
|
95 | }
|
96 | });
|
97 | return acc;
|
98 | }
|
99 | function readTsConfigWithRemappedPaths(tsConfig, generatedTsConfigPath, dependencies) {
|
100 | const generatedTsConfig = { compilerOptions: {} };
|
101 | generatedTsConfig.extends = (0, path_1.relative)((0, path_1.dirname)(generatedTsConfigPath), tsConfig);
|
102 | generatedTsConfig.compilerOptions.paths = computeCompilerOptionsPaths(tsConfig, dependencies);
|
103 | if (process.env.NX_VERBOSE_LOGGING_PATH_MAPPINGS === 'true') {
|
104 | output_1.output.log({
|
105 | title: 'TypeScript path mappings have been rewritten.',
|
106 | });
|
107 | console.log(JSON.stringify(generatedTsConfig.compilerOptions.paths, null, 2));
|
108 | }
|
109 | return generatedTsConfig;
|
110 | }
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 | function computeCompilerOptionsPaths(tsConfig, dependencies) {
|
118 | const paths = readPaths(tsConfig) || {};
|
119 | updatePaths(dependencies, paths);
|
120 | return paths;
|
121 | }
|
122 | exports.computeCompilerOptionsPaths = computeCompilerOptionsPaths;
|
123 | function readPaths(tsConfig) {
|
124 | var _a;
|
125 | if (!tsModule) {
|
126 | tsModule = (0, typescript_1.ensureTypescript)();
|
127 | }
|
128 | try {
|
129 | let config;
|
130 | if (typeof tsConfig === 'string') {
|
131 | const configFile = tsModule.readConfigFile(tsConfig, tsModule.sys.readFile);
|
132 | config = tsModule.parseJsonConfigFileContent(configFile.config, tsModule.sys, (0, path_1.dirname)(tsConfig));
|
133 | }
|
134 | else {
|
135 | config = tsConfig;
|
136 | }
|
137 | if ((_a = config.options) === null || _a === void 0 ? void 0 : _a.paths) {
|
138 | return config.options.paths;
|
139 | }
|
140 | else {
|
141 | return null;
|
142 | }
|
143 | }
|
144 | catch (e) {
|
145 | return null;
|
146 | }
|
147 | }
|
148 | function createTmpTsConfig(tsconfigPath, workspaceRoot, projectRoot, dependencies) {
|
149 | const tmpTsConfigPath = (0, path_1.join)(workspaceRoot, 'tmp', projectRoot, 'tsconfig.generated.json');
|
150 | const parsedTSConfig = readTsConfigWithRemappedPaths(tsconfigPath, tmpTsConfigPath, dependencies);
|
151 | process.on('exit', () => cleanupTmpTsConfigFile(tmpTsConfigPath));
|
152 | (0, devkit_1.writeJsonFile)(tmpTsConfigPath, parsedTSConfig);
|
153 | return (0, path_1.join)(tmpTsConfigPath);
|
154 | }
|
155 | exports.createTmpTsConfig = createTmpTsConfig;
|
156 | function cleanupTmpTsConfigFile(tmpTsConfigPath) {
|
157 | try {
|
158 | if (tmpTsConfigPath) {
|
159 | (0, fs_1.unlinkSync)(tmpTsConfigPath);
|
160 | }
|
161 | }
|
162 | catch (e) { }
|
163 | }
|
164 | function checkDependentProjectsHaveBeenBuilt(root, projectName, targetName, projectDependencies) {
|
165 | const missing = findMissingBuildDependencies(root, projectName, targetName, projectDependencies);
|
166 | if (missing.length > 0) {
|
167 | console.error((0, devkit_1.stripIndents) `
|
168 | It looks like all of ${projectName}'s dependencies have not been built yet:
|
169 | ${missing.map((x) => ` - ${x.node.name}`).join('\n')}
|
170 |
|
171 | You might be missing a "targetDefaults" configuration in your root nx.json (https://nx.dev/reference/project-configuration#target-defaults),
|
172 | or "dependsOn" configured in ${projectName}'s project.json (https://nx.dev/reference/project-configuration#dependson)
|
173 | `);
|
174 | return false;
|
175 | }
|
176 | else {
|
177 | return true;
|
178 | }
|
179 | }
|
180 | exports.checkDependentProjectsHaveBeenBuilt = checkDependentProjectsHaveBeenBuilt;
|
181 | function findMissingBuildDependencies(root, projectName, targetName, projectDependencies) {
|
182 | const depLibsToBuildFirst = [];
|
183 |
|
184 | projectDependencies.forEach((dep) => {
|
185 | if (dep.node.type !== 'lib') {
|
186 | return;
|
187 | }
|
188 | const paths = dep.outputs.map((p) => (0, path_1.join)(root, p));
|
189 | if (!paths.some(fileutils_1.directoryExists)) {
|
190 | depLibsToBuildFirst.push(dep);
|
191 | }
|
192 | });
|
193 | return depLibsToBuildFirst;
|
194 | }
|
195 | exports.findMissingBuildDependencies = findMissingBuildDependencies;
|
196 | function updatePaths(dependencies, paths) {
|
197 | const pathsKeys = Object.keys(paths);
|
198 |
|
199 | dependencies.forEach((dep) => {
|
200 | var _a;
|
201 |
|
202 | if (dep.outputs && dep.outputs.length > 0) {
|
203 |
|
204 | paths[dep.name] = dep.outputs;
|
205 |
|
206 |
|
207 | for (const path of pathsKeys) {
|
208 | const nestedName = `${dep.name}/`;
|
209 |
|
210 | if (path.startsWith(nestedName)) {
|
211 | const nestedPart = path.slice(nestedName.length);
|
212 |
|
213 | let mappedPaths = dep.outputs.map((output) => `${output}/${nestedPart}`);
|
214 |
|
215 | const { root } = (((_a = dep.node) === null || _a === void 0 ? void 0 : _a.data) || {});
|
216 | if (root) {
|
217 |
|
218 | mappedPaths = mappedPaths.concat(paths[path].flatMap((path) => dep.outputs.map((output) => path.replace(root, output))));
|
219 | }
|
220 | paths[path] = mappedPaths;
|
221 | }
|
222 | }
|
223 | }
|
224 | });
|
225 | }
|
226 | exports.updatePaths = updatePaths;
|
227 |
|
228 |
|
229 |
|
230 |
|
231 | function updateBuildableProjectPackageJsonDependencies(root, projectName, targetName, configurationName, node, dependencies, typeOfDependency = 'dependencies') {
|
232 | const outputs = (0, devkit_1.getOutputsForTargetAndConfiguration)({
|
233 | overrides: {},
|
234 | target: {
|
235 | project: projectName,
|
236 | target: targetName,
|
237 | configuration: configurationName,
|
238 | },
|
239 | }, node);
|
240 | const packageJsonPath = `${outputs[0]}/package.json`;
|
241 | let packageJson;
|
242 | let workspacePackageJson;
|
243 | try {
|
244 | packageJson = (0, devkit_1.readJsonFile)(packageJsonPath);
|
245 | workspacePackageJson = (0, devkit_1.readJsonFile)(`${root}/package.json`);
|
246 | }
|
247 | catch (e) {
|
248 |
|
249 | return;
|
250 | }
|
251 | packageJson.dependencies = packageJson.dependencies || {};
|
252 | packageJson.peerDependencies = packageJson.peerDependencies || {};
|
253 | let updatePackageJson = false;
|
254 | dependencies.forEach((entry) => {
|
255 | var _a;
|
256 | const packageName = (0, operators_1.isNpmProject)(entry.node)
|
257 | ? entry.node.data.packageName
|
258 | : entry.name;
|
259 | if (!hasDependency(packageJson, 'dependencies', packageName) &&
|
260 | !hasDependency(packageJson, 'devDependencies', packageName) &&
|
261 | !hasDependency(packageJson, 'peerDependencies', packageName)) {
|
262 | try {
|
263 | let depVersion;
|
264 | if (entry.node.type === 'lib') {
|
265 | const outputs = (0, devkit_1.getOutputsForTargetAndConfiguration)({
|
266 | overrides: {},
|
267 | target: {
|
268 | project: projectName,
|
269 | target: targetName,
|
270 | configuration: configurationName,
|
271 | },
|
272 | }, entry.node);
|
273 | const depPackageJsonPath = (0, path_1.join)(root, outputs[0], 'package.json');
|
274 | depVersion = (0, devkit_1.readJsonFile)(depPackageJsonPath).version;
|
275 | packageJson[typeOfDependency][packageName] = depVersion;
|
276 | }
|
277 | else if ((0, operators_1.isNpmProject)(entry.node)) {
|
278 |
|
279 | if (!!((_a = workspacePackageJson.devDependencies) === null || _a === void 0 ? void 0 : _a[entry.node.data.packageName])) {
|
280 | return;
|
281 | }
|
282 | depVersion = entry.node.data.version;
|
283 | packageJson[typeOfDependency][entry.node.data.packageName] =
|
284 | depVersion;
|
285 | }
|
286 | updatePackageJson = true;
|
287 | }
|
288 | catch (e) {
|
289 |
|
290 | }
|
291 | }
|
292 | });
|
293 | if (updatePackageJson) {
|
294 | (0, devkit_1.writeJsonFile)(packageJsonPath, packageJson);
|
295 | }
|
296 | }
|
297 | exports.updateBuildableProjectPackageJsonDependencies = updateBuildableProjectPackageJsonDependencies;
|
298 |
|
299 | function hasDependency(outputJson, depConfigName, packageName) {
|
300 | if (outputJson[depConfigName]) {
|
301 | return outputJson[depConfigName][packageName];
|
302 | }
|
303 | else {
|
304 | return false;
|
305 | }
|
306 | }
|
307 |
|
\ | No newline at end of file |