diff --git a/packages/typescript/src/preflight.ts b/packages/typescript/src/preflight.ts index 3b7e70e2d..39cc1731c 100644 --- a/packages/typescript/src/preflight.ts +++ b/packages/typescript/src/preflight.ts @@ -17,6 +17,8 @@ ${pluginName}: Rollup requires that TypeScript produces ES Modules. Unfortunatel "module" other than "esnext". Unless you know what you're doing, please change "module" to "esnext" in the target tsconfig.json file or plugin options.`.replace(/\n/g, ''); +const rootDirErrorMessage = `${pluginName}: The "rootDir" or "rootDirs" option is required when the "tsconfig" option is not specified and "declaration" is "true".`; + const tsLibErrorMessage = `${pluginName}: Could not find module 'tslib', which is required by this plugin. Is it installed?`; let undef; @@ -28,6 +30,11 @@ export const preflight = ({ config, context, rollupOptions, tslib }: PreflightOp context.warn(moduleErrorMessage); } + const { options } = config; + if (options.declaration && !options.configFilePath && !options.rootDir && !options.rootDirs) { + context.error(rootDirErrorMessage); + } + if (!rollupOptions.preserveModules && tslib === null) { context.error(tsLibErrorMessage); } diff --git a/packages/typescript/test/snapshots/tsconfig.ts.md b/packages/typescript/test/snapshots/tsconfig.ts.md new file mode 100644 index 000000000..cd5733ae1 --- /dev/null +++ b/packages/typescript/test/snapshots/tsconfig.ts.md @@ -0,0 +1,25 @@ +# Snapshot report for `test/tsconfig.ts` + +The actual snapshot is saved in `tsconfig.ts.snap`. + +Generated by [AVA](https://avajs.dev). + +## inline config without tsconfig + rootDir + +> Snapshot 1 + + [ + 'main.js', + 'types/main.d.ts', + ] + +## inline config without tsconfig without rootDir fails + +> Snapshot 1 + + Error { + code: 'PLUGIN_ERROR', + hook: 'buildStart', + plugin: 'typescript', + message: '@rollup/plugin-typescript: The "rootDir" or "rootDirs" option is required when the "tsconfig" option is not specified and "declaration" is "true".', + } diff --git a/packages/typescript/test/snapshots/tsconfig.ts.snap b/packages/typescript/test/snapshots/tsconfig.ts.snap new file mode 100644 index 000000000..ecf6b0f74 Binary files /dev/null and b/packages/typescript/test/snapshots/tsconfig.ts.snap differ diff --git a/packages/typescript/test/tsconfig.ts b/packages/typescript/test/tsconfig.ts new file mode 100644 index 000000000..567e9d9b6 --- /dev/null +++ b/packages/typescript/test/tsconfig.ts @@ -0,0 +1,50 @@ +import test from 'ava'; +import { rollup } from 'rollup'; + +import typescript from '..'; + +import { getCode, onwarn } from '../../../util/test'; + +test.beforeEach(() => process.chdir(__dirname)); + +test.serial('inline config without tsconfig + rootDir', async (t) => { + const bundle = await rollup({ + input: 'fixtures/basic/main.ts', + plugins: [ + typescript({ + declaration: true, + declarationDir: 'fixtures/basic/dist/types', + exclude: 'fixtures/basic/dist/types', + include: 'fixtures/basic/*.ts', + tsconfig: false, + rootDir: 'fixtures/basic' + }) + ], + onwarn + }); + const files = await getCode(bundle, { format: 'esm', dir: 'fixtures/basic/dist' }, true); + const [, { source }] = files; + + t.snapshot(files.map(({ fileName }) => fileName)); + t.true((source as string)?.includes('declare const answer = 42;')); +}); + +test.serial('inline config without tsconfig without rootDir fails', async (t) => { + const fail = () => + rollup({ + input: 'fixtures/basic/main.ts', + plugins: [ + typescript({ + declaration: true, + declarationDir: 'fixtures/basic/dist/types', + exclude: 'fixtures/basic/dist/types', + include: 'fixtures/basic/*.ts', + tsconfig: false + }) + ], + onwarn + }); + + const error = await t.throwsAsync(fail); + t.snapshot(error); +});