@nx/node 0.0.0-pr-31222-862e973 → 0.0.0-pr-31313-387cdca

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.
Files changed (46) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -1
  3. package/migrations.json +24 -38
  4. package/package.json +9 -8
  5. package/src/generators/application/application.d.ts +3 -1
  6. package/src/generators/application/application.js +102 -27
  7. package/src/generators/application/files/common/tsconfig.app.json +0 -1
  8. package/src/generators/application/files/common/webpack.config.js__tmpl__ +4 -4
  9. package/src/generators/application/schema.d.ts +5 -5
  10. package/src/generators/application/schema.json +27 -30
  11. package/src/generators/e2e-project/e2e-project.js +112 -32
  12. package/src/generators/e2e-project/files/cli/jest.config.ts__tmpl__ +17 -4
  13. package/src/generators/e2e-project/files/server/common/jest.config.ts__tmpl__ +17 -4
  14. package/src/generators/e2e-project/files/server/common/src/support/global-setup.ts__tmpl__ +6 -0
  15. package/src/generators/e2e-project/files/server/common/src/support/global-teardown.ts__tmpl__ +3 -0
  16. package/src/generators/e2e-project/files/server/common/src/support/test-setup.ts__tmpl__ +0 -1
  17. package/src/generators/e2e-project/files/ts-solution/tsconfig.json__tmpl__ +14 -0
  18. package/src/generators/e2e-project/schema.d.ts +1 -3
  19. package/src/generators/e2e-project/schema.json +4 -5
  20. package/src/generators/library/files/ts-solution/tsconfig.lib.json +15 -0
  21. package/src/generators/library/library.d.ts +1 -0
  22. package/src/generators/library/library.js +78 -43
  23. package/src/generators/library/schema.d.ts +3 -5
  24. package/src/generators/library/schema.json +21 -24
  25. package/src/utils/kill-port.d.ts +7 -0
  26. package/src/utils/kill-port.js +36 -0
  27. package/src/utils/versions.d.ts +6 -6
  28. package/src/utils/versions.js +6 -6
  29. package/src/utils/wait-for-port-open.d.ts +24 -0
  30. package/src/utils/wait-for-port-open.js +47 -0
  31. package/utils.d.ts +2 -0
  32. package/utils.js +7 -0
  33. package/src/generators/e2e-project/files/cli/tsconfig.spec.json__tmpl__ +0 -12
  34. package/src/generators/e2e-project/files/server/common/tsconfig.json__tmpl__ +0 -13
  35. package/src/generators/library/files/lib/package.json__tmpl__ +0 -4
  36. package/src/migrations/update-16-0-0/update-webpack-executor.d.ts +0 -2
  37. package/src/migrations/update-16-0-0/update-webpack-executor.js +0 -17
  38. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.d.ts +0 -2
  39. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.js +0 -9
  40. package/src/migrations/update-16-3-1/update-webpack-executor.d.ts +0 -2
  41. package/src/migrations/update-16-3-1/update-webpack-executor.js +0 -17
  42. package/src/migrations/update-16-4-0/replace-node-executor.d.ts +0 -2
  43. package/src/migrations/update-16-4-0/replace-node-executor.js +0 -14
  44. /package/src/generators/e2e-project/files/{cli → non-ts-solution}/tsconfig.json__tmpl__ +0 -0
  45. /package/src/generators/e2e-project/files/{server/common → non-ts-solution}/tsconfig.spec.json__tmpl__ +0 -0
  46. /package/src/generators/library/files/{lib → non-ts-solution}/tsconfig.lib.json +0 -0
@@ -11,10 +11,13 @@ const versions_1 = require("../../utils/versions");
11
11
  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
+ const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
15
+ const posix_1 = require("node:path/posix");
16
+ const add_swc_config_1 = require("@nx/js/src/utils/swc/add-swc-config");
14
17
  async function e2eProjectGenerator(host, options) {
15
18
  return await e2eProjectGeneratorInternal(host, {
16
19
  addPlugin: false,
17
- projectNameAndRootFormat: 'derived',
20
+ useProjectJson: true,
18
21
  ...options,
19
22
  });
20
23
  }
