@nx/js 20.0.7 → 20.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/js",
3
- "version": "20.0.7",
3
+ "version": "20.1.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": {
@@ -39,8 +39,8 @@
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": "20.0.7",
43
- "@nx/workspace": "20.0.7",
42
+ "@nx/devkit": "20.1.0-beta.0",
43
+ "@nx/workspace": "20.1.0-beta.0",
44
44
  "@zkochan/js-yaml": "0.0.7",
45
45
  "babel-plugin-const-enum": "^1.0.1",
46
46
  "babel-plugin-macros": "^2.8.0",
@@ -29,8 +29,7 @@ async function* nodeExecutor(options, context) {
29
29
  throw new Error(`Cannot find build target ${chalk.bold(options.buildTarget)} for project ${chalk.bold(context.projectName)}`);
30
30
  }
31
31
  const buildTargetExecutor = project.data.targets[buildTarget.target]?.executor;
32
- if (buildTargetExecutor === 'nx:run-commands' ||
33
- buildTargetExecutor === '@nrwl/workspace:run-commands') {
32
+ if (buildTargetExecutor === 'nx:run-commands') {
34
33
  // Run commands does not emit build event, so we have to switch to run entire build through Nx CLI.
35
34
  options.runBuildTargetDependencies = true;
36
35
  }
@@ -113,13 +113,13 @@
113
113
  "description": "Generate a lockfile (e.g. package-lock.json) that matches the workspace lockfile to ensure package versions match.",
114
114
  "default": false,
115
115
  "x-priority": "internal"
116
+ },
117
+ "stripLeadingPaths": {
118
+ "type": "boolean",
119
+ "description": "Remove leading directory from output (e.g. src). See: https://swc.rs/docs/usage/cli#--strip-leading-paths",
120
+ "default": false
116
121
  }
117
122
  },
118
- "stripLeadingPaths": {
119
- "type": "boolean",
120
- "description": "Remove leading directory from output (e.g. src). See: https://swc.rs/docs/usage/cli#--strip-leading-paths",
121
- "default": false
122
- },
123
123
  "required": ["main", "outputPath", "tsConfig"],
