@decaf-ts/integrations 0.3.12 → 0.4.1-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/README.md +11 -3
  2. package/dist/integrations.cjs +445 -7
  3. package/dist/integrations.js +479 -8
  4. package/jest.config.cjs +1 -1
  5. package/lib/cjs/feature-flags/constants.cjs +16 -0
  6. package/lib/cjs/feature-flags/decorators.cjs +65 -0
  7. package/lib/cjs/feature-flags/environment.cjs +26 -0
  8. package/lib/cjs/feature-flags/index.cjs +31 -0
  9. package/lib/cjs/feature-flags/models/FeatureFlag.model.cjs +81 -0
  10. package/lib/cjs/feature-flags/models/FeatureFlagAccess.model.cjs +78 -0
  11. package/lib/cjs/feature-flags/readers/FeatureFlagReader.cjs +25 -0
  12. package/lib/cjs/feature-flags/readers/index.cjs +19 -0
  13. package/lib/cjs/feature-flags/services/FeatureFlag.service.cjs +259 -0
  14. package/lib/cjs/feature-flags/types.cjs +4 -0
  15. package/lib/cjs/feature-flags/utils.cjs +141 -0
  16. package/lib/cjs/graph/engine/execution/SwitchGraphNodeExecutor.cjs +9 -9
  17. package/lib/cjs/graph/shared/nodes/flow-control.cjs +4 -3
  18. package/lib/cjs/graph/shared/types.cjs +2 -2
  19. package/lib/cjs/index.cjs +6 -5
  20. package/lib/cjs/kibana/builders/KibanaIndexBuilder.cjs +329 -0
  21. package/lib/cjs/kibana/builders/KibanaIndexBuilderCollection.cjs +37 -0
  22. package/lib/cjs/kibana/builders/index.cjs +20 -0
  23. package/lib/cjs/kibana/helpers.cjs +20 -16
  24. package/lib/cjs/kibana/index.cjs +3 -2
  25. package/lib/cjs/kibana/types.cjs +11 -2
  26. package/lib/cjs/loader/ObjectLoader.cjs +154 -0
  27. package/lib/cjs/loader/families.cjs +78 -0
  28. package/lib/cjs/loader/index.cjs +28 -0
  29. package/lib/cjs/loader/types.cjs +4 -0
  30. package/lib/cjs/nest/decorators.cjs +17 -0
  31. package/lib/cjs/nest/index.cjs +3 -3
  32. package/lib/cjs/nest/keycloakAuthHandler.cjs +74 -35
  33. package/lib/cjs/nest/keycloakModule.cjs +7 -10
  34. package/lib/cjs/nest/types.cjs +2 -2
  35. package/lib/cjs/nest/utils.cjs +58 -50
  36. package/lib/cjs/plugins/contract.cjs +76 -0
  37. package/lib/cjs/plugins/index.cjs +35 -0
  38. package/lib/cjs/plugins/kibana/host.cjs +24 -0
  39. package/lib/cjs/plugins/kibana/index.cjs +38 -0
  40. package/lib/cjs/plugins/kibana/installer.cjs +180 -0
  41. package/lib/cjs/plugins/kibana/manifest.cjs +33 -0
  42. package/lib/cjs/plugins/kibana/templates.cjs +503 -0
  43. package/lib/cjs/plugins/kibana/types.cjs +33 -0
  44. package/lib/cjs/plugins/superset/host.cjs +26 -0
  45. package/lib/cjs/plugins/superset/index.cjs +40 -0
  46. package/lib/cjs/plugins/superset/installer.cjs +232 -0
  47. package/lib/cjs/plugins/superset/manifest.cjs +35 -0
  48. package/lib/cjs/plugins/superset/templates.cjs +844 -0
  49. package/lib/cjs/plugins/superset/types.cjs +39 -0
  50. package/lib/esm/feature-flags/constants.js +12 -0
  51. package/lib/esm/feature-flags/decorators.js +49 -0
  52. package/lib/esm/feature-flags/environment.js +18 -0
  53. package/lib/esm/feature-flags/index.js +14 -0
  54. package/lib/esm/feature-flags/models/FeatureFlag.model.js +72 -0
  55. package/lib/esm/feature-flags/models/FeatureFlagAccess.model.js +69 -0
  56. package/lib/esm/feature-flags/readers/FeatureFlagReader.js +19 -0
  57. package/lib/esm/feature-flags/readers/index.js +2 -0
  58. package/lib/esm/feature-flags/services/FeatureFlag.service.js +250 -0
  59. package/lib/esm/feature-flags/types.js +2 -0
  60. package/lib/esm/feature-flags/utils.js +126 -0
  61. package/lib/esm/graph/engine/execution/SwitchGraphNodeExecutor.js +8 -8
  62. package/lib/esm/graph/shared/nodes/flow-control.js +3 -2
  63. package/lib/esm/graph/shared/types.js +1 -1
  64. package/lib/esm/index.js +5 -4
  65. package/lib/esm/kibana/builders/KibanaIndexBuilder.js +319 -0
  66. package/lib/esm/kibana/builders/KibanaIndexBuilderCollection.js +32 -0
  67. package/lib/esm/kibana/builders/index.js +3 -0
  68. package/lib/esm/kibana/helpers.js +19 -15
  69. package/lib/esm/kibana/index.js +2 -1
  70. package/lib/esm/kibana/types.js +13 -2
  71. package/lib/esm/loader/ObjectLoader.js +115 -0
  72. package/lib/esm/loader/families.js +66 -0
  73. package/lib/esm/loader/index.js +11 -0
  74. package/lib/esm/loader/types.js +2 -0
  75. package/lib/esm/nest/decorators.js +12 -0
  76. package/lib/esm/nest/index.js +2 -2
  77. package/lib/esm/nest/keycloakAuthHandler.js +67 -35
  78. package/lib/esm/nest/keycloakModule.js +7 -10
  79. package/lib/esm/nest/types.js +1 -1
  80. package/lib/esm/nest/utils.js +55 -46
  81. package/lib/esm/plugins/contract.js +68 -0
  82. package/lib/esm/plugins/index.js +18 -0
  83. package/lib/esm/plugins/kibana/host.js +19 -0
  84. package/lib/esm/plugins/kibana/index.js +14 -0
  85. package/lib/esm/plugins/kibana/installer.js +140 -0
  86. package/lib/esm/plugins/kibana/manifest.js +32 -0
  87. package/lib/esm/plugins/kibana/templates.js +499 -0
  88. package/lib/esm/plugins/kibana/types.js +10 -0
  89. package/lib/esm/plugins/superset/host.js +21 -0
  90. package/lib/esm/plugins/superset/index.js +16 -0
  91. package/lib/esm/plugins/superset/installer.js +192 -0
  92. package/lib/esm/plugins/superset/manifest.js +30 -0
  93. package/lib/esm/plugins/superset/templates.js +840 -0
  94. package/lib/esm/plugins/superset/types.js +11 -0
  95. package/lib/types/feature-flags/constants.d.cts +11 -0
  96. package/lib/types/feature-flags/constants.d.mts +11 -0
  97. package/lib/types/feature-flags/decorators.d.cts +11 -0
  98. package/lib/types/feature-flags/decorators.d.mts +11 -0
  99. package/lib/types/feature-flags/environment.d.cts +11 -0
  100. package/lib/types/feature-flags/environment.d.mts +11 -0
  101. package/lib/types/feature-flags/index.d.cts +13 -0
  102. package/lib/types/feature-flags/index.d.mts +13 -0
  103. package/lib/types/feature-flags/models/FeatureFlag.model.d.cts +16 -0
  104. package/lib/types/feature-flags/models/FeatureFlag.model.d.mts +16 -0
  105. package/lib/types/feature-flags/models/FeatureFlagAccess.model.d.cts +15 -0
  106. package/lib/types/feature-flags/models/FeatureFlagAccess.model.d.mts +15 -0
  107. package/lib/types/feature-flags/readers/FeatureFlagReader.d.cts +10 -0
  108. package/lib/types/feature-flags/readers/FeatureFlagReader.d.mts +10 -0
  109. package/lib/types/feature-flags/readers/index.d.cts +1 -0
  110. package/lib/types/feature-flags/readers/index.d.mts +1 -0
  111. package/lib/types/feature-flags/services/FeatureFlag.service.d.cts +43 -0
  112. package/lib/types/feature-flags/services/FeatureFlag.service.d.mts +43 -0
  113. package/lib/types/feature-flags/types.d.cts +39 -0
  114. package/lib/types/feature-flags/types.d.mts +39 -0
  115. package/lib/types/feature-flags/utils.d.cts +13 -0
  116. package/lib/types/feature-flags/utils.d.mts +13 -0
  117. package/lib/types/graph/engine/execution/SwitchGraphNodeExecutor.d.cts +2 -2
  118. package/lib/types/graph/engine/execution/SwitchGraphNodeExecutor.d.mts +2 -2
  119. package/lib/types/graph/shared/types.d.cts +3 -3
  120. package/lib/types/graph/shared/types.d.mts +3 -3
  121. package/lib/types/index.d.cts +3 -2
  122. package/lib/types/index.d.mts +3 -2
  123. package/lib/types/kibana/builders/KibanaIndexBuilder.d.cts +67 -0
  124. package/lib/types/kibana/builders/KibanaIndexBuilder.d.mts +67 -0
  125. package/lib/types/kibana/builders/KibanaIndexBuilderCollection.d.cts +17 -0
  126. package/lib/types/kibana/builders/KibanaIndexBuilderCollection.d.mts +17 -0
  127. package/lib/types/kibana/builders/index.d.cts +2 -0
  128. package/lib/types/kibana/builders/index.d.mts +2 -0
  129. package/lib/types/kibana/index.d.cts +1 -0
  130. package/lib/types/kibana/index.d.mts +1 -0
  131. package/lib/types/kibana/types.d.cts +11 -0
  132. package/lib/types/kibana/types.d.mts +11 -0
  133. package/lib/types/loader/ObjectLoader.d.cts +27 -0
  134. package/lib/types/loader/ObjectLoader.d.mts +27 -0
  135. package/lib/types/loader/families.d.cts +34 -0
  136. package/lib/types/loader/families.d.mts +34 -0
  137. package/lib/types/loader/index.d.cts +10 -0
  138. package/lib/types/loader/index.d.mts +10 -0
  139. package/lib/types/loader/types.d.cts +24 -0
  140. package/lib/types/loader/types.d.mts +24 -0
  141. package/lib/types/nest/decorators.d.cts +8 -0
  142. package/lib/types/nest/decorators.d.mts +8 -0
  143. package/lib/types/nest/index.d.cts +1 -1
  144. package/lib/types/nest/index.d.mts +1 -1
  145. package/lib/types/nest/keycloakAuthHandler.d.cts +19 -42
  146. package/lib/types/nest/keycloakAuthHandler.d.mts +19 -42
  147. package/lib/types/nest/keycloakModule.d.cts +3 -5
  148. package/lib/types/nest/keycloakModule.d.mts +3 -5
  149. package/lib/types/nest/types.d.cts +2 -0
  150. package/lib/types/nest/types.d.mts +2 -0
  151. package/lib/types/nest/utils.d.cts +3 -4
  152. package/lib/types/nest/utils.d.mts +3 -4
  153. package/lib/types/plugins/contract.d.cts +180 -0
  154. package/lib/types/plugins/contract.d.mts +180 -0
  155. package/lib/types/plugins/index.d.cts +17 -0
  156. package/lib/types/plugins/index.d.mts +17 -0
  157. package/lib/types/plugins/kibana/host.d.cts +18 -0
  158. package/lib/types/plugins/kibana/host.d.mts +18 -0
  159. package/lib/types/plugins/kibana/index.d.cts +13 -0
  160. package/lib/types/plugins/kibana/index.d.mts +13 -0
  161. package/lib/types/plugins/kibana/installer.d.cts +45 -0
  162. package/lib/types/plugins/kibana/installer.d.mts +45 -0
  163. package/lib/types/plugins/kibana/manifest.d.cts +31 -0
  164. package/lib/types/plugins/kibana/manifest.d.mts +31 -0
  165. package/lib/types/plugins/kibana/templates.d.cts +12 -0
  166. package/lib/types/plugins/kibana/templates.d.mts +12 -0
  167. package/lib/types/plugins/kibana/types.d.cts +9 -0
  168. package/lib/types/plugins/kibana/types.d.mts +9 -0
  169. package/lib/types/plugins/superset/host.d.cts +20 -0
  170. package/lib/types/plugins/superset/host.d.mts +20 -0
  171. package/lib/types/plugins/superset/index.d.cts +15 -0
  172. package/lib/types/plugins/superset/index.d.mts +15 -0
  173. package/lib/types/plugins/superset/installer.d.cts +70 -0
  174. package/lib/types/plugins/superset/installer.d.mts +70 -0
  175. package/lib/types/plugins/superset/manifest.d.cts +28 -0
  176. package/lib/types/plugins/superset/manifest.d.mts +28 -0
  177. package/lib/types/plugins/superset/templates.d.cts +12 -0
  178. package/lib/types/plugins/superset/templates.d.mts +12 -0
  179. package/lib/types/plugins/superset/types.d.cts +10 -0
  180. package/lib/types/plugins/superset/types.d.mts +10 -0
  181. package/package.json +62 -3
  182. package/plugins/kibana/.gitignore +16 -0
  183. package/plugins/kibana/Dockerfile +19 -0
  184. package/plugins/kibana/docker-compose.yml +50 -0
  185. package/plugins/kibana/host/index.html +101 -0
  186. package/plugins/kibana/setup-dashboards.sh +84 -0
  187. package/plugins/superset/.gitignore +17 -0
  188. package/plugins/superset/Dockerfile +79 -0
  189. package/plugins/superset/docker-compose.yml +62 -0
  190. package/plugins/superset/host/index.html +168 -0
  191. package/plugins/superset/setup-dashboards.sh +106 -0
  192. package/plugins/superset/superset_config.py +49 -0
  193. package/lib/cjs/nest/authService.cjs +0 -91
  194. package/lib/esm/nest/authService.js +0 -86
  195. package/lib/types/nest/authService.d.cts +0 -63
  196. package/lib/types/nest/authService.d.mts +0 -63
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Creates two dummy dashboards in Kibana via the saved objects API.
4
+ #
5
+ # Usage: setup-dashboards.sh <kibana_host>
6
+ # kibana_host e.g. http://localhost:5602
7
+ #
8
+ set -euo pipefail
9
+
10
+ KIBANA_HOST=${1:?Usage: setup-dashboards.sh <kibana_host>}
11
+
12
+ echo "Waiting for Kibana to be ready..."
13
+ for i in $(seq 1 60); do
14
+ if curl -sf "${KIBANA_HOST}/api/status" >/dev/null 2>&1; then
15
+ echo "Kibana is ready."
16
+ break
17
+ fi
18
+ sleep 2
19
+ done
20
+
21
+ # Create an index pattern first (required for dashboards)
22
+ echo "Creating index pattern..."
23
+ INDEX_PATTERN_RESPONSE=$(curl -sf -X POST "${KIBANA_HOST}/api/saved_objects/index-pattern" \
24
+ -H "kbn-xsrf: true" \
25
+ -H "Content-Type: application/json" \
26
+ -d '{
27
+ "attributes": {
28
+ "title": "test-logs-*",
29
+ "timeFieldName": "@timestamp"
30
+ }
31
+ }')
32
+
33
+ INDEX_PATTERN_ID=$(echo "$INDEX_PATTERN_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
34
+ echo "Created index pattern: $INDEX_PATTERN_ID"
35
+
36
+ # Create Dashboard A
37
+ echo "Creating Dashboard A..."
38
+ DASHBOARD_A_RESPONSE=$(curl -sf -X POST "${KIBANA_HOST}/api/saved_objects/dashboard" \
39
+ -H "kbn-xsrf: true" \
40
+ -H "Content-Type: application/json" \
41
+ -d "{
42
+ \"attributes\": {
43
+ \"title\": \"E2E Test Dashboard A\",
44
+ \"description\": \"Dashboard A for e2e testing\",
45
+ \"panelsJSON\": \"[]\",
46
+ \"optionsJSON\": \"{\\\"hidePanelTitles\\\":false,\\\"useMargins\\\":true}\",
47
+ \"version\": 3,
48
+ \"timeRestore\": false
49
+ }
50
+ }")
51
+
52
+ DASHBOARD_A_ID=$(echo "$DASHBOARD_A_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
53
+ echo "Created Dashboard A: $DASHBOARD_A_ID"
54
+
55
+ # Create Dashboard B
56
+ echo "Creating Dashboard B..."
57
+ DASHBOARD_B_RESPONSE=$(curl -sf -X POST "${KIBANA_HOST}/api/saved_objects/dashboard" \
58
+ -H "kbn-xsrf: true" \
59
+ -H "Content-Type: application/json" \
60
+ -d "{
61
+ \"attributes\": {
62
+ \"title\": \"E2E Test Dashboard B\",
63
+ \"description\": \"Dashboard B for e2e testing\",
64
+ \"panelsJSON\": \"[]\",
65
+ \"optionsJSON\": \"{\\\"hidePanelTitles\\\":false,\\\"useMargins\\\":true}\",
66
+ \"version\": 3,
67
+ \"timeRestore\": false
68
+ }
69
+ }")
70
+
71
+ DASHBOARD_B_ID=$(echo "$DASHBOARD_B_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
72
+ echo "Created Dashboard B: $DASHBOARD_B_ID"
73
+
74
+ # Output the dashboard IDs for the test harness
75
+ cat > "$(dirname "$0")/dashboards.json" << EOF
76
+ {
77
+ "indexPatternId": "$INDEX_PATTERN_ID",
78
+ "dashboardA": "$DASHBOARD_A_ID",
79
+ "dashboardB": "$DASHBOARD_B_ID"
80
+ }
81
+ EOF
82
+
83
+ echo "Dashboard setup complete."
84
+ cat "$(dirname "$0")/dashboards.json"
@@ -0,0 +1,17 @@
1
+ # Ignore everything by default
2
+ *
3
+
4
+ # Re-include the .gitignore itself
5
+ !.gitignore
6
+
7
+ # Re-include curated configuration (Dockerfiles, compose, config, host pages, scripts)
8
+ !Dockerfile
9
+ !docker-compose.yml
10
+ !superset_config.py
11
+ !setup-dashboards.sh
12
+ !dashboards.json
13
+ !host/
14
+ !host/**
15
+
16
+ # Everything else (generated patch scripts org_dashboard_embed_superset/,
17
+ # cloned Superset source .superset-source/, build artifacts, node_modules) remains ignored
@@ -0,0 +1,79 @@
1
+ # Custom Superset image built from source with the switchable-dashboard patch.
2
+ #
3
+ # This Dockerfile clones the Apache Superset source, applies the patch scripts
4
+ # (materialized by SupersetDashboardEmbedPlugin.install()), builds the SDK and
5
+ # frontend, and produces a lean runtime image.
6
+ #
7
+ # Build context is the integrations/plugins/superset/ directory, which contains:
8
+ # - org_dashboard_embed_superset/ (generated by install())
9
+ # - superset_config.py (curated runtime config)
10
+ #
11
+ FROM node:18-slim AS builder
12
+
13
+ RUN apt-get update && apt-get install -y --no-install-recommends \
14
+ git python3 python3-pip curl bash \
15
+ && rm -rf /var/lib/apt/lists/*
16
+
17
+ WORKDIR /build
18
+
19
+ # Clone Superset source
20
+ ARG SUPERSET_GIT_URL=https://github.com/apache/superset.git
21
+ ARG SUPERSET_GIT_REF=6.1.0
22
+ RUN git clone --depth 1 --branch ${SUPERSET_GIT_REF} ${SUPERSET_GIT_URL} /build/superset
23
+
24
+ # Copy patch scripts (materialized by install())
25
+ COPY org_dashboard_embed_superset/patches/ /build/patches/
26
+ COPY org_dashboard_embed_superset/build/ /build/build-scripts/
27
+
28
+ # Apply patch
29
+ RUN python3 /build/patches/apply_superset_6_1_patch.py /build/superset
30
+
31
+ # Verify patch
32
+ RUN bash /build/patches/verify_patch.sh /build/superset
33
+
34
+ # Build SDK
35
+ RUN cd /build/superset/superset-embedded-sdk && npm ci && npm run build
36
+
37
+ # Build frontend
38
+ RUN cd /build/superset/superset-frontend && npm ci && npm run build
39
+
40
+ # ─── Runtime stage ──────────────────────────────────────────────────────
41
+ FROM node:18-slim AS runtime
42
+
43
+ RUN apt-get update && apt-get install -y --no-install-recommends \
44
+ python3 python3-pip python3-venv curl bash \
45
+ && rm -rf /var/lib/apt/lists/*
46
+
47
+ RUN python3 -m venv /app/venv
48
+ ENV PATH="/app/venv/bin:$PATH"
49
+
50
+ WORKDIR /app
51
+
52
+ # Install Superset Python dependencies
53
+ RUN pip install --no-cache-dir \
54
+ apache-superset==6.1.0 \
55
+ psycopg2-binary \
56
+ celery \
57
+ redis \
58
+ gunicorn
59
+
60
+ # Copy built frontend assets from builder
61
+ COPY --from=builder /build/superset/superset-frontend/ /app/superset-frontend/
62
+
63
+ # Copy built SDK
64
+ COPY --from=builder /build/superset/superset-embedded-sdk/ /app/superset-embedded-sdk/
65
+
66
+ # Copy Superset config
67
+ COPY superset_config.py /app/
68
+
69
+ ENV SUPERSET_CONFIG_PATH=/app/superset_config.py
70
+ ENV FLASK_APP=superset
71
+
72
+ EXPOSE 8088
73
+
74
+ # Initialize Superset
75
+ RUN superset db upgrade && \
76
+ superset fab create-admin --username admin --firstname Admin --lastname User --email admin@example.com --password admin || true && \
77
+ superset init
78
+
79
+ CMD ["gunicorn", "-b", "0.0.0.0:8088", "-w", "4", "--timeout", "120", "superset.app:create_app()"]
@@ -0,0 +1,62 @@
1
+ services:
2
+ postgres:
3
+ image: postgres:16-alpine
4
+ environment:
5
+ POSTGRES_DB: superset
6
+ POSTGRES_USER: superset
7
+ POSTGRES_PASSWORD: superset
8
+ ports:
9
+ - "15433:5432"
10
+ healthcheck:
11
+ test: ["CMD-SHELL", "pg_isready -U superset"]
12
+ interval: 5s
13
+ timeout: 5s
14
+ retries: 10
15
+ networks:
16
+ - e2e
17
+
18
+ redis:
19
+ image: redis:7-alpine
20
+ ports:
21
+ - "16380:6379"
22
+ healthcheck:
23
+ test: ["CMD", "redis-cli", "ping"]
24
+ interval: 5s
25
+ timeout: 5s
26
+ retries: 10
27
+ networks:
28
+ - e2e
29
+
30
+ superset:
31
+ build:
32
+ context: .
33
+ dockerfile: Dockerfile
34
+ args:
35
+ SUPERSET_GIT_URL: https://github.com/apache/superset.git
36
+ SUPERSET_GIT_REF: "6.1.0"
37
+ environment:
38
+ - SUPERSET_CONFIG_PATH=/app/superset_config.py
39
+ - SUPERSET_GUEST_TOKEN_JWT_SECRET=e2e-test-secret-at-least-32-chars-long
40
+ - DATABASE_URL=postgresql+psycopg2://superset:superset@postgres:5432/superset
41
+ - REDIS_URL=redis://redis:6379/0
42
+ - SUPERSET_SECRET_KEY=e2e-test-secret-key-for-flask
43
+ - TALISMAN_ENABLED=false
44
+ ports:
45
+ - "8089:8088"
46
+ depends_on:
47
+ postgres:
48
+ condition: service_healthy
49
+ redis:
50
+ condition: service_healthy
51
+ healthcheck:
52
+ test: ["CMD-SHELL", "curl -sf http://localhost:8088/health || exit 1"]
53
+ interval: 10s
54
+ timeout: 10s
55
+ retries: 30
56
+ start_period: 60s
57
+ networks:
58
+ - e2e
59
+
60
+ networks:
61
+ e2e:
62
+ driver: bridge
@@ -0,0 +1,168 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>Superset Embed E2E Test Host</title>
6
+ <style>
7
+ * { margin: 0; padding: 0; box-sizing: border-box; }
8
+ body { font-family: -apple-system, sans-serif; height: 100vh; display: flex; flex-direction: column; }
9
+ .toolbar { padding: 12px 20px; background: #f0f0f0; border-bottom: 1px solid #ccc; display: flex; gap: 12px; align-items: center; }
10
+ .toolbar h1 { font-size: 16px; font-weight: 600; margin-right: auto; }
11
+ .toolbar button { padding: 8px 16px; border: 1px solid #ccc; border-radius: 4px; background: #fff; cursor: pointer; font-size: 14px; }
12
+ .toolbar button:hover { background: #e8e8e8; }
13
+ .toolbar button.active { background: #0066cc; color: #fff; border-color: #0066cc; }
14
+ #status { font-size: 12px; color: #666; padding: 4px 20px; background: #fafafa; }
15
+ .embed-container { flex: 1; position: relative; overflow: hidden; }
16
+ #supersetMount { width: 100%; height: 100%; }
17
+ #supersetMount iframe { width: 100%; height: 100%; border: 0; display: block; }
18
+ </style>
19
+ </head>
20
+ <body>
21
+ <div class="toolbar">
22
+ <h1>Superset Dashboard Embed E2E</h1>
23
+ <button id="btn-a" class="active">Dashboard A</button>
24
+ <button id="btn-b">Dashboard B</button>
25
+ </div>
26
+ <div id="status">Initializing...</div>
27
+ <div class="embed-container">
28
+ <div id="supersetMount"></div>
29
+ </div>
30
+
31
+ <!-- The patched SDK is loaded from the Superset container -->
32
+ <script type="module">
33
+ // These values are injected by the test harness via config.js
34
+ const config = window.__E2E_CONFIG || {};
35
+ const supersetHost = config.supersetHost || 'http://localhost:8089';
36
+ const embeddedA = config.embeddedA || '';
37
+ const embeddedB = config.embeddedB || '';
38
+ const dashboardA = config.dashboardA || '';
39
+ const dashboardB = config.dashboardB || '';
40
+
41
+ const status = document.getElementById('status');
42
+ const mountPoint = document.getElementById('supersetMount');
43
+
44
+ // Import the patched SDK from the Superset container
45
+ // The SDK is built from patched source and served by Superset
46
+ let embeddedDashboard = null;
47
+
48
+ // Guest token fetch — calls Superset guest token API
49
+ async function fetchGuestToken(dashboardId) {
50
+ status.textContent = `Fetching guest token for ${dashboardId || 'initial'}...`;
51
+ const url = dashboardId
52
+ ? `${supersetHost}/api/v1/security/guest_token/`
53
+ : `${supersetHost}/api/v1/security/guest_token/`;
54
+
55
+ // For e2e, we use the admin access token to create guest tokens
56
+ const loginResponse = await fetch(`${supersetHost}/api/v1/security/login`, {
57
+ method: 'POST',
58
+ headers: { 'Content-Type': 'application/json' },
59
+ body: JSON.stringify({
60
+ username: 'admin',
61
+ password: 'admin',
62
+ provider: 'db',
63
+ refresh: false,
64
+ }),
65
+ });
66
+ const loginData = await loginResponse.json();
67
+ const accessToken = loginData.access_token;
68
+
69
+ const targetDashboard = dashboardId || dashboardA;
70
+ const response = await fetch(url, {
71
+ method: 'POST',
72
+ headers: {
73
+ 'Authorization': `Bearer ${accessToken}`,
74
+ 'Content-Type': 'application/json',
75
+ },
76
+ body: JSON.stringify({
77
+ user: { username: 'e2e-user', first_name: 'E2E', last_name: 'Test' },
78
+ resources: [{ type: 'dashboard', id: targetDashboard }],
79
+ rls: [],
80
+ }),
81
+ });
82
+ const data = await response.json();
83
+ status.textContent = `Got guest token for ${targetDashboard}`;
84
+ return data.token;
85
+ }
86
+
87
+ async function initEmbed() {
88
+ try {
89
+ status.textContent = 'Loading Superset embedded SDK...';
90
+
91
+ // Dynamically import the SDK from the Superset container
92
+ // The patched SDK is available at /superset-embedded-sdk/
93
+ const sdkModule = await import(`${supersetHost}/superset-embedded-sdk/dist/index.mjs`);
94
+ const { embedDashboard } = sdkModule;
95
+
96
+ status.textContent = 'Mounting embedded dashboard...';
97
+
98
+ embeddedDashboard = await embedDashboard({
99
+ id: embeddedA,
100
+ supersetDomain: supersetHost,
101
+ mountPoint: mountPoint,
102
+ fetchGuestToken: fetchGuestToken,
103
+ dashboardUiConfig: {
104
+ hideTitle: true,
105
+ hideTab: true,
106
+ hideChartControls: true,
107
+ filters: { visible: true, expanded: false },
108
+ urlParams: { standalone: '1' },
109
+ },
110
+ iframeTitle: 'Superset E2E Dashboard',
111
+ });
112
+
113
+ window.__E2E_READY = true;
114
+ window.__E2E_EMBEDDED = embeddedDashboard;
115
+ status.textContent = `READY — embedded: ${embeddedA}`;
116
+
117
+ // Capture the original iframe reference
118
+ const iframe = mountPoint.querySelector('iframe');
119
+ window.__ORIGINAL_IFRAME = iframe;
120
+ } catch (err) {
121
+ status.textContent = `ERROR — ${err.message}`;
122
+ window.__E2E_ERROR = err.message;
123
+ console.error(err);
124
+ }
125
+ }
126
+
127
+ async function switchDashboard(dashboardId) {
128
+ if (!embeddedDashboard) {
129
+ status.textContent = 'Embedded dashboard not ready';
130
+ return;
131
+ }
132
+
133
+ try {
134
+ status.textContent = `Switching to ${dashboardId}...`;
135
+ window.__E2E_SWITCH_RESULT = null;
136
+
137
+ const result = await embeddedDashboard.switchDashboard(dashboardId);
138
+ window.__E2E_SWITCH_RESULT = result;
139
+ status.textContent = `Switched to ${result.dashboardId}`;
140
+ } catch (err) {
141
+ status.textContent = `Switch error — ${err.message}`;
142
+ window.__E2E_ERROR = err.message;
143
+ console.error(err);
144
+ }
145
+ }
146
+
147
+ // Button handlers
148
+ document.getElementById('btn-a').addEventListener('click', () => {
149
+ switchDashboard(dashboardA);
150
+ document.querySelectorAll('.toolbar button').forEach(b => b.classList.remove('active'));
151
+ document.getElementById('btn-a').classList.add('active');
152
+ });
153
+
154
+ document.getElementById('btn-b').addEventListener('click', () => {
155
+ switchDashboard(dashboardB);
156
+ document.querySelectorAll('.toolbar button').forEach(b => b.classList.remove('active'));
157
+ document.getElementById('btn-b').classList.add('active');
158
+ });
159
+
160
+ // Expose for Playwright
161
+ window.__E2E_SWITCH = switchDashboard;
162
+ window.__E2E_INIT = initEmbed;
163
+
164
+ // Start initialization
165
+ initEmbed();
166
+ </script>
167
+ </body>
168
+ </html>
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Creates two dummy dashboards in Superset via the REST API.
4
+ # Also creates an embedded configuration for each dashboard and sets allowed domains.
5
+ #
6
+ # Usage: setup-dashboards.sh <superset_host>
7
+ # superset_host e.g. http://localhost:8089
8
+ #
9
+ set -euo pipefail
10
+
11
+ SUPERSET_HOST=${1:?Usage: setup-dashboards.sh <superset_host>}
12
+
13
+ echo "Waiting for Superset to be ready..."
14
+ for i in $(seq 1 60); do
15
+ if curl -sf "${SUPERSET_HOST}/health" >/dev/null 2>&1; then
16
+ echo "Superset is ready."
17
+ break
18
+ fi
19
+ sleep 2
20
+ done
21
+
22
+ # Authenticate and get access token
23
+ echo "Authenticating..."
24
+ LOGIN_RESPONSE=$(curl -sf -X POST "${SUPERSET_HOST}/api/v1/security/login" \
25
+ -H "Content-Type: application/json" \
26
+ -d '{
27
+ "username": "admin",
28
+ "password": "admin",
29
+ "provider": "db",
30
+ "refresh": false
31
+ }')
32
+
33
+ ACCESS_TOKEN=$(echo "$LOGIN_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")
34
+ echo "Got access token."
35
+
36
+ AUTH_HEADER="Authorization: Bearer ${ACCESS_TOKEN}"
37
+
38
+ # Create Dashboard A
39
+ echo "Creating Dashboard A..."
40
+ DASHBOARD_A_RESPONSE=$(curl -sf -X POST "${SUPERSET_HOST}/api/v1/dashboard/" \
41
+ -H "${AUTH_HEADER}" \
42
+ -H "Content-Type: application/json" \
43
+ -d '{
44
+ "dashboard_title": "E2E Test Dashboard A",
45
+ "slug": "e2e-dashboard-a",
46
+ "position_json": "{\"DASHBOARD_VERSION_KEY\": \"v2\"}",
47
+ "metadata": "{\"chart_configuration\": {}}"
48
+ }')
49
+
50
+ DASHBOARD_A_ID=$(echo "$DASHBOARD_A_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
51
+ echo "Created Dashboard A: $DASHBOARD_A_ID"
52
+
53
+ # Create Dashboard B
54
+ echo "Creating Dashboard B..."
55
+ DASHBOARD_B_RESPONSE=$(curl -sf -X POST "${SUPERSET_HOST}/api/v1/dashboard/" \
56
+ -H "${AUTH_HEADER}" \
57
+ -H "Content-Type: application/json" \
58
+ -d '{
59
+ "dashboard_title": "E2E Test Dashboard B",
60
+ "slug": "e2e-dashboard-b",
61
+ "position_json": "{\"DASHBOARD_VERSION_KEY\": \"v2\"}",
62
+ "metadata": "{\"chart_configuration\": {}}"
63
+ }')
64
+
65
+ DASHBOARD_B_ID=$(echo "$DASHBOARD_B_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
66
+ echo "Created Dashboard B: $DASHBOARD_B_ID"
67
+
68
+ # Create embedded configurations for both dashboards
69
+ echo "Creating embedded configuration for Dashboard A..."
70
+ EMBEDDED_A_RESPONSE=$(curl -sf -X POST "${SUPERSET_HOST}/api/v1/dashboard/embedded/" \
71
+ -H "${AUTH_HEADER}" \
72
+ -H "Content-Type: application/json" \
73
+ -d "{
74
+ \"resource_name\": \"Dashboard\",
75
+ \"resource_id\": ${DASHBOARD_A_ID},
76
+ \"allowed_domains\": [\"http://localhost:3002\", \"http://localhost:3001\"]
77
+ }")
78
+
79
+ EMBEDDED_A_UUID=$(echo "$EMBEDDED_A_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['uuid'])")
80
+ echo "Created embedded config A: $EMBEDDED_A_UUID"
81
+
82
+ echo "Creating embedded configuration for Dashboard B..."
83
+ EMBEDDED_B_RESPONSE=$(curl -sf -X POST "${SUPERSET_HOST}/api/v1/dashboard/embedded/" \
84
+ -H "${AUTH_HEADER}" \
85
+ -H "Content-Type: application/json" \
86
+ -d "{
87
+ \"resource_name\": \"Dashboard\",
88
+ \"resource_id\": ${DASHBOARD_B_ID},
89
+ \"allowed_domains\": [\"http://localhost:3002\", \"http://localhost:3001\"]
90
+ }")
91
+
92
+ EMBEDDED_B_UUID=$(echo "$EMBEDDED_B_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['uuid'])")
93
+ echo "Created embedded config B: $EMBEDDED_B_UUID"
94
+
95
+ # Output the dashboard IDs for the test harness
96
+ cat > "$(dirname "$0")/dashboards.json" << EOF
97
+ {
98
+ "dashboardA": "${DASHBOARD_A_ID}",
99
+ "dashboardB": "${DASHBOARD_B_ID}",
100
+ "embeddedA": "${EMBEDDED_A_UUID}",
101
+ "embeddedB": "${EMBEDDED_B_UUID}"
102
+ }
103
+ EOF
104
+
105
+ echo "Dashboard setup complete."
106
+ cat "$(dirname "$0")/dashboards.json"
@@ -0,0 +1,49 @@
1
+ """Superset configuration for e2e testing."""
2
+
3
+ import os
4
+
5
+ # Database
6
+ SQLALCHEMY_DATABASE_URI = os.environ.get(
7
+ "DATABASE_URL", "postgresql+psycopg2://superset:superset@postgres:5432/superset"
8
+ )
9
+
10
+ # Redis
11
+ REDIS_HOST = os.environ.get("REDIS_HOST", "redis")
12
+ REDIS_PORT = int(os.environ.get("REDIS_PORT", "6379"))
13
+ CELERY_REDIS_URL = f"redis://{REDIS_HOST}:{REDIS_PORT}/0"
14
+ CACHE_REDIS_URL = f"redis://{REDIS_HOST}:{REDIS_PORT}/1"
15
+
16
+ # Secret key
17
+ SECRET_KEY = os.environ.get("SUPERSET_SECRET_KEY", "e2e-test-secret-key-for-flask")
18
+
19
+ # Enable embedded dashboards
20
+ FEATURE_FLAGS = {
21
+ "EMBEDDED_SUPERSET": True,
22
+ "EMBEDDABLE_DASHBOARDS": True,
23
+ }
24
+
25
+ # Guest token
26
+ GUEST_ROLE_NAME = "EmbeddedGuest"
27
+ GUEST_TOKEN_JWT_SECRET = os.environ.get("SUPERSET_GUEST_TOKEN_JWT_SECRET", "e2e-test-secret-at-least-32-chars-long")
28
+ GUEST_TOKEN_JWT_ALGO = "HS256"
29
+ GUEST_TOKEN_HEADER_NAME = "X-GuestToken"
30
+
31
+ # Disable Talisman for e2e (no HTTPS)
32
+ TALISMAN_ENABLED = False
33
+
34
+ # CORS
35
+ ENABLE_CORS = True
36
+ CORS_OPTIONS = {
37
+ "origins": ["*"],
38
+ "supports_credentials": False,
39
+ }
40
+
41
+ # Allowed domains for embedded dashboards — allows localhost for e2e tests
42
+ # This is set per-dashboard via the API, but the default is permissive for e2e
43
+ HTTP_HEADERS = {}
44
+
45
+ # Session
46
+ SESSION_COOKIE_SECURE = False
47
+
48
+ # Logging
49
+ LOG_LEVEL = "INFO"