feat: add public external module registration API#455
Open
xanahopper wants to merge 3 commits into
Open
Conversation
Foundational infrastructure for the External Module API. No behavior change for existing modules; only adds opt-in surfaces. * EllesmereUI.API_VERSION = 1 -- constant external modules check against via spec.apiVersion (reject/mismatch path comes with RegisterExternalModule). * EllesmereUI_ExternalModules.lua -- new file. Hosts the callback bus today; will host RegisterExternalModule in a follow-up commit. Lives on its own chunk so EllesmereUI.lua (already at the 200-upvalue limit) gains zero new locals. * EllesmereUI.RegisterModuleCallback / FireModuleCallback -- minimal event bus. Every listener xpcall'd through the global error handler so one bad callback cannot block the host lifecycle. * EllesmereUI.SwitchProfile fires "ProfileChanged" at both exit paths (sync-reload prompt and normal switch). Covers manual switch, the SetProfile alias, and PLAYER_SPECIALIZATION_CHANGED mid-session. Login-time PreSeedSpecProfile deliberately does NOT fire (external modules read the right values via OnEnable).
Third-party addons can now register as native EllesmereUI modules with
their own sidebar entry, options page, and tab list.
* EllesmereUI._RegisterModuleConfig -- internal allowlist-free writer,
extracted from RegisterModule's post-allowlist body. Defined as a
method (not a local) so EllesmereUI.lua's main chunk gains zero new
upvalues (still at the Lua 5.1 200-upvalue limit). Behavior for
official modules is unchanged: same code path, just relocated.
* EllesmereUI.RegisterExternalModule(spec) -- public API in
EllesmereUI_ExternalModules.lua. Pipeline:
1. Validate required spec fields (folder/display/apiVersion/pages/
buildPage).
2. Verify the caller's folder (via debugstack) matches spec.folder
-- prevents addon A from spoofing addon B's identity.
3. API version handshake against EllesmereUI.API_VERSION: reject
if module requires newer, warn if targets older, accept on match.
4. Inject into ADDON_ROSTER, _addonInfoByFolder, and a dedicated
"external" ADDON_GROUPS entry (lazy-created, labeled "External",
routed through EllesmereUI.L for community translation).
5. Mark _syncExempt[folder] = true -- external modules don't
implement the host profile-sync protocol; showing the sync icon
would mislead users.
6. Wrap buildPage / onPageCacheRestore / onReset in xpcall so a
buggy module cannot brick the options UI. buildPage errors
render a red-text notice on the page wrapper instead of crashing.
* spec schema is documented in the file header. Notably, the sidebar
row has no left icon (info.icon is reserved for future use), and
comingSoon/maintenance mirror the official module semantics (greyed
row, no power toggle).
Idempotent: re-registration of the same folder replaces in-place rather
than appending duplicates.
Mid-session refresh (when the panel is already open) is intentionally
NOT triggered: RefreshSidebarStates is a file-local declared further
down in EllesmereUI.lua and unreachable from this scope without
restructuring forward declarations. External modules should register
at OnEnable (PLAYER_LOGIN), same as official modules do.
cf11fca to
b460f36
Compare
Author
|
hello~ can this PR be merged? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
I plan to port ElvUI_WindTools into EllesmereUI_WindTools, and that requires a supported way for third-party addons to integrate with EllesmereUI as native modules without relying on internal allowlists or fragile implementation details.
This PR adds a versioned extension surface so external modules can register their own sidebar entry, options pages, and lifecycle callbacks while keeping the host options UI protected from module errors.
What Changed
EllesmereUI.API_VERSIONas the compatibility contract for external modules.EllesmereUI_ExternalModules.luaand loaded it fromEllesmereUI.toc.EllesmereUI.RegisterModuleCallbackandEllesmereUI.FireModuleCallbackfor host lifecycle events.EllesmereUI.RegisterExternalModule(spec)for third-party addons to register:xpcallso module failures surface through the normal error handler without breaking the EllesmereUI options panel.Externalsidebar group for registered third-party modules.ProfileChangedcallback when EllesmereUI profiles are switched so external modules can rebuild cached profile state._RegisterModuleConfigso both official modules and validated external modules can share the same registration path.Note
This PR was generated with AI assistance, and has been manually tested and reviewed.
Test Case like this: