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 | const isInternalTarget = projGraph.nodes[dependency.target];
|
90 | if (!shallow && isInternalTarget) {
|
91 | collectDependencies(dependency.target, projGraph, acc, shallow, false);
|
92 | }
|
93 | }
|
94 | });
|
95 | return acc;
|
96 | }
|
97 | function readTsConfigWithRemappedPaths(tsConfig, generatedTsConfigPath, dependencies) {
|
98 | const generatedTsConfig = { compilerOptions: {} };
|
99 | generatedTsConfig.extends = (0, path_1.relative)((0, path_1.dirname)(generatedTsConfigPath), tsConfig);
|
100 | generatedTsConfig.compilerOptions.paths = computeCompilerOptionsPaths(tsConfig, dependencies);
|
101 | if (process.env.NX_VERBOSE_LOGGING_PATH_MAPPINGS === 'true') {
|
102 | output_1.output.log({
|
103 | title: 'TypeScript path mappings have been rewritten.',
|
104 | });
|
105 | console.log(JSON.stringify(generatedTsConfig.compilerOptions.paths, null, 2));
|
106 | }
|
107 | return generatedTsConfig;
|
108 | }
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 | function computeCompilerOptionsPaths(tsConfig, dependencies) {
|
116 | const paths = readPaths(tsConfig) || {};
|
117 | updatePaths(dependencies, paths);
|
118 | return paths;
|
119 | }
|
120 | exports.computeCompilerOptionsPaths = computeCompilerOptionsPaths;
|
121 | function readPaths(tsConfig) {
|
122 | var _a;
|
123 | try {
|
124 | let config;
|
125 | if (typeof tsConfig === 'string') {
|
126 | const configFile = ts.readConfigFile(tsConfig, ts.sys.readFile);
|
127 | config = ts.parseJsonConfigFileContent(configFile.config, ts.sys, (0, path_1.dirname)(tsConfig));
|
128 | }
|
129 | else {
|
130 | config = tsConfig;
|
131 | }
|
132 | if ((_a = config.options) === null || _a === void 0 ? void 0 : _a.paths) {
|
133 | return config.options.paths;
|
134 | }
|
135 | else {
|
136 | return null;
|
137 | }
|
138 | }
|
139 | catch (e) {
|
140 | return null;
|
141 | }
|
142 | }
|
143 | function createTmpTsConfig(tsconfigPath, workspaceRoot, projectRoot, dependencies) {
|
144 | const tmpTsConfigPath = (0, path_1.join)(workspaceRoot, 'tmp', projectRoot, 'tsconfig.generated.json');
|
145 | const parsedTSConfig = readTsConfigWithRemappedPaths(tsconfigPath, tmpTsConfigPath, dependencies);
|
146 | process.on('exit', () => cleanupTmpTsConfigFile(tmpTsConfigPath));
|
147 | (0, devkit_1.writeJsonFile)(tmpTsConfigPath, parsedTSConfig);
|
148 | return (0, path_1.join)(tmpTsConfigPath);
|
149 | }
|
150 | exports.createTmpTsConfig = createTmpTsConfig;
|
151 | function cleanupTmpTsConfigFile(tmpTsConfigPath) {
|
152 | try {
|
153 | if (tmpTsConfigPath) {
|
154 | (0, fs_1.unlinkSync)(tmpTsConfigPath);
|
155 | }
|
156 | }
|
157 | catch (e) { }
|
158 | }
|
159 | function checkDependentProjectsHaveBeenBuilt(root, projectName, targetName, projectDependencies) {
|
160 | const missing = findMissingBuildDependencies(root, projectName, targetName, projectDependencies);
|
161 | if (missing.length > 0) {
|
162 | console.error((0, devkit_1.stripIndents) `
|
163 | It looks like all of ${projectName}'s dependencies have not been built yet:
|
164 | ${missing.map((x) => ` - ${x.node.name}`).join('\n')}
|
165 |
|
166 | You might be missing a "targetDefaults" configuration in your root nx.json (https://nx.dev/reference/project-configuration#target-defaults),
|
167 | or "dependsOn" configured in ${projectName}'s project.json (https://nx.dev/reference/project-configuration#dependson)
|
168 | `);
|
169 | return false;
|
170 | }
|
171 | else {
|
172 | return true;
|
173 | }
|
174 | }
|
175 | exports.checkDependentProjectsHaveBeenBuilt = checkDependentProjectsHaveBeenBuilt;
|
176 | function findMissingBuildDependencies(root, projectName, targetName, projectDependencies) {
|
177 | const depLibsToBuildFirst = [];
|
178 |
|
179 | projectDependencies.forEach((dep) => {
|
180 | if (dep.node.type !== 'lib') {
|
181 | return;
|
182 | }
|
183 | const paths = dep.outputs.map((p) => (0, path_1.join)(root, p));
|
184 | if (!paths.some(fileutils_1.directoryExists)) {
|
185 | depLibsToBuildFirst.push(dep);
|
186 | }
|
187 | });
|
188 | return depLibsToBuildFirst;
|
189 | }
|
190 | exports.findMissingBuildDependencies = findMissingBuildDependencies;
|
191 | function updatePaths(dependencies, paths) {
|
192 | const pathsKeys = Object.keys(paths);
|
193 |
|
194 | dependencies.forEach((dep) => {
|
195 | var _a;
|
196 |
|
197 | if (dep.outputs && dep.outputs.length > 0) {
|
198 |
|
199 | paths[dep.name] = dep.outputs;
|
200 |
|
201 |
|
202 | for (const path of pathsKeys) {
|
203 | const nestedName = `${dep.name}/`;
|
204 |
|
205 | if (path.startsWith(nestedName)) {
|
206 | const nestedPart = path.slice(nestedName.length);
|
207 |
|
208 | let mappedPaths = dep.outputs.map((output) => `${output}/${nestedPart}`);
|
209 |
|
210 | const { root } = ((_a = dep.node) === null || _a === void 0 ? void 0 : _a.data) || {};
|
211 | if (root) {
|
212 |
|
213 | mappedPaths = mappedPaths.concat(paths[path].flatMap((path) => dep.outputs.map((output) => path.replace(root, output))));
|
214 | }
|
215 | paths[path] = mappedPaths;
|
216 | }
|
217 | }
|
218 | }
|
219 | });
|
220 | }
|
221 | exports.updatePaths = updatePaths;
|
222 |
|
223 |
|
224 |
|
225 |
|
226 | function updateBuildableProjectPackageJsonDependencies(root, projectName, targetName, configurationName, node, dependencies, typeOfDependency = 'dependencies') {
|
227 | const outputs = (0, devkit_1.getOutputsForTargetAndConfiguration)({
|
228 | overrides: {},
|
229 | target: {
|
230 | project: projectName,
|
231 | target: targetName,
|
232 | configuration: configurationName,
|
233 | },
|
234 | }, node);
|
235 | const packageJsonPath = `${outputs[0]}/package.json`;
|
236 | let packageJson;
|
237 | let workspacePackageJson;
|
238 | try {
|
239 | packageJson = (0, devkit_1.readJsonFile)(packageJsonPath);
|
240 | workspacePackageJson = (0, devkit_1.readJsonFile)(`${root}/package.json`);
|
241 | }
|
242 | catch (e) {
|
243 |
|
244 | return;
|
245 | }
|
246 | packageJson.dependencies = packageJson.dependencies || {};
|
247 | packageJson.peerDependencies = packageJson.peerDependencies || {};
|
248 | let updatePackageJson = false;
|
249 | dependencies.forEach((entry) => {
|
250 | var _a;
|
251 | const packageName = (0, operators_1.isNpmProject)(entry.node)
|
252 | ? entry.node.data.packageName
|
253 | : entry.name;
|
254 | if (!hasDependency(packageJson, 'dependencies', packageName) &&
|
255 | !hasDependency(packageJson, 'devDependencies', packageName) &&
|
256 | !hasDependency(packageJson, 'peerDependencies', packageName)) {
|
257 | try {
|
258 | let depVersion;
|
259 | if (entry.node.type === 'lib') {
|
260 | const outputs = (0, devkit_1.getOutputsForTargetAndConfiguration)({
|
261 | overrides: {},
|
262 | target: {
|
263 | project: projectName,
|
264 | target: targetName,
|
265 | configuration: configurationName,
|
266 | },
|
267 | }, entry.node);
|
268 | const depPackageJsonPath = (0, path_1.join)(root, outputs[0], 'package.json');
|
269 | depVersion = (0, devkit_1.readJsonFile)(depPackageJsonPath).version;
|
270 | packageJson[typeOfDependency][packageName] = depVersion;
|
271 | }
|
272 | else if ((0, operators_1.isNpmProject)(entry.node)) {
|
273 |
|
274 | if (!!((_a = workspacePackageJson.devDependencies) === null || _a === void 0 ? void 0 : _a[entry.node.data.packageName])) {
|
275 | return;
|
276 | }
|
277 | depVersion = entry.node.data.version;
|
278 | packageJson[typeOfDependency][entry.node.data.packageName] =
|
279 | depVersion;
|
280 | }
|
281 | updatePackageJson = true;
|
282 | }
|
283 | catch (e) {
|
284 |
|
285 | }
|
286 | }
|
287 | });
|
288 | if (updatePackageJson) {
|
289 | (0, devkit_1.writeJsonFile)(packageJsonPath, packageJson);
|
290 | }
|
291 | }
|
292 | exports.updateBuildableProjectPackageJsonDependencies = updateBuildableProjectPackageJsonDependencies;
|
293 |
|
294 | function hasDependency(outputJson, depConfigName, packageName) {
|
295 | if (outputJson[depConfigName]) {
|
296 | return outputJson[depConfigName][packageName];
|
297 | }
|
298 | else {
|
299 | return false;
|
300 | }
|
301 | }
|
302 |
|
\ | No newline at end of file |