/** * Helix Engage โ€” Ramaiah Hospital Data Seeder * * Seeds clinic + 195 doctors from scraped website data. * Run: cd helix-engage && SEED_GQL=https://ramaiah.app.healix360.net/graphql SEED_SUB=ramaiah SEED_ORIGIN=https://ramaiah.app.healix360.net npx tsx scripts/seed-ramaiah.ts */ import { readFileSync } from 'fs'; const GQL = process.env.SEED_GQL ?? 'http://localhost:4000/graphql'; const SUB = process.env.SEED_SUB ?? 'ramaiah'; const ORIGIN = process.env.SEED_ORIGIN ?? 'http://ramaiah.localhost:5080'; const DATA_FILE = process.env.SEED_DATA ?? '/tmp/ramaiah-seed-data.json'; let token = ''; async function gql(query: string, variables?: any) { const h: Record = { 'Content-Type': 'application/json', 'X-Workspace-Subdomain': SUB }; if (token) h['Authorization'] = `Bearer ${token}`; const r = await fetch(GQL, { method: 'POST', headers: h, body: JSON.stringify({ query, variables }) }); const d: any = await r.json(); if (d.errors) { console.error('โŒ', d.errors[0].message); throw new Error(d.errors[0].message); } return d.data; } async function auth() { const d1 = await gql(`mutation { getLoginTokenFromCredentials(email: "dev@fortytwo.dev", password: "tim@apple.dev", origin: "${ORIGIN}") { loginToken { token } } }`); const lt = d1.getLoginTokenFromCredentials.loginToken.token; const d2 = await gql(`mutation { getAuthTokensFromLoginToken(loginToken: "${lt}", origin: "${ORIGIN}") { tokens { accessOrWorkspaceAgnosticToken { token } } } }`); token = d2.getAuthTokensFromLoginToken.tokens.accessOrWorkspaceAgnosticToken.token; } async function mk(entity: string, data: any): Promise { const cap = entity[0].toUpperCase() + entity.slice(1); const d = await gql(`mutation($data: ${cap}CreateInput!) { create${cap}(data: $data) { id } }`, { data }); return d[`create${cap}`].id; } async function main() { console.log('๐ŸŒฑ Seeding Ramaiah Hospital data...\n'); const raw = JSON.parse(readFileSync(DATA_FILE, 'utf-8')); console.log(`๐Ÿ“ Loaded ${raw.doctors.length} doctors, ${raw.departments.length} departments\n`); await auth(); console.log('โœ… Auth OK\n'); // Clinic console.log('๐Ÿฅ Clinic'); const clinicId = await mk('clinic', { name: raw.clinic.name, clinicName: raw.clinic.name, status: 'ACTIVE', opensAt: '08:00', closesAt: '20:00', openMonday: true, openTuesday: true, openWednesday: true, openThursday: true, openFriday: true, openSaturday: true, openSunday: false, phone: { primaryPhoneNumber: raw.clinic.phone?.replace(/[^0-9]/g, '').slice(-10) ?? '', primaryPhoneCallingCode: '+91', primaryPhoneCountryCode: 'IN', }, addressCustom: { addressStreet1: raw.clinic.address?.split(',')[0] ?? 'New BEL Road', addressCity: raw.clinic.city ?? 'Bangalore', addressState: raw.clinic.state ?? 'Karnataka', addressCountry: 'India', addressPostcode: raw.clinic.pincode ?? '560054', }, onlineBooking: true, walkInAllowed: true, }); console.log(` ${raw.clinic.name}: ${clinicId}\n`); // Re-auth (long operation ahead) await auth(); // Doctors โ€” batch in groups of 20 with re-auth console.log(`๐Ÿ‘จโ€โš•๏ธ Doctors (${raw.doctors.length})`); let created = 0; let failed = 0; for (let i = 0; i < raw.doctors.length; i++) { // Re-auth every 40 doctors (token may expire on long runs) if (i > 0 && i % 40 === 0) { await auth(); console.log(` (re-authed at ${i})`); } const doc = raw.doctors[i]; const firstName = doc.name.replace(/^Dr\.?\s*/i, '').split(' ')[0] ?? ''; const lastNameParts = doc.name.replace(/^Dr\.?\s*/i, '').split(' ').slice(1); const lastName = lastNameParts.join(' '); try { await mk('doctor', { name: doc.name, fullName: { firstName, lastName }, department: doc.department ?? 'Other', specialty: doc.designation ?? 'Consultant', qualifications: doc.qualifications ?? '', registrationNumber: '', active: true, }); created++; if (created % 20 === 0) console.log(` ${created}/${raw.doctors.length} created...`); } catch (err: any) { failed++; console.error(` โœ— ${doc.name}: ${err.message?.slice(0, 80)}`); } } console.log(`\n โœ… ${created} doctors created, ${failed} failed\n`); console.log('๐ŸŽ‰ Ramaiah seed complete!'); console.log(` 1 clinic ยท ${created} doctors ยท ${raw.departments.length} departments`); } main().catch(e => { console.error('๐Ÿ’ฅ', e.message); process.exit(1); });