TypeScript 61.9%
HTML 37.2%
SQL 0.7%
1import { NextResponse } from 'next/server';2import { eq, inArray } from '@/lib/db';3import { db, collections, collectionItems, watchlists, watchlistItems, alerts, savedSearches, priceTargets, notifications, loginEvents, apiKeys } from '@/lib/db';4import { getCurrentUser } from '@/lib/auth/session';56export const dynamic = 'force-dynamic';78/** Full personal data export (GDPR-style): everything the member created, as JSON. */9export async function GET() {10 const u = await getCurrentUser();11 if (!u) return NextResponse.json({ error: 'unauthorized' }, { status: 401 });12 const cols = await db().select().from(collections).where(eq(collections.userId, u.id));13 const items = cols.length ? await db().select().from(collectionItems).where(inArray(collectionItems.collectionId, cols.map((c) => c.id))) : [];14 const wls = await db().select().from(watchlists).where(eq(watchlists.userId, u.id));15 const wItems = wls.length ? await db().select().from(watchlistItems).where(inArray(watchlistItems.watchlistId, wls.map((w) => w.id))) : [];16 const [al, ss, pt, nt, le, keys] = await Promise.all([17 db().select().from(alerts).where(eq(alerts.userId, u.id)),18 db().select().from(savedSearches).where(eq(savedSearches.userId, u.id)),19 db().select().from(priceTargets).where(eq(priceTargets.userId, u.id)),20 db().select().from(notifications).where(eq(notifications.userId, u.id)),21 db().select().from(loginEvents).where(eq(loginEvents.userId, u.id)),22 db().select({ id: apiKeys.id, name: apiKeys.name, prefix: apiKeys.prefix, tier: apiKeys.tier, createdAt: apiKeys.createdAt, revokedAt: apiKeys.revokedAt }).from(apiKeys).where(eq(apiKeys.userId, u.id)),23 ]);24 const { passwordHash: _p, totpSecretEnc: _t, ...profile } = u;25 void _p;26 void _t;27 const body = { exportedAt: new Date().toISOString(), profile, collections: cols, collectionItems: items, watchlists: wls, watchlistItems: wItems, alerts: al, savedSearches: ss, priceTargets: pt, notifications: nt, loginEvents: le, apiKeys: keys };28 return new NextResponse(JSON.stringify(body, null, 2), { headers: { 'content-type': 'application/json', 'content-disposition': `attachment; filename="rareindex-export-${new Date().toISOString().slice(0, 10)}.json"` } });29}30