@nx/node 21.0.0-beta.0 → 21.0.0-beta.2
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/package.json +7 -5
- package/src/generators/application/application.d.ts +2 -1
- package/src/generators/application/application.js +37 -25
- package/src/generators/application/schema.d.ts +1 -0
- package/src/generators/application/schema.json +4 -0
- package/src/generators/e2e-project/e2e-project.js +47 -37
- package/src/generators/e2e-project/files/server/common/src/support/global-setup.ts__tmpl__ +6 -0
- package/src/generators/e2e-project/files/server/common/src/support/global-teardown.ts__tmpl__ +3 -0
- package/src/generators/e2e-project/schema.d.ts +1 -0
- package/src/generators/e2e-project/schema.json +4 -0
- package/src/generators/library/library.js +9 -10
- package/src/generators/library/schema.d.ts +1 -0
- package/src/generators/library/schema.json +4 -0
- package/src/utils/kill-port.d.ts +7 -0
- package/src/utils/kill-port.js +36 -0
- package/src/utils/wait-for-port-open.d.ts +24 -0
- package/src/utils/wait-for-port-open.js +47 -0
- package/utils.d.ts +2 -0
- package/utils.js +7 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@nx/node",
|
3
|
-
"version": "21.0.0-beta.
|
3
|
+
"version": "21.0.0-beta.2",
|
4
4
|
"private": false,
|
5
5
|
"description": "The Node Plugin for Nx contains generators to manage Node applications within an Nx workspace.",
|
6
6
|
"repository": {
|
@@ -32,10 +32,12 @@
|
|
32
32
|
},
|
33
33
|
"dependencies": {
|
34
34
|
"tslib": "^2.3.0",
|
35
|
-
"@nx/devkit": "21.0.0-beta.
|
36
|
-
"@nx/jest": "21.0.0-beta.
|
37
|
-
"@nx/js": "21.0.0-beta.
|
38
|
-
"@nx/eslint": "21.0.0-beta.
|
35
|
+
"@nx/devkit": "21.0.0-beta.2",
|
36
|
+
"@nx/jest": "21.0.0-beta.2",
|
37
|
+
"@nx/js": "21.0.0-beta.2",
|
38
|
+
"@nx/eslint": "21.0.0-beta.2",
|
39
|
+
"tcp-port-used": "^1.0.2",
|
40
|
+
"kill-port": "^1.6.1"
|
39
41
|
},
|
40
42
|
"publishConfig": {
|
41
43
|
"access": "public"
|
@@ -1,9 +1,10 @@
|
|
1
1
|
import { GeneratorCallback, Tree } from '@nx/devkit';
|
2
2
|
import { Schema } from './schema';
|
3
|
-
export interface NormalizedSchema extends Schema {
|
3
|
+
export interface NormalizedSchema extends Omit<Schema, 'useTsSolution'> {
|
4
4
|
appProjectRoot: string;
|
5
5
|
parsedTags: string[];
|
6
6
|
outputPath: string;
|
7
|
+
importPath: string;
|
7
8
|
isUsingTsSolutionConfig: boolean;
|
8
9
|
}
|
9
10
|
export declare function addLintingToApplication(tree: Tree, options: NormalizedSchema): Promise<GeneratorCallback>;
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.addLintingToApplication = addLintingToApplication;
|
4
4
|
exports.applicationGenerator = applicationGenerator;
|
5
5
|
exports.applicationGeneratorInternal = applicationGeneratorInternal;
|
6
|
-
const get_import_path_1 = require("@nx/js/src/utils/get-import-path");
|
7
6
|
const devkit_1 = require("@nx/devkit");
|
8
7
|
const project_name_and_root_utils_1 = require("@nx/devkit/src/generators/project-name-and-root-utils");
|
9
8
|
const jest_1 = require("@nx/jest");
|
@@ -79,6 +78,7 @@ function getEsBuildConfig(project, options) {
|
|
79
78
|
}
|
80
79
|
function getServeConfig(options) {
|
81
80
|
return {
|
81
|
+
continuous: true,
|
82
82
|
executor: '@nx/js:node',
|
83
83
|
defaultConfiguration: 'development',
|
84
84
|
// Run build, which includes dependency on "^build" by default, so the first run
|
@@ -138,23 +138,24 @@ function addProject(tree, options) {
|
|
138
138
|
}
|
139
139
|
}
|
140
140
|
project.targets.serve = getServeConfig(options);
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
},
|
153
|
-
});
|
141
|
+
const packageJson = {
|
142
|
+
name: options.importPath,
|
143
|
+
version: '0.0.1',
|
144
|
+
private: true,
|
145
|
+
};
|
146
|
+
if (!options.useProjectJson) {
|
147
|
+
packageJson.nx = {
|
148
|
+
name: options.name !== options.importPath ? options.name : undefined,
|
149
|
+
targets: project.targets,
|
150
|
+
tags: project.tags?.length ? project.tags : undefined,
|
151
|
+
};
|
154
152
|
}
|
155
153
|
else {
|
156
154
|
(0, devkit_1.addProjectConfiguration)(tree, options.name, project, options.standaloneConfig);
|
157
155
|
}
|
156
|
+
if (!options.useProjectJson || options.isUsingTsSolutionConfig) {
|
157
|
+
(0, devkit_1.writeJson)(tree, (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'package.json'), packageJson);
|
158
|
+
}
|
158
159
|
}
|
159
160
|
function addAppFiles(tree, options) {
|
160
161
|
(0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, './files/common'), options.appProjectRoot, {
|
@@ -194,10 +195,16 @@ function addAppFiles(tree, options) {
|
|
194
195
|
}
|
195
196
|
function addProxy(tree, options) {
|
196
197
|
const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.frontendProject);
|
197
|
-
if (projectConfig.targets &&
|
198
|
+
if (projectConfig.targets &&
|
199
|
+
['serve', 'dev'].find((t) => !!projectConfig.targets[t])) {
|
200
|
+
const targetName = ['serve', 'dev'].find((t) => !!projectConfig.targets[t]);
|
201
|
+
projectConfig.targets[targetName].dependsOn = [
|
202
|
+
...(projectConfig.targets[targetName].dependsOn ?? []),
|
203
|
+
`${options.name}:serve`,
|
204
|
+
];
|
198
205
|
const pathToProxyFile = `${projectConfig.root}/proxy.conf.json`;
|
199
|
-
projectConfig.targets.
|
200
|
-
...projectConfig.targets.
|
206
|
+
projectConfig.targets[targetName].options = {
|
207
|
+
...projectConfig.targets[targetName].options,
|
201
208
|
proxyConfig: pathToProxyFile,
|
202
209
|
};
|
203
210
|
if (!tree.exists(pathToProxyFile)) {
|
@@ -314,6 +321,7 @@ function updateTsConfigOptions(tree, options) {
|
|
314
321
|
async function applicationGenerator(tree, schema) {
|
315
322
|
return await applicationGeneratorInternal(tree, {
|
316
323
|
addPlugin: false,
|
324
|
+
useProjectJson: true,
|
317
325
|
...schema,
|
318
326
|
});
|
319
327
|
}
|
@@ -374,6 +382,11 @@ async function applicationGeneratorInternal(tree, schema) {
|
|
374
382
|
}
|
375
383
|
addAppFiles(tree, options);
|
376
384
|
addProject(tree, options);
|
385
|
+
// If we are using the new TS solution
|
386
|
+
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
387
|
+
if (options.isUsingTsSolutionConfig) {
|
388
|
+
await (0, ts_solution_setup_1.addProjectToTsSolutionWorkspace)(tree, options.appProjectRoot);
|
389
|
+
}
|
377
390
|
updateTsConfigOptions(tree, options);
|
378
391
|
if (options.linter === eslint_1.Linter.EsLint) {
|
379
392
|
const lintTask = await addLintingToApplication(tree, options);
|
@@ -438,11 +451,6 @@ async function applicationGeneratorInternal(tree, schema) {
|
|
438
451
|
? ['eslint.config.js', 'eslint.config.cjs', 'eslint.config.mjs']
|
439
452
|
: undefined);
|
440
453
|
}
|
441
|
-
// If we are using the new TS solution
|
442
|
-
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
443
|
-
if (options.isUsingTsSolutionConfig) {
|
444
|
-
(0, ts_solution_setup_1.addProjectToTsSolutionWorkspace)(tree, options.appProjectRoot);
|
445
|
-
}
|
446
454
|
(0, sort_fields_1.sortPackageJsonFields)(tree, options.appProjectRoot);
|
447
455
|
if (!options.skipFormat) {
|
448
456
|
await (0, devkit_1.formatFiles)(tree);
|
@@ -453,8 +461,8 @@ async function applicationGeneratorInternal(tree, schema) {
|
|
453
461
|
return (0, devkit_1.runTasksInSerial)(...tasks);
|
454
462
|
}
|
455
463
|
async function normalizeOptions(host, options) {
|
456
|
-
await (0, project_name_and_root_utils_1.
|
457
|
-
const { projectName
|
464
|
+
await (0, project_name_and_root_utils_1.ensureRootProjectName)(options, 'application');
|
465
|
+
const { projectName, projectRoot: appProjectRoot, importPath, } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(host, {
|
458
466
|
name: options.name,
|
459
467
|
projectType: 'application',
|
460
468
|
directory: options.directory,
|
@@ -471,6 +479,8 @@ async function normalizeOptions(host, options) {
|
|
471
479
|
nxJson.useInferencePlugins !== false;
|
472
480
|
const isUsingTsSolutionConfig = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(host);
|
473
481
|
const swcJest = options.swcJest ?? isUsingTsSolutionConfig;
|
482
|
+
const appProjectName = !isUsingTsSolutionConfig || options.name ? projectName : importPath;
|
483
|
+
const useProjectJson = options.useProjectJson ?? !isUsingTsSolutionConfig;
|
474
484
|
return {
|
475
485
|
addPlugin,
|
476
486
|
...options,
|
@@ -479,6 +489,7 @@ async function normalizeOptions(host, options) {
|
|
479
489
|
? (0, devkit_1.names)(options.frontendProject).fileName
|
480
490
|
: undefined,
|
481
491
|
appProjectRoot,
|
492
|
+
importPath,
|
482
493
|
parsedTags,
|
483
494
|
linter: options.linter ?? eslint_1.Linter.EsLint,
|
484
495
|
unitTestRunner: options.unitTestRunner ?? 'jest',
|
@@ -486,9 +497,10 @@ async function normalizeOptions(host, options) {
|
|
486
497
|
port: options.port ?? 3000,
|
487
498
|
outputPath: isUsingTsSolutionConfig
|
488
499
|
? (0, devkit_1.joinPathFragments)(appProjectRoot, 'dist')
|
489
|
-
: (0, devkit_1.joinPathFragments)('dist', options.rootProject ?
|
500
|
+
: (0, devkit_1.joinPathFragments)('dist', options.rootProject ? appProjectName : appProjectRoot),
|
490
501
|
isUsingTsSolutionConfig,
|
491
502
|
swcJest,
|
503
|
+
useProjectJson,
|
492
504
|
};
|
493
505
|
}
|
494
506
|
exports.default = applicationGenerator;
|
@@ -123,6 +123,10 @@
|
|
123
123
|
"docker": {
|
124
124
|
"type": "boolean",
|
125
125
|
"description": "Add a docker build target"
|
126
|
+
},
|
127
|
+
"useProjectJson": {
|
128
|
+
"type": "boolean",
|
129
|
+
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
126
130
|
}
|
127
131
|
},
|
128
132
|
"required": ["directory"]
|
@@ -12,12 +12,12 @@ const eslint_file_1 = require("@nx/eslint/src/generators/utils/eslint-file");
|
|
12
12
|
const log_show_project_command_1 = require("@nx/devkit/src/utils/log-show-project-command");
|
13
13
|
const config_file_1 = require("@nx/jest/src/utils/config/config-file");
|
14
14
|
const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
|
15
|
-
const get_import_path_1 = require("@nx/js/src/utils/get-import-path");
|
16
15
|
const posix_1 = require("node:path/posix");
|
17
16
|
const add_swc_config_1 = require("@nx/js/src/utils/swc/add-swc-config");
|
18
17
|
async function e2eProjectGenerator(host, options) {
|
19
18
|
return await e2eProjectGeneratorInternal(host, {
|
20
19
|
addPlugin: false,
|
20
|
+
useProjectJson: true,
|
21
21
|
...options,
|
22
22
|
});
|
23
23
|
}
|
@@ -25,30 +25,30 @@ async function e2eProjectGeneratorInternal(host, _options) {
|
|
25
25
|
const tasks = [];
|
26
26
|
const options = await normalizeOptions(host, _options);
|
27
27
|
const appProject = (0, devkit_1.readProjectConfiguration)(host, options.project);
|
28
|
-
const isUsingTsSolutionConfig = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(host);
|
29
28
|
// TODO(@ndcunningham): This is broken.. the outputs are wrong.. and this isn't using the jest generator
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
}
|
47
|
-
|
29
|
+
const packageJson = {
|
30
|
+
name: options.importPath,
|
31
|
+
version: '0.0.1',
|
32
|
+
private: true,
|
33
|
+
};
|
34
|
+
if (!options.useProjectJson) {
|
35
|
+
packageJson.nx = {
|
36
|
+
name: options.e2eProjectName !== options.importPath
|
37
|
+
? options.e2eProjectName
|
38
|
+
: undefined,
|
39
|
+
implicitDependencies: [options.project],
|
40
|
+
targets: {
|
41
|
+
e2e: {
|
42
|
+
executor: '@nx/jest:jest',
|
43
|
+
outputs: ['{projectRoot}/test-output/jest/coverage'],
|
44
|
+
options: {
|
45
|
+
jestConfig: `${options.e2eProjectRoot}/jest.config.ts`,
|
46
|
+
passWithNoTests: true,
|
48
47
|
},
|
48
|
+
dependsOn: [`${options.project}:build`, `${options.project}:serve`],
|
49
49
|
},
|
50
50
|
},
|
51
|
-
}
|
51
|
+
};
|
52
52
|
}
|
53
53
|
else {
|
54
54
|
(0, devkit_1.addProjectConfiguration)(host, options.e2eProjectName, {
|
@@ -63,11 +63,14 @@ async function e2eProjectGeneratorInternal(host, _options) {
|
|
63
63
|
jestConfig: `${options.e2eProjectRoot}/jest.config.ts`,
|
64
64
|
passWithNoTests: true,
|
65
65
|
},
|
66
|
-
dependsOn: [`${options.project}:build`],
|
66
|
+
dependsOn: [`${options.project}:build`, `${options.project}:serve`],
|
67
67
|
},
|
68
68
|
},
|
69
69
|
});
|
70
70
|
}
|
71
|
+
if (!options.useProjectJson || options.isUsingTsSolutionConfig) {
|
72
|
+
(0, devkit_1.writeJson)(host, (0, devkit_1.joinPathFragments)(options.e2eProjectRoot, 'package.json'), packageJson);
|
73
|
+
}
|
71
74
|
// TODO(@nicholas): Find a better way to get build target
|
72
75
|
// We remove the 'test' target from the e2e project because it is not needed
|
73
76
|
// The 'e2e' target is the one that should run the tests for the e2e project
|
@@ -94,28 +97,28 @@ async function e2eProjectGeneratorInternal(host, _options) {
|
|
94
97
|
});
|
95
98
|
}
|
96
99
|
const jestPreset = (0, config_file_1.findRootJestPreset)(host) ?? 'jest.preset.js';
|
97
|
-
const tsConfigFile = isUsingTsSolutionConfig
|
100
|
+
const tsConfigFile = options.isUsingTsSolutionConfig
|
98
101
|
? 'tsconfig.json'
|
99
102
|
: 'tsconfig.spec.json';
|
100
103
|
const rootOffset = (0, devkit_1.offsetFromRoot)(options.e2eProjectRoot);
|
101
|
-
const coverageDirectory = isUsingTsSolutionConfig
|
104
|
+
const coverageDirectory = options.isUsingTsSolutionConfig
|
102
105
|
? 'test-output/jest/coverage'
|
103
106
|
: (0, devkit_1.joinPathFragments)(rootOffset, 'coverage', options.e2eProjectName);
|
107
|
+
const projectSimpleName = options.project.split('/').pop();
|
104
108
|
if (options.projectType === 'server') {
|
105
109
|
(0, devkit_1.generateFiles)(host, path.join(__dirname, 'files/server/common'), options.e2eProjectRoot, {
|
106
110
|
...options,
|
107
|
-
...(0, devkit_1.names)(options.rootProject ? 'server' :
|
111
|
+
...(0, devkit_1.names)(options.rootProject ? 'server' : projectSimpleName),
|
108
112
|
tsConfigFile,
|
109
113
|
offsetFromRoot: rootOffset,
|
110
114
|
jestPreset,
|
111
115
|
coverageDirectory,
|
112
|
-
isUsingTsSolutionConfig,
|
113
116
|
tmpl: '',
|
114
117
|
});
|
115
118
|
if (options.isNest) {
|
116
119
|
(0, devkit_1.generateFiles)(host, path.join(__dirname, 'files/server/nest'), options.e2eProjectRoot, {
|
117
120
|
...options,
|
118
|
-
...(0, devkit_1.names)(options.rootProject ? 'server' :
|
121
|
+
...(0, devkit_1.names)(options.rootProject ? 'server' : projectSimpleName),
|
119
122
|
tsConfigFile,
|
120
123
|
offsetFromRoot: rootOffset,
|
121
124
|
tmpl: '',
|
@@ -126,17 +129,16 @@ async function e2eProjectGeneratorInternal(host, _options) {
|
|
126
129
|
const mainFile = appProject.targets.build?.options?.outputPath;
|
127
130
|
(0, devkit_1.generateFiles)(host, path.join(__dirname, 'files/cli'), options.e2eProjectRoot, {
|
128
131
|
...options,
|
129
|
-
...(0, devkit_1.names)(options.rootProject ? 'cli' :
|
132
|
+
...(0, devkit_1.names)(options.rootProject ? 'cli' : projectSimpleName),
|
130
133
|
mainFile,
|
131
134
|
tsConfigFile,
|
132
135
|
offsetFromRoot: rootOffset,
|
133
136
|
jestPreset,
|
134
137
|
coverageDirectory,
|
135
|
-
isUsingTsSolutionConfig,
|
136
138
|
tmpl: '',
|
137
139
|
});
|
138
140
|
}
|
139
|
-
if (isUsingTsSolutionConfig) {
|
141
|
+
if (options.isUsingTsSolutionConfig) {
|
140
142
|
(0, add_swc_config_1.addSwcTestConfig)(host, options.e2eProjectRoot, 'es6');
|
141
143
|
(0, devkit_1.generateFiles)(host, path.join(__dirname, 'files/ts-solution'), options.e2eProjectRoot, {
|
142
144
|
...options,
|
@@ -177,7 +179,7 @@ async function e2eProjectGeneratorInternal(host, _options) {
|
|
177
179
|
]);
|
178
180
|
}
|
179
181
|
}
|
180
|
-
if (isUsingTsSolutionConfig) {
|
182
|
+
if (options.isUsingTsSolutionConfig) {
|
181
183
|
(0, devkit_1.updateJson)(host, 'tsconfig.json', (json) => {
|
182
184
|
json.references ??= [];
|
183
185
|
const e2eRef = `./${options.e2eProjectRoot}`;
|
@@ -189,8 +191,8 @@ async function e2eProjectGeneratorInternal(host, _options) {
|
|
189
191
|
}
|
190
192
|
// If we are using the new TS solution
|
191
193
|
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
192
|
-
if (isUsingTsSolutionConfig) {
|
193
|
-
(0, ts_solution_setup_1.addProjectToTsSolutionWorkspace)(host, options.e2eProjectRoot);
|
194
|
+
if (options.isUsingTsSolutionConfig) {
|
195
|
+
await (0, ts_solution_setup_1.addProjectToTsSolutionWorkspace)(host, options.e2eProjectRoot);
|
194
196
|
}
|
195
197
|
if (!options.skipFormat) {
|
196
198
|
await (0, devkit_1.formatFiles)(host);
|
@@ -201,22 +203,30 @@ async function e2eProjectGeneratorInternal(host, _options) {
|
|
201
203
|
return (0, devkit_1.runTasksInSerial)(...tasks);
|
202
204
|
}
|
203
205
|
async function normalizeOptions(tree, options) {
|
204
|
-
|
205
|
-
|
206
|
+
let directory = options.rootProject ? 'e2e' : options.directory;
|
207
|
+
if (!directory) {
|
208
|
+
const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
|
209
|
+
directory = `${projectConfig.root}-e2e`;
|
210
|
+
}
|
211
|
+
const { projectName: e2eProjectName, projectRoot: e2eProjectRoot, importPath, } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(tree, {
|
206
212
|
name: options.name,
|
207
|
-
projectType: '
|
208
|
-
directory
|
213
|
+
projectType: 'application',
|
214
|
+
directory,
|
209
215
|
});
|
210
216
|
const nxJson = (0, devkit_1.readNxJson)(tree);
|
211
217
|
const addPlugin = process.env.NX_ADD_PLUGINS !== 'false' &&
|
212
218
|
nxJson.useInferencePlugins !== false;
|
219
|
+
const isUsingTsSolutionConfig = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
|
213
220
|
return {
|
214
221
|
addPlugin,
|
215
222
|
...options,
|
216
223
|
e2eProjectRoot,
|
217
224
|
e2eProjectName,
|
225
|
+
importPath,
|
218
226
|
port: options.port ?? 3000,
|
219
227
|
rootProject: !!options.rootProject,
|
228
|
+
isUsingTsSolutionConfig,
|
229
|
+
useProjectJson: options.useProjectJson ?? !isUsingTsSolutionConfig,
|
220
230
|
};
|
221
231
|
}
|
222
232
|
exports.default = e2eProjectGenerator;
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import { waitForPortOpen } from '@nx/node/utils';
|
2
|
+
|
1
3
|
/* eslint-disable */
|
2
4
|
var __TEARDOWN_MESSAGE__: string;
|
3
5
|
|
@@ -5,6 +7,10 @@ module.exports = async function() {
|
|
5
7
|
// Start services that that the app needs to run (e.g. database, docker-compose, etc.).
|
6
8
|
console.log('\nSetting up...\n');
|
7
9
|
|
10
|
+
const host = process.env.HOST ?? 'localhost';
|
11
|
+
const port = process.env.PORT ? Number(process.env.PORT) : <%= port %>;
|
12
|
+
await waitForPortOpen(port, { host });
|
13
|
+
|
8
14
|
// Hint: Use `globalThis` to pass variables to global teardown.
|
9
15
|
globalThis.__TEARDOWN_MESSAGE__ = '\nTearing down...\n';
|
10
16
|
};
|
package/src/generators/e2e-project/files/server/common/src/support/global-teardown.ts__tmpl__
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
import { killPort } from '@nx/node/utils';
|
1
2
|
/* eslint-disable */
|
2
3
|
|
3
4
|
module.exports = async function() {
|
4
5
|
// Put clean up logic here (e.g. stopping services, docker-compose, etc.).
|
5
6
|
// Hint: `globalThis` is shared between setup and teardown.
|
7
|
+
const port = process.env.PORT ? Number(process.env.PORT) : <%= port %>;
|
8
|
+
await killPort(port);
|
6
9
|
console.log(globalThis.__TEARDOWN_MESSAGE__);
|
7
10
|
};
|
@@ -59,6 +59,10 @@
|
|
59
59
|
"default": false,
|
60
60
|
"hidden": true,
|
61
61
|
"x-priority": "internal"
|
62
|
+
},
|
63
|
+
"useProjectJson": {
|
64
|
+
"type": "boolean",
|
65
|
+
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
62
66
|
}
|
63
67
|
},
|
64
68
|
"required": ["project"]
|
@@ -12,11 +12,11 @@ const versions_1 = require("../../utils/versions");
|
|
12
12
|
const init_1 = require("../init/init");
|
13
13
|
const target_defaults_utils_1 = require("@nx/devkit/src/generators/target-defaults-utils");
|
14
14
|
const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
|
15
|
-
const get_import_path_1 = require("@nx/js/src/utils/get-import-path");
|
16
15
|
const sort_fields_1 = require("@nx/js/src/utils/package-json/sort-fields");
|
17
16
|
async function libraryGenerator(tree, schema) {
|
18
17
|
return await libraryGeneratorInternal(tree, {
|
19
18
|
addPlugin: false,
|
19
|
+
useProjectJson: true,
|
20
20
|
...schema,
|
21
21
|
});
|
22
22
|
}
|
@@ -25,21 +25,21 @@ async function libraryGeneratorInternal(tree, schema) {
|
|
25
25
|
// If we are using the new TS solution
|
26
26
|
// We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
|
27
27
|
if (options.isUsingTsSolutionConfig) {
|
28
|
-
(0, ts_solution_setup_1.addProjectToTsSolutionWorkspace)(tree, options.projectRoot);
|
28
|
+
await (0, ts_solution_setup_1.addProjectToTsSolutionWorkspace)(tree, options.projectRoot);
|
29
29
|
}
|
30
30
|
const tasks = [];
|
31
31
|
if (options.publishable === true && !schema.importPath) {
|
32
32
|
throw new Error(`For publishable libs you have to provide a proper "--importPath" which needs to be a valid npm package name (e.g. my-awesome-lib or @myorg/my-lib)`);
|
33
33
|
}
|
34
34
|
// Create `package.json` first because @nx/js:lib generator will update it.
|
35
|
-
if (options.
|
35
|
+
if (!options.useProjectJson ||
|
36
|
+
options.isUsingTsSolutionConfig ||
|
36
37
|
options.publishable ||
|
37
38
|
options.buildable) {
|
38
39
|
(0, devkit_1.writeJson)(tree, (0, devkit_1.joinPathFragments)(options.projectRoot, 'package.json'), {
|
39
|
-
name:
|
40
|
+
name: options.importPath,
|
40
41
|
version: '0.0.1',
|
41
42
|
private: true,
|
42
|
-
files: options.publishable ? ['dist', '!**/*.tsbuildinfo'] : undefined,
|
43
43
|
});
|
44
44
|
}
|
45
45
|
tasks.push(await (0, js_1.libraryGenerator)(tree, {
|
@@ -50,7 +50,7 @@ async function libraryGeneratorInternal(tree, schema) {
|
|
50
50
|
testEnvironment: 'node',
|
51
51
|
skipFormat: true,
|
52
52
|
setParserOptionsProject: schema.setParserOptionsProject,
|
53
|
-
useProjectJson:
|
53
|
+
useProjectJson: options.useProjectJson,
|
54
54
|
}));
|
55
55
|
updatePackageJson(tree, options);
|
56
56
|
tasks.push(await (0, init_1.initGenerator)(tree, {
|
@@ -75,7 +75,7 @@ async function libraryGeneratorInternal(tree, schema) {
|
|
75
75
|
}
|
76
76
|
exports.default = libraryGenerator;
|
77
77
|
async function normalizeOptions(tree, options) {
|
78
|
-
await (0, project_name_and_root_utils_1.
|
78
|
+
await (0, project_name_and_root_utils_1.ensureRootProjectName)(options, 'library');
|
79
79
|
const { projectName, names: projectNames, projectRoot, importPath, } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(tree, {
|
80
80
|
name: options.name,
|
81
81
|
projectType: 'library',
|
@@ -96,13 +96,12 @@ async function normalizeOptions(tree, options) {
|
|
96
96
|
return {
|
97
97
|
...options,
|
98
98
|
fileName,
|
99
|
-
projectName: isUsingTsSolutionConfig
|
100
|
-
? (0, get_import_path_1.getImportPath)(tree, projectName)
|
101
|
-
: projectName,
|
99
|
+
projectName: isUsingTsSolutionConfig && !options.name ? importPath : projectName,
|
102
100
|
projectRoot,
|
103
101
|
parsedTags,
|
104
102
|
importPath,
|
105
103
|
isUsingTsSolutionConfig,
|
104
|
+
useProjectJson: options.useProjectJson ?? !isUsingTsSolutionConfig,
|
106
105
|
};
|
107
106
|
}
|
108
107
|
function createFiles(tree, options) {
|
@@ -123,6 +123,10 @@
|
|
123
123
|
"type": "boolean",
|
124
124
|
"description": "Whether or not to configure the ESLint `parserOptions.project`. We do not do this by default for lint performance reasons.",
|
125
125
|
"default": false
|
126
|
+
},
|
127
|
+
"useProjectJson": {
|
128
|
+
"type": "boolean",
|
129
|
+
"description": "Use a `project.json` configuration file instead of inlining the Nx configuration in the `package.json` file."
|
126
130
|
}
|
127
131
|
},
|
128
132
|
"required": ["directory"]
|
@@ -0,0 +1,36 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.kill = void 0;
|
4
|
+
exports.killPort = killPort;
|
5
|
+
const devkit_1 = require("@nx/devkit");
|
6
|
+
const tcp_port_used_1 = require("tcp-port-used");
|
7
|
+
exports.kill = require('kill-port');
|
8
|
+
/**
|
9
|
+
* Kills the process on the given port
|
10
|
+
* @param port
|
11
|
+
* @param killPortDelay
|
12
|
+
*/
|
13
|
+
async function killPort(port, killPortDelay = 2500) {
|
14
|
+
if (await (0, tcp_port_used_1.check)(port)) {
|
15
|
+
let killPortResult;
|
16
|
+
try {
|
17
|
+
devkit_1.logger.info(`Attempting to close port ${port}`);
|
18
|
+
killPortResult = await (0, exports.kill)(port);
|
19
|
+
await new Promise((resolve) => setTimeout(() => resolve(), killPortDelay));
|
20
|
+
if (await (0, tcp_port_used_1.check)(port)) {
|
21
|
+
devkit_1.logger.error(`Port ${port} still open ${JSON.stringify(killPortResult)}`);
|
22
|
+
}
|
23
|
+
else {
|
24
|
+
devkit_1.logger.info(`Port ${port} successfully closed`);
|
25
|
+
return true;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
catch {
|
29
|
+
devkit_1.logger.error(`Port ${port} closing failed`);
|
30
|
+
}
|
31
|
+
return false;
|
32
|
+
}
|
33
|
+
else {
|
34
|
+
return true;
|
35
|
+
}
|
36
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
interface WaitForPortOpenOptions {
|
2
|
+
/**
|
3
|
+
* The host to connect to
|
4
|
+
* @default 'localhost'
|
5
|
+
*/
|
6
|
+
host?: string;
|
7
|
+
/**
|
8
|
+
* The number of retries to attempt
|
9
|
+
* @default 120
|
10
|
+
*/
|
11
|
+
retries?: number;
|
12
|
+
/**
|
13
|
+
* The delay between retries
|
14
|
+
* @default 1000
|
15
|
+
*/
|
16
|
+
retryDelay?: number;
|
17
|
+
}
|
18
|
+
/**
|
19
|
+
* Waits for the given port to be open
|
20
|
+
* @param port
|
21
|
+
* @param options
|
22
|
+
*/
|
23
|
+
export declare function waitForPortOpen(port: number, options?: WaitForPortOpenOptions): Promise<void>;
|
24
|
+
export {};
|
@@ -0,0 +1,47 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.waitForPortOpen = waitForPortOpen;
|
4
|
+
const net = require("net");
|
5
|
+
const devkit_1 = require("@nx/devkit");
|
6
|
+
/**
|
7
|
+
* Waits for the given port to be open
|
8
|
+
* @param port
|
9
|
+
* @param options
|
10
|
+
*/
|
11
|
+
function waitForPortOpen(port, options = {}) {
|
12
|
+
const host = options.host ?? 'localhost';
|
13
|
+
const allowedErrorCodes = ['ECONNREFUSED', 'ECONNRESET', 'ETIMEDOUT'];
|
14
|
+
return new Promise((resolve, reject) => {
|
15
|
+
const checkPort = (retries = options.retries ?? 120) => {
|
16
|
+
const client = new net.Socket();
|
17
|
+
const cleanupClient = () => {
|
18
|
+
client.removeAllListeners('connect');
|
19
|
+
client.removeAllListeners('error');
|
20
|
+
client.end();
|
21
|
+
client.destroy();
|
22
|
+
client.unref();
|
23
|
+
};
|
24
|
+
client.once('connect', () => {
|
25
|
+
cleanupClient();
|
26
|
+
resolve();
|
27
|
+
});
|
28
|
+
client.once('error', (err) => {
|
29
|
+
if (retries === 0 || !allowedErrorCodes.includes(err['code'])) {
|
30
|
+
if (process.env['NX_VERBOSE_LOGGING'] === 'true') {
|
31
|
+
devkit_1.logger.info(`Error connecting on ${host}:${port}: ${err['code'] || err}`);
|
32
|
+
}
|
33
|
+
cleanupClient();
|
34
|
+
reject(err);
|
35
|
+
}
|
36
|
+
else {
|
37
|
+
setTimeout(() => checkPort(retries - 1), options.retryDelay ?? 1000);
|
38
|
+
}
|
39
|
+
});
|
40
|
+
if (process.env['NX_VERBOSE_LOGGING'] === 'true') {
|
41
|
+
devkit_1.logger.info(`Connecting on ${host}:${port}`);
|
42
|
+
}
|
43
|
+
client.connect({ port, host });
|
44
|
+
};
|
45
|
+
checkPort();
|
46
|
+
});
|
47
|
+
}
|
package/utils.d.ts
ADDED
package/utils.js
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.killPort = exports.waitForPortOpen = void 0;
|
4
|
+
var wait_for_port_open_1 = require("./src/utils/wait-for-port-open");
|
5
|
+
Object.defineProperty(exports, "waitForPortOpen", { enumerable: true, get: function () { return wait_for_port_open_1.waitForPortOpen; } });
|
6
|
+
var kill_port_1 = require("./src/utils/kill-port");
|
7
|
+
Object.defineProperty(exports, "killPort", { enumerable: true, get: function () { return kill_port_1.killPort; } });
|