Type-safe functions for defining different types of Directus extensions. Each function provides proper TypeScript support and validation for extension configurations.
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'
}
}
]
});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;
}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>;
}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;
}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[];
}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>;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;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[];
}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'
}
});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[];
}