https://github.com/k2wanko/kysely-cloudflare-do-sqlite
Kysely dialect for Cloudflare Durable Objects SQLite storage
https://github.com/k2wanko/kysely-cloudflare-do-sqlite
cloudflare database dialect durable-objects kysely sql sqlite typescript
Last synced: 3 months ago
JSON representation
Kysely dialect for Cloudflare Durable Objects SQLite storage
- Host: GitHub
- URL: https://github.com/k2wanko/kysely-cloudflare-do-sqlite
- Owner: k2wanko
- License: mit
- Created: 2025-10-24T15:12:40.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2025-10-24T15:48:41.000Z (3 months ago)
- Last Synced: 2025-10-24T17:27:38.788Z (3 months ago)
- Topics: cloudflare, database, dialect, durable-objects, kysely, sql, sqlite, typescript
- Language: TypeScript
- Homepage:
- Size: 29.3 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# kysely-cloudflare-do-sqlite
[Kysely](https://kysely.dev/) dialect for [Cloudflare Durable Objects SQLite](https://developers.cloudflare.com/durable-objects/api/sqlite-storage-api/)
This package provides a Kysely dialect that allows you to use the powerful type-safe SQL query builder with Cloudflare Durable Objects' SQLite storage.
## Installation
```bash
npm install kysely-cloudflare-do-sqlite kysely
```
## Basic Usage
### 1. Define your database schema
```ts
import { Generated } from 'kysely';
export interface Database {
artist: ArtistTable;
album: AlbumTable;
}
export interface ArtistTable {
artistid: Generated;
artistname: string;
}
export interface AlbumTable {
albumid: Generated;
artistid: number;
albumtitle: string;
}
```
### 2. Create your Durable Object with Kysely
```ts
import { DurableObject } from "cloudflare:workers";
import { Kysely } from 'kysely';
import { DurableObjectDialect } from 'kysely-cloudflare-do-sqlite';
export class MyDurableObject extends DurableObject {
db: Kysely;
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
this.db = new Kysely({
dialect: new DurableObjectDialect({ ctx }),
});
}
override async fetch(request: Request): Promise {
// Create tables if they don't exist
await this.createTables();
// Query data
const artists = await this.db.selectFrom("artist").selectAll().execute();
return new Response(JSON.stringify({ artists }), {
headers: { "Content-Type": "application/json" },
});
}
private async createTables() {
// Create artist table
await this.db.schema
.createTable("artist")
.ifNotExists()
.addColumn("artistid", "integer", (col) => col.primaryKey().autoIncrement())
.addColumn("artistname", "text", (col) => col.notNull())
.execute();
// Create album table
await this.db.schema
.createTable("album")
.ifNotExists()
.addColumn("albumid", "integer", (col) => col.primaryKey().autoIncrement())
.addColumn("artistid", "integer", (col) => col.notNull())
.addColumn("albumtitle", "text", (col) => col.notNull())
.execute();
}
}
```
### 3. Configure your Worker
```ts
export type Env = {
MY_DURABLE_OBJECT: DurableObjectNamespace;
};
export default {
async fetch(request: Request, env: Env): Promise {
const url = new URL(request.url);
const instanceId = url.searchParams.get("instance") || "default";
const id = env.MY_DURABLE_OBJECT.idFromName(instanceId);
const stub = env.MY_DURABLE_OBJECT.get(id);
return await stub.fetch(request);
},
} satisfies ExportedHandler;
```
### 4. Configure wrangler.toml
```toml
name = "my-kysely-app"
compatibility_date = "2025-01-16"
[[durable_objects.bindings]]
name = "MY_DURABLE_OBJECT"
class_name = "MyDurableObject"
[[migrations]]
tag = "v1"
new_sqlite_classes = ["MyDurableObject"]
```
## Advanced Usage
### Transaction
The dialect supports transactions using Cloudflare Durable Objects' `ctx.storage.transaction()`:
```ts
// Simple transaction
await this.ctx.storage.transaction(async () => {
const artist = await this.db
.insertInto("artist")
.values({ artistname: "Transaction Artist" })
.returningAll()
.execute();
await this.db
.insertInto("album")
.values({
artistid: artist[0].artistid,
albumtitle: "Transaction Album"
})
.execute();
});
// Transaction with rollback on error
try {
await this.ctx.storage.transaction(async () => {
await this.db
.insertInto("artist")
.values({ artistname: "Test Artist" })
.execute();
// This will cause the entire transaction to rollback
throw new Error("Intentional rollback");
});
} catch (error) {
console.log("Transaction rolled back:", error.message);
}
```
# License
This project is licensed under the MIT License.