kysely-bun-dialects
v1.0.0
Published
Kysely dialects for Bun's built-in SQLite, MySQL, and PostgreSQL drivers
Maintainers
Readme
kysely-bun-dialects
Kysely dialects for Bun's built-in database drivers. Supports SQLite (bun:sqlite), MySQL, and PostgreSQL via Bun.SQL — no external database packages required.
Installation
bun add kysely-bun-dialects kyselyDialects
SQLite
Uses Bun's built-in bun:sqlite module.
import { BunSqliteDialect } from 'kysely-bun-dialects'
import { Database } from 'bun:sqlite'
import { Kysely, sql, type Generated } from 'kysely'
interface UserTable {
id: Generated<number>
email: string
name: string
}
interface Database {
users: UserTable
}
const db = new Kysely<Database>({
dialect: new BunSqliteDialect({
database: new Database('app.db'),
}),
})Pass :memory: for an in-memory database:
new BunSqliteDialect({
database: new Database(':memory:'),
})Or use a factory function if you need to defer opening the file:
new BunSqliteDialect({
database: () => new Database('app.db'),
})PostgreSQL
Uses Bun's built-in Bun.SQL with the Postgres adapter.
import { BunPostgresDialect } from 'kysely-bun-dialects'
import { SQL } from 'bun'
import { Kysely, type Generated, type ColumnType } from 'kysely'
interface UserTable {
id: Generated<number>
email: string
name: string
created_at: ColumnType<Date, string | undefined, never>
}
interface AppDatabase {
users: UserTable
}
const db = new Kysely<AppDatabase>({
dialect: new BunPostgresDialect({
sql: new SQL(process.env.DATABASE_URL),
}),
})Use returningAll() on inserts since Postgres supports RETURNING:
const user = await db
.insertInto('users')
.values({ email: '[email protected]', name: 'Ada Lovelace' })
.returningAll()
.executeTakeFirstOrThrow()MySQL
Uses Bun's built-in Bun.SQL with the MySQL adapter.
import { BunMySqlDialect } from 'kysely-bun-dialects'
import { SQL } from 'bun'
import { Kysely, type Generated, type ColumnType } from 'kysely'
interface UserTable {
id: Generated<number>
email: string
name: string
created_at: ColumnType<Date, string | undefined, never>
}
interface AppDatabase {
users: UserTable
}
const db = new Kysely<AppDatabase>({
dialect: new BunMySqlDialect({
sql: new SQL('mysql://user:pass@localhost:3306/mydb'),
}),
})MySQL doesn't support RETURNING, so fetch the inserted row separately using insertId:
const result = await db
.insertInto('users')
.values({ email: '[email protected]', name: 'Ada Lovelace' })
.executeTakeFirstOrThrow()
const user = await db
.selectFrom('users')
.selectAll()
.where('id', '=', Number(result.insertId))
.executeTakeFirstOrThrow()Subpath imports
Each dialect is also available as a subpath import if you want to avoid loading all three:
import { BunSqliteDialect } from 'kysely-bun-dialects/sqlite'
import { BunMySqlDialect } from 'kysely-bun-dialects/mysql'
import { BunPostgresDialect } from 'kysely-bun-dialects/postgres'Connection options
SQLite options
| Option | Type | Description |
|--------|------|-------------|
| database | Database \| () => Database | A bun:sqlite Database instance, or a factory function |
| onCreateConnection | (conn) => void \| Promise<void> | Called once when the connection is first created |
MySQL & PostgreSQL options
Both BunMySqlDialect and BunPostgresDialect accept the same shape:
| Option | Type | Description |
|--------|------|-------------|
| sql | SQL \| () => SQL \| Promise<SQL> | A Bun.SQL instance, or a factory function |
| onCreateConnection | (conn) => void \| Promise<void> | Called once after a connection is reserved from the pool |
| onReserveConnection | (conn) => void \| Promise<void> | Called every time a connection is reserved from the pool |
Creating a Bun.SQL instance
Pass a connection URL:
new SQL('postgres://user:pass@localhost:5432/mydb')
new SQL('mysql://user:pass@localhost:3306/mydb')Or an options object:
new SQL({
hostname: 'localhost',
port: 5432,
username: 'user',
password: 'pass',
database: 'mydb',
max: 10, // connection pool size
idleTimeout: 30, // seconds before idle connections are closed
})Transactions
Transactions work the same way as any other Kysely dialect:
await db.transaction().execute(async (trx) => {
const user = await trx
.insertInto('users')
.values({ email: '[email protected]', name: 'Ada Lovelace' })
.returningAll()
.executeTakeFirstOrThrow()
await trx
.insertInto('posts')
.values({ user_id: user.id, title: 'Hello world' })
.execute()
})Requirements
License
MIT
