Skip to main content

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:
  1. Loads all TailorDB types with plugin attachments
  2. Passes each type to the attached plugins
  3. Generates additional types and executors based on plugin output
  4. 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():
tailor.config.ts
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:
tailordb/user.ts
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:
tailordb/customer.ts
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():
tailor.config.ts
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-deleteexample-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

HookTriggerCan do
onTypeLoadedEach type with .plugin() attachedGenerate types, resolvers, executors; extend source type fields
onNamespaceLoadedOnce per namespaceGenerate 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

HookAvailable dataCan do
onTailorDBReadyTailorDB types, AuthWrite output files
onResolverReadyTailorDB types, Resolvers, AuthWrite output files
onExecutorReadyTailorDB types, Resolvers, Executors, AuthWrite 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.
tailor.config.ts
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:
resolvers/userQuery.ts
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.
tailor.config.ts
import { enumConstantsPlugin } from "@tailor-platform/sdk/plugin/enum-constants";

export const plugins = definePlugins(
  enumConstantsPlugin({ distPath: "./generated/enums.ts" }),
);
Generated output:
generated/enums.ts
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.
tailor.config.ts
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.
tailor.config.ts
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:
plugins/example.ts
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):
tailor.config.ts
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):
tailor.config.ts
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:
  1. Plugin Factory: Return a plugin configuration object
  2. Lifecycle Hooks: Implement the hooks you need
  3. Type Generation: Create new types based on existing ones
  4. Executor Generation: Generate event handlers automatically
  5. 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

Build docs developers (and LLMs) love