Skip to content

Commit

Permalink
Refactoring option normalization
Browse files Browse the repository at this point in the history
  • Loading branch information
lukastaegert committed Jan 24, 2020
1 parent 0bc81a6 commit bc5c9a9
Show file tree
Hide file tree
Showing 17 changed files with 320 additions and 407 deletions.
1 change: 0 additions & 1 deletion cli/help.md
Expand Up @@ -52,7 +52,6 @@ Basic options:
--no-treeshake Disable tree-shaking optimisations
--no-treeshake.annotations Ignore pure call annotations
--no-treeshake.propertyReadSideEffects Ignore property access side-effects
--treeshake.pureExternalModules Assume side-effect free externals

Examples:

Expand Down
14 changes: 4 additions & 10 deletions cli/run/index.ts
@@ -1,7 +1,7 @@
import { realpathSync } from 'fs';
import relative from 'require-relative';
import { WarningHandler } from '../../src/rollup/types';
import mergeOptions, { GenericConfigObject } from '../../src/utils/mergeOptions';
import { mergeOptions } from '../../src/utils/mergeOptions';
import { GenericConfigObject } from '../../src/utils/parseOptions';
import { getAliasName } from '../../src/utils/relativeId';
import { handleError } from '../logging';
import batchWarnings from './batchWarnings';
Expand Down Expand Up @@ -107,14 +107,8 @@ async function execute(
} else {
for (const config of configs) {
const warnings = batchWarnings();
const { inputOptions, outputOptions, optionError } = mergeOptions({
command,
config,
defaultOnWarnHandler: warnings.add
});
if (optionError) {
(inputOptions.onwarn as WarningHandler)({ code: 'UNKNOWN_OPTION', message: optionError });
}
const { inputOptions, outputOptions } = mergeOptions(config, command,
warnings.add);
if (command.stdin !== false) {
inputOptions.plugins!.push(stdinPlugin());
}
Expand Down
4 changes: 2 additions & 2 deletions cli/run/loadConfigFile.ts
Expand Up @@ -2,7 +2,7 @@ import path from 'path';
import tc from 'turbocolor';
import * as rollup from '../../src/node-entry';
import { RollupBuild, RollupOutput } from '../../src/rollup/types';
import { GenericConfigObject } from '../../src/utils/mergeOptions';
import { GenericConfigObject } from '../../src/utils/parseOptions';
import relativeId from '../../src/utils/relativeId';
import { handleError, stderr } from '../logging';
import batchWarnings from './batchWarnings';
Expand Down Expand Up @@ -73,4 +73,4 @@ export default function loadConfigFile(
return Array.isArray(configs) ? configs : [configs];
});
});
}
}
42 changes: 11 additions & 31 deletions cli/run/watch.ts
Expand Up @@ -4,12 +4,9 @@ import ms from 'pretty-ms';
import onExit from 'signal-exit';
import tc from 'turbocolor';
import * as rollup from '../../src/node-entry';
import {
RollupWatcher,
RollupWatchOptions,
WarningHandler
} from '../../src/rollup/types';
import mergeOptions, { GenericConfigObject } from '../../src/utils/mergeOptions';
import { RollupWatcher, RollupWatchOptions } from '../../src/rollup/types';
import { mergeOptions } from '../../src/utils/mergeOptions';
import { GenericConfigObject } from '../../src/utils/parseOptions';
import relativeId from '../../src/utils/relativeId';
import { handleError, stderr } from '../logging';
import batchWarnings from './batchWarnings';
Expand All @@ -26,35 +23,20 @@ export default function watch(
const isTTY = Boolean(process.stderr.isTTY);
const warnings = batchWarnings();
const initialConfigs = processConfigs(configs);
const clearScreen = initialConfigs.every(
config => config.watch!.clearScreen !== false
);
const clearScreen = initialConfigs.every(config => config.watch!.clearScreen !== false);

const resetScreen = getResetScreen(isTTY && clearScreen);
let watcher: RollupWatcher;
let configWatcher: RollupWatcher;

function processConfigs(configs: GenericConfigObject[]): RollupWatchOptions[] {
return configs.map(options => {
const merged = mergeOptions({
command,
config: options,
defaultOnWarnHandler: warnings.add
});

const { inputOptions, outputOptions } = mergeOptions(options, command, warnings.add);
const result: RollupWatchOptions = {
...merged.inputOptions,
output: merged.outputOptions
...inputOptions,
output: outputOptions
};

if (!result.watch) result.watch = {};

if (merged.optionError)
(merged.inputOptions.onwarn as WarningHandler)({
code: 'UNKNOWN_OPTION',
message: merged.optionError
});

return result;
});
}
Expand Down Expand Up @@ -87,9 +69,7 @@ export default function watch(
}
stderr(
tc.cyan(
`bundles ${tc.bold(input)}${tc.bold(
event.output.map(relativeId).join(', ')
)}...`
`bundles ${tc.bold(input)}${tc.bold(event.output.map(relativeId).join(', '))}...`
)
);
}
Expand All @@ -100,9 +80,9 @@ export default function watch(
if (!silent)
stderr(
tc.green(
`created ${tc.bold(
event.output.map(relativeId).join(', ')
)} in ${tc.bold(ms(event.duration))}`
`created ${tc.bold(event.output.map(relativeId).join(', '))} in ${tc.bold(
ms(event.duration)
)}`
)
);
if (event.result && event.result.getTimings) {
Expand Down
93 changes: 28 additions & 65 deletions src/rollup/rollup.ts
Expand Up @@ -8,7 +8,12 @@ import commondir from '../utils/commondir';
import { errCannotEmitFromOptionsHook, errInvalidExportOptionValue, error } from '../utils/error';
import { writeFile } from '../utils/fs';
import getExportMode from '../utils/getExportMode';
import mergeOptions, { ensureArray, GenericConfigObject } from '../utils/mergeOptions';
import {
ensureArray,
GenericConfigObject,
parseInputOptions,
parseOutputOptions
} from '../utils/parseOptions';
import { basename, dirname, isAbsolute, resolve } from '../utils/path';
import { PluginDriver } from '../utils/PluginDriver';
import { ANONYMOUS_OUTPUT_PLUGIN_PREFIX, ANONYMOUS_PLUGIN_PREFIX } from '../utils/pluginUtils';
Expand Down Expand Up @@ -53,12 +58,6 @@ function getAbsoluteEntryModulePaths(chunks: Chunk[]): string[] {
return absoluteEntryModulePaths;
}

const throwAsyncGenerateError = {
get() {
throw new Error(`bundle.generate(...) now returns a Promise instead of a { code, map } object`);
}
};

function applyOptionHook(inputOptions: InputOptions, plugin: Plugin) {
if (plugin.options)
return plugin.options.call({ meta: { rollupVersion } }, inputOptions) || inputOptions;
Expand All @@ -81,13 +80,7 @@ function getInputOptions(rawInputOptions: GenericConfigObject): InputOptions {
if (!rawInputOptions) {
throw new Error('You must supply an options object to rollup');
}
let { inputOptions, optionError } = mergeOptions({
config: rawInputOptions
});

if (optionError)
(inputOptions.onwarn as WarningHandler)({ message: optionError, code: 'UNKNOWN_OPTION' });

let inputOptions = parseInputOptions(rawInputOptions);
inputOptions = inputOptions.plugins!.reduce(applyOptionHook, inputOptions);
inputOptions.plugins = normalizePlugins(inputOptions.plugins!, ANONYMOUS_PLUGIN_PREFIX);

Expand Down Expand Up @@ -300,21 +293,18 @@ export async function rollupInternal(
const cache = useCache ? graph.getCache() : undefined;
const result: RollupBuild = {
cache: cache!,
generate: ((rawOutputOptions: GenericConfigObject) => {
generate: (rawOutputOptions: OutputOptions) => {
const { outputOptions, outputPluginDriver } = getOutputOptionsAndPluginDriver(
rawOutputOptions
rawOutputOptions as GenericConfigObject
);
const promise = generate(outputOptions, false, outputPluginDriver).then(result =>
return generate(outputOptions, false, outputPluginDriver).then(result =>
createOutput(result)
);
Object.defineProperty(promise, 'code', throwAsyncGenerateError);
Object.defineProperty(promise, 'map', throwAsyncGenerateError);
return promise;
}) as any,
},
watchFiles: Object.keys(graph.watchFiles),
write: ((rawOutputOptions: GenericConfigObject) => {
write: (rawOutputOptions: OutputOptions) => {
const { outputOptions, outputPluginDriver } = getOutputOptionsAndPluginDriver(
rawOutputOptions
rawOutputOptions as GenericConfigObject
);
if (!outputOptions.dir && !outputOptions.file) {
return error({
Expand All @@ -323,37 +313,13 @@ export async function rollupInternal(
});
}
return generate(outputOptions, true, outputPluginDriver).then(async bundle => {
let chunkCount = 0;
for (const fileName of Object.keys(bundle)) {
const file = bundle[fileName];
if (file.type === 'asset') continue;
chunkCount++;
if (chunkCount > 1) break;
}
if (chunkCount > 1) {
if (outputOptions.sourcemapFile)
return error({
code: 'INVALID_OPTION',
message: '"output.sourcemapFile" is only supported for single-file builds.'
});
if (typeof outputOptions.file === 'string')
return error({
code: 'INVALID_OPTION',
message:
'When building multiple chunks, the "output.dir" option must be used, not "output.file".' +
(typeof inputOptions.input !== 'string' ||
inputOptions.inlineDynamicImports === true
? ''
: ' To inline dynamic imports, set the "inlineDynamicImports" option.')
});
}
await Promise.all(
Object.keys(bundle).map(chunkId => writeOutputFile(bundle[chunkId], outputOptions))
);
await outputPluginDriver.hookParallel('writeBundle', [bundle]);
return createOutput(bundle);
});
}) as any
}
};
if (inputOptions.perf === true) result.getTimings = getTimings;
return result;
Expand Down Expand Up @@ -425,25 +391,16 @@ function normalizeOutputOptions(
hasMultipleChunks: boolean,
outputPluginDriver: PluginDriver
): OutputOptions {
const mergedOptions = mergeOptions({
config: {
output: {
...rawOutputOptions,
...(rawOutputOptions.output as object),
...(inputOptions.output as object)
}
}
});

if (mergedOptions.optionError) throw new Error(mergedOptions.optionError);

// now outputOptions is an array, but rollup.rollup API doesn't support arrays
const mergedOutputOptions = mergedOptions.outputOptions[0];
const outputOptionBase = rawOutputOptions.output || inputOptions.output || rawOutputOptions;
let outputOptions = parseOutputOptions(
outputOptionBase as GenericConfigObject,
inputOptions.onwarn as WarningHandler
);
const outputOptionsReducer = (outputOptions: OutputOptions, result: OutputOptions) =>
result || outputOptions;
const outputOptions = outputPluginDriver.hookReduceArg0Sync(
outputOptions = outputPluginDriver.hookReduceArg0Sync(
'outputOptions',
[mergedOutputOptions],
[outputOptions],
outputOptionsReducer,
pluginContext => {
const emitError = () => pluginContext.error(errCannotEmitFromOptionsHook());
Expand Down Expand Up @@ -488,7 +445,13 @@ function normalizeOutputOptions(
return error({
code: 'INVALID_OPTION',
message:
'You must set "output.dir" instead of "output.file" when generating multiple chunks.'
'When building multiple chunks, the "output.dir" option must be used, not "output.file". ' +
'To inline dynamic imports, set the "inlineDynamicImports" option.'
});
if (outputOptions.sourcemapFile)
return error({
code: 'INVALID_OPTION',
message: '"output.sourcemapFile" is only supported for single-file builds.'
});
}

Expand Down

0 comments on commit bc5c9a9

Please sign in to comment.