@healthcloudai/hc-import-vitals
v0.0.2
Published
React Native vitals importer for HealthKit and Health Connect with background sync, offline queue, and retry logic.
Downloads
15
Maintainers
Readme
HC Import Vitals
Reusable React Native module for importing vitals from:
- iOS HealthKit
- Android Health Connect
Includes:
- background sync
- incremental sync by
lastSyncDate - offline queue
- retry logic with exponential backoff
- REST API upload
CSV Source of Truth
assets/vitals-by-platform.csv is the source of truth.
Catalog code is auto-generated into:
src/generated/vitalCatalog.generated.ts
Do not edit generated files manually. Update CSV and run:
npm run gen:vitalsHelpers exported from src/vitalCatalog.ts (backed by generated catalog):
VITALS_CATALOGIOS_RECORD_TYPES_BY_VITALANDROID_RECORD_TYPES_BY_VITALgetDefaultVitalsForPlatform(platform)getSupportedVitalsForPlatform(platform)normalizeVitalType()normalizeVitals()
Do not manually edit src/generated/vitalCatalog.generated.ts.
Install
npm install @healthcloudai/hc-import-vitals \
@react-native-async-storage/async-storage \
@react-native-community/netinfo \
react-native-background-fetch \
react-native-health \
react-native-health-connectiOS Setup
- Enable
HealthKitcapability in Xcode. - Add usage descriptions in
Info.plist:
<key>NSHealthShareUsageDescription</key>
<string>This app reads your vitals to sync with your care team.</string>
<key>NSHealthUpdateUsageDescription</key>
<string>This app can write health records when needed.</string>- Run pods:
cd ios && pod installAndroid Setup
- Complete
react-native-health-connectsetup. - Add required health permissions in
AndroidManifest.xmlfor the vitals you need. - Ensure Health Connect is installed on the device.
Android Headless Setup
Background sync on Android needs headless task registration in the consumer app:
// index.js or index.ts in consumer app
import { registerHCVitalsHeadlessTask } from "@healthcloudai/hc-import-vitals";
import { importer } from "./src/health/importer";
registerHCVitalsHeadlessTask(() => importer);Without this setup, background sync can run only while app process is alive. The importer instance should be shared (single instance used by App and headless bootstrap).
Quick Start
import { Platform } from "react-native";
import {
HCVitalsImporter,
getDefaultVitalsForPlatform
} from "@healthcloudai/hc-import-vitals";
const importer = new HCVitalsImporter({
apiBaseUrl: "https://api.your-domain.com",
apiPath: "/v1/vitals/import",
patientId: "patient-123",
getAuthToken: async () => "your-jwt-token",
vitals: getDefaultVitalsForPlatform(Platform.OS),
syncIntervalMinutes: 30,
batchSize: 50,
maxRetryAttempts: 5
});
await importer.initialize({
requestPermissions: true,
startBackgroundSync: true
});
const result = await importer.syncNow({ reason: "manual" });
console.log("Sync result:", result);React Component Usage
import React from "react";
import { HCVitalsAutoSync, HCVitalsImporter } from "@healthcloudai/hc-import-vitals";
const importer = new HCVitalsImporter({
apiBaseUrl: "https://api.your-domain.com",
getAuthToken: async () => "your-jwt-token",
syncIntervalMinutes: 30
});
export default function App() {
return (
<>
<HCVitalsAutoSync
importer={importer}
onSyncSuccess={(result) => console.log("Vitals synced", result)}
onSyncError={(error) => console.error("Vitals sync failed", error)}
/>
{/* Rest of your app */}
</>
);
}API Payload
{
"patientId": "patient-123",
"source": "hc-import-vitals",
"reason": "manual",
"fromDate": "2026-02-24T10:00:00.000Z",
"toDate": "2026-02-25T10:00:00.000Z",
"sentAt": "2026-02-25T10:00:01.000Z",
"vitals": [
{
"id": "a1b2c3",
"type": "heart_rate",
"value": 68,
"unit": "bpm",
"recordedAt": "2026-02-25T09:48:23.000Z",
"source": "healthkit"
}
]
}Key Methods
initialize(options)syncNow({ reason })flushQueue()getStatus()clearState()
Retry and Queue Behavior
- Failed uploads are persisted in offline queue (
AsyncStorage). - Queue size is capped (
maxQueueItems, default200), oldest items are dropped first. - Queue retries use exponential backoff.
- Non-retryable API errors (most
4xxexcept429) are dropped. - Sync cycle order:
- flush queue
- pull incremental data
- send or queue new batches
- flush queue again
Android HRV Note
heart_rate_variability_sdnn on Android is currently mapped from RMSSD when available.
Metadata includes method: "rmssd" to make this explicit.
Example App File
See example/App.tsx. Headless bootstrap example: example/index.ts.
