138 lines
3.7 KiB
TypeScript
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();
|