mirror of
https://github.com/apache/superset.git
synced 2026-04-30 21:44:40 +00:00
Compare commits
2 Commits
semantic-l
...
thumbnail-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c563e9414f | ||
|
|
b7ee772034 |
@@ -83,7 +83,6 @@ github:
|
||||
- cypress-matrix (5, chrome)
|
||||
- dependency-review
|
||||
- frontend-build
|
||||
- playwright-tests (chromium)
|
||||
- pre-commit (current)
|
||||
- pre-commit (previous)
|
||||
- test-mysql
|
||||
|
||||
@@ -3,3 +3,14 @@
|
||||
For complete documentation on using GitHub Codespaces with Apache Superset, please see:
|
||||
|
||||
**[Setting up a Development Environment - GitHub Codespaces](https://superset.apache.org/docs/contributing/development#github-codespaces-cloud-development)**
|
||||
|
||||
## Pre-installed Development Environment
|
||||
|
||||
When you create a new Codespace from this repository, it automatically:
|
||||
|
||||
1. **Creates a Python virtual environment** using `uv venv`
|
||||
2. **Installs all development dependencies** via `uv pip install -r requirements/development.txt`
|
||||
3. **Sets up pre-commit hooks** with `pre-commit install`
|
||||
4. **Activates the virtual environment** automatically in all terminals
|
||||
|
||||
The virtual environment is located at `/workspaces/{repository-name}/.venv` and is automatically activated through environment variables set in the devcontainer configuration.
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
// Extend the base configuration
|
||||
"extends": "../devcontainer-base.json",
|
||||
|
||||
"name": "Apache Superset Development (Default)",
|
||||
|
||||
// Forward ports for development
|
||||
"forwardPorts": [9001],
|
||||
"portsAttributes": {
|
||||
"9001": {
|
||||
"label": "Superset (via Webpack Dev Server)",
|
||||
"onAutoForward": "notify",
|
||||
"visibility": "public"
|
||||
}
|
||||
},
|
||||
|
||||
// Auto-start Superset on Codespace resume
|
||||
"postStartCommand": ".devcontainer/start-superset.sh"
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
{
|
||||
"name": "Apache Superset Development",
|
||||
// Keep this in sync with the base image in Dockerfile (ARG PY_VER)
|
||||
// Using the same base as Dockerfile, but non-slim for dev tools
|
||||
"image": "python:3.11.13-bookworm",
|
||||
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/docker-in-docker:2": {
|
||||
"moby": true,
|
||||
"dockerDashComposeVersion": "v2"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "20"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/git:1": {},
|
||||
"ghcr.io/devcontainers/features/common-utils:2": {
|
||||
"configureZshAsDefaultShell": true
|
||||
},
|
||||
"ghcr.io/devcontainers/features/sshd:1": {
|
||||
"version": "latest"
|
||||
}
|
||||
},
|
||||
|
||||
// Run commands after container is created
|
||||
"postCreateCommand": "chmod +x .devcontainer/setup-dev.sh && .devcontainer/setup-dev.sh",
|
||||
|
||||
// VS Code customizations
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"charliermarsh.ruff",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,30 +3,76 @@
|
||||
|
||||
echo "🔧 Setting up Superset development environment..."
|
||||
|
||||
# The universal image has most tools, just need Superset-specific libs
|
||||
echo "📦 Installing Superset-specific dependencies..."
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y \
|
||||
libsasl2-dev \
|
||||
libldap2-dev \
|
||||
libpq-dev \
|
||||
tmux \
|
||||
gh
|
||||
# System dependencies and uv are now pre-installed in the Docker image
|
||||
# This speeds up Codespace creation significantly!
|
||||
|
||||
# Install uv for fast Python package management
|
||||
echo "📦 Installing uv..."
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
# Create virtual environment using uv
|
||||
echo "🐍 Creating Python virtual environment..."
|
||||
if ! uv venv; then
|
||||
echo "❌ Failed to create virtual environment"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Add cargo/bin to PATH for uv
|
||||
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc
|
||||
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.zshrc
|
||||
# Install Python dependencies
|
||||
echo "📦 Installing Python dependencies..."
|
||||
if ! uv pip install -r requirements/development.txt; then
|
||||
echo "❌ Failed to install Python dependencies"
|
||||
echo "💡 You may need to run this manually after the Codespace starts"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install pre-commit hooks
|
||||
echo "🪝 Installing pre-commit hooks..."
|
||||
if source .venv/bin/activate && pre-commit install; then
|
||||
echo "✅ Pre-commit hooks installed"
|
||||
else
|
||||
echo "⚠️ Pre-commit hooks installation failed (non-critical)"
|
||||
fi
|
||||
|
||||
# Install Claude Code CLI via npm
|
||||
echo "🤖 Installing Claude Code..."
|
||||
npm install -g @anthropic-ai/claude-code
|
||||
if npm install -g @anthropic-ai/claude-code; then
|
||||
echo "✅ Claude Code installed"
|
||||
else
|
||||
echo "⚠️ Claude Code installation failed (non-critical)"
|
||||
fi
|
||||
|
||||
# Make the start script executable
|
||||
chmod +x .devcontainer/start-superset.sh
|
||||
|
||||
# Add bashrc additions for automatic venv activation
|
||||
echo "🔧 Setting up automatic environment activation..."
|
||||
if [ -f ~/.bashrc ]; then
|
||||
# Check if we've already added our additions
|
||||
if ! grep -q "Superset Codespaces environment setup" ~/.bashrc; then
|
||||
echo "" >> ~/.bashrc
|
||||
cat .devcontainer/bashrc-additions >> ~/.bashrc
|
||||
echo "✅ Added automatic venv activation to ~/.bashrc"
|
||||
else
|
||||
echo "✅ Bashrc additions already present"
|
||||
fi
|
||||
else
|
||||
# Create bashrc if it doesn't exist
|
||||
cat .devcontainer/bashrc-additions > ~/.bashrc
|
||||
echo "✅ Created ~/.bashrc with automatic venv activation"
|
||||
fi
|
||||
|
||||
# Also add to zshrc since that's the default shell
|
||||
if [ -f ~/.zshrc ] || [ -n "$ZSH_VERSION" ]; then
|
||||
if ! grep -q "Superset Codespaces environment setup" ~/.zshrc; then
|
||||
echo "" >> ~/.zshrc
|
||||
cat .devcontainer/bashrc-additions >> ~/.zshrc
|
||||
echo "✅ Added automatic venv activation to ~/.zshrc"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "✅ Development environment setup complete!"
|
||||
echo "🚀 Run '.devcontainer/start-superset.sh' to start Superset"
|
||||
echo ""
|
||||
echo "📝 The virtual environment will be automatically activated in new terminals"
|
||||
echo ""
|
||||
echo "🔄 To activate in this terminal, run:"
|
||||
echo " source ~/.bashrc"
|
||||
echo ""
|
||||
echo "🚀 To start Superset:"
|
||||
echo " start-superset"
|
||||
echo ""
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#!/bin/bash
|
||||
# Startup script for Superset in Codespaces
|
||||
|
||||
# Log to a file for debugging
|
||||
LOG_FILE="/tmp/superset-startup.log"
|
||||
echo "[$(date)] Starting Superset startup script" >> "$LOG_FILE"
|
||||
echo "[$(date)] User: $(whoami), PWD: $(pwd)" >> "$LOG_FILE"
|
||||
|
||||
echo "🚀 Starting Superset in Codespaces..."
|
||||
echo "🌐 Frontend will be available at port 9001"
|
||||
|
||||
# Check if MCP is enabled
|
||||
if [ "$ENABLE_MCP" = "true" ]; then
|
||||
echo "🤖 MCP Service will be available at port 5008"
|
||||
fi
|
||||
|
||||
# Find the workspace directory (Codespaces clones as 'superset', not 'superset-2')
|
||||
WORKSPACE_DIR=$(find /workspaces -maxdepth 1 -name "superset*" -type d | head -1)
|
||||
if [ -n "$WORKSPACE_DIR" ]; then
|
||||
@@ -18,32 +18,71 @@ else
|
||||
echo "📁 Using current directory: $(pwd)"
|
||||
fi
|
||||
|
||||
# Check if docker is running
|
||||
if ! docker info > /dev/null 2>&1; then
|
||||
echo "⏳ Waiting for Docker to start..."
|
||||
sleep 5
|
||||
# Wait for Docker to be available
|
||||
echo "⏳ Waiting for Docker to start..."
|
||||
echo "[$(date)] Waiting for Docker..." >> "$LOG_FILE"
|
||||
max_attempts=30
|
||||
attempt=0
|
||||
while ! docker info > /dev/null 2>&1; do
|
||||
if [ $attempt -eq $max_attempts ]; then
|
||||
echo "❌ Docker failed to start after $max_attempts attempts"
|
||||
echo "[$(date)] Docker failed to start after $max_attempts attempts" >> "$LOG_FILE"
|
||||
echo "🔄 Please restart the Codespace or run this script manually later"
|
||||
exit 1
|
||||
fi
|
||||
echo " Attempt $((attempt + 1))/$max_attempts..."
|
||||
echo "[$(date)] Docker check attempt $((attempt + 1))/$max_attempts" >> "$LOG_FILE"
|
||||
sleep 2
|
||||
attempt=$((attempt + 1))
|
||||
done
|
||||
echo "✅ Docker is ready!"
|
||||
echo "[$(date)] Docker is ready" >> "$LOG_FILE"
|
||||
|
||||
# Check if Superset containers are already running
|
||||
if docker ps | grep -q "superset"; then
|
||||
echo "✅ Superset containers are already running!"
|
||||
echo ""
|
||||
echo "🌐 To access Superset:"
|
||||
echo " 1. Click the 'Ports' tab at the bottom of VS Code"
|
||||
echo " 2. Find port 9001 and click the globe icon to open"
|
||||
echo " 3. Wait 10-20 minutes for initial startup"
|
||||
echo ""
|
||||
echo "📝 Login credentials: admin/admin"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Clean up any existing containers
|
||||
echo "🧹 Cleaning up existing containers..."
|
||||
docker-compose -f docker-compose-light.yml --profile mcp down
|
||||
docker-compose -f docker-compose-light.yml down
|
||||
|
||||
# Start services
|
||||
echo "🏗️ Building and starting services..."
|
||||
echo "🏗️ Starting Superset in background (daemon mode)..."
|
||||
echo ""
|
||||
echo "📝 Once started, login with:"
|
||||
echo " Username: admin"
|
||||
echo " Password: admin"
|
||||
echo ""
|
||||
echo "📋 Running in foreground with live logs (Ctrl+C to stop)..."
|
||||
|
||||
# Run docker-compose and capture exit code
|
||||
if [ "$ENABLE_MCP" = "true" ]; then
|
||||
echo "🤖 Starting with MCP Service enabled..."
|
||||
docker-compose -f docker-compose-light.yml --profile mcp up
|
||||
else
|
||||
docker-compose -f docker-compose-light.yml up
|
||||
fi
|
||||
# Start in detached mode
|
||||
docker-compose -f docker-compose-light.yml up -d
|
||||
|
||||
echo ""
|
||||
echo "✅ Docker Compose started successfully!"
|
||||
echo ""
|
||||
echo "📋 Important information:"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "⏱️ Initial startup takes 10-20 minutes"
|
||||
echo "🌐 Check the 'Ports' tab for your Superset URL (port 9001)"
|
||||
echo "👤 Login: admin / admin"
|
||||
echo ""
|
||||
echo "📊 Useful commands:"
|
||||
echo " docker-compose -f docker-compose-light.yml logs -f # Follow logs"
|
||||
echo " docker-compose -f docker-compose-light.yml ps # Check status"
|
||||
echo " docker-compose -f docker-compose-light.yml down # Stop services"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo "💤 Keeping terminal open for 60 seconds to test persistence..."
|
||||
sleep 60
|
||||
echo "✅ Test complete - check if this terminal is still visible!"
|
||||
|
||||
# Show final status
|
||||
docker-compose -f docker-compose-light.yml ps
|
||||
EXIT_CODE=$?
|
||||
|
||||
# If it failed, provide helpful instructions
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
// Extend the base configuration
|
||||
"extends": "../devcontainer-base.json",
|
||||
|
||||
"name": "Apache Superset Development with MCP",
|
||||
|
||||
// Forward ports for development
|
||||
"forwardPorts": [9001, 5008],
|
||||
"portsAttributes": {
|
||||
"9001": {
|
||||
"label": "Superset (via Webpack Dev Server)",
|
||||
"onAutoForward": "notify",
|
||||
"visibility": "public"
|
||||
},
|
||||
"5008": {
|
||||
"label": "MCP Service (Model Context Protocol)",
|
||||
"onAutoForward": "notify",
|
||||
"visibility": "private"
|
||||
}
|
||||
},
|
||||
|
||||
// Auto-start Superset with MCP on Codespace resume
|
||||
"postStartCommand": "ENABLE_MCP=true .devcontainer/start-superset.sh",
|
||||
|
||||
// Environment variables
|
||||
"containerEnv": {
|
||||
"ENABLE_MCP": "true"
|
||||
}
|
||||
}
|
||||
23
.github/workflows/bashlib.sh
vendored
23
.github/workflows/bashlib.sh
vendored
@@ -195,7 +195,6 @@ playwright-install() {
|
||||
|
||||
playwright-run() {
|
||||
local APP_ROOT=$1
|
||||
local TEST_PATH=$2
|
||||
|
||||
# Start Flask from the project root (same as Cypress)
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
@@ -239,26 +238,8 @@ playwright-run() {
|
||||
|
||||
say "::group::Run Playwright tests"
|
||||
echo "Running Playwright with baseURL: ${PLAYWRIGHT_BASE_URL}"
|
||||
if [ -n "$TEST_PATH" ]; then
|
||||
# Check if there are any test files in the specified path
|
||||
if ! find "playwright/tests/${TEST_PATH}" -name "*.spec.ts" -type f 2>/dev/null | grep -q .; then
|
||||
echo "No test files found in ${TEST_PATH} - skipping test run"
|
||||
say "::endgroup::"
|
||||
kill $flaskProcessId
|
||||
return 0
|
||||
fi
|
||||
echo "Running tests: ${TEST_PATH}"
|
||||
# Set INCLUDE_EXPERIMENTAL=true to allow experimental tests to run
|
||||
export INCLUDE_EXPERIMENTAL=true
|
||||
npx playwright test "${TEST_PATH}" --output=playwright-results
|
||||
local status=$?
|
||||
# Unset to prevent leaking into subsequent commands
|
||||
unset INCLUDE_EXPERIMENTAL
|
||||
else
|
||||
echo "Running all required tests (experimental/ excluded via playwright.config.ts)"
|
||||
npx playwright test --output=playwright-results
|
||||
local status=$?
|
||||
fi
|
||||
npx playwright test auth/login --reporter=github --output=playwright-results
|
||||
local status=$?
|
||||
say "::endgroup::"
|
||||
|
||||
# After job is done, print out Flask log for debugging
|
||||
|
||||
115
.github/workflows/superset-e2e.yml
vendored
115
.github/workflows/superset-e2e.yml
vendored
@@ -151,118 +151,3 @@ jobs:
|
||||
with:
|
||||
path: ${{ github.workspace }}/superset-frontend/cypress-base/cypress/screenshots
|
||||
name: cypress-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}-${{ matrix.parallel_id }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
|
||||
|
||||
playwright-tests:
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
browser: ["chromium"]
|
||||
app_root: ["", "/app/prefix"]
|
||||
env:
|
||||
SUPERSET_ENV: development
|
||||
SUPERSET_CONFIG: tests.integration_tests.superset_test_config
|
||||
SUPERSET__SQLALCHEMY_DATABASE_URI: postgresql+psycopg2://superset:superset@127.0.0.1:15432/superset
|
||||
PYTHONPATH: ${{ github.workspace }}
|
||||
REDIS_PORT: 16379
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
env:
|
||||
POSTGRES_USER: superset
|
||||
POSTGRES_PASSWORD: superset
|
||||
ports:
|
||||
- 15432:5432
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
ports:
|
||||
- 16379:6379
|
||||
steps:
|
||||
# -------------------------------------------------------
|
||||
# Conditional checkout based on context (same as Cypress workflow)
|
||||
- name: Checkout for push or pull_request event
|
||||
if: github.event_name == 'push' || github.event_name == 'pull_request'
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: recursive
|
||||
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
||||
- name: Checkout using ref (workflow_dispatch)
|
||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.ref != ''
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
submodules: recursive
|
||||
- name: Checkout using PR ID (workflow_dispatch)
|
||||
if: github.event_name == 'workflow_dispatch' && github.event.inputs.pr_id != ''
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
ref: refs/pull/${{ github.event.inputs.pr_id }}/merge
|
||||
submodules: recursive
|
||||
# -------------------------------------------------------
|
||||
- name: Check for file changes
|
||||
id: check
|
||||
uses: ./.github/actions/change-detector/
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Setup Python
|
||||
uses: ./.github/actions/setup-backend/
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
- name: Setup postgres
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: setup-postgres
|
||||
- name: Import test data
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: testdata
|
||||
- name: Setup Node.js
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version-file: './superset-frontend/.nvmrc'
|
||||
- name: Install npm dependencies
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: npm-install
|
||||
- name: Build javascript packages
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: build-instrumented-assets
|
||||
- name: Install Playwright
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: playwright-install
|
||||
- name: Run Playwright (Required Tests)
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
env:
|
||||
NODE_OPTIONS: "--max-old-space-size=4096"
|
||||
with:
|
||||
run: playwright-run "${{ matrix.app_root }}"
|
||||
- name: Set safe app root
|
||||
if: failure()
|
||||
id: set-safe-app-root
|
||||
run: |
|
||||
APP_ROOT="${{ matrix.app_root }}"
|
||||
SAFE_APP_ROOT=${APP_ROOT//\//_}
|
||||
echo "safe_app_root=$SAFE_APP_ROOT" >> $GITHUB_OUTPUT
|
||||
- name: Upload Playwright Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/superset-frontend/playwright-results/
|
||||
${{ github.workspace }}/superset-frontend/test-results/
|
||||
name: playwright-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
|
||||
|
||||
6
.github/workflows/superset-frontend.yml
vendored
6
.github/workflows/superset-frontend.yml
vendored
@@ -135,15 +135,15 @@ jobs:
|
||||
run: |
|
||||
docker load < docker-image.tar.gz
|
||||
|
||||
- name: lint
|
||||
- name: eslint
|
||||
run: |
|
||||
docker run --rm $TAG bash -c \
|
||||
"npm i && npm run lint"
|
||||
"npm i && npm run eslint -- . --quiet"
|
||||
|
||||
- name: tsc
|
||||
run: |
|
||||
docker run --rm $TAG bash -c \
|
||||
"npm i && npm run plugins:build && npm run type"
|
||||
"npm run plugins:build && npm run type"
|
||||
|
||||
validate-frontend:
|
||||
needs: frontend-build
|
||||
|
||||
13
.github/workflows/superset-playwright.yml
vendored
13
.github/workflows/superset-playwright.yml
vendored
@@ -1,4 +1,4 @@
|
||||
name: Playwright Experimental Tests
|
||||
name: Playwright E2E Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -23,10 +23,9 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
# NOTE: Required Playwright tests are in superset-e2e.yml (E2E / playwright-tests)
|
||||
# This workflow contains only experimental tests that run in shadow mode
|
||||
playwright-tests-experimental:
|
||||
playwright-tests:
|
||||
runs-on: ubuntu-22.04
|
||||
# Allow workflow to succeed even if tests fail during shadow mode
|
||||
continue-on-error: true
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -118,13 +117,13 @@ jobs:
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
with:
|
||||
run: playwright-install
|
||||
- name: Run Playwright (Experimental Tests)
|
||||
- name: Run Playwright
|
||||
if: steps.check.outputs.python || steps.check.outputs.frontend
|
||||
uses: ./.github/actions/cached-dependencies
|
||||
env:
|
||||
NODE_OPTIONS: "--max-old-space-size=4096"
|
||||
with:
|
||||
run: playwright-run "${{ matrix.app_root }}" experimental/
|
||||
run: playwright-run ${{ matrix.app_root }}
|
||||
- name: Set safe app root
|
||||
if: failure()
|
||||
id: set-safe-app-root
|
||||
@@ -139,4 +138,4 @@ jobs:
|
||||
path: |
|
||||
${{ github.workspace }}/superset-frontend/playwright-results/
|
||||
${{ github.workspace }}/superset-frontend/test-results/
|
||||
name: playwright-experimental-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
|
||||
name: playwright-artifact-${{ github.run_id }}-${{ github.job }}-${{ matrix.browser }}--${{ steps.set-safe-app-root.outputs.safe_app_root }}
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -33,7 +33,6 @@ cover
|
||||
.env
|
||||
.envrc
|
||||
.idea
|
||||
.roo
|
||||
.mypy_cache
|
||||
.python-version
|
||||
.tox
|
||||
@@ -122,8 +121,6 @@ docker/requirements-local.txt
|
||||
|
||||
cache/
|
||||
docker/*local*
|
||||
docker/superset-websocket/config.json
|
||||
docker-compose.override.yml
|
||||
|
||||
.temp_cache
|
||||
|
||||
@@ -137,4 +134,3 @@ PROJECT.md
|
||||
.aider*
|
||||
.claude_rc*
|
||||
.env.local
|
||||
oxc-custom-build/
|
||||
|
||||
@@ -60,23 +60,9 @@ repos:
|
||||
args: ["--markdown-linebreak-ext=md"]
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: prettier-frontend
|
||||
name: prettier (frontend)
|
||||
entry: bash -c 'cd superset-frontend && for file in "$@"; do npx prettier --write "${file#superset-frontend/}"; done'
|
||||
language: system
|
||||
pass_filenames: true
|
||||
files: ^superset-frontend/.*\.(js|jsx|ts|tsx|css|scss|sass|json)$
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: oxlint-frontend
|
||||
name: oxlint (frontend)
|
||||
entry: ./scripts/oxlint.sh
|
||||
language: system
|
||||
pass_filenames: true
|
||||
files: ^superset-frontend/.*\.(js|jsx|ts|tsx)$
|
||||
- id: custom-rules-frontend
|
||||
name: custom rules (frontend)
|
||||
entry: ./scripts/check-custom-rules.sh
|
||||
- id: eslint-frontend
|
||||
name: eslint (frontend)
|
||||
entry: ./scripts/eslint.sh
|
||||
language: system
|
||||
pass_filenames: true
|
||||
files: ^superset-frontend/.*\.(js|jsx|ts|tsx)$
|
||||
@@ -124,12 +110,9 @@ repos:
|
||||
- -c
|
||||
- |
|
||||
TARGET_BRANCH=${GITHUB_BASE_REF:-master}
|
||||
# Only fetch if we're not in CI (CI already has all refs)
|
||||
if [ -z "$CI" ]; then
|
||||
git fetch --no-recurse-submodules origin "$TARGET_BRANCH" 2>/dev/null || true
|
||||
fi
|
||||
BASE=$(git merge-base origin/"$TARGET_BRANCH" HEAD 2>/dev/null) || BASE="HEAD"
|
||||
files=$(git diff --name-only --diff-filter=ACM "$BASE"..HEAD 2>/dev/null | grep '^superset/.*\.py$' || true)
|
||||
git fetch origin "$TARGET_BRANCH"
|
||||
BASE=$(git merge-base origin/"$TARGET_BRANCH" HEAD)
|
||||
files=$(git diff --name-only --diff-filter=ACM "$BASE"..HEAD | grep '^superset/.*\.py$' || true)
|
||||
if [ -n "$files" ]; then
|
||||
pylint --rcfile=.pylintrc --load-plugins=superset.extensions.pylint --reports=no $files
|
||||
else
|
||||
|
||||
@@ -53,7 +53,7 @@ extension-pkg-whitelist=pyarrow
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
disable=all
|
||||
enable=json-import,disallowed-sql-import,consider-using-transaction
|
||||
enable=disallowed-json-import,disallowed-sql-import,consider-using-transaction
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
.nvmrc
|
||||
.prettierrc
|
||||
.rat-excludes
|
||||
.swcrc
|
||||
.*log
|
||||
.*pyc
|
||||
.*lock
|
||||
|
||||
@@ -25,14 +25,14 @@ little bit helps, and credit will always be given.
|
||||
|
||||
All developer and contribution documentation has moved to the Apache Superset Developer Portal:
|
||||
|
||||
**[📚 View the Developer Portal →](https://superset.apache.org/developer_portal/)**
|
||||
**[📚 View the Developer Portal →](https://superset.apache.org/docs/developer-portal/)**
|
||||
|
||||
The Developer Portal includes comprehensive guides for:
|
||||
- [Contributing Overview](https://superset.apache.org/developer_portal/contributing/overview)
|
||||
- [Development Setup](https://superset.apache.org/developer_portal/contributing/development-setup)
|
||||
- [Submitting Pull Requests](https://superset.apache.org/developer_portal/contributing/submitting-pr)
|
||||
- [Contribution Guidelines](https://superset.apache.org/developer_portal/contributing/guidelines)
|
||||
- [Code Review Process](https://superset.apache.org/developer_portal/contributing/code-review)
|
||||
- [Development How-tos](https://superset.apache.org/developer_portal/contributing/howtos)
|
||||
- [Contributing Overview](https://superset.apache.org/docs/developer-portal/contributing/overview)
|
||||
- [Development Setup](https://superset.apache.org/docs/developer-portal/contributing/development-setup)
|
||||
- [Submitting Pull Requests](https://superset.apache.org/docs/developer-portal/contributing/submitting-pr)
|
||||
- [Contribution Guidelines](https://superset.apache.org/docs/developer-portal/contributing/guidelines)
|
||||
- [Code Review Process](https://superset.apache.org/docs/developer-portal/contributing/code-review)
|
||||
- [Development How-tos](https://superset.apache.org/docs/developer-portal/contributing/howtos)
|
||||
|
||||
Source for the Developer Portal documentation is [located here](https://github.com/apache/superset/tree/master/docs/developer_portal).
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
######################################################################
|
||||
# Node stage to deal with static asset construction
|
||||
######################################################################
|
||||
ARG PY_VER=3.11.14-slim-trixie
|
||||
ARG PY_VER=3.11.13-slim-trixie
|
||||
|
||||
# If BUILDPLATFORM is null, set it to 'amd64' (or leave as is otherwise).
|
||||
ARG BUILDPLATFORM=${BUILDPLATFORM:-amd64}
|
||||
@@ -171,8 +171,6 @@ RUN mkdir -p \
|
||||
&& touch superset/static/version_info.json
|
||||
|
||||
# Install Playwright and optionally setup headless browsers
|
||||
ENV PLAYWRIGHT_BROWSERS_PATH=/usr/local/share/playwright-browsers
|
||||
|
||||
ARG INCLUDE_CHROMIUM="false"
|
||||
ARG INCLUDE_FIREFOX="false"
|
||||
RUN --mount=type=cache,target=${SUPERSET_HOME}/.cache/uv \
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
# Superset Frontend Linting Architecture
|
||||
|
||||
## Overview
|
||||
We use a hybrid linting approach combining OXC (fast, standard rules) with custom AST-based checks for Superset-specific patterns.
|
||||
|
||||
## Components
|
||||
|
||||
### 1. Primary Linter: OXC
|
||||
- **What**: Oxidation Compiler's linter (oxlint)
|
||||
- **Handles**: 95% of linting rules (standard ESLint rules, TypeScript, React, etc.)
|
||||
- **Speed**: ~50-100x faster than ESLint
|
||||
- **Config**: `oxlint.json`
|
||||
|
||||
### 2. Custom Rule Checker
|
||||
- **What**: Node.js AST-based script
|
||||
- **Handles**: Superset-specific rules:
|
||||
- No literal colors (use theme)
|
||||
- No FontAwesome icons (use Icons component)
|
||||
- No template vars in i18n
|
||||
- **Speed**: Fast enough for pre-commit
|
||||
- **Script**: `scripts/check-custom-rules.js`
|
||||
|
||||
## Developer Workflow
|
||||
|
||||
### Local Development
|
||||
```bash
|
||||
# Fast linting (OXC only)
|
||||
npm run lint
|
||||
|
||||
# Full linting (OXC + custom rules)
|
||||
npm run lint:full
|
||||
|
||||
# Auto-fix what's possible
|
||||
npm run lint-fix
|
||||
```
|
||||
|
||||
### Pre-commit
|
||||
1. OXC runs first (via `scripts/oxlint.sh`)
|
||||
2. Custom rules check runs second (lightweight, AST-based)
|
||||
3. Both must pass for commit to succeed
|
||||
|
||||
### CI Pipeline
|
||||
```yaml
|
||||
- name: Lint with OXC
|
||||
run: npm run lint
|
||||
|
||||
- name: Check custom rules
|
||||
run: npm run check:custom-rules
|
||||
```
|
||||
|
||||
## Why This Architecture?
|
||||
|
||||
### ✅ Pros
|
||||
1. **No binary distribution issues** - ASF compatible
|
||||
2. **Fast performance** - OXC for bulk, lightweight script for custom
|
||||
3. **Maintainable** - Custom rules in JavaScript, not Rust
|
||||
4. **Flexible** - Can evolve as OXC adds plugin support
|
||||
5. **Cacheable** - Both OXC and Node.js are standard tools
|
||||
|
||||
### ❌ Cons
|
||||
1. **Two tools** - Slightly more complex than single linter
|
||||
2. **Duplicate parsing** - Files parsed twice (once by each tool)
|
||||
|
||||
### 🔄 Migration Path
|
||||
When OXC supports JavaScript plugins:
|
||||
1. Convert `check-custom-rules.js` to OXC plugin format
|
||||
2. Consolidate back to single tool
|
||||
3. Keep same rules and developer experience
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
- [x] OXC for standard linting
|
||||
- [x] Pre-commit integration
|
||||
- [ ] Custom rules script
|
||||
- [ ] Combine in npm scripts
|
||||
- [ ] Update CI pipeline
|
||||
- [ ] Developer documentation
|
||||
|
||||
## Performance Targets
|
||||
|
||||
| Operation | Target Time | Current |
|
||||
|-----------|------------|---------|
|
||||
| Pre-commit (changed files) | <2s | ✅ 1.5s |
|
||||
| Full lint (all files) | <10s | ✅ 8s |
|
||||
| Custom rules check | <5s | 🔄 TBD |
|
||||
|
||||
## Caching Strategy
|
||||
|
||||
### Local Development
|
||||
- OXC: Built-in incremental checking
|
||||
- Custom rules: Use file hash cache (similar to pytest cache)
|
||||
|
||||
### CI
|
||||
- Cache `node_modules` (includes oxlint binary)
|
||||
- Cache custom rules results by commit hash
|
||||
- Skip unchanged files using git diff
|
||||
|
||||
## Future Improvements
|
||||
|
||||
1. **When OXC adds plugin support**: Migrate custom rules to OXC plugins
|
||||
2. **Consider Biome**: Another Rust-based linter with plugin support
|
||||
3. **AST sharing**: Investigate sharing AST between tools to avoid double parsing
|
||||
103
UPDATING.md
103
UPDATING.md
@@ -23,107 +23,6 @@ This file documents any backwards-incompatible changes in Superset and
|
||||
assists people when migrating to a new version.
|
||||
|
||||
## Next
|
||||
|
||||
### MCP Service
|
||||
|
||||
The MCP (Model Context Protocol) service enables AI assistants and automation tools to interact programmatically with Superset.
|
||||
|
||||
#### New Features
|
||||
- MCP service infrastructure with FastMCP framework
|
||||
- Tools for dashboards, charts, datasets, SQL Lab, and instance metadata
|
||||
- Optional dependency: install with `pip install apache-superset[fastmcp]`
|
||||
- Runs as separate process from Superset web server
|
||||
- JWT-based authentication for production deployments
|
||||
|
||||
#### New Configuration Options
|
||||
|
||||
**Development** (single-user, local testing):
|
||||
```python
|
||||
# superset_config.py
|
||||
MCP_DEV_USERNAME = "admin" # User for MCP authentication
|
||||
MCP_SERVICE_HOST = "localhost"
|
||||
MCP_SERVICE_PORT = 5008
|
||||
```
|
||||
|
||||
**Production** (JWT-based, multi-user):
|
||||
```python
|
||||
# superset_config.py
|
||||
MCP_AUTH_ENABLED = True
|
||||
MCP_JWT_ISSUER = "https://your-auth-provider.com"
|
||||
MCP_JWT_AUDIENCE = "superset-mcp"
|
||||
MCP_JWT_ALGORITHM = "RS256" # or "HS256" for shared secrets
|
||||
|
||||
# Option 1: Use JWKS endpoint (recommended for RS256)
|
||||
MCP_JWKS_URI = "https://auth.example.com/.well-known/jwks.json"
|
||||
|
||||
# Option 2: Use static public key (RS256)
|
||||
MCP_JWT_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----..."
|
||||
|
||||
# Option 3: Use shared secret (HS256)
|
||||
MCP_JWT_ALGORITHM = "HS256"
|
||||
MCP_JWT_SECRET = "your-shared-secret-key"
|
||||
|
||||
# Optional overrides
|
||||
MCP_SERVICE_HOST = "0.0.0.0"
|
||||
MCP_SERVICE_PORT = 5008
|
||||
MCP_SESSION_CONFIG = {
|
||||
"SESSION_COOKIE_SECURE": True,
|
||||
"SESSION_COOKIE_HTTPONLY": True,
|
||||
"SESSION_COOKIE_SAMESITE": "Strict",
|
||||
}
|
||||
```
|
||||
|
||||
#### Running the MCP Service
|
||||
|
||||
```bash
|
||||
# Development
|
||||
superset mcp run --port 5008 --debug
|
||||
|
||||
# Production
|
||||
superset mcp run --port 5008
|
||||
|
||||
# With factory config
|
||||
superset mcp run --port 5008 --use-factory-config
|
||||
```
|
||||
|
||||
#### Deployment Considerations
|
||||
|
||||
The MCP service runs as a **separate process** from the Superset web server.
|
||||
|
||||
**Important**:
|
||||
- Requires same Python environment and configuration as Superset
|
||||
- Shares database connections with main Superset app
|
||||
- Can be scaled independently from web server
|
||||
- Requires `fastmcp` package (optional dependency)
|
||||
|
||||
**Installation**:
|
||||
```bash
|
||||
# Install with MCP support
|
||||
pip install apache-superset[fastmcp]
|
||||
|
||||
# Or add to requirements.txt
|
||||
apache-superset[fastmcp]>=X.Y.Z
|
||||
```
|
||||
|
||||
**Process Management**:
|
||||
Use systemd, supervisord, or Kubernetes to manage the MCP service process.
|
||||
See `superset/mcp_service/PRODUCTION.md` for deployment guides.
|
||||
|
||||
**Security**:
|
||||
- Development: Uses `MCP_DEV_USERNAME` for single-user access
|
||||
- Production: **MUST** configure JWT authentication
|
||||
- See `superset/mcp_service/SECURITY.md` for details
|
||||
|
||||
#### Documentation
|
||||
|
||||
- Architecture: `superset/mcp_service/ARCHITECTURE.md`
|
||||
- Security: `superset/mcp_service/SECURITY.md`
|
||||
- Production: `superset/mcp_service/PRODUCTION.md`
|
||||
- Developer Guide: `superset/mcp_service/CLAUDE.md`
|
||||
- Quick Start: `superset/mcp_service/README.md`
|
||||
|
||||
---
|
||||
|
||||
- [33055](https://github.com/apache/superset/pull/33055): Upgrades Flask-AppBuilder to 5.0.0. The AUTH_OID authentication type has been deprecated and is no longer available as an option in Flask-AppBuilder. OpenID (OID) is considered a deprecated authentication protocol - if you are using AUTH_OID, you will need to migrate to an alternative authentication method such as OAuth, LDAP, or database authentication before upgrading.
|
||||
- [35062](https://github.com/apache/superset/pull/35062): Changed the function signature of `setupExtensions` to `setupCodeOverrides` with options as arguments.
|
||||
- [34871](https://github.com/apache/superset/pull/34871): Fixed Jest test hanging issue from Ant Design v5 upgrade. MessageChannel is now mocked in test environment to prevent rc-overflow from causing Jest to hang. Test environment only - no production impact.
|
||||
@@ -142,7 +41,7 @@ Note: Pillow is now a required dependency (previously optional) to support image
|
||||
- [33116](https://github.com/apache/superset/pull/33116) In Echarts Series charts (e.g. Line, Area, Bar, etc.) charts, the `x_axis_sort_series` and `x_axis_sort_series_ascending` form data items have been renamed with `x_axis_sort` and `x_axis_sort_asc`.
|
||||
There's a migration added that can potentially affect a significant number of existing charts.
|
||||
- [32317](https://github.com/apache/superset/pull/32317) The horizontal filter bar feature is now out of testing/beta development and its feature flag `HORIZONTAL_FILTER_BAR` has been removed.
|
||||
- [31590](https://github.com/apache/superset/pull/31590) Marks the beginning of intricate work around supporting dynamic Theming, and breaks support for [THEME_OVERRIDES](https://github.com/apache/superset/blob/732de4ac7fae88e29b7f123b6cbb2d7cd411b0e4/superset/config.py#L671) in favor of a new theming system based on AntD V5. Likely this will be in disrepair until settling over the 5.x lifecycle.
|
||||
- [31590](https://github.com/apache/superset/pull/31590) Marks the begining of intricate work around supporting dynamic Theming, and breaks support for [THEME_OVERRIDES](https://github.com/apache/superset/blob/732de4ac7fae88e29b7f123b6cbb2d7cd411b0e4/superset/config.py#L671) in favor of a new theming system based on AntD V5. Likely this will be in disrepair until settling over the 5.x lifecycle.
|
||||
- [32432](https://github.com/apache/superset/pull/31260) Moves the List Roles FAB view to the frontend and requires `FAB_ADD_SECURITY_API` to be enabled in the configuration and `superset init` to be executed.
|
||||
- [34319](https://github.com/apache/superset/pull/34319) Drill to Detail and Drill By is now supported in Embedded mode, and also with the `DASHBOARD_RBAC` FF. If you don't want to expose these features in Embedded / `DASHBOARD_RBAC`, make sure the roles used for Embedded / `DASHBOARD_RBAC`don't have the required permissions to perform D2D actions.
|
||||
|
||||
|
||||
@@ -137,9 +137,9 @@ services:
|
||||
- /home/superset-websocket/node_modules
|
||||
- /home/superset-websocket/dist
|
||||
|
||||
# Mount config file. Create your own docker/superset-websocket/config.json
|
||||
# for custom settings, then point to it here. Do not use this example in production.
|
||||
- ./docker/superset-websocket/config.example.json:/home/superset-websocket/config.json:ro
|
||||
# Mounting a config file that contains a dummy secret required to boot up.
|
||||
# do not use this docker compose in production
|
||||
- ./docker/superset-websocket/config.json:/home/superset-websocket/config.json
|
||||
environment:
|
||||
- PORT=8080
|
||||
- REDIS_HOST=redis
|
||||
|
||||
@@ -34,24 +34,8 @@ intended for use with local development.
|
||||
|
||||
### Local overrides
|
||||
|
||||
#### Environment Variables
|
||||
|
||||
To override environment variables locally, create a `./docker/.env-local` file (git-ignored). This file will be loaded after `.env` and can override any settings.
|
||||
|
||||
#### Python Configuration
|
||||
|
||||
In order to override configuration settings locally, simply make a copy of [`./docker/pythonpath_dev/superset_config_local.example`](./pythonpath_dev/superset_config_local.example)
|
||||
into `./docker/pythonpath_dev/superset_config_docker.py` (git-ignored) and fill in your overrides.
|
||||
|
||||
#### WebSocket Configuration
|
||||
|
||||
To customize the WebSocket server configuration, create `./docker/superset-websocket/config.json` (git-ignored) based on [`./docker/superset-websocket/config.example.json`](./superset-websocket/config.example.json).
|
||||
|
||||
Then update the `superset-websocket`.`volumes` config to mount it.
|
||||
|
||||
#### Docker Compose Overrides
|
||||
|
||||
For advanced Docker Compose customization, create a `docker-compose-override.yml` file (git-ignored) to override or extend services without modifying the main compose file.
|
||||
into `./docker/pythonpath_dev/superset_config_docker.py` (git ignored) and fill in your overrides.
|
||||
|
||||
### Local packages
|
||||
|
||||
|
||||
@@ -80,16 +80,12 @@ case "${1}" in
|
||||
;;
|
||||
app)
|
||||
echo "Starting web app (using development server)..."
|
||||
flask run -p $PORT --reload --debugger --without-threads --host=0.0.0.0 --exclude-patterns "*/node_modules/*:*/.venv/*:*/build/*:*/__pycache__/*"
|
||||
flask run -p $PORT --reload --debugger --without-threads --host=0.0.0.0
|
||||
;;
|
||||
app-gunicorn)
|
||||
echo "Starting web app..."
|
||||
/usr/bin/run-server.sh
|
||||
;;
|
||||
mcp)
|
||||
echo "Starting MCP service..."
|
||||
superset mcp run --host 0.0.0.0 --port ${MCP_PORT:-5008} --debug
|
||||
;;
|
||||
*)
|
||||
echo "Unknown Operation!!!"
|
||||
;;
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"port": 8080,
|
||||
"logLevel": "info",
|
||||
"logToFile": false,
|
||||
"logFilename": "app.log",
|
||||
"statsd": {
|
||||
"host": "127.0.0.1",
|
||||
"port": 8125,
|
||||
"globalTags": []
|
||||
},
|
||||
"redis": {
|
||||
"port": 6379,
|
||||
"host": "127.0.0.1",
|
||||
"password": "",
|
||||
"db": 0,
|
||||
"ssl": false
|
||||
},
|
||||
"redisStreamPrefix": "async-events-",
|
||||
"jwtAlgorithms": ["HS256"],
|
||||
"jwtSecret": "CHANGE-ME-IN-PRODUCTION-GOTTA-BE-LONG-AND-SECRET",
|
||||
"jwtCookieName": "async-token"
|
||||
}
|
||||
772
docs/developer_portal/api/frontend.md
Normal file
772
docs/developer_portal/api/frontend.md
Normal file
@@ -0,0 +1,772 @@
|
||||
---
|
||||
title: Frontend API Reference
|
||||
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.
|
||||
-->
|
||||
|
||||
# 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.
|
||||
|
||||
```typescript
|
||||
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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
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
|
||||
|
||||
```typescript
|
||||
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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
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
|
||||
|
||||
```typescript
|
||||
import {
|
||||
Table,
|
||||
List,
|
||||
Card,
|
||||
Collapse,
|
||||
Tabs,
|
||||
Tag,
|
||||
Badge,
|
||||
Statistic,
|
||||
Timeline,
|
||||
Tree,
|
||||
Empty,
|
||||
Result
|
||||
} from '@apache-superset/core';
|
||||
```
|
||||
|
||||
### Form Components
|
||||
|
||||
```typescript
|
||||
import {
|
||||
Form,
|
||||
FormItem,
|
||||
FormList,
|
||||
InputNumber,
|
||||
TextArea,
|
||||
Upload,
|
||||
Rate,
|
||||
Cascader,
|
||||
AutoComplete,
|
||||
Mentions
|
||||
} from '@apache-superset/core';
|
||||
```
|
||||
|
||||
## Authentication API
|
||||
|
||||
Access authentication and user information.
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
// 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.
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
// 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.
|
||||
|
||||
```typescript
|
||||
// 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.
|
||||
|
||||
```typescript
|
||||
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.
|
||||
|
||||
```typescript
|
||||
// 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.
|
||||
|
||||
```typescript
|
||||
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:
|
||||
|
||||
```typescript
|
||||
import type {
|
||||
ExtensionContext,
|
||||
Disposable,
|
||||
Event,
|
||||
EventEmitter,
|
||||
Uri,
|
||||
Command,
|
||||
QuickPickItem,
|
||||
InputBoxOptions,
|
||||
Progress,
|
||||
CancellationToken
|
||||
} from '@apache-superset/core';
|
||||
```
|
||||
|
||||
## Version Compatibility
|
||||
|
||||
The API follows semantic versioning:
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
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
|
||||
|
||||
```typescript
|
||||
// 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
|
||||
|
||||
```typescript
|
||||
// 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;
|
||||
}
|
||||
```
|
||||
194
docs/developer_portal/architecture/overview.md
Normal file
194
docs/developer_portal/architecture/overview.md
Normal file
@@ -0,0 +1,194 @@
|
||||
---
|
||||
title: Extension Architecture
|
||||
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.
|
||||
-->
|
||||
|
||||
# Superset Extension Architecture
|
||||
|
||||
Apache Superset's extension architecture enables developers to enhance and customize the platform without modifying the core codebase. Inspired by the successful VS Code Extensions model, this architecture provides well-defined, versioned APIs and clear contribution points that allow the community to build upon and extend Superset's functionality.
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### Extensions vs Plugins
|
||||
|
||||
We use the term "extensions" rather than "plugins" to better convey the idea of enhancing and expanding Superset's core capabilities in a modular and integrated way. Extensions can add new features, modify existing behavior, and integrate deeply with the host application through well-defined APIs.
|
||||
|
||||
### Lean Core Philosophy
|
||||
|
||||
Superset's core remains minimal, with many features delegated to extensions. Built-in features are implemented using the same APIs available to external extension authors, ensuring consistency and validating the extension architecture through real-world usage.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
The extension architecture consists of several key components:
|
||||
|
||||
### Core Packages
|
||||
|
||||
#### @apache-superset/core (Frontend)
|
||||
Provides essential building blocks for extensions:
|
||||
- Shared UI components
|
||||
- Utility functions
|
||||
- Type definitions
|
||||
- Frontend APIs for interacting with the host
|
||||
|
||||
#### apache-superset-core (Backend)
|
||||
Exposes backend functionality:
|
||||
- Database access APIs
|
||||
- Security models
|
||||
- REST API extensions
|
||||
- SQLAlchemy models and utilities
|
||||
|
||||
### Extension CLI
|
||||
|
||||
The `apache-superset-extensions-cli` package provides commands for:
|
||||
- Scaffolding new extension projects
|
||||
- Building and bundling extensions
|
||||
- Development workflows with hot-reload
|
||||
- Packaging extensions for distribution
|
||||
|
||||
### Host Application
|
||||
|
||||
Superset acts as the host, providing:
|
||||
- Extension registration and management
|
||||
- Dynamic loading of extension assets
|
||||
- API implementation for extensions
|
||||
- Lifecycle management (activation/deactivation)
|
||||
|
||||
## Extension Points
|
||||
|
||||
Extensions can contribute to various parts of Superset:
|
||||
|
||||
### SQL Lab Extensions
|
||||
- Custom panels (left, right, bottom)
|
||||
- Editor enhancements
|
||||
- Query processors
|
||||
- Autocomplete providers
|
||||
- Execution plan visualizers
|
||||
|
||||
### Dashboard Extensions (Future)
|
||||
- Custom widget types
|
||||
- Filter components
|
||||
- Interaction handlers
|
||||
|
||||
### Chart Extensions (Future)
|
||||
- New visualization types
|
||||
- Data transformers
|
||||
- Export formats
|
||||
|
||||
## Technical Foundation
|
||||
|
||||
### Module Federation
|
||||
|
||||
Frontend extensions leverage Webpack Module Federation for dynamic loading:
|
||||
- Extensions are built independently
|
||||
- Dependencies are shared with the host
|
||||
- No rebuild of Superset required
|
||||
- Runtime loading of extension assets
|
||||
|
||||
### API Versioning
|
||||
|
||||
All public APIs follow semantic versioning:
|
||||
- Breaking changes require major version bumps
|
||||
- Extensions declare compatibility requirements
|
||||
- Backward compatibility maintained within major versions
|
||||
|
||||
### Security Model
|
||||
|
||||
- Extensions disabled by default (require `ENABLE_EXTENSIONS` flag)
|
||||
- Built-in extensions follow same security standards as core
|
||||
- External extensions run in same context as host (sandboxing planned)
|
||||
- Administrators responsible for vetting third-party extensions
|
||||
|
||||
## Development Workflow
|
||||
|
||||
1. **Initialize**: Use CLI to scaffold new extension
|
||||
2. **Develop**: Work with hot-reload in development mode
|
||||
3. **Build**: Bundle frontend and backend assets
|
||||
4. **Package**: Create `.supx` distribution file
|
||||
5. **Deploy**: Upload through API or management UI
|
||||
|
||||
## Example: Dataset References Extension
|
||||
|
||||
A practical example demonstrating the architecture:
|
||||
|
||||
```typescript
|
||||
// Frontend activation
|
||||
export function activate(context) {
|
||||
// Register a new SQL Lab panel
|
||||
const panel = core.registerView('dataset_references.main',
|
||||
<DatasetReferencesPanel />
|
||||
);
|
||||
|
||||
// Listen to query changes
|
||||
const listener = sqlLab.onDidQueryRun(editor => {
|
||||
// Analyze query and update panel
|
||||
});
|
||||
|
||||
// Cleanup on deactivation
|
||||
context.subscriptions.push(panel, listener);
|
||||
}
|
||||
```
|
||||
|
||||
```python
|
||||
# Backend API extension
|
||||
from superset_core.api import rest_api
|
||||
from .api import DatasetReferencesAPI
|
||||
|
||||
# Register custom REST endpoints
|
||||
rest_api.add_extension_api(DatasetReferencesAPI)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Extension Design
|
||||
- Keep extensions focused on specific functionality
|
||||
- Use versioned APIs for stability
|
||||
- Handle cleanup properly on deactivation
|
||||
- Follow Superset's coding standards
|
||||
|
||||
### Performance
|
||||
- Lazy load assets when possible
|
||||
- Minimize bundle sizes
|
||||
- Share dependencies with host
|
||||
- Cache expensive operations
|
||||
|
||||
### Compatibility
|
||||
- Declare API version requirements
|
||||
- Test across Superset versions
|
||||
- Provide migration guides for breaking changes
|
||||
- Document compatibility clearly
|
||||
|
||||
## Future Roadmap
|
||||
|
||||
Planned enhancements include:
|
||||
- JavaScript sandboxing for untrusted extensions
|
||||
- Extension marketplace and registry
|
||||
- Inter-extension communication
|
||||
- Advanced theming capabilities
|
||||
- Backend hot-reload without restart
|
||||
|
||||
## Getting Started
|
||||
|
||||
Ready to build your first extension? Check out:
|
||||
- [Extension Project Structure](/developer_portal/extensions/extension-project-structure)
|
||||
- [API Reference](/developer_portal/api/frontend)
|
||||
- [CLI Documentation](/developer_portal/cli/overview)
|
||||
- [Frontend Contribution Types](/developer_portal/extensions/frontend-contribution-types)
|
||||
55
docs/developer_portal/capabilities/common-capabilities.md
Normal file
55
docs/developer_portal/capabilities/common-capabilities.md
Normal file
@@ -0,0 +1,55 @@
|
||||
---
|
||||
title: Common Plugin Capabilities
|
||||
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.
|
||||
-->
|
||||
|
||||
# Common Plugin Capabilities
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Explore the shared functionality and common patterns available to all Superset plugins.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Plugin lifecycle hooks (initialization, activation, deactivation)
|
||||
- Accessing Superset's core services and APIs
|
||||
- State management and data persistence
|
||||
- Event handling and plugin communication
|
||||
- Internationalization (i18n) support
|
||||
- Error handling and logging
|
||||
- Plugin configuration management
|
||||
- Accessing user context and permissions
|
||||
- Working with datasets and queries
|
||||
- Plugin metadata and manifests
|
||||
|
||||
## Core Services Available
|
||||
|
||||
- **API Client** - HTTP client for backend communication
|
||||
- **State Store** - Redux store access
|
||||
- **Theme Provider** - Access to current theme settings
|
||||
- **User Context** - Current user information and permissions
|
||||
- **Dataset Service** - Working with data sources
|
||||
- **Chart Service** - Chart rendering utilities
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
62
docs/developer_portal/capabilities/extending-workbench.md
Normal file
62
docs/developer_portal/capabilities/extending-workbench.md
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
title: Extending the Workbench
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
# Extending the Workbench
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Discover how to extend Superset's main interface and workbench with custom components and functionality.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Adding custom menu items and navigation
|
||||
- Creating custom dashboard components
|
||||
- Extending the SQL Lab interface
|
||||
- Adding custom sidebar panels
|
||||
- Creating floating panels and modals
|
||||
- Integrating with the command palette
|
||||
- Custom toolbar buttons and actions
|
||||
- Workspace state management
|
||||
- Plugin-specific keyboard shortcuts
|
||||
- Context menu extensions
|
||||
|
||||
## Extension Points
|
||||
|
||||
- **Main navigation** - Top-level menu items
|
||||
- **Dashboard builder** - Custom components and layouts
|
||||
- **SQL Lab** - Query editor extensions
|
||||
- **Chart explorer** - Visualization building tools
|
||||
- **Settings panels** - Configuration interfaces
|
||||
- **Data source explorer** - Database navigation
|
||||
|
||||
## UI Integration Patterns
|
||||
|
||||
- React component composition
|
||||
- Portal-based rendering
|
||||
- Event-driven UI updates
|
||||
- Responsive layout adaptation
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
53
docs/developer_portal/capabilities/overview.md
Normal file
53
docs/developer_portal/capabilities/overview.md
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: Plugin Capabilities Overview
|
||||
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.
|
||||
-->
|
||||
|
||||
# Plugin Capabilities Overview
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
This section provides a comprehensive overview of what Superset plugins can do and how they integrate with the core platform.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Plugin architecture and lifecycle
|
||||
- Available extension points
|
||||
- Core APIs and services
|
||||
- Plugin communication patterns
|
||||
- Configuration and settings management
|
||||
- Plugin permissions and security
|
||||
- Performance considerations
|
||||
- Best practices for plugin development
|
||||
|
||||
## Plugin Types
|
||||
|
||||
Superset supports several types of plugins:
|
||||
- **Visualization plugins** - Custom chart types and data visualizations
|
||||
- **Database connectors** - New data source integrations
|
||||
- **UI extensions** - Custom dashboard components and interfaces
|
||||
- **Theme plugins** - Custom styling and branding
|
||||
- **Filter plugins** - Custom filter components
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
61
docs/developer_portal/capabilities/theming.md
Normal file
61
docs/developer_portal/capabilities/theming.md
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: Theming and Styling
|
||||
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.
|
||||
-->
|
||||
|
||||
# Theming and Styling
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Learn how to create custom themes and style your plugins to match Superset's design system.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Understanding Superset's theme architecture
|
||||
- Using the theme provider in plugins
|
||||
- Creating custom color palettes
|
||||
- Responsive design considerations
|
||||
- Dark mode and light mode support
|
||||
- Customizing chart colors and styling
|
||||
- Brand customization and white-labeling
|
||||
- CSS-in-JS best practices
|
||||
- Working with Ant Design components
|
||||
- Accessibility in custom themes
|
||||
|
||||
## Theme Structure
|
||||
|
||||
- **Color tokens** - Primary, secondary, and semantic colors
|
||||
- **Typography** - Font families, sizes, and weights
|
||||
- **Spacing** - Grid system and layout tokens
|
||||
- **Component styles** - Default component appearances
|
||||
- **Chart themes** - Color schemes for visualizations
|
||||
|
||||
## Supported Theming APIs
|
||||
|
||||
- Theme provider context
|
||||
- CSS custom properties
|
||||
- Emotion/styled-components integration
|
||||
- Chart color palette API
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
578
docs/developer_portal/cli/overview.md
Normal file
578
docs/developer_portal/cli/overview.md
Normal file
@@ -0,0 +1,578 @@
|
||||
---
|
||||
title: Extension CLI
|
||||
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.
|
||||
-->
|
||||
|
||||
# Superset Extension CLI
|
||||
|
||||
The `apache-superset-extensions-cli` package provides command-line tools for creating, developing, and packaging Apache Superset extensions. It streamlines the entire extension development workflow from initialization to deployment.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the CLI globally using pip:
|
||||
|
||||
```bash
|
||||
pip install apache-superset-extensions-cli
|
||||
```
|
||||
|
||||
Or install locally in your project:
|
||||
|
||||
```bash
|
||||
pip install --user apache-superset-extensions-cli
|
||||
```
|
||||
|
||||
Verify installation:
|
||||
|
||||
```bash
|
||||
superset-extensions --version
|
||||
# Output: apache-superset-extensions-cli version 1.0.0
|
||||
```
|
||||
|
||||
## Commands Overview
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `init` | Create a new extension project |
|
||||
| `dev` | Start development mode with hot reload |
|
||||
| `build` | Build extension assets for production |
|
||||
| `bundle` | Package extension into a .supx file |
|
||||
| `validate` | Validate extension metadata and structure |
|
||||
| `publish` | Publish extension to registry (future) |
|
||||
|
||||
## Command Reference
|
||||
|
||||
### init
|
||||
|
||||
Creates a new extension project with the standard structure and boilerplate code.
|
||||
|
||||
```bash
|
||||
superset-extensions init [options] <extension-name>
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
- `--type, -t <type>` - Extension type: `full` (default), `frontend-only`, `backend-only`
|
||||
- `--template <template>` - Project template: `default`, `sql-lab`, `dashboard`, `chart`
|
||||
- `--author <name>` - Extension author name
|
||||
- `--description <desc>` - Extension description
|
||||
- `--license <license>` - License identifier (default: Apache-2.0)
|
||||
- `--superset-version <version>` - Minimum Superset version (default: 4.0.0)
|
||||
- `--skip-install` - Skip installing dependencies
|
||||
- `--use-typescript` - Use TypeScript for frontend (default: true)
|
||||
- `--use-npm` - Use npm instead of yarn
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Create a basic extension
|
||||
superset-extensions init my-extension
|
||||
|
||||
# Create a SQL Lab focused extension
|
||||
superset-extensions init query-optimizer --template sql-lab
|
||||
|
||||
# Create frontend-only extension
|
||||
superset-extensions init custom-viz --type frontend-only
|
||||
|
||||
# Create with metadata
|
||||
superset-extensions init data-quality \
|
||||
--author "Jane Doe" \
|
||||
--description "Data quality monitoring for SQL Lab"
|
||||
```
|
||||
|
||||
#### Generated Structure
|
||||
|
||||
```
|
||||
my-extension/
|
||||
├── extension.json # Extension metadata
|
||||
├── frontend/ # Frontend source code
|
||||
│ ├── src/
|
||||
│ │ ├── index.tsx # Main entry point
|
||||
│ │ └── components/ # React components
|
||||
│ ├── package.json
|
||||
│ ├── tsconfig.json
|
||||
│ └── webpack.config.js
|
||||
├── backend/ # Backend source code
|
||||
│ ├── src/
|
||||
│ │ └── my_extension/
|
||||
│ │ ├── __init__.py
|
||||
│ │ └── api.py
|
||||
│ ├── tests/
|
||||
│ └── requirements.txt
|
||||
├── README.md
|
||||
└── .gitignore
|
||||
```
|
||||
|
||||
### dev
|
||||
|
||||
Starts development mode with automatic rebuilding and hot reload.
|
||||
|
||||
```bash
|
||||
superset-extensions dev [options]
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
- `--port, -p <port>` - Development server port (default: 9001)
|
||||
- `--host <host>` - Development server host (default: localhost)
|
||||
- `--watch-backend` - Also watch backend files (default: true)
|
||||
- `--watch-frontend` - Also watch frontend files (default: true)
|
||||
- `--no-open` - Don't open browser automatically
|
||||
- `--superset-url <url>` - Superset instance URL (default: http://localhost:8088)
|
||||
- `--verbose` - Enable verbose logging
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Start development mode
|
||||
superset-extensions dev
|
||||
|
||||
# Use custom port
|
||||
superset-extensions dev --port 9002
|
||||
|
||||
# Connect to remote Superset
|
||||
superset-extensions dev --superset-url https://superset.example.com
|
||||
```
|
||||
|
||||
#### Development Workflow
|
||||
|
||||
1. **Start the dev server:**
|
||||
```bash
|
||||
superset-extensions dev
|
||||
```
|
||||
|
||||
2. **Configure Superset** (`superset_config.py`):
|
||||
```python
|
||||
LOCAL_EXTENSIONS = [
|
||||
"/path/to/your/extension"
|
||||
]
|
||||
ENABLE_EXTENSIONS = True
|
||||
```
|
||||
|
||||
3. **Start Superset:**
|
||||
```bash
|
||||
superset run -p 8088 --with-threads --reload
|
||||
```
|
||||
|
||||
The extension will automatically reload when you make changes.
|
||||
|
||||
### build
|
||||
|
||||
Builds extension assets for production deployment.
|
||||
|
||||
```bash
|
||||
superset-extensions build [options]
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
- `--mode <mode>` - Build mode: `production` (default), `development`
|
||||
- `--analyze` - Generate bundle analysis report
|
||||
- `--source-maps` - Generate source maps
|
||||
- `--minify` - Minify output (default: true in production)
|
||||
- `--output, -o <dir>` - Output directory (default: dist)
|
||||
- `--clean` - Clean output directory before build
|
||||
- `--parallel` - Build frontend and backend in parallel
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Production build
|
||||
superset-extensions build
|
||||
|
||||
# Development build with source maps
|
||||
superset-extensions build --mode development --source-maps
|
||||
|
||||
# Analyze bundle size
|
||||
superset-extensions build --analyze
|
||||
|
||||
# Custom output directory
|
||||
superset-extensions build --output build
|
||||
```
|
||||
|
||||
#### Build Output
|
||||
|
||||
```
|
||||
dist/
|
||||
├── manifest.json # Build manifest
|
||||
├── frontend/
|
||||
│ ├── remoteEntry.[hash].js
|
||||
│ ├── [name].[hash].js
|
||||
│ └── assets/
|
||||
└── backend/
|
||||
└── my_extension/
|
||||
├── __init__.py
|
||||
└── *.py
|
||||
```
|
||||
|
||||
### bundle
|
||||
|
||||
Packages the built extension into a distributable `.supx` file.
|
||||
|
||||
```bash
|
||||
superset-extensions bundle [options]
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
- `--output, -o <file>` - Output filename (default: `{name}-{version}.supx`)
|
||||
- `--sign` - Sign the bundle (requires configured keys)
|
||||
- `--compression <level>` - Compression level 0-9 (default: 6)
|
||||
- `--exclude <patterns>` - Files to exclude (comma-separated)
|
||||
- `--include-dev-deps` - Include development dependencies
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Create bundle
|
||||
superset-extensions bundle
|
||||
|
||||
# Custom output name
|
||||
superset-extensions bundle --output my-extension-latest.supx
|
||||
|
||||
# Signed bundle
|
||||
superset-extensions bundle --sign
|
||||
|
||||
# Exclude test files
|
||||
superset-extensions bundle --exclude "**/*.test.js,**/*.spec.ts"
|
||||
```
|
||||
|
||||
#### Bundle Structure
|
||||
|
||||
The `.supx` file is a ZIP archive containing:
|
||||
|
||||
```
|
||||
my-extension-1.0.0.supx
|
||||
├── manifest.json
|
||||
├── extension.json
|
||||
├── frontend/
|
||||
│ └── dist/
|
||||
└── backend/
|
||||
└── src/
|
||||
```
|
||||
|
||||
### validate
|
||||
|
||||
Validates extension structure, metadata, and compatibility.
|
||||
|
||||
```bash
|
||||
superset-extensions validate [options]
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
- `--strict` - Enable strict validation
|
||||
- `--fix` - Auto-fix correctable issues
|
||||
- `--check-deps` - Validate dependencies
|
||||
- `--check-security` - Run security checks
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
# Basic validation
|
||||
superset-extensions validate
|
||||
|
||||
# Strict mode with auto-fix
|
||||
superset-extensions validate --strict --fix
|
||||
|
||||
# Full validation
|
||||
superset-extensions validate --check-deps --check-security
|
||||
```
|
||||
|
||||
#### Validation Checks
|
||||
|
||||
- Extension metadata completeness
|
||||
- File structure conformity
|
||||
- API version compatibility
|
||||
- Dependency security vulnerabilities
|
||||
- Code quality standards
|
||||
- Bundle size limits
|
||||
|
||||
## Configuration File
|
||||
|
||||
Create `.superset-extension.json` for project-specific settings:
|
||||
|
||||
```json
|
||||
{
|
||||
"build": {
|
||||
"mode": "production",
|
||||
"sourceMaps": true,
|
||||
"analyze": false,
|
||||
"parallel": true
|
||||
},
|
||||
"dev": {
|
||||
"port": 9001,
|
||||
"host": "localhost",
|
||||
"autoOpen": true
|
||||
},
|
||||
"bundle": {
|
||||
"compression": 6,
|
||||
"sign": false,
|
||||
"exclude": [
|
||||
"**/*.test.*",
|
||||
"**/*.spec.*",
|
||||
"**/tests/**"
|
||||
]
|
||||
},
|
||||
"validation": {
|
||||
"strict": true,
|
||||
"autoFix": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Configure CLI behavior using environment variables:
|
||||
|
||||
```bash
|
||||
# Superset connection
|
||||
export SUPERSET_URL=http://localhost:8088
|
||||
export SUPERSET_USERNAME=admin
|
||||
export SUPERSET_PASSWORD=admin
|
||||
|
||||
# Development settings
|
||||
export EXTENSION_DEV_PORT=9001
|
||||
export EXTENSION_DEV_HOST=localhost
|
||||
|
||||
# Build settings
|
||||
export EXTENSION_BUILD_MODE=production
|
||||
export EXTENSION_SOURCE_MAPS=true
|
||||
|
||||
# Registry settings (future)
|
||||
export EXTENSION_REGISTRY_URL=https://registry.superset.apache.org
|
||||
export EXTENSION_REGISTRY_TOKEN=your-token
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Custom Templates
|
||||
|
||||
Create custom project templates:
|
||||
|
||||
```bash
|
||||
# Use custom template
|
||||
superset-extensions init my-ext --template https://github.com/user/template
|
||||
|
||||
# Use local template
|
||||
superset-extensions init my-ext --template ./my-template
|
||||
```
|
||||
|
||||
### CI/CD Integration
|
||||
|
||||
#### GitHub Actions
|
||||
|
||||
```yaml
|
||||
name: Build Extension
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.9'
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '16'
|
||||
|
||||
- name: Install CLI
|
||||
run: pip install apache-superset-extensions-cli
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
npm install --prefix frontend
|
||||
pip install -r backend/requirements.txt
|
||||
|
||||
- name: Validate
|
||||
run: superset-extensions validate --strict
|
||||
|
||||
- name: Build
|
||||
run: superset-extensions build --mode production
|
||||
|
||||
- name: Bundle
|
||||
run: superset-extensions bundle
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: extension-bundle
|
||||
path: '*.supx'
|
||||
```
|
||||
|
||||
### Automated Deployment
|
||||
|
||||
Deploy extensions automatically:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# deploy.sh
|
||||
|
||||
# Build and bundle
|
||||
superset-extensions build --mode production
|
||||
superset-extensions bundle --sign
|
||||
|
||||
# Upload to Superset instance
|
||||
BUNDLE=$(ls *.supx | head -1)
|
||||
curl -X POST "$SUPERSET_URL/api/v1/extensions/import/" \
|
||||
-H "Authorization: Bearer $SUPERSET_TOKEN" \
|
||||
-F "bundle=@$BUNDLE"
|
||||
|
||||
# Verify deployment
|
||||
curl "$SUPERSET_URL/api/v1/extensions/" \
|
||||
-H "Authorization: Bearer $SUPERSET_TOKEN"
|
||||
```
|
||||
|
||||
### Multi-Extension Projects
|
||||
|
||||
Manage multiple extensions in one repository:
|
||||
|
||||
```bash
|
||||
# Initialize multiple extensions
|
||||
superset-extensions init extensions/viz-plugin --type frontend-only
|
||||
superset-extensions init extensions/sql-optimizer --template sql-lab
|
||||
superset-extensions init extensions/auth-provider --type backend-only
|
||||
|
||||
# Build all extensions
|
||||
for dir in extensions/*/; do
|
||||
(cd "$dir" && superset-extensions build)
|
||||
done
|
||||
|
||||
# Bundle all extensions
|
||||
for dir in extensions/*/; do
|
||||
(cd "$dir" && superset-extensions bundle)
|
||||
done
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Port already in use
|
||||
|
||||
```bash
|
||||
# Error: Port 9001 is already in use
|
||||
|
||||
# Solution: Use a different port
|
||||
superset-extensions dev --port 9002
|
||||
```
|
||||
|
||||
#### Module not found
|
||||
|
||||
```bash
|
||||
# Error: Cannot find module '@apache-superset/core'
|
||||
|
||||
# Solution: Ensure dependencies are installed
|
||||
npm install --prefix frontend
|
||||
```
|
||||
|
||||
#### Build failures
|
||||
|
||||
```bash
|
||||
# Check Node and Python versions
|
||||
node --version # Should be 16+
|
||||
python --version # Should be 3.9+
|
||||
|
||||
# Clear cache and rebuild
|
||||
rm -rf dist node_modules frontend/node_modules
|
||||
npm install --prefix frontend
|
||||
superset-extensions build --clean
|
||||
```
|
||||
|
||||
#### Bundle too large
|
||||
|
||||
```bash
|
||||
# Warning: Bundle size exceeds recommended limit
|
||||
|
||||
# Solution: Analyze and optimize
|
||||
superset-extensions build --analyze
|
||||
|
||||
# Exclude unnecessary files
|
||||
superset-extensions bundle --exclude "**/*.map,**/*.test.*"
|
||||
```
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable debug logging:
|
||||
|
||||
```bash
|
||||
# Set debug environment variable
|
||||
export DEBUG=superset-extensions:*
|
||||
|
||||
# Or use verbose flag
|
||||
superset-extensions dev --verbose
|
||||
superset-extensions build --verbose
|
||||
```
|
||||
|
||||
### Getting Help
|
||||
|
||||
```bash
|
||||
# General help
|
||||
superset-extensions --help
|
||||
|
||||
# Command-specific help
|
||||
superset-extensions init --help
|
||||
superset-extensions dev --help
|
||||
|
||||
# Version information
|
||||
superset-extensions --version
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Development
|
||||
|
||||
1. **Use TypeScript** for type safety
|
||||
2. **Follow the style guide** for consistency
|
||||
3. **Write tests** for critical functionality
|
||||
4. **Document your code** with JSDoc/docstrings
|
||||
5. **Use development mode** for rapid iteration
|
||||
|
||||
### Building
|
||||
|
||||
1. **Optimize bundle size** - analyze and tree-shake
|
||||
2. **Generate source maps** for debugging
|
||||
3. **Validate before building** to catch issues early
|
||||
4. **Use production mode** for final builds
|
||||
5. **Clean build directory** to avoid stale files
|
||||
|
||||
### Deployment
|
||||
|
||||
1. **Sign your bundles** for security
|
||||
2. **Version properly** using semantic versioning
|
||||
3. **Test in staging** before production deployment
|
||||
4. **Document breaking changes** in CHANGELOG
|
||||
5. **Provide migration guides** for major updates
|
||||
|
||||
## Resources
|
||||
|
||||
- [Extension Architecture](/developer_portal/architecture/overview)
|
||||
- [API Reference](/developer_portal/api/frontend)
|
||||
- [Frontend Contribution Types](/developer_portal/extensions/frontend-contribution-types)
|
||||
- [GitHub Repository](https://github.com/apache/superset)
|
||||
- [Community Forum](https://github.com/apache/superset/discussions)
|
||||
44
docs/developer_portal/coding-guidelines/overview.md
Normal file
44
docs/developer_portal/coding-guidelines/overview.md
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
title: Coding Guidelines Overview
|
||||
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.
|
||||
-->
|
||||
|
||||
# Coding Guidelines Overview
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Best practices and coding standards for Apache Superset development.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- General coding principles
|
||||
- Code organization
|
||||
- Error handling
|
||||
- Performance considerations
|
||||
- Security best practices
|
||||
- Testing requirements
|
||||
- Documentation standards
|
||||
- Commit message conventions
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
@@ -327,9 +327,9 @@ stats.sort_stats('cumulative').print_stats(10)
|
||||
## Resources
|
||||
|
||||
### Internal
|
||||
- [Coding Guidelines](../guidelines/design-guidelines)
|
||||
- [Coding Guidelines](../coding-guidelines/overview)
|
||||
- [Testing Guide](../testing/overview)
|
||||
- [Extension Architecture](../extensions/architecture)
|
||||
- [Architecture Overview](../architecture/overview)
|
||||
|
||||
### External
|
||||
- [Google's Code Review Guide](https://google.github.io/eng-practices/review/)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Overview
|
||||
title: Contributing Overview
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
@@ -22,7 +22,7 @@ specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Contributing
|
||||
# Contributing to Apache Superset
|
||||
|
||||
Superset is an [Apache Software foundation](https://www.apache.org/theapacheway/index.html) project.
|
||||
The core contributors (or committers) to Superset communicate primarily in the following channels (which can be joined by anyone):
|
||||
|
||||
@@ -35,7 +35,7 @@ Learn how to create and submit high-quality pull requests to Apache Superset.
|
||||
- [ ] You've found or created an issue to work on
|
||||
|
||||
### PR Readiness Checklist
|
||||
- [ ] Code follows [coding guidelines](../guidelines/design-guidelines)
|
||||
- [ ] Code follows [coding guidelines](../coding-guidelines/overview)
|
||||
- [ ] Tests are passing locally
|
||||
- [ ] Linting passes (`pre-commit run --all-files`)
|
||||
- [ ] Documentation is updated if needed
|
||||
|
||||
36
docs/developer_portal/extensions/architectural-principles.md
Normal file
36
docs/developer_portal/extensions/architectural-principles.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
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.
|
||||
@@ -1,253 +0,0 @@
|
||||
---
|
||||
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
|
||||
36
docs/developer_portal/extensions/built-in-features.md
Normal file
36
docs/developer_portal/extensions/built-in-features.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
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.
|
||||
84
docs/developer_portal/extensions/dynamic-module-loading.md
Normal file
84
docs/developer_portal/extensions/dynamic-module-loading.md
Normal file
@@ -0,0 +1,84 @@
|
||||
---
|
||||
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,
|
||||
};
|
||||
}
|
||||
```
|
||||
41
docs/developer_portal/extensions/high-level-architecture.md
Normal file
41
docs/developer_portal/extensions/high-level-architecture.md
Normal file
@@ -0,0 +1,41 @@
|
||||
---
|
||||
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.
|
||||
@@ -26,8 +26,6 @@ under the License.
|
||||
|
||||
Extensions interact with Superset through well-defined, versioned APIs provided by the `@apache-superset/core` (frontend) and `apache-superset-core` (backend) packages. These APIs are designed to be stable, discoverable, and consistent for both built-in and external extensions.
|
||||
|
||||
**Note**: The `superset_core.api` module provides abstract classes that are replaced with concrete implementations via dependency injection when Superset initializes. This allows extensions to use the same interfaces as the host application.
|
||||
|
||||
**Frontend APIs** (via `@apache-superset/core)`:
|
||||
|
||||
The frontend extension APIs in Superset are organized into logical namespaces such as `authentication`, `commands`, `extensions`, `sqlLab`, and others. Each namespace groups related functionality, making it easy for extension authors to discover and use the APIs relevant to their needs. For example, the `sqlLab` namespace provides events and methods specific to SQL Lab, allowing extensions to react to user actions and interact with the SQL Lab environment:
|
||||
@@ -92,38 +90,31 @@ Backend APIs follow a similar pattern, providing access to Superset's models, se
|
||||
Extension endpoints are registered under a dedicated `/extensions` namespace to avoid conflicting with built-in endpoints and also because they don't share the same version constraints. By grouping all extension endpoints under `/extensions`, Superset establishes a clear boundary between core and extension functionality, making it easier to manage, document, and secure both types of APIs.
|
||||
|
||||
``` python
|
||||
from superset_core.api.models import Database, get_session
|
||||
from superset_core.api.daos import DatabaseDAO
|
||||
from superset_core.api.rest_api import add_extension_api
|
||||
from superset_core.api import rest_api, models, query
|
||||
from .api import DatasetReferencesAPI
|
||||
|
||||
# Register a new extension REST API
|
||||
add_extension_api(DatasetReferencesAPI)
|
||||
rest_api.add_extension_api(DatasetReferencesAPI)
|
||||
|
||||
# Fetch Superset entities via the DAO to apply base filters that filter out entities
|
||||
# that the user doesn't have access to
|
||||
databases = DatabaseDAO.find_all()
|
||||
|
||||
# ..or apply simple filters on top of base filters
|
||||
databases = DatabaseDAO.filter_by(uuid=database.uuid)
|
||||
# Access Superset models with simple queries that filter out entities that
|
||||
# the user doesn't have access to
|
||||
databases = models.get_databases(id=database_id)
|
||||
if not databases:
|
||||
raise Exception("Database not found")
|
||||
return self.response_404()
|
||||
|
||||
return databases[0]
|
||||
database = databases[0]
|
||||
|
||||
# Perform complex queries using SQLAlchemy Query, also filtering out
|
||||
# inaccessible entities
|
||||
session = get_session()
|
||||
databases_query = session.query(Database).filter(
|
||||
Database.database_name.ilike("%abc%")
|
||||
)
|
||||
return DatabaseDAO.query(databases_query)
|
||||
# Perform complex queries using SQLAlchemy BaseQuery, also filtering
|
||||
# out inaccessible entities
|
||||
session = models.get_session()
|
||||
db_model = models.get_database_model())
|
||||
database_query = session.query(db_model.database_name.ilike("%abc%")
|
||||
databases_containing_abc = models.get_databases(query)
|
||||
|
||||
# Bypass security model for highly custom use cases
|
||||
session = get_session()
|
||||
all_databases_containing_abc = session.query(Database).filter(
|
||||
Database.database_name.ilike("%abc%")
|
||||
).all()
|
||||
session = models.get_session()
|
||||
db_model = models.get_database_model())
|
||||
all_databases_containg_abc = session.query(db_model.database_name.ilike("%abc%").all()
|
||||
```
|
||||
|
||||
In the future, we plan to expand the backend APIs to support configuring security models, database engines, SQL Alchemy dialects, etc.
|
||||
|
||||
41
docs/developer_portal/extensions/lifecycle-management.md
Normal file
41
docs/developer_portal/extensions/lifecycle-management.md
Normal file
@@ -0,0 +1,41 @@
|
||||
---
|
||||
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: Overview
|
||||
title: Extensions Overview
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
@@ -22,7 +22,7 @@ specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Overview
|
||||
# Extensions 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,7 +32,8 @@ Superset extensions are self-contained packages that extend the core platform's
|
||||
|
||||
## Extension Architecture
|
||||
|
||||
- **[Architecture](./architecture)** - Architectural principles and high-level system overview
|
||||
- **[Architectural Principles](./architectural-principles)** - Core design principles guiding extension development
|
||||
- **[High-level Architecture](./high-level-architecture)** - System overview and component relationships
|
||||
- **[Extension Project Structure](./extension-project-structure)** - Standard project layout and organization
|
||||
- **[Extension Metadata](./extension-metadata)** - Configuration and manifest structure
|
||||
|
||||
@@ -40,18 +41,19 @@ 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
|
||||
|
||||
- **[Quick Start](./quick-start)** - Complete Hello World extension walkthrough
|
||||
- **[Proof of Concept](./proof-of-concept)** - Complete Hello World extension walkthrough
|
||||
|
||||
## Extension Capabilities
|
||||
|
||||
@@ -66,9 +68,9 @@ Extensions can provide:
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. **Learn the Architecture**: Start with [Architecture](./architecture) to understand the design philosophy
|
||||
1. **Learn the Architecture**: Start with [Architectural Principles](./architectural-principles) 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 [Quick Start](./quick-start) tutorial
|
||||
3. **Build Your First Extension**: Complete the [Proof of Concept](./proof-of-concept) tutorial
|
||||
4. **Deploy and Share**: Use the [Deploying Extension](./deploying-extension) guide to package your extension
|
||||
|
||||
## Extension Ecosystem
|
||||
|
||||
288
docs/developer_portal/extensions/proof-of-concept.md
Normal file
288
docs/developer_portal/extensions/proof-of-concept.md
Normal file
@@ -0,0 +1,288 @@
|
||||
---
|
||||
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.
|
||||
@@ -1,397 +0,0 @@
|
||||
---
|
||||
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.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.
|
||||
31
docs/developer_portal/extensions/versioning.md
Normal file
31
docs/developer_portal/extensions/versioning.md
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
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.
|
||||
61
docs/developer_portal/guides/command-palette.md
Normal file
61
docs/developer_portal/guides/command-palette.md
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: Command Palette Integration
|
||||
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.
|
||||
-->
|
||||
|
||||
# Command Palette Integration
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Learn how to integrate your plugin with Superset's command palette to provide quick access to plugin functionality.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Understanding the command palette architecture
|
||||
- Registering custom commands
|
||||
- Command categories and organization
|
||||
- Keyboard shortcuts and hotkeys
|
||||
- Dynamic command generation
|
||||
- Command context and availability
|
||||
- Icon and description customization
|
||||
- Command execution and callbacks
|
||||
- Search and filtering integration
|
||||
- Command palette theming
|
||||
|
||||
## Command Types
|
||||
|
||||
- **Navigation commands** - Quick navigation to plugin views
|
||||
- **Action commands** - Execute plugin-specific actions
|
||||
- **Creation commands** - Create new charts, dashboards, or data sources
|
||||
- **Configuration commands** - Quick access to settings
|
||||
- **Help commands** - Documentation and support links
|
||||
|
||||
## Implementation Patterns
|
||||
|
||||
- Command registration lifecycle
|
||||
- Async command execution
|
||||
- Context-aware command availability
|
||||
- Command result handling
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
64
docs/developer_portal/guides/custom-editors.md
Normal file
64
docs/developer_portal/guides/custom-editors.md
Normal file
@@ -0,0 +1,64 @@
|
||||
---
|
||||
title: Custom Editors
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
# Custom Editors
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Build specialized editing interfaces for data manipulation, query building, and configuration management.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Editor component architecture
|
||||
- Syntax highlighting and code completion
|
||||
- Real-time validation and error detection
|
||||
- Undo/redo functionality
|
||||
- Collaborative editing features
|
||||
- Custom language support
|
||||
- Editor extensions and plugins
|
||||
- Integration with Superset's SQL Lab
|
||||
- File and document management
|
||||
- Export and import capabilities
|
||||
|
||||
## Editor Types
|
||||
|
||||
- **SQL query editors** - Enhanced database query interfaces
|
||||
- **Configuration editors** - JSON, YAML, and custom config formats
|
||||
- **Formula editors** - Mathematical and business logic expressions
|
||||
- **Chart configuration** - Visual chart property editors
|
||||
- **Data transformation** - ETL pipeline builders
|
||||
- **Dashboard layout editors** - Drag-and-drop interface builders
|
||||
|
||||
## Advanced Features
|
||||
|
||||
- Monaco Editor integration
|
||||
- CodeMirror customization
|
||||
- Custom language definitions
|
||||
- Intelligent autocomplete
|
||||
- Syntax error highlighting
|
||||
- Multi-cursor editing
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
58
docs/developer_portal/guides/overview.md
Normal file
58
docs/developer_portal/guides/overview.md
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: Development Guides Overview
|
||||
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.
|
||||
-->
|
||||
|
||||
# Development Guides Overview
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
This section contains practical guides and tutorials for common plugin development scenarios and advanced techniques.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Step-by-step development tutorials
|
||||
- Common development patterns and solutions
|
||||
- Integration with Superset's core features
|
||||
- Advanced plugin architectures
|
||||
- Performance optimization techniques
|
||||
- Debugging and troubleshooting guides
|
||||
- Migration guides for plugin updates
|
||||
- Best practices and coding standards
|
||||
|
||||
## Available Guides
|
||||
|
||||
- **Command Palette Integration** - Add custom commands and shortcuts
|
||||
- **WebViews and Embedded Content** - Display external content in Superset
|
||||
- **Custom Editors** - Build specialized data editing interfaces
|
||||
- **Virtual Documents** - Handle dynamic content and data sources
|
||||
|
||||
## Guide Categories
|
||||
|
||||
- **Beginner** - Getting started with basic concepts
|
||||
- **Intermediate** - Common patterns and integrations
|
||||
- **Advanced** - Complex architectures and performance optimization
|
||||
- **Troubleshooting** - Debugging and problem-solving
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
63
docs/developer_portal/guides/virtual-documents.md
Normal file
63
docs/developer_portal/guides/virtual-documents.md
Normal file
@@ -0,0 +1,63 @@
|
||||
---
|
||||
title: Virtual Documents
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
# Virtual Documents
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Learn how to create and manage virtual documents that represent dynamic content and data sources within Superset.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Virtual document concepts and architecture
|
||||
- Dynamic content generation
|
||||
- Document lifecycle management
|
||||
- Data source abstraction
|
||||
- Real-time document updates
|
||||
- Document caching and performance
|
||||
- Version control and history
|
||||
- Collaborative document editing
|
||||
- Document search and indexing
|
||||
- Export and sharing capabilities
|
||||
|
||||
## Virtual Document Types
|
||||
|
||||
- **Dynamic reports** - Auto-updating analytical reports
|
||||
- **Data lineage documents** - Interactive data flow visualization
|
||||
- **Configuration schemas** - Dynamic form generation
|
||||
- **API documentation** - Auto-generated from code
|
||||
- **Data dictionaries** - Searchable metadata catalogs
|
||||
- **Query libraries** - Shared SQL query collections
|
||||
|
||||
## Implementation Patterns
|
||||
|
||||
- Document provider interfaces
|
||||
- Content resolution strategies
|
||||
- Change detection and synchronization
|
||||
- Document serialization formats
|
||||
- Access control and permissions
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
61
docs/developer_portal/guides/webviews.md
Normal file
61
docs/developer_portal/guides/webviews.md
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: WebViews and Embedded Content
|
||||
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.
|
||||
-->
|
||||
|
||||
# WebViews and Embedded Content
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Explore how to embed external web content, iframes, and interactive applications within your Superset plugins.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Creating secure WebView components
|
||||
- iframe integration and sandboxing
|
||||
- Cross-origin communication patterns
|
||||
- Authentication and session management
|
||||
- WebView lifecycle and memory management
|
||||
- Event handling between parent and child
|
||||
- Responsive WebView sizing
|
||||
- Loading states and error handling
|
||||
- Performance optimization for embedded content
|
||||
- Security considerations and CSP compliance
|
||||
|
||||
## WebView Use Cases
|
||||
|
||||
- **External dashboards** - Embed third-party analytics tools
|
||||
- **Interactive documentation** - Live code examples and tutorials
|
||||
- **Configuration panels** - External admin interfaces
|
||||
- **Data exploration tools** - Specialized analysis applications
|
||||
- **Custom visualizations** - Complex D3.js or other web-based charts
|
||||
|
||||
## Security Features
|
||||
|
||||
- Content Security Policy (CSP) integration
|
||||
- Cross-origin resource sharing (CORS) handling
|
||||
- Secure message passing
|
||||
- Domain allowlisting
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
@@ -35,8 +35,8 @@ Welcome to the Apache Superset Developer Portal - your comprehensive resource fo
|
||||
|
||||
### Extension Development
|
||||
- [Extension Project Structure](/developer_portal/extensions/extension-project-structure)
|
||||
- [Extension Architecture](/developer_portal/extensions/architecture)
|
||||
- [Quick Start](/developer_portal/extensions/quick-start)
|
||||
- [Extension Architecture](/developer_portal/architecture/overview)
|
||||
- [Extension Architecture](/developer_portal/extensions/high-level-architecture)
|
||||
|
||||
## 📚 Documentation Sections
|
||||
|
||||
@@ -105,9 +105,9 @@ Everything you need to contribute to the Apache Superset project. This section i
|
||||
<td width="50%">
|
||||
|
||||
**I want to build an extension**
|
||||
1. [Start with Quick Start](/developer_portal/extensions/quick-start)
|
||||
1. [Learn the architecture](/developer_portal/architecture/overview)
|
||||
2. [Learn extension structure](/developer_portal/extensions/extension-project-structure)
|
||||
3. [Explore architecture](/developer_portal/extensions/architecture)
|
||||
3. [Explore architecture](/developer_portal/extensions/high-level-architecture)
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
549
docs/developer_portal/references/activation-events.md
Normal file
549
docs/developer_portal/references/activation-events.md
Normal file
@@ -0,0 +1,549 @@
|
||||
---
|
||||
title: Activation Events
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
# Activation Events
|
||||
|
||||
Activation events control when your extension is loaded and activated. Extensions should specify activation events to ensure they're only loaded when needed, improving Superset's startup performance.
|
||||
|
||||
## Overview
|
||||
|
||||
Extensions are activated lazily - they're loaded only when certain conditions are met. This is controlled by the `activationEvents` field in your `extension.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"activationEvents": [
|
||||
"onCommand:myExtension.start",
|
||||
"onView:sqllab.panels",
|
||||
"onLanguage:sql"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Activation Event Types
|
||||
|
||||
### onCommand
|
||||
|
||||
Activated when a specific command is invoked:
|
||||
|
||||
```json
|
||||
"activationEvents": [
|
||||
"onCommand:myExtension.analyze",
|
||||
"onCommand:myExtension.export"
|
||||
]
|
||||
```
|
||||
|
||||
The extension activates when any of its commands are executed, either through:
|
||||
- Command palette
|
||||
- Menu items
|
||||
- Keyboard shortcuts
|
||||
- API calls
|
||||
|
||||
### onView
|
||||
|
||||
Activated when a specific view becomes visible:
|
||||
|
||||
```json
|
||||
"activationEvents": [
|
||||
"onView:sqllab.panels",
|
||||
"onView:dashboard.widgets"
|
||||
]
|
||||
```
|
||||
|
||||
**Available Views**:
|
||||
- `sqllab.panels` - SQL Lab side panels
|
||||
- `sqllab.bottomPanels` - SQL Lab bottom panels
|
||||
|
||||
**TODO: Future Views**:
|
||||
- `dashboard.widgets` - Dashboard widget areas
|
||||
- `chart.toolbar` - Chart toolbar views
|
||||
- `explore.panels` - Explore view panels
|
||||
|
||||
### onLanguage
|
||||
|
||||
Activated when a file of a specific language is opened:
|
||||
|
||||
```json
|
||||
"activationEvents": [
|
||||
"onLanguage:sql",
|
||||
"onLanguage:python"
|
||||
]
|
||||
```
|
||||
|
||||
Useful for extensions that provide:
|
||||
- Language-specific features
|
||||
- Syntax highlighting
|
||||
- Code completion
|
||||
- Linting
|
||||
|
||||
### workspaceContains
|
||||
|
||||
Activated when the workspace contains files matching a pattern:
|
||||
|
||||
```json
|
||||
"activationEvents": [
|
||||
"workspaceContains:**/*.sql",
|
||||
"workspaceContains:**/.supersetrc",
|
||||
"workspaceContains:**/superset_config.py"
|
||||
]
|
||||
```
|
||||
|
||||
Uses glob patterns to detect:
|
||||
- Configuration files
|
||||
- Project types
|
||||
- Specific file structures
|
||||
|
||||
### onStartupFinished
|
||||
|
||||
Activated after Superset has fully started:
|
||||
|
||||
```json
|
||||
"activationEvents": [
|
||||
"onStartupFinished"
|
||||
]
|
||||
```
|
||||
|
||||
Use for extensions that:
|
||||
- Don't need immediate activation
|
||||
- Provide background services
|
||||
- Monitor system events
|
||||
|
||||
### Star Activation (*)
|
||||
|
||||
Always activate (not recommended):
|
||||
|
||||
```json
|
||||
"activationEvents": ["*"]
|
||||
```
|
||||
|
||||
⚠️ **Warning**: This impacts startup performance. Only use when absolutely necessary.
|
||||
|
||||
## Extension Lifecycle
|
||||
|
||||
### 1. Registration
|
||||
|
||||
When Superset starts or an extension is installed:
|
||||
|
||||
```typescript
|
||||
// Extension is registered but not loaded
|
||||
{
|
||||
id: 'myExtension',
|
||||
state: 'unloaded',
|
||||
activationEvents: ['onCommand:myExtension.start']
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Activation Trigger
|
||||
|
||||
When an activation event occurs:
|
||||
|
||||
```typescript
|
||||
// Event triggered
|
||||
eventBus.emit('command:myExtension.start');
|
||||
|
||||
// Extension manager checks activation events
|
||||
if (extension.activationEvents.includes('onCommand:myExtension.start')) {
|
||||
activateExtension(extensionId);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Loading
|
||||
|
||||
Extension assets are loaded:
|
||||
|
||||
```typescript
|
||||
async function loadExtension(extensionId: string) {
|
||||
// Load frontend assets
|
||||
await loadRemoteEntry(extension.remoteEntry);
|
||||
|
||||
// Load backend modules (if applicable)
|
||||
await loadBackendModules(extension.backendModules);
|
||||
|
||||
return extension;
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Activation
|
||||
|
||||
The `activate` function is called:
|
||||
|
||||
```typescript
|
||||
export async function activate(context: ExtensionContext) {
|
||||
console.log('Extension activating');
|
||||
|
||||
// Register contributions
|
||||
const view = context.registerView(...);
|
||||
const command = context.registerCommand(...);
|
||||
|
||||
// Store disposables for cleanup
|
||||
context.subscriptions.push(view, command);
|
||||
|
||||
// Perform initialization
|
||||
await initialize();
|
||||
|
||||
console.log('Extension activated');
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Active State
|
||||
|
||||
Extension is fully operational:
|
||||
|
||||
```typescript
|
||||
{
|
||||
id: 'myExtension',
|
||||
state: 'activated',
|
||||
exports: { /* exposed APIs */ }
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Deactivation
|
||||
|
||||
When extension is disabled or Superset shuts down:
|
||||
|
||||
```typescript
|
||||
export async function deactivate() {
|
||||
console.log('Extension deactivating');
|
||||
|
||||
// Cleanup resources
|
||||
await cleanup();
|
||||
|
||||
// Subscriptions are automatically disposed
|
||||
console.log('Extension deactivated');
|
||||
}
|
||||
```
|
||||
|
||||
## Activation Strategies
|
||||
|
||||
### Lazy Activation (Recommended)
|
||||
|
||||
Activate only when needed:
|
||||
|
||||
```json
|
||||
{
|
||||
"activationEvents": [
|
||||
"onCommand:myExtension.start",
|
||||
"onView:myExtension.panel"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Benefits:
|
||||
- ✅ Fast startup
|
||||
- ✅ Lower memory usage
|
||||
- ✅ Better performance
|
||||
|
||||
### Eager Activation
|
||||
|
||||
Activate on startup for critical features:
|
||||
|
||||
```json
|
||||
{
|
||||
"activationEvents": [
|
||||
"onStartupFinished"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Use cases:
|
||||
- Authentication providers
|
||||
- Security extensions
|
||||
- Core infrastructure
|
||||
|
||||
### Conditional Activation
|
||||
|
||||
Activate based on workspace:
|
||||
|
||||
```json
|
||||
{
|
||||
"activationEvents": [
|
||||
"workspaceContains:**/superset_config.py",
|
||||
"workspaceContains:**/*.sql"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Benefits:
|
||||
- Context-aware activation
|
||||
- Project-specific features
|
||||
- Automatic detection
|
||||
|
||||
## Multiple Activation Events
|
||||
|
||||
Extensions can specify multiple events (OR logic):
|
||||
|
||||
```json
|
||||
{
|
||||
"activationEvents": [
|
||||
"onCommand:myExtension.start",
|
||||
"onCommand:myExtension.configure",
|
||||
"onView:sqllab.panels",
|
||||
"onLanguage:sql",
|
||||
"workspaceContains:**/*.myext"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
The extension activates when **any** event occurs.
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Do's ✅
|
||||
|
||||
1. **Use specific activation events**
|
||||
```json
|
||||
"activationEvents": ["onCommand:myExtension.specific"]
|
||||
```
|
||||
|
||||
2. **Defer heavy initialization**
|
||||
```typescript
|
||||
export async function activate(context) {
|
||||
// Quick registration
|
||||
context.registerCommand('myExtension.heavy', async () => {
|
||||
// Heavy work only when command is used
|
||||
await doHeavyWork();
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
3. **Load resources on demand**
|
||||
```typescript
|
||||
let heavyModule;
|
||||
|
||||
export async function activate(context) {
|
||||
context.registerCommand('myExtension.feature', async () => {
|
||||
// Lazy load when needed
|
||||
heavyModule = heavyModule || await import('./heavy');
|
||||
heavyModule.execute();
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Don'ts ❌
|
||||
|
||||
1. **Avoid star activation**
|
||||
```json
|
||||
// Bad - activates always
|
||||
"activationEvents": ["*"]
|
||||
```
|
||||
|
||||
2. **Don't block activation**
|
||||
```typescript
|
||||
// Bad - blocks activation
|
||||
export async function activate(context) {
|
||||
await longRunningOperation(); // Blocks
|
||||
}
|
||||
|
||||
// Good - defer work
|
||||
export async function activate(context) {
|
||||
setImmediate(() => longRunningOperation());
|
||||
}
|
||||
```
|
||||
|
||||
3. **Avoid unnecessary events**
|
||||
```json
|
||||
// Bad - too many events
|
||||
"activationEvents": [
|
||||
"onStartupFinished",
|
||||
"onCommand:*",
|
||||
"onView:*"
|
||||
]
|
||||
```
|
||||
|
||||
## Testing Activation Events
|
||||
|
||||
### Manual Testing
|
||||
|
||||
1. **Check activation timing**:
|
||||
```typescript
|
||||
export async function activate(context) {
|
||||
console.time('activation');
|
||||
// ... activation code
|
||||
console.timeEnd('activation');
|
||||
}
|
||||
```
|
||||
|
||||
2. **Verify event triggers**:
|
||||
```typescript
|
||||
// In browser console
|
||||
superset.extensions.getExtension('myExtension').state
|
||||
// Should be 'unloaded' before event
|
||||
|
||||
// Trigger event
|
||||
superset.commands.executeCommand('myExtension.start');
|
||||
|
||||
// Check again
|
||||
superset.extensions.getExtension('myExtension').state
|
||||
// Should be 'activated' after event
|
||||
```
|
||||
|
||||
### Automated Testing
|
||||
|
||||
```typescript
|
||||
describe('Extension Activation', () => {
|
||||
it('should activate on command', async () => {
|
||||
const extension = await loadExtension('myExtension');
|
||||
|
||||
expect(extension.state).toBe('unloaded');
|
||||
|
||||
await commands.executeCommand('myExtension.start');
|
||||
|
||||
expect(extension.state).toBe('activated');
|
||||
});
|
||||
|
||||
it('should not activate on unrelated event', async () => {
|
||||
const extension = await loadExtension('myExtension');
|
||||
|
||||
await commands.executeCommand('unrelated.command');
|
||||
|
||||
expect(extension.state).toBe('unloaded');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Debugging Activation
|
||||
|
||||
### Enable Debug Logging
|
||||
|
||||
```typescript
|
||||
// In extension
|
||||
const DEBUG = true;
|
||||
|
||||
export async function activate(context) {
|
||||
if (DEBUG) {
|
||||
console.log('[MyExtension] Activating', {
|
||||
extensionId: context.extensionId,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Monitor Activation Events
|
||||
|
||||
```typescript
|
||||
// In browser console
|
||||
superset.events.on('extension:activating', (e) => {
|
||||
console.log('Extension activating:', e.extensionId);
|
||||
});
|
||||
|
||||
superset.events.on('extension:activated', (e) => {
|
||||
console.log('Extension activated:', e.extensionId);
|
||||
});
|
||||
```
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Extension not activating:**
|
||||
- Check activation events are correct
|
||||
- Verify event is being triggered
|
||||
- Check browser console for errors
|
||||
- Ensure extension is enabled
|
||||
|
||||
**Extension activating too early:**
|
||||
- Review activation events
|
||||
- Consider using more specific events
|
||||
- Check for star activation
|
||||
|
||||
**Extension activating multiple times:**
|
||||
- Check for duplicate event registrations
|
||||
- Verify deactivation cleanup
|
||||
- Review activation logic
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Choose minimal activation events** - Only what's necessary
|
||||
2. **Defer expensive operations** - Don't block activation
|
||||
3. **Use specific events** - Avoid broad patterns
|
||||
4. **Test activation timing** - Ensure good performance
|
||||
5. **Document activation requirements** - Help users understand
|
||||
6. **Handle activation failures** - Graceful error handling
|
||||
7. **Clean up on deactivation** - Prevent memory leaks
|
||||
8. **Log activation in debug mode** - Aid troubleshooting
|
||||
9. **Consider user experience** - Balance performance and features
|
||||
10. **Version activation events** - Plan for changes
|
||||
|
||||
## Future Activation Events
|
||||
|
||||
These activation events are planned for future releases:
|
||||
|
||||
- `onUri` - Custom URI schemes
|
||||
- `onWebviewPanel` - Webview visibility
|
||||
- `onFileSystem` - File system providers
|
||||
- `onDebug` - Debug sessions
|
||||
- `onTaskType` - Task providers
|
||||
- `onNotebook` - Notebook documents
|
||||
- `onAuthentication` - Auth providers
|
||||
- `onCustomEditor` - Custom editors
|
||||
- `onTerminalProfile` - Terminal profiles
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### From Always Active to Lazy
|
||||
|
||||
Before (always active):
|
||||
```json
|
||||
{
|
||||
"activationEvents": ["*"]
|
||||
}
|
||||
```
|
||||
|
||||
After (lazy activation):
|
||||
```json
|
||||
{
|
||||
"activationEvents": [
|
||||
"onCommand:myExtension.command1",
|
||||
"onCommand:myExtension.command2",
|
||||
"onView:myExtension.view"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Adding New Activation Events
|
||||
|
||||
When adding features:
|
||||
```json
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"activationEvents": [
|
||||
"onCommand:myExtension.oldCommand"
|
||||
]
|
||||
}
|
||||
|
||||
// Version 1.1.0 - Added new feature
|
||||
{
|
||||
"version": "1.1.0",
|
||||
"activationEvents": [
|
||||
"onCommand:myExtension.oldCommand",
|
||||
"onCommand:myExtension.newCommand", // New
|
||||
"onView:myExtension.panel" // New
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Extension Manifest](/developer_portal/references/manifest)
|
||||
- [Lifecycle Management](/developer_portal/extensions/lifecycle-management)
|
||||
- [Contribution Points](/developer_portal/references/contribution-points)
|
||||
- [Architecture Overview](/developer_portal/architecture/overview)
|
||||
101
docs/developer_portal/references/api.md
Normal file
101
docs/developer_portal/references/api.md
Normal file
@@ -0,0 +1,101 @@
|
||||
---
|
||||
title: API Reference
|
||||
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.
|
||||
-->
|
||||
|
||||
# API Reference
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Complete API documentation for all Superset plugin development interfaces and services.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Core plugin development APIs
|
||||
- Chart and visualization APIs
|
||||
- Data transformation and query APIs
|
||||
- UI component and theming APIs
|
||||
- Event handling and lifecycle APIs
|
||||
- Configuration and settings APIs
|
||||
- Security and authentication APIs
|
||||
- Performance and monitoring APIs
|
||||
- Utility functions and helpers
|
||||
- TypeScript type definitions
|
||||
|
||||
## API Categories
|
||||
|
||||
### Core Plugin APIs
|
||||
|
||||
#### Plugin Registration
|
||||
```typescript
|
||||
// Plugin registration interface
|
||||
interface PluginConfig {
|
||||
name: string;
|
||||
version: string;
|
||||
components: ComponentRegistry;
|
||||
metadata: PluginMetadata;
|
||||
}
|
||||
|
||||
// registerPlugin function
|
||||
function registerPlugin(config: PluginConfig): void;
|
||||
```
|
||||
|
||||
#### Plugin Lifecycle
|
||||
- `onActivate()` - Plugin activation hook
|
||||
- `onDeactivate()` - Plugin deactivation hook
|
||||
- `onUpdate()` - Plugin update hook
|
||||
- `onConfigChange()` - Configuration change hook
|
||||
|
||||
### Chart Development APIs
|
||||
|
||||
#### Chart Component Interface
|
||||
```typescript
|
||||
interface ChartComponent {
|
||||
render(props: ChartProps): JSX.Element;
|
||||
transformProps(chartProps: ChartProps): TransformedProps;
|
||||
buildQuery(formData: FormData): Query;
|
||||
}
|
||||
```
|
||||
|
||||
#### Data Transformation
|
||||
- `transformProps()` - Data transformation function
|
||||
- `buildQuery()` - Query building function
|
||||
- `formatData()` - Data formatting utilities
|
||||
- `validateData()` - Data validation helpers
|
||||
|
||||
### UI and Theming APIs
|
||||
|
||||
#### Theme Provider
|
||||
- `useTheme()` - Theme context hook
|
||||
- `ThemeProvider` - Theme provider component
|
||||
- `createTheme()` - Theme creation utility
|
||||
- `mergeThemes()` - Theme composition function
|
||||
|
||||
#### Component Library
|
||||
- Button components and variants
|
||||
- Form controls and inputs
|
||||
- Layout and grid components
|
||||
- Data display components
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
475
docs/developer_portal/references/contribution-points.md
Normal file
475
docs/developer_portal/references/contribution-points.md
Normal file
@@ -0,0 +1,475 @@
|
||||
---
|
||||
title: Contribution Points
|
||||
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.
|
||||
-->
|
||||
|
||||
# Contribution Points Reference
|
||||
|
||||
Contribution points define where and how extensions can add functionality to Apache Superset. Extensions declare their contributions in the `extension.json` manifest file.
|
||||
|
||||
## Views
|
||||
|
||||
Views are UI components that appear in designated areas of Superset.
|
||||
|
||||
### SQL Lab Panels
|
||||
|
||||
Extensions can contribute panels to SQL Lab:
|
||||
|
||||
```json
|
||||
"contributions": {
|
||||
"views": {
|
||||
"sqllab.panels": [
|
||||
{
|
||||
"id": "myExtension.dataPanel",
|
||||
"name": "Data Explorer",
|
||||
"icon": "DatabaseOutlined",
|
||||
"when": "sqllab.connected"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Properties**:
|
||||
- `id` - Unique view identifier
|
||||
- `name` - Display name in UI
|
||||
- `icon` - Ant Design icon name
|
||||
- `when` - Conditional visibility
|
||||
|
||||
**Available Locations**:
|
||||
- `sqllab.panels` - Side panels in SQL Lab
|
||||
- `sqllab.bottomPanels` - Bottom panels below editor
|
||||
|
||||
**TODO: Future Locations**:
|
||||
- `dashboard.widgets` - Dashboard widget areas
|
||||
- `chart.panels` - Chart editor panels
|
||||
- `explore.sections` - Explore view sections
|
||||
|
||||
### View Registration
|
||||
|
||||
In your extension code:
|
||||
|
||||
```typescript
|
||||
export function activate(context: ExtensionContext) {
|
||||
const view = context.registerView(
|
||||
'myExtension.dataPanel',
|
||||
<DataExplorerPanel />
|
||||
);
|
||||
|
||||
context.subscriptions.push(view);
|
||||
}
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
Commands are actions that can be invoked by users or other extensions.
|
||||
|
||||
### Command Definition
|
||||
|
||||
```json
|
||||
"commands": [
|
||||
{
|
||||
"command": "myExtension.runAnalysis",
|
||||
"title": "Run Analysis",
|
||||
"category": "Data Tools",
|
||||
"icon": "PlayCircleOutlined",
|
||||
"enablement": "sqllab.hasQuery && !sqllab.running"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**Properties**:
|
||||
- `command` - Unique command identifier
|
||||
- `title` - Display name
|
||||
- `category` - Command palette category
|
||||
- `icon` - Optional icon
|
||||
- `enablement` - Condition for enabling
|
||||
|
||||
### Command Registration
|
||||
|
||||
```typescript
|
||||
commands.registerCommand('myExtension.runAnalysis', {
|
||||
execute: async (...args) => {
|
||||
const query = sqlLab.getCurrentQuery();
|
||||
const result = await analyzeQuery(query);
|
||||
return result;
|
||||
},
|
||||
|
||||
isEnabled: () => {
|
||||
return sqlLab.hasQuery() && !sqlLab.isRunning();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Built-in Commands
|
||||
|
||||
Extensions can invoke these built-in commands:
|
||||
|
||||
```typescript
|
||||
// SQL Lab commands
|
||||
await commands.executeCommand('sqllab.executeQuery');
|
||||
await commands.executeCommand('sqllab.formatQuery');
|
||||
await commands.executeCommand('sqllab.saveQuery');
|
||||
await commands.executeCommand('sqllab.exportResults');
|
||||
|
||||
// Editor commands
|
||||
await commands.executeCommand('editor.action.formatDocument');
|
||||
await commands.executeCommand('editor.action.commentLine');
|
||||
|
||||
// System commands
|
||||
await commands.executeCommand('workbench.action.openSettings');
|
||||
await commands.executeCommand('workbench.action.showCommands');
|
||||
```
|
||||
|
||||
## Menus
|
||||
|
||||
Add items to existing Superset menus.
|
||||
|
||||
### Menu Contributions
|
||||
|
||||
```json
|
||||
"menus": {
|
||||
"sqllab.editor": {
|
||||
"primary": [
|
||||
{
|
||||
"command": "myExtension.analyze",
|
||||
"group": "navigation",
|
||||
"order": 1,
|
||||
"when": "editorFocus"
|
||||
}
|
||||
],
|
||||
"secondary": [
|
||||
{
|
||||
"command": "myExtension.settings",
|
||||
"group": "settings"
|
||||
}
|
||||
],
|
||||
"context": [
|
||||
{
|
||||
"command": "myExtension.explain",
|
||||
"group": "1_modification",
|
||||
"when": "editorTextFocus && editorHasSelection"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Menu Locations**:
|
||||
- `sqllab.editor.primary` - Main toolbar
|
||||
- `sqllab.editor.secondary` - Secondary toolbar
|
||||
- `sqllab.editor.context` - Right-click menu
|
||||
|
||||
**Groups** (for organization):
|
||||
- `navigation` - Primary navigation items
|
||||
- `1_modification` - Edit operations
|
||||
- `2_workspace` - Workspace management
|
||||
- `9_cutcopypaste` - Clipboard operations
|
||||
- `z_commands` - Other commands
|
||||
|
||||
**TODO: Future Menu Locations**:
|
||||
- `explorer.context` - Data explorer context menu
|
||||
- `dashboard.toolbar` - Dashboard toolbar
|
||||
- `chart.context` - Chart context menu
|
||||
|
||||
## Configuration
|
||||
|
||||
Define user-configurable settings.
|
||||
|
||||
### Configuration Schema
|
||||
|
||||
```json
|
||||
"configuration": {
|
||||
"title": "My Extension Settings",
|
||||
"order": 10,
|
||||
"properties": {
|
||||
"myExtension.enableFeature": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Enable the main feature",
|
||||
"order": 1
|
||||
},
|
||||
"myExtension.apiEndpoint": {
|
||||
"type": "string",
|
||||
"default": "https://api.example.com",
|
||||
"description": "API endpoint URL",
|
||||
"pattern": "^https?://",
|
||||
"order": 2
|
||||
},
|
||||
"myExtension.refreshInterval": {
|
||||
"type": "number",
|
||||
"default": 5000,
|
||||
"minimum": 1000,
|
||||
"maximum": 60000,
|
||||
"description": "Refresh interval in milliseconds",
|
||||
"order": 3
|
||||
},
|
||||
"myExtension.theme": {
|
||||
"type": "string",
|
||||
"enum": ["light", "dark", "auto"],
|
||||
"enumDescriptions": [
|
||||
"Light theme",
|
||||
"Dark theme",
|
||||
"Follow system"
|
||||
],
|
||||
"default": "auto",
|
||||
"description": "Color theme",
|
||||
"order": 4
|
||||
},
|
||||
"myExtension.advanced": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cacheSize": {
|
||||
"type": "number",
|
||||
"default": 100
|
||||
},
|
||||
"debug": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"description": "Advanced settings",
|
||||
"order": 5
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Accessing Configuration
|
||||
|
||||
```typescript
|
||||
// Get configuration value
|
||||
const isEnabled = workspace.getConfiguration('myExtension')
|
||||
.get<boolean>('enableFeature');
|
||||
|
||||
// Update configuration
|
||||
await workspace.getConfiguration('myExtension')
|
||||
.update('refreshInterval', 10000);
|
||||
|
||||
// Listen for changes
|
||||
workspace.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('myExtension.theme')) {
|
||||
updateTheme();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Keybindings
|
||||
|
||||
Register keyboard shortcuts for commands.
|
||||
|
||||
### TODO: Keybinding Definition (Future)
|
||||
|
||||
```json
|
||||
"keybindings": [
|
||||
{
|
||||
"command": "myExtension.runQuery",
|
||||
"key": "ctrl+shift+r",
|
||||
"mac": "cmd+shift+r",
|
||||
"when": "editorTextFocus"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Language Support
|
||||
|
||||
### TODO: Language Contributions (Future)
|
||||
|
||||
```json
|
||||
"languages": [
|
||||
{
|
||||
"id": "supersql",
|
||||
"extensions": [".ssql"],
|
||||
"aliases": ["SuperSQL", "ssql"],
|
||||
"configuration": "./language-configuration.json"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Themes
|
||||
|
||||
### TODO: Theme Contributions (Future)
|
||||
|
||||
```json
|
||||
"themes": [
|
||||
{
|
||||
"label": "My Dark Theme",
|
||||
"uiTheme": "vs-dark",
|
||||
"path": "./themes/my-dark-theme.json"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Status Bar
|
||||
|
||||
Add items to the status bar.
|
||||
|
||||
### TODO: Status Bar Contributions (Future)
|
||||
|
||||
```json
|
||||
"statusBar": [
|
||||
{
|
||||
"id": "myExtension.status",
|
||||
"alignment": "left",
|
||||
"priority": 100,
|
||||
"text": "$(database) Connected",
|
||||
"tooltip": "Database connection status",
|
||||
"command": "myExtension.showStatus"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Activity Bar
|
||||
|
||||
### TODO: Activity Bar Contributions (Future)
|
||||
|
||||
```json
|
||||
"activityBar": [
|
||||
{
|
||||
"id": "myExtension.explorer",
|
||||
"title": "Data Explorer",
|
||||
"icon": "./icons/explorer.svg"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Context Variables
|
||||
|
||||
Extensions can use these context variables in `when` clauses:
|
||||
|
||||
### SQL Lab Context
|
||||
|
||||
- `sqllab.connected` - Database connection established
|
||||
- `sqllab.hasQuery` - Query text present
|
||||
- `sqllab.querySelected` - Query text selected
|
||||
- `sqllab.running` - Query executing
|
||||
- `sqllab.hasResults` - Results available
|
||||
- `sqllab.queryExecuted` - Query has been run
|
||||
- `sqllab.panelVisible` - Specific panel visible
|
||||
- `sqllab.tabActive` - Specific tab active
|
||||
|
||||
### Editor Context
|
||||
|
||||
- `editorFocus` - Editor has focus
|
||||
- `editorTextFocus` - Text area focused
|
||||
- `editorHasSelection` - Text selected
|
||||
- `editorHasMultipleSelections` - Multiple selections
|
||||
- `editorReadonly` - Editor is read-only
|
||||
- `editorLangId` - Language ID matches
|
||||
|
||||
### Workspace Context
|
||||
|
||||
- `workspaceFolderCount` - Number of workspace folders
|
||||
- `workspaceState` - Workspace state value
|
||||
- `config.*` - Configuration values
|
||||
|
||||
### Resource Context
|
||||
|
||||
- `resourceScheme` - URI scheme matches
|
||||
- `resourceFilename` - Filename matches pattern
|
||||
- `resourceExtname` - File extension matches
|
||||
- `resourceLangId` - Resource language ID
|
||||
|
||||
## Activation Events
|
||||
|
||||
Control when your extension activates:
|
||||
|
||||
```json
|
||||
"activationEvents": [
|
||||
"onCommand:myExtension.start",
|
||||
"onView:myExtension.explorer",
|
||||
"onLanguage:sql",
|
||||
"workspaceContains:**/*.ssql",
|
||||
"onStartupFinished"
|
||||
]
|
||||
```
|
||||
|
||||
See [Activation Events](/developer_portal/references/activation-events) for details.
|
||||
|
||||
## API Access Declaration
|
||||
|
||||
Declare which APIs your extension uses:
|
||||
|
||||
```json
|
||||
"capabilities": {
|
||||
"apis": [
|
||||
"sqllab.*",
|
||||
"authentication.getUser",
|
||||
"workspace.getConfiguration",
|
||||
"commands.executeCommand"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Contribution Validation
|
||||
|
||||
Contributions are validated:
|
||||
|
||||
1. **At build time** - Schema validation
|
||||
2. **At registration** - Conflict detection
|
||||
3. **At runtime** - Permission checks
|
||||
|
||||
Common validation errors:
|
||||
- Duplicate command IDs
|
||||
- Invalid menu locations
|
||||
- Missing required properties
|
||||
- Circular dependencies
|
||||
- Invalid context expressions
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use namespaced IDs** - Prefix with extension name
|
||||
2. **Declare minimal capabilities** - Only request needed APIs
|
||||
3. **Provide meaningful descriptions** - Help users understand
|
||||
4. **Use appropriate icons** - Follow Ant Design guidelines
|
||||
5. **Group related items** - Organize menus logically
|
||||
6. **Test context conditions** - Ensure `when` clauses work
|
||||
7. **Handle missing permissions** - Graceful degradation
|
||||
8. **Document commands** - Explain what they do
|
||||
9. **Version your APIs** - Plan for changes
|
||||
10. **Validate user input** - For configuration values
|
||||
|
||||
## Future Contribution Points
|
||||
|
||||
These contribution points are planned for future releases:
|
||||
|
||||
- **Debuggers** - Custom debugging adapters
|
||||
- **Tasks** - Background task providers
|
||||
- **Snippets** - Code snippets
|
||||
- **Color Themes** - Complete color themes
|
||||
- **Icon Themes** - Icon set definitions
|
||||
- **Product Icons** - Custom product icons
|
||||
- **Walkthroughs** - Getting started guides
|
||||
- **Authentication** - Auth providers
|
||||
- **Views Containers** - Custom view containers
|
||||
- **Terminal** - Terminal profiles
|
||||
- **Comments** - Comment providers
|
||||
- **Code Actions** - Quick fixes
|
||||
- **Code Lens** - Inline commands
|
||||
- **Semantic Tokens** - Syntax highlighting
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Extension Manifest](/developer_portal/references/manifest)
|
||||
- [Activation Events](/developer_portal/references/activation-events)
|
||||
- [API Reference](/developer_portal/api/frontend)
|
||||
- [Frontend Contribution Types](/developer_portal/extensions/frontend-contribution-types)
|
||||
526
docs/developer_portal/references/manifest.md
Normal file
526
docs/developer_portal/references/manifest.md
Normal file
@@ -0,0 +1,526 @@
|
||||
---
|
||||
title: Extension Manifest
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
# Extension Manifest Reference
|
||||
|
||||
The `extension.json` file defines metadata, capabilities, and configuration for a Superset extension. This file is required at the root of every extension project.
|
||||
|
||||
## Complete Example
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "dataset_references",
|
||||
"displayName": "Dataset References",
|
||||
"version": "1.0.0",
|
||||
"description": "Display metadata about tables referenced in SQL queries",
|
||||
"author": "Apache Superset Contributors",
|
||||
"license": "Apache-2.0",
|
||||
"homepage": "https://github.com/apache/superset",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/apache/superset.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/apache/superset/issues"
|
||||
},
|
||||
"engines": {
|
||||
"superset": ">=4.0.0"
|
||||
},
|
||||
"categories": ["SQL Lab", "Analytics"],
|
||||
"keywords": ["sql", "metadata", "tables", "references"],
|
||||
"icon": "database",
|
||||
"galleryBanner": {
|
||||
"color": "#1890ff",
|
||||
"theme": "dark"
|
||||
},
|
||||
"frontend": {
|
||||
"main": "./dist/index.js",
|
||||
"contributions": {
|
||||
"views": {
|
||||
"sqllab.panels": [
|
||||
{
|
||||
"id": "dataset_references.main",
|
||||
"name": "Dataset References",
|
||||
"icon": "TableOutlined",
|
||||
"when": "sqllab.queryExecuted"
|
||||
}
|
||||
]
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"command": "dataset_references.refresh",
|
||||
"title": "Refresh Dataset Metadata",
|
||||
"category": "Dataset References",
|
||||
"icon": "ReloadOutlined"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
"sqllab.editor": {
|
||||
"primary": [
|
||||
{
|
||||
"command": "dataset_references.refresh",
|
||||
"group": "navigation",
|
||||
"when": "dataset_references.panelVisible"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"configuration": {
|
||||
"title": "Dataset References",
|
||||
"properties": {
|
||||
"dataset_references.autoRefresh": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Automatically refresh metadata on query execution"
|
||||
},
|
||||
"dataset_references.showPartitions": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Display partition information"
|
||||
},
|
||||
"dataset_references.cacheTimeout": {
|
||||
"type": "number",
|
||||
"default": 300,
|
||||
"description": "Cache timeout in seconds"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"moduleFederation": {
|
||||
"name": "dataset_references",
|
||||
"exposes": {
|
||||
"./index": "./src/index"
|
||||
},
|
||||
"shared": {
|
||||
"react": { "singleton": true },
|
||||
"react-dom": { "singleton": true }
|
||||
}
|
||||
}
|
||||
},
|
||||
"backend": {
|
||||
"main": "dataset_references.entrypoint",
|
||||
"entryPoints": ["dataset_references.entrypoint"],
|
||||
"files": ["backend/src/dataset_references/**/*.py"],
|
||||
"requirements": [
|
||||
"sqlparse>=0.4.0",
|
||||
"pandas>=1.3.0"
|
||||
]
|
||||
},
|
||||
"activationEvents": [
|
||||
"onView:sqllab.panels",
|
||||
"onCommand:dataset_references.refresh",
|
||||
"workspaceContains:**/*.sql"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Required Fields
|
||||
|
||||
### name
|
||||
- **Type**: `string`
|
||||
- **Pattern**: `^[a-z0-9_]+$`
|
||||
- **Description**: Unique identifier for the extension. Must be lowercase with underscores.
|
||||
|
||||
```json
|
||||
"name": "my_extension"
|
||||
```
|
||||
|
||||
### version
|
||||
- **Type**: `string`
|
||||
- **Format**: [Semantic Versioning](https://semver.org/)
|
||||
- **Description**: Extension version following semver format.
|
||||
|
||||
```json
|
||||
"version": "1.2.3"
|
||||
```
|
||||
|
||||
### engines
|
||||
- **Type**: `object`
|
||||
- **Description**: Specifies compatible Superset versions.
|
||||
|
||||
```json
|
||||
"engines": {
|
||||
"superset": ">=4.0.0 <5.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
## Metadata Fields
|
||||
|
||||
### displayName
|
||||
- **Type**: `string`
|
||||
- **Description**: Human-readable name shown in UI.
|
||||
|
||||
### description
|
||||
- **Type**: `string`
|
||||
- **Description**: Short description of extension functionality.
|
||||
|
||||
### author
|
||||
- **Type**: `string` | `object`
|
||||
- **Description**: Extension author information.
|
||||
|
||||
```json
|
||||
"author": {
|
||||
"name": "Jane Doe",
|
||||
"email": "jane@example.com",
|
||||
"url": "https://example.com"
|
||||
}
|
||||
```
|
||||
|
||||
### license
|
||||
- **Type**: `string`
|
||||
- **Description**: SPDX license identifier.
|
||||
- **Common values**: `Apache-2.0`, `MIT`, `BSD-3-Clause`
|
||||
|
||||
### categories
|
||||
- **Type**: `string[]`
|
||||
- **Description**: Extension categories for marketplace organization.
|
||||
- **Valid values**:
|
||||
- `"SQL Lab"`
|
||||
- `"Dashboard"`
|
||||
- `"Charts"`
|
||||
- `"Data Sources"`
|
||||
- `"Analytics"`
|
||||
- `"Security"`
|
||||
- `"Theming"`
|
||||
- `"Developer Tools"`
|
||||
|
||||
### keywords
|
||||
- **Type**: `string[]`
|
||||
- **Description**: Search keywords for extension discovery.
|
||||
|
||||
### icon
|
||||
- **Type**: `string`
|
||||
- **Description**: Icon identifier or path to icon file.
|
||||
|
||||
## Frontend Configuration
|
||||
|
||||
### frontend.main
|
||||
- **Type**: `string`
|
||||
- **Description**: Entry point for frontend code.
|
||||
|
||||
### frontend.contributions
|
||||
|
||||
Defines how the extension extends Superset's UI.
|
||||
|
||||
#### views
|
||||
Register custom views and panels:
|
||||
|
||||
```json
|
||||
"views": {
|
||||
"sqllab.panels": [
|
||||
{
|
||||
"id": "extension.panel",
|
||||
"name": "My Panel",
|
||||
"icon": "icon-name",
|
||||
"when": "condition"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**View Locations**:
|
||||
- `sqllab.panels` - SQL Lab side panels
|
||||
- `sqllab.bottomPanels` - SQL Lab bottom panels
|
||||
- `dashboard.widgets` - Dashboard widgets (TODO: future)
|
||||
- `chart.toolbar` - Chart toolbar items (TODO: future)
|
||||
|
||||
#### commands
|
||||
Register executable commands:
|
||||
|
||||
```json
|
||||
"commands": [
|
||||
{
|
||||
"command": "extension.doSomething",
|
||||
"title": "Do Something",
|
||||
"category": "My Extension",
|
||||
"icon": "PlayCircleOutlined",
|
||||
"enablement": "resourceIsSelected"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### menus
|
||||
Add items to existing menus:
|
||||
|
||||
```json
|
||||
"menus": {
|
||||
"sqllab.editor": {
|
||||
"primary": [
|
||||
{
|
||||
"command": "extension.command",
|
||||
"group": "navigation",
|
||||
"when": "editorFocus"
|
||||
}
|
||||
],
|
||||
"context": [
|
||||
{
|
||||
"command": "extension.contextAction",
|
||||
"group": "1_modification"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Menu Locations**:
|
||||
- `sqllab.editor.primary` - Main SQL Lab toolbar
|
||||
- `sqllab.editor.secondary` - Secondary actions
|
||||
- `sqllab.editor.context` - Right-click context menu
|
||||
- `explorer.context` - Data explorer context menu (TODO: future)
|
||||
|
||||
#### configuration
|
||||
Define extension settings:
|
||||
|
||||
```json
|
||||
"configuration": {
|
||||
"title": "My Extension",
|
||||
"properties": {
|
||||
"myExtension.setting1": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Enable feature X"
|
||||
},
|
||||
"myExtension.setting2": {
|
||||
"type": "string",
|
||||
"enum": ["option1", "option2"],
|
||||
"default": "option1",
|
||||
"description": "Choose option"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Property Types**:
|
||||
- `boolean` - True/false toggle
|
||||
- `string` - Text input
|
||||
- `number` - Numeric input
|
||||
- `array` - List of values
|
||||
- `object` - Complex configuration
|
||||
|
||||
### frontend.moduleFederation
|
||||
|
||||
Webpack Module Federation configuration:
|
||||
|
||||
```json
|
||||
"moduleFederation": {
|
||||
"name": "extension_name",
|
||||
"exposes": {
|
||||
"./index": "./src/index"
|
||||
},
|
||||
"shared": {
|
||||
"react": { "singleton": true },
|
||||
"react-dom": { "singleton": true },
|
||||
"@apache-superset/core": { "singleton": true }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Backend Configuration
|
||||
|
||||
### backend.main
|
||||
- **Type**: `string`
|
||||
- **Description**: Main Python module entry point.
|
||||
|
||||
### backend.entryPoints
|
||||
- **Type**: `string[]`
|
||||
- **Description**: Python modules to load on startup.
|
||||
|
||||
```json
|
||||
"entryPoints": [
|
||||
"my_extension.api",
|
||||
"my_extension.security",
|
||||
"my_extension.models"
|
||||
]
|
||||
```
|
||||
|
||||
### backend.files
|
||||
- **Type**: `string[]`
|
||||
- **Description**: Glob patterns for backend files to include.
|
||||
|
||||
```json
|
||||
"files": [
|
||||
"backend/src/**/*.py",
|
||||
"backend/config/*.yaml"
|
||||
]
|
||||
```
|
||||
|
||||
### backend.requirements
|
||||
- **Type**: `string[]`
|
||||
- **Description**: Python package dependencies.
|
||||
|
||||
```json
|
||||
"requirements": [
|
||||
"requests>=2.28.0",
|
||||
"pandas>=1.3.0,<2.0.0"
|
||||
]
|
||||
```
|
||||
|
||||
## Activation Events
|
||||
|
||||
Controls when the extension is activated:
|
||||
|
||||
```json
|
||||
"activationEvents": [
|
||||
"onView:sqllab.panels",
|
||||
"onCommand:myExtension.start",
|
||||
"onLanguage:sql",
|
||||
"workspaceContains:**/*.sql",
|
||||
"*"
|
||||
]
|
||||
```
|
||||
|
||||
**Event Types**:
|
||||
- `onView:<viewId>` - When specific view is opened
|
||||
- `onCommand:<commandId>` - When command is executed
|
||||
- `onLanguage:<language>` - When file type is opened
|
||||
- `workspaceContains:<pattern>` - When workspace contains matching files
|
||||
- `onStartupFinished` - After Superset fully starts
|
||||
- `*` - Always activate (not recommended)
|
||||
|
||||
## Conditional Activation ("when" clauses)
|
||||
|
||||
Control when UI elements are visible/enabled:
|
||||
|
||||
```json
|
||||
"when": "sqllab.queryExecuted && config.myExtension.enabled"
|
||||
```
|
||||
|
||||
**Context Keys**:
|
||||
- `sqllab.queryExecuted` - Query has been run
|
||||
- `sqllab.hasResults` - Query returned results
|
||||
- `editorFocus` - Editor is focused
|
||||
- `resourceIsSelected` - Resource selected in explorer
|
||||
- `config.<setting>` - Configuration value check
|
||||
|
||||
**Operators**:
|
||||
- `&&` - AND
|
||||
- `||` - OR
|
||||
- `!` - NOT
|
||||
- `==` - Equals
|
||||
- `!=` - Not equals
|
||||
- `=~` - Regex match
|
||||
|
||||
## Capabilities Declaration
|
||||
|
||||
Declare required permissions and capabilities:
|
||||
|
||||
```json
|
||||
"capabilities": {
|
||||
"permissions": [
|
||||
"database.read",
|
||||
"query.execute",
|
||||
"cache.write"
|
||||
],
|
||||
"apis": [
|
||||
"sqllab.*",
|
||||
"authentication.getUser"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Build Configuration
|
||||
|
||||
### TODO: Future Fields
|
||||
|
||||
These fields are planned for future implementation:
|
||||
|
||||
```json
|
||||
{
|
||||
"publisher": "organization-name",
|
||||
"preview": false,
|
||||
"contributes": {
|
||||
"themes": [],
|
||||
"languages": [],
|
||||
"debuggers": [],
|
||||
"jsonValidation": []
|
||||
},
|
||||
"extensionDependencies": [
|
||||
"other-extension@^1.0.0"
|
||||
],
|
||||
"extensionPack": [
|
||||
"extension1",
|
||||
"extension2"
|
||||
],
|
||||
"scripts": {
|
||||
"compile": "webpack",
|
||||
"test": "jest",
|
||||
"lint": "eslint"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
The manifest is validated against a JSON schema during:
|
||||
- Development (`superset-extensions dev`)
|
||||
- Build (`superset-extensions build`)
|
||||
- Installation (API upload)
|
||||
|
||||
Common validation errors:
|
||||
- Missing required fields
|
||||
- Invalid version format
|
||||
- Incompatible engine version
|
||||
- Duplicate command IDs
|
||||
- Invalid activation events
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use semantic versioning** for the version field
|
||||
2. **Declare minimum Superset version** accurately
|
||||
3. **Use specific activation events** to improve performance
|
||||
4. **Provide clear descriptions** for configuration options
|
||||
5. **Include all required Python dependencies** in requirements
|
||||
6. **Use unique IDs** for commands and views
|
||||
7. **Follow naming conventions** (snake_case for name, camelCase for settings)
|
||||
8. **Include complete author information** for support
|
||||
9. **Specify appropriate categories** for discovery
|
||||
10. **Test manifest changes** before deployment
|
||||
|
||||
## Migration from Legacy Format
|
||||
|
||||
If migrating from older extension formats:
|
||||
|
||||
```javascript
|
||||
// Legacy format (deprecated)
|
||||
{
|
||||
"plugin_name": "MyPlugin",
|
||||
"plugin_version": "1.0"
|
||||
}
|
||||
|
||||
// New format
|
||||
{
|
||||
"name": "my_plugin",
|
||||
"version": "1.0.0",
|
||||
"engines": {
|
||||
"superset": ">=4.0.0"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Extension Project Structure](/developer_portal/extensions/extension-project-structure)
|
||||
- [Contribution Points](/developer_portal/references/contribution-points)
|
||||
- [Activation Events](/developer_portal/references/activation-events)
|
||||
- [API Reference](/developer_portal/api/frontend)
|
||||
74
docs/developer_portal/references/overview.md
Normal file
74
docs/developer_portal/references/overview.md
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
title: References Overview
|
||||
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.
|
||||
-->
|
||||
|
||||
# References Overview
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Comprehensive reference documentation for all Superset plugin APIs, configuration options, and development resources.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Complete API reference documentation
|
||||
- Plugin configuration schemas
|
||||
- Event and hook reference
|
||||
- Component library documentation
|
||||
- TypeScript type definitions
|
||||
- Extension point catalog
|
||||
- Error code reference
|
||||
- Performance metrics documentation
|
||||
- Migration guides and changelogs
|
||||
- Troubleshooting and FAQ
|
||||
|
||||
## Reference Sections
|
||||
|
||||
### API Documentation
|
||||
- **Plugin APIs** - Core plugin development interfaces
|
||||
- **Chart APIs** - Visualization component interfaces
|
||||
- **Data APIs** - Query and transformation interfaces
|
||||
- **UI APIs** - User interface and theming interfaces
|
||||
- **Utility APIs** - Helper functions and utilities
|
||||
|
||||
### Configuration References
|
||||
- **Plugin Manifests** - Plugin.json schema and options
|
||||
- **Contribution Points** - Available extension points
|
||||
- **Activation Events** - Plugin lifecycle triggers
|
||||
- **Settings Schema** - Configuration option definitions
|
||||
|
||||
### Development Resources
|
||||
- **TypeScript Definitions** - Complete type reference
|
||||
- **Component Library** - Reusable UI components
|
||||
- **Testing Utilities** - Testing helpers and mocks
|
||||
- **Build Tools** - Webpack and bundling configuration
|
||||
|
||||
## Documentation Format
|
||||
|
||||
- **Interactive examples** - Live code demonstrations
|
||||
- **Type annotations** - Complete TypeScript signatures
|
||||
- **Usage patterns** - Common implementation examples
|
||||
- **Migration notes** - Version upgrade guidance
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
@@ -22,10 +22,16 @@ module.exports = {
|
||||
'index',
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Contributing',
|
||||
collapsed: true,
|
||||
label: 'Getting Started',
|
||||
items: [
|
||||
'contributing/overview',
|
||||
'getting-started/index',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Architecture',
|
||||
items: [
|
||||
'architecture/overview',
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -33,24 +39,47 @@ module.exports = {
|
||||
label: 'Extensions',
|
||||
collapsed: true,
|
||||
items: [
|
||||
'extensions/overview',
|
||||
'extensions/quick-start',
|
||||
'extensions/architecture',
|
||||
'extensions/architectural-principles',
|
||||
'extensions/high-level-architecture',
|
||||
'extensions/extension-project-structure',
|
||||
'extensions/extension-metadata',
|
||||
'extensions/frontend-contribution-types',
|
||||
'extensions/interacting-with-host',
|
||||
'extensions/dynamic-module-loading',
|
||||
'extensions/deploying-extension',
|
||||
'extensions/lifecycle-management',
|
||||
'extensions/development-mode',
|
||||
'extensions/versioning',
|
||||
'extensions/security-implications',
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'extensions/built-in-features',
|
||||
customProps: {
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
'extensions/proof-of-concept',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Testing',
|
||||
collapsed: true,
|
||||
label: 'API Reference',
|
||||
items: [
|
||||
'testing/overview',
|
||||
'api/frontend',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'CLI',
|
||||
items: [
|
||||
'cli/overview',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Examples',
|
||||
items: [
|
||||
'examples/index',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Overview
|
||||
title: Testing Overview
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
@@ -22,7 +22,7 @@ specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
# Overview
|
||||
# Testing Overview
|
||||
|
||||
Apache Superset follows a comprehensive testing strategy that ensures code quality, reliability, and maintainability. This section covers all aspects of testing in the Superset ecosystem, from unit tests to end-to-end testing workflows.
|
||||
|
||||
|
||||
70
docs/developer_portal/ux/accessibility.md
Normal file
70
docs/developer_portal/ux/accessibility.md
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
title: Accessibility Guidelines
|
||||
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.
|
||||
-->
|
||||
|
||||
# Accessibility Guidelines
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Ensure your Superset plugins are accessible to users with disabilities and comply with modern accessibility standards.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- WCAG 2.1 compliance requirements
|
||||
- Keyboard navigation and focus management
|
||||
- Screen reader compatibility
|
||||
- Color contrast and visual accessibility
|
||||
- Alternative text for images and charts
|
||||
- Accessible form design and validation
|
||||
- ARIA labels and semantic markup
|
||||
- Accessibility testing tools and techniques
|
||||
- Voice control and assistive technology support
|
||||
- Internationalization and right-to-left languages
|
||||
|
||||
## Accessibility Standards
|
||||
|
||||
### WCAG 2.1 Level AA Compliance
|
||||
- **Perceivable** - Information presented in ways users can perceive
|
||||
- **Operable** - Interface components must be operable by all users
|
||||
- **Understandable** - Information and UI operation must be understandable
|
||||
- **Robust** - Content must be robust enough for various assistive technologies
|
||||
|
||||
### Key Requirements
|
||||
|
||||
- **Color contrast** - Minimum 4.5:1 ratio for normal text
|
||||
- **Keyboard navigation** - All functionality accessible via keyboard
|
||||
- **Focus indicators** - Clear visual focus indicators
|
||||
- **Alternative text** - Meaningful descriptions for non-text content
|
||||
- **Error identification** - Clear error messages and instructions
|
||||
|
||||
## Testing Tools
|
||||
|
||||
- axe-core accessibility testing
|
||||
- Lighthouse accessibility audits
|
||||
- Screen reader testing (NVDA, JAWS, VoiceOver)
|
||||
- Keyboard navigation testing
|
||||
- Color contrast analyzers
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
73
docs/developer_portal/ux/best-practices.md
Normal file
73
docs/developer_portal/ux/best-practices.md
Normal file
@@ -0,0 +1,73 @@
|
||||
---
|
||||
title: UX Best Practices
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
# UX Best Practices
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Practical guidelines and proven patterns for creating exceptional user experiences in Superset plugins.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- User research and persona development
|
||||
- Usability testing and feedback collection
|
||||
- Information architecture and navigation design
|
||||
- Interaction design patterns
|
||||
- Visual design and branding consistency
|
||||
- Performance optimization for user experience
|
||||
- Mobile and responsive design strategies
|
||||
- User onboarding and feature discovery
|
||||
- Error handling and graceful degradation
|
||||
- Analytics and user behavior tracking
|
||||
|
||||
## Common UX Patterns
|
||||
|
||||
### Data Visualization
|
||||
- **Progressive disclosure** - Show summary first, details on demand
|
||||
- **Contextual actions** - Relevant controls near data points
|
||||
- **Consistent legends** - Standardized color coding and symbols
|
||||
- **Responsive charts** - Adapt to different screen sizes
|
||||
|
||||
### Navigation and Discovery
|
||||
- **Breadcrumb navigation** - Clear path indicators
|
||||
- **Search and filtering** - Quick content discovery
|
||||
- **Contextual menus** - Right-click and hover actions
|
||||
- **Keyboard shortcuts** - Power user efficiency
|
||||
|
||||
### Form Design
|
||||
- **Smart defaults** - Pre-populate based on context
|
||||
- **Inline validation** - Real-time feedback
|
||||
- **Progressive enhancement** - Advanced features for power users
|
||||
- **Clear error states** - Helpful error messages and recovery
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
- Loading state management
|
||||
- Perceived performance optimization
|
||||
- Data streaming and pagination
|
||||
- Client-side caching strategies
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
68
docs/developer_portal/ux/design-principles.md
Normal file
68
docs/developer_portal/ux/design-principles.md
Normal file
@@ -0,0 +1,68 @@
|
||||
---
|
||||
title: Design Principles
|
||||
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.
|
||||
-->
|
||||
|
||||
# Design Principles
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Core design principles that guide the development of effective and user-friendly Superset plugins.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Data-first design philosophy
|
||||
- Progressive disclosure principles
|
||||
- Cognitive load reduction strategies
|
||||
- Visual hierarchy and information architecture
|
||||
- Feedback and affordance design
|
||||
- Error prevention and recovery
|
||||
- Performance and perceived performance
|
||||
- Cross-platform consistency
|
||||
- Internationalization considerations
|
||||
- Mobile and responsive design principles
|
||||
|
||||
## Fundamental Principles
|
||||
|
||||
### Data Transparency
|
||||
- Make data sources and transformations visible
|
||||
- Provide clear data lineage and provenance
|
||||
- Show confidence levels and data quality indicators
|
||||
|
||||
### User Empowerment
|
||||
- Enable self-service analytics
|
||||
- Provide multiple paths to accomplish goals
|
||||
- Support both novice and expert workflows
|
||||
|
||||
### Contextual Relevance
|
||||
- Show relevant information at the right time
|
||||
- Minimize context switching
|
||||
- Provide smart defaults based on user behavior
|
||||
|
||||
### Collaborative Design
|
||||
- Support sharing and collaboration features
|
||||
- Enable team workflows and permissions
|
||||
- Provide commenting and annotation capabilities
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
62
docs/developer_portal/ux/overview.md
Normal file
62
docs/developer_portal/ux/overview.md
Normal file
@@ -0,0 +1,62 @@
|
||||
---
|
||||
title: User Experience Guidelines
|
||||
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.
|
||||
-->
|
||||
|
||||
# User Experience Guidelines
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Comprehensive guidelines for creating intuitive and accessible user experiences in Superset plugins.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Superset design system principles
|
||||
- User interface consistency standards
|
||||
- Interaction patterns and behaviors
|
||||
- Visual hierarchy and layout guidelines
|
||||
- Color usage and accessibility compliance
|
||||
- Typography and content guidelines
|
||||
- Responsive design principles
|
||||
- Error handling and user feedback
|
||||
- Loading states and performance indicators
|
||||
- User onboarding and help systems
|
||||
|
||||
## UX Principles
|
||||
|
||||
- **Consistency** - Follow established patterns and conventions
|
||||
- **Clarity** - Make interfaces intuitive and self-explanatory
|
||||
- **Efficiency** - Optimize for user productivity and speed
|
||||
- **Accessibility** - Ensure inclusive design for all users
|
||||
- **Flexibility** - Support different workflows and preferences
|
||||
|
||||
## Design Resources
|
||||
|
||||
- Component library and style guide
|
||||
- Design tokens and theme variables
|
||||
- Icon library and usage guidelines
|
||||
- Layout templates and grid systems
|
||||
- Accessibility testing tools
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
77
docs/developer_portal/viz-plugins/controls.md
Normal file
77
docs/developer_portal/viz-plugins/controls.md
Normal file
@@ -0,0 +1,77 @@
|
||||
---
|
||||
title: Controls and Configuration
|
||||
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.
|
||||
-->
|
||||
|
||||
# Controls and Configuration
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Learn how to create intuitive control panels and configuration interfaces for your visualization plugins.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Control panel architecture and layout
|
||||
- Built-in control types and components
|
||||
- Creating custom control components
|
||||
- Control validation and error handling
|
||||
- Conditional control visibility
|
||||
- Control grouping and sections
|
||||
- Advanced control patterns
|
||||
- Form state management
|
||||
- Control panel theming
|
||||
- Accessibility in control design
|
||||
|
||||
## Available Control Types
|
||||
|
||||
### Basic Controls
|
||||
- **Text Input** - String values and labels
|
||||
- **Number Input** - Numeric values with validation
|
||||
- **Checkbox** - Boolean toggles
|
||||
- **Radio Buttons** - Single selection from options
|
||||
- **Select Dropdown** - Single or multi-select
|
||||
- **Slider** - Numeric range selection
|
||||
|
||||
### Advanced Controls
|
||||
- **Color Picker** - Color selection with palette
|
||||
- **Date Picker** - Date and time selection
|
||||
- **Code Editor** - SQL, JSON, or custom syntax
|
||||
- **File Upload** - Asset and data file handling
|
||||
- **Metrics Selector** - Data column selection
|
||||
- **Filter Controls** - Dynamic filtering options
|
||||
|
||||
### Custom Controls
|
||||
- Building reusable control components
|
||||
- Control component API and props
|
||||
- Integration with form validation
|
||||
- Custom control styling and theming
|
||||
|
||||
## Control Configuration Patterns
|
||||
|
||||
- Section organization and collapsible groups
|
||||
- Conditional control display logic
|
||||
- Dynamic control generation
|
||||
- Control dependencies and relationships
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
80
docs/developer_portal/viz-plugins/creating-viz-plugin.md
Normal file
80
docs/developer_portal/viz-plugins/creating-viz-plugin.md
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
title: Creating a Visualization Plugin
|
||||
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.
|
||||
-->
|
||||
|
||||
# Creating a Visualization Plugin
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Step-by-step guide to building your first custom visualization plugin for Apache Superset.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Setting up the plugin development environment
|
||||
- Using the visualization plugin generator
|
||||
- Understanding the plugin file structure
|
||||
- Implementing the chart component
|
||||
- Creating the control panel interface
|
||||
- Adding data transformation logic
|
||||
- Testing your visualization locally
|
||||
- Debugging common issues
|
||||
- Packaging for distribution
|
||||
- Publishing to npm registry
|
||||
|
||||
## Development Steps
|
||||
|
||||
### 1. Project Setup
|
||||
- Clone the superset-ui repository
|
||||
- Install dependencies and development tools
|
||||
- Create a new plugin directory
|
||||
- Configure build and development scripts
|
||||
|
||||
### 2. Chart Implementation
|
||||
- Define the main chart component
|
||||
- Handle data props and rendering
|
||||
- Implement responsive design
|
||||
- Add interactive features
|
||||
|
||||
### 3. Configuration Interface
|
||||
- Design the control panel layout
|
||||
- Add form controls and validation
|
||||
- Implement conditional controls
|
||||
- Handle control state management
|
||||
|
||||
### 4. Testing and Validation
|
||||
- Unit testing with Jest
|
||||
- Integration testing with Storybook
|
||||
- Visual regression testing
|
||||
- Performance benchmarking
|
||||
|
||||
## Code Examples
|
||||
|
||||
Examples will include:
|
||||
- Basic chart component structure
|
||||
- Control panel configuration
|
||||
- Data transformation functions
|
||||
- Event handling patterns
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
67
docs/developer_portal/viz-plugins/overview.md
Normal file
67
docs/developer_portal/viz-plugins/overview.md
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
title: Visualization Plugins Overview
|
||||
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.
|
||||
-->
|
||||
|
||||
# Visualization Plugins Overview
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Learn how to create custom visualization plugins to extend Superset's charting capabilities with new chart types and data representations.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Visualization plugin architecture
|
||||
- Chart component development
|
||||
- Data transformation and processing
|
||||
- Control panel configuration
|
||||
- Chart rendering lifecycle
|
||||
- Interactive features and event handling
|
||||
- Performance optimization for large datasets
|
||||
- Chart theming and customization
|
||||
- Export and sharing capabilities
|
||||
- Plugin packaging and distribution
|
||||
|
||||
## Plugin Components
|
||||
|
||||
### Core Components
|
||||
- **Chart Component** - Main visualization renderer
|
||||
- **Control Panel** - Configuration interface
|
||||
- **Transform Props** - Data processing logic
|
||||
- **Metadata** - Plugin registration and configuration
|
||||
|
||||
### Optional Components
|
||||
- **Thumbnail** - Chart preview image
|
||||
- **Build Query** - Custom query generation
|
||||
- **Control Panel Sections** - Advanced configuration grouping
|
||||
|
||||
## Supported Chart Libraries
|
||||
|
||||
- **D3.js** - Custom SVG-based visualizations
|
||||
- **ECharts** - Rich interactive charts
|
||||
- **Deck.gl** - Geospatial and 3D visualizations
|
||||
- **React** - Custom React-based components
|
||||
- **Canvas/WebGL** - High-performance rendering
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
76
docs/developer_portal/viz-plugins/transforming-data.md
Normal file
76
docs/developer_portal/viz-plugins/transforming-data.md
Normal file
@@ -0,0 +1,76 @@
|
||||
---
|
||||
title: Transforming Data
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
# Transforming Data
|
||||
|
||||
🚧 **Coming Soon** 🚧
|
||||
|
||||
Master data transformation techniques to prepare and optimize data for your visualization plugins.
|
||||
|
||||
## Topics to be covered:
|
||||
|
||||
- Data transformation pipeline architecture
|
||||
- Understanding query results structure
|
||||
- Implementing transform props functions
|
||||
- Data aggregation and grouping
|
||||
- Filtering and sorting operations
|
||||
- Data type conversion and validation
|
||||
- Handling missing and null values
|
||||
- Performance optimization for large datasets
|
||||
- Caching and memoization strategies
|
||||
- Error handling in data transformations
|
||||
|
||||
## Transformation Patterns
|
||||
|
||||
### Data Preparation
|
||||
- **Normalization** - Converting data to consistent formats
|
||||
- **Aggregation** - Grouping and summarizing data
|
||||
- **Pivoting** - Reshaping data for different chart types
|
||||
- **Joining** - Combining multiple data sources
|
||||
- **Filtering** - Removing irrelevant data points
|
||||
|
||||
### Chart-Specific Transformations
|
||||
- **Time series** - Date parsing and time-based grouping
|
||||
- **Geographic data** - Coordinate conversion and mapping
|
||||
- **Hierarchical data** - Tree and nested structure handling
|
||||
- **Network data** - Node and edge relationship processing
|
||||
- **Statistical data** - Distribution and correlation analysis
|
||||
|
||||
### Performance Considerations
|
||||
- Lazy evaluation and streaming
|
||||
- Incremental data processing
|
||||
- Client-side vs server-side transformations
|
||||
- Memory management for large datasets
|
||||
- Parallel processing techniques
|
||||
|
||||
## API Reference
|
||||
|
||||
- Transform props function signature
|
||||
- Available utility functions
|
||||
- Data structure interfaces
|
||||
- Error handling patterns
|
||||
|
||||
---
|
||||
|
||||
*This documentation is under active development. Check back soon for updates!*
|
||||
@@ -65,22 +65,6 @@ To send alerts and reports to Slack channels, you need to create a new Slack App
|
||||
|
||||
Note: when you configure an alert or a report, the Slack channel list takes channel names without the leading '#' e.g. use `alerts` instead of `#alerts`.
|
||||
|
||||
#### Large Slack Workspaces (10k+ channels)
|
||||
|
||||
For workspaces with many channels, fetching the complete channel list can take several minutes and may encounter Slack API rate limits. Add the following to your `superset_config.py`:
|
||||
|
||||
```python
|
||||
from datetime import timedelta
|
||||
|
||||
# Increase cache timeout to reduce API calls
|
||||
# Default: 1 day (86400 seconds)
|
||||
SLACK_CACHE_TIMEOUT = int(timedelta(days=2).total_seconds())
|
||||
|
||||
# Increase retry count for rate limit errors
|
||||
# Default: 2
|
||||
SLACK_API_RATE_LIMIT_RETRY_COUNT = 5
|
||||
```
|
||||
|
||||
### Kubernetes-specific
|
||||
|
||||
- You must have a `celery beat` pod running. If you're using the chart included in the GitHub repository under [helm/superset](https://github.com/apache/superset/tree/master/helm/superset), you need to put `supersetCeleryBeat.enabled = true` in your values override.
|
||||
|
||||
@@ -49,8 +49,7 @@ are compatible with Superset.
|
||||
| [Apache Pinot](/docs/configuration/databases#apache-pinot) | `pip install pinotdb` | `pinot://BROKER:5436/query?server=http://CONTROLLER:5983/` |
|
||||
| [Apache Solr](/docs/configuration/databases#apache-solr) | `pip install sqlalchemy-solr` | `solr://{username}:{password}@{hostname}:{port}/{server_path}/{collection}` |
|
||||
| [Apache Spark SQL](/docs/configuration/databases#apache-spark-sql) | `pip install pyhive` | `hive://hive@{hostname}:{port}/{database}` |
|
||||
| [Arc - Apache Arrow](/docs/configuration/databases#arc-arrow) | `pip install arc-superset-arrow` | `arc+arrow://{api_key}@{hostname}:{port}/{database}` |
|
||||
| [Arc - JSON](/docs/configuration/databases#arc-json) | `pip install arc-superset-dialect` | `arc+json://{api_key}@{hostname}:{port}/{database}` |
|
||||
| [Arc (Basekick Labs)](/docs/configuration/databases#arc) | `pip install arc-superset-dialect` | `arc://{api_key}@{hostname}:{port}/{database}` |
|
||||
| [Ascend.io](/docs/configuration/databases#ascendio) | `pip install impyla` | `ascend://{username}:{password}@{hostname}:{port}/{database}?auth_mechanism=PLAIN;use_ssl=true` |
|
||||
| [Azure MS SQL](/docs/configuration/databases#sql-server) | `pip install pymssql` | `mssql+pymssql://UserName@presetSQL:TestPassword@presetSQL.database.windows.net:1433/TestSchema` |
|
||||
| [ClickHouse](/docs/configuration/databases#clickhouse) | `pip install clickhouse-connect` | `clickhousedb://{username}:{password}@{hostname}:{port}/{database}` |
|
||||
@@ -1260,31 +1259,17 @@ hive://hive@{hostname}:{port}/{database}
|
||||
|
||||
#### Arc
|
||||
|
||||
There are two ways to connect Superset to Arc:
|
||||
|
||||
**1. Arc with Apache Arrow (Recommended)**
|
||||
|
||||
The recommended connector library for Arc with Apache Arrow support is [arc-superset-arrow](https://pypi.org/project/arc-superset-arrow/).
|
||||
The recommended connector library is [arc-superset-dialect](https://pypi.org/project/arc-superset-dialect/). Install with `pip install arc-superset-dialect`.
|
||||
|
||||
The connection string looks like:
|
||||
|
||||
```
|
||||
arc+arrow://{api_key}@{hostname}:{port}/{database}
|
||||
arc://{api_key}@{hostname}:{port}/{database}
|
||||
```
|
||||
|
||||
**2. Arc with JSON**
|
||||
##### Multi-Database Support
|
||||
|
||||
Alternatively, you can use the JSON connector [arc-superset-dialect](https://pypi.org/project/arc-superset-dialect/).
|
||||
|
||||
The connection string looks like:
|
||||
|
||||
```
|
||||
arc+json://{api_key}@{hostname}:{port}/{database}
|
||||
```
|
||||
|
||||
Arc supports multiple databases (schemas) within a single instance. In Superset, each Arc database appears as a schema in the SQL Lab.
|
||||
|
||||
**Note:** The Arrow dialect (`arc-superset-arrow`) is recommended for production use as it provides 3-5x better performance using Apache Arrow IPC binary format.
|
||||
Arc supports multiple databases (schemas) within a single instance. In Superset, each Arc database appears as a schema in the SQL Lab, and cross-database queries are supported using `database.table` syntax.
|
||||
|
||||
#### SQL Server
|
||||
|
||||
|
||||
@@ -12,13 +12,11 @@ version: 1
|
||||
SQL Lab and Explore supports [Jinja templating](https://jinja.palletsprojects.com/en/2.11.x/) in queries.
|
||||
To enable templating, the `ENABLE_TEMPLATE_PROCESSING` [feature flag](/docs/configuration/configuring-superset#feature-flags) needs to be enabled in `superset_config.py`.
|
||||
|
||||
:::warning[Security Warning]
|
||||
|
||||
While powerful, this feature executes template code on the server. Within the Superset security model, this is **intended functionality**, as users with permissions to edit charts and virtual datasets are considered **trusted users**.
|
||||
|
||||
If you grant these permissions to untrusted users, this feature can be exploited as a **Server-Side Template Injection (SSTI)** vulnerability. Do not enable `ENABLE_TEMPLATE_PROCESSING` unless you fully understand and accept the associated security risks.
|
||||
|
||||
:::
|
||||
> #### ⚠️ Security Warning
|
||||
>
|
||||
> While powerful, this feature executes template code on the server. Within the Superset security model, this is **intended functionality**, as users with permissions to edit charts and virtual datasets are considered **trusted users**.
|
||||
>
|
||||
> If you grant these permissions to untrusted users, this feature can be exploited as a **Server-Side Template Injection (SSTI)** vulnerability. Do not enable `ENABLE_TEMPLATE_PROCESSING` unless you fully understand and accept the associated security risks.
|
||||
|
||||
When templating is enabled, python code can be embedded in virtual datasets and
|
||||
in Custom SQL in the filter and metric controls in Explore. By default, the following variables are
|
||||
@@ -184,7 +182,7 @@ The available validators and names can be found in
|
||||
|
||||
In this section, we'll walkthrough the pre-defined Jinja macros in Superset.
|
||||
|
||||
### Current Username
|
||||
**Current Username**
|
||||
|
||||
The `{{ current_username() }}` macro returns the `username` of the currently logged in user.
|
||||
|
||||
@@ -199,7 +197,7 @@ cache key by adding the following parameter to your Jinja code:
|
||||
{{ current_username(add_to_cache_keys=False) }}
|
||||
```
|
||||
|
||||
### Current User ID
|
||||
**Current User ID**
|
||||
|
||||
The `{{ current_user_id() }}` macro returns the account ID of the currently logged in user.
|
||||
|
||||
@@ -214,7 +212,7 @@ cache key by adding the following parameter to your Jinja code:
|
||||
{{ current_user_id(add_to_cache_keys=False) }}
|
||||
```
|
||||
|
||||
### Current User Email
|
||||
**Current User Email**
|
||||
|
||||
The `{{ current_user_email() }}` macro returns the email address of the currently logged in user.
|
||||
|
||||
@@ -229,7 +227,7 @@ cache key by adding the following parameter to your Jinja code:
|
||||
{{ current_user_email(add_to_cache_keys=False) }}
|
||||
```
|
||||
|
||||
### Current User Roles
|
||||
**Current User Roles**
|
||||
|
||||
The `{{ current_user_roles() }}` macro returns an array of roles for the logged in user.
|
||||
|
||||
@@ -259,7 +257,7 @@ Will be rendered as:
|
||||
SELECT * FROM users WHERE role IN ('admin', 'viewer')
|
||||
```
|
||||
|
||||
### Current User RLS Rules
|
||||
**Current User RLS Rules**
|
||||
|
||||
The `{{ current_user_rls_rules() }}` macro returns an array of RLS rules applied to the current dataset for the logged in user.
|
||||
|
||||
@@ -267,7 +265,7 @@ If you have caching enabled in your Superset configuration, then the list of RLS
|
||||
by Superset when calculating the cache key. A cache key is a unique identifier that determines if there's a
|
||||
cache hit in the future and Superset can retrieve cached data.
|
||||
|
||||
### Custom URL Parameters
|
||||
**Custom URL Parameters**
|
||||
|
||||
The `{{ url_param('custom_variable') }}` macro lets you define arbitrary URL
|
||||
parameters and reference them in your SQL code.
|
||||
@@ -301,7 +299,7 @@ Here's a concrete example:
|
||||
WHERE country_code = 'US'
|
||||
```
|
||||
|
||||
### Explicitly Including Values in Cache Key
|
||||
**Explicitly Including Values in Cache Key**
|
||||
|
||||
The `{{ cache_key_wrapper() }}` function explicitly instructs Superset to add a value to the
|
||||
accumulated list of values used in the calculation of the cache key.
|
||||
@@ -313,7 +311,7 @@ in the cache key. You can gain more context
|
||||
Note that this function powers the caching of the `user_id` and `username` values
|
||||
in the `current_user_id()` and `current_username()` function calls (if you have caching enabled).
|
||||
|
||||
### Filter Values
|
||||
**Filter Values**
|
||||
|
||||
You can retrieve the value for a specific filter as a list using `{{ filter_values() }}`.
|
||||
|
||||
@@ -334,7 +332,7 @@ GROUP BY action
|
||||
|
||||
There `where_in` filter converts the list of values from `filter_values('action_type')` into a string suitable for an `IN` expression.
|
||||
|
||||
### Filters for a Specific Column
|
||||
**Filters for a Specific Column**
|
||||
|
||||
The `{{ get_filters() }}` macro returns the filters applied to a given column. In addition to
|
||||
returning the values (similar to how `filter_values()` does), the `get_filters()` macro
|
||||
@@ -396,7 +394,7 @@ Here's a concrete example:
|
||||
order by lineage, level
|
||||
```
|
||||
|
||||
### Time Filter
|
||||
**Time Filter**
|
||||
|
||||
The `{{ get_time_filter() }}` macro returns the time filter applied to a specific column. This is useful if you want
|
||||
to handle time filters inside the virtual dataset, as by default the time filter is placed on the outer query. This can
|
||||
@@ -471,7 +469,7 @@ WHERE
|
||||
AND dttm < {{ time_filter.to_expr }}
|
||||
```
|
||||
|
||||
### Datasets
|
||||
**Datasets**
|
||||
|
||||
It's possible to query physical and virtual datasets using the `dataset` macro. This is useful if you've defined computed columns and metrics on your datasets, and want to reuse the definition in adhoc SQL Lab queries.
|
||||
|
||||
@@ -495,7 +493,7 @@ Since metrics are aggregations, the resulting SQL expression will be grouped by
|
||||
SELECT * FROM {{ dataset(42, include_metrics=True, columns=["ds", "category"]) }} LIMIT 10
|
||||
```
|
||||
|
||||
### Metrics
|
||||
**Metrics**
|
||||
|
||||
The `{{ metric('metric_key', dataset_id) }}` macro can be used to retrieve the metric SQL syntax from a dataset. This can be useful for different purposes:
|
||||
|
||||
@@ -513,7 +511,7 @@ The parameter can be used in SQL Lab, or when fetching a metric from another dat
|
||||
|
||||
Superset supports [builtin filters from the Jinja2 templating package](https://jinja.palletsprojects.com/en/stable/templates/#builtin-filters). Custom filters have also been implemented:
|
||||
|
||||
### Where In
|
||||
**Where In**
|
||||
Parses a list into a SQL-compatible statement. This is useful with macros that return an array (for example the `filter_values` macro):
|
||||
|
||||
```
|
||||
@@ -530,7 +528,7 @@ Dashboard filter without any value applied
|
||||
{{ filter_values('column')|where_in(default_to_none=True) }} => None
|
||||
```
|
||||
|
||||
### To Datetime
|
||||
**To Datetime**
|
||||
|
||||
Loads a string as a `datetime` object. This is useful when performing date operations. For example:
|
||||
```
|
||||
|
||||
@@ -166,56 +166,6 @@ server:
|
||||
npm run dev-server
|
||||
```
|
||||
|
||||
#### Deploying your visualization plugin
|
||||
|
||||
Once your plugin is complete, you will need to deploy it to your superset instance.
|
||||
|
||||
This step assumes you are running your own Docker image as described [here](https://superset.apache.org/docs/installation/docker-builds/#building-your-own-production-docker-image).
|
||||
Instructions may vary for other kinds of deployments.
|
||||
|
||||
If you have your own Superset Docker image, the first line is most likely:
|
||||
`FROM apache/superset:latest` or something similar. You will need to compile
|
||||
your own `"lean"` image and replace this FROM line with your own image.
|
||||
|
||||
1. Publish your chart plugin to npm: it makes the build process simpler.
|
||||
|
||||
Note: if your chart is not published to npm, then in the docker build below, you will need
|
||||
to edit the default Dockerfile to copy your plugin source code to the appropriate
|
||||
location in the container build environment.
|
||||
|
||||
2. Install your chart in the frontend with `npm i <your_chart_package>`.
|
||||
3. Start with a base superset release.
|
||||
|
||||
```bash
|
||||
git checkout tags/X.0.0
|
||||
```
|
||||
|
||||
4. Install your chart with the instructions you followed during development.
|
||||
5. Navigate to the root of your superset directory.
|
||||
6. Run `docker build -t apache/superset:mychart --target lean .`
|
||||
7. Rebuild your production container using `FROM apache/superset:mychart`.
|
||||
|
||||
This will create a new productized superset container with your new chart compiled in.
|
||||
Then you can recreate your custom production container based on a superset built with your chart.
|
||||
|
||||
##### Troubleshooting
|
||||
|
||||
|
||||
- If you get the following NPM error:
|
||||
|
||||
```
|
||||
npm error `npm ci` can only install packages when your package.json and package-lock.json
|
||||
```
|
||||
|
||||
It's because your local nodejs/npm version is different than the one being used inside docker.
|
||||
|
||||
You can resolve this by running npm install with the same version used by the container build process
|
||||
|
||||
Replace XYZ in the following command with the node tag used in the Dockerfile (search for "node:" in the Dockerfile to find the tag).
|
||||
```bash
|
||||
docker run --rm -v $PWD/superset-frontend:/app node:XYZ /bin/bash -c "cd /app && npm i"
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### Python Testing
|
||||
@@ -681,8 +631,8 @@ with `pre-commit install`
|
||||
```bash
|
||||
cd superset-frontend
|
||||
npm ci
|
||||
# run linting checks
|
||||
npm run lint
|
||||
# run eslint checks
|
||||
npm run eslint -- .
|
||||
# run tsc (typescript) checks
|
||||
npm run type
|
||||
```
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
# pkg_resources Deprecation and Migration Guide
|
||||
|
||||
## Background
|
||||
|
||||
As of setuptools 81.0.0 (scheduled for removal around 2025-11-30), the `pkg_resources` API is deprecated and will be removed. This affects several packages in the Python ecosystem.
|
||||
|
||||
## Current Status
|
||||
|
||||
### Superset Codebase ✅
|
||||
The Superset codebase has already migrated away from `pkg_resources` to the modern `importlib.metadata` API:
|
||||
|
||||
- `superset/db_engine_specs/__init__.py:36` - Uses `from importlib.metadata import entry_points`
|
||||
- All entry point loading uses the modern API
|
||||
|
||||
### Production Dependencies ⚠️
|
||||
Some third-party dependencies may still use `pkg_resources`:
|
||||
|
||||
- **`clients` package** (Preset-specific): Uses `pkg_resources` in `const.py`
|
||||
- Error path: `/usr/local/lib/python3.10/site-packages/clients/const.py:1`
|
||||
|
||||
## Migration Path
|
||||
|
||||
### Short-term Solution (Current)
|
||||
Pin setuptools to version 80.x to prevent breaking changes:
|
||||
|
||||
```python
|
||||
# requirements/base.in
|
||||
setuptools<81
|
||||
```
|
||||
|
||||
This prevents the removal of `pkg_resources` while dependent packages are updated.
|
||||
|
||||
### Long-term Solution
|
||||
Update all dependencies to use `importlib.metadata` instead of `pkg_resources`:
|
||||
|
||||
#### Migration Example
|
||||
**Old (deprecated):**
|
||||
```python
|
||||
import pkg_resources
|
||||
|
||||
version = pkg_resources.get_distribution("package_name").version
|
||||
entry_points = pkg_resources.iter_entry_points("group_name")
|
||||
```
|
||||
|
||||
**New (recommended):**
|
||||
```python
|
||||
from importlib.metadata import version, entry_points
|
||||
|
||||
pkg_version = version("package_name")
|
||||
eps = entry_points(group="group_name")
|
||||
```
|
||||
|
||||
## Action Items
|
||||
|
||||
### For Preset Team
|
||||
1. **Update `clients` package** to use `importlib.metadata` instead of `pkg_resources`
|
||||
2. **Review other internal packages** for `pkg_resources` usage
|
||||
3. **Test with setuptools >= 81.0.0** once all packages are migrated
|
||||
4. **Monitor Datadog logs** for similar deprecation warnings
|
||||
|
||||
### For Superset Maintainers
|
||||
1. ✅ Already using `importlib.metadata`
|
||||
2. Monitor third-party dependencies for updates
|
||||
3. Update setuptools pin once ecosystem is ready
|
||||
|
||||
## Timeline
|
||||
|
||||
- **2025-11-30**: Expected removal of `pkg_resources` from setuptools
|
||||
- **Before then**: All dependencies must migrate to `importlib.metadata`
|
||||
|
||||
## References
|
||||
|
||||
- [setuptools pkg_resources deprecation notice](https://setuptools.pypa.io/en/latest/pkg_resources.html)
|
||||
- [importlib.metadata documentation](https://docs.python.org/3/library/importlib.metadata.html)
|
||||
- [Migration guide](https://setuptools.pypa.io/en/latest/deprecated/pkg_resources.html)
|
||||
|
||||
## Monitoring
|
||||
|
||||
Track this issue in production using Datadog:
|
||||
- Warning pattern: `pkg_resources is deprecated as an API`
|
||||
- Component: `@component:app`
|
||||
- Environment: `environment:production`
|
||||
@@ -487,7 +487,7 @@ const config: Config = {
|
||||
'data-project-name': 'Apache Superset',
|
||||
'data-project-color': '#FFFFFF',
|
||||
'data-project-logo':
|
||||
'https://superset.apache.org/img/superset-logo-icon-only.png',
|
||||
'https://images.seeklogo.com/logo-png/50/2/superset-icon-logo-png_seeklogo-500354.png',
|
||||
'data-modal-override-open-id': 'ask-ai-input',
|
||||
'data-modal-override-open-class': 'search-input',
|
||||
'data-modal-disclaimer':
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons": "^6.1.0",
|
||||
"@docusaurus/core": "3.9.2",
|
||||
"@docusaurus/plugin-client-redirects": "3.9.2",
|
||||
"@docusaurus/preset-classic": "3.9.2",
|
||||
"@docusaurus/theme-mermaid": "^3.9.2",
|
||||
"@docusaurus/core": "3.9.1",
|
||||
"@docusaurus/plugin-client-redirects": "3.9.1",
|
||||
"@docusaurus/preset-classic": "3.9.1",
|
||||
"@docusaurus/theme-mermaid": "^3.9.1",
|
||||
"@emotion/core": "^10.0.27",
|
||||
"@emotion/react": "^11.13.3",
|
||||
"@emotion/styled": "^10.0.27",
|
||||
@@ -49,8 +49,8 @@
|
||||
"@storybook/preview-api": "^8.6.11",
|
||||
"@storybook/theming": "^8.6.11",
|
||||
"@superset-ui/core": "^0.20.4",
|
||||
"antd": "^5.29.1",
|
||||
"caniuse-lite": "^1.0.30001756",
|
||||
"antd": "^5.27.4",
|
||||
"caniuse-lite": "^1.0.30001750",
|
||||
"docusaurus-plugin-less": "^2.0.2",
|
||||
"json-bigint": "^1.0.0",
|
||||
"less": "^4.4.2",
|
||||
@@ -63,26 +63,26 @@
|
||||
"remark-import-partial": "^0.0.2",
|
||||
"reselect": "^5.1.1",
|
||||
"storybook": "^8.6.11",
|
||||
"swagger-ui-react": "^5.30.2",
|
||||
"swagger-ui-react": "^5.29.4",
|
||||
"tinycolor2": "^1.4.2",
|
||||
"ts-loader": "^9.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "^3.9.1",
|
||||
"@docusaurus/tsconfig": "^3.9.2",
|
||||
"@eslint/js": "^9.39.1",
|
||||
"@docusaurus/tsconfig": "^3.9.1",
|
||||
"@eslint/js": "^9.37.0",
|
||||
"@types/react": "^19.1.8",
|
||||
"@typescript-eslint/eslint-plugin": "^8.37.0",
|
||||
"@typescript-eslint/parser": "^8.46.4",
|
||||
"eslint": "^9.39.1",
|
||||
"@typescript-eslint/parser": "^8.46.0",
|
||||
"eslint": "^9.37.0",
|
||||
"eslint-config-prettier": "^10.1.8",
|
||||
"eslint-plugin-prettier": "^5.5.3",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"globals": "^16.5.0",
|
||||
"globals": "^16.4.0",
|
||||
"prettier": "^3.6.2",
|
||||
"typescript": "~5.9.3",
|
||||
"typescript-eslint": "^8.47.0",
|
||||
"webpack": "^5.103.0"
|
||||
"typescript-eslint": "^8.46.1",
|
||||
"webpack": "^5.102.1"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
||||
@@ -30,7 +30,47 @@ const sidebars = {
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Contributing',
|
||||
label: 'Extensions',
|
||||
collapsed: true,
|
||||
items: [
|
||||
'extensions/overview',
|
||||
'extensions/architectural-principles',
|
||||
'extensions/high-level-architecture',
|
||||
'extensions/extension-project-structure',
|
||||
'extensions/extension-metadata',
|
||||
'extensions/frontend-contribution-types',
|
||||
'extensions/interacting-with-host',
|
||||
'extensions/dynamic-module-loading',
|
||||
'extensions/deploying-extension',
|
||||
'extensions/lifecycle-management',
|
||||
'extensions/development-mode',
|
||||
'extensions/versioning',
|
||||
'extensions/security-implications',
|
||||
{
|
||||
type: 'doc',
|
||||
id: 'extensions/built-in-features',
|
||||
customProps: {
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
'extensions/proof-of-concept',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Testing',
|
||||
collapsed: true,
|
||||
items: [
|
||||
'testing/overview',
|
||||
'testing/frontend-testing',
|
||||
'testing/backend-testing',
|
||||
'testing/e2e-testing',
|
||||
'testing/ci-cd',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Contributing to Superset',
|
||||
collapsed: true,
|
||||
items: [
|
||||
'contributing/overview',
|
||||
@@ -72,35 +112,6 @@ const sidebars = {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Extensions',
|
||||
collapsed: true,
|
||||
items: [
|
||||
'extensions/overview',
|
||||
'extensions/quick-start',
|
||||
'extensions/architecture',
|
||||
'extensions/extension-project-structure',
|
||||
'extensions/extension-metadata',
|
||||
'extensions/frontend-contribution-types',
|
||||
'extensions/interacting-with-host',
|
||||
'extensions/deploying-extension',
|
||||
'extensions/development-mode',
|
||||
'extensions/security-implications',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Testing',
|
||||
collapsed: true,
|
||||
items: [
|
||||
'testing/overview',
|
||||
'testing/frontend-testing',
|
||||
'testing/backend-testing',
|
||||
'testing/e2e-testing',
|
||||
'testing/ci-cd',
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
BIN
docs/static/img/superset-logo-icon-only.png
vendored
BIN
docs/static/img/superset-logo-icon-only.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 116 KiB |
@@ -595,8 +595,8 @@ with `pre-commit install`
|
||||
```bash
|
||||
cd superset-frontend
|
||||
npm ci
|
||||
# run linting checks
|
||||
npm run lint
|
||||
# run eslint checks
|
||||
npm run eslint -- .
|
||||
# run tsc (typescript) checks
|
||||
npm run type
|
||||
```
|
||||
|
||||
1523
docs/yarn.lock
1523
docs/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -48,7 +48,7 @@ dependencies = [
|
||||
"cryptography>=42.0.4, <45.0.0",
|
||||
"deprecation>=2.1.0, <2.2.0",
|
||||
"flask>=2.2.5, <3.0.0",
|
||||
"flask-appbuilder>=5.0.2,<6",
|
||||
"flask-appbuilder>=5.0.0,<6",
|
||||
"flask-caching>=2.1.0, <3",
|
||||
"flask-compress>=1.13, <2.0",
|
||||
"flask-talisman>=1.0.0, <2.0",
|
||||
@@ -60,8 +60,8 @@ dependencies = [
|
||||
"greenlet>=3.0.3, <=3.1.1",
|
||||
"gunicorn>=22.0.0; sys_platform != 'win32'",
|
||||
"hashids>=1.3.1, <2",
|
||||
# holidays>=0.45 required for security fix
|
||||
"holidays>=0.45, <1",
|
||||
# known issue with holidays 0.26.0 and above related to prophet lib #25017
|
||||
"holidays>=0.25, <0.26",
|
||||
"humanize",
|
||||
"isodate",
|
||||
"jsonpath-ng>=1.6.1, <2",
|
||||
@@ -76,7 +76,7 @@ dependencies = [
|
||||
"packaging",
|
||||
# --------------------------
|
||||
# pandas and related (wanting pandas[performance] without numba as it's 100+MB and not needed)
|
||||
"pandas[excel]>=2.1.4, <2.2",
|
||||
"pandas[excel]>=2.0.3, <2.2",
|
||||
"bottleneck", # recommended performance dependency for pandas, see https://pandas.pydata.org/docs/getting_started/install.html#performance-dependencies-recommended
|
||||
# --------------------------
|
||||
"parsedatetime",
|
||||
@@ -94,7 +94,7 @@ dependencies = [
|
||||
"PyJWT>=2.4.0, <3.0",
|
||||
"redis>=4.6.0, <5.0",
|
||||
"selenium>=4.14.0, <5.0",
|
||||
"shillelagh[gsheetsapi]>=1.4.3, <2.0",
|
||||
"shillelagh[gsheetsapi]>=1.2.18, <2.0",
|
||||
"sshtunnel>=0.4.0, <0.5",
|
||||
"simplejson>=3.15.0",
|
||||
"slack_sdk>=3.19.0, <4",
|
||||
@@ -133,17 +133,17 @@ denodo = ["denodo-sqlalchemy~=1.0.6"]
|
||||
dremio = ["sqlalchemy-dremio>=1.2.1, <4"]
|
||||
drill = ["sqlalchemy-drill>=1.1.4, <2"]
|
||||
druid = ["pydruid>=0.6.5,<0.7"]
|
||||
duckdb = ["duckdb>=1.4.2,<2", "duckdb-engine>=0.17.0"]
|
||||
# DuckDB 1.x has type system incompatibilities with duckdb-engine.
|
||||
duckdb = ["duckdb>=0.10.2,<0.11", "duckdb-engine>=0.17.0"]
|
||||
dynamodb = ["pydynamodb>=0.4.2"]
|
||||
solr = ["sqlalchemy-solr >= 0.2.0"]
|
||||
elasticsearch = ["elasticsearch-dbapi>=0.2.9, <0.3.0"]
|
||||
exasol = ["sqlalchemy-exasol >= 2.4.0, <3.0"]
|
||||
excel = ["xlrd>=1.2.0, <1.3"]
|
||||
fastmcp = ["fastmcp>=2.13.0.2"]
|
||||
firebird = ["sqlalchemy-firebird>=0.7.0, <0.8"]
|
||||
firebolt = ["firebolt-sqlalchemy>=1.0.0, <2"]
|
||||
gevent = ["gevent>=23.9.1"]
|
||||
gsheets = ["shillelagh[gsheetsapi]>=1.4.3, <2"]
|
||||
gsheets = ["shillelagh[gsheetsapi]>=1.2.18, <2"]
|
||||
hana = ["hdbcli==2.4.162", "sqlalchemy_hana==0.4.0"]
|
||||
hive = [
|
||||
"pyhive[hive]>=0.6.5;python_version<'3.11'",
|
||||
@@ -171,10 +171,10 @@ playwright = ["playwright>=1.37.0, <2"]
|
||||
postgres = ["psycopg2-binary==2.9.6"]
|
||||
presto = ["pyhive[presto]>=0.6.5"]
|
||||
trino = ["trino>=0.328.0"]
|
||||
prophet = ["prophet>=1.1.6, <2"]
|
||||
prophet = ["prophet>=1.1.5, <2"]
|
||||
redshift = ["sqlalchemy-redshift>=0.8.1, <0.9"]
|
||||
risingwave = ["sqlalchemy-risingwave"]
|
||||
shillelagh = ["shillelagh[all]>=1.4.3, <2"]
|
||||
shillelagh = ["shillelagh[all]>=1.2.18, <2"]
|
||||
singlestore = ["sqlalchemy-singlestoredb>=1.1.1, <2"]
|
||||
snowflake = ["snowflake-sqlalchemy>=1.2.4, <2"]
|
||||
spark = [
|
||||
|
||||
@@ -36,9 +36,3 @@ marshmallow-sqlalchemy>=1.3.0,<1.4.1
|
||||
|
||||
# needed for python 3.12 support
|
||||
openapi-schema-validator>=0.6.3
|
||||
|
||||
# Pin setuptools <81 until all dependencies migrate from pkg_resources to importlib.metadata
|
||||
# pkg_resources is deprecated and will be removed in setuptools 81+ (around 2025-11-30)
|
||||
# Known affected packages: Preset's 'clients' package
|
||||
# See docs/docs/contributing/pkg-resources-migration.md for details
|
||||
setuptools<81
|
||||
|
||||
@@ -42,7 +42,7 @@ cachelib==0.13.0
|
||||
# via
|
||||
# flask-caching
|
||||
# flask-session
|
||||
cachetools==6.2.1
|
||||
cachetools==5.5.2
|
||||
# via google-auth
|
||||
cattrs==25.1.1
|
||||
# via requests-cache
|
||||
@@ -116,7 +116,7 @@ flask==2.3.3
|
||||
# flask-session
|
||||
# flask-sqlalchemy
|
||||
# flask-wtf
|
||||
flask-appbuilder==5.0.2
|
||||
flask-appbuilder==5.0.0
|
||||
# via
|
||||
# apache-superset (pyproject.toml)
|
||||
# apache-superset-core
|
||||
@@ -154,7 +154,7 @@ geographiclib==2.0
|
||||
# via geopy
|
||||
geopy==2.4.1
|
||||
# via apache-superset (pyproject.toml)
|
||||
google-auth==2.43.0
|
||||
google-auth==2.40.3
|
||||
# via shillelagh
|
||||
greenlet==3.1.1
|
||||
# via
|
||||
@@ -167,7 +167,7 @@ h11==0.16.0
|
||||
# via wsproto
|
||||
hashids==1.3.1
|
||||
# via apache-superset (pyproject.toml)
|
||||
holidays==0.82
|
||||
holidays==0.25
|
||||
# via apache-superset (pyproject.toml)
|
||||
humanize==4.12.3
|
||||
# via apache-superset (pyproject.toml)
|
||||
@@ -199,6 +199,8 @@ jsonschema-specifications==2025.4.1
|
||||
# openapi-schema-validator
|
||||
kombu==5.5.3
|
||||
# via celery
|
||||
korean-lunar-calendar==0.3.1
|
||||
# via holidays
|
||||
limits==5.1.0
|
||||
# via flask-limiter
|
||||
mako==1.3.10
|
||||
@@ -364,9 +366,7 @@ rsa==4.9.1
|
||||
# via google-auth
|
||||
selenium==4.32.0
|
||||
# via apache-superset (pyproject.toml)
|
||||
setuptools==80.9.0
|
||||
# via -r requirements/base.in
|
||||
shillelagh==1.4.3
|
||||
shillelagh==1.3.5
|
||||
# via apache-superset (pyproject.toml)
|
||||
simplejson==3.20.1
|
||||
# via apache-superset (pyproject.toml)
|
||||
@@ -386,7 +386,6 @@ sqlalchemy==1.4.54
|
||||
# via
|
||||
# apache-superset (pyproject.toml)
|
||||
# alembic
|
||||
# apache-superset-core
|
||||
# flask-appbuilder
|
||||
# flask-sqlalchemy
|
||||
# marshmallow-sqlalchemy
|
||||
@@ -395,12 +394,9 @@ sqlalchemy==1.4.54
|
||||
sqlalchemy-utils==0.38.3
|
||||
# via
|
||||
# apache-superset (pyproject.toml)
|
||||
# apache-superset-core
|
||||
# flask-appbuilder
|
||||
sqlglot==27.15.2
|
||||
# via
|
||||
# apache-superset (pyproject.toml)
|
||||
# apache-superset-core
|
||||
# via apache-superset (pyproject.toml)
|
||||
sshtunnel==0.4.0
|
||||
# via apache-superset (pyproject.toml)
|
||||
tabulate==0.9.0
|
||||
@@ -411,11 +407,10 @@ trio==0.30.0
|
||||
# trio-websocket
|
||||
trio-websocket==0.12.2
|
||||
# via selenium
|
||||
typing-extensions==4.15.0
|
||||
typing-extensions==4.14.0
|
||||
# via
|
||||
# apache-superset (pyproject.toml)
|
||||
# alembic
|
||||
# apache-superset-core
|
||||
# cattrs
|
||||
# limits
|
||||
# pydantic
|
||||
|
||||
@@ -16,5 +16,5 @@
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
-e .[development,bigquery,druid,duckdb,fastmcp,gevent,gsheets,mysql,postgres,presto,prophet,trino,thumbnails]
|
||||
-e .[development,bigquery,druid,duckdb,gevent,gsheets,mysql,postgres,presto,prophet,trino,thumbnails]
|
||||
-e ./superset-extensions-cli[test]
|
||||
|
||||
@@ -22,12 +22,6 @@ annotated-types==0.7.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# pydantic
|
||||
anyio==4.11.0
|
||||
# via
|
||||
# httpx
|
||||
# mcp
|
||||
# sse-starlette
|
||||
# starlette
|
||||
apispec==6.6.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -42,14 +36,11 @@ attrs==25.3.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# cattrs
|
||||
# cyclopts
|
||||
# jsonschema
|
||||
# outcome
|
||||
# referencing
|
||||
# requests-cache
|
||||
# trio
|
||||
authlib==1.6.5
|
||||
# via fastmcp
|
||||
babel==2.17.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -58,16 +49,10 @@ backoff==2.2.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
backports-tarfile==1.2.0
|
||||
# via jaraco-context
|
||||
bcrypt==4.3.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# paramiko
|
||||
beartype==0.22.5
|
||||
# via
|
||||
# py-key-value-aio
|
||||
# py-key-value-shared
|
||||
billiard==4.2.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -89,11 +74,10 @@ cachelib==0.13.0
|
||||
# -c requirements/base-constraint.txt
|
||||
# flask-caching
|
||||
# flask-session
|
||||
cachetools==6.2.1
|
||||
cachetools==5.5.2
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# google-auth
|
||||
# py-key-value-aio
|
||||
cattrs==25.1.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -105,8 +89,6 @@ celery==5.5.2
|
||||
certifi==2025.6.15
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# httpcore
|
||||
# httpx
|
||||
# requests
|
||||
# selenium
|
||||
cffi==1.17.1
|
||||
@@ -132,7 +114,6 @@ click==8.2.1
|
||||
# click-repl
|
||||
# flask
|
||||
# flask-appbuilder
|
||||
# uvicorn
|
||||
click-didyoumean==0.3.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -172,15 +153,10 @@ cryptography==44.0.3
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
# authlib
|
||||
# paramiko
|
||||
# pyjwt
|
||||
# pyopenssl
|
||||
# secretstorage
|
||||
cycler==0.12.1
|
||||
# via matplotlib
|
||||
cyclopts==4.2.4
|
||||
# via fastmcp
|
||||
db-dtypes==1.3.1
|
||||
# via pandas-gbq
|
||||
defusedxml==0.7.1
|
||||
@@ -197,8 +173,6 @@ deprecation==2.1.0
|
||||
# apache-superset
|
||||
dill==0.4.0
|
||||
# via pylint
|
||||
diskcache==5.6.3
|
||||
# via py-key-value-aio
|
||||
distlib==0.3.8
|
||||
# via virtualenv
|
||||
dnspython==2.7.0
|
||||
@@ -207,11 +181,7 @@ dnspython==2.7.0
|
||||
# email-validator
|
||||
docker==7.0.0
|
||||
# via apache-superset
|
||||
docstring-parser==0.17.0
|
||||
# via cyclopts
|
||||
docutils==0.22.2
|
||||
# via rich-rst
|
||||
duckdb==1.4.2
|
||||
duckdb==0.10.3
|
||||
# via
|
||||
# apache-superset
|
||||
# duckdb-engine
|
||||
@@ -221,15 +191,10 @@ email-validator==2.2.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# flask-appbuilder
|
||||
# pydantic
|
||||
et-xmlfile==2.0.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# openpyxl
|
||||
exceptiongroup==1.3.0
|
||||
# via fastmcp
|
||||
fastmcp==2.13.1
|
||||
# via apache-superset
|
||||
filelock==3.12.2
|
||||
# via virtualenv
|
||||
flask==2.3.3
|
||||
@@ -249,7 +214,7 @@ flask==2.3.3
|
||||
# flask-sqlalchemy
|
||||
# flask-testing
|
||||
# flask-wtf
|
||||
flask-appbuilder==5.0.2
|
||||
flask-appbuilder==5.0.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
@@ -330,7 +295,7 @@ google-api-core==2.23.0
|
||||
# google-cloud-core
|
||||
# pandas-gbq
|
||||
# sqlalchemy-bigquery
|
||||
google-auth==2.43.0
|
||||
google-auth==2.40.3
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# google-api-core
|
||||
@@ -383,26 +348,16 @@ gunicorn==23.0.0
|
||||
h11==0.16.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# httpcore
|
||||
# uvicorn
|
||||
# wsproto
|
||||
hashids==1.3.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
holidays==0.82
|
||||
holidays==0.25
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
# prophet
|
||||
httpcore==1.0.9
|
||||
# via httpx
|
||||
httpx==0.28.1
|
||||
# via
|
||||
# fastmcp
|
||||
# mcp
|
||||
httpx-sse==0.4.1
|
||||
# via mcp
|
||||
humanize==4.12.3
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -412,14 +367,10 @@ identify==2.5.36
|
||||
idna==3.10
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# anyio
|
||||
# email-validator
|
||||
# httpx
|
||||
# requests
|
||||
# trio
|
||||
# url-normalize
|
||||
importlib-metadata==8.7.0
|
||||
# via keyring
|
||||
importlib-resources==6.5.2
|
||||
# via prophet
|
||||
iniconfig==2.0.0
|
||||
@@ -435,16 +386,6 @@ itsdangerous==2.2.0
|
||||
# -c requirements/base-constraint.txt
|
||||
# flask
|
||||
# flask-wtf
|
||||
jaraco-classes==3.4.0
|
||||
# via keyring
|
||||
jaraco-context==6.0.1
|
||||
# via keyring
|
||||
jaraco-functools==4.3.0
|
||||
# via keyring
|
||||
jeepney==0.9.0
|
||||
# via
|
||||
# keyring
|
||||
# secretstorage
|
||||
jinja2==3.1.6
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -459,26 +400,25 @@ jsonschema==4.23.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# flask-appbuilder
|
||||
# mcp
|
||||
# openapi-schema-validator
|
||||
# openapi-spec-validator
|
||||
jsonschema-path==0.3.4
|
||||
# via
|
||||
# fastmcp
|
||||
# openapi-spec-validator
|
||||
# via openapi-spec-validator
|
||||
jsonschema-specifications==2025.4.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# jsonschema
|
||||
# openapi-schema-validator
|
||||
keyring==25.6.0
|
||||
# via py-key-value-aio
|
||||
kiwisolver==1.4.7
|
||||
# via matplotlib
|
||||
kombu==5.5.3
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# celery
|
||||
korean-lunar-calendar==0.3.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# holidays
|
||||
lazy-object-proxy==1.10.0
|
||||
# via openapi-spec-validator
|
||||
limits==5.1.0
|
||||
@@ -524,16 +464,10 @@ matplotlib==3.9.0
|
||||
# via prophet
|
||||
mccabe==0.7.0
|
||||
# via pylint
|
||||
mcp==1.20.0
|
||||
# via fastmcp
|
||||
mdurl==0.1.2
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# markdown-it-py
|
||||
more-itertools==10.8.0
|
||||
# via
|
||||
# jaraco-classes
|
||||
# jaraco-functools
|
||||
msgpack==1.0.8
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -569,8 +503,6 @@ odfpy==1.4.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# pandas
|
||||
openapi-pydantic==0.5.1
|
||||
# via fastmcp
|
||||
openapi-schema-validator==0.6.3
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -630,8 +562,6 @@ parsedatetime==2.6
|
||||
# apache-superset
|
||||
pathable==0.4.3
|
||||
# via jsonschema-path
|
||||
pathvalidate==3.3.1
|
||||
# via py-key-value-aio
|
||||
pgsanity==0.2.9
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -646,7 +576,6 @@ pip==25.1.1
|
||||
platformdirs==4.3.8
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# fastmcp
|
||||
# pylint
|
||||
# requests-cache
|
||||
# virtualenv
|
||||
@@ -672,7 +601,7 @@ prompt-toolkit==3.0.51
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# click-repl
|
||||
prophet==1.2.0
|
||||
prophet==1.1.5
|
||||
# via apache-superset
|
||||
proto-plus==1.25.0
|
||||
# via
|
||||
@@ -689,10 +618,6 @@ psutil==6.1.0
|
||||
# via apache-superset
|
||||
psycopg2-binary==2.9.6
|
||||
# via apache-superset
|
||||
py-key-value-aio==0.2.8
|
||||
# via fastmcp
|
||||
py-key-value-shared==0.2.8
|
||||
# via py-key-value-aio
|
||||
pyarrow==16.1.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -718,16 +643,10 @@ pydantic==2.11.7
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
# fastmcp
|
||||
# mcp
|
||||
# openapi-pydantic
|
||||
# pydantic-settings
|
||||
pydantic-core==2.33.2
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# pydantic
|
||||
pydantic-settings==2.10.1
|
||||
# via mcp
|
||||
pydata-google-auth==1.9.0
|
||||
# via pandas-gbq
|
||||
pydruid==0.6.9
|
||||
@@ -748,7 +667,6 @@ pyjwt==2.10.1
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
# flask-jwt-extended
|
||||
# mcp
|
||||
pylint==3.3.7
|
||||
# via apache-superset
|
||||
pynacl==1.5.0
|
||||
@@ -764,8 +682,6 @@ pyparsing==3.2.3
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
# matplotlib
|
||||
pyperclip==1.10.0
|
||||
# via fastmcp
|
||||
pysocks==1.7.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -803,16 +719,12 @@ python-dotenv==1.1.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
# fastmcp
|
||||
# pydantic-settings
|
||||
python-geohash==0.8.5
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
python-ldap==3.4.4
|
||||
# via apache-superset
|
||||
python-multipart==0.0.20
|
||||
# via mcp
|
||||
pytz==2025.2
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -867,12 +779,7 @@ rfc3339-validator==0.1.4
|
||||
rich==13.9.4
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# cyclopts
|
||||
# fastmcp
|
||||
# flask-limiter
|
||||
# rich-rst
|
||||
rich-rst==1.3.1
|
||||
# via cyclopts
|
||||
rpds-py==0.25.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -884,23 +791,20 @@ rsa==4.9.1
|
||||
# google-auth
|
||||
ruff==0.8.0
|
||||
# via apache-superset
|
||||
secretstorage==3.4.1
|
||||
# via keyring
|
||||
selenium==4.32.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
semver==3.0.4
|
||||
# via apache-superset-extensions-cli
|
||||
setuptools==80.9.0
|
||||
setuptools==80.7.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# nodeenv
|
||||
# pandas-gbq
|
||||
# pydata-google-auth
|
||||
# zope-event
|
||||
# zope-interface
|
||||
shillelagh==1.4.3
|
||||
shillelagh==1.3.5
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
@@ -922,7 +826,6 @@ slack-sdk==3.35.0
|
||||
sniffio==1.3.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# anyio
|
||||
# trio
|
||||
sortedcontainers==2.4.0
|
||||
# via
|
||||
@@ -933,7 +836,6 @@ sqlalchemy==1.4.54
|
||||
# -c requirements/base-constraint.txt
|
||||
# alembic
|
||||
# apache-superset
|
||||
# apache-superset-core
|
||||
# duckdb-engine
|
||||
# flask-appbuilder
|
||||
# flask-sqlalchemy
|
||||
@@ -947,23 +849,17 @@ sqlalchemy-utils==0.38.3
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
# apache-superset-core
|
||||
# flask-appbuilder
|
||||
sqlglot==27.15.2
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
# apache-superset-core
|
||||
sqloxide==0.1.51
|
||||
# via apache-superset
|
||||
sse-starlette==3.0.2
|
||||
# via mcp
|
||||
sshtunnel==0.4.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
starlette==0.48.0
|
||||
# via mcp
|
||||
statsd==4.0.1
|
||||
# via apache-superset
|
||||
tabulate==0.9.0
|
||||
@@ -987,30 +883,24 @@ trio-websocket==0.12.2
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# selenium
|
||||
typing-extensions==4.15.0
|
||||
typing-extensions==4.14.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# alembic
|
||||
# anyio
|
||||
# apache-superset
|
||||
# apache-superset-core
|
||||
# cattrs
|
||||
# exceptiongroup
|
||||
# limits
|
||||
# py-key-value-shared
|
||||
# pydantic
|
||||
# pydantic-core
|
||||
# pyopenssl
|
||||
# referencing
|
||||
# selenium
|
||||
# shillelagh
|
||||
# starlette
|
||||
# typing-inspection
|
||||
typing-inspection==0.4.1
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# pydantic
|
||||
# pydantic-settings
|
||||
tzdata==2025.2
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -1029,10 +919,6 @@ urllib3==2.5.0
|
||||
# requests
|
||||
# requests-cache
|
||||
# selenium
|
||||
uvicorn==0.37.0
|
||||
# via
|
||||
# fastmcp
|
||||
# mcp
|
||||
vine==5.1.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -1054,8 +940,6 @@ websocket-client==1.8.0
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# selenium
|
||||
websockets==15.0.1
|
||||
# via fastmcp
|
||||
werkzeug==3.1.3
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
@@ -1091,8 +975,6 @@ xlsxwriter==3.0.9
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
# pandas
|
||||
zipp==3.23.0
|
||||
# via importlib-metadata
|
||||
zope-event==5.0
|
||||
# via gevent
|
||||
zope-interface==5.4.0
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# 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.
|
||||
|
||||
set -e
|
||||
|
||||
script_dir="$(dirname "$(realpath "$0")")"
|
||||
root_dir="$(dirname "$script_dir")"
|
||||
frontend_dir=superset-frontend
|
||||
|
||||
if [[ ! -d "$root_dir/$frontend_dir" ]]; then
|
||||
echo "Error: $frontend_dir directory not found in $root_dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$root_dir/$frontend_dir"
|
||||
|
||||
# Filter files to only include JS/TS files and remove the frontend dir prefix
|
||||
js_ts_files=()
|
||||
for file in "$@"; do
|
||||
# Remove superset-frontend/ prefix if present
|
||||
cleaned_file="${file#$frontend_dir/}"
|
||||
|
||||
# Only include JS/TS files
|
||||
if [[ "$cleaned_file" =~ \.(js|jsx|ts|tsx)$ ]]; then
|
||||
js_ts_files+=("$cleaned_file")
|
||||
fi
|
||||
done
|
||||
|
||||
# Only run if we have JS/TS files to check
|
||||
if [ ${#js_ts_files[@]} -gt 0 ]; then
|
||||
node scripts/check-custom-rules.js "${js_ts_files[@]}"
|
||||
else
|
||||
echo "No JavaScript/TypeScript files to check for custom rules"
|
||||
fi
|
||||
@@ -27,4 +27,4 @@ if [[ ! -d "$root_dir/$frontend_dir" ]]; then
|
||||
fi
|
||||
|
||||
cd "$root_dir/$frontend_dir"
|
||||
npm run lint-fix -- "${@//$frontend_dir\//}"
|
||||
npm run eslint -- "${@//$frontend_dir\//}" --fix
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# 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.
|
||||
|
||||
set -e
|
||||
|
||||
script_dir="$(dirname "$(realpath "$0")")"
|
||||
root_dir="$(dirname "$script_dir")"
|
||||
frontend_dir=superset-frontend
|
||||
|
||||
if [[ ! -d "$root_dir/$frontend_dir" ]]; then
|
||||
echo "Error: $frontend_dir directory not found in $root_dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd "$root_dir/$frontend_dir"
|
||||
|
||||
# Filter files to only include JS/TS files and remove the frontend dir prefix
|
||||
js_ts_files=()
|
||||
for file in "$@"; do
|
||||
# Remove superset-frontend/ prefix if present
|
||||
cleaned_file="${file#$frontend_dir/}"
|
||||
|
||||
# Only include JS/TS files
|
||||
if [[ "$cleaned_file" =~ \.(js|jsx|ts|tsx)$ ]]; then
|
||||
js_ts_files+=("$cleaned_file")
|
||||
fi
|
||||
done
|
||||
|
||||
# Only run if we have JS/TS files to lint
|
||||
if [ ${#js_ts_files[@]} -gt 0 ]; then
|
||||
# Skip custom OXC build in pre-commit for speed
|
||||
export SKIP_CUSTOM_OXC=true
|
||||
# Use quiet mode in pre-commit to reduce noise (only show errors)
|
||||
npx oxlint --config oxlint.json --fix --quiet "${js_ts_files[@]}"
|
||||
else
|
||||
echo "No JavaScript/TypeScript files to lint"
|
||||
fi
|
||||
@@ -19,23 +19,6 @@
|
||||
|
||||
set -e
|
||||
|
||||
# If not already running in Docker, run this script inside Docker
|
||||
if [ -z "$RUNNING_IN_DOCKER" ]; then
|
||||
# Extract "current" Python version from CI config (single source of truth)
|
||||
PYTHON_VERSION=$(grep -A 1 'if.*"current"' .github/actions/setup-backend/action.yml | grep 'PYTHON_VERSION=' | sed 's/.*PYTHON_VERSION=\([0-9.]*\).*/\1/')
|
||||
|
||||
echo "Running in Docker (Python ${PYTHON_VERSION} on Linux)..."
|
||||
|
||||
docker run --rm \
|
||||
-v "$(pwd)":/app \
|
||||
-w /app \
|
||||
-e RUNNING_IN_DOCKER=1 \
|
||||
python:${PYTHON_VERSION}-slim \
|
||||
bash -c "pip install uv && ./scripts/uv-pip-compile.sh $*"
|
||||
|
||||
exit $?
|
||||
fi
|
||||
|
||||
ADDITIONAL_ARGS="$@"
|
||||
|
||||
# Generate the requirements/base.txt file
|
||||
|
||||
7
setup.py
7
setup.py
@@ -30,9 +30,7 @@ with open(PACKAGE_JSON) as package_file:
|
||||
|
||||
def get_git_sha() -> str:
|
||||
try:
|
||||
output = subprocess.check_output(
|
||||
["git", "rev-parse", "HEAD"]
|
||||
) # noqa: S603, S607
|
||||
output = subprocess.check_output(["git", "rev-parse", "HEAD"]) # noqa: S603, S607
|
||||
return output.decode().strip()
|
||||
except Exception: # pylint: disable=broad-except
|
||||
return ""
|
||||
@@ -60,9 +58,6 @@ setup(
|
||||
include_package_data=True,
|
||||
zip_safe=False,
|
||||
entry_points={
|
||||
"superset.semantic_layers": [
|
||||
"snowflake = superset.semantic_layers.snowflake:SnowflakeSemanticLayer"
|
||||
],
|
||||
"console_scripts": ["superset=superset.cli.main:superset"],
|
||||
# the `postgres` and `postgres+psycopg2://` schemes were removed in SQLAlchemy 1.4 # noqa: E501
|
||||
# add an alias here to prevent breaking existing databases
|
||||
|
||||
@@ -49,7 +49,7 @@ The package is organized into logical modules, each providing specific functiona
|
||||
from flask import request, Response
|
||||
from flask_appbuilder.api import expose, permission_name, protect, safe
|
||||
from superset_core.api import models, query, rest_api
|
||||
from superset_core.api.rest_api import RestApi
|
||||
from superset_core.api.types.rest_api import RestApi
|
||||
|
||||
class DatasetReferencesAPI(RestApi):
|
||||
"""Example extension API demonstrating core functionality."""
|
||||
|
||||
@@ -42,11 +42,7 @@ classifiers = [
|
||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||
]
|
||||
dependencies = [
|
||||
"flask-appbuilder>=5.0.2,<6",
|
||||
"sqlalchemy>=1.4.0,<2.0",
|
||||
"sqlalchemy-utils>=0.38.0",
|
||||
"sqlglot>=27.15.2, <28",
|
||||
"typing-extensions>=4.0.0",
|
||||
"flask-appbuilder>=5.0.0,<6",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
|
||||
@@ -14,7 +14,3 @@
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""
|
||||
Apache Superset Core - Public API with core functions of Superset
|
||||
"""
|
||||
|
||||
@@ -14,3 +14,11 @@
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from .types.models import CoreModelsApi
|
||||
from .types.query import CoreQueryApi
|
||||
from .types.rest_api import CoreRestApi
|
||||
|
||||
models: CoreModelsApi
|
||||
rest_api: CoreRestApi
|
||||
query: CoreQueryApi
|
||||
|
||||
@@ -1,262 +0,0 @@
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Data Access Object API for superset-core.
|
||||
|
||||
Provides dependency-injected DAO classes that will be replaced by
|
||||
host implementations during initialization.
|
||||
|
||||
Usage:
|
||||
from superset_core.api.daos import DatasetDAO, DatabaseDAO
|
||||
|
||||
# Use standard BaseDAO methods
|
||||
datasets = DatasetDAO.find_all()
|
||||
dataset = DatasetDAO.find_one_or_none(id=123)
|
||||
DatasetDAO.create(attributes={"name": "New Dataset"})
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, ClassVar, Generic, TypeVar
|
||||
|
||||
from flask_appbuilder.models.filters import BaseFilter
|
||||
from sqlalchemy.orm import Query as SQLAQuery
|
||||
|
||||
from superset_core.api.models import (
|
||||
Chart,
|
||||
CoreModel,
|
||||
Dashboard,
|
||||
Database,
|
||||
Dataset,
|
||||
KeyValue,
|
||||
Query,
|
||||
SavedQuery,
|
||||
Tag,
|
||||
User,
|
||||
)
|
||||
|
||||
# Type variable bound to our CoreModel
|
||||
T = TypeVar("T", bound=CoreModel)
|
||||
|
||||
|
||||
class BaseDAO(Generic[T], ABC):
|
||||
"""
|
||||
Abstract base class for DAOs.
|
||||
|
||||
This ABC defines the base that all DAOs should implement,
|
||||
providing consistent CRUD operations across Superset and extensions.
|
||||
"""
|
||||
|
||||
# Due to mypy limitations, we can't have `type[T]` here
|
||||
model_cls: ClassVar[type[Any] | None]
|
||||
base_filter: ClassVar[BaseFilter | None]
|
||||
id_column_name: ClassVar[str]
|
||||
uuid_column_name: ClassVar[str]
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def find_all(cls) -> list[T]:
|
||||
"""Get all entities that fit the base_filter."""
|
||||
...
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def find_one_or_none(cls, **filter_by: Any) -> T | None:
|
||||
"""Get the first entity that fits the base_filter."""
|
||||
...
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def create(
|
||||
cls,
|
||||
item: T | None = None,
|
||||
attributes: dict[str, Any] | None = None,
|
||||
) -> T:
|
||||
"""Create an object from the specified item and/or attributes."""
|
||||
...
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def update(
|
||||
cls,
|
||||
item: T | None = None,
|
||||
attributes: dict[str, Any] | None = None,
|
||||
) -> T:
|
||||
"""Update an object from the specified item and/or attributes."""
|
||||
...
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def delete(cls, items: list[T]) -> None:
|
||||
"""Delete the specified items."""
|
||||
...
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def query(cls, query: SQLAQuery) -> list[T]:
|
||||
"""Execute query with base_filter applied."""
|
||||
...
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def filter_by(cls, **filter_by: Any) -> list[T]:
|
||||
"""Get all entries that fit the base_filter."""
|
||||
...
|
||||
|
||||
|
||||
class DatasetDAO(BaseDAO[Dataset]):
|
||||
"""
|
||||
Abstract Dataset DAO interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
# Class variables that will be set by host implementation
|
||||
model_cls = None
|
||||
base_filter = None
|
||||
id_column_name = "id"
|
||||
uuid_column_name = "uuid"
|
||||
|
||||
|
||||
class DatabaseDAO(BaseDAO[Database]):
|
||||
"""
|
||||
Abstract Database DAO interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
# Class variables that will be set by host implementation
|
||||
model_cls = None
|
||||
base_filter = None
|
||||
id_column_name = "id"
|
||||
uuid_column_name = "uuid"
|
||||
|
||||
|
||||
class ChartDAO(BaseDAO[Chart]):
|
||||
"""
|
||||
Abstract Chart DAO interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
# Class variables that will be set by host implementation
|
||||
model_cls = None
|
||||
base_filter = None
|
||||
id_column_name = "id"
|
||||
uuid_column_name = "uuid"
|
||||
|
||||
|
||||
class DashboardDAO(BaseDAO[Dashboard]):
|
||||
"""
|
||||
Abstract Dashboard DAO interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
# Class variables that will be set by host implementation
|
||||
model_cls = None
|
||||
base_filter = None
|
||||
id_column_name = "id"
|
||||
uuid_column_name = "uuid"
|
||||
|
||||
|
||||
class UserDAO(BaseDAO[User]):
|
||||
"""
|
||||
Abstract User DAO interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
# Class variables that will be set by host implementation
|
||||
model_cls = None
|
||||
base_filter = None
|
||||
id_column_name = "id"
|
||||
|
||||
|
||||
class QueryDAO(BaseDAO[Query]):
|
||||
"""
|
||||
Abstract Query DAO interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
# Class variables that will be set by host implementation
|
||||
model_cls = None
|
||||
base_filter = None
|
||||
id_column_name = "id"
|
||||
|
||||
|
||||
class SavedQueryDAO(BaseDAO[SavedQuery]):
|
||||
"""
|
||||
Abstract SavedQuery DAO interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
# Class variables that will be set by host implementation
|
||||
model_cls = None
|
||||
base_filter = None
|
||||
id_column_name = "id"
|
||||
|
||||
|
||||
class TagDAO(BaseDAO[Tag]):
|
||||
"""
|
||||
Abstract Tag DAO interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
# Class variables that will be set by host implementation
|
||||
model_cls = None
|
||||
base_filter = None
|
||||
id_column_name = "id"
|
||||
|
||||
|
||||
class KeyValueDAO(BaseDAO[KeyValue]):
|
||||
"""
|
||||
Abstract KeyValue DAO interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
# Class variables that will be set by host implementation
|
||||
model_cls = None
|
||||
base_filter = None
|
||||
id_column_name = "id"
|
||||
|
||||
|
||||
__all__ = [
|
||||
"BaseDAO",
|
||||
"DatasetDAO",
|
||||
"DatabaseDAO",
|
||||
"ChartDAO",
|
||||
"DashboardDAO",
|
||||
"UserDAO",
|
||||
"QueryDAO",
|
||||
"SavedQueryDAO",
|
||||
"TagDAO",
|
||||
"KeyValueDAO",
|
||||
]
|
||||
@@ -1,295 +0,0 @@
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Model API for superset-core.
|
||||
|
||||
Provides model classes that will be replaced by host implementations
|
||||
during initialization for extension developers to use.
|
||||
|
||||
Usage:
|
||||
from superset_core.api.models import Dataset, Database, get_session
|
||||
|
||||
# Use as regular model classes
|
||||
dataset = Dataset(name="My Dataset")
|
||||
db = Database(database_name="My DB")
|
||||
session = get_session()
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
from uuid import UUID
|
||||
|
||||
from flask_appbuilder import Model
|
||||
from sqlalchemy.orm import scoped_session
|
||||
|
||||
|
||||
class CoreModel(Model):
|
||||
"""
|
||||
Abstract base class that extends Flask-AppBuilder's Model.
|
||||
|
||||
This base class provides the interface contract for all Superset models.
|
||||
The host package provides concrete implementations.
|
||||
"""
|
||||
|
||||
__abstract__ = True
|
||||
|
||||
|
||||
class Database(CoreModel):
|
||||
"""
|
||||
Abstract class for Database models.
|
||||
|
||||
This abstract class defines the contract that database models should implement,
|
||||
providing consistent database connectivity and metadata operations.
|
||||
"""
|
||||
|
||||
__abstract__ = True
|
||||
|
||||
id: int
|
||||
verbose_name: str
|
||||
database_name: str | None
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def backend(self) -> str:
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def data(self) -> dict[str, Any]:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class Dataset(CoreModel):
|
||||
"""
|
||||
Abstract class for Dataset models.
|
||||
|
||||
This abstract class defines the contract that dataset models should implement,
|
||||
providing consistent data source operations and metadata.
|
||||
|
||||
It provides the public API for Datasets implemented by the host application.
|
||||
"""
|
||||
|
||||
__abstract__ = True
|
||||
|
||||
# Type hints for expected attributes (no actual field definitions)
|
||||
id: int
|
||||
uuid: UUID | None
|
||||
table_name: str | None
|
||||
main_dttm_col: str | None
|
||||
database_id: int | None
|
||||
schema: str | None
|
||||
catalog: str | None
|
||||
sql: str | None # For virtual datasets
|
||||
description: str | None
|
||||
default_endpoint: str | None
|
||||
is_featured: bool
|
||||
filter_select_enabled: bool
|
||||
offset: int
|
||||
cache_timeout: int
|
||||
params: str
|
||||
perm: str | None
|
||||
schema_perm: str | None
|
||||
catalog_perm: str | None
|
||||
is_managed_externally: bool
|
||||
external_url: str | None
|
||||
fetch_values_predicate: str | None
|
||||
is_sqllab_view: bool
|
||||
template_params: str | None
|
||||
extra: str | None # JSON string
|
||||
normalize_columns: bool
|
||||
always_filter_main_dttm: bool
|
||||
folders: str | None # JSON string
|
||||
|
||||
|
||||
class Chart(CoreModel):
|
||||
"""
|
||||
Abstract Chart/Slice model interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
__abstract__ = True
|
||||
|
||||
# Type hints for expected attributes (no actual field definitions)
|
||||
id: int
|
||||
uuid: UUID | None
|
||||
slice_name: str | None
|
||||
datasource_id: int | None
|
||||
datasource_type: str | None
|
||||
datasource_name: str | None
|
||||
viz_type: str | None
|
||||
params: str | None
|
||||
query_context: str | None
|
||||
description: str | None
|
||||
cache_timeout: int
|
||||
certified_by: str | None
|
||||
certification_details: str | None
|
||||
is_managed_externally: bool
|
||||
external_url: str | None
|
||||
|
||||
|
||||
class Dashboard(CoreModel):
|
||||
"""
|
||||
Abstract Dashboard model interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
__abstract__ = True
|
||||
|
||||
# Type hints for expected attributes (no actual field definitions)
|
||||
id: int
|
||||
uuid: UUID | None
|
||||
dashboard_title: str | None
|
||||
position_json: str | None
|
||||
description: str | None
|
||||
css: str | None
|
||||
json_metadata: str | None
|
||||
slug: str | None
|
||||
published: bool
|
||||
certified_by: str | None
|
||||
certification_details: str | None
|
||||
is_managed_externally: bool
|
||||
external_url: str | None
|
||||
|
||||
|
||||
class User(CoreModel):
|
||||
"""
|
||||
Abstract User model interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
__abstract__ = True
|
||||
|
||||
# Type hints for expected attributes (no actual field definitions)
|
||||
id: int
|
||||
username: str | None
|
||||
email: str | None
|
||||
first_name: str | None
|
||||
last_name: str | None
|
||||
active: bool
|
||||
|
||||
|
||||
class Query(CoreModel):
|
||||
"""
|
||||
Abstract Query model interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
__abstract__ = True
|
||||
|
||||
# Type hints for expected attributes (no actual field definitions)
|
||||
id: int
|
||||
client_id: str | None
|
||||
database_id: int | None
|
||||
sql: str | None
|
||||
status: str | None
|
||||
user_id: int | None
|
||||
progress: int
|
||||
error_message: str | None
|
||||
|
||||
|
||||
class SavedQuery(CoreModel):
|
||||
"""
|
||||
Abstract SavedQuery model interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
__abstract__ = True
|
||||
|
||||
# Type hints for expected attributes (no actual field definitions)
|
||||
id: int
|
||||
uuid: UUID | None
|
||||
label: str | None
|
||||
sql: str | None
|
||||
database_id: int | None
|
||||
description: str | None
|
||||
user_id: int | None
|
||||
|
||||
|
||||
class Tag(CoreModel):
|
||||
"""
|
||||
Abstract Tag model interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
__abstract__ = True
|
||||
|
||||
# Type hints for expected attributes (no actual field definitions)
|
||||
id: int
|
||||
name: str | None
|
||||
type: str | None
|
||||
|
||||
|
||||
class KeyValue(CoreModel):
|
||||
"""
|
||||
Abstract KeyValue model interface.
|
||||
|
||||
Host implementations will replace this class during initialization
|
||||
with concrete implementation providing actual functionality.
|
||||
"""
|
||||
|
||||
__abstract__ = True
|
||||
|
||||
id: int
|
||||
uuid: UUID | None
|
||||
resource: str | None
|
||||
value: str | None # Encoded value
|
||||
expires_on: datetime | None
|
||||
created_by_fk: int | None
|
||||
changed_by_fk: int | None
|
||||
|
||||
|
||||
def get_session() -> scoped_session:
|
||||
"""
|
||||
Retrieve the SQLAlchemy session to directly interface with the
|
||||
Superset models.
|
||||
|
||||
Host implementations will replace this function during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
|
||||
:returns: The SQLAlchemy scoped session instance.
|
||||
"""
|
||||
raise NotImplementedError("Function will be replaced during initialization")
|
||||
|
||||
|
||||
__all__ = [
|
||||
"Dataset",
|
||||
"Database",
|
||||
"Chart",
|
||||
"Dashboard",
|
||||
"User",
|
||||
"Query",
|
||||
"SavedQuery",
|
||||
"Tag",
|
||||
"KeyValue",
|
||||
"CoreModel",
|
||||
"get_session",
|
||||
]
|
||||
@@ -1,51 +0,0 @@
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Query API for superset-core.
|
||||
|
||||
Provides dependency-injected query utility functions that will be replaced by
|
||||
host implementations during initialization.
|
||||
|
||||
Usage:
|
||||
from superset_core.api.query import get_sqlglot_dialect
|
||||
|
||||
dialect = get_sqlglot_dialect(database)
|
||||
"""
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sqlglot import Dialects
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from superset_core.api.models import Database
|
||||
|
||||
|
||||
def get_sqlglot_dialect(database: "Database") -> Dialects:
|
||||
"""
|
||||
Get the SQLGlot dialect for the specified database.
|
||||
|
||||
Host implementations will replace this function during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
|
||||
:param database: The database instance to get the dialect for.
|
||||
:returns: The SQLGlot dialect enum corresponding to the database.
|
||||
"""
|
||||
raise NotImplementedError("Function will be replaced during initialization")
|
||||
|
||||
|
||||
__all__ = ["get_sqlglot_dialect"]
|
||||
@@ -1,72 +0,0 @@
|
||||
# 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.
|
||||
|
||||
"""
|
||||
REST API functions for superset-core.
|
||||
|
||||
Provides dependency-injected REST API utility functions that will be replaced by
|
||||
host implementations during initialization.
|
||||
|
||||
Usage:
|
||||
from superset_core.api.rest_api import add_api, add_extension_api
|
||||
|
||||
add_api(MyCustomAPI)
|
||||
add_extension_api(MyExtensionAPI)
|
||||
"""
|
||||
|
||||
from flask_appbuilder.api import BaseApi
|
||||
|
||||
|
||||
class RestApi(BaseApi):
|
||||
"""
|
||||
Base REST API class for Superset with browser login support.
|
||||
|
||||
This class extends Flask-AppBuilder's BaseApi and enables browser-based
|
||||
authentication by default.
|
||||
"""
|
||||
|
||||
allow_browser_login = True
|
||||
|
||||
|
||||
def add_api(api: type[RestApi]) -> None:
|
||||
"""
|
||||
Add a REST API to the Superset API.
|
||||
|
||||
Host implementations will replace this function during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
|
||||
:param api: A REST API instance.
|
||||
:returns: None.
|
||||
"""
|
||||
raise NotImplementedError("Function will be replaced during initialization")
|
||||
|
||||
|
||||
def add_extension_api(api: type[RestApi]) -> None:
|
||||
"""
|
||||
Add an extension REST API to the Superset API.
|
||||
|
||||
Host implementations will replace this function during initialization
|
||||
with a concrete implementation providing actual functionality.
|
||||
|
||||
:param api: An extension REST API instance. These are placed under
|
||||
the /extensions resource.
|
||||
:returns: None.
|
||||
"""
|
||||
raise NotImplementedError("Function will be replaced during initialization")
|
||||
|
||||
|
||||
__all__ = ["RestApi", "add_api", "add_extension_api"]
|
||||
90
superset-core/src/superset_core/api/types/models.py
Normal file
90
superset-core/src/superset_core/api/types/models.py
Normal file
@@ -0,0 +1,90 @@
|
||||
# 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.
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any, Type
|
||||
|
||||
from flask_sqlalchemy import BaseQuery
|
||||
from sqlalchemy.orm import scoped_session
|
||||
|
||||
|
||||
class CoreModelsApi(ABC):
|
||||
"""
|
||||
Abstract interface for accessing Superset data models.
|
||||
|
||||
This class defines the contract for retrieving SQLAlchemy sessions
|
||||
and model instances for datasets and databases within Superset.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def get_session() -> scoped_session:
|
||||
"""
|
||||
Retrieve the SQLAlchemy session to directly interface with the
|
||||
Superset models.
|
||||
|
||||
:returns: The SQLAlchemy scoped session instance.
|
||||
"""
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def get_dataset_model() -> Type[Any]:
|
||||
"""
|
||||
Retrieve the Dataset (SqlaTable) SQLAlchemy model.
|
||||
|
||||
:returns: The Dataset SQLAlchemy model class.
|
||||
"""
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def get_database_model() -> Type[Any]:
|
||||
"""
|
||||
Retrieve the Database SQLAlchemy model.
|
||||
|
||||
:returns: The Database SQLAlchemy model class.
|
||||
"""
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def get_datasets(query: BaseQuery | None = None, **kwargs: Any) -> list[Any]:
|
||||
"""
|
||||
Retrieve Dataset (SqlaTable) entities.
|
||||
|
||||
:param query: A query with the Dataset model as the primary entity for complex
|
||||
queries.
|
||||
:param kwargs: Optional keyword arguments to filter datasets using SQLAlchemy's
|
||||
`filter_by()`.
|
||||
:returns: SqlaTable entities.
|
||||
"""
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def get_databases(query: BaseQuery | None = None, **kwargs: Any) -> list[Any]:
|
||||
"""
|
||||
Retrieve Database entities.
|
||||
|
||||
:param query: A query with the Database model as the primary entity for complex
|
||||
queries.
|
||||
:param kwargs: Optional keyword arguments to filter databases using SQLAlchemy's
|
||||
`filter_by()`.
|
||||
:returns: Database entities.
|
||||
"""
|
||||
...
|
||||
@@ -15,30 +15,27 @@
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
# superset/mcp_service/__init__.py
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Any
|
||||
|
||||
"""
|
||||
Apache Superset MCP Service
|
||||
from sqlglot import Dialects
|
||||
|
||||
This package provides the Model Context Protocol (MCP) service for Apache Superset,
|
||||
enabling programmatic access to Superset's functionality through a standardized API.
|
||||
|
||||
The MCP service operates as a standalone FastMCP server.
|
||||
class CoreQueryApi(ABC):
|
||||
"""
|
||||
Abstract interface for query-related operations.
|
||||
|
||||
Quick Start:
|
||||
-----------
|
||||
# Run the MCP server
|
||||
superset mcp run --port 5009
|
||||
This class defines the contract for database query operations,
|
||||
including dialect handling and query processing.
|
||||
"""
|
||||
|
||||
# The service will be available at:
|
||||
# http://localhost:5009/mcp/
|
||||
"""
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def get_sqlglot_dialect(database: Any) -> Dialects:
|
||||
"""
|
||||
Get the SQLGlot dialect for the specified database.
|
||||
|
||||
__version__ = "1.0.0"
|
||||
|
||||
# Tools are auto-registered when imported by the MCP service
|
||||
# Do not import them here to avoid test pollution
|
||||
|
||||
__all__ = [
|
||||
"__version__",
|
||||
]
|
||||
:param database: The database instance to get the dialect for.
|
||||
:returns: The SQLGlot dialect enum corresponding to the database.
|
||||
"""
|
||||
...
|
||||
64
superset-core/src/superset_core/api/types/rest_api.py
Normal file
64
superset-core/src/superset_core/api/types/rest_api.py
Normal file
@@ -0,0 +1,64 @@
|
||||
# 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.
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Type
|
||||
|
||||
from flask_appbuilder.api import BaseApi
|
||||
|
||||
|
||||
class RestApi(BaseApi):
|
||||
"""
|
||||
Base REST API class for Superset with browser login support.
|
||||
|
||||
This class extends Flask-AppBuilder's BaseApi and enables browser-based
|
||||
authentication by default.
|
||||
"""
|
||||
|
||||
allow_browser_login = True
|
||||
|
||||
|
||||
class CoreRestApi(ABC):
|
||||
"""
|
||||
Abstract interface for managing REST APIs in Superset.
|
||||
|
||||
This class defines the contract for adding and managing REST APIs,
|
||||
including both core APIs and extension APIs.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def add_api(api: Type[RestApi]) -> None:
|
||||
"""
|
||||
Add a REST API to the Superset API.
|
||||
|
||||
:param api: A REST API instance.
|
||||
:returns: None.
|
||||
"""
|
||||
...
|
||||
|
||||
@staticmethod
|
||||
@abstractmethod
|
||||
def add_extension_api(api: Type[RestApi]) -> None:
|
||||
"""
|
||||
Add an extension REST API to the Superset API.
|
||||
|
||||
:param api: An extension REST API instance. These are placed under
|
||||
the /extensions resource.
|
||||
:returns: None.
|
||||
"""
|
||||
...
|
||||
12
superset-embedded-sdk/package-lock.json
generated
12
superset-embedded-sdk/package-lock.json
generated
@@ -6696,9 +6696,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "3.14.2",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
|
||||
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"argparse": "^1.0.7",
|
||||
@@ -12972,9 +12972,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.14.2",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
|
||||
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user