This is an automated email from the ASF dual-hosted git repository. rusackas pushed a commit to branch feat/docs-component-index-and-build-perf in repository https://gitbox.apache.org/repos/asf/superset.git
commit 5b6f116cb4c7487474e83414a8692f25d6f3ca7f Author: Evan Rusackas <[email protected]> AuthorDate: Wed Feb 25 09:58:02 2026 -0800 feat(docs): add filterable UI Components table and improve build performance - Add interactive ComponentIndex table with stats cards, search, category filters, and sortable columns (modeled after DatabaseIndex) - Consolidate extension components into main generator, eliminating the separate generate-extension-components job - Enable Docusaurus Faster (Rspack bundler, SWC, SSG worker threads, persistent cache) for significantly improved build performance - Add smart generator caching (generate-if-changed.mjs) that skips unchanged generators in ~45ms, making `yarn start` as fast as `yarn start:quick` when no source files have changed - Inline per-page database data in generated MDX to reduce webpack module graph size during SSR - Remove unused babel.config.js (SWC handles transpilation) - Remove redundant webpack filesystem cache (Rspack handles caching) - Remove DEBUG=docusaurus:* from build script Co-Authored-By: Claude Sonnet 4.6 <[email protected]> --- docs/.gitignore | 3 + docs/developer_portal/extensions/development.md | 2 +- docs/developer_portal/extensions/overview.md | 4 + docs/docs/api.mdx | 36 +- docs/docusaurus.config.ts | 10 + docs/package.json | 11 +- docs/scripts/generate-database-docs.mjs | 8 +- docs/scripts/generate-extension-components.mjs | 31 +- docs/scripts/generate-if-changed.mjs | 306 ++++++++++++++++ docs/scripts/generate-superset-components.mjs | 211 +++++++++-- docs/sidebarTutorials.js | 11 - docs/src/components/databases/DatabaseIndex.tsx | 1 + .../components/ui-components/ComponentIndex.tsx | 262 ++++++++++++++ .../components/ui-components/index.ts} | 15 +- .../ui-components/types.ts} | 37 +- docs/src/data/databases.json | 2 +- docs/src/types/apache-superset-core/index.d.ts | 4 +- docs/src/webpack.extend.ts | 6 - docs/tsconfig.json | 2 +- docs/yarn.lock | 395 ++++++++++++++++++++- 20 files changed, 1236 insertions(+), 121 deletions(-) diff --git a/docs/.gitignore b/docs/.gitignore index 37df51ce524..ca7a95ebf9c 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -44,3 +44,6 @@ developer_portal/extensions/components/ # Note: src/data/databases.json is COMMITTED (not ignored) to preserve feature diagnostics # that require Flask context to generate. Update it locally with: npm run gen-db-docs + +# Generated component metadata JSON (regenerated by generate-superset-components.mjs) +static/data/components.json diff --git a/docs/developer_portal/extensions/development.md b/docs/developer_portal/extensions/development.md index a6c143a3796..80cf193ecb0 100644 --- a/docs/developer_portal/extensions/development.md +++ b/docs/developer_portal/extensions/development.md @@ -299,7 +299,7 @@ InteractiveMyComponent.argTypes = { When the docs site is built (`yarn start` or `yarn build` in the `docs/` directory): -1. The `generate-extension-components` script scans all stories in `superset-core` +1. The `generate-superset-components` script scans all stories (including `superset-core`) 2. For each story, it generates an MDX page with: - Component description - **Live interactive example** with controls extracted from `argTypes` diff --git a/docs/developer_portal/extensions/overview.md b/docs/developer_portal/extensions/overview.md index 175fa9701ca..be8628836d8 100644 --- a/docs/developer_portal/extensions/overview.md +++ b/docs/developer_portal/extensions/overview.md @@ -41,6 +41,10 @@ Extensions can provide: - **REST API Endpoints**: Backend services under the `/api/v1/extensions/` namespace - **MCP Tools and Prompts**: AI agent capabilities for enhanced user assistance +## UI Components for Extensions + +Extension developers have access to pre-built UI components via `@apache-superset/core/ui`. Browse all available components on the [UI Components](/docs/components/) page and filter by **Extension Compatible** to see components available to extensions. + ## Next Steps - **[Quick Start](./quick-start)** - Build your first extension with a complete walkthrough diff --git a/docs/docs/api.mdx b/docs/docs/api.mdx index ff563805a8e..09f3843087f 100644 --- a/docs/docs/api.mdx +++ b/docs/docs/api.mdx @@ -68,14 +68,14 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ | `POST` | [Create a new dashboard](./api/create-a-new-dashboard) | `/api/v1/dashboard/` | | `GET` | [Get metadata information about this API resource (dashboard--info)](./api/get-metadata-information-about-this-api-resource-dashboard-info) | `/api/v1/dashboard/_info` | | `GET` | [Get a dashboard detail information](./api/get-a-dashboard-detail-information) | `/api/v1/dashboard/{id_or_slug}` | -| `GET` | [Get a dashboard's chart definitions.](./api/get-a-dashboards-chart-definitions) | `/api/v1/dashboard/{id_or_slug}/charts` | +| `GET` | [Get a dashboard's chart definitions.](./api/get-a-dashboard-s-chart-definitions) | `/api/v1/dashboard/{id_or_slug}/charts` | | `POST` | [Create a copy of an existing dashboard](./api/create-a-copy-of-an-existing-dashboard) | `/api/v1/dashboard/{id_or_slug}/copy/` | -| `GET` | [Get dashboard's datasets](./api/get-dashboards-datasets) | `/api/v1/dashboard/{id_or_slug}/datasets` | -| `DELETE` | [Delete a dashboard's embedded configuration](./api/delete-a-dashboards-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` | -| `GET` | [Get the dashboard's embedded configuration](./api/get-the-dashboards-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` | -| `POST` | [Set a dashboard's embedded configuration](./api/set-a-dashboards-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` | +| `GET` | [Get dashboard's datasets](./api/get-dashboard-s-datasets) | `/api/v1/dashboard/{id_or_slug}/datasets` | +| `DELETE` | [Delete a dashboard's embedded configuration](./api/delete-a-dashboard-s-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` | +| `GET` | [Get the dashboard's embedded configuration](./api/get-the-dashboard-s-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` | +| `POST` | [Set a dashboard's embedded configuration](./api/set-a-dashboard-s-embedded-configuration) | `/api/v1/dashboard/{id_or_slug}/embedded` | | `PUT` | [Update dashboard by id_or_slug embedded](./api/update-dashboard-by-id-or-slug-embedded) | `/api/v1/dashboard/{id_or_slug}/embedded` | -| `GET` | [Get dashboard's tabs](./api/get-dashboards-tabs) | `/api/v1/dashboard/{id_or_slug}/tabs` | +| `GET` | [Get dashboard's tabs](./api/get-dashboard-s-tabs) | `/api/v1/dashboard/{id_or_slug}/tabs` | | `DELETE` | [Delete a dashboard](./api/delete-a-dashboard) | `/api/v1/dashboard/{pk}` | | `PUT` | [Update a dashboard](./api/update-a-dashboard) | `/api/v1/dashboard/{pk}` | | `POST` | [Compute and cache a screenshot (dashboard-pk-cache-dashboard-screenshot)](./api/compute-and-cache-a-screenshot-dashboard-pk-cache-dashboard-screenshot) | `/api/v1/dashboard/{pk}/cache_dashboard_screenshot/` | @@ -84,7 +84,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ | `POST` | [Mark the dashboard as favorite for the current user](./api/mark-the-dashboard-as-favorite-for-the-current-user) | `/api/v1/dashboard/{pk}/favorites/` | | `PUT` | [Update native filters configuration for a dashboard.](./api/update-native-filters-configuration-for-a-dashboard) | `/api/v1/dashboard/{pk}/filters` | | `GET` | [Get a computed screenshot from cache (dashboard-pk-screenshot-digest)](./api/get-a-computed-screenshot-from-cache-dashboard-pk-screenshot-digest) | `/api/v1/dashboard/{pk}/screenshot/{digest}/` | -| `GET` | [Get dashboard's thumbnail](./api/get-dashboards-thumbnail) | `/api/v1/dashboard/{pk}/thumbnail/{digest}/` | +| `GET` | [Get dashboard's thumbnail](./api/get-dashboard-s-thumbnail) | `/api/v1/dashboard/{pk}/thumbnail/{digest}/` | | `GET` | [Download multiple dashboards as YAML files](./api/download-multiple-dashboards-as-yaml-files) | `/api/v1/dashboard/export/` | | `GET` | [Check favorited dashboards for current user](./api/check-favorited-dashboards-for-current-user) | `/api/v1/dashboard/favorite_status/` | | `POST` | [Import dashboard(s) with associated charts/datasets/databases](./api/import-dashboard-s-with-associated-charts-datasets-databases) | `/api/v1/dashboard/import/` | @@ -177,7 +177,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ | `GET` | [Get names of databases currently available](./api/get-names-of-databases-currently-available) | `/api/v1/database/available/` | | `GET` | [Download database(s) and associated dataset(s) as a zip file](./api/download-database-s-and-associated-dataset-s-as-a-zip-file) | `/api/v1/database/export/` | | `POST` | [Import database(s) with associated datasets](./api/import-database-s-with-associated-datasets) | `/api/v1/database/import/` | -| `GET` | [Receive personal access tokens from OAuth2](./api/receive-personal-access-tokens-from-o-auth-2) | `/api/v1/database/oauth2/` | +| `GET` | [Receive personal access tokens from OAuth2](./api/receive-personal-access-tokens-from-oauth2) | `/api/v1/database/oauth2/` | | `GET` | [Get related fields data (database-related-column-name)](./api/get-related-fields-data-database-related-column-name) | `/api/v1/database/related/{column_name}` | | `POST` | [Test a database connection](./api/test-a-database-connection) | `/api/v1/database/test_connection/` | | `POST` | [Upload a file and returns file metadata](./api/upload-a-file-and-returns-file-metadata) | `/api/v1/database/upload_metadata/` | @@ -201,7 +201,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ | Method | Endpoint | Description | |--------|----------|-------------| -| `GET` | [Get the bootstrap data for SqlLab page](./api/get-the-bootstrap-data-for-sql-lab-page) | `/api/v1/sqllab/` | +| `GET` | [Get the bootstrap data for SqlLab page](./api/get-the-bootstrap-data-for-sqllab-page) | `/api/v1/sqllab/` | | `POST` | [Estimate the SQL query execution cost](./api/estimate-the-sql-query-execution-cost) | `/api/v1/sqllab/estimate/` | | `POST` | [Execute a SQL query](./api/execute-a-sql-query) | `/api/v1/sqllab/execute/` | | `GET` | [Export the SQL query results to a CSV](./api/export-the-sql-query-results-to-a-csv) | `/api/v1/sqllab/export/{client_id}/` | @@ -249,7 +249,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ | Method | Endpoint | Description | |--------|----------|-------------| -| `GET` | [Return an AdvancedDataTypeResponse](./api/return-an-advanced-data-type-response) | `/api/v1/advanced_data_type/convert` | +| `GET` | [Return an AdvancedDataTypeResponse](./api/return-an-advanceddatatyperesponse) | `/api/v1/advanced_data_type/convert` | | `GET` | [Return a list of available advanced data types](./api/return-a-list-of-available-advanced-data-types) | `/api/v1/advanced_data_type/types` | </details> @@ -324,8 +324,8 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ | Method | Endpoint | Description | |--------|----------|-------------| -| `POST` | [Create a new dashboard's permanent link](./api/create-a-new-dashboards-permanent-link) | `/api/v1/dashboard/{pk}/permalink` | -| `GET` | [Get dashboard's permanent link state](./api/get-dashboards-permanent-link-state) | `/api/v1/dashboard/permalink/{key}` | +| `POST` | [Create a new dashboard's permanent link](./api/create-a-new-dashboard-s-permanent-link) | `/api/v1/dashboard/{pk}/permalink` | +| `GET` | [Get dashboard's permanent link state](./api/get-dashboard-s-permanent-link-state) | `/api/v1/dashboard/permalink/{key}` | </details> @@ -335,7 +335,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ | Method | Endpoint | Description | |--------|----------|-------------| | `POST` | [Create a new permanent link (explore-permalink)](./api/create-a-new-permanent-link-explore-permalink) | `/api/v1/explore/permalink` | -| `GET` | [Get chart's permanent link state](./api/get-charts-permanent-link-state) | `/api/v1/explore/permalink/{key}` | +| `GET` | [Get chart's permanent link state](./api/get-chart-s-permanent-link-state) | `/api/v1/explore/permalink/{key}` | </details> @@ -345,7 +345,7 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ | Method | Endpoint | Description | |--------|----------|-------------| | `POST` | [Create a new permanent link (sqllab-permalink)](./api/create-a-new-permanent-link-sqllab-permalink) | `/api/v1/sqllab/permalink` | -| `GET` | [Get permanent link state for SQLLab editor.](./api/get-permanent-link-state-for-sql-lab-editor) | `/api/v1/sqllab/permalink/{key}` | +| `GET` | [Get permanent link state for SQLLab editor.](./api/get-permanent-link-state-for-sqllab-editor) | `/api/v1/sqllab/permalink/{key}` | </details> @@ -363,10 +363,10 @@ curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ | Method | Endpoint | Description | |--------|----------|-------------| -| `POST` | [Create a dashboard's filter state](./api/create-a-dashboards-filter-state) | `/api/v1/dashboard/{pk}/filter_state` | -| `DELETE` | [Delete a dashboard's filter state value](./api/delete-a-dashboards-filter-state-value) | `/api/v1/dashboard/{pk}/filter_state/{key}` | -| `GET` | [Get a dashboard's filter state value](./api/get-a-dashboards-filter-state-value) | `/api/v1/dashboard/{pk}/filter_state/{key}` | -| `PUT` | [Update a dashboard's filter state value](./api/update-a-dashboards-filter-state-value) | `/api/v1/dashboard/{pk}/filter_state/{key}` | +| `POST` | [Create a dashboard's filter state](./api/create-a-dashboard-s-filter-state) | `/api/v1/dashboard/{pk}/filter_state` | +| `DELETE` | [Delete a dashboard's filter state value](./api/delete-a-dashboard-s-filter-state-value) | `/api/v1/dashboard/{pk}/filter_state/{key}` | +| `GET` | [Get a dashboard's filter state value](./api/get-a-dashboard-s-filter-state-value) | `/api/v1/dashboard/{pk}/filter_state/{key}` | +| `PUT` | [Update a dashboard's filter state value](./api/update-a-dashboard-s-filter-state-value) | `/api/v1/dashboard/{pk}/filter_state/{key}` | </details> diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index 336b44d0edd..2af419a98f5 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -166,6 +166,16 @@ if (!versionsConfig.developer_portal.disabled && !versionsConfig.developer_porta } const config: Config = { + future: { + v4: { + // Required by experimental_faster.ssgWorkerThreads + removeLegacyPostBuildHeadAttribute: true, + // Disabled: CSS cascade layers change specificity and cause antd + // styles (from Storybook component pages) to override theme styles + useCssCascadeLayers: false, + }, + experimental_faster: true, + }, title: 'Superset', tagline: 'Apache Superset is a modern data exploration and visualization platform', diff --git a/docs/package.json b/docs/package.json index 484432a7666..9af70da940d 100644 --- a/docs/package.json +++ b/docs/package.json @@ -6,10 +6,12 @@ "scripts": { "docusaurus": "docusaurus", "_init": "cat src/intro_header.txt ../README.md > docs/intro.md", - "start": "yarn run _init && yarn run generate:all && NODE_OPTIONS='--max-old-space-size=8192' NODE_ENV=development docusaurus start", + "start": "yarn run _init && yarn run generate:smart && NODE_OPTIONS='--max-old-space-size=8192' NODE_ENV=development docusaurus start", "start:quick": "yarn run _init && NODE_OPTIONS='--max-old-space-size=8192' NODE_ENV=development docusaurus start", + "start:full": "yarn run _init && yarn run generate:all && NODE_OPTIONS='--max-old-space-size=8192' NODE_ENV=development docusaurus start", "stop": "pkill -f 'docusaurus start' || pkill -f 'docusaurus serve' || echo 'No docusaurus server running'", - "build": "yarn run _init && yarn run generate:all && NODE_OPTIONS='--max-old-space-size=8192' DEBUG=docusaurus:* docusaurus build", + "build": "yarn run _init && yarn run generate:smart && NODE_OPTIONS='--max-old-space-size=8192' docusaurus build", + "build:full": "yarn run _init && yarn run generate:all && NODE_OPTIONS='--max-old-space-size=8192' docusaurus build", "generate:api-docs": "python3 scripts/fix-openapi-spec.py && docusaurus gen-api-docs superset && node scripts/convert-api-sidebar.mjs && node scripts/generate-api-index.mjs && node scripts/generate-api-tag-pages.mjs", "clean:api-docs": "docusaurus clean-api-docs superset", "swizzle": "docusaurus swizzle", @@ -19,11 +21,11 @@ "write-translations": "docusaurus write-translations", "write-heading-ids": "docusaurus write-heading-ids", "typecheck": "yarn run generate:all && tsc", - "generate:extension-components": "node scripts/generate-extension-components.mjs", "generate:superset-components": "node scripts/generate-superset-components.mjs", "generate:database-docs": "node scripts/generate-database-docs.mjs", "gen-db-docs": "node scripts/generate-database-docs.mjs", - "generate:all": "yarn run generate:extension-components & yarn run generate:superset-components & yarn run generate:database-docs & wait && yarn run generate:api-docs", + "generate:smart": "node scripts/generate-if-changed.mjs", + "generate:all": "node scripts/generate-if-changed.mjs --force", "lint:db-metadata": "python3 ../superset/db_engine_specs/lint_metadata.py", "lint:db-metadata:report": "python3 ../superset/db_engine_specs/lint_metadata.py --markdown -o ../superset/db_engine_specs/METADATA_STATUS.md", "update:readme-db-logos": "node scripts/generate-database-docs.mjs --update-readme", @@ -40,6 +42,7 @@ "dependencies": { "@ant-design/icons": "^6.1.0", "@docusaurus/core": "3.9.2", + "@docusaurus/faster": "^3.9.2", "@docusaurus/plugin-client-redirects": "3.9.2", "@docusaurus/preset-classic": "3.9.2", "@docusaurus/theme-live-codeblock": "^3.9.2", diff --git a/docs/scripts/generate-database-docs.mjs b/docs/scripts/generate-database-docs.mjs index 912569294ee..bc412571448 100644 --- a/docs/scripts/generate-database-docs.mjs +++ b/docs/scripts/generate-database-docs.mjs @@ -460,6 +460,9 @@ function generateDatabaseMDX(name, db) { .replace(/\\/g, '\\\\') .replace(/"/g, '\\"'); + // Inline the database data directly to avoid importing the full databases.json + const inlineData = JSON.stringify(db); + return `--- title: ${name} sidebar_label: ${name} @@ -487,9 +490,10 @@ under the License. */} import { DatabasePage } from '@site/src/components/databases'; -import databaseData from '@site/src/data/databases.json'; -<DatabasePage name="${name}" database={databaseData.databases["${name}"]} /> +export const databaseInfo = ${inlineData}; + +<DatabasePage name="${name}" database={databaseInfo} /> `; } diff --git a/docs/scripts/generate-extension-components.mjs b/docs/scripts/generate-extension-components.mjs index c7bed4901c1..efc60b5d863 100644 --- a/docs/scripts/generate-extension-components.mjs +++ b/docs/scripts/generate-extension-components.mjs @@ -634,30 +634,9 @@ async function main() { console.log(`\nFound ${components.length} extension-compatible components\n`); - // Ensure output directory exists - if (!fs.existsSync(OUTPUT_DIR)) { - fs.mkdirSync(OUTPUT_DIR, { recursive: true }); - console.log(`Created directory: ${OUTPUT_DIR}\n`); - } - - // Generate MDX files - for (const component of components) { - // Read the story content for extracting args/controls - const storyContent = fs.readFileSync(component.filePath, 'utf-8'); - const mdxContent = generateMDX(component, storyContent); - const outputPath = path.join( - OUTPUT_DIR, - `${component.componentName.toLowerCase()}.mdx` - ); - fs.writeFileSync(outputPath, mdxContent); - console.log(` Generated: ${path.relative(DOCS_DIR, outputPath)}`); - } - - // Generate index page - const indexContent = generateIndexMDX(components); - const indexPath = path.join(OUTPUT_DIR, 'index.mdx'); - fs.writeFileSync(indexPath, indexContent); - console.log(` Generated: ${path.relative(DOCS_DIR, indexPath)}`); + // MDX generation is handled by generate-superset-components.mjs + // which consolidates all components (including extension) under UI Components. + console.log(' Skipping MDX generation (handled by generate-superset-components.mjs)'); // Generate type declarations if (!fs.existsSync(TYPES_OUTPUT_DIR)) { @@ -667,9 +646,9 @@ async function main() { fs.writeFileSync(TYPES_OUTPUT_PATH, typesContent); console.log(` Generated: ${path.relative(DOCS_DIR, TYPES_OUTPUT_PATH)}`); - console.log('\nDone! Extension component documentation generated.'); + console.log('\nDone! Extension component type declarations generated.'); console.log( - `\nGenerated ${components.length + 2} files (${components.length + 1} MDX + 1 type declaration)` + `\nGenerated 1 type declaration file for ${components.length} components.` ); } diff --git a/docs/scripts/generate-if-changed.mjs b/docs/scripts/generate-if-changed.mjs new file mode 100644 index 00000000000..b26fea53c60 --- /dev/null +++ b/docs/scripts/generate-if-changed.mjs @@ -0,0 +1,306 @@ +/** + * 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. + */ + +/** + * Smart generator wrapper: only runs generators whose input files have changed. + * + * Computes a hash of each generator's input files (stories, engine specs, + * openapi.json, and the generator scripts themselves). Compares against a + * stored cache. Skips generators whose inputs and outputs are unchanged. + * + * Usage: + * node scripts/generate-if-changed.mjs # smart mode (default) + * node scripts/generate-if-changed.mjs --force # force regenerate all + */ + +import { createHash } from 'crypto'; +import { execSync, spawn } from 'child_process'; +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const DOCS_DIR = path.resolve(__dirname, '..'); +const ROOT_DIR = path.resolve(DOCS_DIR, '..'); +const CACHE_FILE = path.join(DOCS_DIR, '.docusaurus', 'generator-hashes.json'); + +const FORCE = process.argv.includes('--force'); + +// Ensure local node_modules/.bin is on PATH (needed for docusaurus CLI) +const localBin = path.join(DOCS_DIR, 'node_modules', '.bin'); +process.env.PATH = `${localBin}${path.delimiter}${process.env.PATH}`; + +// --------------------------------------------------------------------------- +// Generator definitions +// --------------------------------------------------------------------------- + +const GENERATORS = [ + { + name: 'superset-components', + command: 'node scripts/generate-superset-components.mjs', + inputs: [ + { + type: 'glob', + base: path.join(ROOT_DIR, 'superset-frontend/packages/superset-ui-core/src/components'), + pattern: '**/*.stories.tsx', + }, + { + type: 'glob', + base: path.join(ROOT_DIR, 'superset-frontend/packages/superset-core/src'), + pattern: '**/*.stories.tsx', + }, + { type: 'file', path: path.join(DOCS_DIR, 'scripts/generate-superset-components.mjs') }, + { type: 'file', path: path.join(DOCS_DIR, 'src/components/StorybookWrapper.jsx') }, + ], + outputs: [ + path.join(DOCS_DIR, 'developer_portal/components/index.mdx'), + path.join(DOCS_DIR, 'static/data/components.json'), + path.join(DOCS_DIR, 'src/types/apache-superset-core/index.d.ts'), + ], + }, + { + name: 'database-docs', + command: 'node scripts/generate-database-docs.mjs', + inputs: [ + { + type: 'glob', + base: path.join(ROOT_DIR, 'superset/db_engine_specs'), + pattern: '**/*.py', + }, + { type: 'file', path: path.join(DOCS_DIR, 'scripts/generate-database-docs.mjs') }, + ], + outputs: [ + path.join(DOCS_DIR, 'src/data/databases.json'), + path.join(DOCS_DIR, 'docs/databases/supported'), + ], + }, + { + name: 'api-docs', + command: + 'python3 scripts/fix-openapi-spec.py && docusaurus gen-api-docs superset && node scripts/convert-api-sidebar.mjs && node scripts/generate-api-index.mjs && node scripts/generate-api-tag-pages.mjs', + inputs: [ + { type: 'file', path: path.join(DOCS_DIR, 'static/resources/openapi.json') }, + { type: 'file', path: path.join(DOCS_DIR, 'scripts/fix-openapi-spec.py') }, + { type: 'file', path: path.join(DOCS_DIR, 'scripts/convert-api-sidebar.mjs') }, + { type: 'file', path: path.join(DOCS_DIR, 'scripts/generate-api-index.mjs') }, + { type: 'file', path: path.join(DOCS_DIR, 'scripts/generate-api-tag-pages.mjs') }, + ], + outputs: [ + path.join(DOCS_DIR, 'docs/api.mdx'), + ], + }, +]; + +// --------------------------------------------------------------------------- +// Hashing utilities +// --------------------------------------------------------------------------- + +function walkDir(dir, pattern) { + const results = []; + if (!fs.existsSync(dir)) return results; + + const regex = globToRegex(pattern); + function walk(currentDir) { + for (const entry of fs.readdirSync(currentDir, { withFileTypes: true })) { + const fullPath = path.join(currentDir, entry.name); + if (entry.isDirectory()) { + if (entry.name === 'node_modules' || entry.name === '__pycache__') continue; + walk(fullPath); + } else { + const relativePath = path.relative(dir, fullPath); + if (regex.test(relativePath)) { + results.push(fullPath); + } + } + } + } + walk(dir); + return results.sort(); +} + +function globToRegex(pattern) { + // Simple glob-to-regex: ** matches any path, * matches anything except / + const escaped = pattern + .replace(/[.+^${}()|[\]\\]/g, '\\$&') + .replace(/\*\*/g, '<<<GLOBSTAR>>>') + .replace(/\*/g, '[^/]*') + .replace(/<<<GLOBSTAR>>>/g, '.*'); + return new RegExp(`^${escaped}$`); +} + +function hashFile(filePath) { + if (!fs.existsSync(filePath)) return 'missing'; + const stat = fs.statSync(filePath); + // Use mtime + size for speed (avoids reading file contents) + return `${stat.mtimeMs}:${stat.size}`; +} + +function computeInputHash(inputs) { + const hash = createHash('md5'); + for (const input of inputs) { + if (input.type === 'file') { + hash.update(`file:${input.path}:${hashFile(input.path)}\n`); + } else if (input.type === 'glob') { + const files = walkDir(input.base, input.pattern); + hash.update(`glob:${input.base}:${input.pattern}:count=${files.length}\n`); + for (const file of files) { + hash.update(` ${path.relative(input.base, file)}:${hashFile(file)}\n`); + } + } + } + return hash.digest('hex'); +} + +function outputsExist(outputs) { + return outputs.every((p) => fs.existsSync(p)); +} + +// --------------------------------------------------------------------------- +// Cache management +// --------------------------------------------------------------------------- + +function loadCache() { + try { + if (fs.existsSync(CACHE_FILE)) { + return JSON.parse(fs.readFileSync(CACHE_FILE, 'utf8')); + } + } catch { + // Corrupted cache — start fresh + } + return {}; +} + +function saveCache(cache) { + const dir = path.dirname(CACHE_FILE); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + fs.writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2)); +} + +// --------------------------------------------------------------------------- +// Main +// --------------------------------------------------------------------------- + +async function main() { + const cache = loadCache(); + const updatedCache = { ...cache }; + let skipped = 0; + let ran = 0; + + // First pass: determine which generators need to run + // Run independent generators (extension-components, superset-components, + // database-docs) in parallel, then api-docs sequentially (it depends on + // docusaurus CLI being available, not on other generators). + + const independent = GENERATORS.filter((g) => g.name !== 'api-docs'); + const sequential = GENERATORS.filter((g) => g.name === 'api-docs'); + + // Check and run independent generators in parallel + const parallelPromises = independent.map((gen) => { + const currentHash = computeInputHash(gen.inputs); + const cachedHash = cache[gen.name]; + const hasOutputs = outputsExist(gen.outputs); + + if (!FORCE && currentHash === cachedHash && hasOutputs) { + console.log(` ✓ ${gen.name} — no changes, skipping`); + skipped++; + return Promise.resolve(); + } + + const reason = FORCE + ? 'forced' + : !hasOutputs + ? 'output missing' + : 'inputs changed'; + console.log(` ↻ ${gen.name} — ${reason}, regenerating...`); + ran++; + + return new Promise((resolve, reject) => { + const child = spawn('sh', ['-c', gen.command], { + cwd: DOCS_DIR, + stdio: 'inherit', + env: process.env, + }); + child.on('close', (code) => { + if (code === 0) { + updatedCache[gen.name] = currentHash; + resolve(); + } else { + console.error(` ✗ ${gen.name} failed (exit ${code})`); + reject(new Error(`${gen.name} failed with exit code ${code}`)); + } + }); + child.on('error', (err) => { + console.error(` ✗ ${gen.name} failed to start`); + reject(err); + }); + }); + }); + + await Promise.all(parallelPromises); + + // Run sequential generators (api-docs) + for (const gen of sequential) { + const currentHash = computeInputHash(gen.inputs); + const cachedHash = cache[gen.name]; + const hasOutputs = outputsExist(gen.outputs); + + if (!FORCE && currentHash === cachedHash && hasOutputs) { + console.log(` ✓ ${gen.name} — no changes, skipping`); + skipped++; + continue; + } + + const reason = FORCE + ? 'forced' + : !hasOutputs + ? 'output missing' + : 'inputs changed'; + console.log(` ↻ ${gen.name} — ${reason}, regenerating...`); + ran++; + + try { + execSync(gen.command, { + cwd: DOCS_DIR, + stdio: 'inherit', + timeout: 300_000, + }); + updatedCache[gen.name] = currentHash; + } catch (err) { + console.error(` ✗ ${gen.name} failed`); + throw err; + } + } + + saveCache(updatedCache); + + if (ran === 0) { + console.log(`\nAll ${skipped} generators up-to-date — nothing to do!\n`); + } else { + console.log(`\nDone: ${ran} regenerated, ${skipped} skipped.\n`); + } +} + +console.log('Checking generators for changes...\n'); +main().catch((err) => { + console.error(err); + process.exit(1); +}); diff --git a/docs/scripts/generate-superset-components.mjs b/docs/scripts/generate-superset-components.mjs index a85a49bef0a..c34324323ed 100644 --- a/docs/scripts/generate-superset-components.mjs +++ b/docs/scripts/generate-superset-components.mjs @@ -59,6 +59,9 @@ const __dirname = path.dirname(__filename); const ROOT_DIR = path.resolve(__dirname, '../..'); const DOCS_DIR = path.resolve(__dirname, '..'); const OUTPUT_DIR = path.join(DOCS_DIR, 'developer_portal/components'); +const JSON_OUTPUT_PATH = path.join(DOCS_DIR, 'static/data/components.json'); +const TYPES_OUTPUT_DIR = path.join(DOCS_DIR, 'src/types/apache-superset-core'); +const TYPES_OUTPUT_PATH = path.join(TYPES_OUTPUT_DIR, 'index.d.ts'); const FRONTEND_DIR = path.join(ROOT_DIR, 'superset-frontend'); // Source configurations with import paths and categories @@ -146,6 +149,16 @@ const SOURCES = [ enabled: false, // Requires specific setup skipComponents: new Set([]), }, + { + name: 'Extension Components', + path: 'packages/superset-core/src', + importPrefix: '@apache-superset/core/ui', + docImportPrefix: '@apache-superset/core/ui', + category: 'extension', + enabled: true, + extensionCompatible: true, + skipComponents: new Set([]), + }, ]; // Category mapping from story title prefixes to output directories @@ -156,7 +169,7 @@ const CATEGORY_MAP = { 'Legacy Chart Plugins/': 'legacy-charts', 'Core Packages/': 'core-packages', 'Others/': 'utilities', - 'Extension Components/': 'extension', // Skip - handled by other script + 'Extension Components/': 'extension', 'Superset App/': 'app', }; @@ -334,6 +347,7 @@ function parseStoryFile(filePath, sourceConfig) { sourceConfig, resolvedImportPath, isDefaultExport, + extensionCompatible: Boolean(sourceConfig.extensionCompatible), }; } @@ -1141,6 +1155,7 @@ Help improve it by [editing the story file](https://github.com/apache/superset/e const CATEGORY_LABELS = { ui: { title: 'Core Components', sidebarLabel: 'Core Components', description: 'Buttons, inputs, modals, selects, and other fundamental UI elements.' }, 'design-system': { title: 'Layout Components', sidebarLabel: 'Layout Components', description: 'Grid, Layout, Table, Flex, Space, and container components for page structure.' }, + extension: { title: 'Extension Components', sidebarLabel: 'Extension Components', description: 'Components available to extension developers via @apache-superset/core/ui.' }, }; /** @@ -1195,19 +1210,6 @@ ${componentList} * Generate main overview page */ function generateOverviewIndex(categories) { - const categoryList = Object.entries(categories) - .filter(([, components]) => components.length > 0) - .map(([cat, components]) => { - const labels = CATEGORY_LABELS[cat] || { - title: cat.charAt(0).toUpperCase() + cat.slice(1).replace(/-/g, ' '), - }; - const desc = labels.description ? ` ${labels.description}` : ''; - return `### [${labels.title}](./${cat}/)\n${components.length} components —${desc}\n`; - }) - .join('\n'); - - const totalComponents = Object.values(categories).reduce((sum, c) => sum + c.length, 0); - return `--- title: UI Components Overview sidebar_label: Overview @@ -1233,7 +1235,16 @@ sidebar_position: 0 under the License. --> -# Superset Design System +import { ComponentIndex } from '@site/src/components/ui-components'; +import componentData from '@site/static/data/components.json'; + +# UI Components + +<ComponentIndex data={componentData} /> + +--- + +## Design System A design system is a complete set of standards intended to manage design at scale using reusable components and patterns. @@ -1245,14 +1256,6 @@ The Superset Design System uses [Atomic Design](https://bradfrost.com/blog/post/ <img src="/img/atomic-design.png" alt="Atoms = Foundations, Molecules = Components, Organisms = Patterns, Templates = Templates, Pages / Screens = Features" style={{maxWidth: '100%'}} /> ---- - -## Component Library - -Interactive documentation for Superset's UI component library. **${totalComponents} components** documented across ${Object.keys(categories).filter(k => categories[k].length > 0).length} categories. - -${categoryList} - ## Usage All components are exported from \`@superset-ui/core/components\`: @@ -1332,6 +1335,123 @@ ${sections} `; } +/** + * Build metadata for a component (for JSON output) + */ +function buildComponentMetadata(component, storyContent) { + const { componentName, description, category, sourceConfig, resolvedImportPath, extensionCompatible } = component; + const { args, controls, gallery, liveExample } = extractArgsAndControls(storyContent, componentName); + const labels = CATEGORY_LABELS[category] || { + title: category.charAt(0).toUpperCase() + category.slice(1).replace(/-/g, ' '), + }; + + return { + name: componentName, + category, + categoryLabel: labels.title || category, + description: description || '', + importPath: resolvedImportPath || sourceConfig.importPrefix, + package: sourceConfig.docImportPrefix, + extensionCompatible: Boolean(extensionCompatible), + propsCount: Object.keys(args).length, + controlsCount: controls.length, + hasGallery: Boolean(gallery && gallery.sizes && gallery.styles), + hasLiveExample: Boolean(liveExample), + docPath: `developer_portal/components/${category}/${componentName.toLowerCase()}`, + storyFile: component.relativePath, + }; +} + +/** + * Extract type and component export declarations from a component source file. + * Used to generate .d.ts type declarations for extension-compatible components. + */ +function extractComponentTypes(componentPath) { + if (!fs.existsSync(componentPath)) return null; + const content = fs.readFileSync(componentPath, 'utf-8'); + + const types = []; + for (const match of content.matchAll(/export\s+type\s+(\w+)\s*=\s*([^;]+);/g)) { + types.push({ name: match[1], definition: match[2].trim() }); + } + + const components = []; + for (const match of content.matchAll(/export\s+const\s+(\w+)\s*[=:]/g)) { + components.push(match[1]); + } + + return { types, components }; +} + +/** + * Generate TypeScript type declarations for extension-compatible components. + * Produces a .d.ts file that downstream consumers can reference. + */ +function generateExtensionTypeDeclarations(extensionComponents) { + const imports = new Set(); + const typeDeclarations = []; + const componentDeclarations = []; + + for (const comp of extensionComponents) { + const componentDir = path.dirname(comp.filePath); + const componentFile = path.join(componentDir, 'index.tsx'); + const extracted = extractComponentTypes(componentFile); + if (!extracted) continue; + + for (const type of extracted.types) { + if (type.definition.includes('AntdAlertProps') || type.definition.includes('AlertProps')) { + imports.add("import type { AlertProps as AntdAlertProps } from 'antd/es/alert';"); + } + if (type.definition.includes('PropsWithChildren') || type.definition.includes('FC')) { + imports.add("import type { PropsWithChildren, FC } from 'react';"); + } + typeDeclarations.push(`export type ${type.name} = ${type.definition};`); + } + + for (const name of extracted.components) { + const propsType = `${name}Props`; + const hasPropsType = extracted.types.some(t => t.name === propsType); + componentDeclarations.push( + hasPropsType + ? `export const ${name}: FC<${propsType}>;` + : `export const ${name}: FC<Record<string, unknown>>;` + ); + } + } + + return `/** + * 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. + */ + +/** + * Type declarations for @apache-superset/core/ui + * + * AUTO-GENERATED by scripts/generate-superset-components.mjs + * Do not edit manually - regenerate by running: yarn generate:superset-components + */ +${Array.from(imports).join('\n')} + +${typeDeclarations.join('\n')} + +${componentDeclarations.join('\n')} +`; +} + /** * Main function */ @@ -1396,6 +1516,51 @@ async function main() { console.log(` ✓ ${category}/index`); } + // Build JSON metadata for all components + console.log('\nBuilding component metadata JSON...'); + const componentMetadata = []; + for (const component of components) { + const storyContent = fs.readFileSync(component.filePath, 'utf-8'); + componentMetadata.push(buildComponentMetadata(component, storyContent)); + } + + // Build statistics + const byCategory = {}; + for (const comp of componentMetadata) { + if (!byCategory[comp.category]) byCategory[comp.category] = 0; + byCategory[comp.category]++; + } + const jsonData = { + generated: new Date().toISOString(), + statistics: { + totalComponents: componentMetadata.length, + byCategory, + extensionCompatible: componentMetadata.filter(c => c.extensionCompatible).length, + withGallery: componentMetadata.filter(c => c.hasGallery).length, + withLiveExample: componentMetadata.filter(c => c.hasLiveExample).length, + }, + components: componentMetadata, + }; + + // Ensure data directory exists and write JSON + const jsonDir = path.dirname(JSON_OUTPUT_PATH); + if (!fs.existsSync(jsonDir)) { + fs.mkdirSync(jsonDir, { recursive: true }); + } + fs.writeFileSync(JSON_OUTPUT_PATH, JSON.stringify(jsonData, null, 2)); + console.log(` ✓ components.json (${componentMetadata.length} components)`); + + // Generate type declarations for extension-compatible components + const extensionComponents = components.filter(c => c.extensionCompatible); + if (extensionComponents.length > 0) { + if (!fs.existsSync(TYPES_OUTPUT_DIR)) { + fs.mkdirSync(TYPES_OUTPUT_DIR, { recursive: true }); + } + const typesContent = generateExtensionTypeDeclarations(extensionComponents); + fs.writeFileSync(TYPES_OUTPUT_PATH, typesContent); + console.log(` ✓ extension types (${extensionComponents.length} components)`); + } + // Generate main overview const overviewContent = generateOverviewIndex(categories); const overviewPath = path.join(OUTPUT_DIR, 'index.mdx'); diff --git a/docs/sidebarTutorials.js b/docs/sidebarTutorials.js index b786478c0b1..e8c87d58534 100644 --- a/docs/sidebarTutorials.js +++ b/docs/sidebarTutorials.js @@ -74,17 +74,6 @@ const sidebars = { 'extensions/architecture', 'extensions/dependencies', 'extensions/contribution-types', - { - type: 'category', - label: 'Components', - collapsed: true, - items: [ - { - type: 'autogenerated', - dirName: 'extensions/components', - }, - ], - }, { type: 'category', label: 'Extension Points', diff --git a/docs/src/components/databases/DatabaseIndex.tsx b/docs/src/components/databases/DatabaseIndex.tsx index 26f71522dfc..91c58964a31 100644 --- a/docs/src/components/databases/DatabaseIndex.tsx +++ b/docs/src/components/databases/DatabaseIndex.tsx @@ -496,6 +496,7 @@ const DatabaseIndex: React.FC<DatabaseIndexProps> = ({ data }) => { return ( <div className="database-index"> + {/* Statistics Cards */} {/* Statistics Cards */} <Row gutter={[16, 16]} style={{ marginBottom: 24 }}> <Col xs={12} sm={6}> diff --git a/docs/src/components/ui-components/ComponentIndex.tsx b/docs/src/components/ui-components/ComponentIndex.tsx new file mode 100644 index 00000000000..180a67ea2db --- /dev/null +++ b/docs/src/components/ui-components/ComponentIndex.tsx @@ -0,0 +1,262 @@ +/** + * 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. + */ + +import React, { useState, useMemo } from 'react'; +import { Card, Row, Col, Statistic, Table, Tag, Input, Select } from 'antd'; +import { + AppstoreOutlined, + ApiOutlined, + PictureOutlined, + PlayCircleOutlined, + SearchOutlined, +} from '@ant-design/icons'; +import type { ComponentData, ComponentEntry } from './types'; + +interface ComponentIndexProps { + data: ComponentData; +} + +const CATEGORY_COLORS: Record<string, string> = { + ui: 'blue', + 'design-system': 'green', + extension: 'purple', +}; + +const CATEGORY_LABELS: Record<string, string> = { + ui: 'Core', + 'design-system': 'Layout', + extension: 'Extension', +}; + +const ComponentIndex: React.FC<ComponentIndexProps> = ({ data }) => { + const [searchText, setSearchText] = useState(''); + const [categoryFilter, setCategoryFilter] = useState<string | null>(null); + + const { statistics, components } = data; + + const filteredComponents = useMemo(() => { + return components + .filter((comp) => { + const matchesSearch = + !searchText || + comp.name.toLowerCase().includes(searchText.toLowerCase()) || + comp.description.toLowerCase().includes(searchText.toLowerCase()) || + comp.package.toLowerCase().includes(searchText.toLowerCase()); + const matchesCategory = + !categoryFilter || comp.category === categoryFilter; + return matchesSearch && matchesCategory; + }) + .sort((a, b) => a.name.localeCompare(b.name)); + }, [components, searchText, categoryFilter]); + + const { categories, categoryCounts } = useMemo(() => { + const counts: Record<string, number> = {}; + components.forEach((comp) => { + counts[comp.category] = (counts[comp.category] || 0) + 1; + }); + return { + categories: Object.keys(counts).sort(), + categoryCounts: counts, + }; + }, [components]); + + const columns = [ + { + title: 'Component', + dataIndex: 'name', + key: 'name', + sorter: (a: ComponentEntry, b: ComponentEntry) => + a.name.localeCompare(b.name), + defaultSortOrder: 'ascend' as const, + render: (name: string, record: ComponentEntry) => ( + <div> + <a href={`/${record.docPath}`}> + <strong>{name}</strong> + </a> + {record.description && ( + <div style={{ fontSize: '12px', color: '#666' }}> + {record.description.slice(0, 100)} + {record.description.length > 100 ? '...' : ''} + </div> + )} + </div> + ), + }, + { + title: 'Category', + dataIndex: 'category', + key: 'category', + width: 120, + filters: categories.map((cat) => ({ + text: CATEGORY_LABELS[cat] || cat, + value: cat, + })), + onFilter: (value: React.Key | boolean, record: ComponentEntry) => + record.category === value, + render: (cat: string) => ( + <Tag color={CATEGORY_COLORS[cat] || 'default'}> + {CATEGORY_LABELS[cat] || cat} + </Tag> + ), + }, + { + title: 'Package', + dataIndex: 'package', + key: 'package', + width: 220, + render: (pkg: string) => ( + <code style={{ fontSize: '12px' }}>{pkg}</code> + ), + }, + { + title: 'Tags', + key: 'tags', + width: 280, + filters: [ + { text: 'Extension Compatible', value: 'extension' }, + { text: 'Gallery', value: 'gallery' }, + { text: 'Live Demo', value: 'demo' }, + ], + onFilter: (value: React.Key | boolean, record: ComponentEntry) => { + switch (value) { + case 'extension': + return record.extensionCompatible; + case 'gallery': + return record.hasGallery; + case 'demo': + return record.hasLiveExample; + default: + return true; + } + }, + render: (_: unknown, record: ComponentEntry) => ( + <div style={{ display: 'flex', gap: '4px', flexWrap: 'wrap' }}> + {record.extensionCompatible && ( + <Tag color="purple">Extension Compatible</Tag> + )} + {record.hasGallery && <Tag color="cyan">Gallery</Tag>} + {record.hasLiveExample && <Tag color="green">Demo</Tag>} + </div> + ), + }, + { + title: 'Props', + dataIndex: 'propsCount', + key: 'propsCount', + width: 80, + sorter: (a: ComponentEntry, b: ComponentEntry) => + a.propsCount - b.propsCount, + render: (count: number) => ( + <span style={{ color: count > 0 ? '#1890ff' : '#999' }}>{count}</span> + ), + }, + ]; + + return ( + <div className="component-index"> + <Row gutter={[16, 16]} style={{ marginBottom: 24 }}> + <Col xs={12} sm={6}> + <Card> + <Statistic + title="Total Components" + value={statistics.totalComponents} + prefix={<AppstoreOutlined />} + /> + </Card> + </Col> + <Col xs={12} sm={6}> + <Card> + <Statistic + title="Extension Compatible" + value={statistics.extensionCompatible} + prefix={<ApiOutlined />} + /> + </Card> + </Col> + <Col xs={12} sm={6}> + <Card> + <Statistic + title="With Gallery" + value={statistics.withGallery} + prefix={<PictureOutlined />} + /> + </Card> + </Col> + <Col xs={12} sm={6}> + <Card> + <Statistic + title="With Live Demo" + value={statistics.withLiveExample} + prefix={<PlayCircleOutlined />} + /> + </Card> + </Col> + </Row> + + <Row gutter={[16, 16]} style={{ marginBottom: 16 }}> + <Col xs={24} sm={12}> + <Input + placeholder="Search components..." + prefix={<SearchOutlined />} + value={searchText} + onChange={(e) => setSearchText(e.target.value)} + allowClear + /> + </Col> + <Col xs={24} sm={12}> + <Select + placeholder="Filter by category" + style={{ width: '100%' }} + value={categoryFilter} + onChange={setCategoryFilter} + allowClear + options={categories.map((cat) => ({ + label: ( + <span> + <Tag + color={CATEGORY_COLORS[cat] || 'default'} + style={{ marginRight: 8 }} + > + {categoryCounts[cat] || 0} + </Tag> + {CATEGORY_LABELS[cat] || cat} + </span> + ), + value: cat, + }))} + /> + </Col> + </Row> + + <Table + dataSource={filteredComponents} + columns={columns} + rowKey="name" + pagination={{ + defaultPageSize: 20, + showSizeChanger: true, + showTotal: (total) => `${total} components`, + }} + size="middle" + /> + </div> + ); +}; + +export default ComponentIndex; diff --git a/docs/babel.config.js b/docs/src/components/ui-components/index.ts similarity index 75% rename from docs/babel.config.js rename to docs/src/components/ui-components/index.ts index 61032e678a4..2081775d7dc 100644 --- a/docs/babel.config.js +++ b/docs/src/components/ui-components/index.ts @@ -1,4 +1,3 @@ -/* eslint-env node */ /** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -18,15 +17,5 @@ * under the License. */ -module.exports = { - presets: [ - [ - require.resolve('@docusaurus/core/lib/babel/preset'), - { - runtime: 'automatic', - importSource: '@emotion/react', - }, - ], - ], - plugins: ['@emotion/babel-plugin'], -}; +export { default as ComponentIndex } from './ComponentIndex'; +export * from './types'; diff --git a/docs/src/types/apache-superset-core/index.d.ts b/docs/src/components/ui-components/types.ts similarity index 55% copy from docs/src/types/apache-superset-core/index.d.ts copy to docs/src/components/ui-components/types.ts index 5650b85bb2c..f4fb082b065 100644 --- a/docs/src/types/apache-superset-core/index.d.ts +++ b/docs/src/components/ui-components/types.ts @@ -17,15 +17,32 @@ * under the License. */ -/** - * Type declarations for @apache-superset/core/ui - * - * AUTO-GENERATED by scripts/generate-extension-components.mjs - * Do not edit manually - regenerate by running: yarn generate:extension-components - */ -import type { AlertProps as AntdAlertProps } from 'antd/es/alert'; -import type { PropsWithChildren, FC } from 'react'; +export interface ComponentEntry { + name: string; + category: string; + categoryLabel: string; + description: string; + importPath: string; + package: string; + extensionCompatible: boolean; + propsCount: number; + controlsCount: number; + hasGallery: boolean; + hasLiveExample: boolean; + docPath: string; + storyFile: string; +} -export type AlertProps = PropsWithChildren<Omit<AntdAlertProps, 'children'>>; +export interface ComponentStatistics { + totalComponents: number; + byCategory: Record<string, number>; + extensionCompatible: number; + withGallery: number; + withLiveExample: number; +} -export const Alert: FC<AlertProps>; +export interface ComponentData { + generated: string; + statistics: ComponentStatistics; + components: ComponentEntry[]; +} diff --git a/docs/src/data/databases.json b/docs/src/data/databases.json index 67cfdc3aebd..38914dd7868 100644 --- a/docs/src/data/databases.json +++ b/docs/src/data/databases.json @@ -1,5 +1,5 @@ { - "generated": "2026-02-16T04:47:37.257Z", + "generated": "2026-02-24T20:28:17.222Z", "statistics": { "totalDatabases": 72, "withDocumentation": 72, diff --git a/docs/src/types/apache-superset-core/index.d.ts b/docs/src/types/apache-superset-core/index.d.ts index 5650b85bb2c..6e3a121e1b6 100644 --- a/docs/src/types/apache-superset-core/index.d.ts +++ b/docs/src/types/apache-superset-core/index.d.ts @@ -20,8 +20,8 @@ /** * Type declarations for @apache-superset/core/ui * - * AUTO-GENERATED by scripts/generate-extension-components.mjs - * Do not edit manually - regenerate by running: yarn generate:extension-components + * AUTO-GENERATED by scripts/generate-superset-components.mjs + * Do not edit manually - regenerate by running: yarn generate:superset-components */ import type { AlertProps as AntdAlertProps } from 'antd/es/alert'; import type { PropsWithChildren, FC } from 'react'; diff --git a/docs/src/webpack.extend.ts b/docs/src/webpack.extend.ts index e3079ee7e73..f32d9d9847d 100644 --- a/docs/src/webpack.extend.ts +++ b/docs/src/webpack.extend.ts @@ -101,12 +101,6 @@ export default function webpackExtendPlugin(): Plugin<void> { return { devtool: isDev ? false : config.devtool, - cache: { - type: 'filesystem', - buildDependencies: { - config: [__filename], - }, - }, ...(isDev && { optimization: { ...config.optimization, diff --git a/docs/tsconfig.json b/docs/tsconfig.json index b29d41ca6de..f4a3a433d87 100644 --- a/docs/tsconfig.json +++ b/docs/tsconfig.json @@ -14,7 +14,7 @@ "paths": { "@superset-ui/core": ["../superset-frontend/packages/superset-ui-core/src"], "@superset-ui/core/*": ["../superset-frontend/packages/superset-ui-core/src/*"], - // Types for @apache-superset/core/ui are auto-generated by scripts/generate-extension-components.mjs + // Types for @apache-superset/core/ui are auto-generated by scripts/generate-superset-components.mjs // Runtime resolution uses webpack alias pointing to actual source (see src/webpack.extend.ts) // Using /ui path matches the established pattern used throughout the Superset codebase "@apache-superset/core/ui": ["./src/types/apache-superset-core"], diff --git a/docs/yarn.lock b/docs/yarn.lock index a232ce5c2bb..03860481598 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -1695,6 +1695,21 @@ postcss-sort-media-queries "^5.2.0" tslib "^2.6.0" +"@docusaurus/faster@^3.9.2": + version "3.9.2" + resolved "https://registry.yarnpkg.com/@docusaurus/faster/-/faster-3.9.2.tgz#47b69f39ed935fdcc8dc03896274fca29056e962" + integrity sha512-DEVIwhbrZZ4ir31X+qQNEQqDWkgCJUV6kiPPAd2MGTY8n5/n0c4B8qA5k1ipF2izwH00JEf0h6Daaut71zzkyw== + dependencies: + "@docusaurus/types" "3.9.2" + "@rspack/core" "^1.5.0" + "@swc/core" "^1.7.39" + "@swc/html" "^1.13.5" + browserslist "^4.24.2" + lightningcss "^1.27.0" + swc-loader "^0.2.6" + tslib "^2.6.0" + webpack "^5.95.0" + "@docusaurus/[email protected]": version "3.9.2" resolved "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.9.2.tgz" @@ -2104,6 +2119,28 @@ utility-types "^3.10.0" webpack "^5.88.1" +"@emnapi/core@^1.5.0": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.8.1.tgz#fd9efe721a616288345ffee17a1f26ac5dd01349" + integrity sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg== + dependencies: + "@emnapi/wasi-threads" "1.1.0" + tslib "^2.4.0" + +"@emnapi/runtime@^1.5.0": + version "1.8.1" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.8.1.tgz#550fa7e3c0d49c5fb175a116e8cd70614f9a22a5" + integrity sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg== + dependencies: + tslib "^2.4.0" + +"@emnapi/[email protected]": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf" + integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ== + dependencies: + tslib "^2.4.0" + "@emotion/babel-plugin@^11.13.5": version "11.13.5" resolved "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz" @@ -2679,6 +2716,58 @@ dependencies: langium "3.3.1" +"@module-federation/[email protected]": + version "0.22.0" + resolved "https://registry.yarnpkg.com/@module-federation/error-codes/-/error-codes-0.22.0.tgz#31ccc990dc240d73912ba7bd001f7e35ac751992" + integrity sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug== + +"@module-federation/[email protected]": + version "0.22.0" + resolved "https://registry.yarnpkg.com/@module-federation/runtime-core/-/runtime-core-0.22.0.tgz#7321ec792bb7d1d22bee6162ec43564b769d2a3c" + integrity sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA== + dependencies: + "@module-federation/error-codes" "0.22.0" + "@module-federation/sdk" "0.22.0" + +"@module-federation/[email protected]": + version "0.22.0" + resolved "https://registry.yarnpkg.com/@module-federation/runtime-tools/-/runtime-tools-0.22.0.tgz#36f2a7cb267af208a9d1a237fe9a71b4bf31431e" + integrity sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA== + dependencies: + "@module-federation/runtime" "0.22.0" + "@module-federation/webpack-bundler-runtime" "0.22.0" + +"@module-federation/[email protected]": + version "0.22.0" + resolved "https://registry.yarnpkg.com/@module-federation/runtime/-/runtime-0.22.0.tgz#f789c9ef40d846d110711c8221ecc0ad938d43d8" + integrity sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA== + dependencies: + "@module-federation/error-codes" "0.22.0" + "@module-federation/runtime-core" "0.22.0" + "@module-federation/sdk" "0.22.0" + +"@module-federation/[email protected]": + version "0.22.0" + resolved "https://registry.yarnpkg.com/@module-federation/sdk/-/sdk-0.22.0.tgz#6ad4c1de85a900c3c80ff26cb87cce253e3a2770" + integrity sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g== + +"@module-federation/[email protected]": + version "0.22.0" + resolved "https://registry.yarnpkg.com/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.22.0.tgz#dcbe8f972d722fe278e6a7c21988d4bee53d401d" + integrity sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA== + dependencies: + "@module-federation/runtime" "0.22.0" + "@module-federation/sdk" "0.22.0" + +"@napi-rs/[email protected]": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz#dcfea99a75f06209a235f3d941e3460a51e9b14c" + integrity sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw== + dependencies: + "@emnapi/core" "^1.5.0" + "@emnapi/runtime" "^1.5.0" + "@tybys/wasm-util" "^0.10.1" + "@nodelib/[email protected]": version "2.1.5" resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" @@ -3273,6 +3362,88 @@ redux-thunk "^3.1.0" reselect "^5.1.0" +"@rspack/[email protected]": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.7.6.tgz#10144f3841be88ea25c71a537df6b038ae84a87a" + integrity sha512-NZ9AWtB1COLUX1tA9HQQvWpTy07NSFfKBU8A6ylWd5KH8AePZztpNgLLAVPTuNO4CZXYpwcoclf8jG/luJcQdQ== + +"@rspack/[email protected]": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.7.6.tgz#70588e30e1fdcd3149e09fe6798eb95609ad814b" + integrity sha512-J2g6xk8ZS7uc024dNTGTHxoFzFovAZIRixUG7PiciLKTMP78svbSSWrmW6N8oAsAkzYfJWwQpVgWfFNRHvYxSw== + +"@rspack/[email protected]": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.7.6.tgz#322e7fe54fccefd57603d4730130bef311b8dd60" + integrity sha512-eQfcsaxhFrv5FmtaA7+O1F9/2yFDNIoPZzV/ZvqvFz5bBXVc4FAm/1fVpBg8Po/kX1h0chBc7Xkpry3cabFW8w== + +"@rspack/[email protected]": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.7.6.tgz#4444dfe045323f341c7c82fdb7dce5809fea51c1" + integrity sha512-DfQXKiyPIl7i1yECHy4eAkSmlUzzsSAbOjgMuKn7pudsWf483jg0UUYutNgXSlBjc/QSUp7906Cg8oty9OfwPA== + +"@rspack/[email protected]": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.7.6.tgz#c31bf72789c71eeee75cd3cb06d6a6e5449e1bd1" + integrity sha512-NdA+2X3lk2GGrMMnTGyYTzM3pn+zNjaqXqlgKmFBXvjfZqzSsKq3pdD1KHZCd5QHN+Fwvoszj0JFsquEVhE1og== + +"@rspack/[email protected]": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.7.6.tgz#20f8ad786d581af7a7c2802220b533ce531fb4c6" + integrity sha512-rEy6MHKob02t/77YNgr6dREyJ0e0tv1X6Xsg8Z5E7rPXead06zefUbfazj4RELYySWnM38ovZyJAkPx/gOn3VA== + +"@rspack/[email protected]": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@rspack/binding-wasm32-wasi/-/binding-wasm32-wasi-1.7.6.tgz#76ae0f9f584a054e109b83ec02516ce75dcff8e6" + integrity sha512-YupOrz0daSG+YBbCIgpDgzfMM38YpChv+afZpaxx5Ml7xPeAZIIdgWmLHnQ2rts73N2M1NspAiBwV00Xx0N4Vg== + dependencies: + "@napi-rs/wasm-runtime" "1.0.7" + +"@rspack/[email protected]": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.7.6.tgz#4e7f70338dfcc8efa3a67d72064562eb9f0662cb" + integrity sha512-INj7aVXjBvlZ84kEhSK4kJ484ub0i+BzgnjDWOWM1K+eFYDZjLdAsQSS3fGGXwVc3qKbPIssFfnftATDMTEJHQ== + +"@rspack/[email protected]": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.7.6.tgz#efeb807c624536361467dfec0898705213fbd997" + integrity sha512-lXGvC+z67UMcw58In12h8zCa9IyYRmuptUBMItQJzu+M278aMuD1nETyGLL7e4+OZ2lvrnnBIcjXN1hfw2yRzw== + +"@rspack/[email protected]": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.7.6.tgz#48014313c224e9fce31d02134c81525a7cb7f891" + integrity sha512-zeUxEc0ZaPpmaYlCeWcjSJUPuRRySiSHN23oJ2Xyw0jsQ01Qm4OScPdr0RhEOFuK/UE+ANyRtDo4zJsY52Hadw== + +"@rspack/[email protected]": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@rspack/binding/-/binding-1.7.6.tgz#d61b241c0dbb4e395f7753de74a2fe760891d4f2" + integrity sha512-/NrEcfo8Gx22hLGysanrV6gHMuqZSxToSci/3M4kzEQtF5cPjfOv5pqeLK/+B6cr56ul/OmE96cCdWcXeVnFjQ== + optionalDependencies: + "@rspack/binding-darwin-arm64" "1.7.6" + "@rspack/binding-darwin-x64" "1.7.6" + "@rspack/binding-linux-arm64-gnu" "1.7.6" + "@rspack/binding-linux-arm64-musl" "1.7.6" + "@rspack/binding-linux-x64-gnu" "1.7.6" + "@rspack/binding-linux-x64-musl" "1.7.6" + "@rspack/binding-wasm32-wasi" "1.7.6" + "@rspack/binding-win32-arm64-msvc" "1.7.6" + "@rspack/binding-win32-ia32-msvc" "1.7.6" + "@rspack/binding-win32-x64-msvc" "1.7.6" + +"@rspack/core@^1.5.0": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@rspack/core/-/core-1.7.6.tgz#d43a1c4103248cbe4011902906c6d7427b80f3a6" + integrity sha512-Iax6UhrfZqJajA778c1d5DBFbSIqPOSrI34kpNIiNpWd8Jq7mFIa+Z60SQb5ZQDZuUxcCZikjz5BxinFjTkg7Q== + dependencies: + "@module-federation/runtime-tools" "0.22.0" + "@rspack/binding" "1.7.6" + "@rspack/lite-tapable" "1.1.0" + +"@rspack/[email protected]": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@rspack/lite-tapable/-/lite-tapable-1.1.0.tgz#3cfdafeed01078e116bd4f191b684c8b484de425" + integrity sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw== + "@saucelabs/theme-github-codeblock@^0.3.0": version "0.3.0" resolved "https://registry.npmjs.org/@saucelabs/theme-github-codeblock/-/theme-github-codeblock-0.3.0.tgz" @@ -4047,51 +4218,101 @@ resolved "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.11.tgz" integrity sha512-QoIupRWVH8AF1TgxYyeA5nS18dtqMuxNwchjBIwJo3RdwLEFiJq6onOx9JAxHtuPwUkIVuU2Xbp+jCJ7Vzmgtg== +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.13.tgz#f60ff48cb93066b83405074015eb6373ea0cdd77" + integrity sha512-ztXusRuC5NV2w+a6pDhX13CGioMLq8CjX5P4XgVJ21ocqz9t19288Do0y8LklplDtwcEhYGTNdMbkmUT7+lDTg== + "@swc/[email protected]": version "1.15.11" resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.15.11.tgz#31381b6560bbd8b8ca6a0755262df321e28c039d" integrity sha512-S52Gu1QtPSfBYDiejlcfp9GlN+NjTZBRRNsz8PNwBgSE626/FUf2PcllVUix7jqkoMC+t0rS8t+2/aSWlMuQtA== +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/core-darwin-x64/-/core-darwin-x64-1.15.13.tgz#3838c08653ac53a6508cdc34bfa191281da4ed26" + integrity sha512-cVifxQUKhaE7qcO/y9Mq6PEhoyvN9tSLzCnnFZ4EIabFHBuLtDDO6a+vLveOy98hAs5Qu1+bb5Nv0oa1Pihe3Q== + "@swc/[email protected]": version "1.15.11" resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.11.tgz#ea7831776f7d8a548db4a8a5f38ef37faf5c0c66" integrity sha512-lXJs8oXo6Z4yCpimpQ8vPeCjkgoHu5NoMvmJZ8qxDyU99KVdg6KwU9H79vzrmB+HfH+dCZ7JGMqMF//f8Cfvdg== +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.13.tgz#9308b156fae3fe5d12684b86af31ada4255066fc" + integrity sha512-t+xxEzZ48enl/wGGy7SRYd7kImWQ/+wvVFD7g5JZo234g6/QnIgZ+YdfIyjHB+ZJI3F7a2IQHS7RNjxF29UkWw== + "@swc/[email protected]": version "1.15.11" resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.11.tgz#c99a5843115ef57cbefd40b93c99cb130d6db12f" integrity sha512-chRsz1K52/vj8Mfq/QOugVphlKPWlMh10V99qfH41hbGvwAU6xSPd681upO4bKiOr9+mRIZZW+EfJqY42ZzRyA== +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.13.tgz#b150d6091e2bb3cf97dc9712a711d3ba025811a9" + integrity sha512-VndeGvKmTXFn6AGwjy0Kg8i7HccOCE7Jt/vmZwRxGtOfNZM1RLYRQ7MfDLo6T0h1Bq6eYzps3L5Ma4zBmjOnOg== + "@swc/[email protected]": version "1.15.11" resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.11.tgz#9a7831f558b2ff504d3d6eaaf6a4c84e5232284b" integrity sha512-PYftgsTaGnfDK4m6/dty9ryK1FbLk+LosDJ/RJR2nkXGc8rd+WenXIlvHjWULiBVnS1RsjHHOXmTS4nDhe0v0w== +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.13.tgz#35dd5382554096118ecd1db2928e1f71b56aa41a" + integrity sha512-SmZ9m+XqCB35NddHCctvHFLqPZDAs5j8IgD36GoutufDJmeq2VNfgk5rQoqNqKmAK3Y7iFdEmI76QoHIWiCLyw== + "@swc/[email protected]": version "1.15.11" resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.11.tgz#4a1fce9b9abedde04459fefe5da9dd9e405a2ae8" integrity sha512-DKtnJKIHiZdARyTKiX7zdRjiDS1KihkQWatQiCHMv+zc2sfwb4Glrodx2VLOX4rsa92NLR0Sw8WLcPEMFY1szQ== +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.13.tgz#03f89bbdce8f07a1bc02a3ef1c93a5b4e81aef2e" + integrity sha512-5rij+vB9a29aNkHq72EXI2ihDZPszJb4zlApJY4aCC/q6utgqFA6CkrfTfIb+O8hxtG3zP5KERETz8mfFK6A0A== + "@swc/[email protected]": version "1.15.11" resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.11.tgz#0865f23b1cc532d9d77e743a83279e074edbee25" integrity sha512-mUjjntHj4+8WBaiDe5UwRNHuEzLjIWBTSGTw0JT9+C9/Yyuh4KQqlcEQ3ro6GkHmBGXBFpGIj/o5VMyRWfVfWw== +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.13.tgz#27ae66914125bf35724e43bb06b856afed39770c" + integrity sha512-OlSlaOK9JplQ5qn07WiBLibkOw7iml2++ojEXhhR3rbWrNEKCD7sd8+6wSavsInyFdw4PhLA+Hy6YyDBIE23Yw== + "@swc/[email protected]": version "1.15.11" resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.11.tgz#73eda8b54c94046728f5983e5516223ad1009c59" integrity sha512-ZkNNG5zL49YpaFzfl6fskNOSxtcZ5uOYmWBkY4wVAvgbSAQzLRVBp+xArGWh2oXlY/WgL99zQSGTv7RI5E6nzA== +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.13.tgz#39776831949a53754d8f62e4730ac9430d1671f3" + integrity sha512-zwQii5YVdsfG8Ti9gIKgBKZg8qMkRZxl+OlYWUT5D93Jl4NuNBRausP20tfEkQdAPSRrMCSUZBM6FhW7izAZRg== + "@swc/[email protected]": version "1.15.11" resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.11.tgz#0df41547974ba9f26ba3e903e803ff523c15650b" integrity sha512-6XnzORkZCQzvTQ6cPrU7iaT9+i145oLwnin8JrfsLG41wl26+5cNQ2XV3zcbrnFEV6esjOceom9YO1w9mGJByw== +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.13.tgz#995c45c9fd86d9959bc1a7275c4e60ac4efcc12f" + integrity sha512-hYXvyVVntqRlYoAIDwNzkS3tL2ijP3rxyWQMNKaxcCxxkCDto/w3meOK/OB6rbQSkNw0qTUcBfU9k+T0ptYdfQ== + "@swc/[email protected]": version "1.15.11" resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.11.tgz#f6f97500472c0ea4ab756c383c5d97896075f95c" integrity sha512-IQ2n6af7XKLL6P1gIeZACskSxK8jWtoKpJWLZmdXTDj1MGzktUy4i+FvpdtxFmJWNavRWH1VmTr6kAubRDHeKw== +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.13.tgz#b329aec8bb5e84bab49c8f250ebb27f6c27dc213" + integrity sha512-XTzKs7c/vYCcjmcwawnQvlHHNS1naJEAzcBckMI5OJlnrcgW8UtcX9NHFYvNjGtXuKv0/9KvqL4fuahdvlNGKw== + "@swc/core@^1.15.11": version "1.15.11" resolved "https://registry.npmjs.org/@swc/core/-/core-1.15.11.tgz" @@ -4111,11 +4332,98 @@ "@swc/core-win32-ia32-msvc" "1.15.11" "@swc/core-win32-x64-msvc" "1.15.11" +"@swc/core@^1.7.39": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/core/-/core-1.15.13.tgz#19b4117a76576f46b28199ac2f75cad5bc9cdde4" + integrity sha512-0l1gl/72PErwUZuavcRpRAQN9uSst+Nk++niC5IX6lmMWpXoScYx3oq/narT64/sKv/eRiPTaAjBFGDEQiWJIw== + dependencies: + "@swc/counter" "^0.1.3" + "@swc/types" "^0.1.25" + optionalDependencies: + "@swc/core-darwin-arm64" "1.15.13" + "@swc/core-darwin-x64" "1.15.13" + "@swc/core-linux-arm-gnueabihf" "1.15.13" + "@swc/core-linux-arm64-gnu" "1.15.13" + "@swc/core-linux-arm64-musl" "1.15.13" + "@swc/core-linux-x64-gnu" "1.15.13" + "@swc/core-linux-x64-musl" "1.15.13" + "@swc/core-win32-arm64-msvc" "1.15.13" + "@swc/core-win32-ia32-msvc" "1.15.13" + "@swc/core-win32-x64-msvc" "1.15.13" + "@swc/counter@^0.1.3": version "0.1.3" resolved "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/html-darwin-arm64/-/html-darwin-arm64-1.15.13.tgz#6cb94e0a6685df46a48c7168e4d1a048ddcdeceb" + integrity sha512-w/fTkqqkx9haSbws8YhhW/Bp7ZkxCJ6lns5YYZMHdZI2KJL4WEHl6GhGzgzavOXaO8LBouiUwucc2bYPgsfI/w== + +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/html-darwin-x64/-/html-darwin-x64-1.15.13.tgz#c9402ec555c7681370fc978f4f6cc12a19e6e9ba" + integrity sha512-yYb8jq+R+FlM8DlFLt5zmm0G5zdF4UUrHjafETmNj3J05itOzcOO9kI7icZ6DUwCROYbfejG7AwkSooYOV5+kA== + +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/html-linux-arm-gnueabihf/-/html-linux-arm-gnueabihf-1.15.13.tgz#b10aa1b05ccf12610d145833a500aa83e4de6920" + integrity sha512-n+/JK+vi9FwJCe5Jrv7i0J0/keal3x+8ZXROJbLAdzYWoAaqjbEeUNWuqmSH3uU64eOhqUl6kRERLz/NB6LoZw== + +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/html-linux-arm64-gnu/-/html-linux-arm64-gnu-1.15.13.tgz#8e98a5b4672155ff13c6f1404abe731c8967992e" + integrity sha512-ThKrqeXiRKTj4/mo+KoXy4GE390Lt76GjF0apNwXB27YTQxMFLIlcHIntn/WhumAVJCu3pA/n0TYw8ZSu7K3DA== + +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/html-linux-arm64-musl/-/html-linux-arm64-musl-1.15.13.tgz#64487978fcdb347490a3daa2aeee95f2c025d516" + integrity sha512-9nyG3dgAclXuAyOsHBpQq0Q15SwQXkGvifczfiKnyd3srjWrsl4ZhHiE3ZrBBshenoK76NwPxATazf/lU83JNg== + +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/html-linux-x64-gnu/-/html-linux-x64-gnu-1.15.13.tgz#16f72d180846bdb27b60038cd48582f2c8307488" + integrity sha512-yzpOYvLXXDqplHrr9wVImJ+QBLeubP7m92zZTQaW8rdhag01bX2Y/+829emT58K3SfLJTiJdKBYsL3q3mbVWrg== + +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/html-linux-x64-musl/-/html-linux-x64-musl-1.15.13.tgz#4acf02ef41ee7dfc38cd824be81f79e7adc04483" + integrity sha512-VakiAq/YTiSP3TcWKL6Vo5qu7iS8M647T22zGNNMc4D/gxg57R+89SITc1zCphR6p9rEh7vx6bk8/b8NXgYZeQ== + +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/html-win32-arm64-msvc/-/html-win32-arm64-msvc-1.15.13.tgz#3df9183ef9e9d3d08cf1b830a50c72fade286240" + integrity sha512-AhO5wmpnK5doUDDkOLqoPMDnNUrY3xa5HShiqiZBiGH2opB++kys77Q1Q9iW9ZKZgAiFLLZmiqVfcQRjhgdy0g== + +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/html-win32-ia32-msvc/-/html-win32-ia32-msvc-1.15.13.tgz#1586e4b4d6aaf1d69ad93f58b5b996bcaca91705" + integrity sha512-nyjUqwCSezmrWOBTCUf5EXl1oU+Fk/x+zSvvmrEGLAUo7fgpmSJtsNveODkZ8M755MI13ANdO8XkPg0UhYM+4g== + +"@swc/[email protected]": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/html-win32-x64-msvc/-/html-win32-x64-msvc-1.15.13.tgz#d00f0c1fb82658ccb2f3f92a8d0ae98c7214434c" + integrity sha512-ClKtII06nneMXik7dURXOlkPX8XyyBKE/3VfAAEC7B4E00m228gOy4CwTy9E2TDCeo6eqdePcSETSQzY8uOe8w== + +"@swc/html@^1.13.5": + version "1.15.13" + resolved "https://registry.yarnpkg.com/@swc/html/-/html-1.15.13.tgz#4f1a1e6f70e4fa31732f2acffb2f8b9968da9dcd" + integrity sha512-3eICmZEt1QTYEF++ZiyGULhuB3QSyoDaFXRjq2Dso7gD8yENeZ00HHpGt340ievtve11BYSD3rVlPRN3/BGlIA== + dependencies: + "@swc/counter" "^0.1.3" + optionalDependencies: + "@swc/html-darwin-arm64" "1.15.13" + "@swc/html-darwin-x64" "1.15.13" + "@swc/html-linux-arm-gnueabihf" "1.15.13" + "@swc/html-linux-arm64-gnu" "1.15.13" + "@swc/html-linux-arm64-musl" "1.15.13" + "@swc/html-linux-x64-gnu" "1.15.13" + "@swc/html-linux-x64-musl" "1.15.13" + "@swc/html-win32-arm64-msvc" "1.15.13" + "@swc/html-win32-ia32-msvc" "1.15.13" + "@swc/html-win32-x64-msvc" "1.15.13" + "@swc/types@^0.1.25": version "0.1.25" resolved "https://registry.npmjs.org/@swc/types/-/types-0.1.25.tgz" @@ -4143,6 +4451,13 @@ resolved "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz" integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== +"@tybys/wasm-util@^0.10.1": + version "0.10.1" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414" + integrity sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg== + dependencies: + tslib "^2.4.0" + "@types/body-parser@*": version "1.19.6" resolved "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz" @@ -5645,7 +5960,7 @@ browser-assert@^1.2.1: resolved "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz" integrity sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ== -browserslist@^4.0.0, browserslist@^4.23.0, browserslist@^4.24.0, browserslist@^4.24.4, browserslist@^4.25.0, browserslist@^4.25.3, browserslist@^4.28.1: +browserslist@^4.0.0, browserslist@^4.23.0, browserslist@^4.24.0, browserslist@^4.24.2, browserslist@^4.24.4, browserslist@^4.25.0, browserslist@^4.25.3, browserslist@^4.28.1: version "4.28.1" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz" integrity sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA== @@ -9589,6 +9904,80 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" [email protected]: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz#609ff48332adff452a8157a7c2842fd692a8eac4" + integrity sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg== + [email protected]: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz#a13da040a7929582bab3ace9a67bdc146e99fc2d" + integrity sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg== + [email protected]: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz#f7482c311273571ec0c2bd8277c1f5f6e90e03a4" + integrity sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA== + [email protected]: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz#91df1bb290f1cb7bb2af832d7d0d8809225e0124" + integrity sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A== + [email protected]: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz#c3cad5ae8b70045f21600dc95295ab6166acf57e" + integrity sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g== + [email protected]: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz#a5c4f6a5ac77447093f61b209c0bd7fef1f0a3e3" + integrity sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg== + [email protected]: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz#af26ab8f829b727ada0a200938a6c8796ff36900" + integrity sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg== + [email protected]: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz#a891d44e84b71c0d88959feb9a7522bbf61450ee" + integrity sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA== + [email protected]: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz#8c8b21def851f4d477fa897b80cb3db2b650bc6e" + integrity sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA== + [email protected]: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz#79000fb8c57e94a91b8fc643e74d5a54407d7080" + integrity sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w== + [email protected]: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz#7f025274c81c7d659829731e09c8b6f442209837" + integrity sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw== + +lightningcss@^1.27.0: + version "1.31.1" + resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.31.1.tgz#1a19dd327b547a7eda1d5c296ebe1e72df5a184b" + integrity sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ== + dependencies: + detect-libc "^2.0.3" + optionalDependencies: + lightningcss-android-arm64 "1.31.1" + lightningcss-darwin-arm64 "1.31.1" + lightningcss-darwin-x64 "1.31.1" + lightningcss-freebsd-x64 "1.31.1" + lightningcss-linux-arm-gnueabihf "1.31.1" + lightningcss-linux-arm64-gnu "1.31.1" + lightningcss-linux-arm64-musl "1.31.1" + lightningcss-linux-x64-gnu "1.31.1" + lightningcss-linux-x64-musl "1.31.1" + lightningcss-win32-arm64-msvc "1.31.1" + lightningcss-win32-x64-msvc "1.31.1" + lilconfig@^3.1.1: version "3.1.3" resolved "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz" @@ -14107,7 +14496,7 @@ [email protected], swagger2openapi@^7.0.8: yaml "^1.10.0" yargs "^17.0.1" -swc-loader@^0.2.7: +swc-loader@^0.2.6, swc-loader@^0.2.7: version "0.2.7" resolved "https://registry.npmjs.org/swc-loader/-/swc-loader-0.2.7.tgz" integrity sha512-nwYWw3Fh9ame3Rtm7StS9SBLpHRRnYcK7bnpF3UKZmesAK0gw2/ADvlURFAINmPvKtDLzp+GBiP9yLoEjg6S9w== @@ -14327,7 +14716,7 @@ ts-toolbelt@^9.6.0: resolved "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz" integrity sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w== -tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.3.0, tslib@^2.6.0: +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.6.0: version "2.8.1" resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
