mirror of
https://github.com/apache/superset.git
synced 2026-04-22 17:45:21 +00:00
feat(extensions): code-first frontend contributions (#38346)
This commit is contained in:
committed by
GitHub
parent
01d5245cd2
commit
a74d32ab44
@@ -42,6 +42,7 @@ from superset_extensions_cli.exceptions import ExtensionNameError
|
||||
from superset_extensions_cli.types import ExtensionNames
|
||||
from superset_extensions_cli.utils import (
|
||||
generate_extension_names,
|
||||
get_module_federation_name,
|
||||
kebab_to_snake_case,
|
||||
read_json,
|
||||
read_toml,
|
||||
@@ -152,11 +153,12 @@ def build_manifest(cwd: Path, remote_entry: str | None) -> Manifest:
|
||||
composite_id = f"{extension.publisher}.{extension.name}"
|
||||
|
||||
frontend: ManifestFrontend | None = None
|
||||
if extension.frontend and remote_entry:
|
||||
if remote_entry:
|
||||
frontend = ManifestFrontend(
|
||||
contributions=extension.frontend.contributions,
|
||||
moduleFederation=extension.frontend.moduleFederation,
|
||||
remoteEntry=remote_entry,
|
||||
moduleFederationName=get_module_federation_name(
|
||||
extension.publisher, extension.name
|
||||
),
|
||||
)
|
||||
|
||||
backend: ManifestBackend | None = None
|
||||
|
||||
@@ -4,20 +4,6 @@
|
||||
"displayName": "{{ display_name }}",
|
||||
"version": "{{ version }}",
|
||||
"license": "{{ license }}",
|
||||
{% if include_frontend -%}
|
||||
"frontend": {
|
||||
"contributions": {
|
||||
"commands": [],
|
||||
"views": {},
|
||||
"menus": {},
|
||||
"editors": []
|
||||
},
|
||||
"moduleFederation": {
|
||||
"name": "{{ mf_name }}",
|
||||
"exposes": ["./index"]
|
||||
}
|
||||
},
|
||||
{% endif -%}
|
||||
{% if include_backend -%}
|
||||
"backend": {
|
||||
"entryPoints": ["{{ backend_entry }}"],
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
import React from "react";
|
||||
import { core } from "@apache-superset/core";
|
||||
import { views } from "@apache-superset/core";
|
||||
|
||||
export const activate = (context: core.ExtensionContext) => {
|
||||
context.disposables.push(
|
||||
core.registerViewProvider("{{ id }}.example", () => <p>{{ name }}</p>)
|
||||
);
|
||||
console.log("{{ name }} extension activated");
|
||||
};
|
||||
|
||||
export const deactivate = () => {
|
||||
console.log("{{ name }} extension deactivated");
|
||||
};
|
||||
views.registerView(
|
||||
{ id: "{{ id }}.example", name: "{{ display_name }}" },
|
||||
"sqllab.panels",
|
||||
() => <p>{{ display_name }}</p>,
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const path = require("path");
|
||||
const { ModuleFederationPlugin } = require("webpack").container;
|
||||
const packageConfig = require("./package");
|
||||
const extensionConfig = require("../extension.json");
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
const isProd = argv.mode === "production";
|
||||
@@ -19,7 +20,7 @@ module.exports = (env, argv) => {
|
||||
filename: isProd ? undefined : "[name].[contenthash].js",
|
||||
chunkFilename: "[name].[contenthash].js",
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
publicPath: `/api/v1/extensions/{{ publisher }}/{{ name }}/`,
|
||||
publicPath: `/api/v1/extensions/${extensionConfig.publisher}/${extensionConfig.name}/`,
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".ts", ".tsx", ".js", ".jsx"],
|
||||
|
||||
@@ -59,20 +59,6 @@ def extension_with_build_structure():
|
||||
"permissions": [],
|
||||
}
|
||||
|
||||
if include_frontend:
|
||||
extension_json["frontend"] = {
|
||||
"contributions": {
|
||||
"commands": [],
|
||||
"views": {},
|
||||
"menus": {},
|
||||
"editors": [],
|
||||
},
|
||||
"moduleFederation": {
|
||||
"exposes": ["./index"],
|
||||
"name": "testOrg_testExtension",
|
||||
},
|
||||
}
|
||||
|
||||
if include_backend:
|
||||
extension_json["backend"] = {
|
||||
"entryPoints": [
|
||||
@@ -249,18 +235,6 @@ def test_build_manifest_creates_correct_manifest_structure(isolated_filesystem):
|
||||
"version": "1.0.0",
|
||||
"permissions": ["read_data"],
|
||||
"dependencies": ["some_dep"],
|
||||
"frontend": {
|
||||
"contributions": {
|
||||
"commands": [{"id": "test_command", "title": "Test"}],
|
||||
"views": {},
|
||||
"menus": {},
|
||||
"editors": [],
|
||||
},
|
||||
"moduleFederation": {
|
||||
"exposes": ["./index"],
|
||||
"name": "testOrg_testExtension",
|
||||
},
|
||||
},
|
||||
"backend": {
|
||||
"entryPoints": ["superset_extensions.test_org.test_extension.entrypoint"]
|
||||
},
|
||||
@@ -281,11 +255,8 @@ def test_build_manifest_creates_correct_manifest_structure(isolated_filesystem):
|
||||
|
||||
# Verify frontend section
|
||||
assert manifest.frontend is not None
|
||||
assert manifest.frontend.contributions.commands == [
|
||||
{"id": "test_command", "title": "Test"}
|
||||
]
|
||||
assert manifest.frontend.moduleFederation.exposes == ["./index"]
|
||||
assert manifest.frontend.remoteEntry == "remoteEntry.abc123.js"
|
||||
assert manifest.frontend.moduleFederationName == "testOrg_testExtension"
|
||||
|
||||
# Verify backend section
|
||||
assert manifest.backend is not None
|
||||
|
||||
@@ -223,21 +223,8 @@ def test_extension_json_content_is_correct(
|
||||
# Load and verify more complex nested structures
|
||||
content = load_json_file(extension_json_path)
|
||||
|
||||
# Verify frontend section exists and has correct structure
|
||||
assert "frontend" in content
|
||||
frontend = content["frontend"]
|
||||
assert "contributions" in frontend
|
||||
assert "moduleFederation" in frontend
|
||||
assert frontend["contributions"] == {
|
||||
"commands": [],
|
||||
"views": {},
|
||||
"menus": {},
|
||||
"editors": [],
|
||||
}
|
||||
assert frontend["moduleFederation"] == {
|
||||
"exposes": ["./index"],
|
||||
"name": "testOrg_testExtension",
|
||||
}
|
||||
# Verify frontend section is not present (contributions are code-first)
|
||||
assert "frontend" not in content
|
||||
|
||||
# Verify backend section exists and has correct structure
|
||||
assert "backend" in content
|
||||
|
||||
@@ -78,21 +78,8 @@ def test_extension_json_template_renders_with_both_frontend_and_backend(
|
||||
assert parsed["license"] == "Apache-2.0"
|
||||
assert parsed["permissions"] == []
|
||||
|
||||
# Verify frontend section exists
|
||||
assert "frontend" in parsed
|
||||
frontend = parsed["frontend"]
|
||||
assert "contributions" in frontend
|
||||
assert "moduleFederation" in frontend
|
||||
assert frontend["contributions"] == {
|
||||
"commands": [],
|
||||
"views": {},
|
||||
"menus": {},
|
||||
"editors": [],
|
||||
}
|
||||
assert frontend["moduleFederation"] == {
|
||||
"exposes": ["./index"],
|
||||
"name": "testOrg_testExtension",
|
||||
}
|
||||
# Verify frontend section is not present (contributions are code-first)
|
||||
assert "frontend" not in parsed
|
||||
|
||||
# Verify backend section exists
|
||||
assert "backend" in parsed
|
||||
@@ -109,7 +96,7 @@ def test_extension_json_template_renders_with_both_frontend_and_backend(
|
||||
@pytest.mark.parametrize(
|
||||
"include_frontend,include_backend,expected_sections",
|
||||
[
|
||||
(True, False, ["frontend"]),
|
||||
(True, False, []),
|
||||
(False, True, ["backend"]),
|
||||
(False, False, []),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user