Skip to main content

Abstract Class: Plugin\<TConfig\>

Abstract Class: Plugin<TConfig>

Base abstract class for creating AppKit plugins.

All plugins must declare a static manifest property with their metadata and resource requirements. The manifest defines:

  • required resources: Always needed for the plugin to function
  • optional resources: May be needed depending on plugin configuration

Static vs Runtime Resource Requirements

The manifest is static and doesn't know the plugin's runtime configuration. For resources that become required based on config options, plugins can implement a static getResourceRequirements(config) method.

At runtime, this method is called with the actual config to determine which "optional" resources should be treated as "required".

Examples

import { Plugin, toPlugin, PluginManifest, ResourceType } from '@databricks/appkit';

const myManifest: PluginManifest = {
  name: 'myPlugin',
  displayName: 'My Plugin',
  description: 'Does something awesome',
  resources: {
    required: [
      { type: ResourceType.SQL_WAREHOUSE, alias: 'warehouse', ... }
    ],
    optional: []
  }
};

class MyPlugin extends Plugin<MyConfig> {
  static manifest = myManifest;
}
interface MyConfig extends BasePluginConfig {
  enableCaching?: boolean;
}

const myManifest: PluginManifest = {
  name: 'myPlugin',
  resources: {
    required: [
      { type: ResourceType.SQL_WAREHOUSE, alias: 'warehouse', ... }
    ],
    optional: [
      // Database is optional in the static manifest
      { type: ResourceType.DATABASE, alias: 'cache', description: 'Required if caching enabled', ... }
    ]
  }
};

class MyPlugin extends Plugin<MyConfig> {
  static manifest = myManifest<"myPlugin">;

  // Runtime method: converts optional resources to required based on config
  static getResourceRequirements(config: MyConfig) {
    const resources = [];
    if (config.enableCaching) {
      // When caching is enabled, Database becomes required
      resources.push({
        type: ResourceType.DATABASE,
        alias: 'cache',
        resourceKey: 'database',
        description: 'Cache storage for query results',
        permission: 'CAN_CONNECT_AND_CREATE',
        fields: {
          instance_name: { env: 'DATABRICKS_CACHE_INSTANCE' },
          database_name: { env: 'DATABRICKS_CACHE_DB' },
        },
        required: true  // Mark as required at runtime
      });
    }
    return resources;
  }
}

Type Parameters

Type ParameterDefault type
TConfig extends BasePluginConfigBasePluginConfig

Implements

  • BasePlugin

Constructors

Constructor

new Plugin<TConfig>(config: TConfig): Plugin<TConfig>;

Parameters

ParameterType
configTConfig

Returns

Plugin<TConfig>

Properties

app

protected app: AppManager;

cache

protected cache: CacheManager;

config

protected config: TConfig;

context?

protected optional context: PluginContext;

devFileReader

protected devFileReader: DevFileReader;

isReady

protected isReady: boolean = false;

name

name: string;

Plugin name identifier.

Implementation of

BasePlugin.name

streamManager

protected streamManager: StreamManager;

telemetry

protected telemetry: ITelemetry;

phase

static phase: PluginPhase = "normal";

Plugin initialization phase.

  • 'core': Initialized first (e.g., config plugins)
  • 'normal': Initialized second (most plugins)
  • 'deferred': Initialized last (e.g., server plugin)

Methods

abortActiveOperations()

abortActiveOperations(): void;

Cancel in-flight work (abort signals, SSE streams). Runs in the first phase of graceful shutdown, BEFORE any plugin's shutdown() hook — so it must not tear down shared resources (e.g. connection pools) that other plugins' hooks may still need. Put teardown in shutdown().

Returns

void

Implementation of

BasePlugin.abortActiveOperations

asUser()

asUser(req: Request): this;

Execute operations using the user's identity from the request. Returns a proxy of this plugin where all method calls execute with the user's Databricks credentials instead of the service principal.

Parameters

ParameterTypeDescription
reqRequestThe Express request containing the user token in headers

Returns

this

A proxied plugin instance that executes as the user

Throws

AuthenticationError if user token is not available in request headers (production only). In development mode (NODE_ENV=development), skips user impersonation instead of throwing.


attachContext()

attachContext(deps: {
  context?: unknown;
  telemetryConfig?: TelemetryOptions;
}): void;

Binds runtime dependencies (telemetry provider, cache, plugin context) to this plugin. Called by AppKit._createApp after construction and before setup(). Idempotent: safe to call if the constructor already bound them eagerly. Kept separate so factories can eagerly construct plugin instances without running this before TelemetryManager.initialize() / CacheManager.getInstance() have run.

Parameters

ParameterType
deps{ context?: unknown; telemetryConfig?: TelemetryOptions; }
deps.context?unknown
deps.telemetryConfig?TelemetryOptions

