function copyAssetsPlugin({ root, mergedAssets }) {
	let entries = [];
	return {
		name: 'copy-assets',
		buildStart(options) {
			entries = [options.input].flatMap(f => (typeof f === 'object' ? Object.values(f) : f));
		},
		async generateBundle(_, bundle) {
			const processed = new Set();

			for (const f of entries) processed.add(relative(root, f));

			for (let i in bundle) {
				// never overwrite a generated file:
				processed.add(i);

				const chunk = bundle[i];
				if (chunk.type === 'chunk') {
					for (const f of chunk.referencedFiles) processed.add(f);
					for (const f in chunk.modules) {
						if (f[0] === '\0') continue;
						processed.add(relative(root, f));
					}
				} else if (chunk.name) {
					// TODO: this isn't safe because names aren't paths
					processed.add(chunk.name);
					// // @ts-ignore-next
					// if (chunk.referencedFiles) for (const f of chunk.referencedFiles) processed.add(f);
				}
			}

			const files = await readdirRecursive(root, [...IGNORE_FILES, ...Array.from(processed).map(f => '/' + f)]);

			await Promise.all(
				files.map(async name => {
					if (mergedAssets.has(join(root, name))) return;
					this.emitFile({
						type: 'asset',
						fileName: name,
						source: await fs.readFile(join(root, name))
					});
				})
			);
		}
	};
}
@param {object} options
@param {string} options.root
@param {Set<string>} options.mergedAssets
@returns {import('rollup').Plugin}