Plugin API
ExtForge plugins are TypeScript objects implementing ExtForgePluginV1. They register hooks during setup() and the runner fires those hooks at well-defined points in the build.
EntryDescriptor
Describes a single entry point to be bundled by esbuild.
| Member | Type | Description |
|---|---|---|
name | string | Logical name used to derive the output filename. |
file | string | Absolute or root-relative path to the entry source file. |
format | "esm" | "iife" | Output bundle format. |
esbuildOptions? | Record<string, unknown> | undefined | Extra esbuild options merged into this entry’s build. |
isContentScript? | boolean | undefined | Whether this entry is a content script (affects IIFE wrapping). |
PluginHooks
Hook registration methods available inside a plugin’s setup() call.
| Member | Type | Description |
|---|---|---|
onConfigResolved | (fn: (config: ExtForgeConfig) => void | Promise<void>) => void | Called once after config resolution, before any build. |
onManifestTransform | (fn: (manifest: ManifestObject, browser: Browser) => ManifestObject | Promise<ManifestObject>) => void | Called for each browser after the manifest is assembled, allowing mutation. |
onBuildStart | (fn: (info: { browser: Browser; dev: boolean; }) => void | Promise<void>) => void | Called at the start of each browser build. |
onBuildEntry | (fn: (entry: EntryDescriptor) => EntryDescriptor | void | Promise<EntryDescriptor | void>) => void | Called once per entry point, allowing plugins to mutate or replace the descriptor. |
onBuildEnd | (fn: (result: BuildResult) => void | Promise<void>) => void | Called after all entries for a browser have been bundled. |
onDevReload | (fn: (event: HMRUpdate) => void | Promise<void>) => void | Called in dev mode each time the HMR server dispatches a reload event. |
PluginContext
Runtime context injected into every plugin’s setup() function.
| Member | Type | Description |
|---|---|---|
config | ExtForgeConfig | The resolved ExtForge configuration for the current build. |
paths | { readonly root: string; readonly src: string; readonly dist: string; } | Resolved absolute paths for the project root, source, and output directories. |
logger | Logger | Logger instance scoped to the plugin runner. |
hooks | PluginHooks | Hook registration object for this plugin’s subscriptions. |
addEntry | (entry: EntryDescriptor) => void | Adds a synthetic entry point to the build without touching the config. |
emitFile | (rel: string, contents: string | Uint8Array<ArrayBufferLike>) => void | Writes a file to the output directory at the given relative path. |
ExtForgePluginV1
A plugin written against the v1 ExtForge plugin API.
| Member | Type | Description |
|---|---|---|
name | string | Unique-ish identifier; surfaces in logs and error messages. |
apiVersion | 1 | Required discriminator; routes the runner to the modern API. |
setup | (ctx: PluginContext) => void | Promise<void> | Called once after config resolution. Plugins register hooks here. |
ExtForgePluginLegacy
Thin legacy plugin shape accepted for backwards compatibility.
| Member | Type | Description |
|---|---|---|
name | string | Unique-ish identifier; surfaces in logs and error messages. |
setup? | ((config: ExtForgeConfig) => void | Promise<void>) | undefined | Optional hook called once with the resolved config. |
buildStart? | (() => void | Promise<void>) | undefined | Optional hook called at the start of each build. |
buildEnd? | ((result: unknown) => void | Promise<void>) | undefined | Optional hook called after each build completes. |
Example
import type { ExtForgePluginV1 } from 'extforge/plugins';
export function presetTailwind(): ExtForgePluginV1 { return { name: 'extforge:preset-tailwind', apiVersion: 1, setup({ hooks, logger }) { hooks.onBuildEntry((entry) => entry); }, };}