From 7769fb927f857d720882c1632597e908e0ef482f Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Tue, 7 Jan 2020 23:33:18 -0800 Subject: [PATCH] Adds type definitions for RollupWatcher events. (#3302) * Adds type definitions for RollupWatcher events. The type information is extracted from https://github.com/rollup/rollup/blob/master/src/watch/index.ts, someone should double check that I got it all right. I'm new to rollup and have never actually used any of this stuff, but when I tried to I ran into the problem of there being no useful type information which caused me to have to read source code. Rather than having everyone suffer like I did, I decided to create a PR to resolve the issue. * Fixes RollupWatcher.on type signature. I didn't realize that `on` was chainable, this should resolve the issue. * Utilize new watcher type * Remove FATAL references Co-authored-by: Micah Zoltu Co-authored-by: Andrew Powell --- cli/run/watch.ts | 34 ++++------------- docs/02-javascript-api.md | 5 +-- src/rollup/index.ts | 3 +- src/rollup/types.d.ts | 38 ++++++++++++++++++- src/utils/PluginContext.ts | 2 +- src/utils/deconflictChunk.ts | 7 ++-- src/watch/index.ts | 6 +-- .../virtual-modules-conflict/_config.js | 15 +++++--- .../virtual-modules/_config.js | 15 +++++--- test/hooks/index.js | 7 +++- test/watch/index.js | 3 -- 11 files changed, 80 insertions(+), 55 deletions(-) diff --git a/cli/run/watch.ts b/cli/run/watch.ts index 74297a9f8c6..e437c71abc9 100644 --- a/cli/run/watch.ts +++ b/cli/run/watch.ts @@ -5,13 +5,9 @@ import onExit from 'signal-exit'; import tc from 'turbocolor'; import * as rollup from '../../src/node-entry'; import { - InputOption, - RollupBuild, - RollupError, RollupWatcher, RollupWatchOptions, - WarningHandler, - WatcherOptions + WarningHandler } from '../../src/rollup/types'; import mergeOptions, { GenericConfigObject } from '../../src/utils/mergeOptions'; import relativeId from '../../src/utils/relativeId'; @@ -21,15 +17,6 @@ import loadConfigFile from './loadConfigFile'; import { getResetScreen } from './resetScreen'; import { printTimings } from './timings'; -interface WatchEvent { - code?: string; - duration?: number; - error?: RollupError | Error; - input?: InputOption; - output?: string[]; - result?: RollupBuild; -} - export default function watch( configFile: string, configs: GenericConfigObject[], @@ -40,7 +27,7 @@ export default function watch( const warnings = batchWarnings(); const initialConfigs = processConfigs(configs); const clearScreen = initialConfigs.every( - config => (config.watch as WatcherOptions).clearScreen !== false + config => config.watch!.clearScreen !== false ); const resetScreen = getResetScreen(isTTY && clearScreen); @@ -75,16 +62,11 @@ export default function watch( function start(configs: RollupWatchOptions[]) { watcher = rollup.watch(configs as any); - watcher.on('event', (event: WatchEvent) => { + watcher.on('event', event => { switch (event.code) { - case 'FATAL': - handleError(event.error as RollupError, true); - process.exit(1); - break; - case 'ERROR': warnings.flush(); - handleError(event.error as RollupError, true); + handleError(event.error, true); break; case 'START': @@ -106,7 +88,7 @@ export default function watch( stderr( tc.cyan( `bundles ${tc.bold(input)} → ${tc.bold( - (event.output as string[]).map(relativeId).join(', ') + event.output.map(relativeId).join(', ') )}...` ) ); @@ -119,8 +101,8 @@ export default function watch( stderr( tc.green( `created ${tc.bold( - (event.output as string[]).map(relativeId).join(', ') - )} in ${tc.bold(ms(event.duration as number))}` + event.output.map(relativeId).join(', ') + )} in ${tc.bold(ms(event.duration))}` ) ); if (event.result && event.result.getTimings) { @@ -204,6 +186,6 @@ export default function watch( configWatcher = fs.watch(configFile, (event: string) => { if (event === 'change') restart(); - }); + }) as RollupWatcher; } } diff --git a/docs/02-javascript-api.md b/docs/02-javascript-api.md index 992802dbe16..ffa16222774 100755 --- a/docs/02-javascript-api.md +++ b/docs/02-javascript-api.md @@ -117,7 +117,7 @@ const outputOptions = { globals, name, plugins, - + // advanced output options assetFileNames, banner, @@ -135,7 +135,7 @@ const outputOptions = { sourcemapExcludeSources, sourcemapFile, sourcemapPathTransform, - + // danger zone amd, dynamicImportFunction, @@ -167,7 +167,6 @@ watcher.on('event', event => { // BUNDLE_END — finished building a bundle // END — finished building all bundles // ERROR — encountered an error while bundling - // FATAL — encountered an unrecoverable error }); // stop watching diff --git a/src/rollup/index.ts b/src/rollup/index.ts index 69e32e99d1a..1c8217df2c9 100644 --- a/src/rollup/index.ts +++ b/src/rollup/index.ts @@ -401,7 +401,8 @@ function createOutput(outputBundle: Record outputBundle[fileName]) .filter(outputFile => Object.keys(outputFile).length > 0) as ( | OutputChunk - | OutputAsset)[]).sort((outputFileA, outputFileB) => { + | OutputAsset + )[]).sort((outputFileA, outputFileB) => { const fileTypeA = getSortingFileType(outputFileA); const fileTypeB = getSortingFileType(outputFileB); if (fileTypeA === fileTypeB) return 0; diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 0bcab00e757..cc64901301e 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -614,7 +614,43 @@ export interface RollupWatchOptions extends InputOptions { watch?: WatcherOptions; } -export interface RollupWatcher extends EventEmitter { +interface TypedEventEmitter { + addListener(event: K, listener: T[K]): this; + emit(event: K, ...args: any[]): boolean; + eventNames(): Array; + getMaxListeners(): number; + listenerCount(type: keyof T): number; + listeners(event: K): Array; + off(event: K, listener: T[K]): this; + on(event: K, listener: T[K]): this; + once(event: K, listener: T[K]): this; + prependListener(event: K, listener: T[K]): this; + prependOnceListener(event: K, listener: T[K]): this; + rawListeners(event: K): Array; + removeAllListeners(event?: K): this; + removeListener(event: K, listener: T[K]): this; + setMaxListeners(n: number): this; +} + +export type RollupWatcherEvent = + | { code: 'START' } + | { code: 'BUNDLE_START'; input: InputOption; output: readonly string[] } + | { + code: 'BUNDLE_END'; + duration: number; + input: InputOption; + output: readonly string[]; + result: RollupBuild; + } + | { code: 'END' } + | { code: 'ERROR'; error: RollupError }; + +export interface RollupWatcher + extends TypedEventEmitter<{ + change: (id: string) => void; + event: (event: RollupWatcherEvent) => void; + restart: () => void; + }> { close(): void; } diff --git a/src/utils/PluginContext.ts b/src/utils/PluginContext.ts index f89ec229f37..924b8b7614d 100644 --- a/src/utils/PluginContext.ts +++ b/src/utils/PluginContext.ts @@ -194,7 +194,7 @@ export function getPluginContexts( }); deprecationWarningShown = true; } - return watcher!.on(event, handler); + return watcher!.on(event as any, handler); } return { diff --git a/src/utils/deconflictChunk.ts b/src/utils/deconflictChunk.ts index 7519bf763bc..1d2431d98af 100644 --- a/src/utils/deconflictChunk.ts +++ b/src/utils/deconflictChunk.ts @@ -97,9 +97,10 @@ function deconflictImportsOther( if (chunk.exportMode === 'default' || (preserveModules && variable.isNamespace)) { variable.setRenderNames(null, chunk.variableName); } else { - variable.setRenderNames(chunk.variableName, chunk.getVariableExportName(variable) as - | string - | null); + variable.setRenderNames( + chunk.variableName, + chunk.getVariableExportName(variable) as string | null + ); } } } diff --git a/src/watch/index.ts b/src/watch/index.ts index 958dfcd19f8..36b8b5fd849 100644 --- a/src/watch/index.ts +++ b/src/watch/index.ts @@ -28,7 +28,7 @@ export class Watcher { private tasks: Task[]; constructor(configs: GenericConfigObject[] | GenericConfigObject) { - this.emitter = new (class extends EventEmitter implements RollupWatcher { + this.emitter = new (class extends EventEmitter { close: () => void; constructor(close: () => void) { super(); @@ -37,7 +37,7 @@ export class Watcher { // showing the `MaxListenersExceededWarning` to the user. this.setMaxListeners(Infinity); } - })(this.close.bind(this)); + })(this.close.bind(this)) as RollupWatcher; this.tasks = (Array.isArray(configs) ? configs : configs ? [configs] : []).map( config => new Task(this, config) ); @@ -55,7 +55,7 @@ export class Watcher { } emit(event: string, value?: any) { - this.emitter.emit(event, value); + this.emitter.emit(event as any, value); } invalidate(id?: string) { diff --git a/test/function/samples/preserve-modules/virtual-modules-conflict/_config.js b/test/function/samples/preserve-modules/virtual-modules-conflict/_config.js index de79ef35377..dbd42c766d4 100644 --- a/test/function/samples/preserve-modules/virtual-modules-conflict/_config.js +++ b/test/function/samples/preserve-modules/virtual-modules-conflict/_config.js @@ -22,11 +22,14 @@ module.exports = { ] }, bundle(bundle) { - return bundle.generate({ format: 'esm' }).then(generated => - assert.deepEqual( - generated.output.map(chunk => chunk.fileName), - ['main.js', '_virtual/_virtualModule.js', '_virtual/_virtualModule2.js'] - ) - ); + return bundle + .generate({ format: 'esm' }) + .then(generated => + assert.deepEqual(generated.output.map(chunk => chunk.fileName), [ + 'main.js', + '_virtual/_virtualModule.js', + '_virtual/_virtualModule2.js' + ]) + ); } }; diff --git a/test/function/samples/preserve-modules/virtual-modules/_config.js b/test/function/samples/preserve-modules/virtual-modules/_config.js index c33e1a4c7cc..591d4d4b317 100644 --- a/test/function/samples/preserve-modules/virtual-modules/_config.js +++ b/test/function/samples/preserve-modules/virtual-modules/_config.js @@ -22,11 +22,14 @@ module.exports = { ] }, bundle(bundle) { - return bundle.generate({ format: 'esm' }).then(generated => - assert.deepEqual( - generated.output.map(chunk => chunk.fileName), - ['main.js', '_virtual/_virtualModule', 'lib/lib.js'] - ) - ); + return bundle + .generate({ format: 'esm' }) + .then(generated => + assert.deepEqual(generated.output.map(chunk => chunk.fileName), [ + 'main.js', + '_virtual/_virtualModule', + 'lib/lib.js' + ]) + ); } }; diff --git a/test/hooks/index.js b/test/hooks/index.js index c8e083a3b2a..719b6a128ed 100644 --- a/test/hooks/index.js +++ b/test/hooks/index.js @@ -914,7 +914,7 @@ describe('hooks', () => { return new Promise((resolve, reject) => { watcher.on('event', event => { if (event.code === 'BUNDLE_END') resolve(); - else if (event.code === 'ERROR' || event.code === 'FATAL') reject(event.error); + else if (event.code === 'ERROR') reject(event.error); }); }).catch(err => { assert.strictEqual( @@ -1192,7 +1192,10 @@ describe('hooks', () => { }) ) .then(() => { - assert.deepEqual(result, [{ a: file, format: 'cjs' }, { b: file, format: 'cjs' }]); + assert.deepEqual(result, [ + { a: file, format: 'cjs' }, + { b: file, format: 'cjs' } + ]); return sander.rimraf(TEMP_DIR); }); }); diff --git a/test/watch/index.js b/test/watch/index.js index a1042679488..f454536bdd9 100644 --- a/test/watch/index.js +++ b/test/watch/index.js @@ -34,9 +34,6 @@ describe('rollup.watch', () => { } else if (typeof next === 'string') { watcher.once('event', event => { if (event.code !== next) { - if (event.code === 'FATAL') { - console.error(event.error); - } watcher.close(); if (event.code === 'ERROR') console.log(event.error); reject(new Error(`Expected ${next} event, got ${event.code}`));