| 22 | return { |
| 23 | name: 'bun-bundle-feature-replace', |
| 24 | setup(build) { |
| 25 | // Bun's native bun:bundle feature() cannot be overridden by plugins. |
| 26 | // Instead, do source-level text replacement: for each enabled feature, |
| 27 | // replace `feature('NAME')` with `true`; for all other feature() calls, |
| 28 | // replace with `false`. This runs before Bun's own compile-time eval. |
| 29 | build.onLoad({ filter: /\.(ts|tsx)$/ }, async (args) => { |
| 30 | let contents = await Bun.file(args.path).text() |
| 31 | if (!contents.includes('feature(')) return undefined |
| 32 | for (const feat of ENABLED_FEATURES) { |
| 33 | contents = contents.replaceAll(`feature('${feat}')`, 'true') |
| 34 | } |
| 35 | // Remaining feature() calls → false |
| 36 | contents = contents.replace(/feature\('[A-Z_]+'\)/g, 'false') |
| 37 | return { contents, loader: args.path.endsWith('.tsx') ? 'tsx' : 'ts' } |
| 38 | }) |
| 39 | }, |
| 40 | } |
| 41 | } |