[PR #8677] feat(core): add plugin extension registry and dependency validation #16385

Open
opened 2026-04-13 10:30:33 -05:00 by GiteaMirror · 0 comments
Owner

Original Pull Request: https://github.com/better-auth/better-auth/pull/8677

State: open
Merged: No


Summary

Adds a typed, declarative mechanism for plugins to extend other plugins.

Problem

Plugins that extend other plugins (e.g., CIBA extending oauth-provider) rely on undocumented conventions: untyped context injection via init, runtime mutation of foreign options arrays, and any-cast after-hooks. These patterns have no compile-time safety, no IDE discoverability, and silently break when multiple plugins contribute to the same host (a missing ...existing spread clobbers other contributions).

Solution

Three new optional fields on BetterAuthPlugin and one new method on AuthContext:

  • extensions: typed contributions to host plugins, keyed by host plugin ID via BetterAuthExtensionRegistry (module augmentation, same pattern as BetterAuthPluginRegistry)
  • dependencies: required plugin IDs, validated at startup before any init runs
  • getExtensions(hostId): collects typed contributions from all plugins targeting a host

Why this approach

Mirrors the existing BetterAuthPluginRegistry / getPlugin pattern exactly: empty interface augmented via declare module, trivial runtime bridged to rich types with as never. Anyone familiar with getPlugin already understands getExtensions. The core stays generic; each host plugin defines its own contract.

**Original Pull Request:** https://github.com/better-auth/better-auth/pull/8677 **State:** open **Merged:** No --- ## Summary Adds a typed, declarative mechanism for plugins to extend other plugins. ## Problem Plugins that extend other plugins (e.g., CIBA extending oauth-provider) rely on undocumented conventions: untyped context injection via `init`, runtime mutation of foreign options arrays, and `any`-cast after-hooks. These patterns have no compile-time safety, no IDE discoverability, and silently break when multiple plugins contribute to the same host (a missing `...existing` spread clobbers other contributions). ## Solution Three new optional fields on `BetterAuthPlugin` and one new method on `AuthContext`: - **`extensions`**: typed contributions to host plugins, keyed by host plugin ID via `BetterAuthExtensionRegistry` (module augmentation, same pattern as `BetterAuthPluginRegistry`) - **`dependencies`**: required plugin IDs, validated at startup before any `init` runs - **`getExtensions(hostId)`**: collects typed contributions from all plugins targeting a host ## Why this approach Mirrors the existing `BetterAuthPluginRegistry` / `getPlugin` pattern exactly: empty interface augmented via `declare module`, trivial runtime bridged to rich types with `as never`. Anyone familiar with `getPlugin` already understands `getExtensions`. The core stays generic; each host plugin defines its own contract.
GiteaMirror added the pull-request label 2026-04-13 10:30:33 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#16385