Documentation Index
Fetch the complete documentation index at: https://mintlify.com/tailor-platform/sdk/llms.txt
Use this file to discover all available pages before exploring further.
Beta Feature: The plugin system is currently in beta. APIs may change in future releases.
Plugins extend TailorDB types by automatically generating additional types, executors, and output files based on your type definitions.
Overview
When you run tailor-sdk generate, the SDK:
- Loads all TailorDB types with plugin attachments
- Passes each type to the attached plugins
- Generates additional types and executors based on plugin output
- Writes all generated files to the appropriate locations
This enables plugins to create derived functionality based on your application’s schema.
Configuration
Registering Plugins
Define plugins in tailor.config.ts using definePlugins():
import { defineConfig, definePlugins } from "@tailor-platform/sdk";
import { kyselyTypePlugin } from "@tailor-platform/sdk/plugin/kysely-type";
import { enumConstantsPlugin } from "@tailor-platform/sdk/plugin/enum-constants";
import { fileUtilsPlugin } from "@tailor-platform/sdk/plugin/file-utils";
import { seedPlugin } from "@tailor-platform/sdk/plugin/seed";
export const plugins = definePlugins(
kyselyTypePlugin({ distPath: "./generated/tailordb.ts" }),
enumConstantsPlugin({ distPath: "./generated/enums.ts" }),
fileUtilsPlugin({ distPath: "./generated/files.ts" }),
seedPlugin({ distPath: "./seed", machineUserName: "admin" }),
);
export default defineConfig({
name: "my-app",
// ...
});
The plugins export must be a named export (not default).
Attaching Plugins to Types
Use the .plugin() method to attach plugins to specific types:
import { db } from "@tailor-platform/sdk";
export const user = db
.type("User", {
name: db.string(),
email: db.string(),
})
.plugin({
"@example/my-plugin": {},
});
Plugin Configuration
Some plugins accept per-type configuration:
export const customer = db
.type("Customer", {
name: db.string(),
// ...
})
.plugin({
"@example/soft-delete": {
archiveReason: true,
retentionDays: 90,
},
});
Global Plugin Configuration
Plugins can also accept global configuration via definePlugins():
import { definePlugins } from "@tailor-platform/sdk";
import { softDeletePlugin } from "./plugins/soft-delete";
export const plugins = definePlugins(
// Custom plugin with global config (factory function)
softDeletePlugin({
archiveTablePrefix: "Deleted_",
defaultRetentionDays: 90,
}),
);
Generated Output
Plugins can generate:
- Types: Additional TailorDB types (e.g.,
CustomerHistory, Deleted_Customer)
- Executors: Event handlers triggered by record changes
- Field Extensions: Additional fields added to the source type
- Output Files: TypeScript code and other files via generation-time hooks
Generated files are placed under .tailor-sdk/<plugin-id>/ (the plugin ID is sanitized, e.g. @example/soft-delete → example-soft-delete), such as:
.tailor-sdk/example-soft-delete/types
.tailor-sdk/example-soft-delete/executors
Plugin Lifecycle
Plugins have 5 hooks across two lifecycle phases. Each hook fires at a specific point in the tailor-sdk generate pipeline:
tailor-sdk generate
│
├─ Load TailorDB types
│ ├─ onTypeLoaded ← per type with .plugin() attached
│ └─ onNamespaceLoaded ← once per namespace (namespace plugins)
│
├─ Resolve Auth
│
├─ onTailorDBReady ← all types finalized
│
├─ Load Resolvers
│
├─ onResolverReady ← all resolvers finalized
│
├─ Load Executors
│
└─ onExecutorReady ← all executors finalized
Definition-time Hooks
| Hook | Trigger | Can do |
|---|
onTypeLoaded | Each type with .plugin() attached | Generate types, resolvers, executors; extend source type fields |
onNamespaceLoaded | Once per namespace | Generate types, resolvers, executors |
These hooks produce TailorDB types, resolvers, and executors that become part of the application. Requires importPath on the plugin.
Generation-time Hooks
| Hook | Available data | Can do |
|---|
onTailorDBReady | TailorDB types, Auth | Write output files |
onResolverReady | TailorDB types, Resolvers, Auth | Write output files |
onExecutorReady | TailorDB types, Resolvers, Executors, Auth | Write output files |
These hooks receive all finalized data and produce output files (TypeScript code, etc.). They replace the previous standalone defineGenerators() approach. No importPath required.
A plugin can implement hooks from either or both phases.
Builtin Plugins
The SDK includes four builtin plugins for common tasks. All builtin plugins use generation-time hooks.
kyselyTypePlugin
Generates Kysely type definitions and the getDB() function for type-safe database access.
import { kyselyTypePlugin } from "@tailor-platform/sdk/plugin/kysely-type";
export const plugins = definePlugins(
kyselyTypePlugin({ distPath: "./generated/tailordb.ts" }),
);
Prerequisites:
pnpm add -D @tailor-platform/function-types
Usage:
import { getDB } from "./generated/tailordb";
body: async (context) => {
const db = getDB("tailordb");
const users = await db
.selectFrom("User")
.selectAll()
.where("email", "=", context.input.email)
.execute();
return { users };
};
enumConstantsPlugin
Extracts enum constants from TailorDB type definitions.
import { enumConstantsPlugin } from "@tailor-platform/sdk/plugin/enum-constants";
export const plugins = definePlugins(
enumConstantsPlugin({ distPath: "./generated/enums.ts" }),
);
Generated output:
export const OrderStatus = {
PENDING: "PENDING",
PROCESSING: "PROCESSING",
COMPLETED: "COMPLETED",
CANCELLED: "CANCELLED",
} as const;
export type OrderStatus = (typeof OrderStatus)[keyof typeof OrderStatus];
fileUtilsPlugin
Generates utility functions for handling file-type fields.
import { fileUtilsPlugin } from "@tailor-platform/sdk/plugin/file-utils";
export const plugins = definePlugins(
fileUtilsPlugin({ distPath: "./generated/files.ts" }),
);
seedPlugin
Generates seed data configuration files for database initialization.
import { seedPlugin } from "@tailor-platform/sdk/plugin/seed";
export const plugins = definePlugins(
seedPlugin({ distPath: "./seed", machineUserName: "admin" }),
);
Usage:
node seed/exec.mjs -m admin
Plugin System API
Plugins can use the withPluginContext helper to access type information and create executors:
import { withPluginContext } from "@tailor-platform/sdk/plugin";
export const examplePlugin = () => {
return {
id: "@example/my-plugin",
description: "Example plugin",
onTypeLoaded: withPluginContext((ctx) => {
// Access type information
const typeName = ctx.type.name;
const fields = ctx.type.fields;
// Return generated types, executors, etc.
return {
types: [],
executors: [],
fieldExtensions: [],
};
}),
};
};
Available Context
The withPluginContext helper provides:
type: The TailorDB type being processed
namespace: The namespace the type belongs to
schema: Complete schema information
- Helper functions for creating executors and types
Using getGeneratedType
For accessing plugin-generated types, use the getGeneratedType function:
import { getGeneratedType } from "@tailor-platform/sdk/plugin";
// Access type generated by another plugin
const generatedType = getGeneratedType({
pluginId: "@tailor-platform/kysely-type",
originalTypeName: "User",
config: plugins, // Your plugin configuration
});
Migrating from Generators
If you’re using the legacy defineGenerators() syntax, migrate to plugins:
Before (Generators):
import { defineGenerators } from "@tailor-platform/sdk";
export const generators = defineGenerators(
["@tailor-platform/kysely-type", { distPath: "./generated/tailordb.ts" }],
["@tailor-platform/enum-constants", { distPath: "./generated/enums.ts" }],
);
After (Plugins):
import { definePlugins } from "@tailor-platform/sdk";
import { kyselyTypePlugin } from "@tailor-platform/sdk/plugin/kysely-type";
import { enumConstantsPlugin } from "@tailor-platform/sdk/plugin/enum-constants";
export const plugins = definePlugins(
kyselyTypePlugin({ distPath: "./generated/tailordb.ts" }),
enumConstantsPlugin({ distPath: "./generated/enums.ts" }),
);
Both syntaxes are currently supported, but the plugin system is the recommended approach going forward.
Creating Custom Plugins
For detailed information on creating your own plugins, see the Custom Plugins documentation.
Key concepts:
- Plugin Factory: Return a plugin configuration object
- Lifecycle Hooks: Implement the hooks you need
- Type Generation: Create new types based on existing ones
- Executor Generation: Generate event handlers automatically
- File Generation: Output TypeScript files for use in your application
Next Steps
- Explore Generators (legacy approach)
- Learn about TailorDB for database schema definition
- Read about Executors for event-driven handlers