Files
gnommoeditor/backend/migrations/015_uuid_ids.cjs
T

67 lines
4.3 KiB
JavaScript
Raw Normal View History

2026-04-11 09:24:21 +02:00
// Convert videos.id and slides.id (plus every FK that references them) from
// serial integers to UUID (gen_random_uuid).
//
// Safe for dev: truncates all video data first. Re-run the push script after
// migrating to re-ingest videos. shared_assets (asset library) is unchanged.
//
// This is a one-way migration. There is no meaningful down path.
const CHILD_TABLES = [
// table FK constraint name UNIQUE constraint name UNIQUE expression
['narration_segments', 'narration_segments_project_id_fkey', 'narration_segments_project_key_unique', '(project_id, segment_key)'],
['cutouts', 'cutouts_project_id_fkey', 'cutouts_project_name_unique', '(project_id, name)'],
['filter_chains', 'filter_chains_project_id_fkey', null, null],
['video_assets', 'video_assets_project_id_fkey', 'video_assets_project_key_unique', '(project_id, asset_key)'],
['audio_tracks', 'audio_tracks_project_id_fkey', 'audio_tracks_project_key_unique', '(project_id, track_key)'],
['citations', 'citations_project_id_fkey', null, null],
['project_sync', 'project_sync_project_id_fkey', 'project_sync_project_id_key', '(project_id)'],
['transcripts', 'transcripts_project_id_fkey', 'transcripts_project_source_unique', '(project_id, source_name)'],
];
exports.up = (pgm) => {
// ── Clear all video data ─────────────────────────────────────────────────
pgm.sql('TRUNCATE videos CASCADE');
// ── 1. Drop all FKs pointing at videos.id BEFORE touching the PK ────────
// slides
pgm.sql('ALTER TABLE slides DROP CONSTRAINT IF EXISTS slides_video_id_fkey');
pgm.sql('ALTER TABLE slides DROP CONSTRAINT IF EXISTS slides_video_id_gnommo_slide_id_unique');
// all other child tables
for (const [table, fkName, uniqueName] of CHILD_TABLES) {
pgm.sql(`ALTER TABLE ${table} DROP CONSTRAINT IF EXISTS ${fkName}`);
if (uniqueName) pgm.sql(`ALTER TABLE ${table} DROP CONSTRAINT IF EXISTS ${uniqueName}`);
}
// ── 2. videos.id: serial → uuid ─────────────────────────────────────────
pgm.sql('ALTER TABLE videos ALTER COLUMN id DROP DEFAULT');
pgm.sql('ALTER TABLE videos DROP CONSTRAINT videos_pkey');
pgm.sql('ALTER TABLE videos ALTER COLUMN id TYPE uuid USING gen_random_uuid()');
pgm.sql('ALTER TABLE videos ALTER COLUMN id SET DEFAULT gen_random_uuid()');
pgm.sql('ALTER TABLE videos ADD PRIMARY KEY (id)');
// ── 3. slides: video_id FK column, then id PK ───────────────────────────
pgm.sql('ALTER TABLE slides ALTER COLUMN video_id TYPE uuid USING gen_random_uuid()');
pgm.sql('ALTER TABLE slides ADD CONSTRAINT slides_video_id_gnommo_slide_id_unique UNIQUE (video_id, gnommo_slide_id)');
pgm.sql('ALTER TABLE slides ADD CONSTRAINT slides_video_id_fkey FOREIGN KEY (video_id) REFERENCES videos(id) ON DELETE CASCADE');
pgm.sql('ALTER TABLE slides ALTER COLUMN id DROP DEFAULT');
pgm.sql('ALTER TABLE slides DROP CONSTRAINT slides_pkey');
pgm.sql('ALTER TABLE slides ALTER COLUMN id TYPE uuid USING gen_random_uuid()');
pgm.sql('ALTER TABLE slides ALTER COLUMN id SET DEFAULT gen_random_uuid()');
pgm.sql('ALTER TABLE slides ADD PRIMARY KEY (id)');
// ── 4. All other child tables: project_id integer → uuid ────────────────
for (const [table, fkName, uniqueName, uniqueExpr] of CHILD_TABLES) {
pgm.sql(`ALTER TABLE ${table} ALTER COLUMN project_id TYPE uuid USING gen_random_uuid()`);
if (uniqueName && uniqueExpr) {
pgm.sql(`ALTER TABLE ${table} ADD CONSTRAINT ${uniqueName} UNIQUE ${uniqueExpr}`);
}
pgm.sql(`ALTER TABLE ${table} ADD CONSTRAINT ${fkName} FOREIGN KEY (project_id) REFERENCES videos(id) ON DELETE CASCADE`);
}
};
exports.down = () => {
// Intentionally empty — reversing uuid → serial would require re-sequencing
// all IDs and is not worth implementing for a dev-only migration.
};