@@ -23,22 +26,51 @@ async function e2eProjectGeneratorInternal(host, _options) {
23
26
  const options = await normalizeOptions(host, _options);
24
27
  const appProject = (0, devkit_1.readProjectConfiguration)(host, options.project);
25
28
  // TODO(@ndcunningham): This is broken.. the outputs are wrong.. and this isn't using the jest generator
26
- (0, devkit_1.addProjectConfiguration)(host, options.e2eProjectName, {
27
- root: options.e2eProjectRoot,
28
- implicitDependencies: [options.project],
29
- projectType: 'application',
30
- targets: {
31
- e2e: {
32
- executor: '@nx/jest:jest',
33
- outputs: ['{workspaceRoot}/coverage/{e2eProjectRoot}'],
34
- options: {
35
- jestConfig: `${options.e2eProjectRoot}/jest.config.ts`,
36
- passWithNoTests: true,
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,
47
+ },
48
+ dependsOn: [`${options.project}:build`, `${options.project}:serve`],
37
49
  },
38
- dependsOn: [`${options.project}:build`],
39
50
  },
40
- },
41
- });
51
+ };
52
+ }
53
+ else {
54
+ (0, devkit_1.addProjectConfiguration)(host, options.e2eProjectName, {
55
+ root: options.e2eProjectRoot,
56
+ implicitDependencies: [options.project],
57
+ projectType: 'application',
58
+ targets: {
59
+ e2e: {
60
+ executor: '@nx/jest:jest',
61
+ outputs: ['{workspaceRoot}/coverage/{e2eProjectRoot}'],
62
+ options: {
63
+ jestConfig: `${options.e2eProjectRoot}/jest.config.ts`,
64
+ passWithNoTests: true,
65
+ },
66
+ dependsOn: [`${options.project}:build`, `${options.project}:serve`],
67
+ },
68
+ },
69
+ });
70
+ }
71
+ if (!options.useProjectJson || options.isUsingTsSolutionConfig) {
72
+ (0, devkit_1.writeJson)(host, (0, devkit_1.joinPathFragments)(options.e2eProjectRoot, 'package.json'), packageJson);
73
+ }
42
74
  // TODO(@nicholas): Find a better way to get build target
43
75
  // We remove the 'test' target from the e2e project because it is not needed
44
76
  // The 'e2e' target is the one that should run the tests for the e2e project
@@ -65,19 +97,30 @@ async function e2eProjectGeneratorInternal(host, _options) {
65
97
  });
66
98
  }
67
99
  const jestPreset = (0, config_file_1.findRootJestPreset)(host) ?? 'jest.preset.js';