124
124
  "definitions": {
125
125
  "assetPattern": {
@@ -2,11 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.swcExecutor = swcExecutor;
4
4
  const devkit_1 = require("@nx/devkit");
5
- const assets_1 = require("../../utils/assets/assets");
6
5
  const fast_glob_1 = require("fast-glob");
7
6
  const node_fs_1 = require("node:fs");
8
7
  const path_1 = require("path");
9
- const assets_2 = require("../../utils/assets");
8
+ const assets_1 = require("../../utils/assets");
9
+ const assets_2 = require("../../utils/assets/assets");
10
10
  const check_dependencies_1 = require("../../utils/check-dependencies");
11
11
  const compiler_helper_dependency_1 = require("../../utils/compiler-helper-dependency");
12
12
  const inline_1 = require("../../utils/inline");
@@ -14,7 +14,20 @@ const package_json_1 = require("../../utils/package-json");
14
14
  const compile_swc_1 = require("../../utils/swc/compile-swc");
15
15
  const get_swcrc_path_1 = require("../../utils/swc/get-swcrc-path");
16
16
  const inline_2 = require("../../utils/swc/inline");
17
+ const ts_solution_setup_1 = require("../../utils/typescript/ts-solution-setup");
17
18
  function normalizeOptions(options, root, sourceRoot, projectRoot) {
19
+ const isTsSolutionSetup = (0, ts_solution_setup_1.isUsingTsSolutionSetup)();
20
+ if (isTsSolutionSetup) {
21
+ if (options.generateLockfile) {
22
+ throw new Error(`Setting 'generateLockfile: true' is not supported with the current TypeScript setup. Unset the 'generateLockfile' option and try again.`);
23
+ }
24
+ if (options.generateExportsField) {
25
+ throw new Error(`Setting 'generateExportsField: true' is not supported with the current TypeScript setup. Set 'exports' field in the 'package.json' file at the project root and unset the 'generateExportsField' option.`);
26
+ }
27
+ if (options.additionalEntryPoints?.length) {
28
+ throw new Error(`Setting 'additionalEntryPoints' is not supported with the current TypeScript setup. Set additional entry points in the 'package.json' file at the project root and unset the 'additionalEntryPoints' option.`);
29
+ }
30
+ }
18
31
  const outputPath = (0, path_1.join)(root, options.outputPath);
19
32
  if (options.skipTypeCheck == null) {
20
33
  options.skipTypeCheck = false;
@@ -34,7 +47,7 @@ function normalizeOptions(options, root, sourceRoot, projectRoot) {
34
47
  options.external = firstItem;
35
48
  }
36
49
  }
37
- const files = (0, assets_1.assetGlobsToFiles)(options.assets, root, outputPath);
50
+ const files = (0, assets_2.assetGlobsToFiles)(options.assets, root, outputPath);
38
51
  // Always execute from root of project, same as with SWC CLI.
39
52
  const swcCwd = (0, path_1.join)(root, projectRoot);
40
53
  const { swcrcPath, tmpSwcrcPath } = (0, get_swcrc_path_1.getSwcrcPath)(options, root, projectRoot);
@@ -57,34 +70,39 @@ function normalizeOptions(options, root, sourceRoot, projectRoot) {
57
70
  tsConfig: (0, path_1.join)(root, options.tsConfig),
58
71
  swcCliOptions,
59
72
  tmpSwcrcPath,
73
+ isTsSolutionSetup: isTsSolutionSetup,
60
74
  };
61
75
  }
62
76
  async function* swcExecutor(_options, context) {
63
77
  const { sourceRoot, root } = context.projectsConfigurations.projects[context.projectName];
64
78
  const options = normalizeOptions(_options, context.root, sourceRoot, root);
65
- const { tmpTsConfig, dependencies } = (0, check_dependencies_1.checkDependencies)(context, options.tsConfig);
66
- if (tmpTsConfig) {
67
- options.tsConfig = tmpTsConfig;
68
- }
69
- const swcHelperDependency = (0, compiler_helper_dependency_1.getHelperDependency)(compiler_helper_dependency_1.HelperDependency.swc, options.swcCliOptions.swcrcPath, dependencies, context.projectGraph);
70
- if (swcHelperDependency) {
71
- dependencies.push(swcHelperDependency);
72
- }
73
- const inlineProjectGraph = (0, inline_1.handleInliningBuild)(context, options, options.tsConfig);
74
- if (!(0, inline_1.isInlineGraphEmpty)(inlineProjectGraph)) {
75
- if (options.stripLeadingPaths) {
76
- throw new Error(`Cannot use --strip-leading-paths with inlining.`);
79
+ let swcHelperDependency;
80
+ let inlineProjectGraph;
81
+ if (!options.isTsSolutionSetup) {
82
+ const { tmpTsConfig, dependencies } = (0, check_dependencies_1.checkDependencies)(context, options.tsConfig);
83
+ if (tmpTsConfig) {
84
+ options.tsConfig = tmpTsConfig;
85
+ }
86
+ swcHelperDependency = (0, compiler_helper_dependency_1.getHelperDependency)(compiler_helper_dependency_1.HelperDependency.swc, options.swcCliOptions.swcrcPath, dependencies, context.projectGraph);
87
+ if (swcHelperDependency) {
88
+ dependencies.push(swcHelperDependency);
89
+ }
90
+ inlineProjectGraph = (0, inline_1.handleInliningBuild)(context, options, options.tsConfig);
91
+ if (!(0, inline_1.isInlineGraphEmpty)(inlineProjectGraph)) {
92
+ if (options.stripLeadingPaths) {
93
+ throw new Error(`Cannot use --strip-leading-paths with inlining.`);
94
+ }
95
+ options.projectRoot = '.'; // set to root of workspace to include other libs for type check
96
+ // remap paths for SWC compilation
97
+ options.inline = true;
98
+ options.swcCliOptions.swcCwd = '.';
99
+ options.swcCliOptions.srcPath = options.swcCliOptions.swcCwd;
100
+ options.swcCliOptions.destPath = (0, path_1.join)(options.swcCliOptions.destPath.split((0, path_1.normalize)('../')).at(-1), options.swcCliOptions.srcPath);
101
+ // tmp swcrc with dependencies to exclude
102
+ // - buildable libraries
103
+ // - other libraries that are not dependent on the current project
104
+ options.swcCliOptions.swcrcPath = (0, inline_2.generateTmpSwcrc)(inlineProjectGraph, options.swcCliOptions.swcrcPath, options.tmpSwcrcPath);
77
105
  }
78
- options.projectRoot = '.'; // set to root of workspace to include other libs for type check
79
- // remap paths for SWC compilation
80
- options.inline = true;
81
- options.swcCliOptions.swcCwd = '.';
82
- options.swcCliOptions.srcPath = options.swcCliOptions.swcCwd;
83
- options.swcCliOptions.destPath = (0, path_1.join)(options.swcCliOptions.destPath.split((0, path_1.normalize)('../')).at(-1), options.swcCliOptions.srcPath);
84
- // tmp swcrc with dependencies to exclude
85
- // - buildable libraries
86
- // - other libraries that are not dependent on the current project
87
- options.swcCliOptions.swcrcPath = (0, inline_2.generateTmpSwcrc)(inlineProjectGraph, options.swcCliOptions.swcrcPath, options.tmpSwcrcPath);
88
106
  }
89
107
  function determineModuleFormatFromSwcrc(absolutePathToSwcrc) {
90
108
  const swcrc = (0, devkit_1.readJsonFile)(absolutePathToSwcrc);
@@ -95,14 +113,17 @@ async function* swcExecutor(_options, context) {
95
113
  process.on('SIGINT', () => disposeFn());
96
114
  process.on('SIGTERM', () => disposeFn());
97
115
  return yield* (0, compile_swc_1.compileSwcWatch)(context, options, async () => {
98
- const assetResult = await (0, assets_2.copyAssets)(options, context);
99
- const packageJsonResult = await (0, package_json_1.copyPackageJson)({
100
- ...options,
101
- additionalEntryPoints: createEntryPoints(options, context),
102
- format: [
103
- determineModuleFormatFromSwcrc(options.swcCliOptions.swcrcPath),
104
- ],
105
- }, context);
116
+ const assetResult = await (0, assets_1.copyAssets)(options, context);
117
+ let packageJsonResult;
118
+ if (!options.isTsSolutionSetup) {
119
+ packageJsonResult = await (0, package_json_1.copyPackageJson)({
120
+ ...options,
121
+ additionalEntryPoints: createEntryPoints(options, context),
122
+ format: [
123
+ determineModuleFormatFromSwcrc(options.swcCliOptions.swcrcPath),
124
+ ],
125
+ }, context);
126
+ }
106
127
  removeTmpSwcrc(options.swcCliOptions.swcrcPath);
107
128
  disposeFn = () => {
108
129
  assetResult?.stop();
@@ -112,17 +133,19 @@ async function* swcExecutor(_options, context) {
112
133
  }
113
134
  else {
114
135
  return yield (0, compile_swc_1.compileSwc)(context, options, async () => {
115
- await (0, assets_2.copyAssets)(options, context);
116
- await (0, package_json_1.copyPackageJson)({
117
- ...options,
118
- additionalEntryPoints: createEntryPoints(options, context),
119
- format: [
120
- determineModuleFormatFromSwcrc(options.swcCliOptions.swcrcPath),
121
- ],
122
- extraDependencies: swcHelperDependency ? [swcHelperDependency] : [],
123
- }, context);
136
+ await (0, assets_1.copyAssets)(options, context);
137
+ if (!options.isTsSolutionSetup) {
138
+ await (0, package_json_1.copyPackageJson)({
139
+ ...options,
140
+ additionalEntryPoints: createEntryPoints(options, context),
141
+ format: [
142
+ determineModuleFormatFromSwcrc(options.swcCliOptions.swcrcPath),
143
+ ],
144
+ extraDependencies: swcHelperDependency ? [swcHelperDependency] : [],
145
+ }, context);
146
+ (0, inline_1.postProcessInlinedDependencies)(options.outputPath, options.originalProjectRoot, inlineProjectGraph);
147
+ }
124
148
  removeTmpSwcrc(options.swcCliOptions.swcrcPath);
125
- (0, inline_1.postProcessInlinedDependencies)(options.outputPath, options.originalProjectRoot, inlineProjectGraph);
126
149
  });
127
150
  }
128
151
  }
@@ -9,8 +9,8 @@ const versions_1 = require("../../utils/versions");
9
9
  async function convertToSwcGenerator(tree, schema) {
10
10
  const options = normalizeOptions(schema);
11
11
  const projectConfiguration = (0, devkit_1.readProjectConfiguration)(tree, options.project);
12
- updateProjectBuildTargets(tree, projectConfiguration, options.project, options.targets);
13
- return checkSwcDependencies(tree, projectConfiguration);
12
+ const updated = updateProjectBuildTargets(tree, projectConfiguration, options.project, options.targets);
13
+ return updated ? checkSwcDependencies(tree, projectConfiguration) : () => { };
14
14
  }
15
15
  function normalizeOptions(schema) {
16
16
  const options = { ...schema };
@@ -20,15 +20,18 @@ function normalizeOptions(schema) {
20
20
  return options;
21
21
  }
22
22
  function updateProjectBuildTargets(tree, projectConfiguration, projectName, projectTargets) {
23
+ let updated = false;
23
24
  for (const target of projectTargets) {
24
- const targetConfiguration = projectConfiguration.targets[target];
25
- if (!targetConfiguration ||
26
- (targetConfiguration.executor !== '@nx/js:tsc' &&
27
- targetConfiguration.executor !== '@nrwl/js:tsc'))
25
+ const targetConfiguration = projectConfiguration.targets?.[target];
26
+ if (!targetConfiguration || targetConfiguration.executor !== '@nx/js:tsc')
28
27
  continue;
29
28
  targetConfiguration.executor = '@nx/js:swc';
29
+ updated = true;
30
30
  }
31
- (0, devkit_1.updateProjectConfiguration)(tree, projectName, projectConfiguration);
31
+ if (updated) {
32
+ (0, devkit_1.updateProjectConfiguration)(tree, projectName, projectConfiguration);
33
+ }
34
+ return updated;
32
35
  }
33
36
  function checkSwcDependencies(tree, projectConfiguration) {
34
37
  const isSwcrcPresent = tree.exists((0, path_1.join)(projectConfiguration.root, '.swcrc'));
@@ -5,11 +5,10 @@ exports.libraryGeneratorInternal = libraryGeneratorInternal;
5
5
  exports.addLint = addLint;
6
6
  const devkit_1 = require("@nx/devkit");
7
7
  const project_name_and_root_utils_1 = require("@nx/devkit/src/generators/project-name-and-root-utils");
8
+ const prompt_1 = require("@nx/devkit/src/generators/prompt");
8
9
  const target_defaults_utils_1 = require("@nx/devkit/src/generators/target-defaults-utils");
9
10
  const log_show_project_command_1 = require("@nx/devkit/src/utils/log-show-project-command");
10
- const enquirer_1 = require("enquirer");
11
11
  const find_matching_projects_1 = require("nx/src/utils/find-matching-projects");
12
- const is_ci_1 = require("nx/src/utils/is-ci");
13
12
  const path_1 = require("path");
14
13
  const package_manager_workspaces_1 = require("../../utils/package-manager-workspaces");
15
14
  const add_swc_config_1 = require("../../utils/swc/add-swc-config");
@@ -21,8 +20,7 @@ const ts_solution_setup_1 = require("../../utils/typescript/ts-solution-setup");
21
20
  const versions_1 = require("../../utils/versions");
22
21
  const init_1 = require("../init/init");
23
22
  const generator_1 = require("../setup-verdaccio/generator");
24
- const package_manager_workspaces_2 = require("./utils/package-manager-workspaces");
25
- const plugin_registrations_1 = require("./utils/plugin-registrations");
23
+ const plugin_1 = require("../../utils/typescript/plugin");
26
24
  const defaultOutputDirectory = 'dist';
27
25
  async function libraryGenerator(tree, schema) {
28
26
  return await libraryGeneratorInternal(tree, {
@@ -134,7 +132,7 @@ async function libraryGeneratorInternal(tree, schema) {
134
132
  }
135
133
  if (options.isUsingTsSolutionConfig &&
136
134
  options.projectPackageManagerWorkspaceState !== 'included') {
137
- tasks.push((0, package_manager_workspaces_2.getProjectPackageManagerWorkspaceStateWarningTask)(options.projectPackageManagerWorkspaceState, tree.root));
135
+ tasks.push((0, package_manager_workspaces_1.getProjectPackageManagerWorkspaceStateWarningTask)(options.projectPackageManagerWorkspaceState, tree.root));
138
136
  }
139
137
  if (options.publishable) {
140
138
  tasks.push(() => {
@@ -150,32 +148,13 @@ async function configureProject(tree, options) {
150
148
  if (options.hasPlugin) {
151
149
  const nxJson = (0, devkit_1.readNxJson)(tree);
152
150
  if (options.bundler === 'none') {
153
- (0, plugin_registrations_1.ensureProjectIsExcludedFromPluginRegistrations)(nxJson, options.projectRoot);
151
+ (0, plugin_1.ensureProjectIsExcludedFromPluginRegistrations)(nxJson, options.projectRoot);
154
152
  }
155
153
  else {
156
- (0, plugin_registrations_1.ensureProjectIsIncludedInPluginRegistrations)(nxJson, options.projectRoot);
154
+ (0, plugin_1.ensureProjectIsIncludedInPluginRegistrations)(nxJson, options.projectRoot);
157
155
  }
158
156
  (0, devkit_1.updateNxJson)(tree, nxJson);
159
157
  }
160
- if (!options.useProjectJson) {
161
- // we create a cleaner project configuration for the package.json file
162
- const projectConfiguration = {
163
- root: options.projectRoot,
164
- };
165
- if (options.name !== options.importPath) {
166
- // if the name is different than the package.json name, we need to set
167
- // the proper name in the configuration
168
- projectConfiguration.name = options.name;
169
- }
170
- if (options.parsedTags?.length) {
171
- projectConfiguration.tags = options.parsedTags;
172
- }
173
- if (options.publishable) {
174
- await addProjectToNxReleaseConfig(tree, options, projectConfiguration);
175
- }
176
- (0, devkit_1.updateProjectConfiguration)(tree, options.name, projectConfiguration);
177
- return;
178
- }
179
158
  const projectConfiguration = {
180
159
  root: options.projectRoot,
181
160
  sourceRoot: (0, devkit_1.joinPathFragments)(options.projectRoot, 'src'),
@@ -183,36 +162,46 @@ async function configureProject(tree, options) {
183
162
  targets: {},
184
163
  tags: options.parsedTags,
185
164
  };
186
- if (options.bundler &&
187
- options.bundler !== 'none' &&
188
- options.config !== 'npm-scripts') {
189
- if (options.bundler !== 'rollup') {
190
- const outputPath = getOutputPath(options);
191
- const executor = getBuildExecutor(options.bundler);
192
- (0, target_defaults_utils_1.addBuildTargetDefaults)(tree, executor);
193
- projectConfiguration.targets.build = {
194
- executor,
195
- outputs: ['{options.outputPath}'],
196
- options: {
197
- outputPath,
198
- main: `${options.projectRoot}/src/index` + (options.js ? '.js' : '.ts'),
199
- tsConfig: `${options.projectRoot}/tsconfig.lib.json`,
200
- assets: [],
201
- },
202
- };
165
+ if (options.config !== 'npm-scripts' &&
166
+ (options.bundler === 'swc' ||
167
+ options.bundler === 'esbuild' ||
168
+ (!options.isUsingTsSolutionConfig && options.bundler === 'tsc'))) {
169
+ const outputPath = getOutputPath(options);
170
+ const executor = getBuildExecutor(options.bundler);
171
+ (0, target_defaults_utils_1.addBuildTargetDefaults)(tree, executor);
172
+ projectConfiguration.targets.build = {
173
+ executor,
174
+ outputs: ['{options.outputPath}'],
175
+ options: {
176
+ outputPath,
177
+ main: `${options.projectRoot}/src/index` + (options.js ? '.js' : '.ts'),
178
+ tsConfig: `${options.projectRoot}/tsconfig.lib.json`,
179
+ },
180
+ };
181
+ if (options.bundler === 'esbuild') {
182
+ projectConfiguration.targets.build.options.format = ['cjs'];
183
+ }
184
+ if (options.bundler === 'swc' && options.skipTypeCheck) {
185
+ projectConfiguration.targets.build.options.skipTypeCheck = true;
186
+ }
187
+ if (options.isUsingTsSolutionConfig) {
203
188
  if (options.bundler === 'esbuild') {
204
- projectConfiguration.targets.build.options.generatePackageJson = true;
205
- projectConfiguration.targets.build.options.format = ['cjs'];
189
+ projectConfiguration.targets.build.options.declarationRootDir = `${options.projectRoot}/src`;
206
190
  }
207
- if (options.bundler === 'swc' && options.skipTypeCheck) {
208
- projectConfiguration.targets.build.options.skipTypeCheck = true;
191
+ }
192
+ else {
193
+ projectConfiguration.targets.build.options.assets = [];
194
+ if (options.bundler === 'esbuild') {
195
+ projectConfiguration.targets.build.options.generatePackageJson = true;
209
196
  }
210
197
  if (!options.minimal) {
211
198
  projectConfiguration.targets.build.options.assets ??= [];
212
199
  projectConfiguration.targets.build.options.assets.push((0, devkit_1.joinPathFragments)(options.projectRoot, '*.md'));
213
200
  }
214
201
  }
215
- if (options.publishable) {
202
+ }
203
+ if (options.publishable) {
204
+ if (!options.isUsingTsSolutionConfig) {
216
205
  const packageRoot = (0, devkit_1.joinPathFragments)(defaultOutputDirectory, '{projectRoot}');
217
206
  projectConfiguration.targets ??= {};
218
207
  projectConfiguration.targets['nx-release-publish'] = {
@@ -230,10 +219,20 @@ async function configureProject(tree, options) {
230
219
  },
231
220
  },
232
221
  };
233
- await addProjectToNxReleaseConfig(tree, options, projectConfiguration);
234
222
  }
223
+ await addProjectToNxReleaseConfig(tree, options, projectConfiguration);
224
+ }
225
+ if (!options.useProjectJson) {
226
+ // we want the package.json as clean as possible, with the bare minimum
227
+ if (!projectConfiguration.tags?.length) {
228
+ delete projectConfiguration.tags;
229
+ }
230
+ // automatically inferred as `library`
231
+ delete projectConfiguration.projectType;
232
+ // empty targets are cleaned up automatically by `updateProjectConfiguration`
233
+ (0, devkit_1.updateProjectConfiguration)(tree, options.name, projectConfiguration);
235
234
  }
236
- if (options.config === 'workspace' || options.config === 'project') {
235
+ else if (options.config === 'workspace' || options.config === 'project') {
237
236
  (0, devkit_1.addProjectConfiguration)(tree, options.name, projectConfiguration);
238
237
  }
239
238
  else {
@@ -470,15 +469,6 @@ function replaceJestConfig(tree, options) {
470
469
  testEnvironment: options.testEnvironment,
471
470
  });
472
471
  }
473
- function isNonInteractive() {
474
- return ((0, is_ci_1.isCI)() || !process.stdout.isTTY || process.env.NX_INTERACTIVE !== 'true');
475
- }
476
- async function promptWhenInteractive(questions, defaultValue) {
477
- if (isNonInteractive()) {
478
- return defaultValue;
479
- }
480
- return await (0, enquirer_1.prompt)(questions);
481
- }
482
472
  async function normalizeOptions(tree, options) {
483
473
  await (0, project_name_and_root_utils_1.ensureProjectName)(tree, options, 'library');
484
474
  const nxJson = (0, devkit_1.readNxJson)(tree);
@@ -488,31 +478,14 @@ async function normalizeOptions(tree, options) {
488
478
  const hasPlugin = (0, ts_solution_setup_1.isUsingTypeScriptPlugin)(tree);
489
479
  const isUsingTsSolutionConfig = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
490
480
  if (isUsingTsSolutionConfig) {
491
- if (options.bundler === 'esbuild' || options.bundler === 'swc') {
492
- throw new Error(`Cannot use the "${options.bundler}" bundler when using the @nx/js/typescript plugin.`);
493
- }
494
- if (options.bundler === undefined && options.compiler === undefined) {
495
- options.bundler = await promptWhenInteractive({
496
- type: 'select',
497
- name: 'bundler',
498
- message: `Which bundler would you like to use to build the library? Choose 'none' to skip build setup.`,
499
- choices: [
500
- { name: 'tsc' },
501
- { name: 'rollup' },
502
- { name: 'vite' },
503
- { name: 'none' },
504
- ],
505
- initial: 0,
506
- }, { bundler: 'tsc' }).then(({ bundler }) => bundler);
507
- }
508
- options.linter ??= await promptWhenInteractive({
481
+ options.linter ??= await (0, prompt_1.promptWhenInteractive)({
509
482
  type: 'select',
510
483
  name: 'linter',
511
484
  message: `Which linter would you like to use?`,
512
485
  choices: [{ name: 'none' }, { name: 'eslint' }],
513
486
  initial: 0,
514
487
  }, { linter: 'none' }).then(({ linter }) => linter);
515
- options.unitTestRunner ??= await promptWhenInteractive({
488
+ options.unitTestRunner ??= await (0, prompt_1.promptWhenInteractive)({
516
489
  type: 'select',
517
490
  name: 'unitTestRunner',
518
491
  message: `Which unit test runner would you like to use?`,
@@ -521,54 +494,14 @@ async function normalizeOptions(tree, options) {
521
494
  }, { unitTestRunner: 'none' }).then(({ unitTestRunner }) => unitTestRunner);
522
495
  }
523
496
  else {
524
- if (options.bundler === undefined && options.compiler === undefined) {
525
- options.bundler = await promptWhenInteractive({
526
- type: 'select',
527
- name: 'bundler',
528
- message: `Which bundler would you like to use to build the library? Choose 'none' to skip build setup.`,
529
- choices: [
530
- { name: 'swc' },
531
- { name: 'tsc' },
532
- { name: 'rollup' },
533
- { name: 'vite' },
534
- { name: 'esbuild' },
535
- { name: 'none' },
536
- ],
537
- initial: 1,
538
- }, { bundler: 'tsc' }).then(({ bundler }) => bundler);
539
- }
540
- else {
541
- /**
542
- * We are deprecating the compiler and the buildable options.
543
- * However, we want to keep the existing behavior for now.
544
- *
545
- * So, if the user has not provided a bundler, we will use the compiler option, if any.
546
- *
547
- * If the user has not provided a bundler and no compiler, but has set buildable to true,
548
- * we will use tsc, since that is the compiler the old generator used to default to, if buildable was true
549
- * and no compiler was provided.
550
- *
551
- * If the user has not provided a bundler and no compiler, and has not set buildable to true, then
552
- * set the bundler to tsc, to preserve old default behaviour (buildable: true by default).
553
- *
554
- * If it's publishable, we need to build the code before publishing it, so again
555
- * we default to `tsc`. In the previous version of this, it would set `buildable` to true
556
- * and that would default to `tsc`.
557
- *
558
- * In the past, the only way to get a non-buildable library was to set buildable to false.
559
- * Now, the only way to get a non-buildble library is to set bundler to none.
560
- * By default, with nothing provided, libraries are buildable with `@nx/js:tsc`.
561
- */
562
- options.bundler ??= options.compiler;
563
- }
564
- options.linter ??= await promptWhenInteractive({
497
+ options.linter ??= await (0, prompt_1.promptWhenInteractive)({
565
498
  type: 'select',
566
499
  name: 'linter',
567
500
  message: `Which linter would you like to use?`,
568
501
  choices: [{ name: 'eslint' }, { name: 'none' }],
569
502
  initial: 0,
570
503
  }, { linter: 'eslint' }).then(({ linter }) => linter);
571
- options.unitTestRunner ??= await promptWhenInteractive({
504
+ options.unitTestRunner ??= await (0, prompt_1.promptWhenInteractive)({
572
505
  type: 'select',
573
506
  name: 'unitTestRunner',
574
507
  message: `Which unit test runner would you like to use?`,
@@ -582,6 +515,28 @@ async function normalizeOptions(tree, options) {
582
515
  options.unitTestRunner = 'jest';
583
516
  }
584
517
  }
518
+ /**
519
+ * We are deprecating the compiler and the buildable options.
520
+ * However, we want to keep the existing behavior for now.
521
+ *
522
+ * So, if the user has not provided a bundler, we will use the compiler option, if any.
523
+ *
524
+ * If the user has not provided a bundler and no compiler, but has set buildable to true,
525
+ * we will use tsc, since that is the compiler the old generator used to default to, if buildable was true
526
+ * and no compiler was provided.
527
+ *
528
+ * If the user has not provided a bundler and no compiler, and has not set buildable to true, then
529
+ * set the bundler to tsc, to preserve old default behaviour (buildable: true by default).
530
+ *
531
+ * If it's publishable, we need to build the code before publishing it, so again
532
+ * we default to `tsc`. In the previous version of this, it would set `buildable` to true
533
+ * and that would default to `tsc`.
534
+ *
535
+ * In the past, the only way to get a non-buildable library was to set buildable to false.
536
+ * Now, the only way to get a non-buildble library is to set bundler to none.
537
+ * By default, with nothing provided, libraries are buildable with `@nx/js:tsc`.
538
+ */
539
+ options.bundler ??= options.compiler ?? 'tsc';
585
540
  // ensure programmatic runs have an expected default
586
541
  if (!options.config) {
587
542
  options.config = 'project';
@@ -685,6 +640,10 @@ function getBuildExecutor(bundler) {
685
640
  }
686
641
  }
687
642
  function getOutputPath(options) {
643
+ if (options.isUsingTsSolutionConfig) {
644
+ // Executors expect paths relative to workspace root, so we prepend the project root
645
+ return (0, devkit_1.joinPathFragments)(options.projectRoot, 'dist');
646
+ }
688
647
  const parts = [defaultOutputDirectory];
689
648
  if (options.projectRoot === '.') {
690
649
  parts.push(options.name);
@@ -824,8 +783,12 @@ function determineEntryFields(options) {
824
783
  case 'swc':
825
784
  return {
826
785
  type: 'commonjs',
827
- main: './src/index.js',
828
- typings: './src/index.d.ts',
786
+ main: options.isUsingTsSolutionConfig
787
+ ? './dist/src/index.js'
788
+ : './src/index.js',
789
+ typings: options.isUsingTsSolutionConfig
790
+ ? './dist/src/index.d.ts'
791
+ : './src/index.d.ts',
829
792
  };
830
793
  case 'rollup':
831
794
  return {
@@ -856,8 +819,12 @@ function determineEntryFields(options) {
856
819
  // For libraries intended for Node, use CJS.
857
820
  return {
858
821
  type: 'commonjs',
859
- main: './index.cjs',
860
- // typings is missing for esbuild currently
822
+ main: options.isUsingTsSolutionConfig
823
+ ? './dist/index.cjs'
824
+ : './index.cjs',
825
+ typings: options.isUsingTsSolutionConfig
826
+ ? './dist/index.d.ts'
827
+ : './index.d.ts',
861
828
  };
862
829
  default: {
863
830
  return {
@@ -24,6 +24,8 @@
24
24
  "description": "The bundler to use. Choosing 'none' means this library is not buildable.",
25
25
  "type": "string",
26
26
  "enum": ["swc", "tsc", "rollup", "vite", "esbuild", "none"],
27
+ "default": "tsc",
28
+ "x-prompt": "Which bundler would you like to use to build the library? Choose 'none' to skip build setup.",
27
29
  "x-priority": "important"
28
30
  },
29
31
  "linter": {
@@ -2,15 +2,24 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.setupBuildGenerator = setupBuildGenerator;
4
4
  const devkit_1 = require("@nx/devkit");
5
+ const target_defaults_utils_1 = require("@nx/devkit/src/generators/target-defaults-utils");
6
+ const posix_1 = require("node:path/posix");
7
+ const devkit_internals_1 = require("nx/src/devkit-internals");
8
+ const plugin_1 = require("../..//utils/typescript/plugin");
9
+ const get_import_path_1 = require("../../utils/get-import-path");
10
+ const update_package_json_1 = require("../../utils/package-json/update-package-json");
5
11
  const add_swc_config_1 = require("../../utils/swc/add-swc-config");
6
12
  const add_swc_dependencies_1 = require("../../utils/swc/add-swc-dependencies");
13
+ const ensure_typescript_1 = require("../../utils/typescript/ensure-typescript");
14
+ const ts_config_1 = require("../../utils/typescript/ts-config");
15
+ const ts_solution_setup_1 = require("../../utils/typescript/ts-solution-setup");
7
16
  const versions_1 = require("../../utils/versions");
8
- const target_defaults_utils_1 = require("@nx/devkit/src/generators/target-defaults-utils");
17
+ let ts;
9
18
  async function setupBuildGenerator(tree, options) {
10
19
  const tasks = [];
11
20
  const project = (0, devkit_1.readProjectConfiguration)(tree, options.project);
12
- const buildTarget = options.buildTarget ?? 'build';
13
- const prevBuildOptions = project.targets?.[buildTarget]?.options;
21
+ options.buildTarget ??= 'build';
22
+ const prevBuildOptions = project.targets?.[options.buildTarget]?.options;
14
23
  project.targets ??= {};
15
24
  let mainFile;
16
25
  if (prevBuildOptions?.main) {
@@ -36,6 +45,7 @@ async function setupBuildGenerator(tree, options) {
36
45
  if (!mainFile || !tree.exists(mainFile)) {
37
46
  throw new Error(`Cannot locate a main file for ${options.project}. Please specify one using --main=<file-path>.`);
38
47
  }
48
+ options.main = mainFile;
39
49
  let tsConfigFile;
40
50
  if (prevBuildOptions?.tsConfig) {
41
51
  tsConfigFile = prevBuildOptions.tsConfig;
@@ -59,16 +69,22 @@ async function setupBuildGenerator(tree, options) {
59
69
  if (!tsConfigFile || !tree.exists(tsConfigFile)) {
60
70
  throw new Error(`Cannot locate a tsConfig file for ${options.project}. Please specify one using --tsConfig=<file-path>.`);
61
71
  }
72
+ options.tsConfig = tsConfigFile;
73
+ const isTsSolutionSetup = (0, ts_solution_setup_1.isUsingTsSolutionSetup)(tree);
74
+ const nxJson = (0, devkit_1.readNxJson)(tree);
75
+ const addPlugin = process.env.NX_ADD_PLUGINS !== 'false' &&
76
+ nxJson.useInferencePlugins !== false;
62
77
  switch (options.bundler) {
63
78
  case 'vite': {
64
79
  const { viteConfigurationGenerator } = (0, devkit_1.ensurePackage)('@nx/vite', versions_1.nxVersion);
65
80
  const task = await viteConfigurationGenerator(tree, {
66
81
  buildTarget: options.buildTarget,
67
82
  project: options.project,
68
- newProject: true,
83
+ newProject: false,
69
84
  uiFramework: 'none',
70
85
  includeVitest: false,
71
86
  includeLib: true,
87
+ addPlugin,
72
88
  skipFormat: true,
73
89
  });
74
90
  tasks.push(task);
@@ -82,6 +98,7 @@ async function setupBuildGenerator(tree, options) {
82
98
  project: options.project,
83
99
  skipFormat: true,
84
100
  skipValidation: true,
101
+ format: ['cjs'],
85
102
  });
86
103
  tasks.push(task);
87
104
  break;
@@ -95,6 +112,7 @@ async function setupBuildGenerator(tree, options) {
95
112
  project: options.project,
96
113
  compiler: 'tsc',
97
114
  format: ['cjs', 'esm'],
115
+ addPlugin,
98
116
  skipFormat: true,
99
117
  skipValidation: true,
100
118
  });
@@ -102,40 +120,133 @@ async function setupBuildGenerator(tree, options) {
102
120
  break;
103
121
  }
104
122
  case 'tsc': {
105
- (0, target_defaults_utils_1.addBuildTargetDefaults)(tree, '@nx/js:tsc');
106
- const outputPath = (0, devkit_1.joinPathFragments)('dist', project.root);
107
- project.targets[buildTarget] = {
108
- executor: `@nx/js:tsc`,
109
- outputs: ['{options.outputPath}'],
110
- options: {
111
- outputPath,
112
- main: mainFile,
113
- tsConfig: tsConfigFile,
114
- assets: [],
115
- },
116
- };
117
- (0, devkit_1.updateProjectConfiguration)(tree, options.project, project);
123
+ if (isTsSolutionSetup) {
124
+ const nxJson = (0, devkit_1.readNxJson)(tree);
125
+ (0, plugin_1.ensureProjectIsIncludedInPluginRegistrations)(nxJson, project.root, options.buildTarget);
126
+ (0, devkit_1.updateNxJson)(tree, nxJson);
127
+ updatePackageJsonForTsc(tree, options, project);
128
+ }
129
+ else {
130
+ (0, target_defaults_utils_1.addBuildTargetDefaults)(tree, '@nx/js:tsc');
131
+ const outputPath = (0, devkit_1.joinPathFragments)('dist', project.root);
132
+ project.targets[options.buildTarget] = {
133
+ executor: `@nx/js:tsc`,
134
+ outputs: ['{options.outputPath}'],
135
+ options: {
136
+ outputPath,
137
+ main: mainFile,
138
+ tsConfig: tsConfigFile,
139
+ assets: [],
140
+ },
141
+ };
142
+ (0, devkit_1.updateProjectConfiguration)(tree, options.project, project);
143
+ }
118
144
  break;
119
145
  }
120
146
  case 'swc': {
121
147
  (0, target_defaults_utils_1.addBuildTargetDefaults)(tree, '@nx/js:swc');
122
- const outputPath = (0, devkit_1.joinPathFragments)('dist', project.root);
123
- project.targets[buildTarget] = {
148
+ const outputPath = isTsSolutionSetup
149
+ ? (0, devkit_1.joinPathFragments)(project.root, 'dist')
150
+ : (0, devkit_1.joinPathFragments)('dist', project.root);
151
+ project.targets[options.buildTarget] = {
124
152
  executor: `@nx/js:swc`,
125
153
  outputs: ['{options.outputPath}'],
126
154
  options: {
127
155
  outputPath,
128
156
  main: mainFile,
129
157
  tsConfig: tsConfigFile,
130
- assets: [],
131
158
  },
132
159
  };
160
+ if (isTsSolutionSetup) {
161
+ project.targets[options.buildTarget].options.stripLeadingPaths = true;
162
+ }
163
+ else {
164
+ project.targets[options.buildTarget].options.assets = [];
165
+ }
133
166
  (0, devkit_1.updateProjectConfiguration)(tree, options.project, project);
134
- (0, add_swc_dependencies_1.addSwcDependencies)(tree);
135
- (0, add_swc_config_1.addSwcConfig)(tree, project.root, 'es6');
167
+ tasks.push((0, add_swc_dependencies_1.addSwcDependencies)(tree));
168
+ (0, add_swc_config_1.addSwcConfig)(tree, project.root, 'commonjs');
169
+ if (isTsSolutionSetup) {
170
+ updatePackageJsonForSwc(tree, options, project);
171
+ }
136
172
  }
137
173
  }
138
174
  await (0, devkit_1.formatFiles)(tree);
139
175
  return (0, devkit_1.runTasksInSerial)(...tasks);
140
176
  }
141
177
  exports.default = setupBuildGenerator;
178
+ function updatePackageJsonForTsc(tree, options, project) {
179
+ if (!ts) {
180
+ ts = (0, ensure_typescript_1.ensureTypescript)();
181
+ }
182
+ const tsconfig = (0, ts_config_1.readTsConfig)(options.tsConfig, {
183
+ ...ts.sys,
184
+ readFile: (p) => tree.read(p, 'utf-8'),
185
+ fileExists: (p) => tree.exists(p),
186
+ });
187
+ let main;
188
+ let rootDir;
189
+ let outputPath;
190
+ if (project.targets?.[options.buildTarget]) {
191
+ const mergedTarget = mergeTargetDefaults(tree, project, options.buildTarget);
192
+ ({ main, rootDir, outputPath } = mergedTarget.options);
193
+ }
194
+ else {
195
+ main = options.main;
196
+ ({ rootDir = project.root, outDir: outputPath } = tsconfig.options);
197
+ const tsOutFile = tsconfig.options.outFile;
198
+ if (tsOutFile) {
199
+ main = (0, posix_1.join)(project.root, (0, posix_1.basename)(tsOutFile));
200
+ outputPath = (0, posix_1.dirname)(tsOutFile);
201
+ }
202
+ if (!outputPath) {
203
+ outputPath = project.root;
204
+ }
205
+ }
206
+ const module = Object.keys(ts.ModuleKind).find((m) => ts.ModuleKind[m] === tsconfig.options.module);
207
+ const format = module.toLowerCase().startsWith('es')
208
+ ? ['esm']
209
+ : ['cjs'];
210
+ updatePackageJson(tree, options.project, project.root, main, outputPath, rootDir, format);
211
+ }
212
+ function updatePackageJsonForSwc(tree, options, project) {
213
+ const mergedTarget = mergeTargetDefaults(tree, project, options.buildTarget);
214
+ const { main, outputPath, swcrc: swcrcPath = (0, posix_1.join)(project.root, '.swcrc'), } = mergedTarget.options;
215
+ const swcrc = (0, devkit_1.readJson)(tree, swcrcPath);
216
+ const format = swcrc.module?.type?.startsWith('es')
217
+ ? ['esm']
218
+ : ['cjs'];
219
+ updatePackageJson(tree, options.project, project.root, main, outputPath,
220
+ // we set the `stripLeadingPaths` option, so the rootDir would match the dirname of the entry point
221
+ (0, posix_1.dirname)(main), format);
222
+ }
223
+ function updatePackageJson(tree, projectName, projectRoot, main, outputPath, rootDir, format) {
224
+ const packageJsonPath = (0, posix_1.join)(projectRoot, 'package.json');
225
+ let packageJson;
226
+ if (tree.exists(packageJsonPath)) {
227
+ packageJson = (0, devkit_1.readJson)(tree, packageJsonPath);
228
+ }
229
+ else {
230
+ packageJson = {
231
+ name: (0, get_import_path_1.getImportPath)(tree, projectName),
232
+ version: '0.0.1',
233
+ };
234
+ }
235
+ packageJson = (0, update_package_json_1.getUpdatedPackageJsonContent)(packageJson, {
236
+ main,
237
+ outputPath,
238
+ projectRoot,
239
+ generateExportsField: true,
240
+ packageJsonPath,
241
+ rootDir,
242
+ format,
243
+ });
244
+ (0, devkit_1.writeJson)(tree, packageJsonPath, packageJson);
245
+ }
246
+ function mergeTargetDefaults(tree, project, buildTarget) {
247
+ const nxJson = (0, devkit_1.readNxJson)(tree);
248
+ const projectTarget = project.targets[buildTarget];
249
+ return (0, devkit_internals_1.mergeTargetConfigurations)(projectTarget, (projectTarget.executor
250
+ ? nxJson.targetDefaults?.[projectTarget.executor]
251
+ : undefined) ?? nxJson.targetDefaults?.[buildTarget]);
252
+ }
@@ -18,14 +18,16 @@ export interface UpdatePackageJsonOption {
18
18
  updateBuildableProjectDepsInPackageJson?: boolean;
19
19
  buildableProjectDepsInPackageJsonType?: 'dependencies' | 'peerDependencies';
20
20
  generateLockfile?: boolean;
21
+ packageJsonPath?: string;
21
22
  }
22
23
  export declare function updatePackageJson(options: UpdatePackageJsonOption, context: ExecutorContext, target: ProjectGraphProjectNode, dependencies: DependentBuildableProjectNode[], fileMap?: ProjectFileMap): void;
23
24
  interface Exports {
24
25
  '.': string;
25
26
  [name: string]: string;
26
27
  }
27
- export declare function getExports(options: Pick<UpdatePackageJsonOption, 'main' | 'rootDir' | 'projectRoot' | 'outputFileName' | 'additionalEntryPoints'> & {
28
+ export declare function getExports(options: Pick<UpdatePackageJsonOption, 'main' | 'rootDir' | 'projectRoot' | 'outputFileName' | 'additionalEntryPoints' | 'outputPath' | 'packageJsonPath'> & {
28
29
  fileExt: string;
29
30
  }): Exports;
30
31
  export declare function getUpdatedPackageJsonContent(packageJson: PackageJson, options: UpdatePackageJsonOption): PackageJson;
32
+ export declare function getOutputDir(options: Pick<UpdatePackageJsonOption, 'main' | 'rootDir' | 'projectRoot' | 'outputFileName' | 'outputPath' | 'packageJsonPath'>): string;
31
33
  export {};
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.updatePackageJson = updatePackageJson;
4
4
  exports.getExports = getExports;
5
5
  exports.getUpdatedPackageJsonContent = getUpdatedPackageJsonContent;
6
+ exports.getOutputDir = getOutputDir;
6
7
  // eslint-disable-next-line @typescript-eslint/no-restricted-imports
7
8
  const lock_file_1 = require("nx/src/plugins/js/lock-file/lock-file");
8
9
  // eslint-disable-next-line @typescript-eslint/no-restricted-imports
@@ -111,14 +112,12 @@ function addMissingDependencies(packageJson, { projectName, targetName, configur
111
112
  });
112
113
  }
113
114
  function getExports(options) {
115
+ const outputDir = getOutputDir(options);
114
116
  const mainFile = options.outputFileName
115
117
  ? options.outputFileName.replace(/\.[tj]s$/, '')
116
118
  : (0, path_1.basename)(options.main).replace(/\.[tj]s$/, '');
117
- const relativeMainFileDir = options.outputFileName
118
- ? './'
119
- : (0, get_main_file_dir_1.getRelativeDirectoryToProjectRoot)(options.main, options.rootDir ?? options.projectRoot);
120
119
  const exports = {
121
- '.': relativeMainFileDir + mainFile + options.fileExt,
120
+ '.': outputDir + mainFile + options.fileExt,
122
121
  };
123
122
  if (options.additionalEntryPoints) {
124
123
  const jsRegex = /\.[jt]sx?$/;
@@ -148,6 +147,21 @@ function getUpdatedPackageJsonContent(packageJson, options) {
148
147
  typeof packageJson.exports === 'string' ? {} : { ...packageJson.exports };
149
148
  packageJson.exports['./package.json'] ??= './package.json';
150
149
  }
150
+ if (!options.skipTypings) {
151
+ const mainFile = (0, path_1.basename)(options.main).replace(/\.[tj]s$/, '');
152
+ const outputDir = getOutputDir(options);
153
+ const typingsFile = `${outputDir}${mainFile}.d.ts`;
154
+ packageJson.types ??= typingsFile;
155
+ if (options.generateExportsField) {
156
+ if (!packageJson.exports['.']) {
157
+ packageJson.exports['.'] = { types: typingsFile };
158
+ }
159
+ else if (typeof packageJson.exports['.'] === 'object' &&
160
+ !packageJson.exports['.'].types) {
161
+ packageJson.exports['.'].types = typingsFile;
162
+ }
163
+ }
164
+ }
151
165
  if (hasEsmFormat) {
152
166
  const esmExports = getExports({
153
167
  ...options,
@@ -160,9 +174,14 @@ function getUpdatedPackageJsonContent(packageJson, options) {
160
174
  }
161
175
  if (options.generateExportsField) {
162
176
  for (const [exportEntry, filePath] of Object.entries(esmExports)) {
163
- packageJson.exports[exportEntry] ??= hasCjsFormat
164
- ? { import: filePath }
165
- : filePath;
177
+ if (!packageJson.exports[exportEntry]) {
178
+ packageJson.exports[exportEntry] ??= hasCjsFormat
179
+ ? { import: filePath }
180
+ : filePath;
181
+ }
182
+ else if (typeof packageJson.exports[exportEntry] === 'object') {
183
+ packageJson.exports[exportEntry].import ??= filePath;
184
+ }
166
185
  }
167
186
  }
168
187
  }
@@ -180,20 +199,27 @@ function getUpdatedPackageJsonContent(packageJson, options) {
180
199
  }
181
200
  if (options.generateExportsField) {
182
201
  for (const [exportEntry, filePath] of Object.entries(cjsExports)) {
183
- if (hasEsmFormat) {
184
- packageJson.exports[exportEntry]['default'] ??= filePath;
202
+ if (!packageJson.exports[exportEntry]) {
203
+ packageJson.exports[exportEntry] ??= hasEsmFormat
204
+ ? { default: filePath }
205
+ : filePath;
185
206
  }
186
- else {
187
- packageJson.exports[exportEntry] ??= filePath;
207
+ else if (typeof packageJson.exports[exportEntry] === 'object') {
208
+ packageJson.exports[exportEntry].default ??= filePath;
188
209
  }
189
210
  }
190
211
  }
191
212
  }
192
- if (!options.skipTypings) {
193
- const mainFile = (0, path_1.basename)(options.main).replace(/\.[tj]s$/, '');
194
- const relativeMainFileDir = (0, get_main_file_dir_1.getRelativeDirectoryToProjectRoot)(options.main, options.projectRoot);
195
- const typingsFile = `${relativeMainFileDir}${mainFile}.d.ts`;
196
- packageJson.types ??= typingsFile;
197
- }
198
213
  return packageJson;
199
214
  }
215
+ function getOutputDir(options) {
216
+ const packageJsonDir = options.packageJsonPath
217
+ ? (0, path_1.dirname)(options.packageJsonPath)
218
+ : options.outputPath;
219
+ const relativeOutputPath = (0, path_1.relative)(packageJsonDir, options.outputPath);
220
+ const relativeMainDir = options.outputFileName
221
+ ? ''
222
+ : (0, path_1.relative)(options.rootDir ?? options.projectRoot, (0, path_1.dirname)(options.main));
223
+ const outputDir = (0, path_1.join)(relativeOutputPath, relativeMainDir);
224
+ return outputDir === '.' ? `./` : `./${outputDir}/`;
225
+ }
@@ -1,4 +1,5 @@
1
- import { type Tree } from '@nx/devkit';
1
+ import { type GeneratorCallback, type Tree } from '@nx/devkit';
2
2
  export type ProjectPackageManagerWorkspaceState = 'included' | 'excluded' | 'no-workspaces';
3
3
  export declare function getProjectPackageManagerWorkspaceState(tree: Tree, projectRoot: string): ProjectPackageManagerWorkspaceState;
4
4
  export declare function isUsingPackageManagerWorkspaces(tree: Tree): boolean;
5
+ export declare function getProjectPackageManagerWorkspaceStateWarningTask(projectPackageManagerWorkspaceState: ProjectPackageManagerWorkspaceState, workspaceRoot: string): GeneratorCallback;
@@ -2,10 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getProjectPackageManagerWorkspaceState = getProjectPackageManagerWorkspaceState;
4
4
  exports.isUsingPackageManagerWorkspaces = isUsingPackageManagerWorkspaces;
5
+ exports.getProjectPackageManagerWorkspaceStateWarningTask = getProjectPackageManagerWorkspaceStateWarningTask;
5
6
  const devkit_1 = require("@nx/devkit");
6
7
  const minimatch_1 = require("minimatch");
7
8
  const posix_1 = require("node:path/posix");
8
9
  const package_json_1 = require("nx/src/plugins/package-json");
10
+ const semver_1 = require("semver");
9
11
  function getProjectPackageManagerWorkspaceState(tree, projectRoot) {
10
12
  if (!isUsingPackageManagerWorkspaces(tree)) {
11
13
  return 'no-workspaces';
@@ -17,3 +19,45 @@ function getProjectPackageManagerWorkspaceState(tree, projectRoot) {
17
19
  function isUsingPackageManagerWorkspaces(tree) {
18
20
  return (0, devkit_1.isWorkspacesEnabled)((0, devkit_1.detectPackageManager)(tree.root), tree.root);
19
21
  }
22
+ function getProjectPackageManagerWorkspaceStateWarningTask(projectPackageManagerWorkspaceState, workspaceRoot) {
23
+ return () => {
24
+ if (projectPackageManagerWorkspaceState !== 'excluded') {
25
+ return;
26
+ }
27
+ const packageManager = (0, devkit_1.detectPackageManager)(workspaceRoot);
28
+ let adviseMessage = 'updating the "workspaces" option in the workspace root "package.json" file with the project root or pattern that includes it';
29
+ let packageManagerWorkspaceSetupDocs;
30
+ if (packageManager === 'pnpm') {
31
+ adviseMessage =
32
+ 'updating the "pnpm-workspace.yaml" file with the project root or pattern that includes it';
33
+ packageManagerWorkspaceSetupDocs =
34
+ 'https://pnpm.io/workspaces and https://pnpm.io/pnpm-workspace_yaml';
35
+ }
36
+ else if (packageManager === 'yarn') {
37
+ const yarnVersion = (0, devkit_1.getPackageManagerVersion)(packageManager, workspaceRoot);
38
+ if ((0, semver_1.lt)(yarnVersion, '2.0.0')) {
39
+ packageManagerWorkspaceSetupDocs =
40
+ 'https://classic.yarnpkg.com/lang/en/docs/workspaces/';
41
+ }
42
+ else {
43
+ packageManagerWorkspaceSetupDocs =
44
+ 'https://yarnpkg.com/features/workspaces';
45
+ }
46
+ }
47
+ else if (packageManager === 'npm') {
48
+ packageManagerWorkspaceSetupDocs =
49
+ 'https://docs.npmjs.com/cli/v10/using-npm/workspaces';
50
+ }
51
+ else if (packageManager === 'bun') {
52
+ packageManagerWorkspaceSetupDocs =
53
+ 'https://bun.sh/docs/install/workspaces';
54
+ }
55
+ devkit_1.output.warn({
56
+ title: `The project is not included in the package manager workspaces configuration`,
57
+ bodyLines: [
58
+ `Please add the project to the package manager workspaces configuration by ${adviseMessage}.`,
59
+ `Read more about the ${packageManager} workspaces feature and how to set it up at ${packageManagerWorkspaceSetupDocs}.`,
60
+ ],
61
+ });
62
+ };
63
+ }
@@ -53,6 +53,7 @@ export interface NormalizedSwcExecutorOptions
53
53
  skipTypeCheck: boolean;
54
54
  swcCliOptions: SwcCliOptions;
55
55
  tmpSwcrcPath: string;
56
+ isTsSolutionSetup: boolean;
56
57
  sourceRoot?: string;
57
58
  // TODO(v21): remove inline feature
58
59
  inline?: boolean;
@@ -1,3 +1,3 @@
1
1
  import type { NxJsonConfiguration } from '@nx/devkit';
2
- export declare function ensureProjectIsIncludedInPluginRegistrations(nxJson: NxJsonConfiguration, projectRoot: string): void;
2
+ export declare function ensureProjectIsIncludedInPluginRegistrations(nxJson: NxJsonConfiguration, projectRoot: string, buildTargetName?: string): void;
3
3
  export declare function ensureProjectIsExcludedFromPluginRegistrations(nxJson: NxJsonConfiguration, projectRoot: string): void;
@@ -3,11 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ensureProjectIsIncludedInPluginRegistrations = ensureProjectIsIncludedInPluginRegistrations;
4
4
  exports.ensureProjectIsExcludedFromPluginRegistrations = ensureProjectIsExcludedFromPluginRegistrations;
5
5
  const devkit_internals_1 = require("nx/src/devkit-internals");
6
- function ensureProjectIsIncludedInPluginRegistrations(nxJson, projectRoot) {
7
- if (!nxJson.plugins?.length ||
8
- !nxJson.plugins.some(isTypeScriptPluginRegistration)) {
9
- return;
10
- }
6
+ function ensureProjectIsIncludedInPluginRegistrations(nxJson, projectRoot, buildTargetName = 'build') {
7
+ nxJson.plugins ??= [];
11
8
  let isIncluded = false;
12
9
  let index = 0;
13
10
  for (const registration of nxJson.plugins) {
@@ -17,7 +14,7 @@ function ensureProjectIsIncludedInPluginRegistrations(nxJson, projectRoot) {
17
14
  }
18
15
  if (typeof registration === 'string') {
19
16
  // if it's a string all projects are included but the are no user-specified options
20
- // and the `build` task is not inferred by default, so we need to exclude it
17
+ // and the build task is not inferred by default, so we need to exclude it
21
18
  nxJson.plugins[index] = {
22
19
  plugin: '@nx/js/typescript',
23
20
  exclude: [`${projectRoot}/*`],
@@ -28,42 +25,54 @@ function ensureProjectIsIncludedInPluginRegistrations(nxJson, projectRoot) {
28
25
  const matchingConfigFiles = (0, devkit_internals_1.findMatchingConfigFiles)([`${projectRoot}/tsconfig.json`], '**/tsconfig.json', registration.include, registration.exclude);
29
26
  if (matchingConfigFiles.length) {
30
27
  // it's included by the plugin registration, check if the user-specified options would result
31
- // in a `build` task being inferred, if not, we need to exclude it
32
- if (registration.options?.typecheck && registration.options?.build) {
33
- // it has the desired options, do nothing
28
+ // in the appropriate build task being inferred, if not, we need to exclude it
29
+ if (registration.options?.typecheck !== false &&
30
+ matchesBuildTarget(registration.options?.build, buildTargetName)) {
31
+ // it has the desired options, do nothing, but continue processing
32
+ // other registrations to exclude as needed
34
33
  isIncluded = true;
35
34
  }
36
35
  else {
37
- // it would not have the `build` task inferred, so we need to exclude it
36
+ // it would not have the typecheck or build task inferred, so we need to exclude it
38
37
  registration.exclude ??= [];
39
38
  registration.exclude.push(`${projectRoot}/*`);
40
39
  }
41
40
  }
42
- else if (registration.options?.typecheck &&
43
- registration.options?.build &&
44
- !registration.exclude?.length) {
45
- // negative pattern are not supported by the `exclude` option so we
46
- // can't update it to not exclude the project, so we only update the
47
- // plugin registration if there's no `exclude` option, in which case
48
- // the plugin registration should have an `include` options that doesn't
49
- // include the project
50
- isIncluded = true;
51
- registration.include ??= [];
52
- registration.include.push(`${projectRoot}/*`);
41
+ else if (!isIncluded &&
42
+ registration.options?.typecheck !== false &&
43
+ matchesBuildTarget(registration.options?.build, buildTargetName)) {
44
+ if (!registration.exclude?.length) {
45
+ // negative pattern are not supported by the `exclude` option so we
46
+ // can't update it to not exclude the project, so we only update the
47
+ // plugin registration if there's no `exclude` option, in which case
48
+ // the plugin registration should have an `include` options that doesn't
49
+ // include the project
50
+ isIncluded = true;
51
+ registration.include ??= [];
52
+ registration.include.push(`${projectRoot}/*`);
53
+ }
54
+ else if (registration.exclude?.includes(`${projectRoot}/*`)) {
55
+ isIncluded = true;
56
+ registration.exclude = registration.exclude.filter((e) => e !== `${projectRoot}/*`);
57
+ if (!registration.exclude.length) {
58
+ // if there's no `exclude` option left, we can remove the exclude option
59
+ delete registration.exclude;
60
+ }
61
+ }
53
62
  }
54
63
  }
55
64
  index++;
56
65
  }
57
66
  if (!isIncluded) {
58
- // the project is not included by any plugin registration with an inferred `build` task,
59
- // so we create a new plugin registration for it
67
+ // the project is not included by any plugin registration with an inferred build task
68
+ // with the given name, so we create a new plugin registration for it
60
69
  nxJson.plugins.push({
61
70
  plugin: '@nx/js/typescript',
62
71
  include: [`${projectRoot}/*`],
63
72
  options: {
64
73
  typecheck: { targetName: 'typecheck' },
65
74
  build: {
66
- targetName: 'build',
75
+ targetName: buildTargetName,
67
76
  configName: 'tsconfig.lib.json',
68
77
  },
69
78
  },
@@ -106,3 +115,13 @@ function isTypeScriptPluginRegistration(plugin) {
106
115
  return ((typeof plugin === 'string' && plugin === '@nx/js/typescript') ||
107
116
  (typeof plugin !== 'string' && plugin.plugin === '@nx/js/typescript'));
108
117
  }
118
+ function matchesBuildTarget(buildOptions, buildTargetName) {
119
+ if (buildOptions === undefined || buildOptions === false) {
120
+ return false;
121
+ }
122
+ if (buildOptions === true && buildTargetName === 'build') {
123
+ return true;
124
+ }
125
+ return (typeof buildOptions === 'object' &&
126
+ buildOptions.targetName === buildTargetName);
127
+ }
@@ -1,6 +1,6 @@
1
1
  import { Tree } from '@nx/devkit';
2
- import * as ts from 'typescript';
3
- export declare function readTsConfig(tsConfigPath: string): ts.ParsedCommandLine;
2
+ import type * as ts from 'typescript';
3
+ export declare function readTsConfig(tsConfigPath: string, sys?: ts.System): ts.ParsedCommandLine;
4
4
  export declare function getRootTsConfigPathInTree(tree: Tree): string | null;
5
5
  export declare function getRelativePathToRootTsConfig(tree: Tree, targetPath: string): string;
6
6
  export declare function getRootTsConfigPath(): string | null;
@@ -12,12 +12,13 @@ const fs_1 = require("fs");
12
12
  const path_1 = require("path");
13
13
  const ensure_typescript_1 = require("./ensure-typescript");
14
14
  let tsModule;
15
- function readTsConfig(tsConfigPath) {
15
+ function readTsConfig(tsConfigPath, sys) {
16
16
  if (!tsModule) {
17
17
  tsModule = require('typescript');
18
18
  }
19
- const readResult = tsModule.readConfigFile(tsConfigPath, tsModule.sys.readFile);
20
- return tsModule.parseJsonConfigFileContent(readResult.config, tsModule.sys, (0, path_1.dirname)(tsConfigPath));
19
+ sys ??= tsModule.sys;
20
+ const readResult = tsModule.readConfigFile(tsConfigPath, sys.readFile);
21
+ return tsModule.parseJsonConfigFileContent(readResult.config, sys, (0, path_1.dirname)(tsConfigPath));
21
22
  }
22
23
  function getRootTsConfigPathInTree(tree) {
23
24
  for (const path of ['tsconfig.base.json', 'tsconfig.json']) {
@@ -1,4 +1,4 @@
1
1
  import { type Tree } from '@nx/devkit';
2
2
  export declare function isUsingTypeScriptPlugin(tree: Tree): boolean;
3
- export declare function isUsingTsSolutionSetup(tree: Tree): boolean;
3
+ export declare function isUsingTsSolutionSetup(tree?: Tree): boolean;
4
4
  export declare function assertNotUsingTsSolutionSetup(tree: Tree, pluginName: string, generatorName: string): void;
@@ -4,6 +4,7 @@ exports.isUsingTypeScriptPlugin = isUsingTypeScriptPlugin;
4
4
  exports.isUsingTsSolutionSetup = isUsingTsSolutionSetup;
5
5
  exports.assertNotUsingTsSolutionSetup = assertNotUsingTsSolutionSetup;
6
6
  const devkit_1 = require("@nx/devkit");
7
+ const tree_1 = require("nx/src/generators/tree");
7
8
  const package_manager_workspaces_1 = require("../package-manager-workspaces");
8
9
  function isUsingTypeScriptPlugin(tree) {
9
10
  const nxJson = (0, devkit_1.readNxJson)(tree);
@@ -12,6 +13,7 @@ function isUsingTypeScriptPlugin(tree) {
12
13
  : p.plugin === '@nx/js/typescript') ?? false);
13
14
  }
14
15
  function isUsingTsSolutionSetup(tree) {
16
+ tree ??= new tree_1.FsTree(devkit_1.workspaceRoot, false);
15
17
  return ((0, package_manager_workspaces_1.isUsingPackageManagerWorkspaces)(tree) &&
16
18
  isWorkspaceSetupWithTsSolution(tree));
17
19
  }
@@ -1,3 +0,0 @@
1
- import { type GeneratorCallback } from '@nx/devkit';
2
- import type { ProjectPackageManagerWorkspaceState } from '../../../utils/package-manager-workspaces';
3
- export declare function getProjectPackageManagerWorkspaceStateWarningTask(projectPackageManagerWorkspaceState: ProjectPackageManagerWorkspaceState, workspaceRoot: string): GeneratorCallback;
@@ -1,52 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getProjectPackageManagerWorkspaceStateWarningTask = getProjectPackageManagerWorkspaceStateWarningTask;
4
- const devkit_1 = require("@nx/devkit");
5
- const semver_1 = require("semver");
6
- function getProjectPackageManagerWorkspaceStateWarningTask(projectPackageManagerWorkspaceState, workspaceRoot) {
7
- return () => {
8
- const packageManager = (0, devkit_1.detectPackageManager)(workspaceRoot);
9
- let packageManagerWorkspaceSetupDocs;
10
- if (packageManager === 'pnpm') {
11
- packageManagerWorkspaceSetupDocs =
12
- 'https://pnpm.io/workspaces and https://pnpm.io/pnpm-workspace_yaml';
13
- }
14
- else if (packageManager === 'yarn') {
15
- const yarnVersion = (0, devkit_1.getPackageManagerVersion)(packageManager, workspaceRoot);
16
- if ((0, semver_1.lt)(yarnVersion, '2.0.0')) {
17
- packageManagerWorkspaceSetupDocs =
18
- 'https://classic.yarnpkg.com/lang/en/docs/workspaces/';
19
- }
20
- else {
21
- packageManagerWorkspaceSetupDocs =
22
- 'https://yarnpkg.com/features/workspaces';
23
- }
24
- }
25
- else if (packageManager === 'npm') {
26
- packageManagerWorkspaceSetupDocs =
27
- 'https://docs.npmjs.com/cli/v10/using-npm/workspaces';
28
- }
29
- else if (packageManager === 'bun') {
30
- packageManagerWorkspaceSetupDocs =
31
- 'https://bun.sh/docs/install/workspaces';
32
- }
33
- if (projectPackageManagerWorkspaceState === 'no-workspaces') {
34
- devkit_1.output.warn({
35
- title: `The package manager workspaces feature is not enabled in the workspace`,
36
- bodyLines: [
37
- 'You must enable the package manager workspaces feature to use the "@nx/js/typescript" plugin.',
38
- `Read more about the ${packageManager} workspaces feature and how to set it up at ${packageManagerWorkspaceSetupDocs}.`,
39
- ],
40
- });
41
- }
42
- else if (projectPackageManagerWorkspaceState === 'excluded') {
43
- devkit_1.output.warn({
44
- title: `The project is not included in the package manager workspaces configuration`,
45
- bodyLines: [
46
- 'Please add it to the workspace configuration to use the "@nx/js/typescript" plugin.',
47
- `Read more about the ${packageManager} workspaces feature and how to set it up at ${packageManagerWorkspaceSetupDocs}.`,
48
- ],
49
- });
50
- }
51
- };
52
- }