@nx/js 19.6.0 → 19.7.0-beta.0
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/package.json +10 -9
- package/src/executors/node/node-with-require-overrides.d.ts +2 -5
- package/src/executors/node/node-with-require-overrides.js +5 -19
- package/src/executors/node/node.impl.js +6 -3
- package/src/executors/node/patch-require.d.ts +5 -0
- package/src/executors/node/patch-require.js +26 -0
- package/src/executors/node/patch-sigint.d.ts +5 -0
- package/src/executors/node/patch-sigint.js +24 -0
- package/src/executors/tsc/tsc.impl.js +3 -3
- package/src/generators/library/library.js +1 -1
- package/src/generators/release-version/release-version.js +2 -2
- package/src/generators/typescript-sync/typescript-sync.js +90 -22
- package/src/utils/buildable-libs-utils.js +15 -7
- 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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/js",
|
|
3
|
-
"version": "19.
|
|
3
|
+
"version": "19.7.0-beta.0",
|
|
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.7.0-beta.0",
|
|
43
|
+
"@nx/workspace": "19.7.0-beta.0",
|
|
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.0",
|
|
63
|
-
"@nrwl/js": "19.6.0"
|
|
64
|
+
"@nrwl/js": "19.7.0-beta.0"
|
|
64
65
|
},
|
|
65
66
|
"peerDependencies": {
|
|
66
67
|
"verdaccio": "^5.0.4"
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
declare const Module: any;
|
|
2
1
|
declare const url: any;
|
|
3
|
-
declare const
|
|
2
|
+
declare const patchSigint: any;
|
|
3
|
+
declare const patchRequire: any;
|
|
4
4
|
declare const dynamicImport: Function;
|
|
5
|
-
declare const mappings: any;
|
|
6
|
-
declare const keys: string[];
|
|
7
|
-
declare const fileToRun: any;
|
|
@@ -1,21 +1,7 @@
|
|
|
1
|
-
const Module = require('module');
|
|
2
1
|
const url = require('node:url');
|
|
3
|
-
const
|
|
2
|
+
const { patchSigint } = require('./patch-sigint');
|
|
3
|
+
const { patchRequire } = require('./patch-require');
|
|
4
|
+
patchSigint();
|
|
5
|
+
patchRequire();
|
|
4
6
|
const dynamicImport = new Function('specifier', 'return import(specifier)');
|
|
5
|
-
|
|
6
|
-
const keys = Object.keys(mappings);
|
|
7
|
-
const fileToRun = url.pathToFileURL(process.env.NX_FILE_TO_RUN);
|
|
8
|
-
Module._load = function (request, parent) {
|
|
9
|
-
if (!parent)
|
|
10
|
-
return originalLoader.apply(this, arguments);
|
|
11
|
-
const match = keys.find((k) => request === k);
|
|
12
|
-
if (match) {
|
|
13
|
-
const newArguments = [...arguments];
|
|
14
|
-
newArguments[0] = mappings[match];
|
|
15
|
-
return originalLoader.apply(this, newArguments);
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
return originalLoader.apply(this, arguments);
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
dynamicImport(fileToRun);
|
|
7
|
+
dynamicImport(url.pathToFileURL(process.env.NX_FILE_TO_RUN));
|
|
@@ -111,11 +111,14 @@ async function* nodeExecutor(options, context) {
|
|
|
111
111
|
task.childProcess.stderr.on('data', handleStdErr);
|
|
112
112
|
task.childProcess.once('exit', (code) => {
|
|
113
113
|
task.childProcess.off('data', handleStdErr);
|
|
114
|
-
if (options.watch &&
|
|
114
|
+
if (options.watch &&
|
|
115
|
+
!task.killed &&
|
|
116
|
+
// SIGINT should exist the process rather than watch for changes.
|
|
117
|
+
code !== 130) {
|
|
115
118
|
devkit_1.logger.info(`NX Process exited with code ${code}, waiting for changes to restart...`);
|
|
116
119
|
}
|
|
117
|
-
if (!options.watch) {
|
|
118
|
-
if (code !== 0) {
|
|
120
|
+
if (!options.watch || code === 130) {
|
|
121
|
+
if (code !== 0 && code !== 130) {
|
|
119
122
|
error(new Error(`Process exited with code ${code}`));
|
|
120
123
|
}
|
|
121
124
|
else {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.patchRequire = patchRequire;
|
|
4
|
+
const Module = require('node:module');
|
|
5
|
+
const originalLoader = Module._load;
|
|
6
|
+
/**
|
|
7
|
+
* Overrides require calls to map buildable workspace libs to their output location.
|
|
8
|
+
* This is useful for running programs compiled via TSC/SWC that aren't bundled.
|
|
9
|
+
*/
|
|
10
|
+
function patchRequire() {
|
|
11
|
+
const mappings = JSON.parse(process.env.NX_MAPPINGS);
|
|
12
|
+
const keys = Object.keys(mappings);
|
|
13
|
+
Module._load = function (request, parent) {
|
|
14
|
+
if (!parent)
|
|
15
|
+
return originalLoader.apply(this, arguments);
|
|
16
|
+
const match = keys.find((k) => request === k);
|
|
17
|
+
if (match) {
|
|
18
|
+
const newArguments = [...arguments];
|
|
19
|
+
newArguments[0] = mappings[match];
|
|
20
|
+
return originalLoader.apply(this, newArguments);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
return originalLoader.apply(this, arguments);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.patchSigint = patchSigint;
|
|
4
|
+
const readline = require('node:readline');
|
|
5
|
+
/**
|
|
6
|
+
* Patches the current process so that Ctrl+C is properly handled.
|
|
7
|
+
* Without this patch, SIGINT or Ctrl+C does not wait for graceful shutdown and exits immediately.
|
|
8
|
+
*/
|
|
9
|
+
function patchSigint() {
|
|
10
|
+
readline.emitKeypressEvents(process.stdin);
|
|
11
|
+
if (process.stdin.isTTY)
|
|
12
|
+
process.stdin.setRawMode(true);
|
|
13
|
+
process.stdin.on('keypress', async (chunk, key) => {
|
|
14
|
+
if (key && key.ctrl && key.name === 'c') {
|
|
15
|
+
process.stdin.setRawMode(false); // To ensure nx terminal is not stuck in raw mode
|
|
16
|
+
const listeners = process.listeners('SIGINT');
|
|
17
|
+
for (const listener of listeners) {
|
|
18
|
+
await listener('SIGINT');
|
|
19
|
+
}
|
|
20
|
+
process.exit(130);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
console.log('To exit the process, press Ctrl+C');
|
|
24
|
+
}
|
|
@@ -29,11 +29,11 @@ function determineModuleFormatFromTsConfig(absolutePathToTsConfig) {
|
|
|
29
29
|
}
|
|
30
30
|
function createTypeScriptCompilationOptions(normalizedOptions, context) {
|
|
31
31
|
return {
|
|
32
|
-
outputPath: normalizedOptions.outputPath,
|
|
32
|
+
outputPath: (0, devkit_1.joinPathFragments)(normalizedOptions.outputPath),
|
|
33
33
|
projectName: context.projectName,
|
|
34
34
|
projectRoot: normalizedOptions.projectRoot,
|
|
35
|
-
rootDir: normalizedOptions.rootDir,
|
|
36
|
-
tsConfig: normalizedOptions.tsConfig,
|
|
35
|
+
rootDir: (0, devkit_1.joinPathFragments)(normalizedOptions.rootDir),
|
|
36
|
+
tsConfig: (0, devkit_1.joinPathFragments)(normalizedOptions.tsConfig),
|
|
37
37
|
watch: normalizedOptions.watch,
|
|
38
38
|
deleteOutputPath: normalizedOptions.clean,
|
|
39
39
|
getCustomTransformers: (0, lib_1.getCustomTrasformersFactory)(normalizedOptions.transformers),
|
|
@@ -159,7 +159,7 @@ async function addProject(tree, options) {
|
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
if (options.publishable) {
|
|
162
|
-
const packageRoot = (0,
|
|
162
|
+
const packageRoot = (0, devkit_1.joinPathFragments)(defaultOutputDirectory, '{projectRoot}');
|
|
163
163
|
projectConfiguration.targets ??= {};
|
|
164
164
|
projectConfiguration.targets['nx-release-publish'] = {
|
|
165
165
|
options: {
|
|
@@ -76,7 +76,7 @@ Valid values are: ${version_1.validReleaseVersionPrefixes
|
|
|
76
76
|
if (!packageRoot) {
|
|
77
77
|
throw new Error(`The project "${projectName}" does not have a packageRoot available. Please report this issue on https://github.com/nrwl/nx`);
|
|
78
78
|
}
|
|
79
|
-
const packageJsonPath = (0,
|
|
79
|
+
const packageJsonPath = (0, devkit_1.joinPathFragments)(packageRoot, 'package.json');
|
|
80
80
|
if (!tree.exists(packageJsonPath)) {
|
|
81
81
|
throw new Error(`The project "${projectName}" does not have a package.json available at ${packageJsonPath}.
|
|
82
82
|
|
|
@@ -544,7 +544,7 @@ To fix this you will either need to add a package.json file at that location, or
|
|
|
544
544
|
if (!dependencyPackageRoot) {
|
|
545
545
|
throw new Error(`The project "${dependencyProjectName}" does not have a packageRoot available. Please report this issue on https://github.com/nrwl/nx`);
|
|
546
546
|
}
|
|
547
|
-
const dependencyPackageJsonPath = (0,
|
|
547
|
+
const dependencyPackageJsonPath = (0, devkit_1.joinPathFragments)(dependencyPackageRoot, 'package.json');
|
|
548
548
|
const dependencyPackageJson = (0, devkit_1.readJson)(tree, dependencyPackageJsonPath);
|
|
549
549
|
updateDependentProjectAndAddToVersionData({
|
|
550
550
|
dependentProject: transitiveDependentProject,
|
|
@@ -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
|
+
}
|
|
@@ -283,6 +283,9 @@ function updatePaths(dependencies, paths) {
|
|
|
283
283
|
const pathsKeys = Object.keys(paths);
|
|
284
284
|
// For each registered dependency
|
|
285
285
|
dependencies.forEach((dep) => {
|
|
286
|
+
if (dep.node.type === 'npm') {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
286
289
|
// If there are outputs
|
|
287
290
|
if (dep.outputs && dep.outputs.length > 0) {
|
|
288
291
|
// Directly map the dependency name to the output paths (dist/packages/..., etc.)
|
|
@@ -294,14 +297,19 @@ function updatePaths(dependencies, paths) {
|
|
|
294
297
|
// If the path points to the current dependency and is nested (/)
|
|
295
298
|
if (path.startsWith(nestedName)) {
|
|
296
299
|
const nestedPart = path.slice(nestedName.length);
|
|
297
|
-
// Bind secondary endpoints for ng-packagr projects
|
|
300
|
+
// Bind potential secondary endpoints for ng-packagr projects
|
|
298
301
|
let mappedPaths = dep.outputs.map((output) => `${output}/${nestedPart}`);
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
302
|
+
const { root } = dep.node.data;
|
|
303
|
+
// Update nested mappings to point to the dependency's output paths
|
|
304
|
+
mappedPaths = mappedPaths.concat(paths[path].flatMap((p) => dep.outputs.flatMap((output) => {
|
|
305
|
+
const basePath = p.replace(root, output);
|
|
306
|
+
return [
|
|
307
|
+
// extension-less path to support compiled output
|
|
308
|
+
basePath.replace(new RegExp(`${(0, path_1.extname)(basePath)}$`, 'gi'), ''),
|
|
309
|
+
// original path with the root re-mapped to the output path
|
|
310
|
+
basePath,
|
|
311
|
+
];
|
|
312
|
+
})));
|
|
305
313
|
paths[path] = mappedPaths;
|
|
306
314
|
}
|
|
307
315
|
}
|
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
|
}
|