// Export kampaní (templates) a šablón cenoviek (badges) zo Supabase do supabase/data/ // pre prenos na nový server. Stiahne aj obrázky z úložiska newsletter-assets, na ktoré // dáta odkazujú a nie sú medzi statickými obrázkami v supabase/assets/. // Spustenie: npm run db:export (číta .env.local pôvodného projektu) import { createClient } from '@supabase/supabase-js'; import { mkdir, writeFile, access } from 'node:fs/promises'; import path from 'node:path'; const BUCKET = 'newsletter-assets'; const TABLES = ['templates', 'badges']; const DATA_DIR = path.join(process.cwd(), 'supabase', 'data'); const FILES_DIR = path.join(DATA_DIR, 'files'); const ASSETS_DIR = path.join(process.cwd(), 'supabase', 'assets'); const url = (process.env.NEXT_PUBLIC_SUPABASE_URL || '').replace(/\/$/, ''); const key = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY; if (!url || !key) { console.error('Chýba NEXT_PUBLIC_SUPABASE_URL alebo kľúč (SUPABASE_SERVICE_ROLE_KEY / NEXT_PUBLIC_SUPABASE_ANON_KEY) v .env.local'); process.exit(1); } const supabase = createClient(url, key); const storageBase = `${url}/storage/v1/object/public/${BUCKET}/`; await mkdir(FILES_DIR, { recursive: true }); const referenced = new Set(); for (const table of TABLES) { const { data, error } = await supabase.from(table).select('*').order('created_at', { ascending: true }); if (error) { console.error(`✗ ${table}: ${error.message}`); process.exit(1); } await writeFile(path.join(DATA_DIR, `${table}.json`), JSON.stringify(data, null, 2) + '\n'); console.log(`✓ ${table}: ${data.length} záznamov`); // Odkazy na súbory v úložisku (cesta v rámci bucketu) const json = JSON.stringify(data); let i = 0; while ((i = json.indexOf(storageBase, i)) !== -1) { const start = i + storageBase.length; let end = start; while (end < json.length && !`"'()\\ `.includes(json[end])) end++; referenced.add(decodeURIComponent(json.slice(start, end))); i = end; } } const exists = (p) => access(p).then(() => true, () => false); let downloaded = 0; for (const filePath of referenced) { // Statické obrázky šablóny sú už v supabase/assets a nahrajú sa cez db:upload-assets if (!filePath.includes('/') && (await exists(path.join(ASSETS_DIR, filePath)))) continue; const res = await fetch(storageBase + filePath.split('/').map(encodeURIComponent).join('/')); if (!res.ok) { console.warn(`! ${filePath}: HTTP ${res.status} (preskočené)`); continue; } const target = path.join(FILES_DIR, filePath); await mkdir(path.dirname(target), { recursive: true }); await writeFile(target, Buffer.from(await res.arrayBuffer())); downloaded++; } await writeFile( path.join(DATA_DIR, 'meta.json'), JSON.stringify({ exportedAt: new Date().toISOString(), sourceStorageBase: storageBase }, null, 2) + '\n' ); console.log(`✓ obrázky: ${referenced.size} odkazov, ${downloaded} stiahnutých do supabase/data/files/`); console.log('\nHotovo. Commitnite priečinok supabase/data/ a na novom serveri spustite npm run db:import.');