Dependencies
Plugins can use npm packages. Since the gateway container doesn’t include your project’s node_modules, you need a strategy for making dependencies available at runtime.
Bundled dependencies (recommended for most packages)
Section titled “Bundled dependencies (recommended for most packages)”esbuild bundles imported packages into the output file by default. This is the simplest approach — the compiled dist/plugin.js is self-contained:
npm install some-librarynpm run build # esbuild bundles some-library into dist/plugin.jsNo extra setup needed in the container.
External dependencies
Section titled “External dependencies”Some npm packages don’t bundle correctly with esbuild. The most common case is UMD libraries — packages that use a wrapper like this internally:
if (typeof module !== "undefined") { module.exports = f(); // clobbers the outer module.exports in the bundle}When esbuild bundles such a package into a single CJS file, the library’s module.exports = ... assignment overwrites your plugin’s exports, making init and handle disappear.
Symptoms
Section titled “Symptoms”The gateway logs an error like:
plugin './dist/my-plugin.js': init() failed: function 'init' not found in module exportsEven though the functions are clearly defined in your source code.
Fix: mark the package as external
Section titled “Fix: mark the package as external”Tell esbuild to skip bundling the problematic package:
{ "scripts": { "build": "esbuild src/plugin.ts --bundle --format=cjs --platform=node --target=node22 --outfile=dist/plugin.js --external:problematic-package" }}The compiled output will contain require("problematic-package") instead of inlining the package code. Node.js resolves this require() from node_modules/ at runtime — so you must ensure node_modules/ is available inside the container. The simplest way is to volume-mount your project directory (which includes node_modules/) into the container, the same way the examples mount their config directory:
volumes: - ./:/config # mounts your project root, including node_modules/If you don’t want to mount node_modules/ (e.g. in a production image), bundle the dependency instead of marking it external — or copy node_modules/ explicitly into your image.
How to tell if a package needs --external
Section titled “How to tell if a package needs --external”- Build and run — if the plugin loads, bundling works fine
- If you see the “not found in module exports” error, check the bundle for stray
module.exports =assignments from the dependency - Add
--external:package-nameand rebuild
Multiple entry points
Section titled “Multiple entry points”If your project has multiple plugins or interceptors, build each as a separate entry point:
{ "scripts": { "build": "esbuild src/plugin.ts src/interceptor.ts --bundle --format=cjs --platform=node --target=node22 --outdir=dist" }}Use --outdir instead of --outfile when building multiple files.