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