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