Skip to content
Open
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
28 changes: 28 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,34 @@ jobs:
- name: Run Tests
run: pnpm test

playground-integration-test:
name: Playground Integration Tests
needs: detect-changes
if: needs.detect-changes.outputs.appkit == 'true'
runs-on:
group: databricks-protected-runner-group
labels: linux-ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Install Playwright Browsers
run: pnpm --filter=dev-playground exec playwright install --with-deps chromium
- name: Build packages
run: pnpm build
- name: Run Integration Tests
run: pnpm --filter=dev-playground test:integration
env:
APPKIT_E2E_TEST: 'true'
DATABRICKS_WAREHOUSE_ID: e2e-mock
DATABRICKS_WORKSPACE_ID: e2e-mock

docs-build:
name: Docs Build
needs: detect-changes
Expand Down
12 changes: 12 additions & 0 deletions apps/dev-playground/server/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
import { analytics, createApp, server } from "@databricks/appkit";
import { WorkspaceClient } from "@databricks/sdk-experimental";
import { reconnect } from "./reconnect-plugin";
import { telemetryExamples } from "./telemetry-example-plugin";

function createMockClient() {
const client = new WorkspaceClient({
host: "http://localhost",
token: "e2e",
authType: "pat",
});
client.currentUser.me = async () => ({ id: "e2e-test-user" });
return client;
}

createApp({
plugins: [
server({ autoStart: false }),
reconnect(),
telemetryExamples(),
analytics({}),
],
...(process.env.APPKIT_E2E_TEST && { client: createMockClient() }),
}).then((appkit) => {
appkit.server
.extend((app) => {
Expand Down
4 changes: 3 additions & 1 deletion docs/docs/api/appkit/Function.createApp.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
```ts
function createApp<T>(config: {
cache?: CacheConfig;
client?: WorkspaceClient;
plugins?: T;
telemetry?: TelemetryConfig;
}): Promise<PluginMap<T>>;
Expand All @@ -20,8 +21,9 @@ Bootstraps AppKit with the provided configuration.

| Parameter | Type |
| ------ | ------ |
| `config` | \{ `cache?`: [`CacheConfig`](Interface.CacheConfig.md); `plugins?`: `T`; `telemetry?`: [`TelemetryConfig`](Interface.TelemetryConfig.md); \} |
| `config` | \{ `cache?`: [`CacheConfig`](Interface.CacheConfig.md); `client?`: `WorkspaceClient`; `plugins?`: `T`; `telemetry?`: [`TelemetryConfig`](Interface.TelemetryConfig.md); \} |
| `config.cache?` | [`CacheConfig`](Interface.CacheConfig.md) |
| `config.client?` | `WorkspaceClient` |
| `config.plugins?` | `T` |
| `config.telemetry?` | [`TelemetryConfig`](Interface.TelemetryConfig.md) |

Expand Down
23 changes: 15 additions & 8 deletions packages/appkit/src/context/service-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,13 @@ export class ServiceContext {
/**
* Initialize the service context. Should be called once at app startup.
* Safe to call multiple times - will return the same instance.
*
* @param client - Optional pre-configured WorkspaceClient to use instead
* of creating one from environment credentials.
*/
static async initialize(): Promise<ServiceContextState> {
static async initialize(
client?: WorkspaceClient,
): Promise<ServiceContextState> {
if (ServiceContext.instance) {
return ServiceContext.instance;
}
Expand All @@ -67,7 +72,7 @@ export class ServiceContext {
return ServiceContext.initPromise;
}

ServiceContext.initPromise = ServiceContext.createContext();
ServiceContext.initPromise = ServiceContext.createContext(client);
ServiceContext.instance = await ServiceContext.initPromise;
return ServiceContext.instance;
}
Expand Down Expand Up @@ -147,19 +152,21 @@ export class ServiceContext {
return getClientOptions();
}

private static async createContext(): Promise<ServiceContextState> {
const client = new WorkspaceClient({}, getClientOptions());
private static async createContext(
client?: WorkspaceClient,
): Promise<ServiceContextState> {
const wsClient = client ?? new WorkspaceClient({}, getClientOptions());

const warehouseId = ServiceContext.getWarehouseId(client);
const workspaceId = ServiceContext.getWorkspaceId(client);
const currentUser = await client.currentUser.me();
const warehouseId = ServiceContext.getWarehouseId(wsClient);
const workspaceId = ServiceContext.getWorkspaceId(wsClient);
const currentUser = await wsClient.currentUser.me();

if (!currentUser.id) {
throw ConfigurationError.resourceNotFound("Service user ID");
}

return {
client,
client: wsClient,
serviceUserId: currentUser.id,
warehouseId,
workspaceId,
Expand Down
5 changes: 4 additions & 1 deletion packages/appkit/src/core/appkit.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { WorkspaceClient } from "@databricks/sdk-experimental";
import type {
BasePlugin,
CacheConfig,
Expand Down Expand Up @@ -141,6 +142,7 @@ export class AppKit<TPlugins extends InputPluginMap> {
plugins?: T;
telemetry?: TelemetryConfig;
cache?: CacheConfig;
client?: WorkspaceClient;
} = {},
): Promise<PluginMap<T>> {
// Initialize core services
Expand All @@ -149,7 +151,7 @@ export class AppKit<TPlugins extends InputPluginMap> {

// Initialize ServiceContext for Databricks client management
// This provides the service principal client and shared resources
await ServiceContext.initialize();
await ServiceContext.initialize(config?.client);

const rawPlugins = config.plugins as T;
const preparedPlugins = AppKit.preparePlugins(rawPlugins);
Expand Down Expand Up @@ -188,6 +190,7 @@ export async function createApp<
plugins?: T;
telemetry?: TelemetryConfig;
cache?: CacheConfig;
client?: WorkspaceClient;
} = {},
): Promise<PluginMap<T>> {
return AppKit._createApp(config);
Expand Down
6 changes: 3 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.