Raw SQL migration endpoint (bypass drizzle schema requirement)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Robin Choice
2026-04-12 20:35:30 +02:00
parent e66d8bb490
commit 41e8124d78

View File

@@ -51,12 +51,30 @@ const app = new Hono<AppEnv>()
.get('/health', (c) => c.json({ status: 'ok' })) .get('/health', (c) => c.json({ status: 'ok' }))
.post('/migrate', async (c) => { .post('/migrate', async (c) => {
try { try {
const path = await import('path'); const fs = await import('fs');
const folder = path.resolve(process.cwd(), 'packages/db/src/migrations'); const pathMod = await import('path');
await migrate(db, { migrationsFolder: folder }); const { sql: dsql } = await import('drizzle-orm');
return c.json({ status: 'ok', message: 'Migrations applied', folder }); 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) { } catch (err: any) {
return c.json({ status: 'error', message: err.message, stack: err.stack?.slice(0, 500) }, 500); 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 }, 500);
} }
}) })
.basePath('/api/v1') .basePath('/api/v1')