fix(js): ensure js libraries' build produce esm output in ts solution setup (#29546)

- Update js libraries for bundlers `esbuild`, `swc`, and `tsc` to
produce ESM output when using the TS solution setup.
- Fix `esbuild` and `swc` executors so they generate declaration files
even when skipping type-checking.
- Add `cjs` and `cts` to the `ignoredFiles` pattern for the rollup
config file in the eslint config.
- Ensure running an install after a js library is generated when using
the TS solution setup.

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
This commit is contained in:
Leosvel Pérez Espinosa 2025-01-08 18:21:39 +01:00 committed by GitHub
parent 6b8ba9778e
commit 0334dad23f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 471 additions and 29 deletions

View File

@ -0,0 +1,183 @@
import {
cleanupProject,
getPackageManagerCommand,
getSelectedPackageManager,
newProject,
runCLI,
runCommand,
uniq,
updateFile,
updateJson,
} from '@nx/e2e/utils';
describe('JS - TS solution setup', () => {
beforeAll(() => {
newProject({
packages: ['@nx/js'],
preset: 'ts',
});
});
afterAll(() => {
cleanupProject();
});
it('should generate libraries with different bundlers and link them successfully', () => {
const esbuildParentLib = uniq('esbuild-parent-lib');
const esbuildChildLib = uniq('esbuild-child-lib');
const rollupParentLib = uniq('rollup-parent-lib');
const rollupChildLib = uniq('rollup-child-lib');
const swcParentLib = uniq('swc-parent-lib');
const swcChildLib = uniq('swc-child-lib');
const tscParentLib = uniq('tsc-parent-lib');
const tscChildLib = uniq('tsc-child-lib');
const viteParentLib = uniq('vite-parent-lib');
const viteChildLib = uniq('vite-child-lib');
runCLI(
`generate @nx/js:lib packages/${esbuildParentLib} --bundler=esbuild --linter=eslint --unitTestRunner=jest`
);
runCLI(
`generate @nx/js:lib packages/${esbuildChildLib} --bundler=esbuild --linter=eslint --unitTestRunner=jest`
);
runCLI(
`generate @nx/js:lib packages/${rollupParentLib} --bundler=rollup --linter=eslint --unitTestRunner=jest`
);
runCLI(
`generate @nx/js:lib packages/${rollupChildLib} --bundler=rollup --linter=eslint --unitTestRunner=jest`
);
runCLI(
`generate @nx/js:lib packages/${swcParentLib} --bundler=swc --linter=eslint --unitTestRunner=jest`
);
runCLI(
`generate @nx/js:lib packages/${swcChildLib} --bundler=swc --linter=eslint --unitTestRunner=jest`
);
runCLI(
`generate @nx/js:lib packages/${tscParentLib} --bundler=tsc --linter=eslint --unitTestRunner=jest`
);
runCLI(
`generate @nx/js:lib packages/${tscChildLib} --bundler=tsc --linter=eslint --unitTestRunner=jest`
);
runCLI(
`generate @nx/js:lib packages/${viteParentLib} --bundler=vite --linter=eslint --unitTestRunner=jest`
);
runCLI(
`generate @nx/js:lib packages/${viteChildLib} --bundler=vite --linter=eslint --unitTestRunner=jest`
);
// add deps, each parent lib imports all child libs
const addImports = (parentLib: string) => {
updateFile(
`packages/${parentLib}/src/index.ts`,
(content) => `export * from '@proj/${esbuildChildLib}';
export * from '@proj/${rollupChildLib}';
export * from '@proj/${swcChildLib}';
export * from '@proj/${tscChildLib}';
export * from '@proj/${viteChildLib}';
${content}`
);
};
addImports(esbuildParentLib);
addImports(rollupParentLib);
addImports(swcParentLib);
addImports(tscParentLib);
addImports(viteParentLib);
const pm = getSelectedPackageManager();
if (pm === 'pnpm') {
// for pnpm we need to add the local packages as dependencies to each consumer package.json
const addDeps = (parentLib: string) => {
updateJson(`packages/${parentLib}/package.json`, (json) => {
json.dependencies ??= {};
json.dependencies[`@proj/${esbuildChildLib}`] = 'workspace:*';
json.dependencies[`@proj/${rollupChildLib}`] = 'workspace:*';
json.dependencies[`@proj/${swcChildLib}`] = 'workspace:*';
json.dependencies[`@proj/${tscChildLib}`] = 'workspace:*';
json.dependencies[`@proj/${viteChildLib}`] = 'workspace:*';
return json;
});
};
addDeps(esbuildParentLib);
addDeps(rollupParentLib);
addDeps(swcParentLib);
addDeps(tscParentLib);
addDeps(viteParentLib);
const pmc = getPackageManagerCommand({ packageManager: pm });
runCommand(pmc.install);
}
// sync to ensure the TS project references are updated
runCLI(`sync`);
// check build
expect(runCLI(`build ${esbuildParentLib}`)).toContain(
`Successfully ran target build for project ${esbuildParentLib} and 5 tasks it depends on`
);
expect(runCLI(`build ${rollupParentLib}`)).toContain(
`Successfully ran target build for project ${rollupParentLib} and 5 tasks it depends on`
);
expect(runCLI(`build ${swcParentLib}`)).toContain(
`Successfully ran target build for project ${swcParentLib} and 5 tasks it depends on`
);
expect(runCLI(`build ${tscParentLib}`)).toContain(
`Successfully ran target build for project ${tscParentLib} and 5 tasks it depends on`
);
expect(runCLI(`build ${viteParentLib}`)).toContain(
`Successfully ran target build for project ${viteParentLib} and 5 tasks it depends on`
);
// check typecheck
expect(runCLI(`typecheck ${esbuildParentLib}`)).toContain(
`Successfully ran target typecheck for project ${esbuildParentLib} and 5 tasks it depends on`
);
expect(runCLI(`typecheck ${rollupParentLib}`)).toContain(
`Successfully ran target typecheck for project ${rollupParentLib} and 5 tasks it depends on`
);
expect(runCLI(`typecheck ${swcParentLib}`)).toContain(
`Successfully ran target typecheck for project ${swcParentLib} and 5 tasks it depends on`
);
expect(runCLI(`typecheck ${tscParentLib}`)).toContain(
`Successfully ran target typecheck for project ${tscParentLib} and 5 tasks it depends on`
);
expect(runCLI(`typecheck ${viteParentLib}`)).toContain(
`Successfully ran target typecheck for project ${viteParentLib} and 5 tasks it depends on`
);
// check lint
expect(runCLI(`lint ${esbuildParentLib}`)).toContain(
`Successfully ran target lint for project ${esbuildParentLib}`
);
expect(runCLI(`lint ${rollupParentLib}`)).toContain(
`Successfully ran target lint for project ${rollupParentLib}`
);
expect(runCLI(`lint ${swcParentLib}`)).toContain(
`Successfully ran target lint for project ${swcParentLib}`
);
expect(runCLI(`lint ${tscParentLib}`)).toContain(
`Successfully ran target lint for project ${tscParentLib}`
);
expect(runCLI(`lint ${viteParentLib}`)).toContain(
`Successfully ran target lint for project ${viteParentLib}`
);
// check test
expect(runCLI(`test ${esbuildParentLib}`)).toContain(
`Successfully ran target test for project ${esbuildParentLib}`
);
expect(runCLI(`test ${rollupParentLib}`)).toContain(
`Successfully ran target test for project ${rollupParentLib}`
);
expect(runCLI(`test ${swcParentLib}`)).toContain(
`Successfully ran target test for project ${swcParentLib}`
);
expect(runCLI(`test ${tscParentLib}`)).toContain(
`Successfully ran target test for project ${tscParentLib}`
);
expect(runCLI(`test ${viteParentLib}`)).toContain(
`Successfully ran target test for project ${viteParentLib}`
);
}, 300_000);
});

