@nx/node 21.0.0-beta.0 → 21.0.0-beta.10

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/migrations.json CHANGED
@@ -1,24 +1,6 @@
1
1
  {
2
2
  "generators": {},
3
3
  "packageJsonUpdates": {
4
- "17.3.0": {
5
- "version": "17.3.0-beta.3",
6
- "packages": {
7
- "@types/node": {
8
- "version": "18.16.9",
9
- "alwaysAddToPackageJson": false
10
- }
11
- }
12
- },
13
- "17.3.1": {
14
- "version": "17.3.1-beta.0",
15
- "packages": {
16
- "axios": {
17
- "version": "^1.6.0",
18
- "alwaysAddToPackageJson": false
19
- }
20
- }
21
- },
22
4
  "20.4.0": {
23
5
  "version": "20.4.0-beta.3",
24
6
  "packages": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/node",
3
- "version": "21.0.0-beta.0",
3
+ "version": "21.0.0-beta.10",
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.0",
36
- "@nx/jest": "21.0.0-beta.0",
37
- "@nx/js": "21.0.0-beta.0",
38
- "@nx/eslint": "21.0.0-beta.0"
35
+ "@nx/devkit": "21.0.0-beta.10",
36
+ "@nx/jest": "21.0.0-beta.10",
37
+ "@nx/js": "21.0.0-beta.10",
38
+ "@nx/eslint": "21.0.0-beta.10",
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
- if (options.isUsingTsSolutionConfig) {
142
- (0, devkit_1.writeJson)(tree, (0, devkit_1.joinPathFragments)(options.appProjectRoot, 'package.json'), {
143
- name: (0, get_import_path_1.getImportPath)(tree, options.name),
144
- version: '0.0.1',
145
- private: true,
146
- nx: {
147
- name: options.name,
148
- projectType: 'application',
149
- sourceRoot: project.sourceRoot,
150
- targets: project.targets,
151
- tags: project.tags?.length ? project.tags : undefined,
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 && projectConfig.targets.serve) {
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.serve.options = {
200
- ...projectConfig.targets.serve.options,
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.ensureProjectName)(host, options, 'application');
457
- const { projectName: appProjectName, projectRoot: appProjectRoot } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(host, {
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 ? options.name : appProjectRoot),
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;
@@ -25,6 +25,7 @@ export interface Schema {
25
25
  isNest?: boolean;
26
26
  addPlugin?: boolean;
27
27
  useTsSolution?: boolean;
28
+ useProjectJson?: boolean;
28
29
  }
29
30
 
30
31
  export type NodeJsFrameWorks = 'express' | 'koa' | 'fastify' | 'nest' | 'none';
@@ -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
- if (isUsingTsSolutionConfig) {
31
- (0, devkit_1.writeJson)(host, (0, devkit_1.joinPathFragments)(options.e2eProjectRoot, 'package.json'), {
32
- name: (0, get_import_path_1.getImportPath)(host, options.e2eProjectName),
33
- version: '0.0.1',
34
- private: true,
35
- nx: {
36
- name: options.e2eProjectName,
37
- projectType: 'application',
38
- implicitDependencies: [options.project],
39
- targets: {
40
- e2e: {
41
- executor: '@nx/jest:jest',
42
- outputs: ['{workspaceRoot}/coverage/{e2eProjectRoot}'],
43
- options: {
44
- jestConfig: `${options.e2eProjectRoot}/jest.config.ts`,
45
- passWithNoTests: true,
46
- },
47
- dependsOn: [`${options.project}:build`],
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' : options.project),
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' : options.project),
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' : options.project),
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
- options.directory = options.directory ?? `${options.project}-e2e`;
205
- const { projectName: e2eProjectName, projectRoot: e2eProjectRoot } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(tree, {
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: 'library',
208
- directory: options.rootProject ? 'e2e' : options.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
  };
@@ -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
  };
@@ -9,4 +9,5 @@ export interface Schema {
9
9
  isNest?: boolean;
10
10
  skipFormat?: boolean;
11
11
  addPlugin?: boolean;
12
+ useProjectJson?: boolean;
12
13
  }
@@ -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.isUsingTsSolutionConfig ||
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: (0, get_import_path_1.getImportPath)(tree, options.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: !options.isUsingTsSolutionConfig,
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.ensureProjectName)(tree, options, 'library');
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) {
@@ -21,4 +21,5 @@ export interface Schema {
21
21
  setParserOptionsProject?: boolean;
22
22
  compiler: 'tsc' | 'swc';
23
23
  addPlugin?: boolean;
24
+ useProjectJson?: boolean;
24
25
  }
@@ -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,7 @@
1
+ export declare const kill: any;
2
+ /**
3
+ * Kills the process on the given port
4
+ * @param port
5
+ * @param killPortDelay
6
+ */
7
+ export declare function killPort(port: number, killPortDelay?: number): Promise<boolean>;
@@ -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
@@ -0,0 +1,2 @@
1
+ export { waitForPortOpen } from './src/utils/wait-for-port-open';
2
+ export { killPort } from './src/utils/kill-port';
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; } });