# 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[​](#static-vs-runtime-resource-requirements "Direct link to 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[​](#examples "Direct link to Examples")

```typescript
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;
}

```

```typescript
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-parameters "Direct link to Type Parameters")

| Type Parameter                                                                                  | Default type                                                                |
| ----------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| `TConfig` *extends* [`BasePluginConfig`](./docs/api/appkit/Interface.BasePluginConfig.md) | [`BasePluginConfig`](./docs/api/appkit/Interface.BasePluginConfig.md) |

## Implements[​](#implements "Direct link to Implements")

* `BasePlugin`

## Constructors[​](#constructors "Direct link to Constructors")

### Constructor[​](#constructor "Direct link to Constructor")

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

```

#### Parameters[​](#parameters "Direct link to Parameters")

| Parameter | Type      |
| --------- | --------- |
| `config`  | `TConfig` |

#### Returns[​](#returns "Direct link to Returns")

`Plugin`<`TConfig`>

## Properties[​](#properties "Direct link to Properties")

### app[​](#app "Direct link to app")

```ts
protected app: AppManager;

```

***

### cache[​](#cache "Direct link to cache")

```ts
protected cache: CacheManager;

```

***

### config[​](#config "Direct link to config")

```ts
protected config: TConfig;

```

***

### context?[​](#context "Direct link to context?")

```ts
protected optional context: PluginContext;

```

***

### devFileReader[​](#devfilereader "Direct link to devFileReader")

```ts
protected devFileReader: DevFileReader;

```

***

### isReady[​](#isready "Direct link to isReady")

```ts
protected isReady: boolean = false;

```

***

### name[​](#name "Direct link to name")

```ts
name: string;

```

Plugin name identifier.

#### Implementation of[​](#implementation-of "Direct link to Implementation of")

```ts
BasePlugin.name

```

***

### streamManager[​](#streammanager "Direct link to streamManager")

```ts
protected streamManager: StreamManager;

```

***

### telemetry[​](#telemetry "Direct link to telemetry")

```ts
protected telemetry: ITelemetry;

```

***

### phase[​](#phase "Direct link to phase")

```ts
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[​](#methods "Direct link to Methods")

### abortActiveOperations()[​](#abortactiveoperations "Direct link to abortActiveOperations()")

```ts
abortActiveOperations(): void;

```

#### Returns[​](#returns-1 "Direct link to Returns")

`void`

#### Implementation of[​](#implementation-of-1 "Direct link to Implementation of")

```ts
BasePlugin.abortActiveOperations

```

***

### asUser()[​](#asuser "Direct link to asUser()")

```ts
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[​](#parameters-1 "Direct link to Parameters")

| Parameter | Type      | Description                                              |
| --------- | --------- | -------------------------------------------------------- |
| `req`     | `Request` | The Express request containing the user token in headers |

#### Returns[​](#returns-2 "Direct link to Returns")

`this`

A proxied plugin instance that executes as the user

#### Throws[​](#throws "Direct link to 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 "Direct link to attachContext()")

```ts
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[​](#parameters-2 "Direct link to Parameters")

| Parameter               | Type                                                               |
| ----------------------- | ------------------------------------------------------------------ |
| `deps`                  | { `context?`: `unknown`; `telemetryConfig?`: `TelemetryOptions`; } |
| `deps.context?`         | `unknown`                                                          |
| `deps.telemetryConfig?` | `TelemetryOptions`                                                 |

#### Returns[​](#returns-3 "Direct link to Returns")

`void`

#### Implementation of[​](#implementation-of-2 "Direct link to Implementation of")

```ts
BasePlugin.attachContext

```

***

### clientConfig()[​](#clientconfig "Direct link to clientConfig()")

```ts
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[​](#returns-4 "Direct link to Returns")

`Record`<`string`, `unknown`>

#### Example[​](#example "Direct link to Example")

```ts
// 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[​](#implementation-of-3 "Direct link to Implementation of")

```ts
BasePlugin.clientConfig

```

***

### execute()[​](#execute "Direct link to execute()")

```ts
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](./docs/api/appkit/TypeAlias.ExecutionResult.md) 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-parameters-1 "Direct link to Type Parameters")

| Type Parameter |
| -------------- |
| `T`            |

#### Parameters[​](#parameters-3 "Direct link to Parameters")

| Parameter  | Type                                         |
| ---------- | -------------------------------------------- |
| `fn`       | (`signal?`: `AbortSignal`) => `Promise`<`T`> |
| `options`  | `PluginExecutionSettings`                    |
| `userKey?` | `string`                                     |

#### Returns[​](#returns-5 "Direct link to Returns")

`Promise`<[`ExecutionResult`](./docs/api/appkit/TypeAlias.ExecutionResult.md)<`T`>>

***

### executeStream()[​](#executestream "Direct link to executeStream()")

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

```

#### Type Parameters[​](#type-parameters-2 "Direct link to Type Parameters")

| Type Parameter |
| -------------- |
| `T`            |

#### Parameters[​](#parameters-4 "Direct link to Parameters")

| Parameter  | Type                                                                                      |
| ---------- | ----------------------------------------------------------------------------------------- |
| `res`      | `IAppResponse`                                                                            |
| `fn`       | `StreamExecuteHandler`<`T`>                                                               |
| `options`  | [`StreamExecutionSettings`](./docs/api/appkit/Interface.StreamExecutionSettings.md) |
| `userKey?` | `string`                                                                                  |

#### Returns[​](#returns-6 "Direct link to Returns")

`Promise`<`void`>

***

### exports()[​](#exports "Direct link to exports()")

```ts
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[​](#returns-7 "Direct link to Returns")

`unknown`

#### Example[​](#example-1 "Direct link to Example")

```ts
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[​](#implementation-of-4 "Direct link to Implementation of")

```ts
BasePlugin.exports

```

***

### getEndpoints()[​](#getendpoints "Direct link to getEndpoints()")

```ts
getEndpoints(): PluginEndpointMap;

```

#### Returns[​](#returns-8 "Direct link to Returns")

`PluginEndpointMap`

#### Implementation of[​](#implementation-of-5 "Direct link to Implementation of")

```ts
BasePlugin.getEndpoints

```

***

### getSkipBodyParsingPaths()[​](#getskipbodyparsingpaths "Direct link to getSkipBodyParsingPaths()")

```ts
getSkipBodyParsingPaths(): ReadonlySet<string>;

```

#### Returns[​](#returns-9 "Direct link to Returns")

`ReadonlySet`<`string`>

#### Implementation of[​](#implementation-of-6 "Direct link to Implementation of")

```ts
BasePlugin.getSkipBodyParsingPaths

```

***

### injectRoutes()[​](#injectroutes "Direct link to injectRoutes()")

```ts
injectRoutes(_: Router): void;

```

#### Parameters[​](#parameters-5 "Direct link to Parameters")

| Parameter | Type     |
| --------- | -------- |
| `_`       | `Router` |

#### Returns[​](#returns-10 "Direct link to Returns")

`void`

#### Implementation of[​](#implementation-of-7 "Direct link to Implementation of")

```ts
BasePlugin.injectRoutes

```

***

### registerEndpoint()[​](#registerendpoint "Direct link to registerEndpoint()")

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

```

#### Parameters[​](#parameters-6 "Direct link to Parameters")

| Parameter | Type     |
| --------- | -------- |
| `name`    | `string` |
| `path`    | `string` |

#### Returns[​](#returns-11 "Direct link to Returns")

`void`

***

### resolveUserId()[​](#resolveuserid "Direct link to resolveUserId()")

```ts
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[​](#parameters-7 "Direct link to Parameters")

| Parameter | Type      |
| --------- | --------- |
| `req`     | `Request` |

#### Returns[​](#returns-12 "Direct link to Returns")

`string`

#### Throws[​](#throws-1 "Direct link to Throws")

AuthenticationError in production when no user header is present.

***

### route()[​](#route "Direct link to route()")

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

```

#### Type Parameters[​](#type-parameters-3 "Direct link to Type Parameters")

| Type Parameter |
| -------------- |
| `_TResponse`   |

#### Parameters[​](#parameters-8 "Direct link to Parameters")

| Parameter | Type          |
| --------- | ------------- |
| `router`  | `Router`      |
| `config`  | `RouteConfig` |

#### Returns[​](#returns-13 "Direct link to Returns")

`void`

***

### setup()[​](#setup "Direct link to setup()")

```ts
setup(): Promise<void>;

```

#### Returns[​](#returns-14 "Direct link to Returns")

`Promise`<`void`>

#### Implementation of[​](#implementation-of-8 "Direct link to Implementation of")

```ts
BasePlugin.setup

```
