or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cli.mdcomposables.mdextensions.mdindex.mdutilities.md
tile.json

extensions.mddocs/

Extension Definitions

Type-safe functions for defining different types of Directus extensions. Each function provides proper TypeScript support and validation for extension configurations.

Capabilities

Display Extensions

Define custom field display components for showing data in the admin interface.

/**
 * Define a display extension with custom configuration
 * @param config - Display configuration object
 * @returns Extended display configuration with type safety
 */
function defineDisplay<Custom extends CustomConfig<DisplayConfig>>(
  config: ExtendedConfig<DisplayConfig, Custom>
): ExtendedConfig<DisplayConfig, Custom>;

interface DisplayConfig {
  id: string;
  name: string;
  icon: string;
  description?: string;
  component: Component;
  options?: FieldOptions[];
  types: readonly FieldType[];
  localTypes?: readonly LocalType[];
  group?: 'standard' | 'selection' | 'relational' | 'presentation' | 'other';
}

Usage Example:

import { defineDisplay } from '@directus/extensions-sdk';
import DisplayComponent from './display.vue';

export default defineDisplay({
  id: 'my-custom-display',
  name: 'My Custom Display',
  icon: 'format_paint',
  description: 'A custom display for special formatting',
  component: DisplayComponent,
  types: ['string', 'text'],
  options: [
    {
      field: 'color',
      name: 'Color',
      type: 'string',
      meta: {
        interface: 'select-color',
        width: 'half'
      }
    }
  ]
});

Interface Extensions

Define custom field input components for data entry in the admin interface.

/**
 * Define an interface extension with custom configuration
 * @param config - Interface configuration object
 * @returns Extended interface configuration with type safety
 */
function defineInterface<Custom extends CustomConfig<InterfaceConfig>>(
  config: ExtendedConfig<InterfaceConfig, Custom>
): ExtendedConfig<InterfaceConfig, Custom>;

interface InterfaceConfig {
  id: string;
  name: string;
  icon: string;
  description?: string;
  component: Component;
  options?: FieldOptions[];
  types: readonly FieldType[];
  localTypes?: readonly LocalType[];
  group?: 'standard' | 'selection' | 'relational' | 'presentation' | 'group' | 'other';
  relational?: boolean;
}

Layout Extensions

Define custom layout components for displaying collections in the admin interface.

/**
 * Define a layout extension with custom configuration
 * @param config - Layout configuration object
 * @returns Layout configuration with type safety
 */
function defineLayout<Options = any, Query = any>(
  config: LayoutConfig<Options, Query>
): LayoutConfig<Options, Query>;

interface LayoutConfig<Options = any, Query = any> {
  id: string;
  name: string;
  icon: string;
  component: Component;
  slots?: {
    options: Component;
    sidebar: Component;
    actions: Component;
  };
  setup?: (props: LayoutProps<Options, Query>) => Record<string, any>;
}

Module Extensions

Define custom admin modules that appear in the navigation sidebar.

/**
 * Define a module extension with custom configuration
 * @param config - Module configuration object
 * @returns Extended module configuration with type safety
 */
function defineModule<Custom extends CustomConfig<ModuleConfig>>(
  config: ExtendedConfig<ModuleConfig, Custom>
): ExtendedConfig<ModuleConfig, Custom>;

interface ModuleConfig {
  id: string;
  name: string;
  icon: string;
  routes: ModuleRoute[];
  hidden?: boolean;
  preRegisterCheck?: (user: User, permissions: Permission[]) => boolean;
}

Panel Extensions

Define custom dashboard panels for the insights dashboard.

/**
 * Define a panel extension with custom configuration
 * @param config - Panel configuration object
 * @returns Extended panel configuration with type safety
 */
function definePanel<Custom extends CustomConfig<PanelConfig>>(
  config: ExtendedConfig<PanelConfig, Custom>
): ExtendedConfig<PanelConfig, Custom>;

interface PanelConfig {
  id: string;
  name: string;
  icon: string;
  description?: string;
  component: Component;
  options?: FieldOptions[];
  minWidth: number;
  minHeight: number;
  skipUndefinedKeys?: string[];
}

Hook Extensions

Define server-side event hooks that execute during API operations.

/**
 * Define a hook extension configuration
 * @param config - Hook configuration object
 * @returns Hook configuration for server-side execution
 */
function defineHook(config: HookConfig): HookConfig;

interface HookConfig {
  'items.create'?: HookHandler | HookHandler[];
  'items.create.before'?: HookHandler | HookHandler[];
  'items.create.after'?: HookHandler | HookHandler[];
  'items.update'?: HookHandler | HookHandler[];
  'items.update.before'?: HookHandler | HookHandler[];
  'items.update.after'?: HookHandler | HookHandler[];
  'items.delete'?: HookHandler | HookHandler[];
  'items.delete.before'?: HookHandler | HookHandler[];
  'items.delete.after'?: HookHandler | HookHandler[];
  [key: string]: HookHandler | HookHandler[] | undefined;
}

