Skip to main content
Version: Next

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

Using rolldown plugins

You can also use rolldown plugins as compiler plugins. This is useful if you want to use rolldown plugins to transform your source code.

commandkit.config.ts
import { defineConfig } from 'commandkit';
import { someRolldownPlugin } from 'some-rolldown-plugin';

export default defineConfig({
rolldownPlugins: [someRolldownPlugin()],
});

Using custom compiler plugins

You can also create custom compiler plugins by extending the CompilerPlugin class. This is useful if you want to create a custom plugin that modifies the way CommandKit compiles your application.

commandkit.config.ts
import { defineConfig } from 'commandkit';
import { CompilerPlugin } from 'some-commandkit-compiler-plugin';

export default defineConfig({
plugins: [someCompilerPlugin()],
});

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.

my-plugin.ts
import {
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 commandkit create command. CommandKit by default comes with command and event templates. Compiler plugins can register custom templates to be used by the commandkit create command.

my-plugin.ts
import { CompilerPlugin, CompilerPluginRuntime } 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');
}
}
warning

The registerTemplate method must be called inside the activate method, and the unregisterTemplate method must be called inside the deactivate method.

info

Plugins may override the default templates by registering their own templates with the same name.