View File

@ -0,0 +1,98 @@
import { names } from '@nx/devkit';
import {
cleanupProject,
getPackageManagerCommand,
getSelectedPackageManager,
newProject,
runCLI,
runCommand,
uniq,
updateFile,
updateJson,
} from '@nx/e2e/utils';
describe('Vite - TS solution setup', () => {
beforeAll(() => {
newProject({
packages: ['@nx/react', '@nx/js'],
preset: 'ts',
});
});
afterAll(() => {
cleanupProject();
});
it('should generate app and consume libraries with different bundlers', () => {
const reactApp = uniq('react-app');
const esbuildLib = uniq('esbuild-lib');
const rollupLib = uniq('rollup-lib');
const swcLib = uniq('swc-lib');
const tscLib = uniq('tsc-lib');
const viteLib = uniq('vite-lib');
const noBundlerLib = uniq('no-bundler-lib');
runCLI(`generate @nx/react:app apps/${reactApp} --bundler=vite`);
runCLI(`generate @nx/js:lib packages/${esbuildLib} --bundler=esbuild`);
runCLI(`generate @nx/js:lib packages/${rollupLib} --bundler=rollup`);
runCLI(`generate @nx/js:lib packages/${swcLib} --bundler=swc`);
runCLI(`generate @nx/js:lib packages/${tscLib} --bundler=tsc`);
runCLI(`generate @nx/js:lib packages/${viteLib} --bundler=vite`);
runCLI(`generate @nx/js:lib packages/${noBundlerLib} --bundler=none`);
// import all libs from the app
updateFile(
`apps/${reactApp}/src/app/app.tsx`,
(content) => `import { ${
names(esbuildLib).propertyName
} } from '@proj/${esbuildLib}';
import { ${names(rollupLib).propertyName} } from '@proj/${rollupLib}';
import { ${names(swcLib).propertyName} } from '@proj/${swcLib}';
import { ${names(tscLib).propertyName} } from '@proj/${tscLib}';
import { ${names(viteLib).propertyName} } from '@proj/${viteLib}';
import { ${names(noBundlerLib).propertyName} } from '@proj/${noBundlerLib}';
console.log(
${names(esbuildLib).propertyName}(),
${names(rollupLib).propertyName}(),
${names(swcLib).propertyName}(),
${names(tscLib).propertyName}(),
${names(viteLib).propertyName}(),
${names(noBundlerLib).propertyName}()
);
${content}`
);
const pm = getSelectedPackageManager();
if (pm === 'pnpm') {
// for pnpm we need to add the local packages as dependencies to each consumer package.json
updateJson(`apps/${reactApp}/package.json`, (json) => {
json.dependencies ??= {};
json.dependencies[`@proj/${esbuildLib}`] = 'workspace:*';
json.dependencies[`@proj/${rollupLib}`] = 'workspace:*';
json.dependencies[`@proj/${swcLib}`] = 'workspace:*';
json.dependencies[`@proj/${tscLib}`] = 'workspace:*';
json.dependencies[`@proj/${viteLib}`] = 'workspace:*';
json.dependencies[`@proj/${noBundlerLib}`] = 'workspace:*';
return json;
});
const pmc = getPackageManagerCommand({ packageManager: pm });
runCommand(pmc.install);
}
// sync to ensure the TS project references are updated
runCLI(`sync`);
// check build
expect(runCLI(`build ${reactApp}`)).toContain(
`Successfully ran target build for project ${reactApp} and 5 tasks it depends on`
);
// check typecheck
expect(runCLI(`typecheck ${reactApp}`)).toContain(
`Successfully ran target typecheck for project ${reactApp} and 6 tasks it depends on`
);
}, 300_000);
});

