Creating a Compiler Plugin
CommandKit compiler plugins are a powerful way to extend the
functionality of your CommandKit application by modifying the way
CommandKit compiles your application. They are used to add new
features or modify existing ones. For example, you can use a compiler
plugin to transform the source code itself (e.g. CommandKit's
"use cache"
or "use macro"
directives).
Creating a compiler plugin
To create a compiler plugin, you need to create a new class that
extends the
CompilerPlugin
class. This class should implement the transform
method, which is
called by CommandKit to transform the source code. The transform
method should return the transformed source code.
import {
type CompilerPluginRuntime,
CompilerPlugin,
MaybeFalsey,
PluginTransformParameters,
TransformedResult,
} from 'commandkit';
export class MyPlugin extends CompilerPlugin {
// this is the name of the plugin
public readonly name = 'my-plugin';
public async activate(ctx: CompilerPluginRuntime): Promise<void> {
// this is where you can keep initialization logic
}
public async deactivate(ctx: CompilerPluginRuntime): Promise<void> {
// this is where you can keep cleanup logic
}
public async transform(
params: PluginTransformParameters,
): Promise<MaybeFalsey<TransformedResult>> {
const { contents } = params;
// this is just an example, you can do whatever you want with the contents
const transformedContents = contents.replace(
/console\.log/g,
'console.warn',
);
// return the transformed contents
return {
contents: result,
loader: params.loader,
};
}
}
Extending CommandKit templates
CommandKit templates are a way to autogenerate files and other
contents through the commandkit create
CLI command. CommandKit by
default comes with command
and event
templates. Compiler plugins
can register custom templates to be used by the commandkit create
command.
import {
type CompilerPluginRuntime,
CompilerPlugin,
} from 'commandkit';
export class MyPlugin extends CompilerPlugin {
public readonly name = 'my-plugin';
public async activate(ctx: CompilerPluginRuntime): Promise<void> {
// Registers `commandkit create event <name> <path>` template
ctx.registerTemplate('event', async (args: string[]) => {
const [name, path] = args;
const template = `
export default async function on${name[0].toUpperCase() + name.slice(1)}() {
console.log('${name} event fired!');
};
`.trim();
await writeFile(join(path, 'event.ts'), template);
});
}
public async deactivate(ctx: CompilerPluginRuntime): Promise<void> {
// remove the template from the registry when the plugin is deactivated
ctx.unregisterTemplate('event');
}
}
The registerTemplate
method must be called inside the activate
method, and the unregisterTemplate
method must be called inside the
deactivate
method.
Plugins may override the default templates by registering their own templates with the same name.
Using rolldown plugins
You can also use rolldown plugins as compiler plugins to transform your source code.
import { defineConfig } from 'commandkit';
import { someRolldownPlugin } from 'some-rolldown-plugin';
export default defineConfig({
rolldownPlugins: [someRolldownPlugin()],
});