diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index f06ab61..dd4274f 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -51,12 +51,30 @@ const app = new Hono() .get('/health', (c) => c.json({ status: 'ok' })) .post('/migrate', async (c) => { try { - const path = await import('path'); - const folder = path.resolve(process.cwd(), 'packages/db/src/migrations'); - await migrate(db, { migrationsFolder: folder }); - return c.json({ status: 'ok', message: 'Migrations applied', folder }); + const fs = await import('fs'); + const pathMod = await import('path'); + const { sql: dsql } = await import('drizzle-orm'); + const folder = pathMod.resolve(process.cwd(), 'packages/db/src/migrations'); + const journal = JSON.parse(fs.readFileSync(pathMod.join(folder, 'meta', '_journal.json'), 'utf8')); + const results: string[] = []; + for (const entry of journal.entries) { + const sqlFile = pathMod.join(folder, `${entry.tag}.sql`); + if (!fs.existsSync(sqlFile)) { results.push(`skip: ${entry.tag} (not found)`); continue; } + const rawSql = fs.readFileSync(sqlFile, 'utf8'); + const statements = rawSql.split('--> statement-breakpoint').map((s: string) => s.trim()).filter(Boolean); + for (const stmt of statements) { + try { + await db.execute(dsql.raw(stmt)); + } catch (err: any) { + if (err.message?.includes('already exists') || err.message?.includes('duplicate')) continue; + results.push(`error in ${entry.tag}: ${err.message?.slice(0, 150)}`); + } + } + results.push(`ok: ${entry.tag}`); + } + return c.json({ status: 'ok', results }); } catch (err: any) { - return c.json({ status: 'error', message: err.message, stack: err.stack?.slice(0, 500) }, 500); + return c.json({ status: 'error', message: err.message }, 500); } }) .basePath('/api/v1')