/** * Run Jane store discovery and insert into database * Usage: npx ts-node scripts/run-jane-store-discovery.ts [STATE_CODE] * Example: npx ts-node scripts/run-jane-store-discovery.ts AZ */ import { Pool } from 'pg'; import { discoverStoresByState } from '../src/platforms/jane'; /** * Generate slug from store name * e.g., "Hana Meds - Phoenix (REC)" -> "hana-meds-phoenix-rec" */ function generateSlug(name: string): string { return name .toLowerCase() .replace(/[()]/g, '') // Remove parentheses .replace(/[^a-z0-9\s-]/g, '') // Remove special chars .replace(/\s+/g, '-') // Spaces to hyphens .replace(/-+/g, '-') // Collapse multiple hyphens .replace(/^-|-$/g, ''); // Trim hyphens } async function main() { const stateCode = process.argv[2] || 'AZ'; console.log('='.repeat(60)); console.log(`Jane Store Discovery - ${stateCode}`); console.log('='.repeat(60)); // Connect to database const pool = new Pool({ connectionString: process.env.DATABASE_URL, }); try { // Test connection const testResult = await pool.query('SELECT COUNT(*) FROM dispensaries WHERE platform = $1', ['jane']); console.log(`Current Jane stores in DB: ${testResult.rows[0].count}`); // Discover stores console.log(`\nDiscovering Jane stores in ${stateCode}...`); const stores = await discoverStoresByState(stateCode); if (stores.length === 0) { console.log(`No stores found in ${stateCode}`); return; } console.log(`\nFound ${stores.length} stores. Inserting into database...`); // Insert stores let inserted = 0; let updated = 0; const newIds: number[] = []; for (const store of stores) { const menuUrl = `https://www.iheartjane.com/stores/${store.storeId}/${store.urlSlug || 'menu'}`; const slug = generateSlug(store.name); try { const result = await pool.query( `INSERT INTO dispensaries ( name, slug, address1, city, state, zipcode, latitude, longitude, menu_url, menu_type, platform, platform_dispensary_id, is_medical, is_recreational, stage, created_at, updated_at ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, NOW(), NOW()) ON CONFLICT (platform_dispensary_id) WHERE platform_dispensary_id IS NOT NULL DO UPDATE SET name = EXCLUDED.name, slug = EXCLUDED.slug, address1 = EXCLUDED.address1, city = EXCLUDED.city, latitude = EXCLUDED.latitude, longitude = EXCLUDED.longitude, menu_url = EXCLUDED.menu_url, is_medical = EXCLUDED.is_medical, is_recreational = EXCLUDED.is_recreational, updated_at = NOW() RETURNING id, (xmax = 0) AS is_new`, [ store.name, slug, store.address, store.city, stateCode, store.zip, store.lat, store.long, menuUrl, 'embedded', // menu_type: how it's displayed 'jane', // platform: who provides the menu store.storeId, store.medical, store.recreational, 'discovered', ] ); if (result.rows.length > 0) { const { id, is_new } = result.rows[0]; if (is_new) { inserted++; newIds.push(id); console.log(` + Inserted: ${store.name} (DB ID: ${id}, Jane ID: ${store.storeId})`); } else { updated++; console.log(` ~ Updated: ${store.name} (DB ID: ${id})`); } } } catch (error: any) { console.error(` ! Error inserting ${store.name}: ${error.message}`); } } console.log('\n' + '='.repeat(60)); console.log('RESULTS'); console.log('='.repeat(60)); console.log(`Stores discovered: ${stores.length}`); console.log(`New stores inserted: ${inserted}`); console.log(`Existing stores updated: ${updated}`); console.log(`New dispensary IDs: ${newIds.join(', ') || '(none)'}`); // Show final count const finalResult = await pool.query('SELECT COUNT(*) FROM dispensaries WHERE platform = $1', ['jane']); console.log(`\nTotal Jane stores in DB: ${finalResult.rows[0].count}`); } catch (error: any) { console.error('Error:', error.message); process.exit(1); } finally { await pool.end(); } } main();