Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions apps/dev-playground/server/lakebase-examples-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { getUsernameWithApiLookup, Plugin, toPlugin } from "@databricks/appkit";
import {
getUsernameWithApiLookup,
Plugin,
type PluginManifest,
toPlugin,
} from "@databricks/appkit";
import type { IAppRouter } from "shared";
import * as drizzleExample from "./lakebase-examples/drizzle-example";
import * as rawExample from "./lakebase-examples/raw-driver-example";
Expand All @@ -19,7 +24,6 @@ import * as typeormExample from "./lakebase-examples/typeorm-example";
*/

export class LakebaseExamplesPlugin extends Plugin {
public name = "lakebase-examples";
protected envVars: string[] = [];

static manifest = {
Expand All @@ -30,7 +34,7 @@ export class LakebaseExamplesPlugin extends Plugin {
required: [],
optional: [],
},
};
} satisfies PluginManifest<"lakebase-examples">;

async setup() {
// Check if Lakebase is configured
Expand Down Expand Up @@ -80,8 +84,4 @@ export class LakebaseExamplesPlugin extends Plugin {
}
}

export const lakebaseExamples = toPlugin<
typeof LakebaseExamplesPlugin,
Record<string, never>,
"lakebase-examples"
>(LakebaseExamplesPlugin, "lakebase-examples");
export const lakebaseExamples = toPlugin(LakebaseExamplesPlugin);
12 changes: 3 additions & 9 deletions apps/dev-playground/server/reconnect-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Plugin, toPlugin } from "@databricks/appkit";
import { Plugin, type PluginManifest, toPlugin } from "@databricks/appkit";
import type { IAppRouter, StreamExecutionSettings } from "shared";

interface ReconnectResponse {
Expand All @@ -14,8 +14,6 @@ interface ReconnectStreamResponse {
}

export class ReconnectPlugin extends Plugin {
public name = "reconnect";

static manifest = {
name: "reconnect",
displayName: "Reconnect Plugin",
Expand All @@ -24,7 +22,7 @@ export class ReconnectPlugin extends Plugin {
required: [],
optional: [],
},
};
} satisfies PluginManifest<"reconnect">;

injectRoutes(router: IAppRouter): void {
this.route<ReconnectResponse>(router, {
Expand Down Expand Up @@ -84,8 +82,4 @@ export class ReconnectPlugin extends Plugin {
}
}

export const reconnect = toPlugin<
typeof ReconnectPlugin,
Record<string, never>,
"reconnect"
>(ReconnectPlugin, "reconnect");
export const reconnect = toPlugin(ReconnectPlugin);
11 changes: 3 additions & 8 deletions apps/dev-playground/server/telemetry-example-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
type Counter,
type Histogram,
Plugin,
type PluginManifest,
SeverityNumber,
type Span,
SpanStatusCode,
Expand All @@ -16,8 +17,6 @@ import {
import type { Request, Response, Router } from "express";

class TelemetryExamples extends Plugin {
public name = "telemetry-examples" as const;

static manifest = {
name: "telemetry-examples",
displayName: "Telemetry Examples Plugin",
Expand All @@ -26,7 +25,7 @@ class TelemetryExamples extends Plugin {
required: [],
optional: [],
},
};
} satisfies PluginManifest<"telemetry-examples">;

private requestCounter: Counter;
private durationHistogram: Histogram;
Expand Down Expand Up @@ -522,8 +521,4 @@ class TelemetryExamples extends Plugin {
}
}

export const telemetryExamples = toPlugin<
typeof TelemetryExamples,
BasePluginConfig,
"telemetryExamples"
>(TelemetryExamples, "telemetryExamples");
export const telemetryExamples = toPlugin(TelemetryExamples);
2 changes: 2 additions & 0 deletions apps/dev-playground/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
"compilerOptions": {
"baseUrl": ".",
"outDir": "./build",
"declaration": false,
"declarationMap": false,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
Expand Down
5 changes: 1 addition & 4 deletions docs/docs/api/appkit/Class.Plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ const myManifest: PluginManifest = {

class MyPlugin extends Plugin<MyConfig> {
static manifest = myManifest;
name = 'myPlugin';
}
```

Expand All @@ -58,8 +57,7 @@ const myManifest: PluginManifest = {
};

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

// Runtime method: converts optional resources to required based on config
static getResourceRequirements(config: MyConfig) {
Expand Down Expand Up @@ -327,7 +325,6 @@ and adds `asUser(req)` for user-scoped execution.

```ts
class MyPlugin extends Plugin {
name = "myPlugin";
private getData() { return []; }

exports() {
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/api/appkit/Class.ResourceRegistry.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ For each plugin, loads its manifest (required) and runtime resource requirements

| Parameter | Type | Description |
| ------ | ------ | ------ |
| `rawPlugins` | `PluginData`\<`PluginConstructor`, `unknown`, `string`\>[] | Array of plugin data entries from createApp configuration |
| `rawPlugins` | [`PluginData`](TypeAlias.PluginData.md)\<`PluginConstructor`, `unknown`, `string`\>[] | Array of plugin data entries from createApp configuration |

#### Returns

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/api/appkit/Function.createApp.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ with an `asUser(req)` method for user-scoped execution.

| Type Parameter |
| ------ |
| `T` *extends* `PluginData`\<`PluginConstructor`, `unknown`, `string`\>[] |
| `T` *extends* [`PluginData`](TypeAlias.PluginData.md)\<`PluginConstructor`, `unknown`, `string`\>[] |

## Parameters

Expand Down
12 changes: 9 additions & 3 deletions docs/docs/api/appkit/Interface.PluginManifest.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# Interface: PluginManifest
# Interface: PluginManifest\<TName\>

Plugin manifest that declares metadata and resource requirements.
Attached to plugin classes as a static property.

## Type Parameters

| Type Parameter | Default type |
| ------ | ------ |
| `TName` *extends* `string` | `string` |

## Properties

### author?
Expand Down Expand Up @@ -83,10 +89,10 @@ optional license: string;
### name

```ts
name: string;
name: TName;
```

Plugin identifier (matches plugin.name)
Plugin identifier — the single source of truth for the plugin's name

***

Expand Down
41 changes: 41 additions & 0 deletions docs/docs/api/appkit/TypeAlias.PluginData.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Type Alias: PluginData\<T, U, N\>

```ts
type PluginData<T, U, N> = {
config: U;
name: N;
plugin: T;
};
```

## Type Parameters

| Type Parameter |
| ------ |
| `T` |
| `U` |
| `N` |

## Properties

### config

```ts
config: U;
```

***

### name

```ts
name: N;
```

***

### plugin

```ts
plugin: T;
```
2 changes: 1 addition & 1 deletion docs/docs/api/appkit/TypeAlias.ToPlugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ type ToPlugin<T, U, N> = (config?: U) => PluginData<T, U, N>;

## Returns

`PluginData`\<`T`, `U`, `N`\>
[`PluginData`](TypeAlias.PluginData.md)\<`T`, `U`, `N`\>
1 change: 1 addition & 0 deletions docs/docs/api/appkit/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ plugin architecture, and React integration.
| ------ | ------ |
| [ConfigSchema](TypeAlias.ConfigSchema.md) | Configuration schema definition for plugin config. Re-exported from the standard JSON Schema Draft 7 types. |
| [IAppRouter](TypeAlias.IAppRouter.md) | Express router type for plugin route registration |
| [PluginData](TypeAlias.PluginData.md) | - |
| [ResourcePermission](TypeAlias.ResourcePermission.md) | Union of all possible permission levels across all resource types. |
| [ToPlugin](TypeAlias.ToPlugin.md) | - |

Expand Down
5 changes: 5 additions & 0 deletions docs/docs/api/appkit/typedoc-sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ const typedocSidebar: SidebarsConfig = {
id: "api/appkit/TypeAlias.IAppRouter",
label: "IAppRouter"
},
{
type: "doc",
id: "api/appkit/TypeAlias.PluginData",
label: "PluginData"
},
{
type: "doc",
id: "api/appkit/TypeAlias.ResourcePermission",
Expand Down
17 changes: 4 additions & 13 deletions docs/docs/plugins/custom-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,10 @@ For a deeper understanding of the plugin structure, read on.
Extend the [`Plugin`](../api/appkit/Class.Plugin.md) class and export with `toPlugin()`:

```typescript
import { Plugin, toPlugin } from "@databricks/appkit";
import { Plugin, toPlugin, type PluginManifest } from "@databricks/appkit";
import type express from "express";

class MyPlugin extends Plugin {
name = "myPlugin";

// Define resource requirements in the static manifest
static manifest = {
name: "myPlugin",
displayName: "My Plugin",
Expand All @@ -44,7 +41,7 @@ class MyPlugin extends Plugin {
],
optional: []
}
};
} satisfies PluginManifest<"myPlugin">;

async setup() {
// Initialize your plugin
Expand All @@ -59,17 +56,13 @@ class MyPlugin extends Plugin {
}

exports() {
// an object with the methods from this plugin to expose
return {
myCustomMethod: this.myCustomMethod
}
}
}

export const myPlugin = toPlugin<typeof MyPlugin, Record<string, never>, "myPlugin">(
MyPlugin,
"myPlugin",
);
export const myPlugin = toPlugin(MyPlugin);
```

## Config-dependent resources
Expand All @@ -84,8 +77,6 @@ interface MyPluginConfig extends BasePluginConfig {
}

class MyPlugin extends Plugin<MyPluginConfig> {
name = "myPlugin";

static manifest = {
name: "myPlugin",
displayName: "My Plugin",
Expand All @@ -99,7 +90,7 @@ class MyPlugin extends Plugin<MyPluginConfig> {
{ type: "database", alias: "cache", resourceKey: "cache", description: "Query result caching (if enabled)", permission: "CAN_CONNECT_AND_CREATE", fields: { instance_name: { env: "DATABRICKS_CACHE_INSTANCE" }, database_name: { env: "DATABRICKS_CACHE_DB" } } }
]
}
};
} satisfies PluginManifest<"myPlugin">;

// Runtime: Convert optional resources to required based on config
static getResourceRequirements(config: MyPluginConfig) {
Expand Down
1 change: 1 addition & 0 deletions packages/appkit/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type {
BasePluginConfig,
CacheConfig,
IAppRouter,
PluginData,
StreamExecutionSettings,
} from "shared";
export { isSQLTypeMarker, sql } from "shared";
Expand Down
10 changes: 5 additions & 5 deletions packages/appkit/src/plugin/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ const EXCLUDED_FROM_PROXY = new Set([
*
* class MyPlugin extends Plugin<MyConfig> {
* static manifest = myManifest;
* name = 'myPlugin';
* }
* ```
*
Expand All @@ -117,8 +116,7 @@ const EXCLUDED_FROM_PROXY = new Set([
* };
*
* class MyPlugin extends Plugin<MyConfig> {
* static manifest = myManifest;
* name = 'myPlugin';
* static manifest = myManifest<"myPlugin">;
*
* // Runtime method: converts optional resources to required based on config
* static getResourceRequirements(config: MyConfig) {
Expand Down Expand Up @@ -171,7 +169,10 @@ export abstract class Plugin<
name: string;

constructor(protected config: TConfig) {
this.name = config.name ?? "plugin";
this.name =
config.name ??
(this.constructor as { manifest?: { name: string } }).manifest?.name ??
"plugin";
this.telemetry = TelemetryManager.getProvider(this.name, config.telemetry);
this.streamManager = new StreamManager();
this.cache = CacheManager.getInstanceSync();
Expand Down Expand Up @@ -207,7 +208,6 @@ export abstract class Plugin<
* @example
* ```ts
* class MyPlugin extends Plugin {
* name = "myPlugin";
* private getData() { return []; }
*
* exports() {
Expand Down
18 changes: 11 additions & 7 deletions packages/appkit/src/plugin/to-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import type { PluginData, ToPlugin } from "shared";
import type { PluginConstructor, PluginData, ToPlugin } from "shared";

/**
* Wraps a plugin class so it can be passed to createApp with optional config.
* Infers config type from the constructor and plugin name from the static `name` property.
*
* @internal
*/
export function toPlugin<T, U, N extends string>(
export function toPlugin<T extends PluginConstructor>(
plugin: T,
name: N,
): ToPlugin<T, U, N> {
return (config: U = {} as U): PluginData<T, U, N> => ({
): ToPlugin<T, ConstructorParameters<T>[0], T["manifest"]["name"]> {
type Config = ConstructorParameters<T>[0];
type Name = T["manifest"]["name"];
return (config: Config = {} as Config): PluginData<T, Config, Name> => ({
plugin: plugin as T,
config: config as U,
name,
config: config as Config,
name: plugin.manifest.name as Name,
});
}
Loading
Loading