definePlugin
definePlugin
allows you to create custom type-safe plugins that can extend integration hooks with additional parameters and functionality. This is an advanced utility for creating reusable plugin components that can be shared across multiple integrations or distributed as third-party packages.
For more practical examples of how to create your own plugins, check out the built-in plugins source code in the Astro Integration Kit repository.
How it works
Section titled “How it works”When you use definePlugin
, it:
- Defines a named plugin: Creates a plugin with a specific name that can be used across multiple integrations
- Sets up hook extensions: The
setup()
function defines which hooks the plugin extends and what additional parameters it provides - Provides type safety: Ensures that the additional parameters are properly typed and available in your integration hooks
- Enables reusability: Allows the same plugin logic to be shared across different integrations
Creating a plugin
Section titled “Creating a plugin”-
Define your plugin
Create a plugin with a unique name and setup function:
definePlugin({name: "my-plugin",setup({ name }) {return {"astro:config:setup": (hookParams) => ({// Additional parameters to provide to this hookmyUtility: (value: string) => {// Plugin implementation}})}}}) -
Use it in your integration
Add the plugin to your integration using
withPlugins
:export default defineIntegration({name: "my-integration",setup({ name }) {return withPlugins({name,plugins: [myPlugin],hooks: {"astro:config:setup": ({ myUtility }) => {// Use the plugin's functionalitymyUtility("some value");}}})}})
defineAllHooksPlugin
Section titled “defineAllHooksPlugin”defineAllHooksPlugin
is a variation of definePlugin
that provides the same API across all Astro hooks. This is useful when you want to create a plugin that works with any hook, including future hooks or hooks added by other integrations.
When to use it
Section titled “When to use it”Use defineAllHooksPlugin
when:
- Your plugin should work with any Astro hook
- You want to support hooks added by other integrations (like
@astrojs/db
) - You want your plugin to be forward-compatible with future Astro versions
Instead of mapping specific hooks, you provide a factory function that receives the hook name:
defineAllHooksPlugin({ name: "my-plugin", setup({ name }) { return (hookName) => (hookParameters) => ({ doSomething: () => { console.log(`Called from ${hookName} hook`); } }); }})
Plugin deduplication
Section titled “Plugin deduplication”When multiple plugins with the same name are provided, withPlugins
automatically deduplicates them by keeping only the last occurrence. This prevents conflicts and ensures predictable behavior.
return withPlugins({ name, plugins: [pluginA, pluginB, pluginA], // Only the last pluginA is kept hooks: { /* ... */ }})
Example
Section titled “Example”Here’s a complete example of the built-in hasVitePlugin
plugin to demonstrate real-world usage:
-
Define the plugin
package/plugins/has-vite-plugin.ts import type { AstroConfig } from "astro";import type { Plugin, PluginOption } from "vite";import { definePlugin } from "astro-integration-kit";import { hasVitePlugin, getPlugins } from "../utilities/has-vite-plugin.js";export const hasVitePluginPlugin = definePlugin({name: "hasVitePlugin",setup() {return {"astro:config:setup": (params) => {const currentPlugins = getPlugins(new Set(),params.config.vite?.plugins,);const { updateConfig, config } = params;params.updateConfig = (newConfig) => {config.vite.plugins = Array.from(getPlugins(currentPlugins, newConfig.vite?.plugins),);return updateConfig(newConfig);};return {hasVitePlugin: (plugin: string | PluginOption) =>hasVitePlugin(params, {plugin,}),};},};},}); -
Use in integration
my-integration/index.ts import { defineIntegration, withPlugins } from "astro-integration-kit";import { hasVitePluginPlugin } from "astro-integration-kit/plugins";export default defineIntegration({name: "my-integration",setup({ name }) {return withPlugins({name,plugins: [hasVitePluginPlugin],hooks: {"astro:config:setup": ({ hasVitePlugin }) => {// hasVitePlugin is provided by the hasVitePluginPluginif (hasVitePlugin("some-plugin-name")) {// Plugin already exists}}}})}})