100
+ const tsConfigFile = options.isUsingTsSolutionConfig
101
+ ? 'tsconfig.json'
102
+ : 'tsconfig.spec.json';
103
+ const rootOffset = (0, devkit_1.offsetFromRoot)(options.e2eProjectRoot);
104
+ const coverageDirectory = options.isUsingTsSolutionConfig
105
+ ? 'test-output/jest/coverage'
106
+ : (0, devkit_1.joinPathFragments)(rootOffset, 'coverage', options.e2eProjectName);
107
+ const projectSimpleName = options.project.split('/').pop();
68
108
  if (options.projectType === 'server') {
69
109
  (0, devkit_1.generateFiles)(host, path.join(__dirname, 'files/server/common'), options.e2eProjectRoot, {
70
110
  ...options,
71
- ...(0, devkit_1.names)(options.rootProject ? 'server' : options.project),
72
- offsetFromRoot: (0, devkit_1.offsetFromRoot)(options.e2eProjectRoot),
111
+ ...(0, devkit_1.names)(options.rootProject ? 'server' : projectSimpleName),
112
+ tsConfigFile,
113
+ offsetFromRoot: rootOffset,
73
114
  jestPreset,
115
+ coverageDirectory,
74
116
  tmpl: '',
75
117
  });
76
118
  if (options.isNest) {
77
119
  (0, devkit_1.generateFiles)(host, path.join(__dirname, 'files/server/nest'), options.e2eProjectRoot, {
78
120
  ...options,
79
- ...(0, devkit_1.names)(options.rootProject ? 'server' : options.project),
80
- offsetFromRoot: (0, devkit_1.offsetFromRoot)(options.e2eProjectRoot),
121
+ ...(0, devkit_1.names)(options.rootProject ? 'server' : projectSimpleName),
122
+ tsConfigFile,
123
+ offsetFromRoot: rootOffset,
81
124
  tmpl: '',
82
125
  });
83
126
  }
@@ -86,20 +129,38 @@ async function e2eProjectGeneratorInternal(host, _options) {
86
129
  const mainFile = appProject.targets.build?.options?.outputPath;
87
130
  (0, devkit_1.generateFiles)(host, path.join(__dirname, 'files/cli'), options.e2eProjectRoot, {
88
131
  ...options,
89
- ...(0, devkit_1.names)(options.rootProject ? 'cli' : options.project),
132
+ ...(0, devkit_1.names)(options.rootProject ? 'cli' : projectSimpleName),
90
133
  mainFile,
91
- offsetFromRoot: (0, devkit_1.offsetFromRoot)(options.e2eProjectRoot),
134
+ tsConfigFile,
135
+ offsetFromRoot: rootOffset,
92
136
  jestPreset,
137
+ coverageDirectory,
138
+ tmpl: '',
139
+ });
140
+ }
141
+ if (options.isUsingTsSolutionConfig) {
142
+ (0, add_swc_config_1.addSwcTestConfig)(host, options.e2eProjectRoot, 'es6');
143
+ (0, devkit_1.generateFiles)(host, path.join(__dirname, 'files/ts-solution'), options.e2eProjectRoot, {
144
+ ...options,
145
+ relativeProjectReferencePath: (0, posix_1.relative)(options.e2eProjectRoot, appProject.root),
146
+ offsetFromRoot: rootOffset,
147
+ tmpl: '',
148
+ });
149
+ }
150
+ else {
151
+ (0, devkit_1.generateFiles)(host, path.join(__dirname, 'files/non-ts-solution'), options.e2eProjectRoot, {
152
+ ...options,
153
+ offsetFromRoot: rootOffset,
93
154
  tmpl: '',
94
155
  });
95
156
  }
96
157
  // axios is more than likely used in the application code, so install it as a regular dependency.
97
158
  const installTask = (0, devkit_1.addDependenciesToPackageJson)(host, { axios: versions_1.axiosVersion }, {});
98
159
  tasks.push(installTask);
99
- if (options.linter === eslint_1.Linter.EsLint) {
160
+ if (options.linter === 'eslint') {
100
161
  const linterTask = await (0, eslint_1.lintProjectGenerator)(host, {
101
162
  project: options.e2eProjectName,
102
- linter: eslint_1.Linter.EsLint,
163
+ linter: 'eslint',
103
164
  skipFormat: true,
104
165
  tsConfigPaths: [
105
166
  (0, devkit_1.joinPathFragments)(options.e2eProjectRoot, 'tsconfig.json'),
@@ -118,6 +179,21 @@ async function e2eProjectGeneratorInternal(host, _options) {
118
179
  ]);
119
180
  }
120
181
  }
182
+ if (options.isUsingTsSolutionConfig) {
183
+ (0, devkit_1.updateJson)(host, 'tsconfig.json', (json) => {
184
+ json.references ??= [];
185
+ const e2eRef = `./${options.e2eProjectRoot}`;
186
+ if (!json.references.find((ref) => ref.path === e2eRef)) {
187
+ json.references.push({ path: e2eRef });
188
+ }
189
+ return json;
190
+ });
191
+ }
192
+ // If we are using the new TS solution
193
+ // We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
194
+ if (options.isUsingTsSolutionConfig) {
195
+ await (0, ts_solution_setup_1.addProjectToTsSolutionWorkspace)(host, options.e2eProjectRoot);
196
+ }
121
197
  if (!options.skipFormat) {
122
198
  await (0, devkit_1.formatFiles)(host);
123
199
  }
@@ -127,26 +203,30 @@ async function e2eProjectGeneratorInternal(host, _options) {
127
203
  return (0, devkit_1.runTasksInSerial)(...tasks);
128
204
  }
129
205
  async function normalizeOptions(tree, options) {
130
- const { projectName: e2eProjectName, projectRoot: e2eProjectRoot } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(tree, {
131
- name: options.name ?? `${options.project}-e2e`,
132
- projectType: 'library',
133
- directory: options.rootProject ? 'e2e' : options.directory,
134
- projectNameAndRootFormat: options.rootProject
135
- ? 'as-provided'
136
- : options.projectNameAndRootFormat,
137
- // this is an internal generator, don't save defaults
138
- callingGenerator: null,
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, {
212
+ name: options.name,
213
+ projectType: 'application',
214
+ directory,
139
215
  });
140
216
  const nxJson = (0, devkit_1.readNxJson)(tree);
141
217
  const addPlugin = process.env.NX_ADD_PLUGINS !== 'false' &&
142
218
  nxJson.useInferencePlugins !== false;
219
+ const isUsingTsSolutionConfig = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
143
220
  return {
144
221
  addPlugin,
145
222
  ...options,
146
223
  e2eProjectRoot,
147
224
  e2eProjectName,
225
+ importPath,
148
226
  port: options.port ?? 3000,
149
227
  rootProject: !!options.rootProject,
228
+ isUsingTsSolutionConfig,
229
+ useProjectJson: options.useProjectJson ?? !isUsingTsSolutionConfig,
150
230
  };
151
231
  }
152
232
  exports.default = e2eProjectGenerator;
@@ -1,13 +1,26 @@
1
+ <%_ if (isUsingTsSolutionConfig) { _%>
2
+ /* eslint-disable */
3
+ import { readFileSync } from 'fs';
4
+
5
+ // Reading the SWC compilation config for the spec files
6
+ const swcJestConfig = JSON.parse(
7
+ readFileSync(`${__dirname}/.spec.swcrc`, 'utf-8')
8
+ );
9
+
10
+ // Disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves
11
+ swcJestConfig.swcrc = false;
12
+
13
+ <%_ } _%>
1
14
  export default {
2
15
  displayName: '<%= e2eProjectName %>',
3
16
  preset: '<%= offsetFromRoot %><%= jestPreset %>',
4
17
  setupFiles: ['<rootDir>/src/test-setup.ts'],
5
18
  testEnvironment: 'node',
6
19
  transform: {
7
- '^.+\\.[tj]s$': ['ts-jest', {
8
- tsconfig: '<rootDir>/tsconfig.spec.json',
9
- }],
20
+ '^.+\\.[tj]s$': <% if (isUsingTsSolutionConfig) { %>['@swc/jest', swcJestConfig]<% } else { %>['ts-jest', {
21
+ tsconfig: '<rootDir>/<%= tsConfigFile %>',
22
+ }]<% } %>,
10
23
  },
11
24
  moduleFileExtensions: ['ts', 'js', 'html'],
12
- coverageDirectory: '<%= offsetFromRoot %>coverage/<%= e2eProjectName %>',
25
+ coverageDirectory: '<%= coverageDirectory %>',
13
26
  };
@@ -1,3 +1,16 @@
1
+ <%_ if (isUsingTsSolutionConfig) { _%>
2
+ /* eslint-disable */
3
+ import { readFileSync } from 'fs';
4
+
5
+ // Reading the SWC compilation config for the spec files
6
+ const swcJestConfig = JSON.parse(
7
+ readFileSync(`${__dirname}/.spec.swcrc`, 'utf-8')
8
+ );
9
+
10
+ // Disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves
11
+ swcJestConfig.swcrc = false;
12
+
13
+ <%_ } _%>
1
14
  export default {
2
15
  displayName: '<%= e2eProjectName %>',
3
16
  preset: '<%= offsetFromRoot %><%= jestPreset %>',
@@ -6,10 +19,10 @@ export default {
6
19
  setupFiles: ['<rootDir>/src/support/test-setup.ts'],
7
20
  testEnvironment: 'node',
8
21
  transform: {
9
- '^.+\\.[tj]s$': ['ts-jest', {
10
- tsconfig: '<rootDir>/tsconfig.spec.json',
11
- }],
22
+ '^.+\\.[tj]s$': <% if (isUsingTsSolutionConfig) { %>['@swc/jest', swcJestConfig]<% } else { %>['ts-jest', {
23
+ tsconfig: '<rootDir>/<%= tsConfigFile %>',
24
+ }]<% } %>,
12
25
  },
13
26
  moduleFileExtensions: ['ts', 'js', 'html'],
14
- coverageDirectory: '<%= offsetFromRoot %>coverage/<%= e2eProjectName %>',
27
+ coverageDirectory: '<%= coverageDirectory %>',
15
28
  };
@@ -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
  };
@@ -1,5 +1,4 @@
1
1
  /* eslint-disable */
2
-
3
2
  import axios from 'axios';
4
3
 
5
4
  module.exports = async function() {
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "<%= offsetFromRoot %>tsconfig.base.json",
3
+ "compilerOptions": {
4
+ "outDir": "out-tsc/<%= e2eProjectName %>",
5
+ "esModuleInterop": true,
6
+ "noUnusedLocals": false,
7
+ "noImplicitAny": false
8
+ },
9
+ "include": [
10
+ "jest.config.ts",
11
+ "src/**/*.ts"
12
+ ],
13
+ "references": []
14
+ }
@@ -1,10 +1,7 @@
1
- import type { ProjectNameAndRootFormat } from '@nx/devkit/src/generators/project-name-and-root-utils';
2
-
3
1
  export interface Schema {
4
2
  project: string;
5
3
  projectType: 'server' | 'cli';
6
4
  directory?: string;
7
- projectNameAndRootFormat?: ProjectNameAndRootFormat;
8
5
  name?: string;
9
6
  port?: number;
10
7
  linter?: 'eslint' | 'none';
@@ -12,4 +9,5 @@ export interface Schema {
12
9
  isNest?: boolean;
13
10
  skipFormat?: boolean;
14
11
  addPlugin?: boolean;
12
+ useProjectJson?: boolean;
15
13
  }
@@ -18,11 +18,6 @@
18
18
  "type": "string",
19
19
  "x-priority": "important"
20
20
  },
21
- "projectNameAndRootFormat": {
22
- "description": "Whether to generate the project name and root directory as provided (`as-provided`) or generate them composing their values and taking the configured layout into account (`derived`).",
23
- "type": "string",
24
- "enum": ["as-provided", "derived"]
25
- },
26
21
  "name": {
27
22
  "description": "The name of the e2e project. Defaults to the project name with '-e2e' suffix.",
28
23
  "type": "string"
@@ -64,6 +59,10 @@
64
59
  "default": false,
65
60
  "hidden": true,
66
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."
67
66
  }
68
67
  },
69
68
  "required": ["project"]
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "baseUrl": ".",
5
+ "rootDir": "src",
6
+ "module": "nodenext",
7
+ "moduleResolution": "nodenext",
8
+ "outDir": "dist",
9
+ "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo",
10
+ "emitDeclarationOnly": false,
11
+ "types": ["node"]
12
+ },
13
+ "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
14
+ "include": ["src/**/*.ts"]
15
+ }
@@ -6,6 +6,7 @@ export interface NormalizedSchema extends Schema {
6
6
  projectRoot: string;
7
7
  parsedTags: string[];
8
8
  compiler: 'swc' | 'tsc';
9
+ isUsingTsSolutionConfig: boolean;
9
10
  }
10
11
  export declare function libraryGenerator(tree: Tree, schema: Schema): Promise<GeneratorCallback>;
11
12
  export declare function libraryGeneratorInternal(tree: Tree, schema: Schema): Promise<GeneratorCallback>;
@@ -11,40 +11,63 @@ const path_1 = require("path");
11
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
+ const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
15
+ const sort_fields_1 = require("@nx/js/src/utils/package-json/sort-fields");
14
16
  async function libraryGenerator(tree, schema) {
15
17
  return await libraryGeneratorInternal(tree, {
16
18
  addPlugin: false,
17
- projectNameAndRootFormat: 'derived',
19
+ useProjectJson: true,
18
20
  ...schema,
19
21
  });
20
22
  }
21
23
  async function libraryGeneratorInternal(tree, schema) {
22
24
  const options = await normalizeOptions(tree, schema);
23
- const tasks = [
24
- await (0, init_1.initGenerator)(tree, {
25
- ...options,
26
- skipFormat: true,
27
- }),
28
- ];
25
+ // If we are using the new TS solution
26
+ // We need to update the workspace file (package.json or pnpm-workspaces.yaml) to include the new project
27
+ if (options.isUsingTsSolutionConfig) {
28
+ await (0, ts_solution_setup_1.addProjectToTsSolutionWorkspace)(tree, options.projectRoot);
29
+ }
30
+ const tasks = [];
29
31
  if (options.publishable === true && !schema.importPath) {
30
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)`);
31
33
  }
32
- const libraryInstall = await (0, js_1.libraryGenerator)(tree, {
33
- ...options,
34
- bundler: schema.buildable ? 'tsc' : 'none',
34
+ // Create `package.json` first because @nx/js:lib generator will update it.
35
+ if (!options.useProjectJson ||
36
+ options.isUsingTsSolutionConfig ||
37
+ options.publishable ||
38
+ options.buildable) {
39
+ (0, devkit_1.writeJson)(tree, (0, devkit_1.joinPathFragments)(options.projectRoot, 'package.json'), {
40
+ name: options.importPath,
41
+ version: '0.0.1',
42
+ private: true,
43
+ });
44
+ }
45
+ tasks.push(await (0, js_1.libraryGenerator)(tree, {
46
+ ...schema,
47
+ bundler: schema.buildable || schema.publishable ? 'tsc' : 'none',
35
48
  includeBabelRc: schema.babelJest,
36
- importPath: options.importPath,
49
+ importPath: schema.importPath,
37
50
  testEnvironment: 'node',
38
51
  skipFormat: true,
39
- setParserOptionsProject: options.setParserOptionsProject,
40
- });
41
- tasks.push(libraryInstall);
52
+ setParserOptionsProject: schema.setParserOptionsProject,
53
+ useProjectJson: options.useProjectJson,
54
+ }));
55
+ updatePackageJson(tree, options);
56
+ tasks.push(await (0, init_1.initGenerator)(tree, {
57
+ ...options,
58
+ skipFormat: true,
59
+ }));
42
60
  createFiles(tree, options);
43
61
  if (options.js) {
44
62
  (0, devkit_1.updateTsConfigsToJs)(tree, options);
45
63
  }
46
64
  updateProject(tree, options);
47
65
  tasks.push(ensureDependencies(tree));
66
+ // Always run install to link packages.
67
+ if (options.isUsingTsSolutionConfig) {
68
+ tasks.push(() => (0, devkit_1.installPackagesTask)(tree, true));
69
+ }
70
+ (0, sort_fields_1.sortPackageJsonFields)(tree, options.projectRoot);
48
71
  if (!schema.skipFormat) {
49
72
  await (0, devkit_1.formatFiles)(tree);
50
73
  }
@@ -52,41 +75,35 @@ async function libraryGeneratorInternal(tree, schema) {
52
75
  }
53
76
  exports.default = libraryGenerator;
54
77
  async function normalizeOptions(tree, options) {
55
- const { projectName, names: projectNames, projectRoot, importPath, projectNameAndRootFormat, } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(tree, {
78
+ await (0, project_name_and_root_utils_1.ensureRootProjectName)(options, 'library');
79
+ const { projectName, names: projectNames, projectRoot, importPath, } = await (0, project_name_and_root_utils_1.determineProjectNameAndRootOptions)(tree, {
56
80
  name: options.name,
57
81
  projectType: 'library',
58
82
  directory: options.directory,
59
83
  importPath: options.importPath,
60
- projectNameAndRootFormat: options.projectNameAndRootFormat,
61
- callingGenerator: '@nx/node:library',
62
84
  });
63
- options.projectNameAndRootFormat = projectNameAndRootFormat;
64
85
  const nxJson = (0, devkit_1.readNxJson)(tree);
65
86
  const addPluginDefault = process.env.NX_ADD_PLUGINS !== 'false' &&
66
87
  nxJson.useInferencePlugins !== false;
67
88
  options.addPlugin ??= addPluginDefault;
68
- const fileName = getCaseAwareFileName({
69
- fileName: options.simpleModuleName
70
- ? projectNames.projectSimpleName
71
- : projectNames.projectFileName,
72
- pascalCaseFiles: options.pascalCaseFiles,
73
- });
89
+ const fileName = (0, devkit_1.names)(options.simpleModuleName
90
+ ? projectNames.projectSimpleName
91
+ : projectNames.projectFileName).fileName;
74
92
  const parsedTags = options.tags
75
93
  ? options.tags.split(',').map((s) => s.trim())
76
94
  : [];
95
+ const isUsingTsSolutionConfig = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
77
96
  return {
78
97
  ...options,
79
98
  fileName,
80
- projectName,
99
+ projectName: isUsingTsSolutionConfig && !options.name ? importPath : projectName,
81
100
  projectRoot,
82
101
  parsedTags,
83
102
  importPath,
103
+ isUsingTsSolutionConfig,
104
+ useProjectJson: options.useProjectJson ?? !isUsingTsSolutionConfig,
84
105
  };
85
106
  }
86
- function getCaseAwareFileName(options) {
87
- const normalized = (0, devkit_1.names)(options.fileName);
88
- return options.pascalCaseFiles ? normalized.className : normalized.fileName;
89
- }
90
107
  function createFiles(tree, options) {
91
108
  const { className, name, propertyName } = (0, devkit_1.names)(options.fileName);
92
109
  (0, devkit_1.generateFiles)(tree, (0, path_1.join)(__dirname, './files/lib'), options.projectRoot, {
@@ -100,9 +117,6 @@ function createFiles(tree, options) {
100
117
  if (options.unitTestRunner === 'none') {
101
118
  tree.delete((0, path_1.join)(options.projectRoot, `./src/lib/${options.fileName}.spec.ts`));
102
119
  }
103
- if (!options.publishable && !options.buildable) {
104
- tree.delete((0, path_1.join)(options.projectRoot, 'package.json'));
105
- }
106
120
  if (options.js) {
107
121
  (0, devkit_1.toJS)(tree);
108
122
  }
@@ -115,17 +129,25 @@ function updateProject(tree, options) {
115
129
  const rootProject = options.projectRoot === '.' || options.projectRoot === '';
116
130
  project.targets = project.targets || {};
117
131
  (0, target_defaults_utils_1.addBuildTargetDefaults)(tree, `@nx/js:${options.compiler}`);
118
- project.targets.build = {
119
- executor: `@nx/js:${options.compiler}`,
120
- outputs: ['{options.outputPath}'],
121
- options: {
122
- outputPath: (0, devkit_1.joinPathFragments)('dist', rootProject ? options.projectName : options.projectRoot),
123
- tsConfig: `${options.projectRoot}/tsconfig.lib.json`,
124
- packageJson: `${options.projectRoot}/package.json`,
125
- main: `${options.projectRoot}/src/index` + (options.js ? '.js' : '.ts'),
126
- assets: [`${options.projectRoot}/*.md`],
127
- },
128
- };
132
+ // For TS solution, we want tsc build to be inferred by `@nx/js/typescript` plugin.
133
+ if (!options.isUsingTsSolutionConfig || options.compiler === 'swc') {
134
+ project.targets.build = {
135
+ executor: `@nx/js:${options.compiler}`,
136
+ outputs: ['{options.outputPath}'],
137
+ options: {
138
+ outputPath: options.isUsingTsSolutionConfig
139
+ ? (0, devkit_1.joinPathFragments)(options.projectRoot, 'dist')
140
+ : (0, devkit_1.joinPathFragments)('dist', rootProject ? options.projectName : options.projectRoot),
141
+ tsConfig: `${options.projectRoot}/tsconfig.lib.json`,
142
+ packageJson: `${options.projectRoot}/package.json`,
143
+ main: `${options.projectRoot}/src/index` + (options.js ? '.js' : '.ts'),
144
+ assets: options.isUsingTsSolutionConfig
145
+ ? undefined
146
+ : [`${options.projectRoot}/*.md`],
147
+ stripLeadingPaths: options.isUsingTsSolutionConfig ? true : undefined,
148
+ },
149
+ };
150
+ }
129
151
  if (options.compiler === 'swc') {
130
152
  (0, add_swc_dependencies_1.addSwcDependencies)(tree);
131
153
  (0, add_swc_config_1.addSwcConfig)(tree, options.projectRoot);
@@ -138,3 +160,16 @@ function updateProject(tree, options) {
138
160
  function ensureDependencies(tree) {
139
161
  return (0, devkit_1.addDependenciesToPackageJson)(tree, { tslib: versions_1.tslibVersion }, { '@types/node': versions_1.typesNodeVersion });
140
162
  }
163
+ function updatePackageJson(tree, options) {
164
+ const packageJsonPath = (0, devkit_1.joinPathFragments)(options.projectRoot, 'package.json');
165
+ if (!tree.exists(packageJsonPath)) {
166
+ return;
167
+ }
168
+ const packageJson = (0, devkit_1.readJson)(tree, packageJsonPath);
169
+ if (packageJson.type === 'module') {
170
+ // The @nx/js:lib generator can set the type to 'module' which would
171
+ // potentially break consumers of the library.
172
+ delete packageJson.type;
173
+ }
174
+ (0, devkit_1.writeJson)(tree, packageJsonPath, packageJson);
175
+ }
@@ -1,10 +1,8 @@
1
- import type { ProjectNameAndRootFormat } from '@nx/devkit/src/generators/project-name-and-root-utils';
2
1
  import type { Linter, LinterType } from '@nx/eslint';
3
2
 
4
3
  export interface Schema {
5
- name: string;
6
- directory?: string;
7
- projectNameAndRootFormat?: ProjectNameAndRootFormat;
4
+ directory: string;
5
+ name?: string;
8
6
  simpleModuleName?: boolean;
9
7
  skipTsConfig?: boolean;
10
8
  skipFormat?: boolean;
@@ -18,10 +16,10 @@ export interface Schema {
18
16
  rootDir?: string;
19
17
  babelJest?: boolean;
20
18
  js?: boolean;
21
- pascalCaseFiles?: boolean;
22
19
  strict?: boolean;
23
20
  standaloneConfig?: boolean;
24
21
  setParserOptionsProject?: boolean;
25
22
  compiler: 'tsc' | 'swc';
26
23
  addPlugin?: boolean;
24
+ useProjectJson?: boolean;
27
25
  }