import { SqliteClient } from "@effect/sql-sqlite-bun" import { eq } from "drizzle-orm" import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core" import * as Context from "effect/Context" import * as Effect from "effect/Effect" import * as Layer from "effect/Layer" import * as Schema from "effect/Schema" import { EffectDrizzleSqlite } from "../src" const users = sqliteTable("users", { id: integer().primaryKey({ autoIncrement: true }), name: text().notNull(), }) type User = typeof users.$inferSelect const makeDatabase = EffectDrizzleSqlite.makeWithDefaults() type DatabaseShape = Effect.Success const sqliteLayer = SqliteClient.layer({ filename: ":memory:", disableWAL: true }) class Database extends Context.Service()("@opencode/example/Database") { static layer = Layer.effect(Database, makeDatabase).pipe(Layer.provide(sqliteLayer)) } class UserStoreError extends Schema.TaggedErrorClass()("UserStoreError", { message: Schema.String, cause: Schema.optional(Schema.Defect), }) {} const mapStoreError = (message: string) => (cause: unknown) => new UserStoreError({ message, cause }) interface UserStoreShape { migrate(): Effect.Effect create(name: string): Effect.Effect rename(from: string, to: string): Effect.Effect list(): Effect.Effect } class UserStore extends Context.Service()("@opencode/example/UserStore") { static layer = Layer.effect( UserStore, Effect.gen(function* () { const db = yield* Database return UserStore.of({ migrate: Effect.fn("UserStore.migrate")(function* () { yield* EffectDrizzleSqlite.migrate(db, { migrationsFolder: `${import.meta.dirname}/migrations` }).pipe( Effect.mapError((cause) => new UserStoreError({ message: "Failed to migrate users", cause })), ) }), create: Effect.fn("UserStore.create")(function* (name: string) { yield* db .insert(users) .values({ name }) .pipe(Effect.asVoid, Effect.mapError(mapStoreError("Failed to create user"))) }), rename: Effect.fn("UserStore.rename")(function* (from: string, to: string) { yield* db .transaction( Effect.fnUntraced(function* (tx) { yield* tx.insert(users).values({ name: from }) yield* tx.update(users).set({ name: to }).where(eq(users.name, from)) }), { behavior: "immediate" }, ) .pipe(Effect.asVoid, Effect.mapError(mapStoreError("Failed to rename user"))) }), list: Effect.fn("UserStore.list")(function* () { return yield* db .select() .from(users) .pipe(Effect.mapError(mapStoreError("Failed to list users"))) }), }) }), ).pipe(Layer.provide(Database.layer)) } const program = Effect.gen(function* () { const userStore = yield* UserStore yield* userStore.migrate() yield* userStore.create("Ada") yield* userStore.rename("Grace", "Grace Hopper") return yield* userStore.list() }) const rows = await Effect.runPromise(program.pipe(Effect.provide(UserStore.layer))) console.log(rows)