Buckets:
| export * as DatabaseMigration from "./migration" | |
| import { sql } from "drizzle-orm" | |
| import { Effect, Semaphore } from "effect" | |
| import type { EffectDrizzleSqlite } from "@opencode-ai/effect-drizzle-sqlite" | |
| import { migrations } from "./migration.gen" | |
| import schema from "./schema.gen" | |
| type Database = EffectDrizzleSqlite.EffectSQLiteDatabase | |
| type Transaction = Parameters<Parameters<Database["transaction"]>[0]>[0] | |
| const lock = Semaphore.makeUnsafe(1) | |
| export type Migration = { | |
| id: string | |
| up: (tx: Transaction) => Effect.Effect<void, unknown> | |
| } | |
| export function apply(db: Database) { | |
| return lock.withPermit( | |
| Effect.gen(function* () { | |
| const tables = yield* db.all<{ name: string }>( | |
| sql`SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'`, | |
| ) | |
| if (tables.some((table) => table.name === "session")) return yield* applyOnly(db, migrations) | |
| if (tables.length > 0) return yield* Effect.die("Database is not empty and has no session table") | |
| yield* db.transaction((tx) => | |
| Effect.gen(function* () { | |
| yield* schema.up(tx) | |
| yield* tx.run( | |
| sql`CREATE TABLE ${sql.identifier("migration")} (id TEXT PRIMARY KEY, time_completed INTEGER NOT NULL)`, | |
| ) | |
| yield* Effect.forEach(migrations, (migration) => | |
| tx.run( | |
| sql`INSERT INTO ${sql.identifier("migration")} (id, time_completed) VALUES (${migration.id}, ${Date.now()})`, | |
| ), | |
| ) | |
| }), | |
| ) | |
| }), | |
| ) | |
| } | |
| export function applyOnly(db: Database, input: Migration[]) { | |
| return Effect.gen(function* () { | |
| yield* db.run( | |
| sql`CREATE TABLE IF NOT EXISTS ${sql.identifier("migration")} (id TEXT PRIMARY KEY, time_completed INTEGER NOT NULL)`, | |
| ) | |
| let completed = new Set( | |
| (yield* db.all<{ id: string }>(sql`SELECT id FROM ${sql.identifier("migration")}`)).map((row) => row.id), | |
| ) | |
| if (completed.size === 0) { | |
| // Existing installs used Drizzle's migration journal. Seed the new | |
| // journal once so TypeScript migrations don't replay old SQL. | |
| if ( | |
| yield* db.get(sql`SELECT name FROM sqlite_master WHERE type = 'table' AND name = ${"__drizzle_migrations"}`) | |
| ) { | |
| yield* db.run(sql` | |
| INSERT OR IGNORE INTO ${sql.identifier("migration")} (id, time_completed) | |
| SELECT name, ${Date.now()} | |
| FROM ${sql.identifier("__drizzle_migrations")} | |
| WHERE name IS NOT NULL | |
| `) | |
| completed = new Set( | |
| (yield* db.all<{ id: string }>(sql`SELECT id FROM ${sql.identifier("migration")}`)).map((row) => row.id), | |
| ) | |
| } | |
| } | |
| for (const migration of input) { | |
| if (completed.has(migration.id)) continue | |
| yield* db.transaction((tx) => | |
| Effect.gen(function* () { | |
| yield* migration.up(tx) | |
| yield* tx.run( | |
| sql`INSERT INTO ${sql.identifier("migration")} (id, time_completed) VALUES (${migration.id}, ${Date.now()})`, | |
| ) | |
| }), | |
| ) | |
| } | |
| }) | |
| } | |
Xet Storage Details
- Size:
- 3.03 kB
- Xet hash:
- 1ff08e330ff0ca139e07ce2d71dab6567342cf7ba6381ad4d870d2471630e9af
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.