diff --git a/packages/jest/src/generators/configuration/lib/create-files.ts b/packages/jest/src/generators/configuration/lib/create-files.ts index e40d7ccab24fb..1bdf076da8e2c 100644 --- a/packages/jest/src/generators/configuration/lib/create-files.ts +++ b/packages/jest/src/generators/configuration/lib/create-files.ts @@ -62,7 +62,8 @@ export function createFiles( ? `${rootOffset}tsconfig.base.json` : './tsconfig.json', outDir: isTsSolutionSetup ? `./out-tsc/jest` : `${rootOffset}dist/out-tsc`, - module: !isTsSolutionSetup ? 'commonjs' : undefined, + module: + !isTsSolutionSetup || transformer === 'ts-jest' ? 'commonjs' : undefined, }); if (options.setupFile === 'none') { diff --git a/packages/js/src/generators/library/library.spec.ts b/packages/js/src/generators/library/library.spec.ts index cf902d66dd5cf..74ed1e170306b 100644 --- a/packages/js/src/generators/library/library.spec.ts +++ b/packages/js/src/generators/library/library.spec.ts @@ -1686,11 +1686,19 @@ describe('lib', () => { "dependencies": { "tslib": "^2.3.0", }, + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts", + }, + "./package.json": "./package.json", + }, "main": "./dist/index.js", + "module": "./dist/index.js", "name": "@proj/my-ts-lib", "private": true, "type": "module", - "typings": "./dist/index.d.ts", + "types": "./dist/index.d.ts", "version": "0.0.1", } `); @@ -1710,11 +1718,19 @@ describe('lib', () => { "dependencies": { "@swc/helpers": "~0.5.11", }, + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts", + }, + "./package.json": "./package.json", + }, "main": "./dist/index.js", + "module": "./dist/index.js", "name": "@proj/my-ts-lib", "private": true, "type": "module", - "typings": "./dist/index.d.ts", + "types": "./dist/index.d.ts", "version": "0.0.1", } `); diff --git a/packages/js/src/generators/library/library.ts b/packages/js/src/generators/library/library.ts index b74fb86fe0cca..f47a1304a8f0e 100644 --- a/packages/js/src/generators/library/library.ts +++ b/packages/js/src/generators/library/library.ts @@ -1,12 +1,12 @@ import { addDependenciesToPackageJson, - installPackagesTask, addProjectConfiguration, ensurePackage, formatFiles, generateFiles, GeneratorCallback, getPackageManagerCommand, + installPackagesTask, joinPathFragments, names, offsetFromRoot, @@ -35,6 +35,7 @@ import { type PackageJson } from 'nx/src/utils/package-json'; import { join } from 'path'; import type { CompilerOptions } from 'typescript'; import { normalizeLinterOption } from '../../utils/generator-prompts'; +import { getUpdatedPackageJsonContent } from '../../utils/package-json/update-package-json'; import { getProjectPackageManagerWorkspaceState, getProjectPackageManagerWorkspaceStateWarningTask, @@ -43,6 +44,7 @@ import { addSwcConfig } from '../../utils/swc/add-swc-config'; import { getSwcDependencies } from '../../utils/swc/add-swc-dependencies'; import { getNeededCompilerOptionOverrides } from '../../utils/typescript/configuration'; import { tsConfigBaseOptions } from '../../utils/typescript/create-ts-config'; +import { ensureTypescript } from '../../utils/typescript/ensure-typescript'; import { ensureProjectIsIncludedInPluginRegistrations } from '../../utils/typescript/plugin'; import { addTsConfigPath, @@ -68,7 +70,6 @@ import type { LibraryGeneratorSchema, NormalizedLibraryGeneratorOptions, } from './schema'; -import { ensureTypescript } from '../../utils/typescript/ensure-typescript'; const defaultOutputDirectory = 'dist'; @@ -118,7 +119,7 @@ export async function libraryGeneratorInternal( await configurationGenerator(tree, { project: options.name, compiler: 'swc', - format: ['cjs', 'esm'], + format: options.isUsingTsSolutionConfig ? ['esm'] : ['cjs', 'esm'], }); } @@ -206,6 +207,12 @@ export async function libraryGeneratorInternal( // add project reference to the runtime tsconfig.lib.json file json.references ??= []; json.references.push({ path: './tsconfig.lib.json' }); + + if (options.isUsingTsSolutionConfig && options.bundler === 'rollup') { + json.compilerOptions.module = 'esnext'; + json.compilerOptions.moduleResolution = 'bundler'; + } + return json; } ); @@ -503,8 +510,7 @@ function createFiles(tree: Tree, options: NormalizedLibraryGeneratorOptions) { let fileNameImport = options.fileName; if ( options.bundler === 'vite' || - (options.isUsingTsSolutionConfig && - ['esbuild', 'swc', 'tsc'].includes(options.bundler)) + (options.isUsingTsSolutionConfig && options.bundler !== 'none') ) { const tsConfig = readTsConfigFromTree( tree, @@ -606,7 +612,8 @@ function createFiles(tree: Tree, options: NormalizedLibraryGeneratorOptions) { // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#files json.files = ['dist', '!**/*.tsbuildinfo']; } - return { + + const updatedPackageJson = { ...json, dependencies: { ...json.dependencies, @@ -614,9 +621,26 @@ function createFiles(tree: Tree, options: NormalizedLibraryGeneratorOptions) { }, ...determineEntryFields(options), }; + + if ( + options.isUsingTsSolutionConfig && + !['none', 'rollup', 'vite'].includes(options.bundler) + ) { + return getUpdatedPackageJsonContent(updatedPackageJson, { + main: join(options.projectRoot, 'src/index.ts'), + outputPath: joinPathFragments(options.projectRoot, 'dist'), + projectRoot: options.projectRoot, + rootDir: join(options.projectRoot, 'src'), + generateExportsField: true, + packageJsonPath, + format: ['esm'], + }); + } + + return updatedPackageJson; }); } else { - const packageJson: PackageJson = { + let packageJson: PackageJson = { name: options.importPath, version: '0.0.1', dependencies: determineDependencies(options), @@ -630,6 +654,22 @@ function createFiles(tree: Tree, options: NormalizedLibraryGeneratorOptions) { // https://docs.npmjs.com/cli/v10/configuring-npm/package-json#files packageJson.files = ['dist', '!**/*.tsbuildinfo']; } + + if ( + options.isUsingTsSolutionConfig && + !['none', 'rollup', 'vite'].includes(options.bundler) + ) { + packageJson = getUpdatedPackageJsonContent(packageJson, { + main: join(options.projectRoot, 'src/index.ts'), + outputPath: joinPathFragments(options.projectRoot, 'dist'), + projectRoot: options.projectRoot, + rootDir: join(options.projectRoot, 'src'), + generateExportsField: true, + packageJsonPath, + format: ['esm'], + }); + } + writeJson(tree, packageJsonPath, packageJson); } @@ -1094,56 +1134,59 @@ function determineEntryFields( ): Record { switch (options.bundler) { case 'tsc': - return { - type: options.isUsingTsSolutionConfig ? 'module' : 'commonjs', - main: options.isUsingTsSolutionConfig - ? './dist/index.js' - : './src/index.js', - typings: options.isUsingTsSolutionConfig - ? './dist/index.d.ts' - : './src/index.d.ts', - }; case 'swc': - return { - type: options.isUsingTsSolutionConfig ? 'module' : 'commonjs', - main: options.isUsingTsSolutionConfig - ? './dist/index.js' - : './src/index.js', - typings: options.isUsingTsSolutionConfig - ? './dist/index.d.ts' - : './src/index.d.ts', - }; + if (options.isUsingTsSolutionConfig) { + return { + type: 'module', + main: './dist/index.js', + module: './dist/index.js', + types: './dist/index.d.ts', + }; + } else { + return { + type: 'commonjs', + main: './src/index.js', + types: './src/index.d.ts', + }; + } case 'rollup': - return { - // Since we're publishing both formats, skip the type field. - // Bundlers or Node will determine the entry point to use. - main: options.isUsingTsSolutionConfig - ? './dist/index.cjs' - : './index.cjs', - module: options.isUsingTsSolutionConfig - ? './dist/index.js' - : './index.js', - }; + if (options.isUsingTsSolutionConfig) { + // the rollup configuration generator already handles this + return {}; + } else { + return { + // Since we're publishing both formats, skip the type field. + // Bundlers or Node will determine the entry point to use. + main: './index.cjs', + module: './index.js', + }; + } case 'vite': - return { - type: 'module', - main: options.isUsingTsSolutionConfig - ? './dist/index.js' - : './index.js', - typings: options.isUsingTsSolutionConfig - ? './dist/index.d.ts' - : './index.d.ts', - }; + if (options.isUsingTsSolutionConfig) { + // the vite configuration generator already handle this + return {}; + } else { + return { + type: 'module', + main: './index.js', + types: './index.d.ts', + }; + } case 'esbuild': - return { - type: options.isUsingTsSolutionConfig ? 'module' : 'commonjs', - main: options.isUsingTsSolutionConfig - ? './dist/index.js' - : './index.cjs', - typings: options.isUsingTsSolutionConfig - ? './dist/index.d.ts' - : './index.d.ts', - }; + if (options.isUsingTsSolutionConfig) { + return { + type: 'module', + main: './dist/index.js', + module: './dist/index.js', + types: './dist/index.d.ts', + }; + } else { + return { + type: 'commonjs', + main: './index.cjs', + types: './index.d.ts', + }; + } default: { return { // Safest option is to not set a type field. diff --git a/packages/js/src/generators/setup-build/generator.ts b/packages/js/src/generators/setup-build/generator.ts index a5c7515003b6c..0e9ce51fcd2c0 100644 --- a/packages/js/src/generators/setup-build/generator.ts +++ b/packages/js/src/generators/setup-build/generator.ts @@ -144,7 +144,7 @@ export async function setupBuildGenerator( tsConfig: tsConfigFile, project: options.project, compiler: 'tsc', - format: ['cjs', 'esm'], + format: isTsSolutionSetup ? ['esm'] : ['cjs', 'esm'], addPlugin, skipFormat: true, skipValidation: true, diff --git a/packages/js/src/utils/typescript/ts-solution-setup.ts b/packages/js/src/utils/typescript/ts-solution-setup.ts index a7a3bfa7ef42c..10521fd0d76d6 100644 --- a/packages/js/src/utils/typescript/ts-solution-setup.ts +++ b/packages/js/src/utils/typescript/ts-solution-setup.ts @@ -8,9 +8,9 @@ import { updateJson, workspaceRoot, } from '@nx/devkit'; +import { basename, dirname, join } from 'node:path/posix'; import { FsTree } from 'nx/src/generators/tree'; import { isUsingPackageManagerWorkspaces } from '../package-manager-workspaces'; -import { basename, dirname, join, relative } from 'node:path/posix'; export function isUsingTypeScriptPlugin(tree: Tree): boolean { const nxJson = readNxJson(tree); @@ -62,7 +62,7 @@ function isWorkspaceSetupWithTsSolution(tree: Tree): boolean { if ( !baseTsconfigJson.compilerOptions || !baseTsconfigJson.compilerOptions.composite || - !baseTsconfigJson.compilerOptions.declaration + baseTsconfigJson.compilerOptions.declaration === false ) { return false; } diff --git a/packages/nest/src/generators/library/library.spec.ts b/packages/nest/src/generators/library/library.spec.ts index 235b4cf2f1074..d32c69314082a 100644 --- a/packages/nest/src/generators/library/library.spec.ts +++ b/packages/nest/src/generators/library/library.spec.ts @@ -433,6 +433,8 @@ describe('lib', () => { expect(readJson(tree, 'mylib/tsconfig.spec.json')).toMatchInlineSnapshot(` { "compilerOptions": { + "module": "commonjs", + "moduleResolution": "node10", "outDir": "./out-tsc/jest", "types": [ "jest", diff --git a/packages/node/src/generators/library/library.spec.ts b/packages/node/src/generators/library/library.spec.ts index 65d884a80f775..59dad1cdf408f 100644 --- a/packages/node/src/generators/library/library.spec.ts +++ b/packages/node/src/generators/library/library.spec.ts @@ -612,6 +612,8 @@ describe('lib', () => { expect(readJson(tree, 'mylib/tsconfig.spec.json')).toMatchInlineSnapshot(` { "compilerOptions": { + "module": "commonjs", + "moduleResolution": "node10", "outDir": "./out-tsc/jest", "types": [ "jest", @@ -648,7 +650,15 @@ describe('lib', () => { "dependencies": { "tslib": "^2.3.0", }, + "exports": { + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.ts", + }, + "./package.json": "./package.json", + }, "main": "./dist/index.js", + "module": "./dist/index.js", "name": "@proj/mylib", "nx": { "name": "mylib", @@ -672,7 +682,7 @@ describe('lib', () => { }, "private": true, "type": "module", - "typings": "./dist/index.d.ts", + "types": "./dist/index.d.ts", "version": "0.0.1", } `);