-
-
Notifications
You must be signed in to change notification settings - Fork 594
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(typescript): better error when tslib is not installed (#793)
* feat(typescript): better error when tslib is not installed * test: trim snapshot file path
- Loading branch information
1 parent
a927ed8
commit 031b566
Showing
15 changed files
with
473 additions
and
262 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,34 @@ | ||
import { PluginContext } from 'rollup'; | ||
import { PluginContext, RollupOptions } from 'rollup'; | ||
import { ModuleKind } from 'typescript'; | ||
|
||
import { TypeScriptConfig } from './options/tsconfig'; | ||
// import { resolveIdAsync } from './tslib'; | ||
|
||
const moduleError = ` | ||
Rollup requires that TypeScript produces ES Modules. Unfortunately your configuration specifies a | ||
interface PreflightOptions { | ||
config: TypeScriptConfig; | ||
context: PluginContext; | ||
rollupOptions: RollupOptions; | ||
tslib: any; | ||
} | ||
|
||
const pluginName = '@rollup/plugin-typescript'; | ||
const moduleErrorMessage = ` | ||
${pluginName}: Rollup requires that TypeScript produces ES Modules. Unfortunately your configuration specifies a | ||
"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 tsLibErrorMessage = `${pluginName}: Could not find module 'tslib', which is required by this plugin. Is it installed?`; | ||
|
||
let undef; | ||
const validModules = [ModuleKind.ES2015, ModuleKind.ES2020, ModuleKind.ESNext, undef]; | ||
|
||
// eslint-disable-next-line import/prefer-default-export | ||
export const preflight = (config: TypeScriptConfig, context: PluginContext) => { | ||
export const preflight = ({ config, context, rollupOptions, tslib }: PreflightOptions) => { | ||
if (!validModules.includes(config.options.module)) { | ||
context.warn(`@rollup/plugin-typescript: ${moduleError}`); | ||
context.warn(moduleErrorMessage); | ||
} | ||
|
||
if (!rollupOptions.preserveModules && tslib === null) { | ||
context.error(tsLibErrorMessage); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,27 @@ | ||
import resolveId, { AsyncOpts } from 'resolve'; | ||
import resolve, { SyncOpts } from 'resolve'; | ||
|
||
const resolveIdAsync = (file: string, opts: AsyncOpts) => | ||
new Promise<string>((fulfil, reject) => | ||
resolveId(file, opts, (err, contents) => (err || typeof contents === 'undefined' ? reject(err) : fulfil(contents))) | ||
); | ||
// const resolveIdAsync = (file: string, opts: AsyncOpts) => | ||
// new Promise<string>((fulfil, reject) => | ||
// resolveId(file, opts, (err, contents) => | ||
// err || typeof contents === 'undefined' ? reject(err) : fulfil(contents) | ||
// ) | ||
// ); | ||
|
||
const resolveId = (file: string, opts: SyncOpts) => resolve.sync(file, opts); | ||
|
||
/** | ||
* Returns code asynchronously for the tslib helper library. | ||
*/ | ||
export default function getTsLibPath() { | ||
return resolveIdAsync('tslib/tslib.es6.js', { basedir: __dirname }); | ||
} | ||
export const getTsLibPath = () => { | ||
// Note: This isn't preferable, but we've no other way to test this bit. Removing the tslib devDep | ||
// during the test run doesn't work due to the nature of the pnpm flat node_modules, and | ||
// other workspace dependencies that depenend upon tslib. | ||
try { | ||
// eslint-disable-next-line no-underscore-dangle | ||
return resolveId(process.env.__TSLIB_TEST_PATH__ || 'tslib/tslib.es6.js', { | ||
basedir: __dirname | ||
}); | ||
} catch (_) { | ||
return null; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Snapshot report for `test/tslib.ts` | ||
|
||
The actual snapshot is saved in `tslib.ts.snap`. | ||
|
||
Generated by [AVA](https://avajs.dev). | ||
|
||
## fails on bad tslib path | ||
|
||
> Snapshot 1 | ||
Error { | ||
code: 'ENOENT', | ||
errno: -2, | ||
path: 'fixtures/joker/tslib.js', | ||
syscall: 'open', | ||
watchFiles: [ | ||
'packages/typescript/test/fixtures/overriding-tslib/main.ts', | ||
'fixtures/joker/tslib.js', | ||
], | ||
message: 'Could not load fixtures/joker/tslib.js (imported by fixtures/overriding-tslib/main.ts): ENOENT: no such file or directory, open \'fixtures/joker/tslib.js\'', | ||
} | ||
|
||
## fails without tslib installed | ||
|
||
> Snapshot 1 | ||
Error { | ||
code: 'PLUGIN_ERROR', | ||
hook: 'buildStart', | ||
plugin: 'typescript', | ||
message: '@rollup/plugin-typescript: Could not find module \'tslib\', which is required by this plugin. Is it installed?', | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"extends": "../tsconfig.json", | ||
"include": ["."] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { platform } from 'os'; | ||
|
||
import test from 'ava'; | ||
import { rollup, RollupError } from 'rollup'; | ||
|
||
import typescript from '..'; | ||
|
||
import { evaluateBundle, getCode, onwarn } from '../../../util/test'; | ||
|
||
test.beforeEach(() => process.chdir(__dirname)); | ||
|
||
test.serial('supports overriding tslib with a custom path', async (t) => { | ||
const bundle = await rollup({ | ||
input: 'fixtures/overriding-tslib/main.ts', | ||
plugins: [ | ||
typescript({ | ||
tsconfig: 'fixtures/overriding-tslib/tsconfig.json', | ||
tslib: 'fixtures/overriding-tslib/tslib.js' | ||
}) | ||
], | ||
onwarn | ||
}); | ||
const code = await evaluateBundle(bundle); | ||
|
||
t.is((code as any).myParent.baseMethod(), 'base method'); | ||
}); | ||
|
||
test.serial('supports overriding tslib with a custom path in a promise', async (t) => { | ||
const options = { | ||
tsconfig: 'fixtures/overriding-tslib/tsconfig.json', | ||
tslib: Promise.resolve('fixtures/overriding-tslib/tslib.js') | ||
}; | ||
const bundle = await rollup({ | ||
input: 'fixtures/overriding-tslib/main.ts', | ||
plugins: [typescript(options)], | ||
onwarn | ||
}); | ||
const code = await evaluateBundle(bundle); | ||
|
||
t.is((code as any).myParent.baseMethod(), 'base method'); | ||
}); | ||
|
||
test.serial('fails on bad tslib path', async (t) => { | ||
const fail = () => | ||
rollup({ | ||
input: 'fixtures/overriding-tslib/main.ts', | ||
plugins: [ | ||
typescript({ | ||
tsconfig: 'fixtures/overriding-tslib/tsconfig.json', | ||
tslib: 'fixtures/joker/tslib.js' | ||
}) | ||
], | ||
onwarn | ||
}); | ||
|
||
const error = (await t.throwsAsync(fail)) as RollupError; | ||
|
||
// Note: I'm done fucking around with Windows paths | ||
if (platform() === 'win32') { | ||
t.pass(); | ||
return; | ||
} | ||
|
||
if (error.watchFiles) { | ||
let [filePath] = error.watchFiles; | ||
filePath = filePath.substring(filePath.indexOf('packages')); | ||
error.watchFiles[0] = filePath; | ||
} | ||
|
||
t.snapshot(error); | ||
}); | ||
|
||
test.serial('fails without tslib installed', async (t) => { | ||
const fail = () => | ||
rollup({ | ||
input: 'fixtures/overriding-tslib/main.ts', | ||
plugins: [typescript({ tsconfig: 'fixtures/overriding-tslib/tsconfig.json' })], | ||
onwarn | ||
}); | ||
|
||
// eslint-disable-next-line no-underscore-dangle | ||
process.env.__TSLIB_TEST_PATH__ = 'badtslib/tslib.es6.js'; | ||
|
||
const error = await t.throwsAsync(fail); | ||
|
||
// eslint-disable-next-line no-underscore-dangle, no-undefined | ||
process.env.__TSLIB_TEST_PATH__ = ''; | ||
|
||
t.snapshot(error); | ||
}); | ||
|
||
test.serial('creates _tslib.js file when preserveModules is used', async (t) => { | ||
const bundle = await rollup({ | ||
input: 'fixtures/preserve-modules/main.ts', | ||
plugins: [typescript({ tsconfig: 'fixtures/preserve-modules/tsconfig.json' })], | ||
preserveModules: true, | ||
onwarn | ||
}); | ||
|
||
const files = await getCode(bundle, { format: 'es' }, true); | ||
t.true(files[0].fileName.includes('main.js'), files[0].fileName); | ||
t.true(files[1].fileName.includes('tslib.es6.js'), files[1].fileName); | ||
}); |
Oops, something went wrong.