npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@emahuni/rolldown-wrapper

v2.4.1

Published

A package to hack into rolldown or rollup to enable injection of rollup or rolldown options where it is not possible.

Downloads

22

Readme

Rolldown Wrapper

A Node.js ESM loader wrapper for Rollup and Rolldown that allows automatic configuration merging, runtime option injection, and optional debug logging, without requiring changes to consumer code.

⚠️ Node.js v20.10.0+ required.


Why

Normally, Rollup (and Rolldown) expect you to manage configuration through a rollup.config.js file or by passing options directly to their APIs.
This works fine if you control the build process.

But in some cases, like with Directus or other frameworks, Rollup/Rolldown are used internally and you don’t get access to their config files.
That means you cannot:

  • Inject custom plugins
  • Override or add to default rollup options
  • Enforce consistent build settings across projects

This wrapper solves that by:

  • Intercepting rolldown / rollup at import time using Node’s ESM loader hooks.
  • Wrapping the internal functions so your own config and runtime options are always merged in.
  • Ensuring consumers can continue using import { rollup } from 'rollup' or import { rolldown } from 'rolldown' without any changes.

In short:
👉 It gives you centralised control over Rollup/Rolldown behaviour, even when you don’t control the consumer code.


Features

  • Automatically wraps rollup and rolldown exports.
  • Merges config file options with runtime options.
  • Supports:
    • Direct function exports.
    • Imported bindings and re-exports.
    • Plain function or variable definitions.
  • Fully compatible with ESM imports (import { rollup } from 'rollup').
  • Optional debug logging for patched sources.
  • Graceful fallback if a module cannot be patched.
  • Deep merge of objects and concatenation of arrays in options.

Installation

pnpm add @emahuni/rolldown-wrapper

How it Works

  +------------------+
 |   Node Import    |
 | rollup/rolldown  |
 +--------+---------+
          |
          v
 +-------------------------+
 | Rolldown Wrapper Loader  |
 |  - Detects export type  |
 |  - Renames original fn   |
 |    (__original_rollup)  |
 |  - Injects wrapper fn   |
 |    (rollup / rolldown)  |
 |  - Merges config + runtime
 |  - Adds debug logs if enabled
 |  - Resolves loader dynamically
 +--------+----------------+
          |
          v
 +------------------+
 | Consumer Code    |
 | import { rollup }|
 | or import {rolldown} |
 | Works as usual  |
 +------------------+

Usage

1. Programmatic Registration via Script directus-cli.js

This is an example of a programmatic registration script for Directus CLI, as this was the original use case.

import { register } from 'node:module';
import { pathToFileURL } from 'node:url';
import { createRequire } from 'node:module';
import { init } from '@emahuni/rolldown-wrapper';

const require = createRequire(import.meta.url);

// Dynamically resolve loader package
const loaderPackage = '@emahuni/rolldown-wrapper';
const loaderPath = pathToFileURL(new URL(loaderPackage, import.meta.url).pathname);

// Initialise runtime options (optional)
init({
    options        : { // optional, Rollup/Rolldown options to merge with config (the key can also be rollupOptions or rolldownOptions)
        plugins: [],
        build  : { minify: true },
    },
    debug          : true, // optional, enables runtime debug logs
    finalizeOptions: (options) => ({ ...options, customFlag: true }), // optional hook for final transformation
});

// Register loader
register(loaderPackage, loaderPath);

// Dynamically resolve Directus CLI
(async () => {
    try {
        const cliPath = require.resolve('directus/package.json')
                               .replace('package.json', 'cli.js');
        const cli = await import(pathToFileURL(cliPath).href);
        console.debug('Starting Directus CLI...');
    } catch (err) {
        console.error('Failed to start Directus CLI:', err);
    }
})();

⚠️ Recommended: avoids Node’s experimental loader warning.

2. Inline Registration with Dynamic Package Resolution

node --import "data:text/javascript,
import { register } from 'node:module';
import { pathToFileURL } from 'node:url';
import path from 'path';

// Dynamically resolve loader package
const loaderPackage = '@emahuni/rolldown-wrapper';
const loaderPath = pathToFileURL(new URL(loaderPackage, import.meta.url).pathname);
register(loaderPackage, loaderPath);" \
./node_modules/directus/cli.js bootstrap

Usage

Run:

node directus-cli.js bootstrap
node directus-cli.js start
  • Works with any Directus CLI command or directus extensions.
  • No experimental `--loader` warnings.
  • Runtime options from init() are merged the wrapper's consumer, and with your rolldown.config.js if used (see Configuration below).

3. Deprecated: Using `--loader`

node --loader '@emahuni/rolldown-wrapper' ./node_modules/directus/cli.js bootstrap
node --loader '@emahuni/rolldown-wrapper' ./node_modules/directus/cli.js start

⚠️ Deprecated: Node emits an experimental warning:

ExperimentalWarning: \`--experimental-loader\` may be removed in the future; instead use register()

Configuration

You can create a `rolldown.config.js` or `rollup.config.js` in the project root:

export default {
    plugins: [],
    build  : {
        minify: false,
    },
};

Important:

  • Only accepts Rollup/Rolldown-compatible options.
  • Does not accept package-specific options like debug or finalizeOptions. Those must be passed via init().
  • These options are merged with the options (rollupOptions) object from init().

Runtime Options (init())

import { init } from '@emahuni/rolldown-wrapper';

init({
    options        : { // (the key can also be rollupOptions or rolldownOptions)
        plugins: [/* ... */ ],
        build  : { minify: true },
    },
    configFilePath : 'path/to/my.config.js', // optional, path to config.js file, defaults to ./rolldown.config.js or ./rollup.config.js
    debug          : true, // enable debug logs at runtime
    finalizeOptions: (options) => ({ ...options, customFlag: true }), // optional final transformation
});
  • Can include both package-specific options and rollupOptions.
  • options are merged with rolldown.config.js. (the options key can also be rollupOptions or rolldownOptions)
  • debug enables logging of merged options.
  • finalizeOptions allows final transformation of the merged options before invoking the original Rollup/Rolldown function.

Behaviour

  • Detects rollup/rolldown exports in various forms:
  • Direct function export
  • Exported from imported bindings
  • Plain function/variable definitions
  • Renames original function to _original and wraps it with merged options.
  • Logs merged options if debug is enabled.
  • If patching fails, warns in console but does not break the import.
  • Deep merges objects and concatenates arrays in options.

Changes

  • v2.2.0
  • now uses either rollup.config.js or rolldown.config.js file, whichever exists..
  • init() can pass package-specific options and rollupOptions.
  • Added debug option for runtime logging.
  • Added finalizeOptions function.
  • Improved fallback for various export types.
  • Deep merge of objects and array concatenation.
  • Graceful handling when patching fails.

Contribution

  • Contributions are welcome!
  • Please open issues or pull requests on GitHub.
  • Ensure new code includes tests and documentation updates.

Author

Emmanuel Mahuni
GitHub: emahuni


License

MIT