@kingstinct/react-native-healthkit 4.3.0 → 4.4.0
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/ios/ReactNativeHealthkit.swift +2 -2
- package/lib/commonjs/index.ios.js +92 -103
- package/lib/commonjs/index.ios.js.map +1 -1
- package/lib/commonjs/index.js +2 -2
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/native-types.js +9 -1
- package/lib/commonjs/native-types.js.map +1 -1
- package/lib/commonjs/types.js.map +1 -1
- package/lib/module/index.ios.js +92 -103
- package/lib/module/index.ios.js.map +1 -1
- package/lib/module/index.js +2 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/native-types.js +4 -0
- package/lib/module/native-types.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/typescript/src/native-types.d.ts +126 -120
- package/lib/typescript/src/types.d.ts +79 -79
- package/package.json +20 -35
- package/src/index.ios.tsx +260 -269
- package/src/index.tsx +13 -13
- package/src/native-types.ts +184 -182
- package/src/types.ts +100 -100
package/src/index.ios.tsx
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { useCallback, useEffect, useState } from 'react'
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react'
|
|
2
|
+
|
|
2
3
|
import Native, {
|
|
3
4
|
EventEmitter,
|
|
5
|
+
HKQuantityTypeIdentifier,
|
|
6
|
+
HKUnit,
|
|
7
|
+
} from './native-types'
|
|
8
|
+
|
|
9
|
+
import type {
|
|
4
10
|
HKCategorySampleRaw,
|
|
5
11
|
HKCategoryTypeIdentifier,
|
|
6
12
|
HKCategoryValueForIdentifier,
|
|
@@ -8,14 +14,14 @@ import Native, {
|
|
|
8
14
|
HKCorrelationRaw,
|
|
9
15
|
HKCorrelationTypeIdentifier,
|
|
10
16
|
HKQuantitySampleRaw,
|
|
11
|
-
HKQuantityTypeIdentifier,
|
|
12
17
|
HKSampleTypeIdentifier,
|
|
13
|
-
HKUnit,
|
|
14
18
|
HKUnitSI,
|
|
15
19
|
HKUnitSIPrefix,
|
|
16
20
|
HKWorkoutRaw,
|
|
17
21
|
MetadataMapperForCategoryIdentifier,
|
|
18
|
-
|
|
22
|
+
ReadPermissions,
|
|
23
|
+
WritePermissions,
|
|
24
|
+
} from './native-types'
|
|
19
25
|
import type {
|
|
20
26
|
GenericQueryOptions,
|
|
21
27
|
GetMostRecentCategorySampleFn,
|
|
@@ -38,76 +44,73 @@ import type {
|
|
|
38
44
|
SaveQuantitySampleFn,
|
|
39
45
|
SaveWorkoutSampleFn,
|
|
40
46
|
SubscribeToChangesFn,
|
|
41
|
-
} from './types'
|
|
47
|
+
} from './types'
|
|
42
48
|
|
|
43
49
|
const getPreferredUnit: GetPreferredUnitFn = async (type) => {
|
|
44
|
-
const [unit] = await getPreferredUnits([type])
|
|
45
|
-
return unit
|
|
46
|
-
}
|
|
50
|
+
const [unit] = await getPreferredUnits([type])
|
|
51
|
+
return unit
|
|
52
|
+
}
|
|
47
53
|
|
|
48
54
|
const ensureUnit = async <TUnit extends HKUnit>(
|
|
49
55
|
type: HKQuantityTypeIdentifier,
|
|
50
|
-
providedUnit?: TUnit
|
|
56
|
+
providedUnit?: TUnit,
|
|
51
57
|
) => {
|
|
52
58
|
if (providedUnit) {
|
|
53
|
-
return providedUnit
|
|
59
|
+
return providedUnit
|
|
54
60
|
}
|
|
55
|
-
const unit = await Native.getPreferredUnits([type])
|
|
56
|
-
return unit[type] as TUnit
|
|
57
|
-
}
|
|
61
|
+
const unit = await Native.getPreferredUnits([type])
|
|
62
|
+
return unit[type] as TUnit
|
|
63
|
+
}
|
|
58
64
|
|
|
59
65
|
function deserializeSample<
|
|
60
66
|
TIdentifier extends HKQuantityTypeIdentifier,
|
|
61
67
|
TUnit extends HKUnit
|
|
62
68
|
>(
|
|
63
|
-
sample: HKQuantitySampleRaw<TIdentifier, TUnit
|
|
69
|
+
sample: HKQuantitySampleRaw<TIdentifier, TUnit>,
|
|
64
70
|
): HKQuantitySample<TIdentifier, TUnit> {
|
|
65
71
|
return {
|
|
66
72
|
...sample,
|
|
67
73
|
startDate: new Date(sample.startDate),
|
|
68
74
|
endDate: new Date(sample.endDate),
|
|
69
|
-
}
|
|
75
|
+
}
|
|
70
76
|
}
|
|
71
77
|
|
|
72
78
|
function deserializeWorkout<TEnergy extends HKUnit, TDistance extends HKUnit>(
|
|
73
|
-
sample: HKWorkoutRaw<TEnergy, TDistance
|
|
79
|
+
sample: HKWorkoutRaw<TEnergy, TDistance>,
|
|
74
80
|
): HKWorkout<TEnergy, TDistance> {
|
|
75
81
|
return {
|
|
76
82
|
...sample,
|
|
77
83
|
startDate: new Date(sample.startDate),
|
|
78
84
|
endDate: new Date(sample.endDate),
|
|
79
|
-
}
|
|
85
|
+
}
|
|
80
86
|
}
|
|
81
87
|
|
|
82
88
|
const deserializCategorySample = <T extends HKCategoryTypeIdentifier>(
|
|
83
|
-
sample: HKCategorySampleRaw<T
|
|
84
|
-
): HKCategorySample<T> => {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
};
|
|
90
|
-
};
|
|
89
|
+
sample: HKCategorySampleRaw<T>,
|
|
90
|
+
): HKCategorySample<T> => ({
|
|
91
|
+
...sample,
|
|
92
|
+
startDate: new Date(sample.startDate),
|
|
93
|
+
endDate: new Date(sample.endDate),
|
|
94
|
+
})
|
|
91
95
|
|
|
92
|
-
const serializeDate = (date?: Date | null): string =>
|
|
93
|
-
return date ? date.toISOString() : new Date(0).toISOString();
|
|
94
|
-
};
|
|
96
|
+
const serializeDate = (date?: Date | null): string => (date ? date.toISOString() : new Date(0).toISOString())
|
|
95
97
|
|
|
96
98
|
const prepareOptions = (options: GenericQueryOptions) => {
|
|
97
|
-
const limit =
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
99
|
+
const limit = !options.limit || options.limit === Infinity ? 0 : options.limit
|
|
100
|
+
const ascending = options.ascending ?? limit === 0
|
|
101
|
+
const from = serializeDate(options.from)
|
|
102
|
+
const to = serializeDate(options.to)
|
|
103
|
+
return {
|
|
104
|
+
limit, ascending, from, to,
|
|
105
|
+
}
|
|
106
|
+
}
|
|
104
107
|
|
|
105
108
|
const queryQuantitySamples: QueryQuantitySamplesFn = async (
|
|
106
109
|
identifier,
|
|
107
|
-
options
|
|
110
|
+
options,
|
|
108
111
|
) => {
|
|
109
|
-
const unit = await ensureUnit(identifier, options.unit)
|
|
110
|
-
const opts = prepareOptions(options)
|
|
112
|
+
const unit = await ensureUnit(identifier, options.unit)
|
|
113
|
+
const opts = prepareOptions(options)
|
|
111
114
|
|
|
112
115
|
const quantitySamples = await Native.queryQuantitySamples(
|
|
113
116
|
identifier,
|
|
@@ -115,121 +118,153 @@ const queryQuantitySamples: QueryQuantitySamplesFn = async (
|
|
|
115
118
|
opts.from,
|
|
116
119
|
opts.to,
|
|
117
120
|
opts.limit,
|
|
118
|
-
opts.ascending
|
|
119
|
-
)
|
|
121
|
+
opts.ascending,
|
|
122
|
+
)
|
|
120
123
|
|
|
121
|
-
return quantitySamples.map(deserializeSample)
|
|
122
|
-
}
|
|
124
|
+
return quantitySamples.map(deserializeSample)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async function getPreferredUnitsTyped<
|
|
128
|
+
TEnergy extends HKUnit,
|
|
129
|
+
TDistance extends HKUnit
|
|
130
|
+
>(options?: { readonly energyUnit?: TEnergy; readonly distanceUnit?: TDistance }) {
|
|
131
|
+
let energyUnit = options?.energyUnit
|
|
132
|
+
let distanceUnit = options?.distanceUnit
|
|
133
|
+
if (!energyUnit || !distanceUnit) {
|
|
134
|
+
const units = await Native.getPreferredUnits([
|
|
135
|
+
HKQuantityTypeIdentifier.distanceWalkingRunning,
|
|
136
|
+
HKQuantityTypeIdentifier.activeEnergyBurned,
|
|
137
|
+
])
|
|
138
|
+
if (!energyUnit) {
|
|
139
|
+
energyUnit = units[HKQuantityTypeIdentifier.distanceWalkingRunning] as
|
|
140
|
+
| TEnergy
|
|
141
|
+
| undefined
|
|
142
|
+
}
|
|
143
|
+
if (!distanceUnit) {
|
|
144
|
+
distanceUnit = units[HKQuantityTypeIdentifier.activeEnergyBurned] as
|
|
145
|
+
| TDistance
|
|
146
|
+
| undefined
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (!energyUnit) {
|
|
150
|
+
energyUnit = HKUnit.Kilocalories as TEnergy
|
|
151
|
+
}
|
|
152
|
+
if (!distanceUnit) {
|
|
153
|
+
distanceUnit = HKUnit.Meters as TDistance
|
|
154
|
+
}
|
|
155
|
+
return { energyUnit, distanceUnit }
|
|
156
|
+
}
|
|
123
157
|
|
|
124
158
|
const subscribeToChanges: SubscribeToChangesFn = async (
|
|
125
159
|
identifier,
|
|
126
|
-
callback
|
|
160
|
+
callback,
|
|
127
161
|
) => {
|
|
128
162
|
const subscription = EventEmitter.addListener(
|
|
129
163
|
'onChange',
|
|
130
164
|
({ typeIdentifier }) => {
|
|
131
165
|
if (typeIdentifier === identifier) {
|
|
132
|
-
callback()
|
|
166
|
+
callback()
|
|
133
167
|
}
|
|
134
|
-
}
|
|
135
|
-
)
|
|
168
|
+
},
|
|
169
|
+
)
|
|
136
170
|
|
|
137
171
|
const queryId = await Native.subscribeToObserverQuery(identifier).catch(
|
|
138
|
-
(error) => {
|
|
139
|
-
subscription.remove()
|
|
140
|
-
return Promise.reject(error)
|
|
141
|
-
}
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
return () => {
|
|
145
|
-
subscription.remove()
|
|
146
|
-
return Native.unsubscribeQuery(queryId)
|
|
147
|
-
}
|
|
148
|
-
}
|
|
172
|
+
async (error) => {
|
|
173
|
+
subscription.remove()
|
|
174
|
+
return Promise.reject(error)
|
|
175
|
+
},
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
return async () => {
|
|
179
|
+
subscription.remove()
|
|
180
|
+
return Native.unsubscribeQuery(queryId)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
149
183
|
|
|
150
184
|
const getMostRecentQuantitySample: GetMostRecentQuantitySampleFn = async (
|
|
151
185
|
identifier,
|
|
152
|
-
unit
|
|
186
|
+
unit,
|
|
153
187
|
) => {
|
|
154
188
|
const samples = await queryQuantitySamples(identifier, {
|
|
155
189
|
limit: 1,
|
|
156
|
-
unit
|
|
157
|
-
})
|
|
158
|
-
return samples[0]
|
|
159
|
-
}
|
|
190
|
+
unit,
|
|
191
|
+
})
|
|
192
|
+
return samples[0]
|
|
193
|
+
}
|
|
160
194
|
|
|
161
195
|
function useMostRecentWorkout<
|
|
162
196
|
TEnergy extends HKUnit,
|
|
163
197
|
TDistance extends HKUnit
|
|
164
|
-
>(options?: { energyUnit?: TEnergy; distanceUnit?: TDistance }) {
|
|
198
|
+
>(options?: { readonly energyUnit?: TEnergy; readonly distanceUnit?: TDistance }) {
|
|
165
199
|
const [workout, setWorkout] = useState<HKWorkout<TEnergy, TDistance> | null>(
|
|
166
|
-
null
|
|
167
|
-
)
|
|
200
|
+
null,
|
|
201
|
+
)
|
|
168
202
|
useEffect(() => {
|
|
169
|
-
let cancelSubscription: (() => Promise<boolean>) | undefined
|
|
203
|
+
let cancelSubscription: (() => Promise<boolean>) | undefined
|
|
170
204
|
|
|
171
205
|
const init = async () => {
|
|
172
206
|
const { energyUnit, distanceUnit } = await getPreferredUnitsTyped(
|
|
173
|
-
options
|
|
174
|
-
)
|
|
207
|
+
options,
|
|
208
|
+
)
|
|
175
209
|
|
|
176
210
|
cancelSubscription = await subscribeToChanges(
|
|
177
211
|
'HKWorkoutTypeIdentifier',
|
|
178
|
-
() => {
|
|
179
|
-
getMostRecentWorkout({ energyUnit, distanceUnit })
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
212
|
+
async () => {
|
|
213
|
+
const w = await getMostRecentWorkout({ energyUnit, distanceUnit })
|
|
214
|
+
setWorkout(w)
|
|
215
|
+
},
|
|
216
|
+
)
|
|
217
|
+
}
|
|
218
|
+
void init()
|
|
184
219
|
return () => {
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
}, [options])
|
|
188
|
-
return workout
|
|
220
|
+
void cancelSubscription?.()
|
|
221
|
+
}
|
|
222
|
+
}, [options])
|
|
223
|
+
return workout
|
|
189
224
|
}
|
|
190
225
|
|
|
191
226
|
const getMostRecentCategorySample: GetMostRecentCategorySampleFn = async (
|
|
192
|
-
identifier
|
|
227
|
+
identifier,
|
|
193
228
|
) => {
|
|
194
229
|
const samples = await queryCategorySamples(identifier, {
|
|
195
230
|
limit: 1,
|
|
196
231
|
ascending: false,
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
return samples[0];
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
function useMostRecentCategorySample<
|
|
203
|
-
TCategory extends HKCategoryTypeIdentifier
|
|
204
|
-
>(identifier: TCategory) {
|
|
205
|
-
const [category, setCategory] = useState<HKCategorySample<TCategory> | null>(
|
|
206
|
-
null
|
|
207
|
-
);
|
|
208
|
-
const updater = useCallback(() => {
|
|
209
|
-
getMostRecentCategorySample(identifier).then(setCategory);
|
|
210
|
-
}, [identifier]);
|
|
232
|
+
})
|
|
211
233
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
return category;
|
|
234
|
+
return samples[0]
|
|
215
235
|
}
|
|
216
236
|
|
|
217
237
|
function useSubscribeToChanges<TIdentifier extends HKSampleTypeIdentifier>(
|
|
218
238
|
identifier: TIdentifier,
|
|
219
|
-
onChange: () => void
|
|
239
|
+
onChange: () => void,
|
|
220
240
|
): void {
|
|
221
241
|
useEffect(() => {
|
|
222
|
-
let cancelSubscription: (() => Promise<boolean>) | undefined
|
|
242
|
+
let cancelSubscription: (() => Promise<boolean>) | undefined
|
|
223
243
|
|
|
224
244
|
const init = async () => {
|
|
225
|
-
cancelSubscription = await subscribeToChanges(identifier, onChange)
|
|
226
|
-
}
|
|
227
|
-
init()
|
|
245
|
+
cancelSubscription = await subscribeToChanges(identifier, onChange)
|
|
246
|
+
}
|
|
247
|
+
void init()
|
|
228
248
|
|
|
229
249
|
return () => {
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
}, [identifier, onChange])
|
|
250
|
+
void cancelSubscription?.()
|
|
251
|
+
}
|
|
252
|
+
}, [identifier, onChange])
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function useMostRecentCategorySample<
|
|
256
|
+
TCategory extends HKCategoryTypeIdentifier
|
|
257
|
+
>(identifier: TCategory) {
|
|
258
|
+
const [category, setCategory] = useState<HKCategorySample<TCategory> | null>(
|
|
259
|
+
null,
|
|
260
|
+
)
|
|
261
|
+
const updater = useCallback(() => {
|
|
262
|
+
void getMostRecentCategorySample(identifier).then(setCategory)
|
|
263
|
+
}, [identifier])
|
|
264
|
+
|
|
265
|
+
useSubscribeToChanges(identifier, updater)
|
|
266
|
+
|
|
267
|
+
return category
|
|
233
268
|
}
|
|
234
269
|
|
|
235
270
|
function useMostRecentQuantitySample<
|
|
@@ -237,41 +272,40 @@ function useMostRecentQuantitySample<
|
|
|
237
272
|
TUnit extends HKUnit = HKUnit
|
|
238
273
|
>(identifier: TIdentifier, unit?: TUnit) {
|
|
239
274
|
const [lastSample, setLastSample] = useState<HKQuantitySample<
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
> | null>(null)
|
|
275
|
+
TIdentifier,
|
|
276
|
+
TUnit
|
|
277
|
+
> | null>(null)
|
|
243
278
|
|
|
244
279
|
useEffect(() => {
|
|
245
|
-
let cancelSubscription: (() => Promise<boolean>) | undefined
|
|
280
|
+
let cancelSubscription: (() => Promise<boolean>) | undefined
|
|
246
281
|
|
|
247
282
|
const init = async () => {
|
|
248
|
-
const actualUnit = await ensureUnit(identifier, unit)
|
|
283
|
+
const actualUnit = await ensureUnit(identifier, unit)
|
|
249
284
|
|
|
250
|
-
cancelSubscription = await subscribeToChanges(identifier, () => {
|
|
251
|
-
getMostRecentQuantitySample(identifier, actualUnit)
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
init();
|
|
285
|
+
cancelSubscription = await subscribeToChanges(identifier, async () => {
|
|
286
|
+
const value = await getMostRecentQuantitySample(identifier, actualUnit)
|
|
287
|
+
setLastSample(value)
|
|
288
|
+
})
|
|
289
|
+
}
|
|
290
|
+
void init()
|
|
257
291
|
|
|
258
292
|
return () => {
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
}, [identifier, unit])
|
|
293
|
+
void cancelSubscription?.()
|
|
294
|
+
}
|
|
295
|
+
}, [identifier, unit])
|
|
262
296
|
|
|
263
|
-
return lastSample
|
|
297
|
+
return lastSample
|
|
264
298
|
}
|
|
265
299
|
|
|
266
|
-
const saveQuantitySample: SaveQuantitySampleFn = (
|
|
300
|
+
const saveQuantitySample: SaveQuantitySampleFn = async (
|
|
267
301
|
identifier,
|
|
268
302
|
unit,
|
|
269
303
|
value,
|
|
270
|
-
options
|
|
304
|
+
options,
|
|
271
305
|
) => {
|
|
272
|
-
const start = options?.start || options?.end || new Date()
|
|
273
|
-
const end = options?.end || options?.start || new Date()
|
|
274
|
-
const metadata = options?.metadata || {}
|
|
306
|
+
const start = options?.start || options?.end || new Date()
|
|
307
|
+
const end = options?.end || options?.start || new Date()
|
|
308
|
+
const metadata = options?.metadata || {}
|
|
275
309
|
|
|
276
310
|
return Native.saveQuantitySample(
|
|
277
311
|
identifier,
|
|
@@ -279,131 +313,91 @@ const saveQuantitySample: SaveQuantitySampleFn = (
|
|
|
279
313
|
value,
|
|
280
314
|
start.toISOString(),
|
|
281
315
|
end.toISOString(),
|
|
282
|
-
metadata
|
|
283
|
-
)
|
|
284
|
-
}
|
|
316
|
+
metadata,
|
|
317
|
+
)
|
|
318
|
+
}
|
|
285
319
|
|
|
286
320
|
const queryStatisticsForQuantity: QueryStatisticsForQuantityFn = async (
|
|
287
321
|
identifier,
|
|
288
322
|
options,
|
|
289
323
|
from,
|
|
290
324
|
to,
|
|
291
|
-
unit
|
|
325
|
+
unit,
|
|
292
326
|
) => {
|
|
293
|
-
const actualUnit = await ensureUnit(identifier, unit)
|
|
294
|
-
const toDate = to || new Date()
|
|
295
|
-
const { mostRecentQuantityDateInterval, ...rawResponse } =
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
);
|
|
327
|
+
const actualUnit = await ensureUnit(identifier, unit)
|
|
328
|
+
const toDate = to || new Date()
|
|
329
|
+
const { mostRecentQuantityDateInterval, ...rawResponse } = await Native.queryStatisticsForQuantity(
|
|
330
|
+
identifier,
|
|
331
|
+
actualUnit,
|
|
332
|
+
from.toISOString(),
|
|
333
|
+
toDate.toISOString(),
|
|
334
|
+
options,
|
|
335
|
+
)
|
|
303
336
|
|
|
304
337
|
const response = {
|
|
305
338
|
...rawResponse,
|
|
306
339
|
...(mostRecentQuantityDateInterval
|
|
307
340
|
? {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
341
|
+
mostRecentQuantityDateInterval: {
|
|
342
|
+
from: new Date(mostRecentQuantityDateInterval.from),
|
|
343
|
+
to: new Date(mostRecentQuantityDateInterval.to),
|
|
344
|
+
},
|
|
345
|
+
}
|
|
313
346
|
: {}),
|
|
314
|
-
}
|
|
347
|
+
}
|
|
315
348
|
|
|
316
|
-
return response
|
|
317
|
-
}
|
|
349
|
+
return response
|
|
350
|
+
}
|
|
318
351
|
|
|
319
|
-
const requestAuthorization = (
|
|
320
|
-
read: (HKCharacteristicTypeIdentifier | HKSampleTypeIdentifier)[],
|
|
321
|
-
write: HKSampleTypeIdentifier[] = []
|
|
352
|
+
const requestAuthorization = async (
|
|
353
|
+
read: readonly (HKCharacteristicTypeIdentifier | HKSampleTypeIdentifier)[],
|
|
354
|
+
write: readonly HKSampleTypeIdentifier[] = [],
|
|
322
355
|
): Promise<boolean> => {
|
|
323
|
-
const readPermissions = read.reduce((obj, cur) => {
|
|
324
|
-
return { ...obj, [cur]: true };
|
|
325
|
-
}, {});
|
|
356
|
+
const readPermissions = read.reduce((obj, cur) => ({ ...obj, [cur]: true }), {} as ReadPermissions)
|
|
326
357
|
|
|
327
|
-
const writePermissions = write.reduce((obj, cur) => {
|
|
328
|
-
return { ...obj, [cur]: true };
|
|
329
|
-
}, {});
|
|
358
|
+
const writePermissions = write.reduce((obj, cur) => ({ ...obj, [cur]: true }), {} as WritePermissions)
|
|
330
359
|
|
|
331
|
-
return Native.requestAuthorization(writePermissions, readPermissions)
|
|
332
|
-
}
|
|
360
|
+
return Native.requestAuthorization(writePermissions, readPermissions)
|
|
361
|
+
}
|
|
333
362
|
|
|
334
363
|
const getDateOfBirth = async () => {
|
|
335
|
-
const dateOfBirth = await Native.getDateOfBirth()
|
|
336
|
-
return new Date(dateOfBirth)
|
|
337
|
-
}
|
|
364
|
+
const dateOfBirth = await Native.getDateOfBirth()
|
|
365
|
+
return new Date(dateOfBirth)
|
|
366
|
+
}
|
|
338
367
|
|
|
339
|
-
const getRequestStatusForAuthorization = (
|
|
340
|
-
read: (HKCharacteristicTypeIdentifier | HKSampleTypeIdentifier)[],
|
|
341
|
-
write: HKSampleTypeIdentifier[] = []
|
|
368
|
+
const getRequestStatusForAuthorization = async (
|
|
369
|
+
read: readonly (HKCharacteristicTypeIdentifier | HKSampleTypeIdentifier)[],
|
|
370
|
+
write: readonly HKSampleTypeIdentifier[] = [],
|
|
342
371
|
) => {
|
|
343
|
-
const readPermissions = read.reduce((obj, cur) => {
|
|
344
|
-
return { ...obj, [cur]: true };
|
|
345
|
-
}, {});
|
|
372
|
+
const readPermissions = read.reduce((obj, cur) => ({ ...obj, [cur]: true }), {} as ReadPermissions)
|
|
346
373
|
|
|
347
|
-
const writePermissions = write.reduce((obj, cur) => {
|
|
348
|
-
return { ...obj, [cur]: true };
|
|
349
|
-
}, {});
|
|
374
|
+
const writePermissions = write.reduce((obj, cur) => ({ ...obj, [cur]: true }), {} as WritePermissions)
|
|
350
375
|
|
|
351
376
|
return Native.getRequestStatusForAuthorization(
|
|
352
377
|
writePermissions,
|
|
353
|
-
readPermissions
|
|
354
|
-
)
|
|
355
|
-
}
|
|
378
|
+
readPermissions,
|
|
379
|
+
)
|
|
380
|
+
}
|
|
356
381
|
|
|
357
382
|
const queryCategorySamples: QueryCategorySamplesFn = async (
|
|
358
383
|
identifier,
|
|
359
|
-
options
|
|
384
|
+
options,
|
|
360
385
|
) => {
|
|
361
|
-
const opts = prepareOptions(options)
|
|
386
|
+
const opts = prepareOptions(options)
|
|
362
387
|
const results = await Native.queryCategorySamples(
|
|
363
388
|
identifier,
|
|
364
389
|
opts.from,
|
|
365
390
|
opts.to,
|
|
366
391
|
opts.limit,
|
|
367
|
-
opts.ascending
|
|
368
|
-
)
|
|
392
|
+
opts.ascending,
|
|
393
|
+
)
|
|
369
394
|
|
|
370
|
-
return results.map(deserializCategorySample)
|
|
371
|
-
};
|
|
372
|
-
|
|
373
|
-
async function getPreferredUnitsTyped<
|
|
374
|
-
TEnergy extends HKUnit,
|
|
375
|
-
TDistance extends HKUnit
|
|
376
|
-
>(options?: { energyUnit?: TEnergy; distanceUnit?: TDistance }) {
|
|
377
|
-
let energyUnit = options?.energyUnit;
|
|
378
|
-
let distanceUnit = options?.distanceUnit;
|
|
379
|
-
if (!energyUnit || !distanceUnit) {
|
|
380
|
-
const units = await Native.getPreferredUnits([
|
|
381
|
-
HKQuantityTypeIdentifier.distanceWalkingRunning,
|
|
382
|
-
HKQuantityTypeIdentifier.activeEnergyBurned,
|
|
383
|
-
]);
|
|
384
|
-
if (!energyUnit) {
|
|
385
|
-
energyUnit = units[HKQuantityTypeIdentifier.distanceWalkingRunning] as
|
|
386
|
-
| TEnergy
|
|
387
|
-
| undefined;
|
|
388
|
-
}
|
|
389
|
-
if (!distanceUnit) {
|
|
390
|
-
distanceUnit = units[HKQuantityTypeIdentifier.activeEnergyBurned] as
|
|
391
|
-
| TDistance
|
|
392
|
-
| undefined;
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
if (!energyUnit) {
|
|
396
|
-
energyUnit = HKUnit.Kilocalories as TEnergy;
|
|
397
|
-
}
|
|
398
|
-
if (!distanceUnit) {
|
|
399
|
-
distanceUnit = HKUnit.Meters as TDistance;
|
|
400
|
-
}
|
|
401
|
-
return { energyUnit, distanceUnit };
|
|
395
|
+
return results.map(deserializCategorySample)
|
|
402
396
|
}
|
|
403
397
|
|
|
404
398
|
const queryWorkouts: QueryWorkoutsFn = async (options) => {
|
|
405
|
-
const { energyUnit, distanceUnit } = await getPreferredUnitsTyped(options)
|
|
406
|
-
const opts = prepareOptions(options)
|
|
399
|
+
const { energyUnit, distanceUnit } = await getPreferredUnitsTyped(options)
|
|
400
|
+
const opts = prepareOptions(options)
|
|
407
401
|
|
|
408
402
|
const workouts = await Native.queryWorkoutSamples(
|
|
409
403
|
energyUnit,
|
|
@@ -411,11 +405,11 @@ const queryWorkouts: QueryWorkoutsFn = async (options) => {
|
|
|
411
405
|
opts.from,
|
|
412
406
|
opts.to,
|
|
413
407
|
opts.limit,
|
|
414
|
-
opts.ascending
|
|
415
|
-
)
|
|
408
|
+
opts.ascending,
|
|
409
|
+
)
|
|
416
410
|
|
|
417
|
-
return workouts.map(deserializeWorkout)
|
|
418
|
-
}
|
|
411
|
+
return workouts.map(deserializeWorkout)
|
|
412
|
+
}
|
|
419
413
|
|
|
420
414
|
const getMostRecentWorkout: GetMostRecentWorkoutFn = async (options) => {
|
|
421
415
|
const workouts = await queryWorkouts({
|
|
@@ -423,41 +417,39 @@ const getMostRecentWorkout: GetMostRecentWorkoutFn = async (options) => {
|
|
|
423
417
|
ascending: false,
|
|
424
418
|
energyUnit: options?.energyUnit,
|
|
425
419
|
distanceUnit: options?.distanceUnit,
|
|
426
|
-
})
|
|
420
|
+
})
|
|
427
421
|
|
|
428
|
-
return workouts[0]
|
|
429
|
-
}
|
|
422
|
+
return workouts[0]
|
|
423
|
+
}
|
|
430
424
|
|
|
431
|
-
function saveCategorySample<T extends HKCategoryTypeIdentifier>(
|
|
425
|
+
async function saveCategorySample<T extends HKCategoryTypeIdentifier>(
|
|
432
426
|
identifier: T,
|
|
433
427
|
value: HKCategoryValueForIdentifier<T>,
|
|
434
428
|
options?: {
|
|
435
|
-
start?: Date;
|
|
436
|
-
end?: Date;
|
|
437
|
-
metadata?: MetadataMapperForCategoryIdentifier<T>;
|
|
438
|
-
}
|
|
429
|
+
readonly start?: Date;
|
|
430
|
+
readonly end?: Date;
|
|
431
|
+
readonly metadata?: MetadataMapperForCategoryIdentifier<T>;
|
|
432
|
+
},
|
|
439
433
|
) {
|
|
440
|
-
const start = options?.start || options?.end || new Date()
|
|
441
|
-
const end = options?.end || options?.start || new Date()
|
|
442
|
-
const metadata = options?.metadata || {}
|
|
434
|
+
const start = options?.start || options?.end || new Date()
|
|
435
|
+
const end = options?.end || options?.start || new Date()
|
|
436
|
+
const metadata = options?.metadata || {}
|
|
443
437
|
|
|
444
438
|
return Native.saveCategorySample(
|
|
445
439
|
identifier,
|
|
446
440
|
value,
|
|
447
441
|
start.toISOString(),
|
|
448
442
|
end.toISOString(),
|
|
449
|
-
metadata || {}
|
|
450
|
-
)
|
|
443
|
+
metadata || {},
|
|
444
|
+
)
|
|
451
445
|
}
|
|
452
446
|
|
|
453
447
|
const getPreferredUnits: GetPreferredUnitsFn = async (identifiers) => {
|
|
454
|
-
const units = await Native.getPreferredUnits(identifiers)
|
|
455
|
-
return identifiers.map((i) => units[i])
|
|
456
|
-
}
|
|
448
|
+
const units = await Native.getPreferredUnits(identifiers)
|
|
449
|
+
return identifiers.map((i) => units[i])
|
|
450
|
+
}
|
|
457
451
|
|
|
458
|
-
const buildUnitWithPrefix = (prefix: HKUnitSIPrefix, unit: HKUnitSI) => {
|
|
459
|
-
return `${prefix}${unit}` as HKUnit;
|
|
460
|
-
};
|
|
452
|
+
const buildUnitWithPrefix = (prefix: HKUnitSIPrefix, unit: HKUnitSI) => `${prefix}${unit}` as HKUnit
|
|
461
453
|
|
|
462
454
|
function deserializeCorrelation<
|
|
463
455
|
TIdentifier extends HKCorrelationTypeIdentifier
|
|
@@ -465,79 +457,78 @@ function deserializeCorrelation<
|
|
|
465
457
|
return {
|
|
466
458
|
...s,
|
|
467
459
|
objects: s.objects.map((o) => {
|
|
460
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
468
461
|
// @ts-ignore
|
|
469
462
|
if (o.quantity !== undefined) {
|
|
470
|
-
return deserializeSample(o as HKQuantitySampleRaw)
|
|
463
|
+
return deserializeSample(o as HKQuantitySampleRaw)
|
|
471
464
|
}
|
|
472
465
|
|
|
473
|
-
return deserializCategorySample(o as HKCategorySampleRaw)
|
|
466
|
+
return deserializCategorySample(o as HKCategorySampleRaw)
|
|
474
467
|
}),
|
|
475
468
|
endDate: new Date(s.endDate),
|
|
476
469
|
startDate: new Date(s.startDate),
|
|
477
|
-
}
|
|
470
|
+
}
|
|
478
471
|
}
|
|
479
472
|
|
|
480
473
|
function ensureMetadata<TMetadata>(metadata?: TMetadata) {
|
|
481
|
-
return metadata || ({} as TMetadata)
|
|
474
|
+
return metadata || ({} as TMetadata)
|
|
482
475
|
}
|
|
483
476
|
|
|
484
477
|
const queryCorrelationSamples: QueryCorrelationSamplesFn = async (
|
|
485
478
|
typeIdentifier,
|
|
486
|
-
options
|
|
479
|
+
options,
|
|
487
480
|
) => {
|
|
488
|
-
const opts = prepareOptions(options)
|
|
481
|
+
const opts = prepareOptions(options)
|
|
489
482
|
const correlations = await Native.queryCorrelationSamples(
|
|
490
483
|
typeIdentifier,
|
|
491
484
|
opts.from,
|
|
492
|
-
opts.to
|
|
493
|
-
)
|
|
485
|
+
opts.to,
|
|
486
|
+
)
|
|
494
487
|
|
|
495
|
-
return correlations.map(deserializeCorrelation)
|
|
496
|
-
}
|
|
488
|
+
return correlations.map(deserializeCorrelation)
|
|
489
|
+
}
|
|
497
490
|
|
|
498
491
|
const saveCorrelationSample: SaveCorrelationSampleFn = async (
|
|
499
492
|
typeIdentifier,
|
|
500
493
|
samples,
|
|
501
|
-
options
|
|
494
|
+
options,
|
|
502
495
|
) => {
|
|
503
|
-
const start = (options?.start || new Date()).toISOString()
|
|
504
|
-
const end = (options?.end || new Date()).toISOString()
|
|
496
|
+
const start = (options?.start || new Date()).toISOString()
|
|
497
|
+
const end = (options?.end || new Date()).toISOString()
|
|
505
498
|
|
|
506
499
|
return Native.saveCorrelationSample(
|
|
507
500
|
typeIdentifier,
|
|
508
501
|
samples,
|
|
509
502
|
start,
|
|
510
503
|
end,
|
|
511
|
-
ensureMetadata(options?.metadata)
|
|
512
|
-
)
|
|
513
|
-
}
|
|
504
|
+
ensureMetadata(options?.metadata),
|
|
505
|
+
)
|
|
506
|
+
}
|
|
514
507
|
|
|
515
|
-
const saveWorkoutSample: SaveWorkoutSampleFn = (
|
|
508
|
+
const saveWorkoutSample: SaveWorkoutSampleFn = async (
|
|
516
509
|
typeIdentifier,
|
|
517
510
|
quantities,
|
|
518
511
|
_start,
|
|
519
|
-
options
|
|
512
|
+
options,
|
|
520
513
|
) => {
|
|
521
|
-
const start = _start.toISOString()
|
|
522
|
-
const end = (options?.end || new Date()).toISOString()
|
|
514
|
+
const start = _start.toISOString()
|
|
515
|
+
const end = (options?.end || new Date()).toISOString()
|
|
523
516
|
|
|
524
517
|
return Native.saveWorkoutSample(
|
|
525
518
|
typeIdentifier,
|
|
526
519
|
quantities,
|
|
527
520
|
start,
|
|
528
521
|
end,
|
|
529
|
-
ensureMetadata(options?.metadata)
|
|
530
|
-
)
|
|
531
|
-
}
|
|
522
|
+
ensureMetadata(options?.metadata),
|
|
523
|
+
)
|
|
524
|
+
}
|
|
532
525
|
|
|
533
|
-
const getWorkoutRoutes: GetWorkoutRoutesFn = (workoutUUID: string) =>
|
|
534
|
-
return Native.getWorkoutRoutes(workoutUUID);
|
|
535
|
-
};
|
|
526
|
+
const getWorkoutRoutes: GetWorkoutRoutesFn = async (workoutUUID: string) => Native.getWorkoutRoutes(workoutUUID)
|
|
536
527
|
|
|
537
528
|
const Healthkit: ReactNativeHealthkit = {
|
|
538
|
-
authorizationStatusFor: Native.authorizationStatusFor,
|
|
529
|
+
authorizationStatusFor: Native.authorizationStatusFor.bind(Native),
|
|
539
530
|
|
|
540
|
-
isHealthDataAvailable: Native.isHealthDataAvailable,
|
|
531
|
+
isHealthDataAvailable: Native.isHealthDataAvailable.bind(Native),
|
|
541
532
|
|
|
542
533
|
buildUnitWithPrefix,
|
|
543
534
|
|
|
@@ -546,10 +537,10 @@ const Healthkit: ReactNativeHealthkit = {
|
|
|
546
537
|
enableBackgroundDelivery: Native.enableBackgroundDelivery,
|
|
547
538
|
|
|
548
539
|
// simple convenience getters
|
|
549
|
-
getBiologicalSex: Native.getBiologicalSex,
|
|
550
|
-
getFitzpatrickSkinType: Native.getFitzpatrickSkinType,
|
|
540
|
+
getBiologicalSex: Native.getBiologicalSex.bind(Native),
|
|
541
|
+
getFitzpatrickSkinType: Native.getFitzpatrickSkinType.bind(Native),
|
|
551
542
|
getWheelchairUse: Native.getWheelchairUse,
|
|
552
|
-
getBloodType: Native.getBloodType,
|
|
543
|
+
getBloodType: Native.getBloodType.bind(Native),
|
|
553
544
|
getDateOfBirth,
|
|
554
545
|
|
|
555
546
|
getMostRecentQuantitySample,
|
|
@@ -587,9 +578,9 @@ const Healthkit: ReactNativeHealthkit = {
|
|
|
587
578
|
useMostRecentWorkout,
|
|
588
579
|
|
|
589
580
|
useSubscribeToChanges,
|
|
590
|
-
}
|
|
581
|
+
}
|
|
591
582
|
|
|
592
|
-
export * from './native-types'
|
|
593
|
-
export * from './types'
|
|
583
|
+
export * from './native-types'
|
|
584
|
+
export * from './types'
|
|
594
585
|
|
|
595
|
-
export default Healthkit
|
|
586
|
+
export default Healthkit
|