200 lines
9.8 KiB
TypeScript
200 lines
9.8 KiB
TypeScript
/**
|
|
* Seed Quinn's destinations into the quinn.api dev DB.
|
|
*
|
|
* Idempotent: skips any destination that already exists (matched by provider_slug + slug).
|
|
* Run: bun run scripts/seed-quinn-destinations.ts [path-to-db]
|
|
*/
|
|
|
|
import { Database } from 'bun:sqlite';
|
|
|
|
import { destinationMigrations } from '../src/entities/destination/schema';
|
|
import { createDestination, listDestinations } from '../src/entities/destination/repo';
|
|
import { runMigrations, injectDb } from '../src/shared/db';
|
|
import { logger } from '../src/shared/logger';
|
|
import type { DestinationDraft } from '../src/entities/destination/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, destinationMigrations);
|
|
|
|
const PROVIDER = 'quinn';
|
|
|
|
const SEED: DestinationDraft[] = [
|
|
{
|
|
slug: 'san-francisco',
|
|
city: 'San Francisco',
|
|
country: 'US',
|
|
region: 'California',
|
|
fmtyTier: 'west-coast',
|
|
metaTitle: 'San Francisco Escort — Quinn FTW',
|
|
metaDescription: 'Trans escort based in San Francisco. Incall in Berkeley and SOMA. Available for hotel outcall across the Bay Area.',
|
|
headline: 'San Francisco',
|
|
intro: 'Home base. I live in the East Bay and book incall sessions in Berkeley and SOMA — reach out with your hotel or neighborhood and I\'ll let you know if it works.\n\nI prefer afternoon and evening appointments, and I like a client who\'s done their reading before reaching out. Check the rates page first, then text or email.',
|
|
linkedTourStop: false,
|
|
experiences: ['Berkeley incall', 'SOMA incall', 'Hotel outcall', 'Overnight bookings'],
|
|
sortOrder: 10,
|
|
visibility: 'public',
|
|
providerSlug: PROVIDER,
|
|
},
|
|
{
|
|
slug: 'los-angeles',
|
|
city: 'Los Angeles',
|
|
country: 'US',
|
|
region: 'California',
|
|
fmtyTier: 'west-coast',
|
|
metaTitle: 'Los Angeles Escort — Quinn FTW',
|
|
metaDescription: 'Trans escort visiting Los Angeles for multi-day trips. West Hollywood, Beverly Hills, and DTLA. FMTY rates apply.',
|
|
headline: 'Los Angeles',
|
|
intro: 'I make it to LA a few times a year — usually for three to five days at a stretch. I book from a hotel in West Hollywood or Beverly Hills and take outcall appointments across the Westside and downtown.\n\nIf you\'re in LA and want to arrange something while I\'m in town, reach out early — spots fill fast once the dates are confirmed. FMTY is also on the table year-round if you prefer to fly me down.',
|
|
experiences: ['West Hollywood hotel', 'Beverly Hills outcall', 'DTLA availability', 'FMTY bookings'],
|
|
sortOrder: 20,
|
|
visibility: 'public',
|
|
providerSlug: PROVIDER,
|
|
},
|
|
{
|
|
slug: 'seattle',
|
|
city: 'Seattle',
|
|
country: 'US',
|
|
region: 'Washington',
|
|
fmtyTier: 'west-coast',
|
|
metaTitle: 'Seattle Escort — Quinn FTW',
|
|
metaDescription: 'Trans escort visiting Seattle. Capitol Hill area preferred. FMTY available from San Francisco.',
|
|
headline: 'Seattle',
|
|
intro: 'I tour Seattle maybe twice a year, usually staying in Capitol Hill or downtown. The Pacific Northwest clients I\'ve had are some of my favorite — unhurried, good conversationalists, actually read the booking instructions.\n\nCheck the tour schedule for confirmed dates. If nothing\'s listed, FMTY works — I\'ll need travel covered plus my standard overnight rate.',
|
|
experiences: ['Capitol Hill', 'Downtown hotels', 'FMTY from SF', 'Overnight sessions'],
|
|
sortOrder: 30,
|
|
visibility: 'public',
|
|
providerSlug: PROVIDER,
|
|
},
|
|
{
|
|
slug: 'new-york-city',
|
|
city: 'New York City',
|
|
country: 'US',
|
|
region: 'New York',
|
|
fmtyTier: 'domestic',
|
|
metaTitle: 'New York City Escort — Quinn FTW',
|
|
metaDescription: 'Trans escort available in New York City via FMTY. Manhattan preferred. Extended trip bookings welcome.',
|
|
headline: 'New York City',
|
|
intro: 'NYC is on my list — I haven\'t toured yet but I\'m open to FMTY arrangements for Manhattan. If you\'re covering business-class round-trip from SFO and hotel in Midtown or Chelsea, text me and let\'s talk dates.\n\nI book NYC FMTY as three-day minimum. Shorter trips don\'t make sense for either of us at that distance.',
|
|
experiences: ['Manhattan FMTY', 'Midtown hotels', 'Chelsea area', 'Extended bookings only'],
|
|
sortOrder: 40,
|
|
visibility: 'public',
|
|
providerSlug: PROVIDER,
|
|
},
|
|
{
|
|
slug: 'las-vegas',
|
|
city: 'Las Vegas',
|
|
country: 'US',
|
|
region: 'Nevada',
|
|
fmtyTier: 'west-coast',
|
|
metaTitle: 'Las Vegas Escort — Quinn FTW',
|
|
metaDescription: 'Trans escort visiting Las Vegas. Summerlin, The Lakes, Skye Canyon. Hotel incall or suite outcall. West Coast FMTY rates.',
|
|
headline: 'Las Vegas',
|
|
intro: 'I visit Vegas two or three times a year, usually booking from a suite at one of the quieter Strip properties — not the party hotels. If you\'re there for business or staying somewhere with actual privacy, reach out and let\'s find dates that work.\n\nSummerlin clients, I can meet at your place too. The suburban neighborhoods here are genuinely nice and I\'d rather not make you come to a casino if you don\'t need to.',
|
|
experiences: ['Hotel suite incall', 'Summerlin / The Lakes outcall', 'Business visit scheduling', 'West Coast FMTY rates'],
|
|
sortOrder: 25,
|
|
visibility: 'public',
|
|
providerSlug: PROVIDER,
|
|
},
|
|
{
|
|
slug: 'portland',
|
|
city: 'Portland',
|
|
country: 'US',
|
|
region: 'Oregon',
|
|
fmtyTier: 'west-coast',
|
|
metaTitle: 'Portland Escort — Quinn FTW',
|
|
metaDescription: 'Trans escort visiting Portland, Oregon. Pearl District and West Hills preferred. FMTY from SF.',
|
|
headline: 'Portland',
|
|
intro: 'Portland\'s on my rotation — I usually stay somewhere in the Pearl District or near NW 23rd when I\'m there. It\'s an easy trip from the Bay and the clients I\'ve met here have been solid: low-drama, read the instructions, decent hotels.\n\nI don\'t announce Portland dates far in advance. If you want to know when I\'m next up there, drop me a text and I\'ll put you on the list.',
|
|
experiences: ['Pearl District hotel', 'NW Portland area', 'West Hills outcall', 'FMTY from SF'],
|
|
sortOrder: 35,
|
|
visibility: 'public',
|
|
providerSlug: PROVIDER,
|
|
},
|
|
{
|
|
slug: 'san-diego',
|
|
city: 'San Diego',
|
|
country: 'US',
|
|
region: 'California',
|
|
fmtyTier: 'west-coast',
|
|
metaTitle: 'San Diego Escort — Quinn FTW',
|
|
metaDescription: 'Trans escort visiting San Diego. La Jolla, Del Mar, Coronado preferred. West Coast FMTY rates.',
|
|
headline: 'San Diego',
|
|
intro: 'La Jolla is the sweet spot for SD bookings — the hotels there are actually good and the clientele is what I\'m looking for. Coronado works if you\'re staying there. Del Mar is fine too, especially during race season when there\'s actual energy in the city.\n\nI do SD maybe twice a year. FMTY applies at West Coast rates — it\'s a quick flight from SFO.',
|
|
experiences: ['La Jolla hotel', 'Coronado / Del Mar', 'FMTY West Coast rates', 'Short-notice possible'],
|
|
sortOrder: 28,
|
|
visibility: 'public',
|
|
providerSlug: PROVIDER,
|
|
},
|
|
{
|
|
slug: 'chicago',
|
|
city: 'Chicago',
|
|
country: 'US',
|
|
region: 'Illinois',
|
|
fmtyTier: 'domestic',
|
|
metaTitle: 'Chicago Escort — Quinn FTW',
|
|
metaDescription: 'Trans escort available in Chicago via FMTY. Gold Coast, Lincoln Park, River North. Domestic rates.',
|
|
headline: 'Chicago',
|
|
intro: 'Chicago is one of my favorite cities to visit when someone\'s covering the logistics right. Gold Coast or River North for hotels — somewhere with actual doormen and not a converted Airbnb. The architecture alone makes the trip worth it, and the food is genuinely great if we\'re doing dinner.\n\nDomestic FMTY rates apply. I\'d want three to five days minimum to make it make sense — shorter doesn\'t justify the flight from the West Coast.',
|
|
experiences: ['Gold Coast hotel', 'River North area', 'Dinner dates welcome', 'Three-day minimum recommended'],
|
|
sortOrder: 50,
|
|
visibility: 'public',
|
|
providerSlug: PROVIDER,
|
|
},
|
|
{
|
|
slug: 'miami',
|
|
city: 'Miami',
|
|
country: 'US',
|
|
region: 'Florida',
|
|
fmtyTier: 'domestic',
|
|
metaTitle: 'Miami Escort — Quinn FTW',
|
|
metaDescription: 'Trans escort available in Miami via FMTY. South Beach, Brickell, Coconut Grove. Domestic FMTY rates.',
|
|
headline: 'Miami',
|
|
intro: 'Miami on the right terms — South Beach with a room that\'s actually quiet, or Brickell if you\'re there for work and want company that\'s more interesting than the hotel bar. I like the Wynwood murals and I will absolutely drag you through them if you give me an afternoon off-schedule.\n\nDomestic FMTY. Book early — I schedule Miami trips sparingly and the dates fill from the list.',
|
|
experiences: ['South Beach hotel', 'Brickell / Coconut Grove', 'Wynwood / Midtown', 'Domestic FMTY rates'],
|
|
sortOrder: 60,
|
|
visibility: 'public',
|
|
providerSlug: PROVIDER,
|
|
},
|
|
{
|
|
slug: 'e2e-marker',
|
|
city: 'E2E Markerton',
|
|
country: 'US',
|
|
fmtyTier: 'domestic',
|
|
metaTitle: 'E2E Marker Destination',
|
|
metaDescription: 'Synthetic destination used for end-to-end test assertions.',
|
|
headline: 'E2E Markerton',
|
|
intro: 'This destination exists solely as a stable anchor for automated e2e tests.',
|
|
sortOrder: 999,
|
|
visibility: 'public',
|
|
providerSlug: PROVIDER,
|
|
},
|
|
];
|
|
|
|
const existing = listDestinations(db, { providerSlug: PROVIDER });
|
|
const existingSlugs = new Set(existing.map((d) => d.slug));
|
|
|
|
let seeded = 0;
|
|
let skipped = 0;
|
|
|
|
for (const draft of SEED) {
|
|
if (existingSlugs.has(draft.slug)) {
|
|
logger.info('skipping existing destination', { slug: draft.slug });
|
|
skipped++;
|
|
continue;
|
|
}
|
|
createDestination(db, draft);
|
|
logger.info('seeded destination', { slug: draft.slug, city: draft.city });
|
|
seeded++;
|
|
}
|
|
|
|
logger.info('seed complete', { seeded, skipped });
|
|
db.close();
|