← back to AbramsOS

scripts/import-apple-health.js

40 lines

#!/usr/bin/env node
// Import an Apple Health export into AbramsOS health_reading.
//
// Get the file:  iPhone → Health app → profile photo → "Export All Health Data"
//   → AirDrop the .zip to this Mac → unzip → apple_health_export/export.xml
//
// Usage:
//   node scripts/import-apple-health.js <path/to/export.xml> [--person <person_id>]
//
// Idempotent: every reading carries a stable external_id, so re-importing a newer
// export only adds what's new (dedup via the unique index).

require('dotenv').config({ path: require('path').join(__dirname, '..', '.env') });
const db = require('../lib/db');
const hm = require('../lib/health-metrics');
const { insertReadings } = require('../routes/vitals');

const USER_ID = process.env.SAVINGS_USER_ID || 'user_steve';

(async () => {
  const file = process.argv[2];
  const pFlag = process.argv.indexOf('--person');
  let personId = pFlag > -1 ? process.argv[pFlag + 1] : null;
  if (!file) { console.error('usage: import-apple-health.js <export.xml> [--person <id>]'); process.exit(2); }

  if (!personId) {
    const self = await db.query(`SELECT id FROM person WHERE user_id=$1 AND relation='self' LIMIT 1`, [USER_ID]);
    personId = self.rows[0] && self.rows[0].id;
  }

  console.log(`Parsing ${file} …`);
  const { readings, counts } = await hm.parseAppleHealthExport(file);
  console.log('Found:', JSON.stringify(counts));
  if (!readings.length) { console.log('No supported readings found.'); process.exit(0); }

  const out = await insertReadings(USER_ID, personId, readings);
  console.log(`Imported: inserted=${out.inserted} skipped(dupe/invalid)=${out.skipped} of ${readings.length}`);
  process.exit(0);
})().catch((e) => { console.error('FAILED:', e.message); process.exit(1); });