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

105 lines
2.8 KiB
TypeScript

/**
* Seed Quinn shop listings into the quinn.api dev DB.
* Idempotent: skips listings that already exist (matched by provider_slug + slug).
* Run: bun run scripts/seed-quinn-shop.ts [path-to-db]
*/
import { Database } from 'bun:sqlite';
import { shopListingMigrations } from '../src/entities/shop-listing/schema';
import { createShopListing, listShopListings } from '../src/entities/shop-listing/repo';
import { runMigrations, injectDb } from '../src/shared/db';
import { logger } from '../src/shared/logger';
import type { ShopListingDraft } from '../src/entities/shop-listing/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, shopListingMigrations);
const PROVIDER = 'quinn';
const SEED: ShopListingDraft[] = [
{
slug: 'sheer-lace-bodysuit',
title: 'Sheer Lace Bodysuit',
description: 'Black sheer lace bodysuit, worn a handful of times. Size S.',
price: 45,
currency: 'USD',
condition: 'like_new',
category: 'lingerie',
size: 'S',
status: 'available',
photos: [],
sortOrder: 10,
providerSlug: PROVIDER,
},
{
slug: 'thigh-high-boots',
title: 'Thigh-High Boots',
description: 'Black faux-leather thigh-high boots, size 10. Minimal wear.',
price: 85,
currency: 'USD',
condition: 'good',
category: 'accessories',
size: '10',
status: 'available',
photos: [],
sortOrder: 20,
providerSlug: PROVIDER,
},
{
slug: 'mini-skirt-vinyl',
title: 'Vinyl Mini Skirt',
description: 'Glossy vinyl mini skirt. Size M. Perfect for shoots or nights out.',
price: 35,
currency: 'USD',
condition: 'good',
category: 'clothing',
size: 'M',
status: 'available',
photos: [],
sortOrder: 30,
providerSlug: PROVIDER,
},
{
slug: 'e2e-marker',
title: 'E2E Markerton Item',
description: 'Synthetic listing used for end-to-end test assertions.',
price: 1337,
currency: 'USD',
condition: 'new',
category: 'other',
status: 'available',
photos: [],
sortOrder: 999,
providerSlug: PROVIDER,
},
];
const existing = listShopListings(db, { providerSlug: PROVIDER });
const existingSlugs = new Set(existing.map((s) => s.slug));
let seeded = 0;
let skipped = 0;
for (const draft of SEED) {
if (existingSlugs.has(draft.slug)) {
logger.info('skipping existing shop listing', { slug: draft.slug });
skipped++;
continue;
}
createShopListing(db, draft);
logger.info('seeded shop listing', { slug: draft.slug, title: draft.title });
seeded++;
}
logger.info('seed complete', { seeded, skipped });
db.close();