UNPKG

@storecraft/database-cloudflare-d1

Version:

`Storecraft` database driver for `cloudflare` D1 (cloud sqlite)

137 lines (120 loc) 3.56 kB
import { SQL } from "@storecraft/database-sql-base"; import { AggregateDialect } from "@storecraft/database-sql-base/kysely.aggregate.dialect.js"; import { get_migrations } from "@storecraft/database-sql-base/migrate.js"; import { prepare_and_bind } from "@storecraft/database-sql-base/utils.js"; import { Kysely, Migrator } from "kysely"; import path from 'node:path'; import { fileURLToPath } from "node:url"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); /** * * @param {SQL} db_driver * @param {boolean} [destroy_db_upon_completion=true] */ export async function migrateToLatest( db_driver, destroy_db_upon_completion=true ) { const db = db_driver?.client; if(!db) throw new Error('No Kysely client found !!!'); console.log( 'Resolving migrations. This may take 2 minutes ...' ); const migrations = await get_migrations(db_driver.dialectType); if(!migrations) throw new Error('No migrations found !!!'); const sorted = Object .entries(migrations) .sort((a, b) => a[0].localeCompare(b[0])); /** @type {Record<string, import("kysely").Migration>} */ const rewritten_migrations = {}; for (const [name, migration] of sorted) { // console.log(`Executing virtual migration "${name}" ...`); const up_agg_dialect = new AggregateDialect( { dialect: db_driver.config.dialect, } ); const up_agg_kysely = new Kysely( { dialect: up_agg_dialect } ); const down_agg_dialect = new AggregateDialect( { dialect: db_driver.config.dialect, } ); const down_agg_kysely = new Kysely( { dialect: down_agg_dialect } ); await migration.up(up_agg_kysely); await migration.down(down_agg_kysely); // now get the queries const queries_up = up_agg_dialect.queries; const queries_down = down_agg_dialect.queries; // prepare_and_bind rewritten_migrations[name] = { up: async (db) => { const concat_query = queries_up.map( (query) => { return prepare_and_bind( query.sql, query.parameters ); } ).join(';'); await db.executeQuery( { sql: concat_query, parameters: undefined, query: undefined, queryId: undefined } ) }, down: async (db) => { const concat_query = queries_down.map( (query) => { return prepare_and_bind( query.sql, query.parameters ); } ).join(';'); await db.executeQuery( { sql: concat_query, parameters: undefined, query: undefined, queryId: undefined } ) } } } const migrator = new Migrator( { db, provider: { getMigrations: async () => { return rewritten_migrations; } } } ); const { error, results } = await migrator.migrateToLatest(); results?.forEach( (it) => { if (it.status === 'Success') { console.log( `migration "${it.migrationName}" was executed successfully` ); } else if (it.status === 'Error') { console.error( `failed to execute migration "${it.migrationName}"` ); } } ); if (error) { console.error('failed to migrate') console.error(JSON.stringify(error, null, 2)) process.exit(1) } if(destroy_db_upon_completion) await db.destroy(); }