Skip to main content
Version: Next

Frontend Extension API Reference

The @apache-superset/core package provides comprehensive APIs for frontend extensions to interact with Apache Superset. All APIs are versioned and follow semantic versioning principles.

Core APIs

Extension Context

Every extension receives a context object during activation that provides access to the extension system.

interface ExtensionContext {
// Unique extension identifier
extensionId: string;

// Extension metadata
extensionPath: string;
extensionUri: Uri;

// Storage paths
globalStorageUri: Uri;
workspaceStorageUri: Uri;

// Subscription management
subscriptions: Disposable[];

// State management
globalState: Memento;
workspaceState: Memento;

// Extension-specific APIs
registerView(viewId: string, component: React.Component): Disposable;
registerCommand(commandId: string, handler: CommandHandler): Disposable;
}

Lifecycle Methods

// Required: Called when extension is activated
export function activate(context: ExtensionContext): void | Promise<void> {
console.log('Extension activated');
}

// Optional: Called when extension is deactivated
export function deactivate(): void | Promise<void> {
console.log('Extension deactivated');
}

SQL Lab APIs

The sqlLab namespace provides APIs specific to SQL Lab functionality.

Query Management

// Get current query editor content
sqlLab.getCurrentQuery(): string | undefined

// Get active tab information
sqlLab.getCurrentTab(): Tab | undefined

// Get all open tabs
sqlLab.getTabs(): Tab[]

// Get available databases
sqlLab.getDatabases(): Database[]

// Get schemas for a database
sqlLab.getSchemas(databaseId: number): Promise<Schema[]>

// Get tables for a schema
sqlLab.getTables(databaseId: number, schema: string): Promise<Table[]>

// Insert text at cursor position
sqlLab.insertText(text: string): void

// Replace entire query
sqlLab.replaceQuery(query: string): void

// Execute current query
sqlLab.executeQuery(): Promise<QueryResult>

// Stop query execution
sqlLab.stopQuery(queryId: string): Promise<void>

Event Subscriptions

// Query execution events
sqlLab.onDidQueryRun(
listener: (event: QueryRunEvent) => void
): Disposable

sqlLab.onDidQueryComplete(
listener: (event: QueryCompleteEvent) => void
): Disposable

sqlLab.onDidQueryFail(
listener: (event: QueryFailEvent) => void
): Disposable

// Editor events
sqlLab.onDidChangeEditorContent(
listener: (content: string) => void
): Disposable

sqlLab.onDidChangeActiveTab(
listener: (tab: Tab) => void
): Disposable

// Panel events
sqlLab.onDidOpenPanel(
listener: (panel: Panel) => void
): Disposable

sqlLab.onDidClosePanel(
listener: (panel: Panel) => void
): Disposable

Types

interface Tab {
id: string;
title: string;
query: string;
database: Database;
schema?: string;
isActive: boolean;
queryId?: string;
status?: 'pending' | 'running' | 'success' | 'error';
}

interface Database {
id: number;
name: string;
backend: string;
allows_subquery: boolean;
allows_ctas: boolean;
allows_cvas: boolean;
}

interface QueryResult {
queryId: string;
status: 'success' | 'error';
data?: any[];
columns?: Column[];
error?: string;
startTime: number;
endTime: number;
rows: number;
}

Commands API

Register and execute commands within Superset.

Registration

interface CommandHandler {
execute(...args: any[]): any | Promise<any>;
isEnabled?(): boolean;
isVisible?(): boolean;
}

// Register a command
commands.registerCommand(
commandId: string,
handler: CommandHandler
): Disposable

// Register with metadata
commands.registerCommand(
commandId: string,
metadata: CommandMetadata,
handler: (...args: any[]) => any
): Disposable

interface CommandMetadata {
title: string;
category?: string;
icon?: string;
enablement?: string;
when?: string;
}

Execution

// Execute a command
commands.executeCommand<T>(
commandId: string,
...args: any[]
): Promise<T>

// Get all registered commands
commands.getCommands(): Promise<string[]>

// Check if command exists
commands.hasCommand(commandId: string): boolean

Built-in Commands

// SQL Lab commands
'sqllab.executeQuery'
'sqllab.formatQuery'
'sqllab.saveQuery'
'sqllab.shareQuery'
'sqllab.downloadResults'

// Editor commands
'editor.action.formatDocument'
'editor.action.commentLine'
'editor.action.findReferences'

// Extension commands
'extensions.installExtension'
'extensions.uninstallExtension'
'extensions.enableExtension'
'extensions.disableExtension'

UI Components

Pre-built components from @apache-superset/core for consistent UI.

Basic Components

import {
Button,
Input,
Select,
Checkbox,
Radio,
Switch,
Slider,
DatePicker,
TimePicker,
Tooltip,
Popover,
Modal,
Drawer,
Alert,
Message,
Notification,
Spin,
Progress
} from '@apache-superset/core';

Data Display

import {
Table,
List,
Card,
Collapse,
Tabs,
Tag,
Badge,
Statistic,
Timeline,
Tree,
Empty,
Result
} from '@apache-superset/core';

Form Components

import {
Form,
FormItem,
FormList,
InputNumber,
TextArea,
Upload,
Rate,
Cascader,
AutoComplete,
Mentions
} from '@apache-superset/core';

Authentication API

Access authentication and user information.

// Get current user
authentication.getCurrentUser(): User | undefined

interface User {
id: number;
username: string;
email: string;
firstName: string;
lastName: string;
roles: Role[];
isActive: boolean;
isAnonymous: boolean;
}

// Get CSRF token for API requests
authentication.getCSRFToken(): Promise<string>

// Check permissions
authentication.hasPermission(
permission: string,
resource?: string
): boolean

// Get user preferences
authentication.getPreferences(): UserPreferences

// Update preferences
authentication.setPreference(
key: string,
value: any
): Promise<void>

Storage API

Persist data across sessions.

Global Storage

// Shared across all workspaces
const globalState = context.globalState;

// Get value
const value = globalState.get<T>(key: string): T | undefined

// Set value
await globalState.update(key: string, value: any): Promise<void>

// Get all keys
globalState.keys(): readonly string[]

Workspace Storage

// Specific to current workspace
const workspaceState = context.workspaceState;

// Same API as globalState
workspaceState.get<T>(key: string): T | undefined
workspaceState.update(key: string, value: any): Promise<void>
workspaceState.keys(): readonly string[]

Secrets Storage

// Secure storage for sensitive data
secrets.store(key: string, value: string): Promise<void>
secrets.get(key: string): Promise<string | undefined>
secrets.delete(key: string): Promise<void>

Events API

Subscribe to and emit custom events.

// Create an event emitter
const onDidChange = new EventEmitter<ChangeEvent>();

// Expose as event
export const onChange = onDidChange.event;

// Fire event
onDidChange.fire({
type: 'update',
data: newData
});

// Subscribe to event
const disposable = onChange((event) => {
console.log('Changed:', event);
});

// Cleanup
disposable.dispose();

Window API

Interact with the UI window.

Notifications

// Show info message
window.showInformationMessage(
message: string,
...items: string[]
): Promise<string | undefined>

// Show warning
window.showWarningMessage(
message: string,
...items: string[]
): Promise<string | undefined>

// Show error
window.showErrorMessage(
message: string,
...items: string[]
): Promise<string | undefined>

// Show with options
window.showInformationMessage(
message: string,
options: MessageOptions,
...items: MessageItem[]
): Promise<MessageItem | undefined>

interface MessageOptions {
modal?: boolean;
detail?: string;
}

Input Dialogs

// Show input box
window.showInputBox(
options?: InputBoxOptions
): Promise<string | undefined>

interface InputBoxOptions {
title?: string;
prompt?: string;
placeHolder?: string;
value?: string;
password?: boolean;
validateInput?(value: string): string | null;
}

// Show quick pick
window.showQuickPick(
items: string[] | QuickPickItem[],
options?: QuickPickOptions
): Promise<string | QuickPickItem | undefined>

interface QuickPickOptions {
title?: string;
placeHolder?: string;
canPickMany?: boolean;
matchOnDescription?: boolean;
matchOnDetail?: boolean;
}

Progress

// Show progress
window.withProgress<T>(
options: ProgressOptions,
task: (progress: Progress<{message?: string}>) => Promise<T>
): Promise<T>

interface ProgressOptions {
location: ProgressLocation;
title?: string;
cancellable?: boolean;
}

// Example usage
await window.withProgress(
{
location: ProgressLocation.Notification,
title: "Processing",
cancellable: true
},
async (progress) => {
progress.report({ message: 'Step 1...' });
await step1();
progress.report({ message: 'Step 2...' });
await step2();
}
);

Workspace API

Access workspace information and configuration.