View File

@ -134,8 +134,8 @@ export async function* esbuildExecutor(
setup(build: esbuild.PluginBuild) { setup(build: esbuild.PluginBuild) {
build.onEnd(async (result: esbuild.BuildResult) => { build.onEnd(async (result: esbuild.BuildResult) => {
if ( if (
!options.skipTypeCheck && !options.skipTypeCheck ||
!options.isTsSolutionSetup options.isTsSolutionSetup
) { ) {
const { errors } = await runTypeCheck( const { errors } = await runTypeCheck(
options, options,
@ -183,7 +183,7 @@ export async function* esbuildExecutor(
); );
} else { } else {
// Run type-checks first and bail if they don't pass. // Run type-checks first and bail if they don't pass.
if (!options.skipTypeCheck && !options.isTsSolutionSetup) { if (!options.skipTypeCheck || options.isTsSolutionSetup) {
const { errors } = await runTypeCheck(options, context); const { errors } = await runTypeCheck(options, context);
if (errors.length > 0) { if (errors.length > 0) {
yield { success: false }; yield { success: false };
@ -245,6 +245,10 @@ function getTypeCheckOptions(
typeCheckOptions.cacheDir = cacheDir; typeCheckOptions.cacheDir = cacheDir;
} }
if (options.isTsSolutionSetup && options.skipTypeCheck) {
typeCheckOptions.ignoreDiagnostics = true;
}
return typeCheckOptions; return typeCheckOptions;
} }

View File

@ -56,9 +56,7 @@ function normalizeOptions(
const outputPath = join(root, options.outputPath); const outputPath = join(root, options.outputPath);
if (options.skipTypeCheck == null && !isTsSolutionSetup) { options.skipTypeCheck ??= !isTsSolutionSetup;
options.skipTypeCheck = false;
}
if (options.watch == null) { if (options.watch == null) {
options.watch = false; options.watch = false;

View File

@ -1,4 +1,4 @@
import { <%= propertyName %> } from './<%= fileName %>'; import { <%= propertyName %> } from './<%= fileNameImport %>';
describe('<%= propertyName %>', () => { describe('<%= propertyName %>', () => {
it('should work', () => { it('should work', () => {

View File

@ -1439,7 +1439,7 @@ describe('lib', () => {
{ {
ignoredFiles: [ ignoredFiles: [
'{projectRoot}/eslint.config.{js,cjs,mjs}', '{projectRoot}/eslint.config.{js,cjs,mjs}',
'{projectRoot}/rollup.config.{js,ts,mjs,mts}', '{projectRoot}/rollup.config.{js,ts,mjs,mts,cjs,cts}',
], ],
}, },
], ],
@ -1671,5 +1671,130 @@ describe('lib', () => {
} }
`); `);
}); });
it('should set "type: module" in package.json for bundler=tsc', async () => {
await libraryGenerator(tree, {
...defaultOptions,
directory: 'my-ts-lib',
bundler: 'tsc',
unitTestRunner: 'none',
linter: 'none',
});
expect(readJson(tree, 'my-ts-lib/package.json')).toMatchInlineSnapshot(`
{
"dependencies": {
"tslib": "^2.3.0",
},
"main": "./dist/index.js",
"name": "@proj/my-ts-lib",
"private": true,
"type": "module",
"typings": "./dist/index.d.ts",
"version": "0.0.1",
}
`);
});
it('should set "type: module" in package.json for bundler=swc', async () => {
await libraryGenerator(tree, {
...defaultOptions,
directory: 'my-ts-lib',
bundler: 'swc',
unitTestRunner: 'none',
linter: 'none',
});
expect(readJson(tree, 'my-ts-lib/package.json')).toMatchInlineSnapshot(`
{
"dependencies": {
"@swc/helpers": "~0.5.11",
},
"main": "./dist/index.js",
"name": "@proj/my-ts-lib",
"private": true,
"type": "module",
"typings": "./dist/index.d.ts",
"version": "0.0.1",
}
`);
});
it('should set "type: es6" in .swcrc for bundler=swc', async () => {
await libraryGenerator(tree, {
...defaultOptions,
directory: 'my-ts-lib',
bundler: 'swc',
unitTestRunner: 'none',
linter: 'none',
});
expect(tree.read('my-ts-lib/.swcrc', 'utf-8')).toMatchInlineSnapshot(`
"{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "es6"
},
"sourceMaps": true,
"exclude": [
"jest.config.ts",
".*\\\\.spec.tsx?$",
".*\\\\.test.tsx?$",
"./src/jest-setup.ts$",
"./**/jest-setup.ts$",
".*.js$"
]
}
"
`);
});
it('should generate relative import paths with file extension for bundler=tsc', async () => {
await libraryGenerator(tree, {
...defaultOptions,
directory: 'my-ts-lib',
bundler: 'tsc',
unitTestRunner: 'jest',
linter: 'none',
});
expect(tree.read('my-ts-lib/src/index.ts', 'utf-8')).toContain(
`export * from './lib/my-ts-lib.js';`
);
expect(
tree.read('my-ts-lib/src/lib/my-ts-lib.spec.ts', 'utf-8')
).toContain(`import { myTsLib } from './my-ts-lib.js';`);
});
it('should generate relative import paths with file extension for bundler=swc', async () => {
await libraryGenerator(tree, {
...defaultOptions,
directory: 'my-ts-lib',
bundler: 'swc',
unitTestRunner: 'vitest',
linter: 'none',
});
expect(tree.read('my-ts-lib/src/index.ts', 'utf-8')).toContain(
`export * from './lib/my-ts-lib.js';`
);
expect(
tree.read('my-ts-lib/src/lib/my-ts-lib.spec.ts', 'utf-8')
).toContain(`import { myTsLib } from './my-ts-lib.js';`);
});
}); });
}); });

View File

@ -236,7 +236,7 @@ export async function libraryGeneratorInternal(
// Always run install to link packages. // Always run install to link packages.
if (options.isUsingTsSolutionConfig) { if (options.isUsingTsSolutionConfig) {
tasks.push(() => installPackagesTask(tree)); tasks.push(() => installPackagesTask(tree, true));
} }
tasks.push(() => { tasks.push(() => {
@ -285,10 +285,6 @@ async function configureProject(
}, },
}; };
if (options.bundler === 'esbuild') {
projectConfiguration.targets.build.options.format = ['cjs'];
}
if ( if (
options.bundler === 'swc' && options.bundler === 'swc' &&
(options.skipTypeCheck || options.isUsingTsSolutionConfig) (options.skipTypeCheck || options.isUsingTsSolutionConfig)
@ -298,6 +294,7 @@ async function configureProject(
if (options.isUsingTsSolutionConfig) { if (options.isUsingTsSolutionConfig) {
if (options.bundler === 'esbuild') { if (options.bundler === 'esbuild') {
projectConfiguration.targets.build.options.format = ['esm'];
projectConfiguration.targets.build.options.declarationRootDir = `${options.projectRoot}/src`; projectConfiguration.targets.build.options.declarationRootDir = `${options.projectRoot}/src`;
} else if (options.bundler === 'swc') { } else if (options.bundler === 'swc') {
projectConfiguration.targets.build.options.stripLeadingPaths = true; projectConfiguration.targets.build.options.stripLeadingPaths = true;
@ -306,6 +303,7 @@ async function configureProject(
projectConfiguration.targets.build.options.assets = []; projectConfiguration.targets.build.options.assets = [];
if (options.bundler === 'esbuild') { if (options.bundler === 'esbuild') {
projectConfiguration.targets.build.options.format = ['cjs'];
projectConfiguration.targets.build.options.generatePackageJson = true; projectConfiguration.targets.build.options.generatePackageJson = true;
} }
@ -468,7 +466,7 @@ export async function addLint(
} else if (options.bundler === 'rollup') { } else if (options.bundler === 'rollup') {
ruleOptions.ignoredFiles ??= []; ruleOptions.ignoredFiles ??= [];
ruleOptions.ignoredFiles.push( ruleOptions.ignoredFiles.push(
'{projectRoot}/rollup.config.{js,ts,mjs,mts}' '{projectRoot}/rollup.config.{js,ts,mjs,mts,cjs,cts}'
); );
o.rules['@nx/dependency-checks'] = [ruleSeverity, ruleOptions]; o.rules['@nx/dependency-checks'] = [ruleSeverity, ruleOptions];
} else if (options.bundler === 'esbuild') { } else if (options.bundler === 'esbuild') {
@ -503,7 +501,11 @@ function createFiles(tree: Tree, options: NormalizedLibraryGeneratorOptions) {
createProjectTsConfigs(tree, options); createProjectTsConfigs(tree, options);
let fileNameImport = options.fileName; let fileNameImport = options.fileName;
if (options.bundler === 'vite') { if (
options.bundler === 'vite' ||
(options.isUsingTsSolutionConfig &&
['esbuild', 'swc', 'tsc'].includes(options.bundler))
) {
const tsConfig = readTsConfigFromTree( const tsConfig = readTsConfigFromTree(
tree, tree,
join(options.projectRoot, 'tsconfig.lib.json') join(options.projectRoot, 'tsconfig.lib.json')
@ -563,7 +565,9 @@ function createFiles(tree: Tree, options: NormalizedLibraryGeneratorOptions) {
addSwcConfig( addSwcConfig(
tree, tree,
options.projectRoot, options.projectRoot,
options.bundler === 'swc' ? 'commonjs' : 'es6' options.bundler === 'swc' && !options.isUsingTsSolutionConfig
? 'commonjs'
: 'es6'
); );
} else if (options.includeBabelRc) { } else if (options.includeBabelRc) {
addBabelRc(tree, options); addBabelRc(tree, options);
@ -1091,7 +1095,7 @@ function determineEntryFields(
switch (options.bundler) { switch (options.bundler) {
case 'tsc': case 'tsc':
return { return {
type: 'commonjs', type: options.isUsingTsSolutionConfig ? 'module' : 'commonjs',
main: options.isUsingTsSolutionConfig main: options.isUsingTsSolutionConfig
? './dist/index.js' ? './dist/index.js'
: './src/index.js', : './src/index.js',
@ -1101,7 +1105,7 @@ function determineEntryFields(
}; };
case 'swc': case 'swc':
return { return {
type: 'commonjs', type: options.isUsingTsSolutionConfig ? 'module' : 'commonjs',
main: options.isUsingTsSolutionConfig main: options.isUsingTsSolutionConfig
? './dist/index.js' ? './dist/index.js'
: './src/index.js', : './src/index.js',
@ -1131,11 +1135,10 @@ function determineEntryFields(
: './index.d.ts', : './index.d.ts',
}; };
case 'esbuild': case 'esbuild':
// For libraries intended for Node, use CJS.
return { return {
type: 'commonjs', type: options.isUsingTsSolutionConfig ? 'module' : 'commonjs',
main: options.isUsingTsSolutionConfig main: options.isUsingTsSolutionConfig
? './dist/index.cjs' ? './dist/index.js'
: './index.cjs', : './index.cjs',
typings: options.isUsingTsSolutionConfig typings: options.isUsingTsSolutionConfig
? './dist/index.d.ts' ? './dist/index.d.ts'

View File

@ -131,7 +131,7 @@ export async function setupBuildGenerator(
project: options.project, project: options.project,
skipFormat: true, skipFormat: true,
skipValidation: true, skipValidation: true,
format: ['cjs'], format: isTsSolutionSetup ? ['esm'] : ['cjs'],
}); });
tasks.push(task); tasks.push(task);
break; break;
@ -204,7 +204,7 @@ export async function setupBuildGenerator(
updateProjectConfiguration(tree, options.project, project); updateProjectConfiguration(tree, options.project, project);
tasks.push(addSwcDependencies(tree)); tasks.push(addSwcDependencies(tree));
addSwcConfig(tree, project.root, 'commonjs'); addSwcConfig(tree, project.root, isTsSolutionSetup ? 'es6' : 'commonjs');
if (isTsSolutionSetup) { if (isTsSolutionSetup) {
updatePackageJsonForSwc(tree, options, project); updatePackageJsonForSwc(tree, options, project);
} }

View File

@ -485,6 +485,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
"^typecheck", "^typecheck",
], ],
"inputs": [ "inputs": [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.json", "{projectRoot}/tsconfig.json",
"{projectRoot}/src/**/*.ts", "{projectRoot}/src/**/*.ts",
"!{projectRoot}/src/**/foo.ts", "!{projectRoot}/src/**/foo.ts",
@ -552,6 +553,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
"^typecheck", "^typecheck",
], ],
"inputs": [ "inputs": [
"{projectRoot}/package.json",
"{workspaceRoot}/tsconfig.foo.json", "{workspaceRoot}/tsconfig.foo.json",
"{workspaceRoot}/tsconfig.base.json", "{workspaceRoot}/tsconfig.base.json",
"{projectRoot}/tsconfig.json", "{projectRoot}/tsconfig.json",
@ -628,6 +630,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
"^typecheck", "^typecheck",
], ],
"inputs": [ "inputs": [
"{projectRoot}/package.json",
"{workspaceRoot}/tsconfig.foo.json", "{workspaceRoot}/tsconfig.foo.json",
"{workspaceRoot}/tsconfig.base.json", "{workspaceRoot}/tsconfig.base.json",
"{projectRoot}/tsconfig.json", "{projectRoot}/tsconfig.json",
@ -719,6 +722,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
"^typecheck", "^typecheck",
], ],
"inputs": [ "inputs": [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.json", "{projectRoot}/tsconfig.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.spec.json", "{projectRoot}/tsconfig.spec.json",
@ -771,6 +775,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
"^typecheck", "^typecheck",
], ],
"inputs": [ "inputs": [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.json", "{projectRoot}/tsconfig.json",
"{projectRoot}/lib/**/*.ts", "{projectRoot}/lib/**/*.ts",
"^production", "^production",
@ -833,6 +838,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
expect(result.projects['libs/my-lib'].targets.typecheck.inputs) expect(result.projects['libs/my-lib'].targets.typecheck.inputs)
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
[ [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.json", "{projectRoot}/tsconfig.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.spec.json", "{projectRoot}/tsconfig.spec.json",
@ -869,6 +875,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
expect(result.projects['libs/my-lib'].targets.typecheck.inputs) expect(result.projects['libs/my-lib'].targets.typecheck.inputs)
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
[ [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.json", "{projectRoot}/tsconfig.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.spec.json", "{projectRoot}/tsconfig.spec.json",
@ -905,6 +912,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
expect(result.projects['libs/my-lib'].targets.typecheck.inputs) expect(result.projects['libs/my-lib'].targets.typecheck.inputs)
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
[ [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.json", "{projectRoot}/tsconfig.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.spec.json", "{projectRoot}/tsconfig.spec.json",
@ -941,6 +949,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
expect(result.projects['libs/my-lib'].targets.typecheck.inputs) expect(result.projects['libs/my-lib'].targets.typecheck.inputs)
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
[ [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.json", "{projectRoot}/tsconfig.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.spec.json", "{projectRoot}/tsconfig.spec.json",
@ -980,6 +989,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
expect(result.projects['libs/my-lib'].targets.typecheck.inputs) expect(result.projects['libs/my-lib'].targets.typecheck.inputs)
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
[ [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.json", "{projectRoot}/tsconfig.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.spec.json", "{projectRoot}/tsconfig.spec.json",
@ -1432,6 +1442,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
"^typecheck", "^typecheck",
], ],
"inputs": [ "inputs": [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.json", "{projectRoot}/tsconfig.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.spec.json", "{projectRoot}/tsconfig.spec.json",
@ -2208,6 +2219,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
"^build", "^build",
], ],
"inputs": [ "inputs": [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/src/**/*.ts", "{projectRoot}/src/**/*.ts",
"!{projectRoot}/src/**/*.spec.ts", "!{projectRoot}/src/**/*.spec.ts",
@ -2283,6 +2295,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
"^build", "^build",
], ],
"inputs": [ "inputs": [
"{projectRoot}/package.json",
"{workspaceRoot}/tsconfig.foo.json", "{workspaceRoot}/tsconfig.foo.json",
"{workspaceRoot}/tsconfig.base.json", "{workspaceRoot}/tsconfig.base.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
@ -2367,6 +2380,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
"^build", "^build",
], ],
"inputs": [ "inputs": [
"{projectRoot}/package.json",
"{workspaceRoot}/tsconfig.foo.json", "{workspaceRoot}/tsconfig.foo.json",
"{workspaceRoot}/tsconfig.base.json", "{workspaceRoot}/tsconfig.base.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
@ -2448,6 +2462,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
"^build", "^build",
], ],
"inputs": [ "inputs": [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.other.json", "{projectRoot}/tsconfig.other.json",
"{projectRoot}/src/**/*.ts", "{projectRoot}/src/**/*.ts",
@ -2514,6 +2529,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
expect(result.projects['libs/my-lib'].targets.build.inputs) expect(result.projects['libs/my-lib'].targets.build.inputs)
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
[ [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.other.json", "{projectRoot}/tsconfig.other.json",
"{projectRoot}/src/**/*.ts", "{projectRoot}/src/**/*.ts",
@ -2549,6 +2565,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
expect(result.projects['libs/my-lib'].targets.build.inputs) expect(result.projects['libs/my-lib'].targets.build.inputs)
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
[ [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.other.json", "{projectRoot}/tsconfig.other.json",
"{projectRoot}/**/*.ts", "{projectRoot}/**/*.ts",
@ -2584,6 +2601,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
expect(result.projects['libs/my-lib'].targets.build.inputs) expect(result.projects['libs/my-lib'].targets.build.inputs)
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
[ [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.other.json", "{projectRoot}/tsconfig.other.json",
"{projectRoot}/src/**/*.ts", "{projectRoot}/src/**/*.ts",
@ -2619,6 +2637,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
expect(result.projects['libs/my-lib'].targets.build.inputs) expect(result.projects['libs/my-lib'].targets.build.inputs)
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
[ [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.other.json", "{projectRoot}/tsconfig.other.json",
"{projectRoot}/src/**/*.ts", "{projectRoot}/src/**/*.ts",
@ -2657,6 +2676,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
expect(result.projects['libs/my-lib'].targets.build.inputs) expect(result.projects['libs/my-lib'].targets.build.inputs)
.toMatchInlineSnapshot(` .toMatchInlineSnapshot(`
[ [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.other.json", "{projectRoot}/tsconfig.other.json",
"{projectRoot}/src/**/*.ts", "{projectRoot}/src/**/*.ts",
@ -3012,6 +3032,7 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
"^build", "^build",
], ],
"inputs": [ "inputs": [
"{projectRoot}/package.json",
"{projectRoot}/tsconfig.lib.json", "{projectRoot}/tsconfig.lib.json",
"{projectRoot}/tsconfig.other.json", "{projectRoot}/tsconfig.other.json",
"{projectRoot}/other/**/*.ts", "{projectRoot}/other/**/*.ts",

View File

@ -436,6 +436,9 @@ function getInputs(
const inputs: TargetConfiguration['inputs'] = []; const inputs: TargetConfiguration['inputs'] = [];
if (includePaths.size) { if (includePaths.size) {
if (existsSync(join(workspaceRoot, projectRoot, 'package.json'))) {
inputs.push('{projectRoot}/package.json');
}
inputs.push( inputs.push(
...Array.from(configFiles).map((p: string) => ...Array.from(configFiles).map((p: string) =>
pathToInputOrOutput(p, workspaceRoot, projectRoot) pathToInputOrOutput(p, workspaceRoot, projectRoot)

View File

@ -68,6 +68,10 @@ function getTypeCheckOptions(normalizedOptions: NormalizedSwcExecutorOptions) {
typeCheckOptions.cacheDir = cacheDir; typeCheckOptions.cacheDir = cacheDir;
} }
if (normalizedOptions.isTsSolutionSetup && normalizedOptions.skipTypeCheck) {
typeCheckOptions.ignoreDiagnostics = true;
}
return typeCheckOptions; return typeCheckOptions;
} }
@ -90,7 +94,7 @@ export async function compileSwc(
logger.log(swcCmdLog.replace(/\n/, '')); logger.log(swcCmdLog.replace(/\n/, ''));
const isCompileSuccess = swcCmdLog.includes('Successfully compiled'); const isCompileSuccess = swcCmdLog.includes('Successfully compiled');
if (normalizedOptions.skipTypeCheck || normalizedOptions.isTsSolutionSetup) { if (normalizedOptions.skipTypeCheck && !normalizedOptions.isTsSolutionSetup) {
await postCompilationCallback(); await postCompilationCallback();
return { success: isCompileSuccess }; return { success: isCompileSuccess };
} }

View File

@ -22,6 +22,7 @@ interface BaseTypeCheckOptions {
incremental?: boolean; incremental?: boolean;
rootDir?: string; rootDir?: string;
projectRoot?: string; projectRoot?: string;
ignoreDiagnostics?: boolean;
} }
type Mode = NoEmitMode | EmitDeclarationOnlyMode; type Mode = NoEmitMode | EmitDeclarationOnlyMode;
@ -66,7 +67,9 @@ export async function runTypeCheckWatch(
const watchProgram = ts.createWatchProgram(host); const watchProgram = ts.createWatchProgram(host);
const program = watchProgram.getProgram().getProgram(); const program = watchProgram.getProgram().getProgram();
const diagnostics = ts.getPreEmitDiagnostics(program); const diagnostics = options.ignoreDiagnostics
? []
: ts.getPreEmitDiagnostics(program);
return { return {
close: watchProgram.close.bind(watchProgram), close: watchProgram.close.bind(watchProgram),
@ -103,9 +106,9 @@ export async function runTypeCheck(
const result = program.emit(); const result = program.emit();
const allDiagnostics = ts const allDiagnostics = options.ignoreDiagnostics
.getPreEmitDiagnostics(program as Program) ? []
.concat(result.diagnostics); : ts.getPreEmitDiagnostics(program as Program).concat(result.diagnostics);
return getTypeCheckResult( return getTypeCheckResult(
ts, ts,

View File

@ -671,7 +671,7 @@ describe('lib', () => {
}, },
}, },
"private": true, "private": true,
"type": "commonjs", "type": "module",
"typings": "./dist/index.d.ts", "typings": "./dist/index.d.ts",
"version": "0.0.1", "version": "0.0.1",
} }