@nx/js 19.6.1 → 19.6.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/README.md +1 -1
- package/babel.js +25 -24
- package/package.json +10 -9
- package/src/executors/tsc/lib/normalize-options.js +1 -0
- package/src/executors/verdaccio/verdaccio.impl.js +34 -32
- package/src/generators/typescript-sync/typescript-sync.js +90 -22
- package/src/utils/schema.d.ts +2 -2
- package/src/utils/typescript/run-type-check.d.ts +1 -0
- package/src/utils/typescript/run-type-check.js +10 -3
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
# Nx: Smart Monorepos · Fast CI
|
|
24
24
|
|
|
25
|
-
Nx is a build system
|
|
25
|
+
Nx is a build system, optimized for monorepos, with plugins for popular frameworks and tools and advanced CI capabilities including caching and distribution.
|
|
26
26
|
|
|
27
27
|
This package is a [JavaScript/TypeScript plugin for Nx](https://nx.dev/js/overview).
|
|
28
28
|
|
package/babel.js
CHANGED
|
@@ -18,6 +18,30 @@ module.exports = function (api, options = {}) {
|
|
|
18
18
|
if (options.classProperties) {
|
|
19
19
|
devkit_1.logger.warn(`Use =\`loose\` option instead of \`classProperties.loose\`. The \`classProperties\` option will be removed in Nx 20`);
|
|
20
20
|
}
|
|
21
|
+
const plugins = [
|
|
22
|
+
!isNxPackage
|
|
23
|
+
? [
|
|
24
|
+
require.resolve('@babel/plugin-transform-runtime'),
|
|
25
|
+
{
|
|
26
|
+
corejs: false,
|
|
27
|
+
helpers: true,
|
|
28
|
+
regenerator: true,
|
|
29
|
+
useESModules: isModern,
|
|
30
|
+
absoluteRuntime: (0, path_1.dirname)(require.resolve('@babel/runtime/package.json')),
|
|
31
|
+
},
|
|
32
|
+
]
|
|
33
|
+
: null,
|
|
34
|
+
require.resolve('babel-plugin-macros'),
|
|
35
|
+
emitDecoratorMetadata
|
|
36
|
+
? require.resolve('babel-plugin-transform-typescript-metadata')
|
|
37
|
+
: undefined,
|
|
38
|
+
// Must use legacy decorators to remain compatible with TypeScript.
|
|
39
|
+
[
|
|
40
|
+
require.resolve('@babel/plugin-proposal-decorators'),
|
|
41
|
+
options.decorators ?? { legacy: true },
|
|
42
|
+
],
|
|
43
|
+
[require.resolve('@babel/plugin-transform-class-properties'), { loose }],
|
|
44
|
+
].filter(Boolean);
|
|
21
45
|
return {
|
|
22
46
|
presets: [
|
|
23
47
|
// Support module/nomodule pattern.
|
|
@@ -37,30 +61,7 @@ module.exports = function (api, options = {}) {
|
|
|
37
61
|
},
|
|
38
62
|
],
|
|
39
63
|
],
|
|
40
|
-
plugins
|
|
41
|
-
!isNxPackage
|
|
42
|
-
? [
|
|
43
|
-
require.resolve('@babel/plugin-transform-runtime'),
|
|
44
|
-
{
|
|
45
|
-
corejs: false,
|
|
46
|
-
helpers: true,
|
|
47
|
-
regenerator: true,
|
|
48
|
-
useESModules: isModern,
|
|
49
|
-
absoluteRuntime: (0, path_1.dirname)(require.resolve('@babel/runtime/package.json')),
|
|
50
|
-
},
|
|
51
|
-
]
|
|
52
|
-
: null,
|
|
53
|
-
require.resolve('babel-plugin-macros'),
|
|
54
|
-
emitDecoratorMetadata
|
|
55
|
-
? require.resolve('babel-plugin-transform-typescript-metadata')
|
|
56
|
-
: undefined,
|
|
57
|
-
// Must use legacy decorators to remain compatible with TypeScript.
|
|
58
|
-
[
|
|
59
|
-
require.resolve('@babel/plugin-proposal-decorators'),
|
|
60
|
-
options.decorators ?? { legacy: true },
|
|
61
|
-
],
|
|
62
|
-
[require.resolve('@babel/plugin-transform-class-properties'), { loose }],
|
|
63
|
-
].filter(Boolean),
|
|
64
|
+
plugins,
|
|
64
65
|
overrides: [
|
|
65
66
|
// Convert `const enum` to `enum`. The former cannot be supported by babel
|
|
66
67
|
// but at least we can get it to not error out.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/js",
|
|
3
|
-
"version": "19.6.
|
|
3
|
+
"version": "19.6.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": {
|
|
@@ -34,11 +34,13 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@babel/core": "^7.23.2",
|
|
36
36
|
"@babel/plugin-proposal-decorators": "^7.22.7",
|
|
37
|
-
"@babel/plugin-transform-runtime": "^7.23.2",
|
|
38
37
|
"@babel/plugin-transform-class-properties": "^7.22.5",
|
|
38
|
+
"@babel/plugin-transform-runtime": "^7.23.2",
|
|
39
39
|
"@babel/preset-env": "^7.23.2",
|
|
40
40
|
"@babel/preset-typescript": "^7.22.5",
|
|
41
41
|
"@babel/runtime": "^7.22.6",
|
|
42
|
+
"@nx/devkit": "19.6.3",
|
|
43
|
+
"@nx/workspace": "19.6.3",
|
|
42
44
|
"babel-plugin-const-enum": "^1.0.1",
|
|
43
45
|
"babel-plugin-macros": "^2.8.0",
|
|
44
46
|
"babel-plugin-transform-typescript-metadata": "^0.3.1",
|
|
@@ -47,20 +49,19 @@
|
|
|
47
49
|
"detect-port": "^1.5.1",
|
|
48
50
|
"fast-glob": "3.2.7",
|
|
49
51
|
"fs-extra": "^11.1.0",
|
|
50
|
-
"npm-package-arg": "11.0.1",
|
|
51
|
-
"npm-run-path": "^4.0.1",
|
|
52
|
-
"ts-node": "10.9.1",
|
|
53
|
-
"tsconfig-paths": "^4.1.2",
|
|
54
52
|
"ignore": "^5.0.4",
|
|
55
53
|
"js-tokens": "^4.0.0",
|
|
54
|
+
"jsonc-parser": "3.2.0",
|
|
56
55
|
"minimatch": "9.0.3",
|
|
56
|
+
"npm-package-arg": "11.0.1",
|
|
57
|
+
"npm-run-path": "^4.0.1",
|
|
57
58
|
"ora": "5.3.0",
|
|
58
59
|
"semver": "^7.5.3",
|
|
59
60
|
"source-map-support": "0.5.19",
|
|
61
|
+
"ts-node": "10.9.1",
|
|
62
|
+
"tsconfig-paths": "^4.1.2",
|
|
60
63
|
"tslib": "^2.3.0",
|
|
61
|
-
"@
|
|
62
|
-
"@nx/workspace": "19.6.1",
|
|
63
|
-
"@nrwl/js": "19.6.1"
|
|
64
|
+
"@nrwl/js": "19.6.3"
|
|
64
65
|
},
|
|
65
66
|
"peerDependencies": {
|
|
66
67
|
"verdaccio": "^5.0.4"
|
|
@@ -122,19 +122,19 @@ function setupNpm(options) {
|
|
|
122
122
|
const scopes = ['', ...(options.scopes || [])];
|
|
123
123
|
try {
|
|
124
124
|
scopes.forEach((scope) => {
|
|
125
|
-
const
|
|
125
|
+
const registryName = scope ? `${scope}:registry` : 'registry';
|
|
126
126
|
try {
|
|
127
|
-
npmRegistryPaths.push((0, child_process_1.execSync)(`npm config get
|
|
127
|
+
npmRegistryPaths.push((0, child_process_1.execSync)(`npm config get ${registryName} --location ${options.location}`, { env })
|
|
128
128
|
?.toString()
|
|
129
129
|
?.trim()
|
|
130
130
|
?.replace('\u001b[2K\u001b[1G', '') // strip out ansi codes
|
|
131
131
|
);
|
|
132
|
-
(0, child_process_1.execSync)(`npm config set
|
|
132
|
+
(0, child_process_1.execSync)(`npm config set ${registryName} http://localhost:${options.port}/ --location ${options.location}`, { env });
|
|
133
133
|
(0, child_process_1.execSync)(`npm config set //localhost:${options.port}/:_authToken="secretVerdaccioToken" --location ${options.location}`, { env });
|
|
134
|
-
devkit_1.logger.info(`Set npm ${
|
|
134
|
+
devkit_1.logger.info(`Set npm ${registryName} to http://localhost:${options.port}/`);
|
|
135
135
|
}
|
|
136
136
|
catch (e) {
|
|
137
|
-
throw new Error(`Failed to set npm ${
|
|
137
|
+
throw new Error(`Failed to set npm ${registryName} to http://localhost:${options.port}/: ${e.message}`);
|
|
138
138
|
}
|
|
139
139
|
});
|
|
140
140
|
return () => {
|
|
@@ -143,20 +143,20 @@ function setupNpm(options) {
|
|
|
143
143
|
?.toString()
|
|
144
144
|
?.trim()
|
|
145
145
|
?.replace('\u001b[2K\u001b[1G', ''); // strip out ansi codes
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
(0, child_process_1.execSync)(`npm config set
|
|
151
|
-
devkit_1.logger.info(`Reset npm ${
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
146
|
+
scopes.forEach((scope, index) => {
|
|
147
|
+
const registryName = scope ? `${scope}:registry` : 'registry';
|
|
148
|
+
if (npmRegistryPaths[index] &&
|
|
149
|
+
currentNpmRegistryPath.includes('localhost')) {
|
|
150
|
+
(0, child_process_1.execSync)(`npm config set ${registryName} ${npmRegistryPaths[index]} --location ${options.location}`, { env });
|
|
151
|
+
devkit_1.logger.info(`Reset npm ${registryName} to ${npmRegistryPaths[index]}`);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
(0, child_process_1.execSync)(`npm config delete ${registryName} --location ${options.location}`, {
|
|
155
|
+
env,
|
|
156
|
+
});
|
|
157
|
+
devkit_1.logger.info('Cleared custom npm registry');
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
160
|
(0, child_process_1.execSync)(`npm config delete //localhost:${options.port}/:_authToken --location ${options.location}`, { env });
|
|
161
161
|
}
|
|
162
162
|
catch (e) {
|
|
@@ -225,20 +225,22 @@ function setupYarn(options) {
|
|
|
225
225
|
?.toString()
|
|
226
226
|
?.trim()
|
|
227
227
|
?.replace('\u001b[2K\u001b[1G', ''); // strip out ansi codes
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
228
|
+
scopes.forEach((scope, index) => {
|
|
229
|
+
const registryName = scope
|
|
230
|
+
? `${scope}:${registryConfigName}`
|
|
231
|
+
: registryConfigName;
|
|
232
|
+
if (yarnRegistryPaths[index] &&
|
|
233
|
+
currentYarnRegistryPath.includes('localhost')) {
|
|
234
|
+
(0, child_process_1.execSync)(`yarn config set ${registryName} ${yarnRegistryPaths[index]}` +
|
|
233
235
|
(options.location === 'user' ? ' --home' : ''), { env });
|
|
234
|
-
devkit_1.logger.info(`Reset yarn ${
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
(
|
|
240
|
-
|
|
241
|
-
}
|
|
236
|
+
devkit_1.logger.info(`Reset yarn ${registryName} to ${yarnRegistryPaths[index]}`);
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
(0, child_process_1.execSync)(`yarn config ${isYarnV1 ? 'delete' : 'unset'} ${registryName}` +
|
|
240
|
+
(options.location === 'user' ? ' --home' : ''), { env });
|
|
241
|
+
devkit_1.logger.info(`Cleared custom yarn ${registryConfigName}`);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
242
244
|
if (whitelistedLocalhost) {
|
|
243
245
|
const currentWhitelist = getYarnUnsafeHttpWhitelist(isYarnV1);
|
|
244
246
|
if (currentWhitelist.has('localhost')) {
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.syncGenerator = syncGenerator;
|
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const jsonc_parser_1 = require("jsonc-parser");
|
|
5
6
|
const posix_1 = require("node:path/posix");
|
|
7
|
+
const ts = require("typescript");
|
|
6
8
|
const plugin_1 = require("../../plugins/typescript/plugin");
|
|
7
9
|
const COMMON_RUNTIME_TS_CONFIG_FILE_NAMES = [
|
|
8
10
|
'tsconfig.app.json',
|
|
@@ -27,16 +29,25 @@ async function syncGenerator(tree) {
|
|
|
27
29
|
// Root tsconfig containing project references for the whole workspace
|
|
28
30
|
const rootTsconfigPath = 'tsconfig.json';
|
|
29
31
|
if (!tree.exists(rootTsconfigPath)) {
|
|
30
|
-
throw new Error(`A "tsconfig.json" file must exist in the workspace root.`);
|
|
32
|
+
throw new Error(`A "tsconfig.json" file must exist in the workspace root in order to use this sync generator.`);
|
|
31
33
|
}
|
|
32
|
-
const
|
|
34
|
+
const rawTsconfigContentsCache = new Map();
|
|
35
|
+
const stringifiedRootJsonContents = readRawTsconfigContents(tree, rawTsconfigContentsCache, rootTsconfigPath);
|
|
36
|
+
const rootTsconfig = (0, devkit_1.parseJson)(stringifiedRootJsonContents);
|
|
33
37
|
const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
|
|
34
38
|
const projectRoots = new Set();
|
|
39
|
+
const tsconfigHasCompositeEnabledCache = new Map();
|
|
35
40
|
const tsconfigProjectNodeValues = Object.values(projectGraph.nodes).filter((node) => {
|
|
36
41
|
projectRoots.add(node.data.root);
|
|
37
42
|
const projectTsconfigPath = (0, devkit_1.joinPathFragments)(node.data.root, 'tsconfig.json');
|
|
38
|
-
return tree
|
|
43
|
+
return tsconfigExists(tree, rawTsconfigContentsCache, projectTsconfigPath);
|
|
39
44
|
});
|
|
45
|
+
const tsSysFromTree = {
|
|
46
|
+
...ts.sys,
|
|
47
|
+
readFile(path) {
|
|
48
|
+
return readRawTsconfigContents(tree, rawTsconfigContentsCache, path);
|
|
49
|
+
},
|
|
50
|
+
};
|
|
40
51
|
// Track if any changes were made to the tsconfig files. We check the changes
|
|
41
52
|
// made by this generator to know if the TS config is out of sync with the
|
|
42
53
|
// project graph. Therefore, we don't format the files if there were no changes
|
|
@@ -47,7 +58,7 @@ async function syncGenerator(tree) {
|
|
|
47
58
|
for (const ref of rootTsconfig.references ?? []) {
|
|
48
59
|
// reference path is relative to the tsconfig file
|
|
49
60
|
const resolvedRefPath = getTsConfigPathFromReferencePath(tree, rootTsconfigPath, ref.path);
|
|
50
|
-
if (tree
|
|
61
|
+
if (tsconfigExists(tree, rawTsconfigContentsCache, resolvedRefPath)) {
|
|
51
62
|
// we only keep the references that still exist
|
|
52
63
|
referencesSet.add(normalizeReferencePath(ref.path));
|
|
53
64
|
}
|
|
@@ -64,10 +75,13 @@ async function syncGenerator(tree) {
|
|
|
64
75
|
}
|
|
65
76
|
}
|
|
66
77
|
if (hasChanges) {
|
|
67
|
-
|
|
78
|
+
const updatedReferences = Array.from(referencesSet)
|
|
79
|
+
// Check composite is true in the internal reference before proceeding
|
|
80
|
+
.filter((ref) => hasCompositeEnabled(tsSysFromTree, tsconfigHasCompositeEnabledCache, (0, devkit_1.joinPathFragments)(ref, 'tsconfig.json')))
|
|
81
|
+
.map((ref) => ({
|
|
68
82
|
path: `./${ref}`,
|
|
69
83
|
}));
|
|
70
|
-
(
|
|
84
|
+
patchTsconfigJsonReferences(tree, rawTsconfigContentsCache, rootTsconfigPath, updatedReferences);
|
|
71
85
|
}
|
|
72
86
|
}
|
|
73
87
|
const runtimeTsConfigFileNames = nxJson.sync?.generatorOptions?.['@nx/js:typescript-sync']
|
|
@@ -84,7 +98,7 @@ async function syncGenerator(tree) {
|
|
|
84
98
|
const sourceProjectNode = projectGraph.nodes[name];
|
|
85
99
|
// Find the relevant tsconfig file for the source project
|
|
86
100
|
const sourceProjectTsconfigPath = (0, devkit_1.joinPathFragments)(sourceProjectNode.data.root, 'tsconfig.json');
|
|
87
|
-
if (!tree
|
|
101
|
+
if (!tsconfigExists(tree, rawTsconfigContentsCache, sourceProjectTsconfigPath)) {
|
|
88
102
|
if (process.env.NX_VERBOSE_LOGGING === 'true') {
|
|
89
103
|
devkit_1.logger.warn(`Skipping project "${name}" as there is no tsconfig.json file found in the project root "${sourceProjectNode.data.root}".`);
|
|
90
104
|
}
|
|
@@ -97,16 +111,16 @@ async function syncGenerator(tree) {
|
|
|
97
111
|
}
|
|
98
112
|
for (const runtimeTsConfigFileName of runtimeTsConfigFileNames) {
|
|
99
113
|
const runtimeTsConfigPath = (0, devkit_1.joinPathFragments)(sourceProjectNode.data.root, runtimeTsConfigFileName);
|
|
100
|
-
if (!tree
|
|
114
|
+
if (!tsconfigExists(tree, rawTsconfigContentsCache, runtimeTsConfigPath)) {
|
|
101
115
|
continue;
|
|
102
116
|
}
|
|
103
117
|
// Update project references for the runtime tsconfig
|
|
104
118
|
hasChanges =
|
|
105
|
-
updateTsConfigReferences(tree, runtimeTsConfigPath, dependencies, sourceProjectNode.data.root, projectRoots, runtimeTsConfigFileName, runtimeTsConfigFileNames) || hasChanges;
|
|
119
|
+
updateTsConfigReferences(tree, tsSysFromTree, rawTsconfigContentsCache, tsconfigHasCompositeEnabledCache, runtimeTsConfigPath, dependencies, sourceProjectNode.data.root, projectRoots, runtimeTsConfigFileName, runtimeTsConfigFileNames) || hasChanges;
|
|
106
120
|
}
|
|
107
121
|
// Update project references for the tsconfig.json file
|
|
108
122
|
hasChanges =
|
|
109
|
-
updateTsConfigReferences(tree, sourceProjectTsconfigPath, dependencies, sourceProjectNode.data.root, projectRoots) || hasChanges;
|
|
123
|
+
updateTsConfigReferences(tree, tsSysFromTree, rawTsconfigContentsCache, tsconfigHasCompositeEnabledCache, sourceProjectTsconfigPath, dependencies, sourceProjectNode.data.root, projectRoots) || hasChanges;
|
|
110
124
|
}
|
|
111
125
|
if (hasChanges) {
|
|
112
126
|
await (0, devkit_1.formatFiles)(tree);
|
|
@@ -116,8 +130,28 @@ async function syncGenerator(tree) {
|
|
|
116
130
|
}
|
|
117
131
|
}
|
|
118
132
|
exports.default = syncGenerator;
|
|
119
|
-
|
|
120
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Within the context of a sync generator, performance is a key concern,
|
|
135
|
+
* so avoid FS interactions whenever possible.
|
|
136
|
+
*/
|
|
137
|
+
function readRawTsconfigContents(tree, rawTsconfigContentsCache, tsconfigPath) {
|
|
138
|
+
if (!rawTsconfigContentsCache.has(tsconfigPath)) {
|
|
139
|
+
rawTsconfigContentsCache.set(tsconfigPath, tree.read(tsconfigPath, 'utf-8'));
|
|
140
|
+
}
|
|
141
|
+
return rawTsconfigContentsCache.get(tsconfigPath);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Within the context of a sync generator, performance is a key concern,
|
|
145
|
+
* so avoid FS interactions whenever possible.
|
|
146
|
+
*/
|
|
147
|
+
function tsconfigExists(tree, rawTsconfigContentsCache, tsconfigPath) {
|
|
148
|
+
return rawTsconfigContentsCache.has(tsconfigPath)
|
|
149
|
+
? true
|
|
150
|
+
: tree.exists(tsconfigPath);
|
|
151
|
+
}
|
|
152
|
+
function updateTsConfigReferences(tree, tsSysFromTree, rawTsconfigContentsCache, tsconfigHasCompositeEnabledCache, tsConfigPath, dependencies, projectRoot, projectRoots, runtimeTsConfigFileName, possibleRuntimeTsConfigFileNames) {
|
|
153
|
+
const stringifiedJsonContents = readRawTsconfigContents(tree, rawTsconfigContentsCache, tsConfigPath);
|
|
154
|
+
const tsConfig = (0, devkit_1.parseJson)(stringifiedJsonContents);
|
|
121
155
|
// We have at least one dependency so we can safely set it to an empty array if not already set
|
|
122
156
|
const references = [];
|
|
123
157
|
const originalReferencesSet = new Set();
|
|
@@ -127,8 +161,8 @@ function updateTsConfigReferences(tree, tsConfigPath, dependencies, projectRoot,
|
|
|
127
161
|
originalReferencesSet.add(normalizedPath);
|
|
128
162
|
// reference path is relative to the tsconfig file
|
|
129
163
|
const resolvedRefPath = getTsConfigPathFromReferencePath(tree, tsConfigPath, ref.path);
|
|
130
|
-
if (
|
|
131
|
-
// we keep all
|
|
164
|
+
if (isProjectReferenceWithinNxProject(tree, rawTsconfigContentsCache, resolvedRefPath, projectRoot, projectRoots)) {
|
|
165
|
+
// we keep all references within the current Nx project
|
|
132
166
|
references.push(ref);
|
|
133
167
|
newReferencesSet.add(normalizedPath);
|
|
134
168
|
}
|
|
@@ -139,7 +173,11 @@ function updateTsConfigReferences(tree, tsConfigPath, dependencies, projectRoot,
|
|
|
139
173
|
let referencePath = dep.data.root;
|
|
140
174
|
if (runtimeTsConfigFileName) {
|
|
141
175
|
const runtimeTsConfigPath = (0, devkit_1.joinPathFragments)(dep.data.root, runtimeTsConfigFileName);
|
|
142
|
-
if (tree
|
|
176
|
+
if (tsconfigExists(tree, rawTsconfigContentsCache, runtimeTsConfigPath)) {
|
|
177
|
+
// Check composite is true in the dependency runtime tsconfig file before proceeding
|
|
178
|
+
if (!hasCompositeEnabled(tsSysFromTree, tsconfigHasCompositeEnabledCache, runtimeTsConfigPath)) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
143
181
|
referencePath = runtimeTsConfigPath;
|
|
144
182
|
}
|
|
145
183
|
else {
|
|
@@ -148,13 +186,23 @@ function updateTsConfigReferences(tree, tsConfigPath, dependencies, projectRoot,
|
|
|
148
186
|
for (const possibleRuntimeTsConfigFileName of possibleRuntimeTsConfigFileNames ??
|
|
149
187
|
[]) {
|
|
150
188
|
const possibleRuntimeTsConfigPath = (0, devkit_1.joinPathFragments)(dep.data.root, possibleRuntimeTsConfigFileName);
|
|
151
|
-
if (tree
|
|
189
|
+
if (tsconfigExists(tree, rawTsconfigContentsCache, possibleRuntimeTsConfigPath)) {
|
|
190
|
+
// Check composite is true in the dependency runtime tsconfig file before proceeding
|
|
191
|
+
if (!hasCompositeEnabled(tsSysFromTree, tsconfigHasCompositeEnabledCache, possibleRuntimeTsConfigPath)) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
152
194
|
referencePath = possibleRuntimeTsConfigPath;
|
|
153
195
|
break;
|
|
154
196
|
}
|
|
155
197
|
}
|
|
156
198
|
}
|
|
157
199
|
}
|
|
200
|
+
else {
|
|
201
|
+
// Check composite is true in the dependency tsconfig.json file before proceeding
|
|
202
|
+
if (!hasCompositeEnabled(tsSysFromTree, tsconfigHasCompositeEnabledCache, (0, devkit_1.joinPathFragments)(dep.data.root, 'tsconfig.json'))) {
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
158
206
|
const relativePathToTargetRoot = (0, posix_1.relative)(projectRoot, referencePath);
|
|
159
207
|
if (!newReferencesSet.has(relativePathToTargetRoot)) {
|
|
160
208
|
newReferencesSet.add(relativePathToTargetRoot);
|
|
@@ -167,8 +215,7 @@ function updateTsConfigReferences(tree, tsConfigPath, dependencies, projectRoot,
|
|
|
167
215
|
}
|
|
168
216
|
hasChanges ||= newReferencesSet.size !== originalReferencesSet.size;
|
|
169
217
|
if (hasChanges) {
|
|
170
|
-
|
|
171
|
-
(0, devkit_1.writeJson)(tree, tsConfigPath, tsConfig);
|
|
218
|
+
patchTsconfigJsonReferences(tree, rawTsconfigContentsCache, tsConfigPath, references);
|
|
172
219
|
}
|
|
173
220
|
return hasChanges;
|
|
174
221
|
}
|
|
@@ -214,8 +261,8 @@ function normalizeReferencePath(path) {
|
|
|
214
261
|
.replace(/\/tsconfig.json$/, '')
|
|
215
262
|
.replace(/^\.\//, '');
|
|
216
263
|
}
|
|
217
|
-
function
|
|
218
|
-
let currentPath = getTsConfigDirName(tree, refTsConfigPath);
|
|
264
|
+
function isProjectReferenceWithinNxProject(tree, rawTsconfigContentsCache, refTsConfigPath, projectRoot, projectRoots) {
|
|
265
|
+
let currentPath = getTsConfigDirName(tree, rawTsconfigContentsCache, refTsConfigPath);
|
|
219
266
|
if ((0, posix_1.relative)(projectRoot, currentPath).startsWith('..')) {
|
|
220
267
|
// it's outside of the project root, so it's an external project reference
|
|
221
268
|
return false;
|
|
@@ -230,8 +277,10 @@ function isInternalProjectReference(tree, refTsConfigPath, projectRoot, projectR
|
|
|
230
277
|
// it's inside the project root, so it's an internal project reference
|
|
231
278
|
return true;
|
|
232
279
|
}
|
|
233
|
-
function getTsConfigDirName(tree, tsConfigPath) {
|
|
234
|
-
return
|
|
280
|
+
function getTsConfigDirName(tree, rawTsconfigContentsCache, tsConfigPath) {
|
|
281
|
+
return (rawTsconfigContentsCache.has(tsConfigPath)
|
|
282
|
+
? true
|
|
283
|
+
: tree.isFile(tsConfigPath))
|
|
235
284
|
? (0, posix_1.dirname)(tsConfigPath)
|
|
236
285
|
: (0, posix_1.normalize)(tsConfigPath);
|
|
237
286
|
}
|
|
@@ -241,3 +290,22 @@ function getTsConfigPathFromReferencePath(tree, ownerTsConfigPath, referencePath
|
|
|
241
290
|
? resolvedRefPath
|
|
242
291
|
: (0, devkit_1.joinPathFragments)(resolvedRefPath, 'tsconfig.json');
|
|
243
292
|
}
|
|
293
|
+
/**
|
|
294
|
+
* Minimally patch just the "references" property within the tsconfig file at a given path.
|
|
295
|
+
* This allows comments in other sections of the file to remain intact when syncing is run.
|
|
296
|
+
*/
|
|
297
|
+
function patchTsconfigJsonReferences(tree, rawTsconfigContentsCache, tsconfigPath, updatedReferences) {
|
|
298
|
+
const stringifiedJsonContents = readRawTsconfigContents(tree, rawTsconfigContentsCache, tsconfigPath);
|
|
299
|
+
const edits = (0, jsonc_parser_1.modify)(stringifiedJsonContents, ['references'], updatedReferences, {});
|
|
300
|
+
const updatedJsonContents = (0, jsonc_parser_1.applyEdits)(stringifiedJsonContents, edits);
|
|
301
|
+
// The final contents will be formatted by formatFiles() later
|
|
302
|
+
tree.write(tsconfigPath, updatedJsonContents);
|
|
303
|
+
}
|
|
304
|
+
function hasCompositeEnabled(tsSysFromTree, tsconfigHasCompositeEnabledCache, tsconfigPath) {
|
|
305
|
+
if (!tsconfigHasCompositeEnabledCache.has(tsconfigPath)) {
|
|
306
|
+
const parsed = ts.parseJsonConfigFileContent(ts.readConfigFile(tsconfigPath, tsSysFromTree.readFile).config, tsSysFromTree, (0, posix_1.dirname)(tsconfigPath));
|
|
307
|
+
const enabledVal = parsed.options.composite === true;
|
|
308
|
+
tsconfigHasCompositeEnabledCache.set(tsconfigPath, enabledVal);
|
|
309
|
+
}
|
|
310
|
+
return tsconfigHasCompositeEnabledCache.get(tsconfigPath);
|
|
311
|
+
}
|
package/src/utils/schema.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { ProjectNameAndRootFormat } from '@nx/devkit/src/generators/project
|
|
|
2
2
|
import type { AssetGlob, FileInputOutput } from './assets/assets';
|
|
3
3
|
import { TransformerEntry } from './typescript/types';
|
|
4
4
|
// nx-ignore-next-line
|
|
5
|
-
const { Linter } = require('@nx/eslint'); // use require to import to avoid circular dependency
|
|
5
|
+
const { Linter, LinterType } = require('@nx/eslint'); // use require to import to avoid circular dependency
|
|
6
6
|
|
|
7
7
|
export type Compiler = 'tsc' | 'swc';
|
|
8
8
|
export type Bundler = 'swc' | 'tsc' | 'rollup' | 'vite' | 'esbuild' | 'none';
|
|
@@ -17,7 +17,7 @@ export interface LibraryGeneratorSchema {
|
|
|
17
17
|
skipPackageJson?: boolean;
|
|
18
18
|
includeBabelRc?: boolean;
|
|
19
19
|
unitTestRunner?: 'jest' | 'vitest' | 'none';
|
|
20
|
-
linter?: Linter;
|
|
20
|
+
linter?: Linter | LinterType;
|
|
21
21
|
testEnvironment?: 'jsdom' | 'node';
|
|
22
22
|
importPath?: string;
|
|
23
23
|
js?: boolean;
|
|
@@ -55,21 +55,28 @@ async function runTypeCheck(options) {
|
|
|
55
55
|
}
|
|
56
56
|
async function setupTypeScript(options) {
|
|
57
57
|
const ts = await Promise.resolve().then(() => require('typescript'));
|
|
58
|
-
const { workspaceRoot, tsConfigPath, cacheDir, incremental,
|
|
58
|
+
const { workspaceRoot, tsConfigPath, cacheDir, incremental, projectRoot } = options;
|
|
59
59
|
const config = (0, ts_config_1.readTsConfig)(tsConfigPath);
|
|
60
60
|
if (config.errors.length) {
|
|
61
61
|
const errorMessages = config.errors.map((e) => e.messageText).join('\n');
|
|
62
62
|
throw new Error(`Invalid config file due to following: ${errorMessages}`);
|
|
63
63
|
}
|
|
64
64
|
const emitOptions = options.mode === 'emitDeclarationOnly'
|
|
65
|
-
? {
|
|
65
|
+
? {
|
|
66
|
+
emitDeclarationOnly: true,
|
|
67
|
+
declaration: true,
|
|
68
|
+
outDir: options.outDir,
|
|
69
|
+
declarationDir: options.projectRoot && options.outDir.indexOf(projectRoot)
|
|
70
|
+
? options.outDir.replace(projectRoot, '')
|
|
71
|
+
: undefined,
|
|
72
|
+
}
|
|
66
73
|
: { noEmit: true };
|
|
67
74
|
const compilerOptions = {
|
|
68
75
|
...config.options,
|
|
69
76
|
skipLibCheck: true,
|
|
70
77
|
...emitOptions,
|
|
71
78
|
incremental,
|
|
72
|
-
rootDir: rootDir || config.options.rootDir,
|
|
79
|
+
rootDir: options.rootDir || config.options.rootDir,
|
|
73
80
|
};
|
|
74
81
|
return { ts, workspaceRoot, cacheDir, config, compilerOptions };
|
|
75
82
|
}
|