@robinhealth/health-sdk 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +189 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/provider.d.ts +3 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +13 -0
- package/dist/provider.js.map +1 -0
- package/dist/providers/healthconnect.d.ts +16 -0
- package/dist/providers/healthconnect.d.ts.map +1 -0
- package/dist/providers/healthconnect.js +601 -0
- package/dist/providers/healthconnect.js.map +1 -0
- package/dist/providers/healthkit.d.ts +15 -0
- package/dist/providers/healthkit.d.ts.map +1 -0
- package/dist/providers/healthkit.js +392 -0
- package/dist/providers/healthkit.js.map +1 -0
- package/dist/storage.d.ts +3 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +71 -0
- package/dist/storage.js.map +1 -0
- package/dist/types.d.ts +171 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +122 -0
- package/dist/types.js.map +1 -0
- package/package.json +70 -0
- package/src/index.ts +15 -0
- package/src/provider.ts +18 -0
- package/src/providers/healthconnect.ts +725 -0
- package/src/providers/healthkit.ts +499 -0
- package/src/storage.ts +85 -0
- package/src/types.ts +189 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Robin Health
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# @robin/health-sdk
|
|
2
|
+
|
|
3
|
+
Unified health data SDK for React Native — HealthKit (iOS) and Health Connect (Android).
|
|
4
|
+
|
|
5
|
+
One API, both platforms. Query steps, heart rate, sleep, workouts, body composition, and more without writing platform-specific code.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **19 health data types** — activity, vitals, sleep, body composition, hydration
|
|
10
|
+
- **79 workout types** — from running and cycling to pickleball and underwater diving
|
|
11
|
+
- **Sleep sessions** — full stage breakdowns (awake, light, deep, REM)
|
|
12
|
+
- **Aggregations** — sum, average, min, max over any date range
|
|
13
|
+
- **Permission management** — persistent state tracking via expo-sqlite
|
|
14
|
+
- **Type-safe** — full TypeScript definitions
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @robin/health-sdk
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Then install the platform-specific peer dependencies you need:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# iOS
|
|
26
|
+
npm install @kingstinct/react-native-healthkit
|
|
27
|
+
|
|
28
|
+
# Android
|
|
29
|
+
npm install react-native-health-connect
|
|
30
|
+
|
|
31
|
+
# Permission persistence (recommended)
|
|
32
|
+
npm install expo-sqlite
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Platform Setup
|
|
36
|
+
|
|
37
|
+
### iOS (Expo)
|
|
38
|
+
|
|
39
|
+
Add the HealthKit plugin to your `app.json`:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"expo": {
|
|
44
|
+
"plugins": [
|
|
45
|
+
[
|
|
46
|
+
"@kingstinct/react-native-healthkit",
|
|
47
|
+
{
|
|
48
|
+
"NSHealthShareUsageDescription": "This app needs access to your health data."
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### iOS (Bare React Native)
|
|
57
|
+
|
|
58
|
+
1. Enable the **HealthKit** capability in Xcode
|
|
59
|
+
2. Add `NSHealthShareUsageDescription` to `Info.plist`
|
|
60
|
+
3. Run `pod install`
|
|
61
|
+
|
|
62
|
+
### Android (Expo)
|
|
63
|
+
|
|
64
|
+
Add the Health Connect plugin to your `app.json`:
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"expo": {
|
|
69
|
+
"plugins": [
|
|
70
|
+
[
|
|
71
|
+
"expo-health-connect",
|
|
72
|
+
{
|
|
73
|
+
"permissions": [
|
|
74
|
+
"android.permission.health.READ_STEPS",
|
|
75
|
+
"android.permission.health.READ_HEART_RATE"
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Requires `minSdkVersion` 28+.
|
|
85
|
+
|
|
86
|
+
### Android (Bare React Native)
|
|
87
|
+
|
|
88
|
+
1. Set `minSdkVersion` 28+ in `build.gradle`
|
|
89
|
+
2. Declare health permissions in `AndroidManifest.xml`
|
|
90
|
+
3. Add the `ViewPermissionUsageActivity` alias for the permissions rationale screen
|
|
91
|
+
|
|
92
|
+
See [docs/INTEGRATION.md](docs/INTEGRATION.md) for full setup instructions.
|
|
93
|
+
|
|
94
|
+
## Quick Start
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import {
|
|
98
|
+
createHealthProvider,
|
|
99
|
+
HealthDataType,
|
|
100
|
+
} from 'robin-health-sdk';
|
|
101
|
+
|
|
102
|
+
const provider = createHealthProvider();
|
|
103
|
+
|
|
104
|
+
// Check availability
|
|
105
|
+
const available = await provider.isAvailable();
|
|
106
|
+
|
|
107
|
+
// Request permissions
|
|
108
|
+
await provider.requestAuthorization([
|
|
109
|
+
HealthDataType.Steps,
|
|
110
|
+
HealthDataType.HeartRate,
|
|
111
|
+
HealthDataType.SleepAnalysis,
|
|
112
|
+
]);
|
|
113
|
+
|
|
114
|
+
// Query samples
|
|
115
|
+
const now = new Date();
|
|
116
|
+
const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
|
117
|
+
|
|
118
|
+
const heartRateSamples = await provider.querySamples(
|
|
119
|
+
HealthDataType.HeartRate,
|
|
120
|
+
yesterday,
|
|
121
|
+
now,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// Get aggregated stats
|
|
125
|
+
const stepTotal = await provider.queryAggregated(
|
|
126
|
+
HealthDataType.Steps,
|
|
127
|
+
yesterday,
|
|
128
|
+
now,
|
|
129
|
+
);
|
|
130
|
+
console.log(`Steps: ${stepTotal.sum}`);
|
|
131
|
+
|
|
132
|
+
// Query workouts
|
|
133
|
+
const workouts = await provider.queryWorkouts(yesterday, now);
|
|
134
|
+
|
|
135
|
+
// Query sleep sessions with stage breakdowns
|
|
136
|
+
const sleep = await provider.querySleepSessions(yesterday, now);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Supported Data Types
|
|
140
|
+
|
|
141
|
+
| Category | Type | Unit |
|
|
142
|
+
|----------|------|------|
|
|
143
|
+
| **Activity** | Steps | count |
|
|
144
|
+
| | DistanceWalkingRunning | meters |
|
|
145
|
+
| | ActiveEnergyBurned | kcal |
|
|
146
|
+
| | FlightsClimbed | count |
|
|
147
|
+
| **Vitals** | HeartRate | bpm |
|
|
148
|
+
| | RestingHeartRate | bpm |
|
|
149
|
+
| | BloodPressureSystolic | mmHg |
|
|
150
|
+
| | BloodPressureDiastolic | mmHg |
|
|
151
|
+
| | BloodOxygen | % |
|
|
152
|
+
| | RespiratoryRate | breaths/min |
|
|
153
|
+
| **Sleep** | SleepAnalysis | hours |
|
|
154
|
+
| **Body** | BodyFatPercentage | % |
|
|
155
|
+
| | BodyMassIndex | kg/m² |
|
|
156
|
+
| | BasalEnergyBurned | kcal |
|
|
157
|
+
| **Hydration** | Water | mL |
|
|
158
|
+
|
|
159
|
+
## API
|
|
160
|
+
|
|
161
|
+
### `createHealthProvider(): HealthProvider`
|
|
162
|
+
|
|
163
|
+
Returns a platform-specific health provider (HealthKit on iOS, Health Connect on Android).
|
|
164
|
+
|
|
165
|
+
### `HealthProvider`
|
|
166
|
+
|
|
167
|
+
| Method | Description |
|
|
168
|
+
|--------|-------------|
|
|
169
|
+
| `isAvailable()` | Check if health data is available on this device |
|
|
170
|
+
| `shouldRequestAuthorization(types)` | Check if permissions need to be requested |
|
|
171
|
+
| `requestAuthorization(types)` | Request read access for the given data types |
|
|
172
|
+
| `getPermissionStatus()` | Get current permission status |
|
|
173
|
+
| `querySamples(type, start, end)` | Get individual readings in a date range |
|
|
174
|
+
| `queryAggregated(type, start, end)` | Get aggregated stats (sum, avg, min, max) |
|
|
175
|
+
| `queryWorkouts(start, end)` | Get workout sessions with metadata |
|
|
176
|
+
| `querySleepSessions(start, end)` | Get sleep sessions with stage breakdowns |
|
|
177
|
+
|
|
178
|
+
See [docs/API.md](docs/API.md) for the full API reference with type definitions and platform notes.
|
|
179
|
+
|
|
180
|
+
## Requirements
|
|
181
|
+
|
|
182
|
+
- Node >= 16
|
|
183
|
+
- React >= 18.0.0
|
|
184
|
+
- React Native >= 0.72.0
|
|
185
|
+
- iOS 13+ / Android SDK 28+
|
|
186
|
+
|
|
187
|
+
## License
|
|
188
|
+
|
|
189
|
+
MIT — see [LICENSE](LICENSE) for details.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { createHealthProvider } from './provider';
|
|
2
|
+
export type { HealthProvider, HealthSample, HealthAggregate, Workout, SleepStageSample, SleepSession, } from './types';
|
|
3
|
+
export { HealthDataType, WorkoutActivityType, PermissionStatus, SleepStage, } from './types';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,YAAY,EACV,cAAc,EACd,YAAY,EACZ,eAAe,EACf,OAAO,EACP,gBAAgB,EAChB,YAAY,GACb,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,GACX,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AASlD,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,UAAU,GACX,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,wBAAgB,oBAAoB,IAAI,cAAc,CAcrD"}
|
package/dist/provider.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
export function createHealthProvider() {
|
|
3
|
+
if (Platform.OS === 'ios') {
|
|
4
|
+
const { HealthKitProvider } = require('./providers/healthkit');
|
|
5
|
+
return new HealthKitProvider();
|
|
6
|
+
}
|
|
7
|
+
if (Platform.OS === 'android') {
|
|
8
|
+
const { HealthConnectProvider } = require('./providers/healthconnect');
|
|
9
|
+
return new HealthConnectProvider();
|
|
10
|
+
}
|
|
11
|
+
throw new Error(`Health data is not supported on ${Platform.OS}. Supported platforms: ios, android.`);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGxC,MAAM,UAAU,oBAAoB;IAClC,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;QAC1B,MAAM,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;QAC/D,OAAO,IAAI,iBAAiB,EAAE,CAAC;IACjC,CAAC;IAED,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,EAAE,qBAAqB,EAAE,GAAG,OAAO,CAAC,2BAA2B,CAAC,CAAC;QACvE,OAAO,IAAI,qBAAqB,EAAE,CAAC;IACrC,CAAC;IAED,MAAM,IAAI,KAAK,CACb,mCAAmC,QAAQ,CAAC,EAAE,sCAAsC,CACrF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { HealthDataType, PermissionStatus, type HealthProvider, type HealthSample, type HealthAggregate, type Workout, type SleepSession } from '../types';
|
|
2
|
+
export declare class HealthConnectProvider implements HealthProvider {
|
|
3
|
+
private initPromise;
|
|
4
|
+
private ensureInitialized;
|
|
5
|
+
isAvailable(): Promise<boolean>;
|
|
6
|
+
shouldRequestAuthorization(dataTypes: HealthDataType[]): Promise<boolean>;
|
|
7
|
+
requestAuthorization(dataTypes: HealthDataType[]): Promise<boolean>;
|
|
8
|
+
getPermissionStatus(): Promise<PermissionStatus>;
|
|
9
|
+
querySamples(type: HealthDataType, startDate: Date, endDate: Date): Promise<HealthSample[]>;
|
|
10
|
+
queryAggregated(type: HealthDataType, startDate: Date, endDate: Date): Promise<HealthAggregate>;
|
|
11
|
+
querySleepSessions(startDate: Date, endDate: Date): Promise<SleepSession[]>;
|
|
12
|
+
queryWorkouts(startDate: Date, endDate: Date): Promise<Workout[]>;
|
|
13
|
+
private deriveBMISamples;
|
|
14
|
+
private manualAggregate;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=healthconnect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"healthconnect.d.ts","sourceRoot":"","sources":["../../src/providers/healthconnect.ts"],"names":[],"mappings":"AAmBA,OAAO,EACL,cAAc,EAEd,gBAAgB,EAEhB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,OAAO,EAEZ,KAAK,YAAY,EAClB,MAAM,UAAU,CAAC;AAqJlB,qBAAa,qBAAsB,YAAW,cAAc;IAC1D,OAAO,CAAC,WAAW,CAAiC;YAEtC,iBAAiB;IAUzB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAU/B,0BAA0B,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAmCzE,oBAAoB,CAAC,SAAS,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAoCnE,mBAAmB,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAahD,YAAY,CAChB,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,IAAI,EACf,OAAO,EAAE,IAAI,GACZ,OAAO,CAAC,YAAY,EAAE,CAAC;IA2KpB,eAAe,CACnB,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,IAAI,EACf,OAAO,EAAE,IAAI,GACZ,OAAO,CAAC,eAAe,CAAC;IAwDrB,kBAAkB,CACtB,SAAS,EAAE,IAAI,EACf,OAAO,EAAE,IAAI,GACZ,OAAO,CAAC,YAAY,EAAE,CAAC;IAkEpB,aAAa,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;YAkEzD,gBAAgB;YA0ChB,eAAe;CA0B9B"}
|