mirror of
https://github.com/anomalyco/opencode.git
synced 2026-05-13 23:52:06 +00:00
test(effect-drizzle-sqlite): cover transaction edge cases
This commit is contained in:
@@ -7,7 +7,7 @@ import { SQLiteInsertBase } from "drizzle-orm/sqlite-core/query-builders/insert"
|
||||
import { SQLiteRelationalQuery, SQLiteSyncRelationalQuery } from "drizzle-orm/sqlite-core/query-builders/_query"
|
||||
import { SQLiteSelectBase } from "drizzle-orm/sqlite-core/query-builders/select"
|
||||
import { SQLiteUpdateBase } from "drizzle-orm/sqlite-core/query-builders/update"
|
||||
import type { SQLiteTransaction, SQLiteTransactionConfig } from "drizzle-orm/sqlite-core/session"
|
||||
import type { PreparedQueryConfig, SQLiteSession, SQLiteTransaction, SQLiteTransactionConfig } from "drizzle-orm/sqlite-core/session"
|
||||
import { SQLitePreparedQuery } from "drizzle-orm/sqlite-core/session"
|
||||
import type { DrizzleConfig } from "drizzle-orm/utils"
|
||||
import { Cause, Effect, Exit, Schema } from "effect"
|
||||
@@ -241,3 +241,16 @@ declare module "drizzle-orm/query-promise" {
|
||||
asEffect(): Effect.Effect<T, EffectDrizzleQueryError>
|
||||
}
|
||||
}
|
||||
|
||||
declare module "drizzle-orm/sqlite-core/session" {
|
||||
interface SQLitePreparedQuery<T extends PreparedQueryConfig> extends Effect.Effect<T["execute"], EffectDrizzleQueryError> {
|
||||
asEffect(): Effect.Effect<T["execute"], EffectDrizzleQueryError>
|
||||
}
|
||||
}
|
||||
|
||||
declare module "drizzle-orm/sqlite-core/query-builders/count" {
|
||||
interface SQLiteCountBuilder<TSession extends SQLiteSession<any, any, any, any>>
|
||||
extends Effect.Effect<number, EffectDrizzleQueryError> {
|
||||
asEffect(): Effect.Effect<number, EffectDrizzleQueryError>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { afterEach, beforeEach, describe, expect, test } from "bun:test"
|
||||
import { Database } from "bun:sqlite"
|
||||
import { eq } from "drizzle-orm"
|
||||
import { relations } from "drizzle-orm/_relations"
|
||||
import { drizzle as drizzleBun } from "drizzle-orm/bun-sqlite"
|
||||
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core"
|
||||
import { Cause, Effect, Exit } from "effect"
|
||||
import { EffectDrizzleQueryError, make, type EffectSQLiteDatabase } from "../src"
|
||||
@@ -49,6 +51,21 @@ afterEach(() => {
|
||||
})
|
||||
|
||||
describe("effect drizzle sqlite", () => {
|
||||
test("keeps normal Drizzle Bun SQLite clients usable after patching", async () => {
|
||||
const sqlite = new Database(":memory:")
|
||||
try {
|
||||
const normal = drizzleBun({ client: sqlite })
|
||||
sqlite.run("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)")
|
||||
|
||||
normal.insert(users).values({ id: 1, name: "Ada" }).run()
|
||||
|
||||
expect(normal.select().from(users).all()).toEqual([{ id: 1, name: "Ada" }])
|
||||
expect(await normal.select().from(users)).toEqual([{ id: 1, name: "Ada" }])
|
||||
} finally {
|
||||
sqlite.close()
|
||||
}
|
||||
})
|
||||
|
||||
testEffect("makes select/insert/update/delete query builders yieldable Effects", () =>
|
||||
Effect.gen(function* () {
|
||||
yield* db.insert(users).values({ id: 1, name: "Ada" })
|
||||
@@ -141,6 +158,68 @@ describe("effect drizzle sqlite", () => {
|
||||
}),
|
||||
)
|
||||
|
||||
testEffect("supports count builders and prepared queries", () =>
|
||||
Effect.gen(function* () {
|
||||
yield* db.insert(users).values([
|
||||
{ id: 1, name: "Ada" },
|
||||
{ id: 2, name: "Grace" },
|
||||
])
|
||||
|
||||
expect(yield* db.$count(users)).toBe(2)
|
||||
|
||||
const prepared = db.select().from(users).orderBy(users.id).prepare()
|
||||
expect(yield* prepared).toEqual([
|
||||
{ id: 1, name: "Ada" },
|
||||
{ id: 2, name: "Grace" },
|
||||
])
|
||||
}),
|
||||
)
|
||||
|
||||
testEffect("nested pipeable transactions commit or roll back with the outer transaction", () =>
|
||||
Effect.gen(function* () {
|
||||
yield* Effect.gen(function* () {
|
||||
yield* db.insert(users).values({ id: 1, name: "Ada" })
|
||||
yield* Effect.gen(function* () {
|
||||
yield* db.insert(users).values({ id: 2, name: "Grace" })
|
||||
}).pipe(db.withTransaction)
|
||||
}).pipe(db.withTransaction)
|
||||
|
||||
expect(yield* db.select().from(users).orderBy(users.id)).toEqual([
|
||||
{ id: 1, name: "Ada" },
|
||||
{ id: 2, name: "Grace" },
|
||||
])
|
||||
|
||||
const exit = yield* Effect.gen(function* () {
|
||||
yield* db.insert(users).values({ id: 3, name: "Katherine" })
|
||||
yield* Effect.gen(function* () {
|
||||
yield* db.insert(users).values({ id: 4, name: "Dorothy" })
|
||||
return yield* Effect.fail("inner rollback")
|
||||
}).pipe(db.withTransaction)
|
||||
}).pipe(db.withTransaction, Effect.exit)
|
||||
|
||||
expect(Exit.isFailure(exit)).toBe(true)
|
||||
expect(yield* db.select().from(users).orderBy(users.id)).toEqual([
|
||||
{ id: 1, name: "Ada" },
|
||||
{ id: 2, name: "Grace" },
|
||||
])
|
||||
}),
|
||||
)
|
||||
|
||||
testEffect("defects inside transactions roll back and stay defects", () =>
|
||||
Effect.gen(function* () {
|
||||
const exit = yield* Effect.gen(function* () {
|
||||
yield* db.insert(users).values({ id: 1, name: "Ada" })
|
||||
return yield* Effect.die("boom")
|
||||
}).pipe(db.withTransaction, Effect.exit)
|
||||
|
||||
expect(Exit.isFailure(exit)).toBe(true)
|
||||
if (Exit.isFailure(exit)) {
|
||||
expect(exit.cause.reasons.some(Cause.isDieReason)).toBe(true)
|
||||
}
|
||||
expect(yield* db.select().from(users)).toEqual([])
|
||||
}),
|
||||
)
|
||||
|
||||
testEffect("wraps query failures with query text and parameters", () =>
|
||||
Effect.gen(function* () {
|
||||
const exit = yield* Effect.exit(db.insert(posts).values({ id: 1, user_id: 404, title: "Missing" }))
|
||||
|
||||
Reference in New Issue
Block a user