@kingstinct/react-native-healthkit 4.4.0 → 4.4.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/src/index.ios.tsx CHANGED
@@ -4,23 +4,25 @@ import Native, {
4
4
  EventEmitter,
5
5
  HKQuantityTypeIdentifier,
6
6
  HKUnit,
7
+ HKCategoryTypeIdentifier,
7
8
  } from './native-types'
8
9
 
9
10
  import type {
11
+ HKSampleTypeIdentifier,
10
12
  HKCategorySampleRaw,
11
- HKCategoryTypeIdentifier,
12
13
  HKCategoryValueForIdentifier,
13
14
  HKCharacteristicTypeIdentifier,
14
15
  HKCorrelationRaw,
15
16
  HKCorrelationTypeIdentifier,
16
17
  HKQuantitySampleRaw,
17
- HKSampleTypeIdentifier,
18
18
  HKUnitSI,
19
19
  HKUnitSIPrefix,
20
20
  HKWorkoutRaw,
21
21
  MetadataMapperForCategoryIdentifier,
22
22
  ReadPermissions,
23
23
  WritePermissions,
24
+ HealthkitAuthorization,
25
+ HKAuthorizationRequestStatus,
24
26
  } from './native-types'
25
27
  import type {
26
28
  GenericQueryOptions,
@@ -45,6 +47,7 @@ import type {
45
47
  SaveWorkoutSampleFn,
46
48
  SubscribeToChangesFn,
47
49
  } from './types'
50
+ import type { ValueOf } from 'type-fest'
48
51
 
49
52
  const getPreferredUnit: GetPreferredUnitFn = async (type) => {
50
53
  const [unit] = await getPreferredUnits([type])
@@ -234,7 +237,7 @@ const getMostRecentCategorySample: GetMostRecentCategorySampleFn = async (
234
237
  return samples[0]
235
238
  }
236
239
 
237
- function useSubscribeToChanges<TIdentifier extends HKSampleTypeIdentifier>(
240
+ function useSubscribeToChanges<TIdentifier extends ValueOf<typeof HKSampleTypeIdentifier>>(
238
241
  identifier: TIdentifier,
239
242
  onChange: () => void,
240
243
  ): void {
@@ -252,6 +255,8 @@ function useSubscribeToChanges<TIdentifier extends HKSampleTypeIdentifier>(
252
255
  }, [identifier, onChange])
253
256
  }
254
257
 
258
+ useSubscribeToChanges(HKCategoryTypeIdentifier.appleStandHour, () => {})
259
+
255
260
  function useMostRecentCategorySample<
256
261
  TCategory extends HKCategoryTypeIdentifier
257
262
  >(identifier: TCategory) {
@@ -350,8 +355,8 @@ const queryStatisticsForQuantity: QueryStatisticsForQuantityFn = async (
350
355
  }
351
356
 
352
357
  const requestAuthorization = async (
353
- read: readonly (HKCharacteristicTypeIdentifier | HKSampleTypeIdentifier)[],
354
- write: readonly HKSampleTypeIdentifier[] = [],
358
+ read: readonly ValueOf<typeof HealthkitAuthorization>[],
359
+ write: readonly ValueOf<typeof HKSampleTypeIdentifier>[] = [],
355
360
  ): Promise<boolean> => {
356
361
  const readPermissions = read.reduce((obj, cur) => ({ ...obj, [cur]: true }), {} as ReadPermissions)
357
362
 
@@ -366,8 +371,8 @@ const getDateOfBirth = async () => {
366
371
  }
367
372
 
368
373
  const getRequestStatusForAuthorization = async (
369
- read: readonly (HKCharacteristicTypeIdentifier | HKSampleTypeIdentifier)[],
370
- write: readonly HKSampleTypeIdentifier[] = [],
374
+ read: readonly (HKCharacteristicTypeIdentifier | ValueOf<typeof HKSampleTypeIdentifier>)[],
375
+ write: readonly (ValueOf<typeof HKSampleTypeIdentifier>)[] = [],
371
376
  ) => {
372
377
  const readPermissions = read.reduce((obj, cur) => ({ ...obj, [cur]: true }), {} as ReadPermissions)
373
378
 
@@ -578,6 +583,37 @@ const Healthkit: ReactNativeHealthkit = {
578
583
  useMostRecentWorkout,
579
584
 
580
585
  useSubscribeToChanges,
586
+
587
+ useIsHealthDataAvailable: () => {
588
+ const [isAvailable, setIsAvailable] = useState<boolean | null>(null)
589
+ useEffect(() => {
590
+ const init = async () => {
591
+ const res = await Native.isHealthDataAvailable()
592
+ setIsAvailable(res)
593
+ }
594
+ void init()
595
+ }, [])
596
+ return isAvailable
597
+ },
598
+ useHealthkitAuthorization: (read, write) => {
599
+ const [status, setStatus] = useState<HKAuthorizationRequestStatus | null>(null)
600
+ const refreshAuthStatus = useCallback(async () => {
601
+ const auth = await getRequestStatusForAuthorization(read, write)
602
+ setStatus(auth)
603
+ return auth
604
+ }, [])
605
+
606
+ const request = useCallback(async () => {
607
+ await requestAuthorization(read, write)
608
+ return refreshAuthStatus()
609
+ }, [])
610
+
611
+ useEffect(() => {
612
+ void refreshAuthStatus()
613
+ }, [])
614
+
615
+ return [status, request]
616
+ },
581
617
  }
582
618
 
583
619
  export * from './native-types'
package/src/index.tsx CHANGED
@@ -1,49 +1,66 @@
1
1
  import { Platform } from 'react-native'
2
2
 
3
+ import {
4
+ HKAuthorizationRequestStatus, HKBiologicalSex, HKBloodType, HKFitzpatrickSkinType, HKUnit, HKWheelchairUse,
5
+ } from './native-types'
6
+
3
7
  import type { ReactNativeHealthkit } from './types'
4
8
 
5
- const notAvailableError = `Platform "${
9
+ const notAvailableError = `[@kingstinct/react-native-healthkit] Platform "${
6
10
  Platform.OS
7
- }" not supported, use isHealthDataAvailable to check for availability before using it`
11
+ }" not supported`
8
12
 
9
- const UnavailableFn = () => {
10
- throw new Error(notAvailableError)
13
+ function UnavailableFn<T = unknown>(retVal: T) {
14
+ return () => {
15
+ console.warn(notAvailableError)
16
+ return retVal
17
+ }
11
18
  }
12
19
 
13
20
  const Healthkit: ReactNativeHealthkit = {
14
- authorizationStatusFor: UnavailableFn,
15
- buildUnitWithPrefix: UnavailableFn,
16
- disableAllBackgroundDelivery: UnavailableFn,
17
- disableBackgroundDelivery: UnavailableFn,
18
- enableBackgroundDelivery: UnavailableFn,
19
- getBiologicalSex: UnavailableFn,
20
- getBloodType: UnavailableFn,
21
- getDateOfBirth: UnavailableFn,
22
- getFitzpatrickSkinType: UnavailableFn,
23
- getMostRecentCategorySample: UnavailableFn,
24
- getMostRecentQuantitySample: UnavailableFn,
25
- getMostRecentWorkout: UnavailableFn,
26
- getPreferredUnit: UnavailableFn,
27
- getPreferredUnits: UnavailableFn,
28
- getRequestStatusForAuthorization: UnavailableFn,
29
- getWheelchairUse: UnavailableFn,
30
- getWorkoutRoutes: UnavailableFn,
21
+ authorizationStatusFor: UnavailableFn(Promise.resolve(false)),
22
+ buildUnitWithPrefix: UnavailableFn(HKUnit.Atmospheres),
23
+ disableAllBackgroundDelivery: UnavailableFn(Promise.resolve(false)),
24
+ disableBackgroundDelivery: UnavailableFn(Promise.resolve(false)),
25
+ enableBackgroundDelivery: UnavailableFn(Promise.resolve(false)),
26
+ getBiologicalSex: UnavailableFn(Promise.resolve(HKBiologicalSex.notSet)),
27
+ getBloodType: UnavailableFn(Promise.resolve(HKBloodType.notSet)),
28
+ getDateOfBirth: UnavailableFn(Promise.resolve(new Date(0))),
29
+ getFitzpatrickSkinType: UnavailableFn(Promise.resolve(HKFitzpatrickSkinType.notSet)),
30
+ getMostRecentCategorySample: UnavailableFn(Promise.resolve(null)),
31
+ getMostRecentQuantitySample: UnavailableFn(Promise.resolve(null)),
32
+ getMostRecentWorkout: UnavailableFn(Promise.resolve(null)),
33
+ getPreferredUnit: UnavailableFn(Promise.resolve(HKUnit.Atmospheres)),
34
+ getPreferredUnits: UnavailableFn(Promise.resolve([])),
35
+ getRequestStatusForAuthorization: UnavailableFn(Promise.resolve(HKAuthorizationRequestStatus.unknown)),
36
+ getWheelchairUse: UnavailableFn(Promise.resolve(HKWheelchairUse.notSet)),
37
+ getWorkoutRoutes: UnavailableFn(Promise.resolve([])),
31
38
  isHealthDataAvailable: async () => Promise.resolve(false),
32
- queryCategorySamples: UnavailableFn,
33
- queryCorrelationSamples: UnavailableFn,
34
- queryQuantitySamples: UnavailableFn,
35
- queryStatisticsForQuantity: UnavailableFn,
36
- queryWorkouts: UnavailableFn,
37
- requestAuthorization: UnavailableFn,
38
- saveCategorySample: UnavailableFn,
39
- saveCorrelationSample: UnavailableFn,
40
- saveQuantitySample: UnavailableFn,
41
- saveWorkoutSample: UnavailableFn,
42
- subscribeToChanges: UnavailableFn,
43
- useMostRecentCategorySample: UnavailableFn,
44
- useMostRecentQuantitySample: UnavailableFn,
45
- useMostRecentWorkout: UnavailableFn,
46
- useSubscribeToChanges: UnavailableFn,
39
+ queryCategorySamples: UnavailableFn(Promise.resolve([])),
40
+ queryCorrelationSamples: UnavailableFn(Promise.resolve([])),
41
+ queryQuantitySamples: UnavailableFn(Promise.resolve([])),
42
+ queryStatisticsForQuantity: UnavailableFn(Promise.resolve({
43
+ averageQuantity: undefined,
44
+ maximumQuantity: undefined,
45
+ minimumQuantity: undefined,
46
+ sumQuantity: undefined,
47
+ mostRecentQuantity: undefined,
48
+ mostRecentQuantityDateInterval: undefined,
49
+ duration: undefined,
50
+ })),
51
+ queryWorkouts: UnavailableFn(Promise.resolve([])),
52
+ requestAuthorization: UnavailableFn(Promise.resolve(false)),
53
+ saveCategorySample: UnavailableFn(Promise.resolve(false)),
54
+ saveCorrelationSample: UnavailableFn(Promise.resolve(false)),
55
+ saveQuantitySample: UnavailableFn(Promise.resolve(false)),
56
+ saveWorkoutSample: UnavailableFn(Promise.resolve(false)),
57
+ subscribeToChanges: UnavailableFn(Promise.resolve(async () => Promise.resolve(false))),
58
+ useMostRecentCategorySample: UnavailableFn(null),
59
+ useMostRecentQuantitySample: UnavailableFn(null),
60
+ useMostRecentWorkout: UnavailableFn(null),
61
+ useSubscribeToChanges: UnavailableFn([null, () => null]),
62
+ useHealthkitAuthorization: UnavailableFn([null, async () => Promise.resolve(null)] as const),
63
+ useIsHealthDataAvailable: UnavailableFn(false),
47
64
  }
48
65
 
49
66
  export * from './native-types'
@@ -4,20 +4,121 @@ import {
4
4
  } from 'react-native'
5
5
 
6
6
  import type { EmitterSubscription } from 'react-native'
7
+ import type { ValueOf } from 'type-fest'
7
8
 
8
- export const HKWorkoutTypeIdentifier = 'HKWorkoutTypeIdentifier'
9
- export const HKAudiogramTypeIdentifier = 'HKAudiogramTypeIdentifier'
10
- export const HKWorkoutRouteTypeIdentifier = 'HKWorkoutRouteTypeIdentifier'
11
- export const HKDataTypeIdentifierHeartbeatSeries = 'HKDataTypeIdentifierHeartbeatSeries'
9
+ export const HKWorkoutTypeIdentifier = 'HKWorkoutTypeIdentifier' as const
10
+ export const HKAudiogramTypeIdentifier = 'HKAudiogramTypeIdentifier' as const
11
+ export const HKWorkoutRouteTypeIdentifier = 'HKWorkoutRouteTypeIdentifier' as const
12
+ export const HKDataTypeIdentifierHeartbeatSeries = 'HKDataTypeIdentifierHeartbeatSeries' as const
12
13
 
13
- export type HKSampleTypeIdentifier =
14
- | HKCategoryTypeIdentifier
15
- | HKCorrelationTypeIdentifier
16
- | HKQuantityTypeIdentifier
17
- | typeof HKAudiogramTypeIdentifier
18
- | typeof HKDataTypeIdentifierHeartbeatSeries
19
- | typeof HKWorkoutRouteTypeIdentifier
20
- | typeof HKWorkoutTypeIdentifier;
14
+ // Straight mapping to https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier
15
+ export enum HKQuantityTypeIdentifier {
16
+ bodyMassIndex = 'HKQuantityTypeIdentifierBodyMassIndex',
17
+ bodyFatPercentage = 'HKQuantityTypeIdentifierBodyFatPercentage', // Scalar(Percent, 0.0 - 1.0), Discrete
18
+ height = 'HKQuantityTypeIdentifierHeight', // Length, Discrete
19
+ bodyMass = 'HKQuantityTypeIdentifierBodyMass', // Mass, Discrete
20
+ leanBodyMass = 'HKQuantityTypeIdentifierLeanBodyMass', // Mass, Discrete
21
+
22
+ waistCircumference = 'HKQuantityTypeIdentifierWaistCircumference', // Length, Discrete
23
+ // Fitness
24
+ stepCount = 'HKQuantityTypeIdentifierStepCount', // Scalar(Count), Cumulative
25
+ distanceWalkingRunning = 'HKQuantityTypeIdentifierDistanceWalkingRunning', // Length, Cumulative
26
+ distanceCycling = 'HKQuantityTypeIdentifierDistanceCycling', // Length, Cumulative
27
+ distanceWheelchair = 'HKQuantityTypeIdentifierDistanceWheelchair', // Length, Cumulative
28
+ basalEnergyBurned = 'HKQuantityTypeIdentifierBasalEnergyBurned', // Energy, Cumulative
29
+ activeEnergyBurned = 'HKQuantityTypeIdentifierActiveEnergyBurned', // Energy, Cumulative
30
+ flightsClimbed = 'HKQuantityTypeIdentifierFlightsClimbed', // Scalar(Count), Cumulative
31
+ nikeFuel = 'HKQuantityTypeIdentifierNikeFuel', // Scalar(Count), Cumulative
32
+ appleExerciseTime = 'HKQuantityTypeIdentifierAppleExerciseTime', // Time Cumulative
33
+ pushCount = 'HKQuantityTypeIdentifierPushCount', // Scalar(Count), Cumulative
34
+ distanceSwimming = 'HKQuantityTypeIdentifierDistanceSwimming', // Length, Cumulative
35
+ swimmingStrokeCount = 'HKQuantityTypeIdentifierSwimmingStrokeCount', // Scalar(Count), Cumulative
36
+ vo2Max = 'HKQuantityTypeIdentifierVo2Max', // ml/(kg*min) Discrete
37
+ distanceDownhillSnowSports = 'HKQuantityTypeIdentifierDistanceDownhillSnowSports', // Length, Cumulative
38
+
39
+ appleStandTime = 'HKQuantityTypeIdentifierAppleStandTime', // Time, Cumulative
40
+ // Vitals
41
+ heartRate = 'HKQuantityTypeIdentifierHeartRate', // Scalar(Count)/Time, Discrete
42
+ bodyTemperature = 'HKQuantityTypeIdentifierBodyTemperature', // Temperature, Discrete
43
+ basalBodyTemperature = 'HKQuantityTypeIdentifierBasalBodyTemperature', // Basal Body Temperature, Discrete
44
+ bloodPressureSystolic = 'HKQuantityTypeIdentifierBloodPressureSystolic', // Pressure, Discrete
45
+ bloodPressureDiastolic = 'HKQuantityTypeIdentifierBloodPressureDiastolic', // Pressure, Discrete
46
+ respiratoryRate = 'HKQuantityTypeIdentifierRespiratoryRate', // Scalar(Count)/Time, Discrete
47
+ // Beats per minute estimate of a user's lowest heart rate while at rest
48
+ restingHeartRate = 'HKQuantityTypeIdentifierRestingHeartRate', // Scalar(Count)/Time, Discrete
49
+ // Average heartbeats per minute captured by an Apple Watch while a user is walking
50
+ walkingHeartRateAverage = 'HKQuantityTypeIdentifierWalkingHeartRateAverage', // Scalar(Count)/Time, Discrete
51
+ // The standard deviation of heart beat-to-beat intevals (Standard Deviation of Normal to Normal)
52
+
53
+ heartRateVariabilitySDNN = 'HKQuantityTypeIdentifierHeartRateVariabilitySDNN', // Time (ms), Discrete
54
+ // Results
55
+ oxygenSaturation = 'HKQuantityTypeIdentifierOxygenSaturation', // Scalar (Percent, 0.0 - 1.0, Discrete
56
+ peripheralPerfusionIndex = 'HKQuantityTypeIdentifierPeripheralPerfusionIndex', // Scalar(Percent, 0.0 - 1.0), Discrete
57
+ bloodGlucose = 'HKQuantityTypeIdentifierBloodGlucose', // Mass/Volume, Discrete
58
+ numberOfTimesFallen = 'HKQuantityTypeIdentifierNumberOfTimesFallen', // Scalar(Count), Cumulative
59
+ electrodermalActivity = 'HKQuantityTypeIdentifierElectrodermalActivity', // Conductance, Discrete
60
+ inhalerUsage = 'HKQuantityTypeIdentifierInhalerUsage', // Scalar(Count), Cumulative
61
+ insulinDelivery = 'HKQuantityTypeIdentifierInsulinDelivery', // Pharmacology (IU) Cumulative
62
+ bloodAlcoholContent = 'HKQuantityTypeIdentifierBloodAlcoholContent', // Scalar(Percent, 0.0 - 1.0), Discrete
63
+ forcedVitalCapacity = 'HKQuantityTypeIdentifierForcedVitalCapacity', // Volume, Discrete
64
+ forcedExpiratoryVolume1 = 'HKQuantityTypeIdentifierForcedExpiratoryVolume1', // Volume, Discrete
65
+ peakExpiratoryFlowRate = 'HKQuantityTypeIdentifierPeakExpiratoryFlowRate', // Volume/Time, Discrete
66
+ environmentalAudioExposure = 'HKQuantityTypeIdentifierEnvironmentalAudioExposure', // Pressure, Cumulative
67
+
68
+ headphoneAudioExposure = 'HKQuantityTypeIdentifierHeadphoneAudioExposure', // Pressure, Cumulative
69
+ // Nutrition
70
+ dietaryFatTotal = 'HKQuantityTypeIdentifierDietaryFatTotal', // Mass, Cumulative
71
+ dietaryFatPolyunsaturated = 'HKQuantityTypeIdentifierDietaryFatPolyunsaturated', // Mass, Cumulative
72
+ dietaryFatMonounsaturated = 'HKQuantityTypeIdentifierDietaryFatMonounsaturated', // Mass, Cumulative
73
+ dietaryFatSaturated = 'HKQuantityTypeIdentifierDietaryFatSaturated', // Mass, Cumulative
74
+ dietaryCholesterol = 'HKQuantityTypeIdentifierDietaryCholesterol', // Mass, Cumulative
75
+ dietarySodium = 'HKQuantityTypeIdentifierDietarySodium', // Mass, Cumulative
76
+ dietaryCarbohydrates = 'HKQuantityTypeIdentifierDietaryCarbohydrates', // Mass, Cumulative
77
+ dietaryFiber = 'HKQuantityTypeIdentifierDietaryFiber', // Mass, Cumulative
78
+ dietarySugar = 'HKQuantityTypeIdentifierDietarySugar', // Mass, Cumulative
79
+ dietaryEnergyConsumed = 'HKQuantityTypeIdentifierDietaryEnergyConsumed', // Energy, Cumulative
80
+ dietaryProtein = 'HKQuantityTypeIdentifierDietaryProtein', // Mass, Cumulative
81
+
82
+ dietaryVitaminA = 'HKQuantityTypeIdentifierDietaryVitaminA', // Mass, Cumulative
83
+ dietaryVitaminB6 = 'HKQuantityTypeIdentifierDietaryVitaminB6', // Mass, Cumulative
84
+ dietaryVitaminB12 = 'HKQuantityTypeIdentifierDietaryVitaminB12', // Mass, Cumulative
85
+ dietaryVitaminC = 'HKQuantityTypeIdentifierDietaryVitaminC', // Mass, Cumulative
86
+ dietaryVitaminD = 'HKQuantityTypeIdentifierDietaryVitaminD', // Mass, Cumulative
87
+ dietaryVitaminE = 'HKQuantityTypeIdentifierDietaryVitaminE', // Mass, Cumulative
88
+ dietaryVitaminK = 'HKQuantityTypeIdentifierDietaryVitaminK', // Mass, Cumulative
89
+ dietaryCalcium = 'HKQuantityTypeIdentifierDietaryCalcium', // Mass, Cumulative
90
+ dietaryIron = 'HKQuantityTypeIdentifierDietaryIron', // Mass, Cumulative
91
+ dietaryThiamin = 'HKQuantityTypeIdentifierDietaryThiamin', // Mass, Cumulative
92
+ dietaryRiboflavin = 'HKQuantityTypeIdentifierDietaryRiboflavin', // Mass, Cumulative
93
+ dietaryNiacin = 'HKQuantityTypeIdentifierDietaryNiacin', // Mass, Cumulative
94
+ dietaryFolate = 'HKQuantityTypeIdentifierDietaryFolate', // Mass, Cumulative
95
+ dietaryBiotin = 'HKQuantityTypeIdentifierDietaryBiotin', // Mass, Cumulative
96
+ dietaryPantothenicAcid = 'HKQuantityTypeIdentifierDietaryPantothenicAcid', // Mass, Cumulative
97
+ dietaryPhosphorus = 'HKQuantityTypeIdentifierDietaryPhosphorus', // Mass, Cumulative
98
+ dietaryIodine = 'HKQuantityTypeIdentifierDietaryIodine', // Mass, Cumulative
99
+ dietaryMagnesium = 'HKQuantityTypeIdentifierDietaryMagnesium', // Mass, Cumulative
100
+ dietaryZinc = 'HKQuantityTypeIdentifierDietaryZinc', // Mass, Cumulative
101
+ dietarySelenium = 'HKQuantityTypeIdentifierDietarySelenium', // Mass, Cumulative
102
+ dietaryCopper = 'HKQuantityTypeIdentifierDietaryCopper', // Mass, Cumulative
103
+ dietaryManganese = 'HKQuantityTypeIdentifierDietaryManganese', // Mass, Cumulative
104
+ dietaryChromium = 'HKQuantityTypeIdentifierDietaryChromium', // Mass, Cumulative
105
+ dietaryMolybdenum = 'HKQuantityTypeIdentifierDietaryMolybdenum', // Mass, Cumulative
106
+ dietaryChloride = 'HKQuantityTypeIdentifierDietaryChloride', // Mass, Cumulative
107
+ dietaryPotassium = 'HKQuantityTypeIdentifierDietaryPotassium', // Mass, Cumulative
108
+ dietaryCaffeine = 'HKQuantityTypeIdentifierDietaryCaffeine', // Mass, Cumulative
109
+ dietaryWater = 'HKQuantityTypeIdentifierDietaryWater', // Volume, Cumulative
110
+
111
+ // Mobility
112
+ sixMinuteWalkTestDistance = 'HKQuantityTypeIdentifierSixMinuteWalkTestDistance',
113
+ walkingSpeed = 'HKQuantityTypeIdentifierWalkingSpeed',
114
+ walkingStepLength = 'HKQuantityTypeIdentifierWalkingStepLength',
115
+ walkingAsymmetryPercentage = 'HKQuantityTypeIdentifierWalkingAsymmetryPercentage',
116
+ walkingDoubleSupportPercentage = 'HKQuantityTypeIdentifierWalkingDoubleSupportPercentage',
117
+ stairAscentSpeed = 'HKQuantityTypeIdentifierStairAscentSpeed',
118
+ stairDescentSpeed = 'HKQuantityTypeIdentifierStairDescentSpeed',
119
+
120
+ uvExposure = 'HKQuantityTypeIdentifierUvExposure', // Scalar (Count), Discrete
121
+ }
21
122
 
22
123
  export type TypeToUnitMapping = { readonly
23
124
  [key in HKQuantityTypeIdentifier]: HKUnit;
@@ -29,6 +130,11 @@ export enum HKHeartRateMotionContext {
29
130
  sedentary = 1,
30
131
  }
31
132
 
133
+ export enum HKCorrelationTypeIdentifier {
134
+ bloodPressure = 'HKCorrelationTypeIdentifierBloodPressure',
135
+ food = 'HKCorrelationTypeIdentifierFood',
136
+ }
137
+
32
138
  export enum HKCategoryTypeIdentifier {
33
139
  sleepAnalysis = 'HKCategoryTypeIdentifierSleepAnalysis',
34
140
  appleStandHour = 'HKCategoryTypeIdentifierAppleStandHour',
@@ -45,6 +151,16 @@ export enum HKCategoryTypeIdentifier {
45
151
  toothbrushingEvent = 'HKCategoryTypeIdentifierToothbrushingEvent',
46
152
  }
47
153
 
154
+ export const HKSampleTypeIdentifier = {
155
+ ...HKCategoryTypeIdentifier,
156
+ ...HKCorrelationTypeIdentifier,
157
+ ...HKQuantityTypeIdentifier,
158
+ audiogram: HKAudiogramTypeIdentifier,
159
+ heartbeatSeries: HKDataTypeIdentifierHeartbeatSeries,
160
+ workoutRoute: HKWorkoutRouteTypeIdentifier,
161
+ workoute: HKWorkoutTypeIdentifier,
162
+ }
163
+
48
164
  export enum HKCategoryValueAppleStandHour {
49
165
  stood = 0,
50
166
  idle = 1,
@@ -187,115 +303,6 @@ export interface HKWorkoutMetadata
187
303
  // HKWeatherTemperature: HKQuantity<TTemperatureUnit>
188
304
  }
189
305
 
190
- // Straight mapping to https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier
191
- export enum HKQuantityTypeIdentifier {
192
- bodyMassIndex = 'HKQuantityTypeIdentifierBodyMassIndex',
193
- bodyFatPercentage = 'HKQuantityTypeIdentifierBodyFatPercentage', // Scalar(Percent, 0.0 - 1.0), Discrete
194
- height = 'HKQuantityTypeIdentifierHeight', // Length, Discrete
195
- bodyMass = 'HKQuantityTypeIdentifierBodyMass', // Mass, Discrete
196
- leanBodyMass = 'HKQuantityTypeIdentifierLeanBodyMass', // Mass, Discrete
197
-
198
- waistCircumference = 'HKQuantityTypeIdentifierWaistCircumference', // Length, Discrete
199
- // Fitness
200
- stepCount = 'HKQuantityTypeIdentifierStepCount', // Scalar(Count), Cumulative
201
- distanceWalkingRunning = 'HKQuantityTypeIdentifierDistanceWalkingRunning', // Length, Cumulative
202
- distanceCycling = 'HKQuantityTypeIdentifierDistanceCycling', // Length, Cumulative
203
- distanceWheelchair = 'HKQuantityTypeIdentifierDistanceWheelchair', // Length, Cumulative
204
- basalEnergyBurned = 'HKQuantityTypeIdentifierBasalEnergyBurned', // Energy, Cumulative
205
- activeEnergyBurned = 'HKQuantityTypeIdentifierActiveEnergyBurned', // Energy, Cumulative
206
- flightsClimbed = 'HKQuantityTypeIdentifierFlightsClimbed', // Scalar(Count), Cumulative
207
- nikeFuel = 'HKQuantityTypeIdentifierNikeFuel', // Scalar(Count), Cumulative
208
- appleExerciseTime = 'HKQuantityTypeIdentifierAppleExerciseTime', // Time Cumulative
209
- pushCount = 'HKQuantityTypeIdentifierPushCount', // Scalar(Count), Cumulative
210
- distanceSwimming = 'HKQuantityTypeIdentifierDistanceSwimming', // Length, Cumulative
211
- swimmingStrokeCount = 'HKQuantityTypeIdentifierSwimmingStrokeCount', // Scalar(Count), Cumulative
212
- vo2Max = 'HKQuantityTypeIdentifierVo2Max', // ml/(kg*min) Discrete
213
- distanceDownhillSnowSports = 'HKQuantityTypeIdentifierDistanceDownhillSnowSports', // Length, Cumulative
214
-
215
- appleStandTime = 'HKQuantityTypeIdentifierAppleStandTime', // Time, Cumulative
216
- // Vitals
217
- heartRate = 'HKQuantityTypeIdentifierHeartRate', // Scalar(Count)/Time, Discrete
218
- bodyTemperature = 'HKQuantityTypeIdentifierBodyTemperature', // Temperature, Discrete
219
- basalBodyTemperature = 'HKQuantityTypeIdentifierBasalBodyTemperature', // Basal Body Temperature, Discrete
220
- bloodPressureSystolic = 'HKQuantityTypeIdentifierBloodPressureSystolic', // Pressure, Discrete
221
- bloodPressureDiastolic = 'HKQuantityTypeIdentifierBloodPressureDiastolic', // Pressure, Discrete
222
- respiratoryRate = 'HKQuantityTypeIdentifierRespiratoryRate', // Scalar(Count)/Time, Discrete
223
- // Beats per minute estimate of a user's lowest heart rate while at rest
224
- restingHeartRate = 'HKQuantityTypeIdentifierRestingHeartRate', // Scalar(Count)/Time, Discrete
225
- // Average heartbeats per minute captured by an Apple Watch while a user is walking
226
- walkingHeartRateAverage = 'HKQuantityTypeIdentifierWalkingHeartRateAverage', // Scalar(Count)/Time, Discrete
227
- // The standard deviation of heart beat-to-beat intevals (Standard Deviation of Normal to Normal)
228
-
229
- heartRateVariabilitySDNN = 'HKQuantityTypeIdentifierHeartRateVariabilitySDNN', // Time (ms), Discrete
230
- // Results
231
- oxygenSaturation = 'HKQuantityTypeIdentifierOxygenSaturation', // Scalar (Percent, 0.0 - 1.0, Discrete
232
- peripheralPerfusionIndex = 'HKQuantityTypeIdentifierPeripheralPerfusionIndex', // Scalar(Percent, 0.0 - 1.0), Discrete
233
- bloodGlucose = 'HKQuantityTypeIdentifierBloodGlucose', // Mass/Volume, Discrete
234
- numberOfTimesFallen = 'HKQuantityTypeIdentifierNumberOfTimesFallen', // Scalar(Count), Cumulative
235
- electrodermalActivity = 'HKQuantityTypeIdentifierElectrodermalActivity', // Conductance, Discrete
236
- inhalerUsage = 'HKQuantityTypeIdentifierInhalerUsage', // Scalar(Count), Cumulative
237
- insulinDelivery = 'HKQuantityTypeIdentifierInsulinDelivery', // Pharmacology (IU) Cumulative
238
- bloodAlcoholContent = 'HKQuantityTypeIdentifierBloodAlcoholContent', // Scalar(Percent, 0.0 - 1.0), Discrete
239
- forcedVitalCapacity = 'HKQuantityTypeIdentifierForcedVitalCapacity', // Volume, Discrete
240
- forcedExpiratoryVolume1 = 'HKQuantityTypeIdentifierForcedExpiratoryVolume1', // Volume, Discrete
241
- peakExpiratoryFlowRate = 'HKQuantityTypeIdentifierPeakExpiratoryFlowRate', // Volume/Time, Discrete
242
- environmentalAudioExposure = 'HKQuantityTypeIdentifierEnvironmentalAudioExposure', // Pressure, Cumulative
243
-
244
- headphoneAudioExposure = 'HKQuantityTypeIdentifierHeadphoneAudioExposure', // Pressure, Cumulative
245
- // Nutrition
246
- dietaryFatTotal = 'HKQuantityTypeIdentifierDietaryFatTotal', // Mass, Cumulative
247
- dietaryFatPolyunsaturated = 'HKQuantityTypeIdentifierDietaryFatPolyunsaturated', // Mass, Cumulative
248
- dietaryFatMonounsaturated = 'HKQuantityTypeIdentifierDietaryFatMonounsaturated', // Mass, Cumulative
249
- dietaryFatSaturated = 'HKQuantityTypeIdentifierDietaryFatSaturated', // Mass, Cumulative
250
- dietaryCholesterol = 'HKQuantityTypeIdentifierDietaryCholesterol', // Mass, Cumulative
251
- dietarySodium = 'HKQuantityTypeIdentifierDietarySodium', // Mass, Cumulative
252
- dietaryCarbohydrates = 'HKQuantityTypeIdentifierDietaryCarbohydrates', // Mass, Cumulative
253
- dietaryFiber = 'HKQuantityTypeIdentifierDietaryFiber', // Mass, Cumulative
254
- dietarySugar = 'HKQuantityTypeIdentifierDietarySugar', // Mass, Cumulative
255
- dietaryEnergyConsumed = 'HKQuantityTypeIdentifierDietaryEnergyConsumed', // Energy, Cumulative
256
- dietaryProtein = 'HKQuantityTypeIdentifierDietaryProtein', // Mass, Cumulative
257
-
258
- dietaryVitaminA = 'HKQuantityTypeIdentifierDietaryVitaminA', // Mass, Cumulative
259
- dietaryVitaminB6 = 'HKQuantityTypeIdentifierDietaryVitaminB6', // Mass, Cumulative
260
- dietaryVitaminB12 = 'HKQuantityTypeIdentifierDietaryVitaminB12', // Mass, Cumulative
261
- dietaryVitaminC = 'HKQuantityTypeIdentifierDietaryVitaminC', // Mass, Cumulative
262
- dietaryVitaminD = 'HKQuantityTypeIdentifierDietaryVitaminD', // Mass, Cumulative
263
- dietaryVitaminE = 'HKQuantityTypeIdentifierDietaryVitaminE', // Mass, Cumulative
264
- dietaryVitaminK = 'HKQuantityTypeIdentifierDietaryVitaminK', // Mass, Cumulative
265
- dietaryCalcium = 'HKQuantityTypeIdentifierDietaryCalcium', // Mass, Cumulative
266
- dietaryIron = 'HKQuantityTypeIdentifierDietaryIron', // Mass, Cumulative
267
- dietaryThiamin = 'HKQuantityTypeIdentifierDietaryThiamin', // Mass, Cumulative
268
- dietaryRiboflavin = 'HKQuantityTypeIdentifierDietaryRiboflavin', // Mass, Cumulative
269
- dietaryNiacin = 'HKQuantityTypeIdentifierDietaryNiacin', // Mass, Cumulative
270
- dietaryFolate = 'HKQuantityTypeIdentifierDietaryFolate', // Mass, Cumulative
271
- dietaryBiotin = 'HKQuantityTypeIdentifierDietaryBiotin', // Mass, Cumulative
272
- dietaryPantothenicAcid = 'HKQuantityTypeIdentifierDietaryPantothenicAcid', // Mass, Cumulative
273
- dietaryPhosphorus = 'HKQuantityTypeIdentifierDietaryPhosphorus', // Mass, Cumulative
274
- dietaryIodine = 'HKQuantityTypeIdentifierDietaryIodine', // Mass, Cumulative
275
- dietaryMagnesium = 'HKQuantityTypeIdentifierDietaryMagnesium', // Mass, Cumulative
276
- dietaryZinc = 'HKQuantityTypeIdentifierDietaryZinc', // Mass, Cumulative
277
- dietarySelenium = 'HKQuantityTypeIdentifierDietarySelenium', // Mass, Cumulative
278
- dietaryCopper = 'HKQuantityTypeIdentifierDietaryCopper', // Mass, Cumulative
279
- dietaryManganese = 'HKQuantityTypeIdentifierDietaryManganese', // Mass, Cumulative
280
- dietaryChromium = 'HKQuantityTypeIdentifierDietaryChromium', // Mass, Cumulative
281
- dietaryMolybdenum = 'HKQuantityTypeIdentifierDietaryMolybdenum', // Mass, Cumulative
282
- dietaryChloride = 'HKQuantityTypeIdentifierDietaryChloride', // Mass, Cumulative
283
- dietaryPotassium = 'HKQuantityTypeIdentifierDietaryPotassium', // Mass, Cumulative
284
- dietaryCaffeine = 'HKQuantityTypeIdentifierDietaryCaffeine', // Mass, Cumulative
285
- dietaryWater = 'HKQuantityTypeIdentifierDietaryWater', // Volume, Cumulative
286
-
287
- // Mobility
288
- sixMinuteWalkTestDistance = 'HKQuantityTypeIdentifierSixMinuteWalkTestDistance',
289
- walkingSpeed = 'HKQuantityTypeIdentifierWalkingSpeed',
290
- walkingStepLength = 'HKQuantityTypeIdentifierWalkingStepLength',
291
- walkingAsymmetryPercentage = 'HKQuantityTypeIdentifierWalkingAsymmetryPercentage',
292
- walkingDoubleSupportPercentage = 'HKQuantityTypeIdentifierWalkingDoubleSupportPercentage',
293
- stairAscentSpeed = 'HKQuantityTypeIdentifierStairAscentSpeed',
294
- stairDescentSpeed = 'HKQuantityTypeIdentifierStairDescentSpeed',
295
-
296
- uvExposure = 'HKQuantityTypeIdentifierUvExposure', // Scalar (Count), Discrete
297
- }
298
-
299
306
  export enum HKAuthorizationRequestStatus {
300
307
  unknown = 0,
301
308
  shouldRequest = 1,
@@ -661,11 +668,6 @@ export type HKCorrelationRaw<TIdentifier extends HKCorrelationTypeIdentifier> =
661
668
 
662
669
  type QueryId = string;
663
670
 
664
- export enum HKCorrelationTypeIdentifier {
665
- bloodPressure = 'HKCorrelationTypeIdentifierBloodPressure',
666
- food = 'HKCorrelationTypeIdentifierFood',
667
- }
668
-
669
671
  export enum HKUpdateFrequency {
670
672
  immediate = 1,
671
673
  hourly = 2,
@@ -690,7 +692,7 @@ export type WorkoutRoute = {
690
692
  readonly HKMetadataKeySyncVersion?: number;
691
693
  };
692
694
 
693
- type AuthorizationStatusFor = HKCharacteristicTypeIdentifier | HKSampleTypeIdentifier
695
+ export const HealthkitAuthorization = { ...HKCharacteristicTypeIdentifier, ...HKSampleTypeIdentifier }
694
696
 
695
697
  type ReactNativeHealthkitTypeNative = {
696
698
  isHealthDataAvailable(): Promise<boolean>;
@@ -701,11 +703,11 @@ type ReactNativeHealthkitTypeNative = {
701
703
  readonly getWheelchairUse: () => Promise<HKWheelchairUse>;
702
704
 
703
705
  readonly enableBackgroundDelivery: (
704
- typeIdentifier: HKSampleTypeIdentifier,
706
+ typeIdentifier: ValueOf<typeof HKSampleTypeIdentifier>,
705
707
  updateFrequency: HKUpdateFrequency
706
708
  ) => Promise<boolean>;
707
709
  readonly disableBackgroundDelivery: (
708
- typeIdentifier: HKSampleTypeIdentifier
710
+ typeIdentifier: ValueOf<typeof HKSampleTypeIdentifier>,
709
711
  ) => Promise<boolean>;
710
712
  readonly disableAllBackgroundDelivery: () => Promise<boolean>;
711
713
 
@@ -738,11 +740,11 @@ type ReactNativeHealthkitTypeNative = {
738
740
  ) => Promise<readonly HKCorrelationRaw<TIdentifier>[]>;
739
741
 
740
742
  subscribeToObserverQuery(
741
- identifier: HKSampleTypeIdentifier
743
+ identifier: ValueOf<typeof HKSampleTypeIdentifier>
742
744
  ): Promise<QueryId>;
743
745
  unsubscribeQuery(queryId: QueryId): Promise<boolean>;
744
746
  authorizationStatusFor(
745
- type: AuthorizationStatusFor
747
+ type: ValueOf<keyof typeof HealthkitAuthorization>
746
748
  ): Promise<boolean>;
747
749
  getRequestStatusForAuthorization(
748
750
  write: WritePermissions,
@@ -811,7 +813,7 @@ const Native = NativeModules.ReactNativeHealthkit as ReactNativeHealthkitTypeNat
811
813
  type OnChangeCallback = ({
812
814
  typeIdentifier,
813
815
  }: {
814
- readonly typeIdentifier: HKSampleTypeIdentifier;
816
+ readonly typeIdentifier: ValueOf<typeof HKSampleTypeIdentifier>;
815
817
  }) => void;
816
818
 
817
819
  interface HealthkitEventEmitter extends NativeEventEmitter {
package/src/types.ts CHANGED
@@ -26,7 +26,9 @@ import type {
26
26
  MetadataMapperForQuantityIdentifier,
27
27
  QueryStatisticsResponseRaw,
28
28
  WorkoutRoute,
29
+ HealthkitAuthorization,
29
30
  } from './native-types'
31
+ import type { ValueOf } from 'type-fest'
30
32
 
31
33
  export interface QueryWorkoutsOptions<
32
34
  TEnergy extends HKUnit,
@@ -104,7 +106,7 @@ export type QueryWorkoutsFn = <
104
106
  ) => Promise<readonly HKWorkout<TEnergy, TDistance>[]>;
105
107
 
106
108
  export type AuthorizationStatusForFn = (
107
- type: HKCharacteristicTypeIdentifier | HKSampleTypeIdentifier
109
+ type: HKCharacteristicTypeIdentifier | ValueOf<typeof HKSampleTypeIdentifier>
108
110
  ) => Promise<boolean>;
109
111
 
110
112
  export type QueryCategorySamplesFn = <T extends HKCategoryTypeIdentifier>(
@@ -112,14 +114,16 @@ export type QueryCategorySamplesFn = <T extends HKCategoryTypeIdentifier>(
112
114
  options: GenericQueryOptions
113
115
  ) => Promise<readonly HKCategorySample<T>[]>;
114
116
 
117
+ type ReadPermission = HKCharacteristicTypeIdentifier | ValueOf<typeof HKSampleTypeIdentifier>
118
+
115
119
  export type GetRequestStatusForAuthorizationFn = (
116
- read: readonly (HKCharacteristicTypeIdentifier | HKSampleTypeIdentifier)[],
117
- write?: readonly HKSampleTypeIdentifier[]
120
+ read: readonly ReadPermission[],
121
+ write?: readonly ValueOf<typeof HKSampleTypeIdentifier>[]
118
122
  ) => Promise<HKAuthorizationRequestStatus>;
119
123
 
120
124
  export type RequestAuthorizationFn = (
121
- read: readonly (HKCharacteristicTypeIdentifier | HKSampleTypeIdentifier)[],
122
- write?: readonly HKSampleTypeIdentifier[]
125
+ read: readonly (HKCharacteristicTypeIdentifier | ValueOf<typeof HKSampleTypeIdentifier>)[],
126
+ write?: readonly ValueOf<typeof HKSampleTypeIdentifier>[]
123
127
  ) => Promise<boolean>;
124
128
 
125
129
  export type SaveQuantitySampleFn = <TUnit extends HKQuantityTypeIdentifier>(
@@ -142,7 +146,7 @@ export type QueryQuantitySamplesFn = <
142
146
  ) => Promise<readonly HKQuantitySample<TIdentifier, TUnit>[]>;
143
147
 
144
148
  export type SubscribeToChangesFn = (
145
- identifier: HKSampleTypeIdentifier,
149
+ identifier: ValueOf<typeof HKSampleTypeIdentifier>,
146
150
  callback: () => void
147
151
  ) => Promise<UnsubscribeFunction>;
148
152
 
@@ -178,7 +182,7 @@ export type GetMostRecentQuantitySampleFn = <
178
182
  >(
179
183
  identifier: TIdentifier,
180
184
  unit?: TUnit
181
- ) => Promise<HKQuantitySample<TIdentifier, TUnit>>;
185
+ ) => Promise<HKQuantitySample<TIdentifier, TUnit> | null>;
182
186
 
183
187
  export type MostRecentQuantitySampleHook = <
184
188
  TIdentifier extends HKQuantityTypeIdentifier,
@@ -262,7 +266,7 @@ export type QueryCorrelationSamplesFn = <
262
266
  ) => Promise<readonly HKCorrelation<TIdentifier>[]>;
263
267
 
264
268
  export type SubscribeToChangesHook = <
265
- TIdentifier extends HKSampleTypeIdentifier
269
+ TIdentifier extends ValueOf<typeof HKSampleTypeIdentifier>
266
270
  >(
267
271
  identifier: TIdentifier,
268
272
  onChange: () => void,
@@ -306,11 +310,11 @@ export type ReactNativeHealthkit = {
306
310
  readonly saveCorrelationSample: SaveCorrelationSampleFn;
307
311
  readonly saveWorkoutSample: SaveWorkoutSampleFn;
308
312
  readonly enableBackgroundDelivery: (
309
- typeIdentifier: HKSampleTypeIdentifier,
313
+ typeIdentifier: ValueOf<typeof HKSampleTypeIdentifier>,
310
314
  updateFrequency: HKUpdateFrequency
311
315
  ) => Promise<boolean>;
312
316
  readonly disableBackgroundDelivery: (
313
- typeIdentifier: HKSampleTypeIdentifier
317
+ typeIdentifier: ValueOf<typeof HKSampleTypeIdentifier>
314
318
  ) => Promise<boolean>;
315
319
  readonly disableAllBackgroundDelivery: () => Promise<boolean>;
316
320
 
@@ -321,4 +325,9 @@ export type ReactNativeHealthkit = {
321
325
  readonly useMostRecentQuantitySample: MostRecentQuantitySampleHook;
322
326
 
323
327
  readonly useSubscribeToChanges: SubscribeToChangesHook;
328
+ readonly useIsHealthDataAvailable: () => boolean | null;
329
+ readonly useHealthkitAuthorization: (
330
+ read: readonly ValueOf<typeof HealthkitAuthorization>[],
331
+ write?: readonly ValueOf<typeof HKSampleTypeIdentifier>[],
332
+ ) => readonly [authorizationStatus: HKAuthorizationRequestStatus | null, request: () => Promise<HKAuthorizationRequestStatus | null>];
324
333
  };