Returns

void

Implementation of

BasePlugin.attachContext

clientConfig()

clientConfig(): Record<string, unknown>;

Returns startup config to expose to the client. Override this to surface server-side values that are safe to publish to the frontend, such as feature flags, resource IDs, or other app boot settings.

This runs once when the server starts, so it should not depend on request-scoped or user-specific state.

String values that match non-public environment variables are redacted unless you intentionally expose them via a matching PUBLIC_APPKIT_ env var.

Values must be JSON-serializable plain data (no functions, Dates, classes, Maps, Sets, BigInts, or circular references). By default returns an empty object (plugin contributes nothing to client config).

On the client, read the config with the usePluginClientConfig hook (React) or the getPluginClientConfig function (vanilla JS), both from @databricks/appkit-ui.

Returns

Record<string, unknown>

Example

// Server — plugin definition
class MyPlugin extends Plugin<MyConfig> {
  clientConfig() {
    return {
      warehouseId: this.config.warehouseId,
      features: { darkMode: true },
    };
  }
}

// Client — React component
import { usePluginClientConfig } from "@databricks/appkit-ui/react";

interface MyPluginConfig { warehouseId: string; features: { darkMode: boolean } }

const config = usePluginClientConfig<MyPluginConfig>("myPlugin");
config.warehouseId; // "abc-123"

// Client — vanilla JS
import { getPluginClientConfig } from "@databricks/appkit-ui/js";

const config = getPluginClientConfig<MyPluginConfig>("myPlugin");

Implementation of

BasePlugin.clientConfig

execute()

protected execute<T>(
   fn: (signal?: AbortSignal) => Promise<T>, 
   options: PluginExecutionSettings, 
userKey?: string): Promise<ExecutionResult<T>>;

Execute a function with the plugin's interceptor chain.

Returns an ExecutionResult discriminated union:

  • { ok: true, data: T } on success
  • { ok: false, status: number, message: string } on failure

Errors are never thrown — the method is production-safe.

Type Parameters

Type Parameter
T

Parameters

ParameterType
fn(signal?: AbortSignal) => Promise<T>
optionsPluginExecutionSettings
userKey?string

Returns

Promise<ExecutionResult<T>>


executeStream()

protected executeStream<T>(
   res: IAppResponse, 
   fn: StreamExecuteHandler<T>, 
   options: StreamExecutionSettings, 
userKey?: string): Promise<void>;

Type Parameters

Type Parameter
T

Parameters

ParameterType
resIAppResponse
fnStreamExecuteHandler<T>
optionsStreamExecutionSettings
userKey?string

Returns

Promise<void>


exports()

exports(): unknown;

Returns the public exports for this plugin. Override this to define a custom public API. By default, returns an empty object.

The returned object becomes the plugin's public API on the AppKit instance (e.g. appkit.myPlugin.method()). AppKit automatically binds method context and adds asUser(req) for user-scoped execution.

Returns

unknown

Example

class MyPlugin extends Plugin {
  private getData() { return []; }

  exports() {
    return { getData: this.getData };
  }
}

// After registration:
const appkit = await createApp({ plugins: [myPlugin()] });
appkit.myPlugin.getData();

Implementation of

BasePlugin.exports

getEndpoints()

getEndpoints(): PluginEndpointMap;

Returns

PluginEndpointMap

Implementation of

BasePlugin.getEndpoints

getSkipBodyParsingPaths()

getSkipBodyParsingPaths(): ReadonlySet<string>;

Returns

ReadonlySet<string>

Implementation of

BasePlugin.getSkipBodyParsingPaths

injectRoutes()

injectRoutes(_: Router): void;

Parameters

ParameterType
_Router

Returns

void

Implementation of

BasePlugin.injectRoutes

registerEndpoint()

protected registerEndpoint(name: string, path: string): void;

Parameters

ParameterType
namestring
pathstring

Returns

void


resolveUserId()

protected resolveUserId(req: Request): string;

Resolve the effective user ID from a request.

Returns the x-forwarded-user header when present. In development mode (NODE_ENV=development) falls back to the current context user ID so that callers outside an active runInUserContext scope still get a consistent value.

Parameters

ParameterType
reqRequest

Returns

string

Throws

AuthenticationError in production when no user header is present.


route()

protected route<_TResponse>(router: Router, config: RouteConfig): void;

Type Parameters

Type Parameter
_TResponse

Parameters

ParameterType
routerRouter
configRouteConfig

Returns

void


setup()

setup(): Promise<void>;

Returns

Promise<void>

Implementation of

BasePlugin.setup

Databricks Developer Hub

Ready to ship your next agentic app in minutes?

Read docs