#!/usr/bin/env node /** * Merged replacement for the legacy get911.js and storeAddress.js scripts. * Pulls the store list from SIW, validates each address with Google, looks up * phone numbers with Twilio, and writes buildingFile.csv + locationFile.csv * suitable for the E911 uploader. * * Usage: * node scripts/generate911Csv.js [--env dev|prod] * * Defaults to prod. The SIW filter endpoint takes /Store/Filter/{page}/{size}/{sort}/{dir}. */ import fs from 'node:fs/promises'; import { config } from '../src/config.js'; import { getSIWData } from '../src/integrations/siw.js'; import { validatePhoneNumber } from '../src/integrations/twilio.js'; import { formatE911Address, formatSuite, validateAddress } from '../src/integrations/google.js'; import { logger } from '../src/logger.js'; const BUILDING_HEADER = '"Building Name *","Address *","Supplemental Info (20)","Organization Name Override (50)"\n'; const LOCATION_HEADER = '"Building Name *","Location Name *","Phone Number (10)","Alternate ID (50)","Callback Number (10)","Location Info (20)","Organization Name Override (50)","HTML Link Name (64)","HTML Link URL (1024)"\n'; function brandFor(brandCode) { switch (brandCode) { case 'AE': return 'American Eagle'; case 'AR': return 'Aerie'; default: return 'American Eagle'; } } async function main() { const args = process.argv.slice(2); const envIndex = args.indexOf('--env'); const envOverride = envIndex >= 0 ? args[envIndex + 1] : undefined; const baseUrl = envOverride === 'dev' ? config.siw.baseUrl.replace('-prod.', '-dev.') : config.siw.baseUrl; const listUrl = `${baseUrl}/api/Store/Filter/1/9999/store_number/1`; logger.info(`Fetching stores from ${listUrl}`); const stores = await getSIWData(listUrl); let buildingCsv = BUILDING_HEADER; let locationCsv = LOCATION_HEADER; let liveStores = 0; for (const store of stores.stores ?? []) { const openInUsProd = store.status_id === 2 && store.environment_code === 'PRD' && store.country_code === 'US' && store.brand_code !== 'TS' && store.store_number > 1000; if (!openInUsProd) continue; try { const googleAddress = await validateAddress( `${store.address ?? ''} ${store.address2 ?? ''}`.trim(), store.city, store.state, store.postal_code, store.country_code, ); const formatted = formatE911Address(googleAddress); const suite = formatSuite(googleAddress); const phone = await validatePhoneNumber(store.phone); const brand = brandFor(store.brand_code); const padded = String(store.store_number).padStart(4, '0'); buildingCsv += `"Store ${padded}","${formatted}",,"${brand}"\n`; locationCsv += `"Store ${padded}","Store ${padded}","${phone.phone_number}",,,"${suite}","${brand}",,\n`; liveStores++; } catch (error) { logger.error(`Failed store ${store.store_number}:`, error); } } logger.info(`Live stores processed: ${liveStores}`); await fs.writeFile('./buildingFile.csv', buildingCsv); logger.info('buildingFile.csv saved.'); await fs.writeFile('./locationFile.csv', locationCsv); logger.info('locationFile.csv saved.'); } main().catch((error) => { logger.error('generate911Csv failed:', error); process.exit(1); });