Plugins are used to extend the functionality of both Kilpi
and KilpiClient
. They can access the instance themselves, extend their public interface and e.g. access hooks for any custom functionality.
Available plugins
List of all available first-party plugins.
Audit Plugin
Utility for auditing your authorizations.
Endpoint Plugin
Create a web standard endpoint for requesting authorization decisions, used with the Kilpi client.
React Server Components Plugin
React Server Components for working with Kilpi and automatic RSC scope.
React Client Plugin
React Client components for working with Kilpi client.
Creating custom plugins
You are welcome to create custom plugins for Kilpi for use in your own application and as packages for the community. Please share your public community plugins on Github and they can be added to the documentation.
Creating custom server-side plugins
Let’s create an utility plugin for counting the total number of authorizations as an example.
import { createKilpiCorePlugin, type AnyKilpiCore } from "@kilpi/core";
// Plugin constructor is a generic function of <T extends AnyKilpiCore>// and can take any configuration options needed.function CounterPlugin<T extends AnyKilpiCore>(opts: { message: string }) { // The constructor must return a kilpi core plugin with the `createKilpiCorePlugin` // function which provides the Kilpi instance as an argument. return createKilpiCorePlugin((Kilpi: T) => { // Internal state let count = 0;
// Access hooks on the Kilpi instance itself Kilpi.$hooks.onAfterAuthorization(() => { count++; });
// Return optional extensions on the public Kilpi interface. // Please prefix at least your root-level APIs with "$" to avoid // naming conflicts. return { // Function which returns an extension on the Kilpi instance itself extendCoreApi() { return { $logCount() { console.log(opts.message.replace("%", count.toString())); }, }; }, }; });}
// Install the pluginconst Kilpi = createKilpi({ getSubject, policies, plugins: [CounterPlugin({ message: "% authorizations made!" })],});
// Use the pluginKilpi.$logCount(); // "10 authorizations made!"
Creating custom client-side plugins
Let’s create an utility plugin for KilpiClient.
import { createKilpiCorePlugin, type AnyKilpiCore } from "@kilpi/core";import type { KilpiClient } from "@kilpi/client";// Boilerplate if exteending the policy interface:// The type of a KilpiClientPolicy extensionexport interface KilpiClientPolicyExtension_SayHelloPlugin< TClient extends AnyKilpiClient, TAction extends PolicysetActions<TClient["$$infer"]["policies"]>,> { sayHello(): void;}
// Boilerplate if exteending the policy interface:// Augment KilpiClientPolicy with extension.declare module "@kilpi/client" { // eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface IKilpiClientPolicy< TClient extends AnyKilpiClient, TAction extends PolicysetActions<TClient["$$infer"]["policies"]>, > extends KilpiClientPolicyExtension_SayHelloPlugin<TClient, TAction> {}}// Plugin constructor is a generic function of <T extends AnyKilpiCore>// and can take any configuration options needed.function SayHelloPlugin<T extends AnyKilpiCore>(opts: { name: string }) { // The constructor must return a kilpi client plugin with the `createKilpiClientPlugin` // function which provides the KilpiClient as an argument. return createKilpiClientPlugin((Client: KilpiClient<T>) => { // Return optional extensions on the public KilpiClient interface // and the policy interfaces.Please prefix at least your root-level APIs // with "$" to avoid naming conflicts (not requred for policies). return { // Function which returns an extension on the KilpiClient // instance itself. extendClient() { return { $sayHello() { console.log(`Hello from ${opts.name}`); }, }; }, // Function which returns an extension on the policies. // This function must implement the extension defined in // `KilpiClientPolicyExtension_SayHelloPlugin` with access // to the policy. extendPolicy(policy) { return { sayHello() { console.log(`Hello from ${policy.$action}`); }, } satisfies KilpiClientPolicyExtension_SayHelloPlugin< // Required TypeScript boilerplate KilpiClient<TCore>, PolicysetActions<TCore["$$infer"]["policies"]> >; }, }; });}
// Install the pluginconst KilpiClient = createKilpiClient({ ..., plugins: [SayHelloPlugin({ name: "MyKilpiClient" })],});
// Use the pluginKilpiClient.$sayHello(); // Hello from MyKilpiClientKilpiClient.posts.edit(post).sayHello(); // Hello from posts.edit