| 1 | import * as Effect from "effect/Effect"; |
| 2 | import type { RuntimeContext } from "../../RuntimeContext.ts"; |
| 3 | import { applyAlchemyFormat } from "../../SQL/Migrations/AlchemyFormat.ts"; |
| 4 | import { |
| 5 | MigrationError, |
| 6 | type MigrationHistoryConflictError, |
| 7 | type SqlExecutor, |
| 8 | } from "../../SQL/Migrations/Format.ts"; |
| 9 | import { inlineSqlParams } from "../../SQL/Migrations/Utils.ts"; |
| 10 | import { DurableObjectState } from "./DurableObjectState.ts"; |
| 11 | import type { SqlMigrationSnapshot } from "./SqlMigrationsRuntime.ts"; |
| 12 | |
| 13 | /** @internal */ |
| 14 | export const applySqlMigrations: ( |
| 15 | migrations: SqlMigrationSnapshot, |
| 16 | ) => Effect.Effect< |
| 17 | void, |
| 18 | MigrationError | MigrationHistoryConflictError, |
| 19 | DurableObjectState | RuntimeContext |
| 20 | > = Effect.fn("Cloudflare.SqlMigrations.apply")(function* (migrations) { |
| 21 | const { raw } = yield* DurableObjectState; |
| 22 | const storage = raw.storage; |
| 23 | const executor: SqlExecutor = { |
| 24 | dialect: "sqlite", |
| 25 | query: (sql, params = []) => |
| 26 | Effect.try({ |
| 27 | try: () => |
| 28 | storage.sql.exec(inlineSqlParams(sql, params, "sqlite")).toArray(), |
| 29 | catch: (cause) => |
| 30 | new MigrationError({ |
| 31 | message: "Failed to query migration history", |
| 32 | cause, |
| 33 | }), |
| 34 | }), |
| 35 | batch: (statements) => |
| 36 | Effect.try({ |
| 37 | try: () => |
| 38 | storage.transactionSync(() => { |
| 39 | for (const statement of statements) storage.sql.exec(statement); |
| 40 | }), |
| 41 | catch: (cause) => |
| 42 | new MigrationError({ |
| 43 | message: "Failed to apply SQL migration", |
| 44 | cause, |
| 45 | }), |
| 46 | }), |
| 47 | }; |
| 48 | yield* applyAlchemyFormat({ |
| 49 | executor, |
| 50 | table: migrations.table, |
| 51 | records: migrations.records, |
| 52 | }); |
| 53 | }); |