better-auth-effect

raw JSON →
0.4.1 verified Sat Apr 25 auth: no javascript

Better Auth database adapter for @effect/sql, version 0.4.1. Integrates Better Auth authentication with Effect SQL ecosystem, supporting PostgreSQL, MySQL, and SQLite via @effect/sql-pg, @effect/sql-mysql2, and @effect/sql-sqlite-node. Released as a thin adapter that accepts an Effect Runtime to share the connection pool, avoiding manual lifecycle management. Supports all Better Auth adapter operations (create, findOne, findMany, update, delete, etc.) and handles database dialect differences like RETURNING clauses. Requires Effect v3.15+, Better Auth v1.2+, and Node.js 20+.

error TypeError: effectSqlAdapter is not a function
cause Importing from wrong path or incorrect import style (e.g., require() in ESM package).
fix
Use import { effectSqlAdapter } from 'better-auth-effect' with native ESM.
error Error: The runtime argument must be an Effect Runtime, got undefined
cause Runtime not provided or incorrectly extracted from Effect context.
fix
Ensure runtime is obtained via Effect.runtime<SqlClient>() inside a Layer.
error Error: Dialect must be one of: 'pg', 'mysql', 'sqlite'
cause Invalid dialect string passed to effectSqlAdapter config.
fix
Use 'pg' for PostgreSQL, 'mysql' for MySQL, or 'sqlite' for SQLite.
breaking Package is ESM-only; require() throws ERR_MODULE_NOT_FOUND
fix Use import or set type: module in package.json. For CommonJS projects, use dynamic import: const { effectSqlAdapter } = await import('better-auth-effect')
gotcha Runtime must be obtained from Effect.runtime() inside a Layer or from ManagedRuntime, not created manually
fix Use Effect.runtime<SqlClient>() inside a Layer or ManagedRuntime.make().runtime() to get the Runtime.
gotcha MySQL dialect emulates RETURNING via LAST_INSERT_ID() + SELECT; requires id column as primary key on all tables
fix Ensure all database tables (user, account, session, verification) have an id column with auto-increment primary key.
deprecated V0.3.x used a different configuration API; v0.4.0 introduced Runtime-based config
fix Upgrade to v0.4+ and pass { runtime, dialect, debugLogs? } instead of previous SqlClient parameter.
npm install better-auth-effect
yarn add better-auth-effect
pnpm add better-auth-effect

Sets up Better Auth with Effect SQL PostgreSQL adapter using Runtime injection, showing layer composition and ManagedRuntime usage.

import { Effect, Layer, ManagedRuntime } from 'effect'
import { SqlClient } from '@effect/sql'
import { PgClient } from '@effect/sql-pg'
import { betterAuth } from 'better-auth'
import { effectSqlAdapter } from 'better-auth-effect'

// Build the SQL layer
const DatabaseLive = PgClient.layer({
  url: 'postgresql://postgres:password@localhost:5432/myapp',
})

// Build auth layer with adapter
const AuthLive = Layer.scoped(
  Effect.Do.pipe(
    Effect.flatMap(() => Effect.runtime<SqlClient.SqlClient>()),
    Effect.map((rt) =>
      betterAuth({
        database: effectSqlAdapter({ runtime: rt, dialect: 'pg' }),
      })
    )
  )
).pipe(Layer.provide(DatabaseLive))

// Run the application
const runtime = ManagedRuntime.make(Layer.mergeAll(AuthLive, DatabaseLive))
// Use runtime to run effects with auth
console.log('Auth adapter configured successfully')