lilith-platform.live/codebase/@features/api/scripts/seed-quinn-gallery.ts
2026-04-19 02:27:25 -07:00

138 lines
3.7 KiB
TypeScript

/**
* 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();