Adapters Explained
Relevant source files
The following files were used as context for generating this wiki page:- packages/adapters/convex/src/index.ts
- packages/adapters/convex/test/adapter.test.ts
- packages/adapters/convex/src/generate-schema/generate-schema-builder.ts
- packages/adapters/convex/test/schema.test.ts
- packages/cli/src/commands/db/database-explorer-plugin.ts
- packages/plugins/legal-consent/src/index.ts
Adapters in Better Auth Kit serve as the crucial bridge between the core authentication logic and a specific database backend. They provide a standardized, abstract interface for all data persistence operations, such as creating users, finding sessions, or updating accounts. This design allows better-auth to be database-agnostic, with developers able to plug in support for different databases by implementing the required adapter interface.
The primary example within this repository is the @better-auth-kit/convex adapter, which integrates with the Convex backend-as-a-service platform. Adapters are not only responsible for CRUD operations but can also handle more complex tasks like dynamic schema generation. They can interpret schema definitions from the core better-auth configuration and its plugins, and translate them into the native schema language of the target database.
Core Adapter Interface
Every adapter must implement a set of standard methods to be compatible with better-auth. This ensures that the core library can perform its functions regardless of the underlying database technology. The dbExplorerPlugin is a clear example of a consumer of this generic interface, as it provides API endpoints that map directly to these adapter methods.
Sources: packages/adapters/convex/src/index.ts, packages/cli/src/commands/db/database-explorer-plugin.ts:28-151
The following diagram illustrates the generic flow of an adapter operation, where the core logic is decoupled from the database-specific implementation.
Adapter Methods
The table below details the methods that constitute the adapter interface.
| Method | Description |
|---|---|
id | A string identifier for the adapter (e.g., "convex"). |
create | Creates a new record in a specified model (table). |
findOne | Finds a single record matching the given where clause. |
findMany | Finds multiple records, with support for where, limit, offset, & sortBy. |
update | Updates a single record that matches a where clause. |
updateMany | Updates multiple records that match a where clause. |
delete | Deletes a single record matching a where clause. |
deleteMany | Deletes multiple records matching a where clause. |
count | Counts the number of records in a model, optionally filtered by where. |
Sources: packages/adapters/convex/src/index.ts:28-223, packages/cli/src/commands/db/database-explorer-plugin.ts:28-151
Convex Adapter Implementation
The @better-auth-kit/convex package provides a concrete implementation of the adapter interface for the Convex platform.
Initialization
The convexAdapter is a factory function that takes a ConvexHttpClient instance and an optional configuration object. It returns an AdapterInstance that is configured to communicate with your Convex project.
// Example from tests
import { ConvexClient } from "convex/browser";
import { convexAdapter } from "./../src/index";
const client = new ConvexClient(process.env.CONVEX_URL as string);
const auth = betterAuth({
database: convexAdapter(client),
});
Sources: packages/adapters/convex/src/index.ts:12, packages/adapters/convex/test/adapter.test.ts:10-16
Data Flow and Transformation
A key responsibility of the Convex adapter is to translate data and query structures between better-auth and Convex.
- Transformation: The
createTransformutility is used to create functions that transform input data into a format Convex can ingest and transform output data from Convex back into the formatbetter-authexpects. - Query Building: The
queryBuilderfunction constructs Convex query strings from thewhereclauses provided bybetter-auth. It maps operators likeeqto Convex'sq.eq(). - Execution: The adapter then uses a generic
dbfunction to perform the action (e.g.,insert,query,update) against the Convex backend.
The following sequence diagram shows the flow for a findOne operation.
Dynamic Schema Generation
A powerful feature of the Convex adapter is its ability to dynamically generate a schema.ts file. It merges the base better-auth tables (user, session, etc.) with schemas defined in plugins, and combines them with any existing, user-defined tables in the project's convex/schema.ts file.
Schema Generation Process
The process is orchestrated by the generateSchemaBuilderStage function.
This flow allows developers to define schema extensions within their plugins, and the adapter automatically handles the integration into the Convex schema file.
Sources: packages/adapters/convex/src/generate-schema/generate-schema-builder.ts:15-25
Field Type & Reference Mapping
The schema builder maps better-auth schema field types to their Convex convex/values (v) equivalents. It also correctly handles foreign key relationships.
| Better Auth Type | required | Better Auth references | Convex v Type |
|---|---|---|---|
string | true | - | v.string() |
string | false | - | v.optional(v.string()) |
boolean | true | - | v.boolean() |
number | true | - | v.number() |
date | false | - | v.optional(v.string()) |
string[] | false | - | v.optional(v.array()) |
string | true | { model: 'user' } | v.id("user") |
string (as id) | true | - | v.id("tableName") |
This mapping is demonstrated in tests, where a plugin defines a schema and the test verifies the correctly generated Convex schema output.
Sources: packages/adapters/convex/src/generate-schema/generate-schema-builder.ts:101-119, packages/adapters/convex/test/schema.test.ts:210-244
Adapter Usage Example: DB Explorer CLI
The db command for the CLI launches a database explorer web interface. This tool relies on the dbExplorerPlugin, which dynamically adds API endpoints to the user's better-auth instance. Each endpoint corresponds to a method on the adapter interface.
This is a prime example of the adapter abstraction's power: the DB explorer does not need to know if the underlying database is Convex, SQLite, or something else. It interacts with the database through the standardized adapter API.
| Endpoint | HTTP Method | Adapter Method |
|---|---|---|
/api/auth/adapter/create | POST | create |
/api/auth/adapter/find-one | POST | findOne |
/api/auth/adapter/find-many | POST | findMany |
/api/auth/adapter/update | POST | update |
/api/auth/adapter/delete | POST | delete |
/api/auth/adapter/count | POST | count |
/api/auth/adapter/get-schema | GET | (gets schema) |
Sources: packages/cli/src/commands/db/index.ts:39-63, packages/cli/src/commands/db/database-explorer-plugin.ts:28-151