Skip to content

feat(ui): modularize admin scope into independent modules#3137

Merged
jonpspri merged 1 commit intomainfrom
admin-scope-modularised
Apr 2, 2026
Merged

feat(ui): modularize admin scope into independent modules#3137
jonpspri merged 1 commit intomainfrom
admin-scope-modularised

Conversation

@crivetimihai
Copy link
Copy Markdown
Member

@crivetimihai crivetimihai commented Feb 24, 2026

Admin UI Modularisation

The Problem

The original mcpgateway/static/admin.js was a 33,812-line monolithic file — all UI logic, state management, API calls, validation, and event handling in one place. It was untestable in isolation, slow to load, and impossible to maintain at scale.


What Was Done

1. Decomposition into 44 ES Modules (mcpgateway/admin_ui/)

The monolith was split into focused, single-responsibility modules across four conceptual layers:

Layer Modules Purpose
Foundation bootstrap.js, appState.js, utils.js, constants.js, security.js Shared primitives, state, XSS protection
Domain tools.js, servers.js, teams.js, gateway.js, tokens.js, llmModels.js, llmChat.js, prompts.js, resources.js, users.js, roots.js, a2aAgents.js Entity-level CRUD, testing, validation
Features auth.js, filters.js, search.js, tabs.js, pagination.js, modals.js, logging.js, metrics.js, plugins.js, monitoring.js, etc. UI concerns, cross-cutting features
Orchestration initialization.js, events.js, app.js, formSubmitHandlers.js Startup, HTMX delegation, chart registry

2. Facade Pattern (admin_ui/admin.js)

A single facade aggregates all 35+ module exports and exposes them onto the window.Admin namespace — preserving the existing HTML contract where HTMX/Alpine templates call Admin.editTool(...), Admin.showTab(...), etc. No template changes required.

index.js
  └─→ admin.js (facade)
        ├─→ bootstrap.js         (window.Admin = {})
        ├─→ utils.js, tools.js, servers.js ... (ES modules → Admin.fn = fn)
        ├─→ events.js            (IIFE, self-registers)
        └─→ app.js               (IIFE, self-registers)

3. Vite Build Pipeline

A new Vite configuration (vite.config.js) bundles admin_ui/index.js into an IIFE format output at mcpgateway/static/bundle-[HASH].js. The hash changes on every rebuild, providing automatic cache busting. External libraries (HTMX, Alpine, Chart.js, CodeMirror, DOMPurify) remain CDN-loaded and are declared as globals — not bundled.

Python's mcpgateway/admin.py reads the Vite manifest at startup to resolve the hashed filename, injecting it into the admin template as {{ bundle_js }}.

4. Test Suite: 20% → 70%+ Coverage

44 new Vitest unit test files in tests/unit/js/, one per module, using:

  • jsdom environment to simulate the browser DOM
  • vi.mock() for clean module isolation
  • AppState.reset() in afterEach to prevent test pollution
  • Istanbul as coverage provider (text + JSON + HTML + lcov reporters)

The vitest.config.js instruments only mcpgateway/admin_ui/**/*.js (not the compiled bundle), giving accurate per-module coverage.

5. Playwright Tests Maintained

End-to-end Playwright tests continue to pass at the same success rate — the public API (window.Admin.*) is unchanged, so browser-level test contracts were not broken by the refactor.


Key Design Decisions

  • Sequential import order in the facade: bootstrap.js must initialise window.Admin before any module tries to write to it.
  • IIFE for stateful orchestration (events.js, app.js): modules that need to self-register event listeners at load time use the IIFE pattern rather than pure ES module exports.
  • No circular dependencies: appState.js acts as the shared hub; utils.js and constants.js have zero app-level dependencies; domain modules only import from the foundation layer.
  • emptyOutDir: false in Vite config: preserves vendor files, images, and other static assets alongside the bundle.

File Map

Path Description
mcpgateway/admin_ui/*.js 44 source modules (32,224 LOC total)
mcpgateway/admin_ui/index.js Build entry point
mcpgateway/admin_ui/admin.js Facade — aggregates all exports onto window.Admin
mcpgateway/admin.py get_bundle_js_filename() — resolves hashed name at startup
mcpgateway/templates/admin.html References {{ bundle_js }}
vite.config.js Bundler configuration
vitest.config.js Test runner configuration
package.json Scripts and dev dependencies
tests/unit/js/*.test.js 44 Vitest unit test files

@crivetimihai crivetimihai added this to the Release 1.1.0 milestone Feb 24, 2026
@crivetimihai crivetimihai added enhancement New feature or request SHOULD P2: Important but not vital; high-value items that are not crucial for the immediate release labels Feb 24, 2026
@gcgoncalves gcgoncalves force-pushed the admin-scope-modularised branch from 9b2fbe3 to d8b8aaa Compare February 24, 2026 13:57
@gcgoncalves gcgoncalves marked this pull request as draft February 26, 2026 14:35
@gcgoncalves gcgoncalves force-pushed the admin-scope-modularised branch from d8b8aaa to 81c8271 Compare February 28, 2026 08:38
@gcgoncalves gcgoncalves marked this pull request as ready for review February 28, 2026 08:49
@gcgoncalves gcgoncalves marked this pull request as draft February 28, 2026 08:50
@gcgoncalves gcgoncalves force-pushed the admin-scope-modularised branch 2 times, most recently from 59319b4 to 0c9f317 Compare March 2, 2026 11:03
@gcgoncalves gcgoncalves force-pushed the admin-scope-modularised branch 3 times, most recently from ca9317f to 53477a6 Compare March 13, 2026 16:06
@gcgoncalves gcgoncalves marked this pull request as ready for review March 13, 2026 16:06
@gcgoncalves gcgoncalves force-pushed the admin-scope-modularised branch 2 times, most recently from 4802832 to f1e5e15 Compare March 13, 2026 23:00
@gcgoncalves gcgoncalves force-pushed the admin-scope-modularised branch 9 times, most recently from c4ace4e to 9904982 Compare March 19, 2026 14:05
@gcgoncalves gcgoncalves force-pushed the admin-scope-modularised branch 9 times, most recently from 581bdf2 to a114e4c Compare April 2, 2026 09:04
vishu-bh
vishu-bh previously approved these changes Apr 2, 2026
Copy link
Copy Markdown
Collaborator

@vishu-bh vishu-bh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Ran admin UI locally and all looks okay.

@gcgoncalves gcgoncalves added the release-fix Critical bugfix required for the release label Apr 2, 2026
@gcgoncalves gcgoncalves requested a review from vishu-bh April 2, 2026 12:16
@gcgoncalves
Copy link
Copy Markdown
Collaborator

@vishu-bh Rebased and resolved the secrets baseline conflict.

marekdano
marekdano previously approved these changes Apr 2, 2026
Copy link
Copy Markdown
Collaborator

@marekdano marekdano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀

@jonpspri jonpspri force-pushed the admin-scope-modularised branch 2 times, most recently from 3887fda to aaa7b65 Compare April 2, 2026 13:32
Signed-off-by: Gabriel Costa <gabrielcg@proton.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request release-fix Critical bugfix required for the release SHOULD P2: Important but not vital; high-value items that are not crucial for the immediate release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants