@nx/js 19.6.0-beta.1 → 19.6.0-beta.3
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.
- package/generators.json +4 -3
- package/package.json +4 -4
- package/src/generators/release-version/release-version.js +5 -4
- package/src/generators/typescript-sync/typescript-sync.d.ts +4 -0
- package/src/generators/typescript-sync/typescript-sync.js +243 -0
- package/src/plugins/typescript/plugin.js +2 -0
- package/src/generators/sync/sync.d.ts +0 -3
- package/src/generators/sync/sync.js +0 -75
- /package/src/generators/{sync → typescript-sync}/schema.d.ts +0 -0
- /package/src/generators/{sync → typescript-sync}/schema.json +0 -0
package/generators.json
CHANGED
|
@@ -42,10 +42,11 @@
|
|
|
42
42
|
"alias": ["build"],
|
|
43
43
|
"description": "setup-build generator"
|
|
44
44
|
},
|
|
45
|
-
"sync": {
|
|
46
|
-
"factory": "./src/generators/sync/sync
|
|
47
|
-
"schema": "./src/generators/sync/schema.json",
|
|
45
|
+
"typescript-sync": {
|
|
46
|
+
"factory": "./src/generators/typescript-sync/typescript-sync",
|
|
47
|
+
"schema": "./src/generators/typescript-sync/schema.json",
|
|
48
48
|
"description": "Synchronize TypeScript project references based on the project graph",
|
|
49
|
+
"alias": ["sync"],
|
|
49
50
|
"hidden": true
|
|
50
51
|
}
|
|
51
52
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/js",
|
|
3
|
-
"version": "19.6.0-beta.
|
|
3
|
+
"version": "19.6.0-beta.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The JS plugin for Nx contains executors and generators that provide the best experience for developing JavaScript and TypeScript projects. ",
|
|
6
6
|
"repository": {
|
|
@@ -58,9 +58,9 @@
|
|
|
58
58
|
"semver": "^7.5.3",
|
|
59
59
|
"source-map-support": "0.5.19",
|
|
60
60
|
"tslib": "^2.3.0",
|
|
61
|
-
"@nx/devkit": "19.6.0-beta.
|
|
62
|
-
"@nx/workspace": "19.6.0-beta.
|
|
63
|
-
"@nrwl/js": "19.6.0-beta.
|
|
61
|
+
"@nx/devkit": "19.6.0-beta.3",
|
|
62
|
+
"@nx/workspace": "19.6.0-beta.3",
|
|
63
|
+
"@nrwl/js": "19.6.0-beta.3"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
66
|
"verdaccio": "^5.0.4"
|
|
@@ -290,7 +290,8 @@ To fix this you will either need to add a package.json file at that location, or
|
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
if (options.releaseGroup.projectsRelationship === 'independent') {
|
|
293
|
-
specifier = options.releaseGroup
|
|
293
|
+
specifier = options.releaseGroup
|
|
294
|
+
.resolvedVersionPlans.reduce((spec, plan) => {
|
|
294
295
|
if (!spec) {
|
|
295
296
|
return plan.projectVersionBumps[projectName];
|
|
296
297
|
}
|
|
@@ -305,7 +306,7 @@ To fix this you will either need to add a package.json file at that location, or
|
|
|
305
306
|
}, null);
|
|
306
307
|
}
|
|
307
308
|
else {
|
|
308
|
-
specifier = options.releaseGroup.
|
|
309
|
+
specifier = options.releaseGroup.resolvedVersionPlans.reduce((spec, plan) => {
|
|
309
310
|
if (!spec) {
|
|
310
311
|
return plan.groupVersionBump;
|
|
311
312
|
}
|
|
@@ -332,7 +333,7 @@ To fix this you will either need to add a package.json file at that location, or
|
|
|
332
333
|
logger.buffer(`📄 Resolved the specifier as "${specifier}" using version plans.`);
|
|
333
334
|
}
|
|
334
335
|
if (options.deleteVersionPlans) {
|
|
335
|
-
options.releaseGroup.
|
|
336
|
+
(options.releaseGroup.resolvedVersionPlans || []).forEach((p) => {
|
|
336
337
|
deleteVersionPlanCallbacks.push(async (dryRun) => {
|
|
337
338
|
if (!dryRun) {
|
|
338
339
|
await (0, fs_extra_1.remove)(p.absolutePath);
|
|
@@ -386,7 +387,7 @@ To fix this you will either need to add a package.json file at that location, or
|
|
|
386
387
|
let isInCurrentBatch = options.projects.some((project) => project.name === dependentProject.source);
|
|
387
388
|
// For version-plans, we don't just need to consider the current batch of projects, but also the ones that are actually being updated as part of the plan file(s)
|
|
388
389
|
if (isInCurrentBatch && options.specifierSource === 'version-plans') {
|
|
389
|
-
isInCurrentBatch = (options.releaseGroup.
|
|
390
|
+
isInCurrentBatch = (options.releaseGroup.resolvedVersionPlans || []).some((plan) => {
|
|
390
391
|
if ('projectVersionBumps' in plan) {
|
|
391
392
|
return plan.projectVersionBumps[dependentProject.source];
|
|
392
393
|
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.syncGenerator = syncGenerator;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const posix_1 = require("node:path/posix");
|
|
6
|
+
const plugin_1 = require("../../plugins/typescript/plugin");
|
|
7
|
+
const COMMON_RUNTIME_TS_CONFIG_FILE_NAMES = [
|
|
8
|
+
'tsconfig.app.json',
|
|
9
|
+
'tsconfig.lib.json',
|
|
10
|
+
'tsconfig.build.json',
|
|
11
|
+
'tsconfig.cjs.json',
|
|
12
|
+
'tsconfig.esm.json',
|
|
13
|
+
'tsconfig.runtime.json',
|
|
14
|
+
];
|
|
15
|
+
async function syncGenerator(tree) {
|
|
16
|
+
// Ensure that the plugin has been wired up in nx.json
|
|
17
|
+
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
18
|
+
const tscPluginConfig = nxJson.plugins.find((p) => {
|
|
19
|
+
if (typeof p === 'string') {
|
|
20
|
+
return p === plugin_1.PLUGIN_NAME;
|
|
21
|
+
}
|
|
22
|
+
return p.plugin === plugin_1.PLUGIN_NAME;
|
|
23
|
+
});
|
|
24
|
+
if (!tscPluginConfig) {
|
|
25
|
+
throw new Error(`The ${plugin_1.PLUGIN_NAME} plugin must be added to the "plugins" array in nx.json before syncing tsconfigs`);
|
|
26
|
+
}
|
|
27
|
+
// Root tsconfig containing project references for the whole workspace
|
|
28
|
+
const rootTsconfigPath = 'tsconfig.json';
|
|
29
|
+
if (!tree.exists(rootTsconfigPath)) {
|
|
30
|
+
throw new Error(`A "tsconfig.json" file must exist in the workspace root.`);
|
|
31
|
+
}
|
|
32
|
+
const rootTsconfig = (0, devkit_1.readJson)(tree, rootTsconfigPath);
|
|
33
|
+
const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
|
|
34
|
+
const projectRoots = new Set();
|
|
35
|
+
const tsconfigProjectNodeValues = Object.values(projectGraph.nodes).filter((node) => {
|
|
36
|
+
projectRoots.add(node.data.root);
|
|
37
|
+
const projectTsconfigPath = (0, devkit_1.joinPathFragments)(node.data.root, 'tsconfig.json');
|
|
38
|
+
return tree.exists(projectTsconfigPath);
|
|
39
|
+
});
|
|
40
|
+
// Track if any changes were made to the tsconfig files. We check the changes
|
|
41
|
+
// made by this generator to know if the TS config is out of sync with the
|
|
42
|
+
// project graph. Therefore, we don't format the files if there were no changes
|
|
43
|
+
// to avoid potential format-only changes that can lead to false positives.
|
|
44
|
+
let hasChanges = false;
|
|
45
|
+
if (tsconfigProjectNodeValues.length > 0) {
|
|
46
|
+
const referencesSet = new Set();
|
|
47
|
+
for (const ref of rootTsconfig.references ?? []) {
|
|
48
|
+
// reference path is relative to the tsconfig file
|
|
49
|
+
const resolvedRefPath = getTsConfigPathFromReferencePath(tree, rootTsconfigPath, ref.path);
|
|
50
|
+
if (tree.exists(resolvedRefPath)) {
|
|
51
|
+
// we only keep the references that still exist
|
|
52
|
+
referencesSet.add(normalizeReferencePath(ref.path));
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
hasChanges = true;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
for (const node of tsconfigProjectNodeValues) {
|
|
59
|
+
const normalizedPath = normalizeReferencePath(node.data.root);
|
|
60
|
+
// Skip the root tsconfig itself
|
|
61
|
+
if (node.data.root !== '.' && !referencesSet.has(normalizedPath)) {
|
|
62
|
+
referencesSet.add(normalizedPath);
|
|
63
|
+
hasChanges = true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (hasChanges) {
|
|
67
|
+
rootTsconfig.references = Array.from(referencesSet).map((ref) => ({
|
|
68
|
+
path: `./${ref}`,
|
|
69
|
+
}));
|
|
70
|
+
(0, devkit_1.writeJson)(tree, rootTsconfigPath, rootTsconfig);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const runtimeTsConfigFileNames = nxJson.sync?.generatorOptions?.['@nx/js:typescript-sync']
|
|
74
|
+
?.runtimeTsConfigFileNames ??
|
|
75
|
+
COMMON_RUNTIME_TS_CONFIG_FILE_NAMES;
|
|
76
|
+
const collectedDependencies = new Map();
|
|
77
|
+
for (const [name, data] of Object.entries(projectGraph.dependencies)) {
|
|
78
|
+
if (!projectGraph.nodes[name] ||
|
|
79
|
+
projectGraph.nodes[name].data.root === '.' ||
|
|
80
|
+
!data.length) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
// Get the source project nodes for the source and target
|
|
84
|
+
const sourceProjectNode = projectGraph.nodes[name];
|
|
85
|
+
// Find the relevant tsconfig file for the source project
|
|
86
|
+
const sourceProjectTsconfigPath = (0, devkit_1.joinPathFragments)(sourceProjectNode.data.root, 'tsconfig.json');
|
|
87
|
+
if (!tree.exists(sourceProjectTsconfigPath)) {
|
|
88
|
+
if (process.env.NX_VERBOSE_LOGGING === 'true') {
|
|
89
|
+
devkit_1.logger.warn(`Skipping project "${name}" as there is no tsconfig.json file found in the project root "${sourceProjectNode.data.root}".`);
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
// Collect the dependencies of the source project
|
|
94
|
+
const dependencies = collectProjectDependencies(tree, name, projectGraph, collectedDependencies);
|
|
95
|
+
if (!dependencies.length) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
for (const runtimeTsConfigFileName of runtimeTsConfigFileNames) {
|
|
99
|
+
const runtimeTsConfigPath = (0, devkit_1.joinPathFragments)(sourceProjectNode.data.root, runtimeTsConfigFileName);
|
|
100
|
+
if (!tree.exists(runtimeTsConfigPath)) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
// Update project references for the runtime tsconfig
|
|
104
|
+
hasChanges =
|
|
105
|
+
updateTsConfigReferences(tree, runtimeTsConfigPath, dependencies, sourceProjectNode.data.root, projectRoots, runtimeTsConfigFileName, runtimeTsConfigFileNames) || hasChanges;
|
|
106
|
+
}
|
|
107
|
+
// Update project references for the tsconfig.json file
|
|
108
|
+
hasChanges =
|
|
109
|
+
updateTsConfigReferences(tree, sourceProjectTsconfigPath, dependencies, sourceProjectNode.data.root, projectRoots) || hasChanges;
|
|
110
|
+
}
|
|
111
|
+
if (hasChanges) {
|
|
112
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
113
|
+
return {
|
|
114
|
+
outOfSyncMessage: 'Based on the workspace project graph, some TypeScript configuration files are missing project references to the projects they depend on.',
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
exports.default = syncGenerator;
|
|
119
|
+
function updateTsConfigReferences(tree, tsConfigPath, dependencies, projectRoot, projectRoots, runtimeTsConfigFileName, possibleRuntimeTsConfigFileNames) {
|
|
120
|
+
const tsConfig = (0, devkit_1.readJson)(tree, tsConfigPath);
|
|
121
|
+
// We have at least one dependency so we can safely set it to an empty array if not already set
|
|
122
|
+
const references = [];
|
|
123
|
+
const originalReferencesSet = new Set();
|
|
124
|
+
const newReferencesSet = new Set();
|
|
125
|
+
for (const ref of tsConfig.references ?? []) {
|
|
126
|
+
const normalizedPath = normalizeReferencePath(ref.path);
|
|
127
|
+
originalReferencesSet.add(normalizedPath);
|
|
128
|
+
// reference path is relative to the tsconfig file
|
|
129
|
+
const resolvedRefPath = getTsConfigPathFromReferencePath(tree, tsConfigPath, ref.path);
|
|
130
|
+
if (isInternalProjectReference(tree, resolvedRefPath, projectRoot, projectRoots)) {
|
|
131
|
+
// we keep all internal references
|
|
132
|
+
references.push(ref);
|
|
133
|
+
newReferencesSet.add(normalizedPath);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
let hasChanges = false;
|
|
137
|
+
for (const dep of dependencies) {
|
|
138
|
+
// Ensure the project reference for the target is set
|
|
139
|
+
let referencePath = dep.data.root;
|
|
140
|
+
if (runtimeTsConfigFileName) {
|
|
141
|
+
const runtimeTsConfigPath = (0, devkit_1.joinPathFragments)(dep.data.root, runtimeTsConfigFileName);
|
|
142
|
+
if (tree.exists(runtimeTsConfigPath)) {
|
|
143
|
+
referencePath = runtimeTsConfigPath;
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// Check for other possible runtime tsconfig file names
|
|
147
|
+
// TODO(leo): should we check if there are more than one runtime tsconfig files and throw an error?
|
|
148
|
+
for (const possibleRuntimeTsConfigFileName of possibleRuntimeTsConfigFileNames ??
|
|
149
|
+
[]) {
|
|
150
|
+
const possibleRuntimeTsConfigPath = (0, devkit_1.joinPathFragments)(dep.data.root, possibleRuntimeTsConfigFileName);
|
|
151
|
+
if (tree.exists(possibleRuntimeTsConfigPath)) {
|
|
152
|
+
referencePath = possibleRuntimeTsConfigPath;
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const relativePathToTargetRoot = (0, posix_1.relative)(projectRoot, referencePath);
|
|
159
|
+
if (!newReferencesSet.has(relativePathToTargetRoot)) {
|
|
160
|
+
newReferencesSet.add(relativePathToTargetRoot);
|
|
161
|
+
// Make sure we unshift rather than push so that dependencies are built in the right order by TypeScript when it is run directly from the root of the workspace
|
|
162
|
+
references.unshift({ path: relativePathToTargetRoot });
|
|
163
|
+
}
|
|
164
|
+
if (!originalReferencesSet.has(relativePathToTargetRoot)) {
|
|
165
|
+
hasChanges = true;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
hasChanges ||= newReferencesSet.size !== originalReferencesSet.size;
|
|
169
|
+
if (hasChanges) {
|
|
170
|
+
tsConfig.references = references;
|
|
171
|
+
(0, devkit_1.writeJson)(tree, tsConfigPath, tsConfig);
|
|
172
|
+
}
|
|
173
|
+
return hasChanges;
|
|
174
|
+
}
|
|
175
|
+
// TODO(leo): follow up with the TypeScript team to confirm if we really need
|
|
176
|
+
// to reference transitive dependencies.
|
|
177
|
+
// Collect the dependencies of a project recursively sorted from root to leaf
|
|
178
|
+
function collectProjectDependencies(tree, projectName, projectGraph, collectedDependencies) {
|
|
179
|
+
if (collectedDependencies.has(projectName)) {
|
|
180
|
+
// We've already collected the dependencies for this project
|
|
181
|
+
return collectedDependencies.get(projectName);
|
|
182
|
+
}
|
|
183
|
+
collectedDependencies.set(projectName, []);
|
|
184
|
+
for (const dep of projectGraph.dependencies[projectName]) {
|
|
185
|
+
const targetProjectNode = projectGraph.nodes[dep.target];
|
|
186
|
+
if (!targetProjectNode) {
|
|
187
|
+
// It's an npm dependency
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
// Add the target project node to the list of dependencies for the current project
|
|
191
|
+
if (!collectedDependencies
|
|
192
|
+
.get(projectName)
|
|
193
|
+
.some((d) => d.name === targetProjectNode.name)) {
|
|
194
|
+
collectedDependencies.get(projectName).push(targetProjectNode);
|
|
195
|
+
}
|
|
196
|
+
if (process.env.NX_DISABLE_TS_SYNC_TRANSITIVE_DEPENDENCIES === 'true') {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
// Recursively get the dependencies of the target project
|
|
200
|
+
const transitiveDependencies = collectProjectDependencies(tree, dep.target, projectGraph, collectedDependencies);
|
|
201
|
+
for (const transitiveDep of transitiveDependencies) {
|
|
202
|
+
if (!collectedDependencies
|
|
203
|
+
.get(projectName)
|
|
204
|
+
.some((d) => d.name === transitiveDep.name)) {
|
|
205
|
+
collectedDependencies.get(projectName).push(transitiveDep);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return collectedDependencies.get(projectName);
|
|
210
|
+
}
|
|
211
|
+
// Normalize the paths to strip leading `./` and trailing `/tsconfig.json`
|
|
212
|
+
function normalizeReferencePath(path) {
|
|
213
|
+
return (0, posix_1.normalize)(path)
|
|
214
|
+
.replace(/\/tsconfig.json$/, '')
|
|
215
|
+
.replace(/^\.\//, '');
|
|
216
|
+
}
|
|
217
|
+
function isInternalProjectReference(tree, refTsConfigPath, projectRoot, projectRoots) {
|
|
218
|
+
let currentPath = getTsConfigDirName(tree, refTsConfigPath);
|
|
219
|
+
if ((0, posix_1.relative)(projectRoot, currentPath).startsWith('..')) {
|
|
220
|
+
// it's outside of the project root, so it's an external project reference
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
while (currentPath !== projectRoot) {
|
|
224
|
+
if (projectRoots.has(currentPath)) {
|
|
225
|
+
// it's inside a nested project root, so it's and external project reference
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
currentPath = (0, posix_1.dirname)(currentPath);
|
|
229
|
+
}
|
|
230
|
+
// it's inside the project root, so it's an internal project reference
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
function getTsConfigDirName(tree, tsConfigPath) {
|
|
234
|
+
return tree.isFile(tsConfigPath)
|
|
235
|
+
? (0, posix_1.dirname)(tsConfigPath)
|
|
236
|
+
: (0, posix_1.normalize)(tsConfigPath);
|
|
237
|
+
}
|
|
238
|
+
function getTsConfigPathFromReferencePath(tree, ownerTsConfigPath, referencePath) {
|
|
239
|
+
const resolvedRefPath = (0, devkit_1.joinPathFragments)((0, posix_1.dirname)(ownerTsConfigPath), referencePath);
|
|
240
|
+
return tree.isFile(resolvedRefPath)
|
|
241
|
+
? resolvedRefPath
|
|
242
|
+
: (0, devkit_1.joinPathFragments)(resolvedRefPath, 'tsconfig.json');
|
|
243
|
+
}
|
|
@@ -109,6 +109,7 @@ function buildTscTargets(configFilePath, projectRoot, options, context) {
|
|
|
109
109
|
cache: true,
|
|
110
110
|
inputs: getInputs(namedInputs, configFilePath, tsConfig, internalProjectReferences, context.workspaceRoot, projectRoot),
|
|
111
111
|
outputs: getOutputs(configFilePath, tsConfig, internalProjectReferences, context.workspaceRoot, projectRoot),
|
|
112
|
+
syncGenerators: ['@nx/js:typescript-sync'],
|
|
112
113
|
};
|
|
113
114
|
}
|
|
114
115
|
}
|
|
@@ -123,6 +124,7 @@ function buildTscTargets(configFilePath, projectRoot, options, context) {
|
|
|
123
124
|
cache: true,
|
|
124
125
|
inputs: getInputs(namedInputs, configFilePath, tsConfig, internalProjectReferences, context.workspaceRoot, projectRoot),
|
|
125
126
|
outputs: getOutputs(configFilePath, tsConfig, internalProjectReferences, context.workspaceRoot, projectRoot),
|
|
127
|
+
syncGenerators: ['@nx/js:typescript-sync'],
|
|
126
128
|
};
|
|
127
129
|
}
|
|
128
130
|
return { targets };
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.syncGenerator = syncGenerator;
|
|
4
|
-
const devkit_1 = require("@nx/devkit");
|
|
5
|
-
const node_path_1 = require("node:path");
|
|
6
|
-
const plugin_1 = require("../../plugins/typescript/plugin");
|
|
7
|
-
async function syncGenerator(tree, options) {
|
|
8
|
-
// Ensure that the plugin has been wired up in nx.json
|
|
9
|
-
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
10
|
-
let tscPluginConfig = nxJson.plugins.find((p) => {
|
|
11
|
-
if (typeof p === 'string') {
|
|
12
|
-
return p === plugin_1.PLUGIN_NAME;
|
|
13
|
-
}
|
|
14
|
-
return p.plugin === plugin_1.PLUGIN_NAME;
|
|
15
|
-
});
|
|
16
|
-
if (!tscPluginConfig) {
|
|
17
|
-
throw new Error(`The ${plugin_1.PLUGIN_NAME} plugin must be added to the "plugins" array in nx.json before syncing tsconfigs`);
|
|
18
|
-
}
|
|
19
|
-
const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
|
|
20
|
-
const firstPartyDeps = Object.entries(projectGraph.dependencies).filter(([name, data]) => !name.startsWith('npm:') && data.length > 0);
|
|
21
|
-
// Root tsconfig containing project references for the whole workspace
|
|
22
|
-
const rootTsconfigPath = 'tsconfig.json';
|
|
23
|
-
const rootTsconfig = (0, devkit_1.readJson)(tree, rootTsconfigPath);
|
|
24
|
-
const tsconfigProjectNodeValues = Object.values(projectGraph.nodes).filter((node) => {
|
|
25
|
-
const projectTsconfigPath = (0, devkit_1.joinPathFragments)(node.data.root, 'tsconfig.json');
|
|
26
|
-
return tree.exists(projectTsconfigPath);
|
|
27
|
-
});
|
|
28
|
-
if (tsconfigProjectNodeValues.length > 0) {
|
|
29
|
-
// Sync the root tsconfig references from the project graph (do not destroy existing references)
|
|
30
|
-
rootTsconfig.references = rootTsconfig.references || [];
|
|
31
|
-
const referencesSet = new Set(rootTsconfig.references.map((ref) => normalizeReferencePath(ref.path)));
|
|
32
|
-
for (const node of tsconfigProjectNodeValues) {
|
|
33
|
-
const normalizedPath = normalizeReferencePath(node.data.root);
|
|
34
|
-
// Skip the root tsconfig itself
|
|
35
|
-
if (node.data.root !== '.' && !referencesSet.has(normalizedPath)) {
|
|
36
|
-
rootTsconfig.references.push({ path: `./${normalizedPath}` });
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
(0, devkit_1.writeJson)(tree, rootTsconfigPath, rootTsconfig);
|
|
40
|
-
}
|
|
41
|
-
for (const [name, data] of firstPartyDeps) {
|
|
42
|
-
// Get the source project nodes for the source and target
|
|
43
|
-
const sourceProjectNode = projectGraph.nodes[name];
|
|
44
|
-
// Find the relevant tsconfig files for the source project
|
|
45
|
-
const sourceProjectTsconfigPath = (0, devkit_1.joinPathFragments)(sourceProjectNode.data.root, 'tsconfig.json');
|
|
46
|
-
if (!tree.exists(sourceProjectTsconfigPath)) {
|
|
47
|
-
console.warn(`Skipping project "${name}" as there is no tsconfig.json file found in the project root "${sourceProjectNode.data.root}"`);
|
|
48
|
-
continue;
|
|
49
|
-
}
|
|
50
|
-
const sourceTsconfig = (0, devkit_1.readJson)(tree, sourceProjectTsconfigPath);
|
|
51
|
-
for (const dep of data) {
|
|
52
|
-
// Get the target project node
|
|
53
|
-
const targetProjectNode = projectGraph.nodes[dep.target];
|
|
54
|
-
if (!targetProjectNode) {
|
|
55
|
-
// It's an external dependency
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
// Set defaults only in the case where we have at least one dependency so that we don't patch files when not necessary
|
|
59
|
-
sourceTsconfig.references = sourceTsconfig.references || [];
|
|
60
|
-
// Ensure the project reference for the target is set
|
|
61
|
-
const relativePathToTargetRoot = (0, node_path_1.relative)(sourceProjectNode.data.root, targetProjectNode.data.root);
|
|
62
|
-
if (!sourceTsconfig.references.some((ref) => ref.path === relativePathToTargetRoot)) {
|
|
63
|
-
// Make sure we unshift rather than push so that dependencies are built in the right order by TypeScript when it is run directly from the root of the workspace
|
|
64
|
-
sourceTsconfig.references.unshift({ path: relativePathToTargetRoot });
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
// Update the source tsconfig files
|
|
68
|
-
(0, devkit_1.writeJson)(tree, sourceProjectTsconfigPath, sourceTsconfig);
|
|
69
|
-
}
|
|
70
|
-
await (0, devkit_1.formatFiles)(tree);
|
|
71
|
-
}
|
|
72
|
-
// Normalize the paths to strip leading `./` and trailing `/tsconfig.json`
|
|
73
|
-
function normalizeReferencePath(path) {
|
|
74
|
-
return path.replace(/\/tsconfig.json$/, '').replace(/^\.\//, '');
|
|
75
|
-
}
|
|
File without changes
|
|
File without changes
|