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

Open
opened 2026-04-15 22:42:05 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/better-auth/better-auth/pull/8677
Author: @gustavovalverde
Created: 3/18/2026
Status: 🔄 Open

Base: nextHead: feat/extension-registry


📝 Commits (1)

  • fe0b639 feat(core): add plugin extension registry and dependency validation

📊 Changes

7 files changed (+211 additions, -1 deletions)

View changed files

📝 docs/content/docs/concepts/plugins.mdx (+47 -0)
📝 packages/better-auth/src/context/create-context.test.ts (+86 -0)
📝 packages/better-auth/src/context/create-context.ts (+8 -0)
📝 packages/better-auth/src/context/helpers.ts (+13 -0)
📝 packages/core/src/types/context.ts (+29 -0)
📝 packages/core/src/types/index.ts (+1 -0)
📝 packages/core/src/types/plugin.ts (+27 -1)

📄 Description

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.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/better-auth/better-auth/pull/8677 **Author:** [@gustavovalverde](https://github.com/gustavovalverde) **Created:** 3/18/2026 **Status:** 🔄 Open **Base:** `next` ← **Head:** `feat/extension-registry` --- ### 📝 Commits (1) - [`fe0b639`](https://github.com/better-auth/better-auth/commit/fe0b639fee2b68c44c89885c0a1b848b7ddad861) feat(core): add plugin extension registry and dependency validation ### 📊 Changes **7 files changed** (+211 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `docs/content/docs/concepts/plugins.mdx` (+47 -0) 📝 `packages/better-auth/src/context/create-context.test.ts` (+86 -0) 📝 `packages/better-auth/src/context/create-context.ts` (+8 -0) 📝 `packages/better-auth/src/context/helpers.ts` (+13 -0) 📝 `packages/core/src/types/context.ts` (+29 -0) 📝 `packages/core/src/types/index.ts` (+1 -0) 📝 `packages/core/src/types/plugin.ts` (+27 -1) </details> ### 📄 Description ## 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. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-15 22:42:05 -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#25039