mirror of
https://github.com/apache/superset.git
synced 2026-04-18 15:44:57 +00:00
docs: Reorganize and improve developer portal documentation (#36005)
This commit is contained in:
committed by
GitHub
parent
2f2128ac48
commit
208b1f7fa3
@@ -1,36 +0,0 @@
|
||||
---
|
||||
title: Architectural Principles
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Architectural Principles
|
||||
|
||||
Realizing this vision requires a strong architectural foundation. To ensure the resulting system is robust, maintainable, and adaptable, we have defined a set of architectural principles that will guide the design and implementation of the changes. These principles serve as the basis for all technical decisions and help create an environment where extensions can be developed safely and predictably, while minimizing technical debt and fragmentation.
|
||||
|
||||
The architectural principles guiding this proposal include:
|
||||
|
||||
1. **Lean core**: Superset's core should remain as minimal as possible, with many features and capabilities delegated to extensions. Wherever possible, built-in features should be implemented using the same APIs and extension mechanisms available to external extension authors. This approach reduces maintenance burden and complexity in the core application, encourages modularity, and allows the community to innovate and iterate on features independently of the main codebase.
|
||||
2. **Explicit contribution points**: All extension points must be clearly defined and documented, so extension authors know exactly where and how they can interact with the host system. Each extension must also declare its capabilities in a metadata file, enabling the host to manage the extension lifecycle and provide a consistent user experience.
|
||||
3. **Versioned and stable APIs**: Public interfaces for extensions should be versioned and follow semantic versioning, allowing for safe evolution and backward compatibility.
|
||||
4. **Lazy loading and activation**: Extensions should be loaded and activated only when needed, minimizing performance overhead and resource consumption.
|
||||
5. **Composability and reuse**: The architecture should encourage the reuse of extension points and patterns across different modules, promoting consistency and reducing duplication.
|
||||
6. **Community-driven evolution**: The system should be designed to evolve based on real-world feedback and contributions, allowing new extension points and capabilities to be added as needs emerge.
|
||||
253
docs/developer_portal/extensions/architecture.md
Normal file
253
docs/developer_portal/extensions/architecture.md
Normal file
@@ -0,0 +1,253 @@
|
||||
---
|
||||
title: Architecture
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Architecture
|
||||
|
||||
Apache Superset's extension system is designed to enable powerful customization while maintaining stability, security, and performance. This page explains the architectural principles, system design, and technical mechanisms that make the extension ecosystem possible.
|
||||
|
||||
## Architectural Principles
|
||||
|
||||
The extension architecture is built on six core principles that guide all technical decisions and ensure extensions can be developed safely and predictably:
|
||||
|
||||
### 1. Lean Core
|
||||
|
||||
Superset's core should remain minimal, with many features delegated to extensions. Built-in features use the same APIs and extension mechanisms available to external developers. This approach:
|
||||
- Reduces maintenance burden and complexity
|
||||
- Encourages modularity
|
||||
- Allows the community to innovate independently of the main codebase
|
||||
|
||||
### 2. Explicit Contribution Points
|
||||
|
||||
All extension points are clearly defined and documented. Extension authors know exactly where and how they can interact with the host system. Each extension declares its capabilities in a metadata file, enabling the host to:
|
||||
- Manage the extension lifecycle
|
||||
- Provide a consistent user experience
|
||||
- Validate extension compatibility
|
||||
|
||||
### 3. Versioned and Stable APIs
|
||||
|
||||
Public interfaces for extensions follow semantic versioning, allowing for:
|
||||
- Safe evolution of the platform
|
||||
- Backward compatibility
|
||||
- Clear upgrade paths for extension authors
|
||||
|
||||
### 4. Lazy Loading and Activation
|
||||
|
||||
Extensions are loaded and activated only when needed, which:
|
||||
- Minimizes performance overhead
|
||||
- Reduces resource consumption
|
||||
- Improves startup time
|
||||
|
||||
### 5. Composability and Reuse
|
||||
|
||||
The architecture encourages reusing extension points and patterns across different modules, promoting:
|
||||
- Consistency across extensions
|
||||
- Reduced duplication
|
||||
- Shared best practices
|
||||
|
||||
### 6. Community-Driven Evolution
|
||||
|
||||
The system evolves based on real-world feedback and contributions. New extension points and capabilities are added as needs emerge, ensuring the platform remains relevant and flexible.
|
||||
|
||||
## System Overview
|
||||
|
||||
The extension architecture is built around three main components that work together to create a flexible, maintainable ecosystem:
|
||||
|
||||
### Core Packages
|
||||
|
||||
Two core packages provide the foundation for extension development:
|
||||
|
||||
**Frontend: `@apache-superset/core`**
|
||||
|
||||
This package provides essential building blocks for frontend extensions and the host application:
|
||||
- Shared UI components
|
||||
- Utility functions
|
||||
- APIs and hooks
|
||||
- Type definitions
|
||||
|
||||
By centralizing these resources, both extensions and built-in features use the same APIs, ensuring consistency, type safety, and a seamless user experience. The package is versioned to support safe platform evolution while maintaining compatibility.
|
||||
|
||||
**Backend: `apache-superset-core`**
|
||||
|
||||
This package exposes key classes and APIs for backend extensions:
|
||||
- Database connectors
|
||||
- API extensions
|
||||
- Security manager customization
|
||||
- Core utilities and models
|
||||
|
||||
It includes dependencies on critical libraries like Flask-AppBuilder and SQLAlchemy, and follows semantic versioning for compatibility and stability.
|
||||
|
||||
### Developer Tools
|
||||
|
||||
**`apache-superset-extensions-cli`**
|
||||
|
||||
The CLI provides comprehensive commands for extension development:
|
||||
- Project scaffolding
|
||||
- Code generation
|
||||
- Building and bundling
|
||||
- Packaging for distribution
|
||||
|
||||
By standardizing these processes, the CLI ensures extensions are built consistently, remain compatible with evolving versions of Superset, and follow best practices.
|
||||
|
||||
### Host Application
|
||||
|
||||
The Superset host application serves as the runtime environment for extensions:
|
||||
|
||||
**Extension Management**
|
||||
- Exposes `/api/v1/extensions` endpoint for registration and management
|
||||
- Provides a dedicated UI for managing extensions
|
||||
- Stores extension metadata in the `extensions` database table
|
||||
|
||||
**Extension Storage**
|
||||
|
||||
The extensions table contains:
|
||||
- Extension name, version, and author
|
||||
- Contributed features and exposed modules
|
||||
- Metadata and configuration
|
||||
- Built frontend and/or backend code
|
||||
|
||||
### Architecture Diagram
|
||||
|
||||
The following diagram illustrates how these components work together:
|
||||
|
||||
<img width="955" height="586" alt="Extension System Architecture" src="https://github.com/user-attachments/assets/cc2a41df-55a4-48c8-b056-35f7a1e567c6" />
|
||||
|
||||
The diagram shows:
|
||||
1. **Extension projects** depend on core packages for development
|
||||
2. **Core packages** provide APIs and type definitions
|
||||
3. **The host application** implements the APIs and manages extensions
|
||||
4. **Extensions** integrate seamlessly with the host through well-defined interfaces
|
||||
|
||||
### Extension Dependencies
|
||||
|
||||
Extensions can depend on any combination of packages based on their needs. For example:
|
||||
|
||||
**Frontend-only extension** (e.g., a custom chart type):
|
||||
- Depends on `@apache-superset/core` for UI components and React APIs
|
||||
|
||||
**Full-stack extension** (e.g., a custom SQL editor with new API endpoints):
|
||||
- Depends on `@apache-superset/core` for frontend components
|
||||
- Depends on `apache-superset-core` for backend APIs and models
|
||||
|
||||
This modular approach allows extension authors to choose exactly what they need while promoting consistency and reusability.
|
||||
|
||||
## Dynamic Module Loading
|
||||
|
||||
One of the most sophisticated aspects of the extension architecture is how frontend code is dynamically loaded at runtime using Webpack's Module Federation.
|
||||
|
||||
### Module Federation
|
||||
|
||||
The architecture leverages Webpack's Module Federation to enable dynamic loading of frontend assets. This allows extensions to be built independently from Superset.
|
||||
|
||||
### How It Works
|
||||
|
||||
**Extension Configuration**
|
||||
|
||||
Extensions configure Webpack to expose their entry points:
|
||||
|
||||
``` typescript
|
||||
new ModuleFederationPlugin({
|
||||
name: 'my_extension',
|
||||
filename: 'remoteEntry.[contenthash].js',
|
||||
exposes: {
|
||||
'./index': './src/index.tsx',
|
||||
},
|
||||
externalsType: 'window',
|
||||
externals: {
|
||||
'@apache-superset/core': 'superset',
|
||||
},
|
||||
shared: {
|
||||
react: { singleton: true },
|
||||
'react-dom': { singleton: true },
|
||||
'antd-v5': { singleton: true }
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
This configuration does several important things:
|
||||
|
||||
**`exposes`** - Declares which modules are available to the host application. The extension makes `./index` available as its entry point.
|
||||
|
||||
**`externals` and `externalsType`** - Tell Webpack that when the extension imports `@apache-superset/core`, it should use `window.superset` at runtime instead of bundling its own copy. This ensures extensions use the host's implementation of shared packages.
|
||||
|
||||
**`shared`** - Prevents duplication of common libraries like React and Ant Design. The `singleton: true` setting ensures only one instance of each library exists, avoiding version conflicts and reducing bundle size.
|
||||
|
||||
### Runtime Resolution
|
||||
|
||||
The following diagram illustrates the module loading process:
|
||||
|
||||
<img width="913" height="558" alt="Module Federation Flow" src="https://github.com/user-attachments/assets/e5e4d2ae-e8b5-4d17-a2a1-3667c65f25ca" />
|
||||
|
||||
Here's what happens at runtime:
|
||||
|
||||
1. **Extension Registration**: When an extension is registered, Superset stores its remote entry URL
|
||||
2. **Dynamic Loading**: When the extension is activated, the host fetches the remote entry file
|
||||
3. **Module Resolution**: The extension imports `@apache-superset/core`, which resolves to `window.superset`
|
||||
4. **Execution**: The extension code runs with access to the host's APIs and shared dependencies
|
||||
|
||||
### Host API Setup
|
||||
|
||||
On the Superset side, the APIs are mapped to `window.superset` during application bootstrap:
|
||||
|
||||
``` typescript
|
||||
import * as supersetCore from '@apache-superset/core';
|
||||
import {
|
||||
authentication,
|
||||
core,
|
||||
commands,
|
||||
environment,
|
||||
extensions,
|
||||
sqlLab,
|
||||
} from 'src/extensions';
|
||||
|
||||
export default function setupExtensionsAPI() {
|
||||
window.superset = {
|
||||
...supersetCore,
|
||||
authentication,
|
||||
core,
|
||||
commands,
|
||||
environment,
|
||||
extensions,
|
||||
sqlLab,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
This function runs before any extensions are loaded, ensuring the APIs are available when extensions import from `@apache-superset/core`.
|
||||
|
||||
### Benefits
|
||||
|
||||
This architecture provides several key benefits:
|
||||
|
||||
- **Independent development**: Extensions can be built separately from Superset's codebase
|
||||
- **Version isolation**: Each extension can be developed with its own release cycle
|
||||
- **Shared dependencies**: Common libraries are shared, reducing memory usage and bundle size
|
||||
- **Type safety**: TypeScript types flow from the core package to extensions
|
||||
|
||||
## Next Steps
|
||||
|
||||
Now that you understand the architecture, explore:
|
||||
|
||||
- **[Extension Project Structure](./extension-project-structure)** - How to organize your extension code
|
||||
- **[Frontend Contribution Types](./frontend-contribution-types)** - What kinds of extensions you can build
|
||||
- **[Quick Start](./quick-start)** - Build your first extension
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
title: What This Means for Superset's Built-in Features
|
||||
sidebar_position: 13
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# What This Means for Superset's Built-in Features
|
||||
|
||||
Transitioning to a well-defined, versioned API model has significant implications for Superset's built-in features. By exposing stable, public APIs for core functionality, we enable both extensions and internal modules to interact with the application in a consistent and predictable way. This approach brings several key benefits:
|
||||
|
||||
- **Unified API Surface**: All important features of Superset will be accessible through documented, versioned APIs. This not only empowers extension authors but also ensures that built-in features use the same mechanisms, validating the APIs through real-world usage and making it easier to replace or enhance individual features over time.
|
||||
- **Dogfooding and Replaceability**: By building Superset's own features using the same APIs available to extensions, we ensure that these APIs are robust, flexible, and well-tested. This also means that any built-in feature can potentially be replaced or extended by a third-party extension, increasing modularity and adaptability.
|
||||
- **Versioned and Stable Contracts**: Public APIs will be versioned and follow semantic versioning, providing stability for both internal and external consumers. This stability is critical for long-term maintainability, but it also means that extra care must be taken to avoid breaking changes and to provide clear migration paths when changes are necessary.
|
||||
- **Improved Inter-Module Communication**: With clearly defined APIs and a command-based architecture, modules and extensions can communicate through explicit interfaces rather than relying on direct Redux store access or tightly coupled state management. This decouples modules, reduces the risk of unintended side effects, and makes the codebase easier to reason about and maintain.
|
||||
- **Facilitated Refactoring and Evolution**: As the application evolves, having a stable API layer allows for internal refactoring and optimization without breaking consumers. This makes it easier to modernize or optimize internal implementations while preserving compatibility.
|
||||
- **Clearer Documentation and Onboarding**: A public, versioned API surface makes it easier to document and onboard new contributors, both for core development and for extension authors.
|
||||
|
||||
Overall, this shift represents a move toward a more modular, maintainable, and extensible architecture, where both built-in features and extensions are first-class citizens, and where the boundaries between core and community-driven innovation are minimized.
|
||||
@@ -1,84 +0,0 @@
|
||||
---
|
||||
title: Dynamic Module Loading
|
||||
sidebar_position: 7
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Dynamic Module Loading
|
||||
|
||||
The extension architecture leverages Webpack's Module Federation to enable dynamic loading of frontend assets at runtime. This sophisticated mechanism involves several key concepts:
|
||||
|
||||
**Module Federation** allows extensions to be built and deployed independently while sharing dependencies with the host application. Extensions expose their entry points through the federation configuration:
|
||||
|
||||
``` typescript
|
||||
new ModuleFederationPlugin({
|
||||
name: 'my_extension',
|
||||
filename: 'remoteEntry.[contenthash].js',
|
||||
exposes: {
|
||||
'./index': './src/index.tsx',
|
||||
},
|
||||
externalsType: 'window',
|
||||
externals: {
|
||||
'@apache-superset/core': 'superset',
|
||||
},
|
||||
shared: {
|
||||
react: { singleton: true },
|
||||
'react-dom': { singleton: true },
|
||||
'antd-v5': { singleton: true }
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`externals` and `externalsType` ensure that extensions use the host's implementation of shared packages rather than bundling their own copies.
|
||||
|
||||
`shared` dependencies prevent duplication of common libraries like React and Ant Design avoiding version conflicts and reducing bundle size.
|
||||
|
||||
This configuration tells Webpack that when the extension imports from `@apache-superset/core`, it should resolve to `window.superset` at runtime, where the host application provides the actual implementation. The following diagram illustrates how this works in practice:
|
||||
|
||||
<img width="913" height="558" alt="Image" src="https://github.com/user-attachments/assets/e5e4d2ae-e8b5-4d17-a2a1-3667c65f25ca" />
|
||||
|
||||
During extension registration, the host application fetches the remote entry file and dynamically loads the extension's modules without requiring a rebuild or restart of Superset.
|
||||
|
||||
On the host application side, the `@apache-superset/core` package will be mapped to the corresponding implementations during bootstrap in the `setupExtensionsAPI` function.
|
||||
|
||||
``` typescript
|
||||
import * as supersetCore from '@apache-superset/core';
|
||||
import {
|
||||
authentication,
|
||||
core,
|
||||
commands,
|
||||
environment,
|
||||
extensions,
|
||||
sqlLab,
|
||||
} from 'src/extensions';
|
||||
|
||||
export default function setupExtensionsAPI() {
|
||||
window.superset = {
|
||||
...supersetCore,
|
||||
authentication,
|
||||
core,
|
||||
commands,
|
||||
environment,
|
||||
extensions,
|
||||
sqlLab,
|
||||
};
|
||||
}
|
||||
```
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
title: High-level Architecture
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# High-level Architecture
|
||||
|
||||
It is important to note that this SIP is not intended to address every aspect of the architecture in a single document. Rather, it should be seen as a chapter in an ongoing book: it establishes foundational concepts and direction, while recognizing that many important topics remain to be explored. Many topics not covered here are expected to be addressed in subsequent SIPs as the architecture and community needs evolve.
|
||||
|
||||
The following diagram illustrates the overall architecture, emphasizing the relationships between the host application, extensions, and the supporting packages that will be developed to enable this ecosystem.
|
||||
|
||||
<img width="955" height="586" alt="Image" src="https://github.com/user-attachments/assets/cc2a41df-55a4-48c8-b056-35f7a1e567c6" />
|
||||
|
||||
On the frontend side, as a result of discussions in [[SIP-169] Proposal for Extracting and Publishing Superset Core UI Components](https://github.com/apache/superset/issues/33441), the `@apache-superset/core` package will be created to provide all the essential building blocks for both the host application and extensions, including shared UI components, utility functions, APIs, and type definitions. By centralizing these resources, extensions and built-in features can use the same APIs and components, ensuring consistency, type safety, and a seamless user experience across the Superset ecosystem. This package will be versioned to support safe evolution of the platform while maintaining compatibility for both internal and external features.
|
||||
|
||||
On the backend side, the `apache-superset-core` package will expose key classes and APIs needed by extensions that provide backend functionality such as extending Superset's API, providing database connectors, or customizing the security manager. It will contain dependencies on critical libraries like FAB, SQLAlchemy, etc and like `@apache-superset/core`, it will be versioned to ensure compatibility and stability.
|
||||
|
||||
The `apache-superset-extensions-cli` package will provide a comprehensive set of CLI commands for extension development, including tools for code generation, building, and packaging extensions. These commands streamline the development workflow, making it easier for developers to scaffold new projects, build and bundle their code, and distribute extensions efficiently. By standardizing these processes, the CLI helps ensure that extensions are built in a consistent manner, remain compatible with evolving versions of Superset, and adhere to best practices across the ecosystem.
|
||||
|
||||
Extension projects might have references to all packages, depending on their specific needs. For example, an extension that provides a custom SQL editor might depend on the `apache-superset-core` package for backend functionality, while also using the `@apache-superset/core` package for UI components and type definitions. This modular approach allows extension authors to choose the dependencies that best suit their needs, while also promoting consistency and reusability across the ecosystem.
|
||||
|
||||
The host application (Superset) will depend on core packages and is responsible for providing the implementation of the APIs defined in them. It will expose a new endpoint (`/api/v1/extensions`) for extension registration and management, and a dedicated UI for managing extensions. Registered extensions will be stored in the metadata database in a table called `extensions`, which will contain information such as the extension's name, version, author, contributed features, exposed modules, relevant metadata and the built frontend and/or backend code.
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
title: Lifecycle and Management
|
||||
sidebar_position: 9
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Lifecycle and Management
|
||||
|
||||
Superset will manage the full lifecycle of extensions, including activation, deactivation, and cleanup. The lifecycle is designed to ensure that extensions can safely register resources and reliably clean them up when no longer needed.
|
||||
|
||||
## Frontend lifecycle
|
||||
|
||||
- When an extension is activated, its `activate(context)` function is called. The extension should register all event listeners, commands, views, and other contributions using the provided context, and add any disposables to `context.disposables`.
|
||||
- When the extension is deactivated (e.g., disabled or uninstalled), Superset automatically calls `dispose()` on all items in `context.disposables`, ensuring that event listeners, commands, and UI contributions are removed and memory leaks are avoided.
|
||||
|
||||
## Backend lifecycle
|
||||
|
||||
- Backend entry points, which can add REST API endpoints or execute arbitrary backend code, are eagerly evaluated during startup. Other backend code is lazily loaded when needed, ensuring minimal startup latency.
|
||||
- In the future, we plan to leverage mechanisms like Redis pub/sub (already an optional dependency of Superset) to dynamically manage the lifecycle of extensions' backend functionality. This will ensure that all running instances of the Superset backend have the same available extensions without requiring a restart. This will be addressed in a follow-up SIP.
|
||||
|
||||
The proof-of-concept (POC) code for this SIP already implements a management module where administrators can upload, delete, enable/disable, and inspect the manifest for installed extensions via the Superset UI, making extension operations straightforward. These operations are currently supported dynamically for frontend extensions. For backend extensions, dynamic upload, deletion, and enable/disable are planned for a future iteration; at present, changes to backend extensions (such as uploading, deleting, or enabling/disabling) still require a server restart.
|
||||
|
||||
https://github.com/user-attachments/assets/4eb7064b-3290-4e4c-b88b-52d8d1c11245
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Extensions Overview
|
||||
title: Overview
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
@@ -22,7 +22,7 @@ specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Extensions Overview
|
||||
# Overview
|
||||
|
||||
Apache Superset's extension system allows developers to enhance and customize Superset's functionality through a modular, plugin-based architecture. Extensions can add new visualization types, custom UI components, data processing capabilities, and integration points.
|
||||
|
||||
@@ -32,8 +32,7 @@ Superset extensions are self-contained packages that extend the core platform's
|
||||
|
||||
## Extension Architecture
|
||||
|
||||
- **[Architectural Principles](./architectural-principles)** - Core design principles guiding extension development
|
||||
- **[High-level Architecture](./high-level-architecture)** - System overview and component relationships
|
||||
- **[Architecture](./architecture)** - Architectural principles and high-level system overview
|
||||
- **[Extension Project Structure](./extension-project-structure)** - Standard project layout and organization
|
||||
- **[Extension Metadata](./extension-metadata)** - Configuration and manifest structure
|
||||
|
||||
@@ -41,19 +40,18 @@ Superset extensions are self-contained packages that extend the core platform's
|
||||
|
||||
- **[Frontend Contribution Types](./frontend-contribution-types)** - Types of UI contributions available
|
||||
- **[Interacting with Host](./interacting-with-host)** - Communication patterns with Superset core
|
||||
- **[Dynamic Module Loading](./dynamic-module-loading)** - Runtime loading and dependency management
|
||||
- **[Development Mode](./development-mode)** - Tools and workflows for extension development
|
||||
|
||||
For information about runtime loading and dependency management, see the [Dynamic Module Loading](./architecture#dynamic-module-loading) section in the Architecture page.
|
||||
|
||||
## Deployment & Management
|
||||
|
||||
- **[Deploying Extension](./deploying-extension)** - Packaging and distribution strategies
|
||||
- **[Lifecycle Management](./lifecycle-management)** - Installation, updates, and removal
|
||||
- **[Versioning](./versioning)** - Version management and compatibility
|
||||
- **[Security Implications](./security-implications)** - Security considerations and best practices
|
||||
|
||||
## Hands-on Examples
|
||||
|
||||
- **[Proof of Concept](./proof-of-concept)** - Complete Hello World extension walkthrough
|
||||
- **[Quick Start](./quick-start)** - Complete Hello World extension walkthrough
|
||||
|
||||
## Extension Capabilities
|
||||
|
||||
@@ -68,9 +66,9 @@ Extensions can provide:
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. **Learn the Architecture**: Start with [Architectural Principles](./architectural-principles) to understand the design philosophy
|
||||
1. **Learn the Architecture**: Start with [Architecture](./architecture) to understand the design philosophy
|
||||
2. **Set up Development**: Follow the [Development Mode](./development-mode) guide to configure your environment
|
||||
3. **Build Your First Extension**: Complete the [Proof of Concept](./proof-of-concept) tutorial
|
||||
3. **Build Your First Extension**: Complete the [Quick Start](./quick-start) tutorial
|
||||
4. **Deploy and Share**: Use the [Deploying Extension](./deploying-extension) guide to package your extension
|
||||
|
||||
## Extension Ecosystem
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
---
|
||||
title: "Example: Hello World"
|
||||
sidebar_position: 14
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Example: Hello World
|
||||
|
||||
:::warning Work in Progress
|
||||
This documentation is under active development. Some features described may not be fully implemented yet.
|
||||
:::
|
||||
|
||||
This guide walks you through creating your first Superset extension - a simple "Hello World" panel for SQL Lab. You'll learn how to create, build, package, install, and test a basic extension.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before starting, ensure you have:
|
||||
- Node.js 18+ and npm installed
|
||||
- Python 3.9+ installed
|
||||
- A running Superset development environment with `ENABLE_EXTENSIONS = True` in your config
|
||||
- Basic knowledge of React and TypeScript
|
||||
|
||||
## Step 1: Initialize Your Extension
|
||||
|
||||
First, install the Superset extension CLI and create a new extension project:
|
||||
|
||||
```bash
|
||||
# Install the CLI globally
|
||||
pip install apache-superset-extensions-cli
|
||||
|
||||
# Create a new extension
|
||||
superset-extensions init hello-world
|
||||
cd hello-world
|
||||
```
|
||||
|
||||
This creates the following structure:
|
||||
```
|
||||
hello-world/
|
||||
├── extension.json # Extension metadata
|
||||
├── frontend/ # Frontend code
|
||||
│ ├── src/
|
||||
│ │ └── index.tsx # Main entry point
|
||||
│ ├── package.json
|
||||
│ └── webpack.config.js
|
||||
├── backend/ # Backend code (optional)
|
||||
│ └── src/
|
||||
└── README.md
|
||||
```
|
||||
|
||||
## Step 2: Configure Extension Metadata
|
||||
|
||||
Edit `extension.json` to define your extension's capabilities:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "hello_world",
|
||||
"displayName": "Hello World Extension",
|
||||
"version": "1.0.0",
|
||||
"description": "A simple Hello World panel for SQL Lab",
|
||||
"author": "Your Name",
|
||||
"license": "Apache-2.0",
|
||||
"superset": {
|
||||
"minVersion": "4.0.0"
|
||||
},
|
||||
"frontend": {
|
||||
"contributions": {
|
||||
"views": {
|
||||
"sqllab.panels": [
|
||||
{
|
||||
"id": "hello_world.main",
|
||||
"name": "Hello World",
|
||||
"icon": "SmileOutlined"
|
||||
}
|
||||
]
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"command": "hello_world.greet",
|
||||
"title": "Say Hello",
|
||||
"description": "Display a greeting message"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Step 3: Create the Frontend Component
|
||||
|
||||
Create `frontend/src/HelloWorldPanel.tsx`:
|
||||
|
||||
```tsx
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Card, Button, Alert } from '@apache-superset/core';
|
||||
|
||||
export const HelloWorldPanel: React.FC = () => {
|
||||
const [greeting, setGreeting] = useState('Hello, Superset!');
|
||||
const [queryCount, setQueryCount] = useState(0);
|
||||
|
||||
// Listen for query executions
|
||||
useEffect(() => {
|
||||
const handleQueryRun = () => {
|
||||
setQueryCount(prev => prev + 1);
|
||||
setGreeting(`Hello! You've run ${queryCount + 1} queries.`);
|
||||
};
|
||||
|
||||
// Subscribe to SQL Lab events
|
||||
const disposable = window.superset?.sqlLab?.onDidQueryRun?.(handleQueryRun);
|
||||
|
||||
return () => disposable?.dispose?.();
|
||||
}, [queryCount]);
|
||||
|
||||
return (
|
||||
<Card title="Hello World Extension">
|
||||
<Alert
|
||||
message={greeting}
|
||||
type="success"
|
||||
showIcon
|
||||
/>
|
||||
<p style={{ marginTop: 16 }}>
|
||||
This is your first Superset extension! 🎉
|
||||
</p>
|
||||
<p>
|
||||
Queries executed this session: <strong>{queryCount}</strong>
|
||||
</p>
|
||||
<Button
|
||||
onClick={() => setGreeting('Hello from the button!')}
|
||||
style={{ marginTop: 16 }}
|
||||
>
|
||||
Click Me
|
||||
</Button>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## Step 4: Set Up the Entry Point
|
||||
|
||||
Update `frontend/src/index.tsx`:
|
||||
|
||||
```tsx
|
||||
import { ExtensionContext } from '@apache-superset/core';
|
||||
import { HelloWorldPanel } from './HelloWorldPanel';
|
||||
|
||||
export function activate(context: ExtensionContext) {
|
||||
console.log('Hello World extension is activating!');
|
||||
|
||||
// Register the panel
|
||||
const panel = context.registerView(
|
||||
'hello_world.main',
|
||||
<HelloWorldPanel />
|
||||
);
|
||||
|
||||
// Register the command
|
||||
const command = context.registerCommand('hello_world.greet', {
|
||||
execute: () => {
|
||||
console.log('Hello from the command!');
|
||||
// You could trigger panel updates or show notifications here
|
||||
}
|
||||
});
|
||||
|
||||
// Add disposables for cleanup
|
||||
context.subscriptions.push(panel, command);
|
||||
}
|
||||
|
||||
export function deactivate() {
|
||||
console.log('Hello World extension is deactivating!');
|
||||
}
|
||||
```
|
||||
|
||||
## Step 5: Build the Extension
|
||||
|
||||
Build your extension assets:
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
cd frontend
|
||||
npm install
|
||||
|
||||
# Build the extension
|
||||
cd ..
|
||||
superset-extensions build
|
||||
|
||||
# This creates a dist/ folder with your built assets
|
||||
```
|
||||
|
||||
> **Note:** The `superset-extensions` CLI handles webpack configuration automatically. Superset already has Module Federation configured, so you don't need to set up webpack yourself unless you have specific advanced requirements.
|
||||
|
||||
## Step 6: Package the Extension
|
||||
|
||||
Create the distributable `.supx` file:
|
||||
|
||||
```bash
|
||||
superset-extensions bundle
|
||||
|
||||
# This creates hello_world-1.0.0.supx
|
||||
```
|
||||
|
||||
## Step 7: Install in Superset
|
||||
|
||||
Upload your extension to a running Superset instance:
|
||||
|
||||
### Option A: Via API
|
||||
```bash
|
||||
curl -X POST http://localhost:8088/api/v1/extensions/import/ \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-F "bundle=@hello_world-1.0.0.supx"
|
||||
```
|
||||
|
||||
### Option B: Via UI
|
||||
1. Navigate to Settings → Extensions
|
||||
2. Click "Upload Extension"
|
||||
3. Select your `hello_world-1.0.0.supx` file
|
||||
4. Click "Install"
|
||||
|
||||
## Step 9: Test Your Extension
|
||||
|
||||
1. Open SQL Lab in Superset
|
||||
2. Look for the "Hello World" panel in the panels dropdown or sidebar
|
||||
3. The panel should display your greeting message
|
||||
4. Run a SQL query and watch the query counter increment
|
||||
5. Click the button to see the greeting change
|
||||
|
||||
## Step 10: Development Mode (Optional)
|
||||
|
||||
For faster development iteration, use local development mode:
|
||||
|
||||
1. Add to your `superset_config.py`:
|
||||
```python
|
||||
LOCAL_EXTENSIONS = [
|
||||
"/path/to/hello-world"
|
||||
]
|
||||
ENABLE_EXTENSIONS = True
|
||||
```
|
||||
|
||||
2. Run the extension in watch mode:
|
||||
```bash
|
||||
superset-extensions dev
|
||||
```
|
||||
|
||||
3. Changes will be reflected immediately without rebuilding
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Extension Not Loading
|
||||
- Check that `ENABLE_EXTENSIONS = True` in your Superset config
|
||||
- Verify the extension is listed in Settings → Extensions
|
||||
- Check browser console for errors
|
||||
- Ensure all dependencies are installed
|
||||
|
||||
### Build Errors
|
||||
- Make sure you have the correct Node.js version (18+)
|
||||
- Clear node_modules and reinstall: `rm -rf node_modules && npm install`
|
||||
- Check that webpack.config.js is properly configured
|
||||
|
||||
### Panel Not Visible
|
||||
- Verify the contribution point in extension.json matches `sqllab.panels`
|
||||
- Check that the panel ID is unique
|
||||
- Restart Superset after installing the extension
|
||||
|
||||
## Next Steps
|
||||
|
||||
Now that you have a working Hello World extension, you can:
|
||||
- Add more complex UI components
|
||||
- Integrate with Superset's API to fetch data
|
||||
- Add backend functionality for data processing
|
||||
- Create custom commands and menu items
|
||||
- Listen to more SQL Lab events
|
||||
|
||||
For more advanced examples, explore the other pages in this documentation section.
|
||||
397
docs/developer_portal/extensions/quick-start.md
Normal file
397
docs/developer_portal/extensions/quick-start.md
Normal file
@@ -0,0 +1,397 @@
|
||||
---
|
||||
title: Quick Start
|
||||
sidebar_position: 2
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Quick Start
|
||||
|
||||
This guide walks you through creating your first Superset extension - a simple "Hello World" panel that displays a message fetched from a backend API endpoint. You'll learn the essential structure and patterns for building full-stack Superset extensions.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before starting, ensure you have:
|
||||
|
||||
- Node.js and npm compatible with your Superset version
|
||||
- Python compatible with your Superset version
|
||||
- A running Superset development environment
|
||||
- Basic knowledge of React, TypeScript, and Flask
|
||||
|
||||
## Step 1: Install the Extensions CLI
|
||||
|
||||
First, install the Apache Superset Extensions CLI:
|
||||
|
||||
```bash
|
||||
pip install apache-superset-extensions-cli
|
||||
```
|
||||
|
||||
## Step 2: Create a New Extension
|
||||
|
||||
Use the CLI to scaffold a new extension project. Extensions can include frontend functionality, backend functionality, or both, depending on your needs. This quickstart demonstrates a full-stack extension with both frontend UI components and backend API endpoints to show the complete integration pattern.
|
||||
|
||||
```bash
|
||||
superset-extensions init
|
||||
```
|
||||
|
||||
The CLI will prompt you for information:
|
||||
|
||||
```
|
||||
Extension ID (unique identifier, alphanumeric only): hello_world
|
||||
Extension name (human-readable display name): Hello World
|
||||
Initial version [0.1.0]: 0.1.0
|
||||
License [Apache-2.0]: Apache-2.0
|
||||
Include frontend? [Y/n]: Y
|
||||
Include backend? [Y/n]: Y
|
||||
```
|
||||
|
||||
This creates a complete project structure:
|
||||
|
||||
```
|
||||
hello_world/
|
||||
├── extension.json # Extension metadata and configuration
|
||||
├── backend/ # Backend Python code
|
||||
│ ├── src/
|
||||
│ │ └── hello_world/
|
||||
│ │ ├── __init__.py
|
||||
│ │ └── entrypoint.py # Backend registration
|
||||
│ └── pyproject.toml
|
||||
└── frontend/ # Frontend TypeScript/React code
|
||||
├── src/
|
||||
│ └── index.tsx # Frontend entry point
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
└── webpack.config.js
|
||||
```
|
||||
|
||||
## Step 3: Configure Extension Metadata
|
||||
|
||||
The generated `extension.json` contains basic metadata. Update it to register your panel in SQL Lab:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "hello_world",
|
||||
"name": "Hello World",
|
||||
"version": "0.1.0",
|
||||
"license": "Apache-2.0",
|
||||
"frontend": {
|
||||
"contributions": {
|
||||
"views": {
|
||||
"sqllab.panels": [
|
||||
{
|
||||
"id": "hello_world.main",
|
||||
"name": "Hello World"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"moduleFederation": {
|
||||
"exposes": ["./index"]
|
||||
}
|
||||
},
|
||||
"backend": {
|
||||
"entryPoints": ["hello_world.entrypoint"],
|
||||
"files": ["backend/src/hello_world/**/*.py"]
|
||||
},
|
||||
"permissions": ["can_read"]
|
||||
}
|
||||
```
|
||||
|
||||
**Key fields:**
|
||||
|
||||
- `frontend.contributions.views.sqllab.panels`: Registers your panel in SQL Lab
|
||||
- `backend.entryPoints`: Python modules to load eagerly when extension starts
|
||||
|
||||
## Step 4: Create Backend API
|
||||
|
||||
The CLI generated a basic `backend/src/hello_world/entrypoint.py`. We'll create an API endpoint.
|
||||
|
||||
**Create `backend/src/hello_world/api.py`**
|
||||
|
||||
```python
|
||||
from flask import Response
|
||||
from flask_appbuilder.api import expose, protect, safe
|
||||
from superset_core.api.types.rest_api import RestApi
|
||||
|
||||
|
||||
class HelloWorldAPI(RestApi):
|
||||
resource_name = "hello_world"
|
||||
openapi_spec_tag = "Hello World"
|
||||
class_permission_name = "hello_world"
|
||||
|
||||
@expose("/message", methods=("GET",))
|
||||
@protect()
|
||||
@safe
|
||||
def get_message(self) -> Response:
|
||||
"""Gets a hello world message
|
||||
---
|
||||
get:
|
||||
description: >-
|
||||
Get a hello world message from the backend
|
||||
responses:
|
||||
200:
|
||||
description: Hello world message
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
result:
|
||||
type: object
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
401:
|
||||
$ref: '#/components/responses/401'
|
||||
"""
|
||||
return self.response(
|
||||
200,
|
||||
result={"message": "Hello from the backend!"}
|
||||
)
|
||||
```
|
||||
|
||||
**Key points:**
|
||||
|
||||
- Extends `RestApi` from `superset_core.api.types.rest_api`
|
||||
- Uses Flask-AppBuilder decorators (`@expose`, `@protect`, `@safe`)
|
||||
- Returns responses using `self.response(status_code, result=data)`
|
||||
- The endpoint will be accessible at `/extensions/hello_world/message`
|
||||
- OpenAPI docstrings are crucial - Flask-AppBuilder uses them to automatically generate interactive API documentation at `/swagger/v1`, allowing developers to explore endpoints, understand schemas, and test the API directly from the browser
|
||||
|
||||
**Update `backend/src/hello_world/entrypoint.py`**
|
||||
|
||||
Replace the generated print statement with API registration:
|
||||
|
||||
```python
|
||||
from superset_core.api import rest_api
|
||||
|
||||
from .api import HelloWorldAPI
|
||||
|
||||
rest_api.add_extension_api(HelloWorldAPI)
|
||||
```
|
||||
|
||||
This registers your API with Superset when the extension loads.
|
||||
|
||||
## Step 5: Create Frontend Component
|
||||
|
||||
The CLI generated boilerplate files. The webpack config and package.json are already properly configured with Module Federation.
|
||||
|
||||
**Create `frontend/src/HelloWorldPanel.tsx`**
|
||||
|
||||
Create a new file for the component implementation:
|
||||
|
||||
```tsx
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { authentication } from '@apache-superset/core';
|
||||
|
||||
const HelloWorldPanel: React.FC = () => {
|
||||
const [message, setMessage] = useState<string>('');
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string>('');
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMessage = async () => {
|
||||
try {
|
||||
const csrfToken = await authentication.getCSRFToken();
|
||||
const response = await fetch('/extensions/hello_world/message', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRFToken': csrfToken!,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Server returned ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
setMessage(data.result.message);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'An error occurred');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchMessage();
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div style={{ padding: '20px', textAlign: 'center' }}>
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div style={{ padding: '20px', color: 'red' }}>
|
||||
<strong>Error:</strong> {error}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ padding: '20px' }}>
|
||||
<h3>Hello World Extension</h3>
|
||||
<div
|
||||
style={{
|
||||
padding: '16px',
|
||||
backgroundColor: '#f6ffed',
|
||||
border: '1px solid #b7eb8f',
|
||||
borderRadius: '4px',
|
||||
marginBottom: '16px',
|
||||
}}
|
||||
>
|
||||
<strong>{message}</strong>
|
||||
</div>
|
||||
<p>This message was fetched from the backend API! 🎉</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default HelloWorldPanel;
|
||||
```
|
||||
|
||||
**Update `frontend/src/index.tsx`**
|
||||
|
||||
Replace the generated code with the extension entry point:
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { core } from '@apache-superset/core';
|
||||
import HelloWorldPanel from './HelloWorldPanel';
|
||||
|
||||
export const activate = (context: core.ExtensionContext) => {
|
||||
context.disposables.push(
|
||||
core.registerViewProvider('hello_world.main', () => <HelloWorldPanel />),
|
||||
);
|
||||
};
|
||||
|
||||
export const deactivate = () => {};
|
||||
```
|
||||
|
||||
**Key patterns:**
|
||||
|
||||
- `activate` function is called when the extension loads
|
||||
- `core.registerViewProvider` registers the component with ID `hello_world.main` (matching `extension.json`)
|
||||
- `authentication.getCSRFToken()` retrieves the CSRF token for API calls
|
||||
- Fetch calls to `/extensions/{extension_id}/{endpoint}` reach your backend API
|
||||
- `context.disposables.push()` ensures proper cleanup
|
||||
|
||||
## Step 6: Install Dependencies
|
||||
|
||||
Install the frontend dependencies:
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
cd ..
|
||||
```
|
||||
|
||||
## Step 7: Package the Extension
|
||||
|
||||
Create a `.supx` bundle for deployment:
|
||||
|
||||
```bash
|
||||
superset-extensions bundle
|
||||
```
|
||||
|
||||
This command automatically:
|
||||
|
||||
- Builds frontend assets using Webpack with Module Federation
|
||||
- Collects backend Python source files
|
||||
- Creates a `dist/` directory with:
|
||||
- `manifest.json` - Build metadata and asset references
|
||||
- `frontend/dist/` - Built frontend assets (remoteEntry.js, chunks)
|
||||
- `backend/` - Python source files
|
||||
- Packages everything into `hello_world-0.1.0.supx` - a zip archive with the specific structure required by Superset
|
||||
|
||||
## Step 8: Deploy to Superset
|
||||
|
||||
To deploy your extension, you need to enable extensions support and configure where Superset should load them from.
|
||||
|
||||
**Configure Superset**
|
||||
|
||||
Add the following to your `superset_config.py`:
|
||||
|
||||
```python
|
||||
# Enable extensions feature
|
||||
FEATURE_FLAGS = {
|
||||
"EXTENSIONS": True,
|
||||
}
|
||||
|
||||
# Set the directory where extensions are stored
|
||||
EXTENSIONS_PATH = "/path/to/extensions/folder"
|
||||
```
|
||||
|
||||
**Copy Extension Bundle**
|
||||
|
||||
Copy your `.supx` file to the configured extensions path:
|
||||
|
||||
```bash
|
||||
cp hello_world-0.1.0.supx /path/to/extensions/folder/
|
||||
```
|
||||
|
||||
**Restart Superset**
|
||||
|
||||
Restart your Superset instance to load the extension:
|
||||
|
||||
```bash
|
||||
# Restart your Superset server
|
||||
superset run
|
||||
```
|
||||
|
||||
Superset will extract and validate the extension metadata, load the assets, register the extension with its capabilities, and make it available for use.
|
||||
|
||||
## Step 9: Test Your Extension
|
||||
|
||||
1. **Open SQL Lab** in Superset
|
||||
2. Look for the **"Hello World"** panel in the panels dropdown or sidebar
|
||||
3. Open the panel - it should display "Hello from the backend!"
|
||||
4. Check that the message was fetched from your API endpoint
|
||||
|
||||
## Understanding the Flow
|
||||
|
||||
Here's what happens when your extension loads:
|
||||
|
||||
1. **Superset starts**: Reads `extension.json` and loads backend entrypoint
|
||||
2. **Backend registration**: `entrypoint.py` registers your API via `rest_api.add_extension_api()`
|
||||
3. **Frontend loads**: When SQL Lab opens, Superset fetches the remote entry file
|
||||
4. **Module Federation**: Webpack loads your extension code and resolves `@apache-superset/core` to `window.superset`
|
||||
5. **Activation**: `activate()` is called, registering your view provider
|
||||
6. **Rendering**: When the user opens your panel, React renders `<HelloWorldPanel />`
|
||||
7. **API call**: Component fetches data from `/extensions/hello_world/message`
|
||||
8. **Backend response**: Your Flask API returns the hello world message
|
||||
9. **Display**: Component shows the message to the user
|
||||
|
||||
## Next Steps
|
||||
|
||||
Now that you have a working extension, explore:
|
||||
|
||||
- **[Development Mode](./development-mode)** - Faster iteration with local development and watch mode
|
||||
- **[Extension Project Structure](./extension-project-structure)** - Best practices for organizing larger extensions
|
||||
- **[Frontend Contribution Types](./frontend-contribution-types)** - Other UI contribution points beyond panels
|
||||
- **[Interacting with Host](./interacting-with-host)** - Advanced APIs for interacting with Superset
|
||||
- **[Security Implications](./security-implications)** - Security best practices for extensions
|
||||
|
||||
For a complete real-world example, examine the query insights extension in the Superset codebase.
|
||||
@@ -1,31 +0,0 @@
|
||||
---
|
||||
title: Versioning
|
||||
sidebar_position: 11
|
||||
---
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Versioning
|
||||
|
||||
All core packages published to NPM and PyPI—including `@apache-superset/core`, `apache-superset-core`, and `apache-superset-extensions-cli`—will follow semantic versioning ([semver](https://semver.org/)). This means that any breaking changes to public APIs, interfaces, or extension points will result in a major version bump, while new features and non-breaking changes will be released as minor or patch updates.
|
||||
|
||||
During the initial development phase, packages will remain under version 0.x, allowing for rapid iteration and the introduction of breaking changes as the architecture evolves based on real-world feedback. Once the APIs and extension points are considered stable, we will release version 1.0.0 and begin enforcing strict server practices.
|
||||
|
||||
To minimize disruption, breaking changes will be carefully planned and communicated in advance. We will provide clear migration guides and changelogs to help extension authors and core contributors adapt to new versions. Where possible, we will deprecate APIs before removing them, giving developers time to transition to newer interfaces.
|
||||
Reference in New Issue
Block a user