3.0 KiB
session-without-provider
(no submodules)
Purpose
Pin the design invariant from The spec change: the Better-Auth
adapter ships two factories — createBetterAuthSession and
createBetterAuthProvider — and operators MUST be able to wire either side
without dragging in the other. Wiring only the session adapter (keeping
account-lifecycle elsewhere — e.g. Clerk or a custom rolled provider) is the
"hosted IdP for accounts, Better-Auth for session reads against a shared
cookie" topology the design doc §2.3 calls out. Wiring only the provider
adapter (no Better-Auth session resolution) is rarer but legal — the host
fills the auth.session slot with whatever other resolver is configured.
Features
- Sibling test file pins the invariant by:
- Asserting
createBetterAuthSession(opts)returns aSessionResolverwith noroutes/pathPrefixfield. - Asserting
createBetterAuthProvider(opts)returns anAuthProviderAdapterwith noresolve/disposefield. - Walking the recorded route list when
routes(...)IS invoked to verify every canonical name lands.
- Asserting
betterAuthFactoriesconstant re-exports both factories as a single bag so consumer documentation can name the pair without repeating imports.
Usage: Basic
import { betterAuthFactories } from "@suaveplan/api-auth-better-auth";
const resolver = betterAuthFactories.session(opts);
const provider = betterAuthFactories.provider(opts);
Usage: Advanced
import { createBetterAuthSession } from "@suaveplan/api-auth-better-auth";
import { ClerkSessionResolver } from "third-party/clerk-suaveplan-adapter";
// Topology: Clerk owns sign-up / sign-in routes; Better-Auth reads the
// shared session cookie via createBetterAuthSession against a shadow
// Better-Auth DB that mirrors the Clerk user store. Provider side NOT wired.
host.registerAuth({
resolver: new SessionResolverChain({
resolvers: [
createBetterAuthSession({ database: pool, baseUrl, secret }),
new ClerkSessionResolver({ clerkApiKey: process.env.CLERK_KEY! }),
],
}),
});
API Reference
| Export | Shape | Purpose |
|---|---|---|
betterAuthFactories |
Readonly<{ session, provider }> |
Convenience bag pairing both factories |
Implementation Notes
The module is intentionally near-empty — the invariant lives in the test
file. The thin re-export bag is the only runtime contribution because the
OpenSpec scaffolding rule requires every implementation file to have a
sibling .md AND a paired test file. The independence is enforced
structurally by TypeScript anyway — SessionResolver and
AuthProviderAdapter have disjoint shapes — but the test pin guards against
a refactor that accidentally adds an if-not-mounted-mount-the-other-side
side effect inside either factory. The OpenSpec spec delta lists this file
as the verification for the "session-only / provider-only wiring exposes
nothing from the other side" scenario, so the test names match the spec
exactly.