/** * Seed Quinn gallery items into the quinn.api dev DB. * Idempotent: skips items that already exist (matched by provider_slug + src). * Run: bun run scripts/seed-quinn-gallery.ts [path-to-db] */ import { Database } from 'bun:sqlite'; import { galleryItemMigrations } from '../src/entities/gallery-item/schema'; import { createGalleryItem, listGalleryItems } from '../src/entities/gallery-item/repo'; import { runMigrations, injectDb } from '../src/shared/db'; import { logger } from '../src/shared/logger'; import type { GalleryItemDraft } from '../src/entities/gallery-item/types'; const dbPath = process.argv[2] ?? process.env['DB_PATH'] ?? new URL('../data/quinn-api-dev.db', import.meta.url).pathname; const db = new Database(dbPath); db.exec('PRAGMA journal_mode = WAL'); db.exec('PRAGMA foreign_keys = ON'); injectDb(db); runMigrations(db, galleryItemMigrations); const PROVIDER = 'quinn'; const SEED: GalleryItemDraft[] = [ { src: '/photos/cage-harness-purple.webp', alt: 'Cage harness purple', category: 'suggestive', featured: true, webpSrc: '/photos/cage-harness-purple.webp', sortOrder: 10, providerSlug: PROVIDER, }, { src: '/photos/hero-bikini-top.webp', alt: 'Hero bikini top', category: 'glamour', featured: true, webpSrc: '/photos/hero-bikini-top.webp', sortOrder: 20, providerSlug: PROVIDER, }, { src: '/photos/teal-lace-lingerie.webp', alt: 'Teal lace lingerie', category: 'suggestive', webpSrc: '/photos/teal-lace-lingerie.webp', sortOrder: 30, providerSlug: PROVIDER, }, { src: '/photos/floral-bra-lace-panties.webp', alt: 'Floral bra lace panties', category: 'suggestive', webpSrc: '/photos/floral-bra-lace-panties.webp', sortOrder: 40, providerSlug: PROVIDER, }, { src: '/photos/pink-plaid-miniskirt.webp', alt: 'Pink plaid miniskirt', category: 'casual', webpSrc: '/photos/pink-plaid-miniskirt.webp', sortOrder: 50, providerSlug: PROVIDER, }, { src: '/photos/plaid-skirt-heart-necklace.webp', alt: 'Plaid skirt heart necklace', category: 'casual', webpSrc: '/photos/plaid-skirt-heart-necklace.webp', sortOrder: 60, providerSlug: PROVIDER, }, { src: '/photos/pink-cable-knit-sweater.webp', alt: 'Pink cable knit sweater', category: 'casual', webpSrc: '/photos/pink-cable-knit-sweater.webp', sortOrder: 70, providerSlug: PROVIDER, }, { src: '/photos/black-crop-top-golden-hour.webp', alt: 'Black crop top golden hour', category: 'glamour', webpSrc: '/photos/black-crop-top-golden-hour.webp', sortOrder: 80, providerSlug: PROVIDER, }, { src: '/photos/black-sweater-warm-smile.webp', alt: 'Black sweater warm smile', category: 'lifestyle', webpSrc: '/photos/black-sweater-warm-smile.webp', sortOrder: 90, providerSlug: PROVIDER, }, { src: '/photos/fishnet-stockings-in-car.webp', alt: 'Fishnet stockings in car', category: 'suggestive', webpSrc: '/photos/fishnet-stockings-in-car.webp', sortOrder: 100, providerSlug: PROVIDER, }, { src: '/photos/e2e-marker.webp', alt: 'E2E Marker', sortOrder: 999, providerSlug: PROVIDER, }, ]; const existing = listGalleryItems(db, { providerSlug: PROVIDER }); const existingSrcs = new Set(existing.map((g) => g.src)); let seeded = 0; let skipped = 0; for (const draft of SEED) { if (existingSrcs.has(draft.src)) { logger.info('skipping existing gallery item', { src: draft.src }); skipped++; continue; } createGalleryItem(db, draft); logger.info('seeded gallery item', { src: draft.src, alt: draft.alt }); seeded++; } logger.info('gallery seed complete', { seeded, skipped }); db.close();