Repository: rollup/rollup
File: cli/run/commandPlugins.ts (TypeScript)

Code before:
import { resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
import type { InputOptions } from '../../src/rollup/types';
import { stdinPlugin } from './stdin';
import { waitForInputPlugin } from './waitForInput';

export async function addCommandPluginsToInputOptions(
	inputOptions: InputOptions,
	command: Record<string, unknown>
): Promise<void> {
	if (!Array.isArray(inputOptions.plugins)) {
		inputOptions.plugins = [inputOptions.plugins];
	}
	if (command.stdin !== false) {
		inputOptions.plugins.push(stdinPlugin(command.stdin));
	}
	if (command.waitForBundleInput === true) {
		inputOptions.plugins.push(waitForInputPlugin());
	}
	await addPluginsFromCommandOption(command.plugin, inputOptions);
}

export async function addPluginsFromCommandOption(
	commandPlugin: unknown,
	inputOptions: InputOptions
): Promise<void> {
	if (commandPlugin) {
		const plugins: any[] = [commandPlugin].flat(Infinity).filter(Boolean);
		for (const plugin of plugins) {
			if (/[={}]/.test(plugin)) {
				// -p plugin=value
				// -p "{transform(c,i){...}}"
				await loadAndRegisterPlugin(inputOptions, plugin);
			} else {
				// split out plugins joined by commas
				// -p node-resolve,commonjs,buble

Review comment (suggestion):
Actually at this point, it is guaranteed that `plugins` is an array, I just forgot to reflect it in the types. The reason is that `mergeInputOptions` runs first on the options that are passed here, and that one ensures `plugins` is an array. A nicer solution would be the following:

In `types.d.ts`, introduce a new type like

```ts
export interface InputOptionsWithPlugins extends InputOptions {
	plugins: (Plugin | null | false | undefined)[];
}
```

and change

```ts
export interface MergedRollupOptions extends InputOptionsWithPlugins {
	output: OutputOptions[];
}
```

Then use the new type in `mergeInputOptions` and change the type in `addCommandPluginsToInputOptions` from `InputOptions` to the more correct `MergedRollupOptions`.

Code after:
import { resolve } from 'node:path';
import { pathToFileURL } from 'node:url';
import type { InputOptionsWithPlugins } from '../../src/rollup/types';
import { normalizePluginOption } from '../../src/utils/options/options';
import { stdinPlugin } from './stdin';
import { waitForInputPlugin } from './waitForInput';

export async function addCommandPluginsToInputOptions(
	inputOptions: InputOptionsWithPlugins,
	command: Record<string, unknown>
): Promise<void> {
	if (command.stdin !== false) {
		inputOptions.plugins.push(stdinPlugin(command.stdin));
	}
	if (command.waitForBundleInput === true) {
		inputOptions.plugins.push(waitForInputPlugin());
	}
	await addPluginsFromCommandOption(command.plugin, inputOptions);
}

export async function addPluginsFromCommandOption(
	commandPlugin: unknown,
	inputOptions: InputOptionsWithPlugins
): Promise<void> {
	if (commandPlugin) {
		const plugins: any[] = normalizePluginOption(commandPlugin as any);
		for (const plugin of plugins) {
			if (/[={}]/.test(plugin)) {
				// -p plugin=value
				// -p "{transform(c,i){...}}"
				await loadAndRegisterPlugin(inputOptions, plugin);
			} else {
				// split out plugins joined by commas
				// -p node-resolve,commonjs,buble
				for (const p of plugin.split(',')) {
					await loadAndRegisterPlugin(inputOptions, p);