type HookHandler = (context: HookContext) => void | Promise<void>;

Endpoint Extensions

Define custom API endpoints that extend the Directus REST API.

/**
 * Define an endpoint extension configuration
 * @param config - Endpoint configuration object
 * @returns Endpoint configuration for API route registration
 */
function defineEndpoint(config: EndpointConfig): EndpointConfig;

interface EndpointConfig {
  id: string;
  handler: EndpointHandler;
}

type EndpointHandler = (router: Router, context: EndpointContext) => void;

Operation Extensions

Define custom operations for Directus workflows.

/**
 * Define an API operation extension for server-side workflow execution
 * @param config - Operation API configuration object
 * @returns Operation configuration with type safety
 */
function defineOperationApi<Options = Record<string, unknown>>(
  config: OperationApiConfig<Options>
): OperationApiConfig<Options>;

/**
 * Define an app operation extension for client-side workflow configuration
 * @param config - Operation app configuration object
 * @returns Extended operation app configuration with type safety
 */
function defineOperationApp<Custom extends CustomConfig<OperationAppConfig>>(
  config: ExtendedConfig<OperationAppConfig, Custom>
): ExtendedConfig<OperationAppConfig, Custom>;

interface OperationApiConfig<Options = Record<string, unknown>> {
  id: string;
  handler: (options: Options, context: OperationContext) => unknown | Promise<unknown>;
}

interface OperationAppConfig {
  id: string;
  name: string;
  icon: string;
  description?: string;
  overview: (options: Record<string, any>) => string | Component;
  options: FieldOptions[];
}

Theme Extensions

Define custom themes for the Directus admin interface.

/**
 * Define a theme extension
 * @param theme - Theme configuration object
 * @returns Theme configuration with type safety
 */
function defineTheme<T extends Theme>(theme: T): T;

interface Theme {
  name: string;
  appearance: 'light' | 'dark' | 'auto';
  rules: {
    foreground?: string;
    background?: string;
    'background-accent'?: string;
    'background-subdued'?: string;
    'background-normal'?: string;
    border?: string;
    primary?: string;
    secondary?: string;
    success?: string;
    warning?: string;
    danger?: string;
    [key: string]: string | undefined;
  };
}

Theme Usage Example:

import { defineTheme } from '@directus/extensions-sdk';

export default defineTheme({
  name: 'My Custom Theme',
  appearance: 'dark',
  rules: {
    primary: '#ff6b6b',
    secondary: '#4ecdc4',
    background: '#1a1a1a',
    foreground: '#ffffff'
  }
});

Type Definitions

Common types used across extension definitions:

type CustomConfig<T extends object> = { [K in string]: K extends keyof T ? never : unknown };
type ExtendedConfig<T extends object, C> = Prettify<T & Omit<C, keyof T>>;

interface FieldOptions {
  field: string;
  name: string;
  type: string;
  meta?: Record<string, any>;
  schema?: Record<string, any>;
}

type FieldType = 'bigInteger' | 'boolean' | 'date' | 'dateTime' | 'decimal' | 'float' | 'integer' | 'json' | 'string' | 'text' | 'time' | 'timestamp' | 'binary' | 'uuid';
type LocalType = 'standard' | 'file' | 'files' | 'm2o' | 'o2m' | 'm2m' | 'm2a' | 'presentation' | 'translations' | 'group';

type Component = any; // Vue component
type Router = any; // Express router

interface HookContext {
  database: any;
  schema: any;
  accountability: any;
  [key: string]: any;
}

interface EndpointContext {
  services: any;
  database: any;
  schema: any;
  accountability: any;
  getSchema: () => any;
  env: any;
  logger: any;
  [key: string]: any;
}

interface OperationContext {
  data: any;
  accountability: any;
  database: any;
  getSchema: () => any;
  services: any;
  env: any;
  logger: any;
  [key: string]: any;
}

interface ModuleRoute {
  name: string;
  path: string;
  component?: Component;
  redirect?: string;
  children?: ModuleRoute[];
  meta?: {
    [key: string]: any;
  };
}

interface LayoutProps<Options = any, Query = any> {
  collection: string;
  selection: any[];
  layoutOptions: Options;
  layoutQuery: Query;
  filters: any[];
  search: string;
  [key: string]: any;
}

interface User {
  id: string;
  first_name: string;
  last_name: string;
  email: string;
  role: string;
  [key: string]: any;
}

interface Permission {
  id: string;
  role: string;
  collection: string;
  action: string;
  permissions: any;
  validation: any;
  presets: any;
  fields: string[];
}