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.
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; }
// 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'); }
The sqlLab namespace provides APIs specific to SQL Lab functionality.
// 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>
// 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
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; }
Register and execute commands within Superset.
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; }
// 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
// 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'
Pre-built components from @apache-superset/core for consistent UI.
import { Button, Input, Select, Checkbox, Radio, Switch, Slider, DatePicker, TimePicker, Tooltip, Popover, Modal, Drawer, Alert, Message, Notification, Spin, Progress } from '@apache-superset/core';
import { Table, List, Card, Collapse, Tabs, Tag, Badge, Statistic, Timeline, Tree, Empty, Result } from '@apache-superset/core';
import { Form, FormItem, FormList, InputNumber, TextArea, Upload, Rate, Cascader, AutoComplete, Mentions } from '@apache-superset/core';
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>
Persist data across sessions.
// 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[]
// 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[]
// 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>
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();
Interact with the UI window.
// 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; }
// 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; }
// 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(); } );
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>
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 } });
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
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(...) ); }
Complete TypeScript definitions are available:
import type { ExtensionContext, Disposable, Event, EventEmitter, Uri, Command, QuickPickItem, InputBoxOptions, Progress, CancellationToken } from '@apache-superset/core';
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'); }
// 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);
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}` ); } }
// 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()); }
// 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; }