Skip to content

definePlugin

definePlugin<TEnv, TName, TProvides, TRequires, TClient>(config): CfastPlugin<TName, Awaited<TProvides>, RequiresFromPlugins<TRequires>, TClient, TEnv>

Defined in: packages/core/src/define-plugin.ts:90

Defines a cfast plugin for use with createApp().use().

Two equivalent forms are supported:

  1. Inferred form (preferred) — pass plugin references in requires and the setup(ctx) parameter is automatically typed with their provides:

    const dbPlugin = definePlugin({
    name: "db",
    requires: [authPlugin],
    setup(ctx) {
    ctx.auth.user; // typed from authPlugin
    return { client: createDb({}) };
    },
    });

    No need to import or declare a TRequires type token — the dependency type flows directly from the registered plugin objects. Leaf plugins simply omit requires and get ctx: { request, env }.

  2. Curried form (legacy) — kept for backward compatibility with code that only has access to a PluginProvides<typeof authPlugin> type (e.g. when you cannot import the actual plugin value):

    definePlugin<AuthPluginProvides>()({
    name: "db",
    setup(ctx) { ctx.auth.user; return { ... }; },
    });

Plugins declared via the inferred form also benefit from runtime validation: app.use(plugin) throws a CfastConfigError if any plugin listed in requires has not yet been registered, with a message that names the missing dependency.

TEnv = Record<string, unknown>

TName extends string = string

TProvides = unknown

TRequires extends readonly CfastPlugin<string, unknown, any, unknown, any>[] = []

TClient = unknown

Plugin configuration with name, setup, and optional requires, Provider, client.

TClient

TName

ComponentType<{ children: ReactNode; }>

TRequires

(ctx) => TProvides | Promise<TProvides>

CfastPlugin<TName, Awaited<TProvides>, RequiresFromPlugins<TRequires>, TClient, TEnv>

A CfastPlugin instance ready to pass to app.use().

// Leaf plugin (no dependencies)
const analyticsPlugin = definePlugin({
name: 'analytics',
setup(ctx) {
return { track: (event: string) => {} };
},
});
// Dependent plugin — requires inferred from plugin references
const dbPlugin = definePlugin({
name: 'db',
requires: [authPlugin],
setup(ctx) {
ctx.auth.user; // typed from authPlugin
return { client: createDb({}) };
},
});
// Env-typed plugin — pass the env type as the single explicit generic
// to type ctx.env precisely (no casts needed):
const storagePlugin = definePlugin<Cloudflare.Env>({
name: 'storage',
setup(ctx) {
ctx.env.BUCKET; // typed as R2Bucket, not unknown
return { upload: (file: File) => ctx.env.BUCKET.put(file.name, file) };
},
});

definePlugin<TRequires, TEnv>(): <TName, TProvides, TClient>(config) => CfastPlugin<TName, Awaited<TProvides>, TRequires, TClient, TEnv>

Defined in: packages/core/src/define-plugin.ts:115

Defines a cfast plugin for use with createApp().use().

Two equivalent forms are supported:

  1. Inferred form (preferred) — pass plugin references in requires and the setup(ctx) parameter is automatically typed with their provides:

    const dbPlugin = definePlugin({
    name: "db",
    requires: [authPlugin],
    setup(ctx) {
    ctx.auth.user; // typed from authPlugin
    return { client: createDb({}) };
    },
    });

    No need to import or declare a TRequires type token — the dependency type flows directly from the registered plugin objects. Leaf plugins simply omit requires and get ctx: { request, env }.

  2. Curried form (legacy) — kept for backward compatibility with code that only has access to a PluginProvides<typeof authPlugin> type (e.g. when you cannot import the actual plugin value):

    definePlugin<AuthPluginProvides>()({
    name: "db",
    setup(ctx) { ctx.auth.user; return { ... }; },
    });

Plugins declared via the inferred form also benefit from runtime validation: app.use(plugin) throws a CfastConfigError if any plugin listed in requires has not yet been registered, with a message that names the missing dependency.

TRequires

TEnv = Record<string, unknown>

A CfastPlugin instance ready to pass to app.use().

<TName, TProvides, TClient>(config): CfastPlugin<TName, Awaited<TProvides>, TRequires, TClient, TEnv>

TName extends string

TProvides

TClient = unknown

TClient

TName

ComponentType<{ children: ReactNode; }>

(ctx) => TProvides | Promise<TProvides>

CfastPlugin<TName, Awaited<TProvides>, TRequires, TClient, TEnv>

// Leaf plugin (no dependencies)
const analyticsPlugin = definePlugin({
name: 'analytics',
setup(ctx) {
return { track: (event: string) => {} };
},
});
// Dependent plugin — requires inferred from plugin references
const dbPlugin = definePlugin({
name: 'db',
requires: [authPlugin],
setup(ctx) {
ctx.auth.user; // typed from authPlugin
return { client: createDb({}) };
},
});
// Env-typed plugin — pass the env type as the single explicit generic
// to type ctx.env precisely (no casts needed):
const storagePlugin = definePlugin<Cloudflare.Env>({
name: 'storage',
setup(ctx) {
ctx.env.BUCKET; // typed as R2Bucket, not unknown
return { upload: (file: File) => ctx.env.BUCKET.put(file.name, file) };
},
});