// Get workspace folders
workspace.workspaceFolders: readonly WorkspaceFolder[]

// Get configuration
workspace.getConfiguration(
section?: string
): WorkspaceConfiguration

// Update configuration
workspace.getConfiguration('myExtension')
.update('setting', value, ConfigurationTarget.Workspace)

// Watch for configuration changes
workspace.onDidChangeConfiguration(
listener: (e: ConfigurationChangeEvent) => void
): Disposable

// File system operations
workspace.fs.readFile(uri: Uri): Promise<Uint8Array>
workspace.fs.writeFile(uri: Uri, content: Uint8Array): Promise<void>
workspace.fs.delete(uri: Uri): Promise<void>
workspace.fs.rename(oldUri: Uri, newUri: Uri): Promise<void>
workspace.fs.copy(source: Uri, destination: Uri): Promise<void>
workspace.fs.createDirectory(uri: Uri): Promise<void>
workspace.fs.readDirectory(uri: Uri): Promise<[string, FileType][]>
workspace.fs.stat(uri: Uri): Promise<FileStat>

HTTP Client API

Make HTTP requests from extensions.

import { api } from '@apache-superset/core';

// GET request
const response = await api.get('/api/v1/chart/');

// POST request
const response = await api.post('/api/v1/chart/', {
data: chartData
});

// PUT request
const response = await api.put('/api/v1/chart/123', {
data: updatedData
});

// DELETE request
const response = await api.delete('/api/v1/chart/123');

// Custom headers
const response = await api.get('/api/v1/chart/', {
headers: {
'X-Custom-Header': 'value'
}
});

// Query parameters
const response = await api.get('/api/v1/chart/', {
params: {
page: 1,
page_size: 20
}
});

Theming API

Access and customize theme settings.

// Get current theme
theme.getActiveTheme(): Theme

interface Theme {
name: string;
isDark: boolean;
colors: ThemeColors;
typography: Typography;
spacing: Spacing;
}

// Listen for theme changes
theme.onDidChangeTheme(
listener: (theme: Theme) => void
): Disposable

// Get theme colors
const colors = theme.colors;
colors.primary
colors.success
colors.warning
colors.error
colors.info
colors.text
colors.background
colors.border

Disposable Pattern

Manage resource cleanup consistently.

interface Disposable {
dispose(): void;
}

// Create a disposable
class MyDisposable implements Disposable {
dispose() {
// Cleanup logic
}
}

// Combine disposables
const composite = Disposable.from(
disposable1,
disposable2,
disposable3
);

// Dispose all at once
composite.dispose();

// Use in extension
export function activate(context: ExtensionContext) {
// All disposables added here are cleaned up on deactivation
context.subscriptions.push(
registerCommand(...),
registerView(...),
onDidChange(...)
);
}

Type Definitions

Complete TypeScript definitions are available:

import type {
ExtensionContext,
Disposable,
Event,
EventEmitter,
Uri,
Command,
QuickPickItem,
InputBoxOptions,
Progress,
CancellationToken
} from '@apache-superset/core';

Version Compatibility

The API follows semantic versioning:

// Check API version
const version = superset.version;

// Version components
version.major // Breaking changes
version.minor // New features
version.patch // Bug fixes

// Check minimum version
if (version.major < 1) {
throw new Error('Requires Superset API v1.0.0 or higher');
}

Migration Guide

From v0.x to v1.0

// Before (v0.x)
sqlLab.runQuery(query);

// After (v1.0)
sqlLab.executeQuery();

// Before (v0.x)
core.registerPanel(id, component);

// After (v1.0)
context.registerView(id, component);

Best Practices

Error Handling

export async function activate(context: ExtensionContext) {
try {
await initializeExtension();
} catch (error) {
console.error('Failed to initialize:', error);
window.showErrorMessage(
`Extension failed to activate: ${error.message}`
);
}
}

Resource Management

// Always use disposables
const disposables: Disposable[] = [];

disposables.push(
commands.registerCommand(...),
sqlLab.onDidQueryRun(...),
workspace.onDidChangeConfiguration(...)
);

// Cleanup in deactivate
export function deactivate() {
disposables.forEach(d => d.dispose());
}

Type Safety

// Use type guards
function isDatabase(obj: any): obj is Database {
return obj && typeof obj.id === 'number' && typeof obj.name === 'string';
}

// Use generics
function getValue<T>(key: string, defaultValue: T): T {
return context.globalState.get(key) ?? defaultValue;
}