← 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); });