Compare commits

...

10 Commits

Author SHA1 Message Date
Evan Rusackas
da14ef3f99 style(changesets): format config.json
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-11 09:56:26 -08:00
Evan Rusackas
ee29590063 feat(changesets): configure workspace protocol and private packages
- Convert file: references to workspace:* protocol for monorepo deps
- Add eslint-rules/* to workspaces for workspace:* resolution
- Mark eslint plugins as private to prevent accidental publishing
- Add eslint plugins to changeset ignore list
- Changeset dry-run now works correctly

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-11 00:58:10 -08:00
Evan Rusackas
1ab5265d4e fix(build): resolve production build errors with Bun
- Add missing @types packages to root for Bun hoisting (@types/react-table,
  @types/jquery, @types/urijs)
- Add d3 dependency for legacy-plugin-chart-calendar
- Configure ForkTsCheckerWebpackPlugin to exclude test files from production
  type checking (test files have history@5/react-router@5 type mismatch)
- Add geostyler-cql-parser to ESM fullySpecified:false webpack rule

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-11 00:45:07 -08:00
Evan Rusackas
373f121421 fix(types): add missing @types packages and fix TS2742 errors for Bun
Bun's module resolution uses .bun/ symlinks which TypeScript can't
reference portably in declaration files. This causes TS2742 errors
when building packages.

Fixes:
- Add explicit return types to avoid TS2742 inference issues
- Add missing @types packages to root package.json:
  - @types/lodash, @types/prop-types
  - @types/d3-array, @types/d3-cloud, @types/d3-color
  - @types/d3-hierarchy, @types/d3-interpolate, @types/d3-scale, @types/d3-time
- Fix ScaleLinear type compatibility with newer @types/d3-scale
  (add third 'never' type parameter)

Files updated:
- packages/superset-core/src/ui/testing.tsx
- packages/superset-ui-core/src/spec/index.tsx
- packages/superset-ui-core/src/components/DatePicker/index.tsx
- packages/superset-ui-core/src/components/SafeMarkdown/SafeMarkdown.tsx
- packages/superset-ui-core/src/components/Tabs/Tabs.tsx
- plugins/legacy-preset-chart-deckgl/src/utils.ts
- plugins/legacy-preset-chart-deckgl/src/layers/common.tsx
- plugins/legacy-preset-chart-deckgl/src/layers/Heatmap/Heatmap.tsx

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-11 00:15:01 -08:00
Evan Rusackas
d605e49194 perf(build): remove thread-loader from webpack config
thread-loader was added in Dec 2024 when we used Babel for transpilation.
After migrating to SWC (Nov 2025), it became unnecessary overhead:

- SWC is Rust-native and 20-70x faster than Babel
- thread-loader spawns CPU_COUNT-1 Node.js worker processes
- Each worker has significant memory overhead
- The parallelization benefit no longer outweighs the cost

This should reduce memory usage during production builds.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-11 00:00:31 -08:00
Evan Rusackas
85764701f5 docs(ci): complete bun/turborepo/changesets migration docs and workflows
- Update all CI workflows (pre-commit, tech-debt) to use Bun
- Update build scripts (js_build.sh, cypress_build.sh, eslint.sh) for Bun
- Add sync-package-versions.js script for release version alignment
- Simplify package.json scripts (build:packages, publish:packages)
- Add gitTag: false to changesets config to avoid repo tag clutter
- Remove obsolete Lerna scripts (build.js, lernaVersion.sh)
- Update RELEASING/README.md with comprehensive npm publishing guide
- Update all developer documentation for Bun usage
- Update LLM instruction files (AGENTS.md, dev-standard.mdc)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 23:20:33 -08:00
Evan Rusackas
aa94a8eebd feat(docker/ci): migrate Docker and CI from npm to bun
Docker changes:
- Use oven/bun:1-debian as base image instead of node:20-trixie-slim
- Replace npm ci with bun install --frozen-lockfile
- Replace npm run commands with bun run
- Mount bun.lock instead of package-lock.json
- Update cache paths for Bun's cache directory
- Rename NPM_RUN_PRUNE env var to BUN_RUN_PRUNE

CI workflow changes:
- Update bashlib.sh npm-install function to use bun
- Update superset-frontend.yml to use bun run commands
- Update release.yml to use setup-bun action and changesets
- Update superset-e2e.yml to use setup-bun action
- Update superset-playwright.yml to use setup-bun action
- Update superset-translations.yml to use setup-bun action

Note: superset-embedded-sdk and superset-websocket remain on npm
as they are separate packages with their own lockfiles.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 11:46:21 -08:00
Evan Rusackas
a44372d994 fix(turbo): add explicit task dependencies for core packages
Turborepo's `^build` dependency resolution only uses dependencies and
devDependencies, not peerDependencies. This caused plugins to build
before their dependencies (@superset-ui/core, @apache-superset/core,
@superset-ui/chart-controls) were ready.

Added explicit task dependencies to ensure correct build order:
1. @superset-ui/core and @apache-superset/core build first (no deps)
2. @superset-ui/chart-controls builds after core packages
3. All other packages build after chart-controls

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 11:11:53 -08:00
Evan Rusackas
198c7598cf feat(frontend): migrate from npm/lerna to bun/turborepo/changesets
- Replace lerna with changesets for version management and npm publishing
- Migrate from npm to bun as the package manager
- Add bun.lock and remove package-lock.json
- Add changeset scripts: changeset:add, changeset:version, changeset:publish
- Delete lerna.json
- Update .gitignore to exclude package-lock.json

Benefits of this migration:
- Bun: ~10x faster package installs, native TypeScript support
- Turborepo: Intelligent caching for builds (already added)
- Changesets: Cleaner workflow for version management and publishing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 10:45:08 -08:00
Evan Rusackas
d0575ceb29 feat(build): POC - add Turborepo for cached package builds
This PR adds Turborepo as a build orchestration tool for the frontend
monorepo, providing intelligent caching for package builds.

Changes:
- Add turbo.json with task pipeline configuration
- Add turbo devDependency to root package.json
- Add packageManager field for Turborepo compatibility
- Add build/clean/type-check scripts to all packages and plugins
- Add .turbo to .gitignore

New scripts:
- npm run turbo:build - Build all packages with caching
- npm run turbo:build:force - Build without cache
- npm run turbo:type-check - Type check all packages
- npm run turbo:clean - Clean all build artifacts

Benefits:
- Cached builds: 5s → 314ms (16x faster) on unchanged packages
- Parallel builds across packages
- Only rebuilds what changed
- Local-only caching (no cloud dependencies)

Note: Lerna is preserved for versioning and publishing. Turborepo
handles build orchestration, not package publishing.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 10:25:06 -08:00
77 changed files with 9871 additions and 58588 deletions

View File

@@ -18,6 +18,11 @@ Apache Superset is a data visualization platform with Flask/Python backend and R
- **NO Enzyme** - Use React Testing Library/Jest (Enzyme fully removed)
- **Use @superset-ui/core** - Don't import Ant Design directly
### Package Manager Migration
- **Use Bun instead of npm** - The frontend uses Bun as the package manager (e.g., `bun install`, `bun run build`)
- **Use Turborepo for builds** - Use `bun run build:packages` to build packages with caching
- **Use Changesets for versioning** - Use `bun run changeset:add` to track version changes
### Testing Strategy Migration
- **Prefer unit tests** over integration tests
- **Prefer integration tests** over Cypress end-to-end tests

View File

@@ -21,9 +21,15 @@ curl -LsSf https://astral.sh/uv/install.sh | sh
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.bashrc
echo 'export PATH="$HOME/.cargo/bin:$PATH"' >> ~/.zshrc
# Install Claude Code CLI via npm
# Install Bun
echo "📦 Installing Bun..."
curl -fsSL https://bun.sh/install | bash
echo 'export PATH="$HOME/.bun/bin:$PATH"' >> ~/.bashrc
echo 'export PATH="$HOME/.bun/bin:$PATH"' >> ~/.zshrc
# Install Claude Code CLI
echo "🤖 Installing Claude Code..."
npm install -g @anthropic-ai/claude-code
~/.bun/bin/bun install -g @anthropic-ai/claude-code
# Make the start script executable
chmod +x .devcontainer/start-superset.sh

View File

@@ -41,21 +41,21 @@ pip-upgrade() {
npm-install() {
cd "$GITHUB_WORKSPACE/superset-frontend"
# cache-restore npm
say "::group::Install npm packages"
echo "npm: $(npm --version)"
# cache-restore bun
say "::group::Install packages with bun"
echo "bun: $(bun --version)"
echo "node: $(node --version)"
npm ci
bun install --frozen-lockfile
say "::endgroup::"
# cache-save npm
# cache-save bun
}
build-assets() {
cd "$GITHUB_WORKSPACE/superset-frontend"
say "::group::Build static assets"
npm run build
bun run build
say "::endgroup::"
}
@@ -67,7 +67,7 @@ build-instrumented-assets() {
if [[ -f "$ASSETS_MANIFEST" ]]; then
echo 'Skip frontend build because instrumented static assets already exist.'
else
npm run build-instrumented
bun run build-instrumented
cache-save instrumented-assets
fi
say "::endgroup::"

View File

@@ -38,15 +38,15 @@ jobs:
echo "HOMEBREW_CELLAR=$HOMEBREW_CELLAR" >>"${GITHUB_ENV}"
echo "HOMEBREW_REPOSITORY=$HOMEBREW_REPOSITORY" >>"${GITHUB_ENV}"
brew install norwoodj/tap/helm-docs
- name: Setup Node.js
uses: actions/setup-node@v6
- name: Install Bun
uses: oven-sh/setup-bun@v2
with:
node-version: '20'
bun-version: latest
- name: Install Frontend Dependencies
run: |
cd superset-frontend
npm ci
bun install --frozen-lockfile
- name: Install Docs Dependencies
run: |

View File

@@ -28,7 +28,7 @@ jobs:
steps:
- uses: actions/checkout@v6
with:
# pulls all commits (needed for lerna / semantic release to correctly version)
# pulls all commits (needed for changesets to correctly version)
fetch-depth: 0
- name: Get tags and filter trigger tags
run: |
@@ -40,48 +40,33 @@ jobs:
git fetch --prune --unshallow
git tag -d `git tag | grep -E '^trigger-'`
- name: Install Node.js
- name: Install Bun
if: env.HAS_TAGS
uses: actions/setup-node@v6
uses: oven-sh/setup-bun@v2
with:
node-version-file: './superset-frontend/.nvmrc'
bun-version: latest
- name: Cache npm
- name: Cache bun
if: env.HAS_TAGS
uses: actions/cache@v5
with:
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }}
restore-keys: |
${{ runner.OS }}-node-
${{ runner.OS }}-
- name: Get npm cache directory path
if: env.HAS_TAGS
id: npm-cache-dir-path
run: echo "dir=$(npm config get cache)" >> $GITHUB_OUTPUT
- name: Cache npm
if: env.HAS_TAGS
uses: actions/cache@v5
id: npm-cache # use this to check for `cache-hit` (`steps.npm-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.npm-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-
${{ runner.os }}-bun-
- name: Install dependencies
if: env.HAS_TAGS
working-directory: ./superset-frontend
run: npm ci
run: bun install --frozen-lockfile
- name: Run unit tests
if: env.HAS_TAGS
working-directory: ./superset-frontend
run: npm run test -- plugins packages
run: bun run test -- plugins packages
- name: Build packages
if: env.HAS_TAGS
working-directory: ./superset-frontend
run: npm run plugins:build
run: bun run build:packages
- name: Configure npm and git
if: env.HAS_TAGS
@@ -96,12 +81,12 @@ jobs:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ github.token }}
- name: Bump version and publish package(s)
- name: Publish packages with changesets
if: env.HAS_TAGS
working-directory: ./superset-frontend
run: |
git tag -d `git tag | grep -E '^trigger-'`
npm run plugins:release-from-tag
bun run changeset:publish
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ github.token }}

View File

@@ -107,12 +107,12 @@ jobs:
uses: ./.github/actions/cached-dependencies
with:
run: testdata
- name: Setup Node.js
- name: Setup Bun
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: actions/setup-node@v6
uses: oven-sh/setup-bun@v2
with:
node-version-file: './superset-frontend/.nvmrc'
- name: Install npm dependencies
bun-version: latest
- name: Install dependencies
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
@@ -224,12 +224,12 @@ jobs:
uses: ./.github/actions/cached-dependencies
with:
run: playwright_testdata
- name: Setup Node.js
- name: Setup Bun
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: actions/setup-node@v6
uses: oven-sh/setup-bun@v2
with:
node-version-file: './superset-frontend/.nvmrc'
- name: Install npm dependencies
bun-version: latest
- name: Install dependencies
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:

View File

@@ -80,14 +80,14 @@ jobs:
- name: Load Docker Image
run: docker load < docker-image.tar.gz
- name: npm run test with coverage
- name: bun run test with coverage
run: |
mkdir -p ${{ github.workspace }}/superset-frontend/coverage
docker run \
-v ${{ github.workspace }}/superset-frontend/coverage:/app/superset-frontend/coverage \
--rm $TAG \
bash -c \
"npm run test -- --coverage --shard=${{ matrix.shard }}/8 --coverageReporters=json-summary"
"bun run test -- --coverage --shard=${{ matrix.shard }}/8 --coverageReporters=json-summary"
- name: Upload Coverage Artifact
uses: actions/upload-artifact@v6
@@ -138,12 +138,12 @@ jobs:
- name: lint
run: |
docker run --rm $TAG bash -c \
"npm i && npm run lint"
"bun install && bun run lint"
- name: tsc
run: |
docker run --rm $TAG bash -c \
"npm i && npm run plugins:build && npm run type"
"bun install && bun run build:packages && bun run type"
validate-frontend:
needs: frontend-build
@@ -161,12 +161,12 @@ jobs:
- name: Build Plugins Packages
run: |
docker run --rm $TAG bash -c \
"npm run plugins:build"
"bun run build:packages"
- name: Build Plugins Storybook
run: |
docker run --rm $TAG bash -c \
"npm run plugins:build-storybook"
"bun run plugins:build-storybook"
test-storybook:
needs: frontend-build
@@ -184,4 +184,4 @@ jobs:
- name: Build Storybook and Run Tests
run: |
docker run --rm $TAG bash -c \
"npm run build-storybook && npx playwright install-deps && npx playwright install chromium && npm run test-storybook:ci"
"bun run build-storybook && bun x playwright install-deps && bun x playwright install chromium && bun run test-storybook:ci"

View File

@@ -98,12 +98,12 @@ jobs:
uses: ./.github/actions/cached-dependencies
with:
run: playwright_testdata
- name: Setup Node.js
- name: Setup Bun
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: actions/setup-node@v6
uses: oven-sh/setup-bun@v2
with:
node-version-file: './superset-frontend/.nvmrc'
- name: Install npm dependencies
bun-version: latest
- name: Install dependencies
if: steps.check.outputs.python || steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:

View File

@@ -29,21 +29,21 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
- name: Setup Bun
if: steps.check.outputs.frontend
uses: actions/setup-node@v6
uses: oven-sh/setup-bun@v2
with:
node-version-file: './superset-frontend/.nvmrc'
bun-version: latest
- name: Install dependencies
if: steps.check.outputs.frontend
uses: ./.github/actions/cached-dependencies
with:
run: npm-install
- name: lint
- name: Build translations
if: steps.check.outputs.frontend
working-directory: ./superset-frontend
run: |
npm run build-translation
bun run build-translation
babel-extract:
runs-on: ubuntu-24.04

View File

@@ -29,19 +29,19 @@ jobs:
- name: Checkout Repository
uses: actions/checkout@v6
- name: Set up Node.js
uses: actions/setup-node@v6
- name: Install Bun
uses: oven-sh/setup-bun@v2
with:
node-version-file: './superset-frontend/.nvmrc'
bun-version: latest
- name: Install Dependencies
run: npm ci
run: bun install --frozen-lockfile
working-directory: ./superset-frontend
- name: Run Script
env:
SPREADSHEET_ID: "1oABNnzxJYzwUrHjr_c9wfYEq9dFL1ScVof9LlaAdxvo"
SERVICE_ACCOUNT_KEY: ${{ secrets.GSHEET_KEY }}
run: npm run lint-stats
run: bun run lint-stats
continue-on-error: true
working-directory: ./superset-frontend

View File

@@ -55,7 +55,7 @@ repos:
exclude: ^helm/superset/templates/
- id: debug-statements
- id: end-of-file-fixer
exclude: .*/lerna\.json$|^docs/static/img/logos/
exclude: ^docs/static/img/logos/
- id: trailing-whitespace
exclude: ^.*\.(snap)
args: ["--markdown-linebreak-ext=md"]

View File

@@ -34,6 +34,11 @@ Common pre-commit failures:
- **Use antd theming tokens** - Prefer antd tokens over legacy theming tokens
- **Avoid custom css and styles** - Follow antd best practices and avoid styling and custom CSS whenever possible
### Package Manager Migration
- **Use Bun instead of npm** - The frontend uses Bun as the package manager (e.g., `bun install`, `bun run build`)
- **Use Turborepo for builds** - Use `bun run build:packages` to build packages with caching
- **Use Changesets for versioning** - Use `bun run changeset:add` to track version changes
### Testing Strategy Migration
- **Prefer unit tests** over integration tests
- **Prefer integration tests** over end-to-end tests
@@ -154,22 +159,22 @@ The Developer Portal auto-generates MDX documentation from Storybook stories. **
### Running Tests
```bash
# Frontend
npm run test # All tests
npm run test -- filename.test.tsx # Single file
bun run test # All tests
bun run test -- filename.test.tsx # Single file
# E2E Tests (Playwright - NEW)
npm run playwright:test # All Playwright tests
npm run playwright:ui # Interactive UI mode
npm run playwright:headed # See browser during tests
npx playwright test tests/auth/login.spec.ts # Single file
npm run playwright:debug tests/auth/login.spec.ts # Debug specific file
bun run playwright:test # All Playwright tests
bun run playwright:ui # Interactive UI mode
bun run playwright:headed # See browser during tests
bun x playwright test tests/auth/login.spec.ts # Single file
bun run playwright:debug tests/auth/login.spec.ts # Debug specific file
# E2E Tests (Cypress - DEPRECATED)
cd superset-frontend/cypress-base
npm run cypress-run-chrome # All Cypress tests (headless)
npm run cypress-debug # Interactive Cypress UI
# Backend
# Backend
pytest # All tests
pytest tests/unit_tests/specific_test.py # Single file
pytest tests/unit_tests/ # Directory
@@ -190,7 +195,8 @@ curl -f http://localhost:8088/health || echo "❌ Setup required - see https://s
"It appears you aren't set up properly. Please refer to the [Working with LLMs](https://superset.apache.org/docs/contributing/development#working-with-llms) section in the development docs for setup instructions."
**Key Project Files:**
- `superset-frontend/package.json` - Frontend build scripts (`npm run dev` on port 9000, `npm run test`, `npm run lint`)
- `superset-frontend/package.json` - Frontend build scripts (`bun run dev` on port 9000, `bun run test`, `bun run lint`)
- `superset-frontend/turbo.json` - Turborepo build configuration for packages/plugins
- `pyproject.toml` - Python tooling (ruff, mypy configs)
- `requirements/` folder - Python dependencies (base.txt, development.txt)

View File

@@ -29,7 +29,7 @@ ARG BUILD_TRANSLATIONS="false"
######################################################################
# superset-node-ci used as a base for building frontend assets and CI
######################################################################
FROM --platform=${BUILDPLATFORM} node:20-trixie-slim AS superset-node-ci
FROM --platform=${BUILDPLATFORM} oven/bun:1-debian AS superset-node-ci
ARG BUILD_TRANSLATIONS
ENV BUILD_TRANSLATIONS=${BUILD_TRANSLATIONS}
ARG DEV_MODE="false" # Skip frontend build in dev mode
@@ -37,13 +37,13 @@ ENV DEV_MODE=${DEV_MODE}
COPY docker/ /app/docker/
# Arguments for build configuration
ARG NPM_BUILD_CMD="build"
ARG BUN_BUILD_CMD="build"
# Install system dependencies required for node-gyp
RUN /app/docker/apt-install.sh build-essential python3 zstd
# Define environment variables for frontend build
ENV BUILD_CMD=${NPM_BUILD_CMD} \
ENV BUILD_CMD=${BUN_BUILD_CMD} \
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true
# Run the frontend memory monitoring script
@@ -57,17 +57,17 @@ RUN mkdir -p /app/superset/static/assets \
# Mount package files and install dependencies if not in dev mode
# NOTE: we mount packages and plugins as they are referenced in package.json as workspaces
# ideally we'd COPY only their package.json. Here npm ci will be cached as long
# ideally we'd COPY only their package.json. Here bun install will be cached as long
# as the full content of these folders don't change, yielding a decent cache reuse rate.
# Note that it's not possible to selectively COPY or mount using blobs.
RUN --mount=type=bind,source=./superset-frontend/package.json,target=./package.json \
--mount=type=bind,source=./superset-frontend/package-lock.json,target=./package-lock.json \
--mount=type=bind,source=./superset-frontend/bun.lock,target=./bun.lock \
--mount=type=cache,target=/root/.cache \
--mount=type=cache,target=/root/.npm \
--mount=type=cache,target=/root/.bun/install/cache \
if [ "${DEV_MODE}" = "false" ]; then \
npm ci; \
bun install --frozen-lockfile; \
else \
echo "Skipping 'npm ci' in dev mode"; \
echo "Skipping 'bun install' in dev mode"; \
fi
# Runs the webpack build process
@@ -79,12 +79,12 @@ COPY superset-frontend /app/superset-frontend
FROM superset-node-ci AS superset-node
# Build the frontend if not in dev mode
RUN --mount=type=cache,target=/root/.npm \
RUN --mount=type=cache,target=/root/.bun/install/cache \
if [ "${DEV_MODE}" = "false" ]; then \
echo "Running 'npm run ${BUILD_CMD}'"; \
npm run ${BUILD_CMD}; \
echo "Running 'bun run ${BUILD_CMD}'"; \
bun run ${BUILD_CMD}; \
else \
echo "Skipping 'npm run ${BUILD_CMD}' in dev mode"; \
echo "Skipping 'bun run ${BUILD_CMD}' in dev mode"; \
fi;
# Copy translation files
@@ -92,7 +92,7 @@ COPY superset/translations /app/superset/translations
# Build translations if enabled, then cleanup localization files
RUN if [ "${BUILD_TRANSLATIONS}" = "true" ]; then \
npm run build-translation; \
bun run build-translation; \
fi; \
rm -rf /app/superset/translations/*/*/*.[po,mo];

View File

@@ -391,7 +391,7 @@ RSA key verified
There are also additional support scripts leveraging this to make it easy for those downloading a release to test it in-situ. You can do either of the following to validate these release assets:
- `cd` into `superset-frontend` and run `npm run validate-release`
- `cd` into `superset-frontend` and run `bun run validate-release`
- `cd` into `RELEASES` and run `./validate_this_release.sh`
## Publishing a successful release
@@ -444,9 +444,9 @@ Create the distribution
```bash
cd superset-frontend/
npm ci && npm run build
bun install --frozen-lockfile && bun run build
# Compile translations for the frontend
npm run build-translation
bun run build-translation
cd ../
@@ -524,23 +524,171 @@ generated images.
**NOTE:** If the docker image isn't built, you'll need to run this [GH action](https://github.com/apache/superset/actions/workflows/tag-release.yml) where you provide it the tag sha.
### Npm Release
### Npm Package Release
You might want to publish the latest @superset-ui release to npm
Superset publishes `@superset-ui/*` and `@apache-superset/*` packages to npm. These are considered
"convenience releases" (not official ASF releases) and can be published independently of Superset releases.
Superset uses [Changesets](https://github.com/changesets/changesets) for version management and
[Turborepo](https://turbo.build/) for building packages.
#### Two Publishing Workflows
**1. Periodic Publishing (on master)** - For ongoing development, packages are versioned based on
accumulated changesets and published periodically by maintainers.
**2. Release Publishing (on release branches)** - When cutting a Superset release, packages are
synced to match the Superset version (e.g., all packages become 6.1.0).
---
#### Workflow 1: Periodic Publishing on Master
##### During Development: Adding Changesets
When a PR changes publishable packages, the author should add a changeset:
```bash
cd superset/superset-frontend
cd superset-frontend
bun run changeset:add
```
An automated GitHub action will run and generate a new tag, which will contain a version number provided as a parameter.
This interactive CLI asks:
1. Which packages changed? (multi-select)
2. Bump type? (major / minor / patch)
3. Summary for changelog
A markdown file is created in `.changeset/` describing the change.
##### Periodic Publishing (Maintainers)
When ready to publish accumulated changes:
```bash
export GH_TOKEN={GITHUB_TOKEN}
npx lerna version {VERSION} --conventional-commits --create-release github --no-private --yes --message {COMMIT_MESSAGE}
cd superset-frontend
# 1. Check what's pending
bun run changeset:status
# 2. Bump versions (consumes changesets, updates CHANGELOGs)
bun run changeset:version
# 3. Review and commit
git diff
git add .
git commit -m "chore(packages): version packages"
# 4. Dry run to verify
bun run publish:packages:dry
# 5. Publish to npm
bun run publish:packages
# 6. Push the version commit
git push
```
This action will publish the specified version to npm registry.
---
#### Workflow 2: Release Branch Publishing
When cutting a Superset release (e.g., 6.1.0), sync all packages to match:
##### For Release Candidates
```bash
npx lerna publish from-package --yes
cd superset-frontend
# Sync all packages to RC version
bun run sync-versions 6.1.0-rc.1
# Review changes
git diff
# Commit
git add .
git commit -m "chore(packages): bump versions to 6.1.0-rc.1"
# Dry run
bun run publish:packages:dry
# Publish (goes to npm with version tag, not @latest)
bun run publish:packages
```
##### For Final Release
After the vote passes:
```bash
cd superset-frontend
# Sync all packages to final version
bun run sync-versions 6.1.0
# Commit
git add .
git commit -m "chore(packages): bump versions to 6.1.0"
# Publish
bun run publish:packages
```
##### Dry Run
Always preview before publishing:
```bash
# Preview version sync without making changes
bun run sync-versions:dry 6.1.0
# Preview what would be published
bun run publish:packages:dry
```
---
#### Quick Reference
| Task | Command |
|------|---------|
| Add a changeset (during PR) | `bun run changeset:add` |
| Check pending changes | `bun run changeset:status` |
| Bump versions (from changesets) | `bun run changeset:version` |
| Sync versions (for releases) | `bun run sync-versions <version>` |
| Sync versions (dry run) | `bun run sync-versions:dry <version>` |
| Build packages | `bun run build:packages` |
| Preview publish | `bun run publish:packages:dry` |
| Publish to npm | `bun run publish:packages` |
---
#### npm Credentials
To publish, you need npm credentials with publish access to `@superset-ui` and `@apache-superset` scopes.
```bash
# Login to npm
npm login
# Verify access
npm whoami
npm access ls-packages
```
Contact a PMC member if you need publish access granted.
---
#### Troubleshooting
**"You do not have permission to publish"**
- Ensure you're logged in: `npm whoami`
- Request access from a PMC member
**"Version already exists"**
- The version was already published; bump to a new version
**Build failures**
- Run `bun run build:packages:force` to rebuild from scratch
- Check for TypeScript errors: `bun run turbo:type-check`

View File

@@ -152,10 +152,10 @@ services:
DEV_MODE: "true"
BUILD_TRANSLATIONS: ${BUILD_TRANSLATIONS:-false}
environment:
# set this to false if you have perf issues running the npm i; npm run dev in-docker
# set this to false if you have perf issues running bun install; bun run dev in-docker
# if you do so, you have to run this manually on the host, which should perform better!
BUILD_SUPERSET_FRONTEND_IN_DOCKER: true
NPM_RUN_PRUNE: false
BUN_RUN_PRUNE: false
SCARF_ANALYTICS: "${SCARF_ANALYTICS:-}"
# configuring the dev-server to use the host.docker.internal to connect to the backend
superset: "http://superset-light:8088"

View File

@@ -168,10 +168,10 @@ services:
DEV_MODE: "true"
BUILD_TRANSLATIONS: ${BUILD_TRANSLATIONS:-false}
environment:
# set this to false if you have perf issues running the npm i; npm run dev in-docker
# set this to false if you have perf issues running bun install; bun run dev in-docker
# if you do so, you have to run this manually on the host, which should perform better!
BUILD_SUPERSET_FRONTEND_IN_DOCKER: true
NPM_RUN_PRUNE: false
BUN_RUN_PRUNE: false
SCARF_ANALYTICS: "${SCARF_ANALYTICS:-}"
# configuring the dev-server to use the host.docker.internal to connect to the backend
superset: "http://superset:8088"

View File

@@ -27,18 +27,18 @@ if [ "$BUILD_SUPERSET_FRONTEND_IN_DOCKER" = "true" ]; then
echo "Building Superset frontend in dev mode inside docker container"
cd /app/superset-frontend
if [ "$NPM_RUN_PRUNE" = "true" ]; then
echo "Running \"npm run prune\""
npm run prune
if [ "$BUN_RUN_PRUNE" = "true" ]; then
echo "Running \"bun run prune\""
bun run prune
fi
echo "Running \"npm install\""
npm install
echo "Running \"bun install\""
bun install
echo "Start webpack dev server"
# start the webpack dev server, serving dynamically at http://localhost:9000
# it proxies to the backend served at http://localhost:8088
npm run dev-server
bun run dev-server
else
echo "Skipping frontend build steps - YOU NEED TO RUN IT MANUALLY ON THE HOST!"

View File

@@ -348,10 +348,10 @@ curl -f http://localhost:8088/health && echo "✅ Superset ready"
```bash
# Frontend development
cd superset-frontend
npm run dev # Development server on http://localhost:9000
npm run test # Run all tests
npm run test -- filename.test.tsx # Run single test file
npm run lint # Linting and type checking
bun run dev # Development server on http://localhost:9000
bun run test # Run all tests
bun run test -- filename.test.tsx # Run single test file
bun run lint # Linting and type checking
# Backend validation
pre-commit run mypy # Type checking
@@ -481,19 +481,36 @@ Frontend assets (TypeScript, JavaScript, CSS, and images) must be compiled in or
#### Prerequisite
##### nvm and node
##### Bun (Recommended)
First, be sure you are using the following versions of Node.js and npm:
Superset uses [Bun](https://bun.sh) as its JavaScript runtime and package manager. Bun is significantly faster than npm (up to 10x faster installs) and includes native TypeScript support.
- `Node.js`: Version 20
- `npm`: Version 10
**Install Bun:**
```bash
# macOS, Linux, or WSL
curl -fsSL https://bun.sh/install | bash
# Or using Homebrew (macOS)
brew install oven-sh/bun/bun
# Verify installation
bun --version
```
##### Node.js (Alternative)
If you prefer Node.js, ensure you have:
- `Node.js`: Version 20+
- `npm`: Version 10+
We recommend using [nvm](https://github.com/nvm-sh/nvm) to manage your node environment:
```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.0/install.sh | bash
in case it shows '-bash: nvm: command not found'
# In case it shows '-bash: nvm: command not found'
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
@@ -503,13 +520,9 @@ nvm install --lts
nvm use --lts
```
Or if you use the default macOS starting with Catalina shell `zsh`, try:
```zsh
sh -c "$(curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.0/install.sh)"
```
For those interested, you may also try out [avn](https://github.com/nvm-sh/nvm#deeper-shell-integration) to automatically switch to the node version that is required to run Superset frontend.
:::note
While Node.js/npm will work, the project is optimized for Bun. CI/CD pipelines and Docker builds use Bun.
:::
#### Install dependencies
@@ -519,11 +532,14 @@ Install third-party dependencies listed in `package.json` via:
# From the root of the repository
cd superset-frontend
# Install dependencies from `package-lock.json`
npm ci
# Install dependencies from `bun.lock`
bun install
# Or with frozen lockfile (recommended for CI/reproducible builds)
bun install --frozen-lockfile
```
Note that Superset uses [Scarf](https://docs.scarf.sh) to capture telemetry/analytics about versions being installed, including the `scarf-js` npm package and an analytics pixel. As noted elsewhere in this documentation, Scarf gathers aggregated stats for the sake of security/release strategy and does not capture/retain PII. [You can read here](https://docs.scarf.sh/package-analytics/) about the `scarf-js` package, and various means to opt out of it, but you can opt out of the npm package _and_ the pixel by setting the `SCARF_ANALYTICS` environment variable to `false` or opt out of the pixel by adding this setting in `superset-frontent/package.json`:
Note that Superset uses [Scarf](https://docs.scarf.sh) to capture telemetry/analytics about versions being installed, including the `scarf-js` package and an analytics pixel. As noted elsewhere in this documentation, Scarf gathers aggregated stats for the sake of security/release strategy and does not capture/retain PII. [You can read here](https://docs.scarf.sh/package-analytics/) about the `scarf-js` package, and various means to opt out of it, but you can opt out of the package _and_ the pixel by setting the `SCARF_ANALYTICS` environment variable to `false` or opt out of the pixel by adding this setting in `superset-frontend/package.json`:
```json
// your-package/package.json
@@ -540,9 +556,9 @@ Note that Superset uses [Scarf](https://docs.scarf.sh) to capture telemetry/anal
There are three types of assets you can build:
1. `npm run build`: the production assets, CSS/JSS minified and optimized
2. `npm run dev-server`: local development assets, with sourcemaps and hot refresh support
3. `npm run build-instrumented`: instrumented application code for collecting code coverage from Cypress tests
1. `bun run build`: the production assets, CSS/JSS minified and optimized
2. `bun run dev-server`: local development assets, with sourcemaps and hot refresh support
3. `bun run build-instrumented`: instrumented application code for collecting code coverage from E2E tests
If while using the above commands you encounter an error related to the limit of file watchers:
@@ -591,7 +607,7 @@ So a typical development workflow is the following:
2. in parallel, run the Webpack dev server locally on port `9000`,<br/>
```bash
npm run dev-server
bun run dev-server
```
3. access `http://localhost:9000` (the Webpack server, _not_ Flask) in your web browser. This will use the hot-reloading front-end assets from the Webpack development server while redirecting back-end queries to Flask/Superset: your changes on Superset codebase — either front or back-end — will then be reflected live in the browser.
@@ -600,36 +616,52 @@ It's possible to change the Webpack server settings:
```bash
# Start the dev server at http://localhost:9000
npm run dev-server
bun run dev-server
# Run the dev server on a non-default port
npm run dev-server -- --port=9001
bun run dev-server -- --port=9001
# Proxy backend requests to a Flask server running on a non-default port
npm run dev-server -- --env=--supersetPort=8081
bun run dev-server -- --env=--supersetPort=8081
# Proxy to a remote backend but serve local assets
npm run dev-server -- --env=--superset=https://superset-dev.example.com
bun run dev-server -- --env=--superset=https://superset-dev.example.com
```
The `--superset=` option is useful in case you want to debug a production issue or have to setup Superset behind a firewall. It allows you to run Flask server in another environment while keep assets building locally for the best developer experience.
#### Other npm commands
#### Other bun commands
Alternatively, there are other NPM commands you may find useful:
Alternatively, there are other commands you may find useful:
1. `npm run build-dev`: build assets in development mode.
2. `npm run dev`: built dev assets in watch mode, will automatically rebuild when a file changes
1. `bun run build-dev`: build assets in development mode.
2. `bun run dev`: built dev assets in watch mode, will automatically rebuild when a file changes
3. `bun run build:packages`: build all packages/plugins with Turborepo (intelligent caching)
4. `bun run build:packages:force`: rebuild all packages ignoring cache
#### Docker (docker compose)
See docs [here](https://superset.apache.org/docs/installation/docker-compose)
#### Updating NPM packages
#### Updating packages
Use npm in the prescribed way, making sure that
`superset-frontend/package-lock.json` is updated according to `npm`-prescribed
best practices.
Use bun to add or update packages:
```bash
# Add a new package
bun add package-name
# Add a dev dependency
bun add -d package-name
# Update a package
bun update package-name
# Update all packages
bun update
```
The `bun.lock` file will be automatically updated.
#### Feature flags
@@ -792,13 +824,13 @@ We use [Jest](https://jestjs.io/) and [React Testing Library](https://testing-li
```bash
cd superset-frontend
npm run test
bun run test
```
To run a single test file:
```bash
npm run test -- path/to/file.js
bun run test -- path/to/file.js
```
#### Known Issues and Workarounds
@@ -983,7 +1015,7 @@ Superset includes a [Storybook](https://storybook.js.org/) to preview the layout
```bash
cd superset-frontend
npm run storybook
bun run storybook
```
When contributing new React components to Superset, please try to add a Story alongside the component's `jsx/tsx` file.

View File

@@ -36,8 +36,8 @@ To set up your local environment for documentation development:
```bash
cd docs
npm install
npm run start
bun install
bun run start
```
The site will be available at http://localhost:3000
@@ -47,8 +47,8 @@ The site will be available at http://localhost:3000
To create a production build:
```bash
npm run build
npm run serve # Test the build locally
bun run build
bun run serve # Test the build locally
```
### Deployment
@@ -61,15 +61,14 @@ Visualization plugins allow you to add custom chart types to Superset. They are
### Prerequisites
- Node.js 18+
- npm or yarn
- Bun (recommended) or Node.js 20+
- A local Superset development environment
### Creating a simple Hello World viz plugin
1. **Install the Superset Yeoman generator**:
```bash
npm install -g @superset-ui/generator-superset
bun add -g @superset-ui/generator-superset
```
2. **Create a new plugin**:
@@ -89,14 +88,14 @@ The generator creates a complete plugin structure with TypeScript, React compone
5. **Test your plugin locally**:
```bash
npm run dev
bun run dev
```
6. **Link to your local Superset**:
```bash
npm link
bun link
# In your Superset frontend directory:
npm link superset-plugin-chart-hello-world
bun link superset-plugin-chart-hello-world
```
7. **Import and register in Superset**:
@@ -147,16 +146,16 @@ Run frontend tests using Jest:
cd superset-frontend
# Run all tests
npm run test
bun run test
# Run with coverage
npm run test -- --coverage
bun run test -- --coverage
# Run in watch mode
npm run test -- --watch
bun run test -- --watch
# Run specific test file
npm run test -- MyComponent.test.tsx
bun run test -- MyComponent.test.tsx
```
### E2E Integration Testing
@@ -172,26 +171,26 @@ Playwright is our new E2E testing framework, gradually replacing Cypress.
cd superset-frontend
# Run all Playwright tests
npm run playwright:test
# or: npx playwright test
bun run playwright:test
# or: bun x playwright test
# Run with interactive UI for debugging
npm run playwright:ui
# or: npx playwright test --ui
bun run playwright:ui
# or: bun x playwright test --ui
# Run in headed mode (see browser)
npm run playwright:headed
# or: npx playwright test --headed
bun run playwright:headed
# or: bun x playwright test --headed
# Run specific test file
npx playwright test tests/auth/login.spec.ts
bun x playwright test tests/auth/login.spec.ts
# Run with debug mode (step through tests)
npm run playwright:debug tests/auth/login.spec.ts
# or: npx playwright test --debug tests/auth/login.spec.ts
bun run playwright:debug tests/auth/login.spec.ts
# or: bun x playwright test --debug tests/auth/login.spec.ts
# Generate test report
npm run playwright:report
bun run playwright:report
```
#### Cypress (DEPRECATED - will be removed)
@@ -290,7 +289,7 @@ pybabel init -i superset/translations/messages.pot -d superset/translations -l d
pybabel extract -F babel.cfg -o superset/translations/messages.pot -k lazy_gettext superset
# Extract JavaScript strings
npm run build-translation
bun run build-translation
```
### Updating language files
@@ -305,7 +304,7 @@ pybabel update -i superset/translations/messages.pot -d superset/translations
```bash
# Frontend
cd superset-frontend
npm run build-translation
bun run build-translation
# Backend
pybabel compile -d superset/translations
@@ -340,22 +339,22 @@ We use a hybrid linting approach combining OXC (Oxidation Compiler) for standard
cd superset-frontend
# Run both OXC and custom rules
npm run lint:full
bun run lint:full
# Run OXC linter only (faster for most checks)
npm run lint
bun run lint
# Fix auto-fixable issues with OXC
npm run lint-fix
bun run lint-fix
# Run custom rules checker only
npm run check:custom-rules
bun run check:custom-rules
# Run tsc (typescript) checks
npm run type
bun run type
# Format with Prettier
npm run prettier
bun run prettier
```
#### Architecture
@@ -481,15 +480,15 @@ alias sfront='cd superset-frontend && npm run dev-server'
## Common Issues and Solutions
### Node/npm Issues
### Bun/Node Issues
```bash
# Clear npm cache
npm cache clean --force
# Clear bun cache
bun pm cache rm
# Reinstall dependencies
rm -rf node_modules package-lock.json
npm install
rm -rf node_modules bun.lock
bun install
```
### Python Environment Issues

View File

@@ -270,6 +270,26 @@ docker tag apache/superset:X.Y.Z apache/superset:latest
docker push apache/superset:latest
```
#### Publish npm Packages
Superset publishes frontend packages to npm for use by plugin developers and embedders.
See [RELEASING/README.md](https://github.com/apache/superset/blob/master/RELEASING/README.md#npm-package-publishing)
for the complete npm publishing guide.
```bash
cd superset-frontend
# Sync package versions to release version
bun run sync-versions X.Y.Z
# Review and commit version changes
git diff
git add -A && git commit -m "chore(packages): bump versions to X.Y.Z"
# Build and publish (requires npm auth)
bun run publish:packages
```
### 6. Post-Release Tasks
#### Update Documentation
@@ -277,7 +297,7 @@ docker push apache/superset:latest
# Update docs version
cd docs
# Update docusaurus.config.js with new version
npm run build
bun run build
```
#### Announcement Email
@@ -461,6 +481,7 @@ Credit:
- [Apache Release Policy](https://www.apache.org/legal/release-policy.html)
- [Superset Release History](https://github.com/apache/superset/releases)
- [Version Strategy Discussion](https://github.com/apache/superset/discussions)
- [npm Publishing Guide](https://github.com/apache/superset/blob/master/RELEASING/README.md#npm-package-publishing) - Detailed instructions for publishing frontend packages
### Tools
- [Release Scripts](https://github.com/apache/superset/tree/master/scripts/release)

View File

@@ -63,7 +63,7 @@ edit files...
# Run tests
pytest tests/unit_tests/
cd superset-frontend && npm run test
cd superset-frontend && bun run test
# Run linting
pre-commit run --all-files
@@ -226,7 +226,7 @@ pytest tests/integration_tests/ -v
#### Frontend Test Failures
```bash
cd superset-frontend
npm run test -- --coverage
bun run test -- --coverage
```
#### Linting Failures

View File

@@ -220,7 +220,7 @@ LOCAL_EXTENSIONS = [
]
```
This instructs Superset to load and serve extensions directly from disk, so you can iterate quickly. Running `superset-extensions dev` watches for file changes and rebuilds assets automatically, while the Webpack development server (started separately with `npm run dev-server`) serves updated files as soon as they're modified. This enables immediate feedback for React components, styles, and other frontend code. Changes to backend files are also detected automatically and immediately synced, ensuring that both frontend and backend updates are reflected in your development environment.
This instructs Superset to load and serve extensions directly from disk, so you can iterate quickly. Running `superset-extensions dev` watches for file changes and rebuilds assets automatically, while the Webpack development server (started separately with `bun run dev-server`) serves updated files as soon as they're modified. This enables immediate feedback for React components, styles, and other frontend code. Changes to backend files are also detected automatically and immediately synced, ensuring that both frontend and backend updates are reflected in your development environment.
Example output when running in development mode:
@@ -285,7 +285,7 @@ InteractiveMyComponent.argTypes = {
### How Documentation is Generated
When the docs site is built (`yarn start` or `yarn build` in the `docs/` directory):
When the docs site is built (`bun run start` or `bun run build` in the `docs/` directory):
1. The `generate-extension-components` script scans all stories in `superset-core`
2. For each story, it generates an MDX page with:

View File

@@ -30,7 +30,7 @@ This guide walks you through creating your first Superset extension - a simple "
Before starting, ensure you have:
- Node.js and npm compatible with your Superset version
- [Bun](https://bun.sh) (recommended) or Node.js 20+ compatible with your Superset version
- Python compatible with your Superset version
- A running Superset development environment
- Basic knowledge of React, TypeScript, and Flask
@@ -422,7 +422,7 @@ Install the frontend dependencies:
```bash
cd frontend
npm install
bun install
cd ..
```

View File

@@ -34,23 +34,23 @@ Apache Superset uses Playwright for end-to-end testing, migrating from the legac
cd superset-frontend
# Run all tests
npm run playwright:test
# or: npx playwright test
bun run playwright:test
# or: bun x playwright test
# Run specific test file
npx playwright test tests/auth/login.spec.ts
bun x playwright test tests/auth/login.spec.ts
# Run with UI mode for debugging
npm run playwright:ui
# or: npx playwright test --ui
bun run playwright:ui
# or: bun x playwright test --ui
# Run in headed mode (see browser)
npm run playwright:headed
# or: npx playwright test --headed
bun run playwright:headed
# or: bun x playwright test --headed
# Debug specific test file
npm run playwright:debug tests/auth/login.spec.ts
# or: npx playwright test --debug tests/auth/login.spec.ts
bun run playwright:debug tests/auth/login.spec.ts
# or: bun x playwright test --debug tests/auth/login.spec.ts
```
### Cypress (Deprecated)
@@ -152,11 +152,11 @@ Playwright generates multiple reports for better visibility:
```bash
# View interactive HTML report (opens automatically on failure)
npm run playwright:report
# or: npx playwright show-report
bun run playwright:report
# or: bun x playwright show-report
# View test trace for debugging failures
npx playwright show-trace test-results/[test-name]/trace.zip
bun x playwright show-trace test-results/[test-name]/trace.zip
```
### Report Types

View File

@@ -44,16 +44,16 @@ Comprehensive guide for testing Superset's frontend components and features.
```bash
# Run all frontend tests
npm run test
bun run test
# Run tests in watch mode
npm run test -- --watch
bun run test -- --watch
# Run tests with coverage
npm run test -- --coverage
bun run test -- --coverage
# Run specific test file
npm run test -- MyComponent.test.tsx
bun run test -- MyComponent.test.tsx
```
---

View File

@@ -80,16 +80,16 @@ Superset embraces a testing pyramid approach:
### Quick Commands
```bash
# Frontend unit tests
npm run test
bun run test
# Backend unit tests
# Backend unit tests
pytest tests/unit_tests/
# End-to-end tests
npm run playwright:test
bun run playwright:test
# All tests with coverage
npm run test:coverage
bun run test:coverage
```
### Test Development Workflow

View File

@@ -42,10 +42,10 @@ To run the main Superset Storybook locally:
cd superset-frontend
# Start Storybook (opens at http://localhost:6006)
npm run storybook
bun run storybook
# Build static Storybook
npm run build-storybook
bun run build-storybook
```
### @superset-ui Package Storybook
@@ -55,12 +55,11 @@ The `@superset-ui` packages have a separate Storybook for component library deve
```bash
cd superset-frontend
# Install dependencies and bootstrap packages
npm ci && npm run bootstrap
# Install dependencies and build packages
bun install && bun run turbo:build
# Start the @superset-ui Storybook (opens at http://localhost:9001)
cd packages/superset-ui-demo
npm run storybook
bun run plugins:storybook
```
## Adding Stories
@@ -78,7 +77,7 @@ storybook/stories/<package>/index.js
1. Add package dependencies:
```bash
npm install <package>
bun add <package>
```
2. Create a story folder matching the package name:

View File

@@ -27,4 +27,4 @@ if [[ ! -d "$root_dir/$frontend_dir" ]]; then
fi
cd "$root_dir/$frontend_dir"
npm run lint-fix -- "${@//$frontend_dir\//}"
bun run lint-fix -- "${@//$frontend_dir\//}"

View File

@@ -0,0 +1,38 @@
# Changesets
This folder is used by [Changesets](https://github.com/changesets/changesets) to manage versioning and changelogs for the Superset frontend packages.
## How to add a changeset
When you make changes to packages that should be published, run:
```bash
npx changeset
```
This will prompt you to:
1. Select which packages have changed
2. Choose the semver bump type (major/minor/patch)
3. Write a summary of the changes
A markdown file will be created in this folder describing your changes.
## Releasing
To create a new release:
```bash
# 1. Update versions and changelogs based on changesets
npm run changeset:version
# 2. Build all packages
npm run turbo:build
# 3. Publish to npm
npm run changeset:publish
```
## More information
- [Changesets documentation](https://github.com/changesets/changesets)
- [Using Changesets with Turborepo](https://turbo.build/repo/docs/handbook/publishing-packages/versioning-and-publishing)

View File

@@ -0,0 +1,22 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
"changelog": ["@changesets/changelog-github", { "repo": "apache/superset" }],
"commit": false,
"gitTag": false,
"fixed": [],
"linked": [["@superset-ui/*", "@apache-superset/*"]],
"access": "public",
"baseBranch": "master",
"updateInternalDependencies": "patch",
"ignore": [
"@superset-ui/demo",
"@superset-ui/generator-superset",
"eslint-plugin-i18n-strings",
"eslint-plugin-icons",
"eslint-plugin-theme-colors"
],
"privatePackages": {
"version": false,
"tag": false
}
}

View File

@@ -12,3 +12,8 @@ src/temp
**/lib/*
**/storybook-static/*
migration-storybook.log
# Turborepo cache
.turbo
# npm lockfile (using bun.lock instead)
package-lock.json

8905
superset-frontend/bun.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -29,8 +29,8 @@ PORT='8081'
flask run -p $PORT --with-threads --reload --debugger &
#block on the longer running javascript process
time npm ci
time npm run build-instrumented
time bun install --frozen-lockfile
time bun run build-instrumented
echo "[completed js build steps]"
#setup cypress

View File

@@ -1,6 +1,7 @@
{
"name": "eslint-plugin-i18n-strings",
"version": "1.0.0",
"private": true,
"description": "Warns about translation variables",
"main": "index.ts",
"scripts": {

View File

@@ -1,6 +1,7 @@
{
"name": "eslint-plugin-icons",
"version": "1.0.0",
"private": true,
"description": "Warns about direct usage of Ant Design icons",
"main": "index.ts",
"scripts": {

View File

@@ -1,6 +1,7 @@
{
"name": "eslint-plugin-theme-colors",
"version": "1.0.0",
"private": true,
"description": "Warns about rgb(a)/hex/literal colors",
"main": "index.ts",
"scripts": {

View File

@@ -17,10 +17,10 @@
#
set -e
cd "$(dirname "$0")"
npm --version
bun --version
node --version
time npm ci
time npm run lint
time npm run check
time npm run cover # this also runs the tests, so no need to 'npm run test'
time npm run build
time bun install --frozen-lockfile
time bun run lint
time bun run check
time bun run cover # this also runs the tests, so no need to 'bun run test'
time bun run build

View File

@@ -1,26 +0,0 @@
{
"npmClient": "npm",
"packages": [
"packages/*",
"plugins/*",
"src/setup/*"
],
"version": "0.20.4",
"ignoreChanges": [
"**/*.md",
"**/*.spec.tsx?",
"**/*.spec.jsx?",
"**/__mocks__/**"
],
"command": {
"publish": {
"message": "chore(superset-ui): publish %s",
"graphType": "all"
},
"version": {
"message": "chore(superset-ui): publish %s",
"exact": true
}
},
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,7 @@
{
"name": "superset",
"version": "0.0.0-dev",
"packageManager": "bun@1.3.4",
"description": "Superset is a data exploration platform designed to be visual, intuitive, and interactive.",
"keywords": [
"big",
@@ -34,6 +35,7 @@
"workspaces": [
"packages/*",
"plugins/*",
"eslint-rules/*",
"src/setup/*"
],
"scripts": {
@@ -59,16 +61,20 @@
"check:custom-rules": "node scripts/check-custom-rules.js",
"ensure-oxc": "echo 'OXC linter is ready' && npx oxlint --version",
"lint-stats": "node ./scripts/oxlint-metrics-uploader.js",
"plugins:build": "node ./scripts/build.js",
"plugins:build-assets": "node ./scripts/copyAssets.js",
"plugins:build-storybook": "cd packages/superset-ui-demo && npm run build-storybook",
"plugins:create-conventional-version": "npm run prune && lerna version --conventional-commits --create-release github --no-private --yes --tag-version-prefix=\"plugins-and-packages-v\"",
"plugins:create-minor-version": "npm run prune && lerna version minor --no-private --yes --tag-version-prefix=\"plugins-and-packages-v\"",
"plugins:create-patch-version": "npm run prune && lerna version patch --no-private --yes --tag-version-prefix=\"plugins-and-packages-v\"",
"plugins:publish-all": "npm run prune && npm run plugins:build && lerna publish from-package --force-publish --yes",
"plugins:release-conventional": "npm run prune && npm run plugins:build && lerna publish --conventional-commits --create-release github --yes",
"plugins:release-from-tag": "npm run prune && npm run plugins:build && lerna publish from-package --yes",
"plugins:storybook": "cd packages/superset-ui-demo && npm run storybook",
"build:packages": "turbo run build",
"build:packages:force": "turbo run build --force",
"build:packages:assets": "node ./scripts/copyAssets.js",
"publish:packages": "bun run build:packages && changeset publish",
"publish:packages:dry": "bun run build:packages && changeset publish --dry-run",
"changeset:add": "changeset add",
"changeset:version": "changeset version",
"changeset:status": "changeset status",
"sync-versions": "node scripts/sync-package-versions.js",
"sync-versions:dry": "node scripts/sync-package-versions.js --dry-run",
"turbo:type-check": "turbo run type-check",
"turbo:lint": "turbo run lint",
"turbo:test": "turbo run test",
"turbo:clean": "turbo run clean && rm -rf .turbo",
"playwright:test": "playwright test",
"playwright:ui": "playwright test --ui",
"playwright:headed": "playwright test --headed",
@@ -96,7 +102,7 @@
"last 3 edge versions"
],
"dependencies": {
"@apache-superset/core": "file:packages/superset-core",
"@apache-superset/core": "workspace:*",
"@deck.gl/aggregation-layers": "~9.2.5",
"@deck.gl/core": "~9.2.5",
"@deck.gl/extensions": "~9.2.5",
@@ -104,6 +110,7 @@
"@deck.gl/layers": "~9.2.5",
"@deck.gl/mesh-layers": "~9.2.5",
"@deck.gl/react": "~9.2.5",
"d3": "^3.5.17",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
@@ -121,28 +128,28 @@
"@rjsf/utils": "^5.24.3",
"@rjsf/validator-ajv8": "^5.24.13",
"@scarf/scarf": "^1.4.0",
"@superset-ui/chart-controls": "file:./packages/superset-ui-chart-controls",
"@superset-ui/core": "file:./packages/superset-ui-core",
"@superset-ui/legacy-plugin-chart-calendar": "file:./plugins/legacy-plugin-chart-calendar",
"@superset-ui/legacy-plugin-chart-chord": "file:./plugins/legacy-plugin-chart-chord",
"@superset-ui/legacy-plugin-chart-country-map": "file:./plugins/legacy-plugin-chart-country-map",
"@superset-ui/legacy-plugin-chart-horizon": "file:./plugins/legacy-plugin-chart-horizon",
"@superset-ui/legacy-plugin-chart-map-box": "file:./plugins/legacy-plugin-chart-map-box",
"@superset-ui/legacy-plugin-chart-paired-t-test": "file:./plugins/legacy-plugin-chart-paired-t-test",
"@superset-ui/legacy-plugin-chart-parallel-coordinates": "file:./plugins/legacy-plugin-chart-parallel-coordinates",
"@superset-ui/legacy-plugin-chart-partition": "file:./plugins/legacy-plugin-chart-partition",
"@superset-ui/legacy-plugin-chart-rose": "file:./plugins/legacy-plugin-chart-rose",
"@superset-ui/legacy-plugin-chart-world-map": "file:./plugins/legacy-plugin-chart-world-map",
"@superset-ui/legacy-preset-chart-deckgl": "file:./plugins/legacy-preset-chart-deckgl",
"@superset-ui/legacy-preset-chart-nvd3": "file:./plugins/legacy-preset-chart-nvd3",
"@superset-ui/plugin-chart-ag-grid-table": "file:./plugins/plugin-chart-ag-grid-table",
"@superset-ui/plugin-chart-cartodiagram": "file:./plugins/plugin-chart-cartodiagram",
"@superset-ui/plugin-chart-echarts": "file:./plugins/plugin-chart-echarts",
"@superset-ui/plugin-chart-handlebars": "file:./plugins/plugin-chart-handlebars",
"@superset-ui/plugin-chart-pivot-table": "file:./plugins/plugin-chart-pivot-table",
"@superset-ui/plugin-chart-table": "file:./plugins/plugin-chart-table",
"@superset-ui/plugin-chart-word-cloud": "file:./plugins/plugin-chart-word-cloud",
"@superset-ui/switchboard": "file:./packages/superset-ui-switchboard",
"@superset-ui/chart-controls": "workspace:*",
"@superset-ui/core": "workspace:*",
"@superset-ui/legacy-plugin-chart-calendar": "workspace:*",
"@superset-ui/legacy-plugin-chart-chord": "workspace:*",
"@superset-ui/legacy-plugin-chart-country-map": "workspace:*",
"@superset-ui/legacy-plugin-chart-horizon": "workspace:*",
"@superset-ui/legacy-plugin-chart-map-box": "workspace:*",
"@superset-ui/legacy-plugin-chart-paired-t-test": "workspace:*",
"@superset-ui/legacy-plugin-chart-parallel-coordinates": "workspace:*",
"@superset-ui/legacy-plugin-chart-partition": "workspace:*",
"@superset-ui/legacy-plugin-chart-rose": "workspace:*",
"@superset-ui/legacy-plugin-chart-world-map": "workspace:*",
"@superset-ui/legacy-preset-chart-deckgl": "workspace:*",
"@superset-ui/legacy-preset-chart-nvd3": "workspace:*",
"@superset-ui/plugin-chart-ag-grid-table": "workspace:*",
"@superset-ui/plugin-chart-cartodiagram": "workspace:*",
"@superset-ui/plugin-chart-echarts": "workspace:*",
"@superset-ui/plugin-chart-handlebars": "workspace:*",
"@superset-ui/plugin-chart-pivot-table": "workspace:*",
"@superset-ui/plugin-chart-table": "workspace:*",
"@superset-ui/plugin-chart-word-cloud": "workspace:*",
"@superset-ui/switchboard": "workspace:*",
"@types/d3-format": "^3.0.1",
"@types/d3-selection": "^3.0.11",
"@types/d3-time-format": "^4.0.3",
@@ -165,7 +172,7 @@
"dom-to-image-more": "^3.7.2",
"dom-to-pdf": "^0.3.2",
"echarts": "^5.6.0",
"eslint-plugin-i18n-strings": "file:eslint-rules/eslint-plugin-i18n-strings",
"eslint-plugin-i18n-strings": "workspace:*",
"fast-glob": "^3.3.2",
"fs-extra": "^11.3.3",
"fuse.js": "^7.1.0",
@@ -187,11 +194,11 @@
"markdown-to-jsx": "^9.7.3",
"match-sorter": "^6.3.4",
"memoize-one": "^5.2.1",
"pretty-ms": "^9.3.0",
"mousetrap": "^1.6.5",
"mustache": "^4.2.0",
"nanoid": "^5.1.6",
"ol": "^7.5.2",
"pretty-ms": "^9.3.0",
"query-string": "9.3.1",
"re-resizable": "^6.11.2",
"react": "^17.0.2",
@@ -252,6 +259,8 @@
"@babel/runtime": "^7.28.6",
"@babel/runtime-corejs3": "^7.29.0",
"@babel/types": "^7.28.6",
"@changesets/changelog-github": "^0.5.2",
"@changesets/cli": "^2.29.8",
"@cypress/react": "^8.0.2",
"@emotion/babel-plugin": "^11.13.5",
"@emotion/jest": "^11.14.2",
@@ -280,12 +289,22 @@
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^12.8.3",
"@types/content-disposition": "^0.5.9",
"@types/d3-array": "^3.2.2",
"@types/d3-cloud": "^1.2.9",
"@types/d3-color": "^3.1.3",
"@types/d3-hierarchy": "^3.1.7",
"@types/d3-interpolate": "^3.0.4",
"@types/d3-scale": "^4.0.9",
"@types/d3-time": "^3.0.4",
"@types/dom-to-image": "^2.6.7",
"@types/jest": "^30.0.0",
"@types/jquery": "^3.5.33",
"@types/js-levenshtein": "^1.1.3",
"@types/json-bigint": "^1.0.4",
"@types/lodash": "^4.17.23",
"@types/mousetrap": "^1.6.15",
"@types/node": "^25.2.2",
"@types/prop-types": "^15.7.15",
"@types/react": "^17.0.83",
"@types/react-dom": "^17.0.26",
"@types/react-loadable": "^5.5.11",
@@ -296,9 +315,11 @@
"@types/react-window": "^1.8.8",
"@types/redux-localstorage": "^1.0.8",
"@types/redux-mock-store": "^1.0.6",
"@types/react-table": "^7.7.20",
"@types/rison": "0.1.0",
"@types/tinycolor2": "^1.4.3",
"@types/unzipper": "^0.10.11",
"@types/urijs": "^1.19.26",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"babel-jest": "^30.0.2",
@@ -319,7 +340,7 @@
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-cypress": "^3.6.0",
"eslint-plugin-file-progress": "^1.5.0",
"eslint-plugin-icons": "file:eslint-rules/eslint-plugin-icons",
"eslint-plugin-icons": "workspace:*",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jest-dom": "^5.5.0",
"eslint-plugin-jsx-a11y": "^6.4.1",
@@ -331,7 +352,7 @@
"eslint-plugin-react-you-might-not-need-an-effect": "^0.8.5",
"eslint-plugin-storybook": "^0.8.0",
"eslint-plugin-testing-library": "^7.15.4",
"eslint-plugin-theme-colors": "file:eslint-rules/eslint-plugin-theme-colors",
"eslint-plugin-theme-colors": "workspace:*",
"fetch-mock": "^12.6.0",
"fork-ts-checker-webpack-plugin": "^9.1.0",
"history": "^5.3.0",
@@ -344,7 +365,6 @@
"jest-websocket-mock": "^2.5.0",
"js-yaml-loader": "^1.2.2",
"jsdom": "^28.0.0",
"lerna": "^8.2.3",
"lightningcss": "^1.31.1",
"mini-css-extract-plugin": "^2.10.0",
"open-cli": "^8.0.0",
@@ -363,10 +383,10 @@
"style-loader": "^4.0.0",
"swc-loader": "^0.2.7",
"terser-webpack-plugin": "^5.3.16",
"thread-loader": "^4.0.4",
"ts-jest": "^29.4.6",
"tscw-config": "^1.1.2",
"tsx": "^4.21.0",
"turbo": "^2.8.4",
"typescript": "5.4.5",
"unzipper": "^0.12.3",
"vm-browserify": "^1.1.2",

View File

@@ -47,7 +47,7 @@
"scripts": {
"clean": "rm -rf lib tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type": "npx tsc --noEmit"
"type-check": "npx tsc --noEmit"
},
"publishConfig": {
"access": "public"

View File

@@ -18,7 +18,7 @@
*/
import userEvent from '@testing-library/user-event';
import { ReactElement } from 'react';
import { render, RenderOptions } from '@testing-library/react';
import { render, RenderOptions, RenderResult } from '@testing-library/react';
import '@testing-library/jest-dom';
import { themeObject } from './theme';
@@ -33,7 +33,7 @@ const Providers = ({ children }: { children: React.ReactNode }) => (
const customRender = (
ui: ReactElement,
options?: Omit<RenderOptions, 'wrapper'>,
) => render(ui, { wrapper: Providers, ...options });
): RenderResult => render(ui, { wrapper: Providers, ...options });
export {
createEvent,

View File

@@ -47,5 +47,10 @@
},
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -131,5 +131,10 @@
"require": "./lib/utils/*.js",
"types": "./lib/utils/*.d.ts"
}
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -17,6 +17,7 @@
* under the License.
*/
import { DatePicker as AntdDatePicker } from 'antd';
import type { FC } from 'react';
import { css } from '@apache-superset/core/ui';
import type { DatePickerProps, RangePickerProps } from './types';
@@ -29,6 +30,8 @@ export const DatePicker = (props: DatePickerProps) => (
/>
);
export const { RangePicker } = AntdDatePicker;
// Explicitly typed to avoid TS2742 with Bun's module resolution
export const RangePicker: FC<RangePickerProps> =
AntdDatePicker.RangePicker as FC<RangePickerProps>;
export type { DatePickerProps, RangePickerProps };

View File

@@ -34,7 +34,7 @@ interface SafeMarkdownProps {
export function getOverrideHtmlSchema(
originalSchema: typeof defaultSchema,
htmlSchemaOverrides: SafeMarkdownProps['htmlSchemaOverrides'],
) {
): typeof defaultSchema {
return mergeWith(originalSchema, htmlSchemaOverrides, (objValue, srcValue) =>
Array.isArray(objValue) ? objValue.concat(srcValue) : undefined,
);

View File

@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import type { FC } from 'react';
import type { ComponentType, FC } from 'react';
import { css, styled, useTheme } from '@apache-superset/core/ui';
// eslint-disable-next-line no-restricted-imports
@@ -30,6 +30,21 @@ export interface TabsProps extends AntdTabsProps {
contentStyle?: SerializedStyles;
}
// Type for TabPane to avoid TS2742 with Bun's module resolution
// Using a broader type to accommodate all TabPane props (tab, key, closeIcon, etc.)
type TabPaneProps = {
tab?: React.ReactNode;
key?: string;
closeIcon?: React.ReactNode;
disabled?: boolean;
forceRender?: boolean;
closable?: boolean;
children?: React.ReactNode;
};
type TabPaneType = ComponentType<TabPaneProps> & {
defaultProps?: Partial<TabPaneProps>;
};
const StyledTabs = ({
animated = false,
allowOverflow = true,
@@ -93,11 +108,14 @@ const StyledTabs = ({
);
};
const StyledTabPane = styled(AntdTabs.TabPane)``;
const StyledTabPane: TabPaneType = styled(AntdTabs.TabPane)``;
const Tabs = Object.assign(StyledTabs, {
TabPane: StyledTabPane,
});
const Tabs: FC<TabsProps> & { TabPane: TabPaneType } = Object.assign(
StyledTabs,
{
TabPane: StyledTabPane,
},
);
const StyledEditableTabs = styled(StyledTabs)`
${({ theme, contentStyle }) => `
@@ -121,9 +139,10 @@ const StyledEditableTabs = styled(StyledTabs)`
const StyledCloseOutlined = styled(Icons.CloseOutlined)`
color: ${({ theme }) => theme.colorIcon};
`;
export const EditableTabs = Object.assign(StyledEditableTabs, {
TabPane: StyledTabPane,
});
export const EditableTabs: FC<TabsProps> & { TabPane: TabPaneType } =
Object.assign(StyledEditableTabs, {
TabPane: StyledTabPane,
});
EditableTabs.defaultProps = {
type: 'editable-card',
@@ -163,7 +182,7 @@ export const StyledLineEditableTabs = styled(EditableTabs)`
`;
export const LineEditableTabs: FC<TabsProps> & {
TabPane: typeof StyledTabPane;
TabPane: TabPaneType;
} = Object.assign(StyledLineEditableTabs, {
TabPane: StyledTabPane,
});

View File

@@ -18,7 +18,7 @@
*/
import userEvent from '@testing-library/user-event';
import { ReactElement } from 'react';
import { render, RenderOptions } from '@testing-library/react';
import { render, RenderOptions, RenderResult } from '@testing-library/react';
import '@testing-library/jest-dom';
import { themeObject } from '@apache-superset/core/ui';
@@ -33,7 +33,7 @@ const AllTheProviders = ({ children }: { children: React.ReactNode }) => (
const customRender = (
ui: ReactElement,
options?: Omit<RenderOptions, 'wrapper'>,
) => render(ui, { wrapper: AllTheProviders, ...options });
): RenderResult => render(ui, { wrapper: AllTheProviders, ...options });
export {
createEvent,

View File

@@ -30,5 +30,10 @@
"homepage": "https://github.com/apache/superset#readme",
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -37,5 +37,10 @@
},
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -37,5 +37,10 @@
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"@apache-superset/core": "*"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -35,5 +35,10 @@
"@superset-ui/chart-controls": "*",
"@superset-ui/core": "*",
"react": "^17.0.2"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -35,5 +35,10 @@
},
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -40,5 +40,10 @@
},
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -35,5 +35,10 @@
},
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -37,5 +37,10 @@
"@superset-ui/core": "*",
"@apache-superset/core": "*",
"react": "^17.0.2"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -38,5 +38,10 @@
},
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -36,5 +36,10 @@
},
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -40,5 +40,10 @@
"@superset-ui/core": "*",
"@apache-superset/core": "*",
"react": "^17.0.2"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -72,5 +72,10 @@
},
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -24,6 +24,7 @@ import {
JsonObject,
QueryFormData,
} from '@superset-ui/core';
import type { ScaleLinear } from 'd3-scale';
import { isPointInBonds } from '../../utilities/utils';
import { commonLayerProps, getColorRange } from '../common';
import sandboxedEval from '../../utils/sandbox';
@@ -122,7 +123,9 @@ export const getLayer: GetLayerType<HeatmapLayer> = ({
const colorScale = getSequentialSchemeRegistry()
?.get(colorScheme)
?.createLinearScale([0, 6]);
?.createLinearScale([0, 6]) as
| ScaleLinear<string, string, never>
| undefined;
const colorSchemeType = fd.color_scheme_type;
const colorRange = getColorRange({

View File

@@ -234,7 +234,7 @@ export const getColorRange = ({
defaultBreakpointsColor: { r: number; g: number; b: number; a: number };
fixedColor?: { r: number; g: number; b: number; a: number };
colorBreakpoints?: ColorBreakpointType[];
colorScale?: CategoricalColorScale | ScaleLinear<string, string>;
colorScale?: CategoricalColorScale | ScaleLinear<string, string, never>;
}) => {
let colorRange: Color[] | undefined;
switch (colorSchemeType) {

View File

@@ -142,7 +142,9 @@ export function getBreakPointColorScaler(
if (!colorScheme) {
return () => TRANSPARENT_COLOR_ARRAY;
}
let scaler: ScaleLinear<string, string> | ScaleThreshold<number, string>;
let scaler:
| ScaleLinear<string, string, never>
| ScaleThreshold<number, string, never>;
let maskPoint: (v: number | undefined) => boolean;
if (breakPoints !== null) {
// bucket colors into discrete colors
@@ -170,11 +172,15 @@ export function getBreakPointColorScaler(
// interpolate colors linearly
const linearScaleDomain = extent(features, accessor);
if (!linearScaleDomain.some(i => typeof i === 'number')) {
scaler = colorScheme.createLinearScale();
scaler = colorScheme.createLinearScale() as ScaleLinear<
string,
string,
never
>;
} else {
scaler = colorScheme.createLinearScale(
extent(features, accessor) as number[],
);
) as ScaleLinear<string, string, never>;
}
maskPoint = () => false;
}

View File

@@ -44,5 +44,10 @@
"@superset-ui/core": "*",
"dayjs": "^1.11.19",
"react": "^17.0.2"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -52,5 +52,10 @@
},
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -49,5 +49,10 @@
"polished": "*",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -40,5 +40,10 @@
},
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -46,5 +46,10 @@
"@types/jest": "^30.0.0",
"@types/lodash": "^4.17.23",
"jest": "^30.2.0"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -41,5 +41,10 @@
"@babel/types": "^7.29.0",
"@types/jest": "^30.0.0",
"jest": "^30.2.0"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -52,5 +52,10 @@
},
"publishConfig": {
"access": "public"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -43,5 +43,10 @@
},
"devDependencies": {
"@types/d3-cloud": "^1.2.9"
},
"scripts": {
"clean": "rm -rf lib esm tsconfig.tsbuildinfo",
"build": "npm run clean && npx tsc --build",
"type-check": "npx tsc --noEmit"
}
}

View File

@@ -1,129 +0,0 @@
#!/bin/env node
/*
* 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.
*/
/* eslint-disable no-console */
/**
* Build packages/plugins filtered by globs
*/
process.env.PATH = `./node_modules/.bin:${process.env.PATH}`;
const { spawnSync } = require('child_process');
const fastGlob = require('fast-glob');
const { argv } = require('yargs');
const { _: globs } = argv;
const glob = globs.length > 1 ? `{${globs.join(',')}}` : globs[0] || '*';
const BABEL_CONFIG = '--config-file=../../babel.config.js';
// packages that do not need tsc
const META_PACKAGES = new Set(['demo', 'generator-superset']);
function run(cmd, options) {
console.log(`\n>> ${cmd}\n`);
const [p, ...args] = cmd.split(' ');
const runner = spawnSync;
const { status } = runner(p, args, { stdio: 'inherit', ...options });
if (status !== 0) {
process.exit(status);
}
}
function getPackages(packagePattern, tsOnly = false) {
let pattern = packagePattern;
if (pattern === '*' && !tsOnly) {
return `{@superset-ui/!(${[...META_PACKAGES].join('|')}),@apache-superset/*}`;
}
if (!pattern.includes('*')) {
pattern = `*${pattern}`;
}
// Find packages in both @superset-ui and @apache-superset scopes
const supersetUiPackages = [
...new Set(
fastGlob
.sync([
`./node_modules/@superset-ui/${pattern}/src/**/*.${
tsOnly ? '{ts,tsx}' : '{ts,tsx,js,jsx}'
}`,
])
.map(x => x.split('/')[3])
.filter(x => !META_PACKAGES.has(x)),
),
];
const apachePackages = [
...new Set(
fastGlob
.sync([
`./node_modules/@apache-superset/${pattern}/src/**/*.${
tsOnly ? '{ts,tsx}' : '{ts,tsx,js,jsx}'
}`,
])
.map(x => x.split('/')[3]),
),
];
const allScopes = [];
if (supersetUiPackages.length > 0) {
allScopes.push(
`@superset-ui/${
supersetUiPackages.length > 1
? `{${supersetUiPackages.join(',')}}`
: supersetUiPackages[0]
}`,
);
}
if (apachePackages.length > 0) {
allScopes.push(
`@apache-superset/${
apachePackages.length > 1
? `{${apachePackages.join(',')}}`
: apachePackages[0]
}`,
);
}
if (allScopes.length === 0) {
throw new Error('No matching packages');
}
return allScopes.length > 1 ? `{${allScopes.join(',')}}` : allScopes[0];
}
let scope = getPackages(glob);
console.log('--- Run babel --------');
const babelCommand = `lerna exec --stream --concurrency 10 --scope ${scope}
-- babel ${BABEL_CONFIG} src --extensions ".ts,.tsx,.js,.jsx" --copy-files`;
run(`${babelCommand} --out-dir lib`);
console.log('--- Run babel esm ---');
// run again with
run(`${babelCommand} --out-dir esm`, {
env: { ...process.env, NODE_ENV: 'production', BABEL_OUTPUT: 'esm' },
});
console.log('--- Run tsc ---');
// only run tsc for packages with ts files
scope = getPackages(glob, true);
run(`lerna exec --stream --concurrency 3 --scope ${scope} \
-- ../../scripts/tsc.sh --build`);

View File

@@ -1,67 +0,0 @@
#!/bin/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.
rootDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )"
lernaVersionArg="$1"
if [[ -z $lernaVersionArg ]]; then
echo '[ERROR] Please provide argument for "lerna version".'
exit 1
fi
currentNpm=$(npm --version)
npmVersion=$(node -e "process.stdout.write(require('./package.json').engines.npm)");
isSatisfiedNpm=$(node -e "process.stdout.write(require('semver').satisfies('$currentNpm', '$npmVersion').toString())");
currentNode=$(node --version)
nodeVersion=$(node -e "process.stdout.write(require('./package.json').engines.node)");
isSatisfiedNode=$(node -e "process.stdout.write(require('semver').satisfies('$currentNode', '$nodeVersion').toString())");
# Check node version compatible with package.json
if [[ $isSatisfiedNode != 'true' ]]; then
echo "[ERROR] Your node version($currentNode) is not compatible with package.json($nodeVersion)"
exit 1
fi
# Check npm version compatible with package.json
if [[ $isSatisfiedNpm != 'true' ]]; then
echo "[ERROR] Your npm version($currentNpm) is not compatible with package.json($npmVersion)"
exit 1
fi
# Ignore Lerna's tag and push
lerna version $1 --no-push --no-git-tag-version --yes
if [[ -z $(git diff --stat) ]]; then
echo '[ERROR] No changed packages to version.'
exit 1
fi
# Get the current tag version
tag=v$(node -e "process.stdout.write(require('./lerna.json').version)");
message="chore(plugins): publish $tag"
if [[ $? -ne 0 ]]; then
echo '[ERROR] Can not update package-lock.json'
exit 1
fi
# Auto-tag and auto-commit like usual
git commit --all -m "${message}"
git tag -a ${tag} -m ${tag}
git push origin ${tag}
git push

View File

@@ -0,0 +1,167 @@
#!/usr/bin/env node
/*
* 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.
*/
/**
* Sync all publishable package versions to a specific version.
* Used during Superset releases to align npm package versions.
*
* Usage:
* node scripts/sync-package-versions.js <version>
* node scripts/sync-package-versions.js 6.1.0
* node scripts/sync-package-versions.js 6.1.0-rc.1
* node scripts/sync-package-versions.js 6.1.0 --dry-run
*/
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const args = process.argv.slice(2);
const dryRun = args.includes('--dry-run');
const version = args.find(arg => !arg.startsWith('--'));
if (!version) {
console.error(
'Usage: node scripts/sync-package-versions.js <version> [--dry-run]',
);
console.error('Example: node scripts/sync-package-versions.js 6.1.0');
console.error(
'Example: node scripts/sync-package-versions.js 6.1.0-rc.1 --dry-run',
);
process.exit(1);
}
// Validate version format (semver with optional prerelease)
const semverRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$/;
if (!semverRegex.test(version)) {
console.error(`Invalid version format: ${version}`);
console.error(
'Expected format: MAJOR.MINOR.PATCH or MAJOR.MINOR.PATCH-prerelease',
);
process.exit(1);
}
const rootDir = path.resolve(__dirname, '..');
// Find all publishable packages (those with "private": false or no "private" field)
// Exclude demo and generator packages per changeset config
const excludePackages = new Set([
'@superset-ui/demo',
'@superset-ui/generator-superset',
]);
function findPackages() {
const packages = [];
// Check packages directory
const packagesDir = path.join(rootDir, 'packages');
if (fs.existsSync(packagesDir)) {
for (const dir of fs.readdirSync(packagesDir)) {
const pkgPath = path.join(packagesDir, dir, 'package.json');
if (fs.existsSync(pkgPath)) {
packages.push(pkgPath);
}
}
}
// Check plugins directory
const pluginsDir = path.join(rootDir, 'plugins');
if (fs.existsSync(pluginsDir)) {
for (const dir of fs.readdirSync(pluginsDir)) {
const pkgPath = path.join(pluginsDir, dir, 'package.json');
if (fs.existsSync(pkgPath)) {
packages.push(pkgPath);
}
}
}
return packages;
}
function updatePackage(pkgPath, newVersion) {
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
// Skip private packages
if (pkg.private === true) {
return { skipped: true, reason: 'private', name: pkg.name };
}
// Skip excluded packages
if (excludePackages.has(pkg.name)) {
return { skipped: true, reason: 'excluded', name: pkg.name };
}
const oldVersion = pkg.version;
pkg.version = newVersion;
if (!dryRun) {
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
}
return {
skipped: false,
name: pkg.name,
oldVersion,
newVersion,
path: pkgPath,
};
}
console.log(
`\n${dryRun ? '[DRY RUN] ' : ''}Syncing package versions to ${version}\n`,
);
const packages = findPackages();
const results = packages.map(pkgPath => updatePackage(pkgPath, version));
// Print results
console.log('Updated packages:');
results
.filter(r => !r.skipped)
.forEach(r => {
console.log(` ${r.name}: ${r.oldVersion} -> ${r.newVersion}`);
});
console.log('\nSkipped packages:');
results
.filter(r => r.skipped)
.forEach(r => {
console.log(` ${r.name} (${r.reason})`);
});
const updatedCount = results.filter(r => !r.skipped).length;
console.log(
`\n${dryRun ? 'Would update' : 'Updated'} ${updatedCount} packages.`,
);
if (dryRun) {
console.log('\nRun without --dry-run to apply changes.');
} else {
console.log('\nNext steps:');
console.log(' 1. Review changes: git diff');
console.log(
' 2. Commit: git add . && git commit -m "chore(packages): bump versions to ' +
version +
'"',
);
console.log(' 3. Dry run publish: bun run publish:packages:dry');
console.log(' 4. Publish: bun run publish:packages');
}

View File

@@ -0,0 +1,64 @@
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"@superset-ui/core#build": {
"dependsOn": [],
"inputs": ["src/**", "package.json", "tsconfig.json", "tsconfig.*.json"],
"outputs": ["lib/**", "esm/**", "dist/**", "tsconfig.tsbuildinfo"],
"cache": true
},
"@apache-superset/core#build": {
"dependsOn": [],
"inputs": ["src/**", "package.json", "tsconfig.json", "tsconfig.*.json"],
"outputs": ["lib/**", "esm/**", "dist/**", "tsconfig.tsbuildinfo"],
"cache": true
},
"@superset-ui/chart-controls#build": {
"dependsOn": ["@superset-ui/core#build", "@apache-superset/core#build"],
"inputs": ["src/**", "package.json", "tsconfig.json", "tsconfig.*.json"],
"outputs": ["lib/**", "esm/**", "dist/**", "tsconfig.tsbuildinfo"],
"cache": true
},
"build": {
"dependsOn": ["@superset-ui/core#build", "@apache-superset/core#build", "@superset-ui/chart-controls#build", "^build"],
"inputs": ["src/**", "package.json", "tsconfig.json", "tsconfig.*.json"],
"outputs": ["lib/**", "esm/**", "dist/**", "tsconfig.tsbuildinfo"],
"cache": true
},
"build:esm": {
"dependsOn": ["^build:esm"],
"inputs": ["src/**", "package.json", "tsconfig.json"],
"outputs": ["esm/**"],
"cache": true
},
"build:cjs": {
"dependsOn": ["^build:cjs"],
"inputs": ["src/**", "package.json", "tsconfig.json"],
"outputs": ["lib/**"],
"cache": true
},
"type-check": {
"dependsOn": ["^build"],
"inputs": ["src/**", "*.ts", "*.tsx", "tsconfig.json"],
"outputs": [],
"cache": true
},
"lint": {
"inputs": ["src/**", "*.ts", "*.tsx", "*.js", "*.jsx"],
"outputs": [],
"cache": true
},
"test": {
"dependsOn": ["^build"],
"inputs": ["src/**", "test/**", "spec/**", "**/*.test.*", "**/*.spec.*"],
"outputs": ["coverage/**"],
"cache": true
},
"clean": {
"cache": false
}
},
"ui": "tui",
"daemon": true,
"cacheDir": ".turbo"
}

View File

@@ -235,6 +235,16 @@ if (!isDevMode) {
},
},
},
// Filter out errors from test files during production builds
issue: {
exclude: [
{ file: '**/*.test.ts' },
{ file: '**/*.test.tsx' },
{ file: '**/spec/**' },
{ file: '**/__tests__/**' },
{ file: '**/__mocks__/**' },
],
},
}),
);
}
@@ -489,7 +499,7 @@ const config = {
},
},
{
test: /node_modules\/(geostyler-style|geostyler-qgis-parser)\/.*\.js$/,
test: /node_modules\/(geostyler-style|geostyler-qgis-parser|geostyler-cql-parser)\/.*\.js$/,
resolve: {
fullySpecified: false,
},
@@ -497,10 +507,7 @@ const config = {
{
test: /\.tsx?$/,
exclude: [/\.test.tsx?$/, /node_modules/],
// Skip thread-loader in dev mode - it breaks HMR by running in worker threads
use: isDevMode
? [createSwcLoader('typescript', true)]
: ['thread-loader', createSwcLoader('typescript', true)],
use: [createSwcLoader('typescript', true)],
},
{
test: /\.jsx?$/,

View File

@@ -1,27 +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.
*/
// Minimal service worker for PWA file handling support
self.addEventListener('install', event => {
event.waitUntil(self.skipWaiting());
});
self.addEventListener('activate', event => {
event.waitUntil(self.clients.claim());
});
(()=>{"use strict";let e;var r,t,o,n,a,i,l,f,u,s,p,d,c,v,h,g,y={74068(){self.addEventListener("install",e=>{e.waitUntil(self.skipWaiting())}),self.addEventListener("activate",e=>{e.waitUntil(self.clients.claim())})}},b={};function O(e){var r=b[e];if(void 0!==r)return r.exports;var t=b[e]={id:e,loaded:!1,exports:{}};return y[e].call(t.exports,t,t.exports,O),t.loaded=!0,t.exports}O.m=y,O.c=b,r=[],O.O=(e,t,o,n)=>{if(t){n=n||0;for(var a=r.length;a>0&&r[a-1][2]>n;a--)r[a]=r[a-1];r[a]=[t,o,n];return}for(var i=1/0,a=0;a<r.length;a++){for(var[t,o,n]=r[a],l=!0,f=0;f<t.length;f++)(!1&n||i>=n)&&Object.keys(O.O).every(e=>O.O[e](t[f]))?t.splice(f--,1):(l=!1,n<i&&(i=n));if(l){r.splice(a--,1);var u=o();void 0!==u&&(e=u)}}return e},O.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return O.d(r,{a:r}),r},o=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,O.t=function(e,r){if(1&r&&(e=this(e)),8&r||"object"==typeof e&&e&&(4&r&&e.__esModule||16&r&&"function"==typeof e.then))return e;var n=Object.create(null);O.r(n);var a={};t=t||[null,o({}),o([]),o(o)];for(var i=2&r&&e;("object"==typeof i||"function"==typeof i)&&!~t.indexOf(i);i=o(i))Object.getOwnPropertyNames(i).forEach(r=>a[r]=()=>e[r]);return a.default=()=>e,O.d(n,a),n},O.d=(e,r)=>{for(var t in r)O.o(r,t)&&!O.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},O.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),O.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},O.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),O.S={},n={},a={},O.I=(e,r)=>{r||(r=[]);var t=a[e];if(t||(t=a[e]={}),!(r.indexOf(t)>=0)){if(r.push(t),n[e])return n[e];O.o(O.S,e)||(O.S[e]={});var o=O.S[e],i="superset",l=(e,r,t,n)=>{var a=o[e]=o[e]||{},l=a[r];(!l||!l.loaded&&(!n!=!l.eager?n:i>l.from))&&(a[r]={get:t,from:i,eager:!!n})},f=[];return("default"===e&&(l("antd","5.29.3",()=>()=>O(27901),1),l("react-dom","17.0.2",()=>()=>O(67319),1),l("react","17.0.2",()=>()=>O(11979),1)),f.length)?n[e]=Promise.all(f).then(()=>n[e]=1):n[e]=1}},i=e=>{var r=e=>e.split(".").map(e=>+e==e?+e:e),t=/^([^-+]+)?(?:-([^+]+))?(?:\+(.+))?$/.exec(e),o=t[1]?r(t[1]):[];return t[2]&&(o.length++,o.push.apply(o,r(t[2]))),t[3]&&(o.push([]),o.push.apply(o,r(t[3]))),o},l=(e,r)=>{e=i(e),r=i(r);for(var t=0;;){if(t>=e.length)return t<r.length&&"u"!=(typeof r[t])[0];var o=e[t],n=(typeof o)[0];if(t>=r.length)return"u"==n;var a=r[t],l=(typeof a)[0];if(n!=l)return"o"==n&&"n"==l||"s"==l||"u"==n;if("o"!=n&&"u"!=n&&o!=a)return o<a;t++}},f=e=>{var r=e[0],t="";if(1===e.length)return"*";if(r+.5){t+=0==r?">=":-1==r?"<":1==r?"^":2==r?"~":r>0?"=":"!=";for(var o=1,n=1;n<e.length;n++)o--,t+="u"==(typeof(i=e[n]))[0]?"-":(o>0?".":"")+(o=2,i);return t}var a=[];for(n=1;n<e.length;n++){var i=e[n];a.push(0===i?"not("+l()+")":1===i?"("+l()+" || "+l()+")":2===i?a.pop()+" "+a.pop():f(i))}return l();function l(){return a.pop().replace(/^\((.+)\)$/,"$1")}},u=(e,r)=>{if(0 in e){r=i(r);var t=e[0],o=t<0;o&&(t=-t-1);for(var n=0,a=1,l=!0;;a++,n++){var f,s,p=a<e.length?(typeof e[a])[0]:"";if(n>=r.length||"o"==(s=(typeof(f=r[n]))[0]))return!l||("u"==p?a>t&&!o:""==p!=o);if("u"==s){if(!l||"u"!=p)return!1}else if(l)if(p==s)if(a<=t){if(f!=e[a])return!1}else{if(o?f>e[a]:f<e[a])return!1;f!=e[a]&&(l=!1)}else if("s"!=p&&"n"!=p){if(o||a<=t)return!1;l=!1,a--}else{if(a<=t||s<p!=o)return!1;l=!1}else"s"!=p&&"n"!=p&&(l=!1,a--)}}var d=[],c=d.pop.bind(d);for(n=1;n<e.length;n++){var v=e[n];d.push(1==v?c()|c():2==v?c()&c():v?u(v,r):!c())}return!!c()},s=e=>Object.keys(e).reduce((r,t)=>(e[t].eager&&(r[t]=e[t]),r),{}),e=(e,r,t,o,n,a)=>{if(!((e,r)=>e&&O.o(e,r))(r,t))return((e,r,t)=>t?t():(e=>{throw Error(e)})("Shared module "+r+" doesn't exist in shared scope "+e))(e,t,a);var i=((e,r,t)=>{var o=t?s(e[r]):e[r];return Object.keys(o).reduce((e,r)=>!e||!o[e].loaded&&l(e,r)?r:e,0)})(r,t,o);return u(n,i)||(e=>{"u">typeof console&&console.warn&&console.warn(e)})(((e,r,t,o)=>"Unsatisfied version "+t+" from "+(t&&e[r][t].from)+" of shared singleton module "+r+" (required "+f(o)+")")(r,t,i,n)),(e=>(e.loaded=1,e.get()))(r[t][i])},p=function(r,t,o,n,a){var i=O.I(r);return i&&i.then&&!o?i.then(e.bind(e,r,O.S[r],t,!1,n,a)):e(r,O.S[r],t,o,n,a)},d={},c={52485:()=>p("default","react",!0,[1,17,0,2],()=>()=>O(11979)),92366:()=>p("default","react-dom",!0,[1,17,0,2],()=>()=>O(67319))},[52485,92366].forEach(e=>{O.m[e]=r=>{d[e]=0,delete O.c[e];var t=c[e]();if("function"!=typeof t)throw Error("Shared module is not available for eager consumption: "+e);r.exports=t()}}),v={2771:0,7084:0},O.O.j=e=>0===v[e],h=(e,r)=>{var t,o,[n,a,i]=r,l=0;if(n.some(e=>0!==v[e])){for(t in a)O.o(a,t)&&(O.m[t]=a[t]);if(i)var f=i(O)}for(e&&e(r);l<n.length;l++)o=n[l],O.o(v,o)&&v[o]&&v[o][0](),v[o]=0;return O.O(f)},(g=globalThis.webpackChunksuperset=globalThis.webpackChunksuperset||[]).forEach(h.bind(null,0)),g.push=h.bind(null,g.push.bind(g));var m=O.O(void 0,[8096,6578,7084],()=>O(74068));m=O.O(m)})();