Client
better() - options, client-level methods, and the values exported from better-drizzle.
import { better } from 'better-drizzle';
const client = better(db, options);better(db, options) wraps a Drizzle database instance and returns a fully typed client.
Options
Prop
Type
relations options
better-drizzle infers a direct many-to-many relation whenever a junction table has exactly two required foreign-key relations and no other required columns. Use these options when your schema has more than one possible path.
Prop
Type
const client = better(db, {
schema,
relations: {
manyToMany: [
{
through: 'memberships',
left: { relation: 'user' },
right: { relation: 'group', name: 'groups' },
},
],
},
});
// `groups` is now a first-class relation on the user delegate
const user = await client.users.findFirst({
where: { id: 1 },
include: { groups: { take: 10 } },
});Ambiguous paths fail with a structured error at use time instead of picking a junction silently. See relations for the inference rules.
raw options
Prop
Type
When raw.enabled is false, every raw method throws a BetterDrizzleError with code RAW_DISABLED. Calling $rawUnsafe() without raw.allowUnsafe: true throws RAW_UNSAFE_DISABLED. With raw.requireComment, a call without options.comment throws RAW_COMMENT_REQUIRED. See error codes.
Client methods
Beyond the per-table delegates, the client exposes:
| Method | Description |
|---|---|
client.<table> | the model delegate for each table |
repository(name) | resolve a delegate by schema key or DB table name |
extends(objectOrFactory) | attach app-specific helpers or values to the client |
transaction(fn, options?) | run fn in a transaction |
$raw(...) | run a safe raw read, returns rows |
$executeRaw(...) | run a safe raw write, returns { rowsAffected } |
$rawUnsafe(query, params?, options?) | run a raw string query (requires raw.allowUnsafe) |
$withContext(meta) | clone the client with default metadata merged into every operation |
repository(name) accepts either the TypeScript schema key or the underlying database table name:
const usersByKey = client.repository('users');
const usersByDbName = client.repository('app_users');extends(...) accepts either a plain object or a callback that receives the bound client:
const extended = client.extends((client) => ({
findById(id: number) {
return client.users.findFirst({ where: { id } });
},
}));See the full guide at Client extensions.
$rawUnsafe
$rawUnsafe(query, params?, options?) takes a plain SQL string. Use ? placeholders for values: each one is replaced by the matching entry of params as a bound parameter, in order. It returns rows like $raw.
const client = better(db, { schema, raw: { allowUnsafe: true } });
const rows = await client.$rawUnsafe(
'select id, name from users where id = ? and active = ?',
[1, true],
{ name: 'admin-user-lookup' },
);When params is non-empty and the number of ? placeholders differs from params.length, the call throws RAW_UNSAFE_PLACEHOLDER_MISMATCH (status 400) with details: { params, placeholders }. Without params, the string runs as-is.
Transaction clients
The client passed to a transaction(...) callback also has rollback(reason?), afterCommit(cb), and afterRollback(cb). See transactions. The root client does not declare afterCommit / afterRollback; calling them on it at runtime throws AFTER_COMMIT_OUTSIDE_TRANSACTION / AFTER_ROLLBACK_OUTSIDE_TRANSACTION.
Exports
import {
better,
definePlugin,
OrderType,
version,
// error helpers
isDatabaseError,
getDatabaseErrorInfo,
isUniqueViolation,
isForeignKeyViolation,
isNotNullViolation,
isCheckViolation,
// errors
BetterDrizzleError,
BetterDrizzleErrorCode,
BetterDrizzleTransactionRollbackError,
} from 'better-drizzle';Enums
enum OrderType {
Asc = 'asc',
Desc = 'desc',
}The library also exports its full type surface (BetterDrizzleClient, BetterDrizzleModelDelegate, QueryArgs, WhereInput, Plugin, hook context types, and more) for typing your own helpers.
Every entrypoint re-exports the package version. Since 0.2.0 ships as a
single package, these are always the same value:
import { version } from 'better-drizzle';
import { version as softDeleteVersion } from 'better-drizzle/soft-delete';
version === softDeleteVersion; // true