Files
qinglong/back/shared/schemaMigrations.ts
T
whyour e3989f86aa feat: migrate SQLite runtime and verify complete upgrade bundles
Use MikroORM's official Node SQLite dialect with bounded database isolation, preserve legacy schema and data for rollback, and require Node 22.17 or newer. Update Debian runtimes and retain ARMv6 musl compatibility without a SQLite addon.

Complete short archive writes, stop orphaned SQL workers after owner death, preserve buffered startup requests, and prestart the archived backend on every platform. Cover real package installation, migration, failure recovery, and legacy database compatibility.
2026-10-22 12:22:27 +08:00

61 lines
2.3 KiB
TypeScript

import { DatabaseClient } from '../data/databaseClient';
// Append new entries; IDs are persisted and must not be renumbered or reused.
const columns = [
{
table: 'CrontabViews',
column: 'filterRelation',
type: 'VARCHAR(255)',
},
{ table: 'Subscriptions', column: 'proxy', type: 'VARCHAR(255)' },
{ table: 'CrontabViews', column: 'type', type: 'NUMBER' },
{ table: 'Subscriptions', column: 'autoAddCron', type: 'NUMBER' },
{ table: 'Subscriptions', column: 'autoDelCron', type: 'NUMBER' },
{ table: 'Crontabs', column: 'sub_id', type: 'NUMBER' },
{ table: 'Crontabs', column: 'extra_schedules', type: 'JSON' },
{ table: 'Crontabs', column: 'task_before', type: 'TEXT' },
{ table: 'Crontabs', column: 'task_after', type: 'TEXT' },
{ table: 'Crontabs', column: 'log_name', type: 'VARCHAR(255)' },
{
table: 'Crontabs',
column: 'allow_multiple_instances',
type: 'NUMBER',
},
{ table: 'Crontabs', column: 'work_dir', type: 'VARCHAR(255)' },
{ table: 'Envs', column: 'isPinned', type: 'NUMBER' },
{ table: 'Envs', column: 'labels', type: 'JSON' },
{ table: 'Crontabs', column: 'queued_token', type: 'VARCHAR(255)' },
];
export async function migrateSchema(database: DatabaseClient): Promise<void> {
await database.transaction(async () => {
await database.query(
'CREATE TABLE IF NOT EXISTS "SchemaMigrations" ("id" TEXT PRIMARY KEY, "applied_at" TEXT NOT NULL)',
);
const applied = await database.query<{ id: string }>(
'SELECT "id" FROM "SchemaMigrations"',
);
const appliedIds = new Set(applied.map(({ id }) => id));
for (const { table, column, type } of columns) {
const id = `add-${table}-${column}`;
const fields = await database.query<{ name: string }>(
`PRAGMA table_info("${table}")`,
);
if (fields.length === 0)
throw new Error(`Migration table is missing: ${table}`);
if (!fields.some((field) => field.name === column)) {
// table/column/type come only from the static migration manifest above.
await database.query(
`ALTER TABLE "${table}" ADD COLUMN "${column}" ${type}`,
);
}
if (!appliedIds.has(id)) {
await database.query(
'INSERT INTO "SchemaMigrations" ("id", "applied_at") VALUES (?, ?)',
[id, new Date().toISOString()],
);
}
}
});
}