@kingstinct/react-native-healthkit 6.1.0 → 7.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 (268) hide show
  1. package/README.md +7 -5
  2. package/app.plugin.js +69 -0
  3. package/ios/Constants.swift +28 -0
  4. package/ios/Helpers.swift +152 -0
  5. package/ios/ReactNativeHealthkit.m +24 -0
  6. package/ios/ReactNativeHealthkit.swift +534 -728
  7. package/ios/Serializers.swift +206 -0
  8. package/lib/commonjs/hooks/useHealthkitAuthorization.js +0 -6
  9. package/lib/commonjs/hooks/useHealthkitAuthorization.js.map +1 -1
  10. package/lib/commonjs/hooks/useHealthkitAuthorization.test.js +2 -9
  11. package/lib/commonjs/hooks/useHealthkitAuthorization.test.js.map +1 -1
  12. package/lib/commonjs/hooks/useIsHealthDataAvailable.js +0 -6
  13. package/lib/commonjs/hooks/useIsHealthDataAvailable.js.map +1 -1
  14. package/lib/commonjs/hooks/useIsHealthDataAvailable.test.js +1 -6
  15. package/lib/commonjs/hooks/useIsHealthDataAvailable.test.js.map +1 -1
  16. package/lib/commonjs/hooks/useMostRecentCategorySample.js +1 -7
  17. package/lib/commonjs/hooks/useMostRecentCategorySample.js.map +1 -1
  18. package/lib/commonjs/hooks/useMostRecentQuantitySample.js +0 -10
  19. package/lib/commonjs/hooks/useMostRecentQuantitySample.js.map +1 -1
  20. package/lib/commonjs/hooks/useMostRecentWorkout.js +0 -10
  21. package/lib/commonjs/hooks/useMostRecentWorkout.js.map +1 -1
  22. package/lib/commonjs/hooks/useSources.js +0 -5
  23. package/lib/commonjs/hooks/useSources.js.map +1 -1
  24. package/lib/commonjs/hooks/useStatisticsForQuantity.js +1 -7
  25. package/lib/commonjs/hooks/useStatisticsForQuantity.js.map +1 -1
  26. package/lib/commonjs/hooks/useSubscribeToChanges.js +0 -8
  27. package/lib/commonjs/hooks/useSubscribeToChanges.js.map +1 -1
  28. package/lib/commonjs/index.ios.js +6 -33
  29. package/lib/commonjs/index.ios.js.map +1 -1
  30. package/lib/commonjs/index.js +7 -11
  31. package/lib/commonjs/index.js.map +1 -1
  32. package/lib/commonjs/jest.setup.js +3 -1
  33. package/lib/commonjs/jest.setup.js.map +1 -1
  34. package/lib/commonjs/native-types.js +166 -250
  35. package/lib/commonjs/native-types.js.map +1 -1
  36. package/lib/commonjs/test-utils.js +1 -3
  37. package/lib/commonjs/test-utils.js.map +1 -1
  38. package/lib/commonjs/types.js +0 -2
  39. package/lib/commonjs/types.js.map +1 -1
  40. package/lib/commonjs/utils/deleteQuantitySample.js +0 -4
  41. package/lib/commonjs/utils/deleteQuantitySample.js.map +1 -1
  42. package/lib/commonjs/utils/deleteSamples.js +0 -4
  43. package/lib/commonjs/utils/deleteSamples.js.map +1 -1
  44. package/lib/commonjs/utils/deserializeCategorySample.js +2 -3
  45. package/lib/commonjs/utils/deserializeCategorySample.js.map +1 -1
  46. package/lib/commonjs/utils/deserializeCategorySample.test.js +3 -5
  47. package/lib/commonjs/utils/deserializeCategorySample.test.js.map +1 -1
  48. package/lib/commonjs/utils/deserializeCorrelation.js +2 -7
  49. package/lib/commonjs/utils/deserializeCorrelation.js.map +1 -1
  50. package/lib/commonjs/utils/deserializeHeartbeatSeriesSample.js +2 -3
  51. package/lib/commonjs/utils/deserializeHeartbeatSeriesSample.js.map +1 -1
  52. package/lib/commonjs/utils/deserializeSample.js +2 -3
  53. package/lib/commonjs/utils/deserializeSample.js.map +1 -1
  54. package/lib/commonjs/utils/deserializeWorkout.js +2 -3
  55. package/lib/commonjs/utils/deserializeWorkout.js.map +1 -1
  56. package/lib/commonjs/utils/ensureMetadata.js +0 -2
  57. package/lib/commonjs/utils/ensureMetadata.js.map +1 -1
  58. package/lib/commonjs/utils/ensureUnit.js +0 -5
  59. package/lib/commonjs/utils/ensureUnit.js.map +1 -1
  60. package/lib/commonjs/utils/getDateOfBirth.js +0 -4
  61. package/lib/commonjs/utils/getDateOfBirth.js.map +1 -1
  62. package/lib/commonjs/utils/getMostRecentCategorySample.js +1 -5
  63. package/lib/commonjs/utils/getMostRecentCategorySample.js.map +1 -1
  64. package/lib/commonjs/utils/getMostRecentQuantitySample.js +1 -5
  65. package/lib/commonjs/utils/getMostRecentQuantitySample.js.map +1 -1
  66. package/lib/commonjs/utils/getMostRecentWorkout.js +0 -4
  67. package/lib/commonjs/utils/getMostRecentWorkout.js.map +1 -1
  68. package/lib/commonjs/utils/getPreferredUnit.js +0 -4
  69. package/lib/commonjs/utils/getPreferredUnit.js.map +1 -1
  70. package/lib/commonjs/utils/getPreferredUnits.js +0 -4
  71. package/lib/commonjs/utils/getPreferredUnits.js.map +1 -1
  72. package/lib/commonjs/utils/getPreferredUnitsTyped.js +0 -11
  73. package/lib/commonjs/utils/getPreferredUnitsTyped.js.map +1 -1
  74. package/lib/commonjs/utils/getRequestStatusForAuthorization.js +4 -6
  75. package/lib/commonjs/utils/getRequestStatusForAuthorization.js.map +1 -1
  76. package/lib/commonjs/utils/prepareOptions.js +0 -4
  77. package/lib/commonjs/utils/prepareOptions.js.map +1 -1
  78. package/lib/commonjs/utils/queryCategorySamples.js +3 -14
  79. package/lib/commonjs/utils/queryCategorySamples.js.map +1 -1
  80. package/lib/commonjs/utils/queryCategorySamplesWithAnchor.js +22 -0
  81. package/lib/commonjs/utils/queryCategorySamplesWithAnchor.js.map +1 -0
  82. package/lib/commonjs/utils/queryCorrelationSamples.js +1 -7
  83. package/lib/commonjs/utils/queryCorrelationSamples.js.map +1 -1
  84. package/lib/commonjs/utils/queryHeartbeatSeriesSamples.js +3 -13
  85. package/lib/commonjs/utils/queryHeartbeatSeriesSamples.js.map +1 -1
  86. package/lib/commonjs/utils/queryHeartbeatSeriesSamplesWithAnchor.js +22 -0
  87. package/lib/commonjs/utils/queryHeartbeatSeriesSamplesWithAnchor.js.map +1 -0
  88. package/lib/commonjs/utils/queryQuantitySamples.js +3 -15
  89. package/lib/commonjs/utils/queryQuantitySamples.js.map +1 -1
  90. package/lib/commonjs/utils/queryQuantitySamplesWithAnchor.js +24 -0
  91. package/lib/commonjs/utils/queryQuantitySamplesWithAnchor.js.map +1 -0
  92. package/lib/commonjs/utils/querySources.js +0 -4
  93. package/lib/commonjs/utils/querySources.js.map +1 -1
  94. package/lib/commonjs/utils/queryStatisticsForQuantity.js +3 -7
  95. package/lib/commonjs/utils/queryStatisticsForQuantity.js.map +1 -1
  96. package/lib/commonjs/utils/queryWorkouts.js +1 -8
  97. package/lib/commonjs/utils/queryWorkouts.js.map +1 -1
  98. package/lib/commonjs/utils/requestAuthorization.js +4 -6
  99. package/lib/commonjs/utils/requestAuthorization.js.map +1 -1
  100. package/lib/commonjs/utils/saveCategorySample.js +0 -4
  101. package/lib/commonjs/utils/saveCategorySample.js.map +1 -1
  102. package/lib/commonjs/utils/saveCorrelationSample.js +3 -7
  103. package/lib/commonjs/utils/saveCorrelationSample.js.map +1 -1
  104. package/lib/commonjs/utils/saveQuantitySample.js +0 -4
  105. package/lib/commonjs/utils/saveQuantitySample.js.map +1 -1
  106. package/lib/commonjs/utils/saveWorkoutSample.js +3 -8
  107. package/lib/commonjs/utils/saveWorkoutSample.js.map +1 -1
  108. package/lib/commonjs/utils/serializeDate.js +0 -2
  109. package/lib/commonjs/utils/serializeDate.js.map +1 -1
  110. package/lib/commonjs/utils/serializeDate.test.js +0 -2
  111. package/lib/commonjs/utils/serializeDate.test.js.map +1 -1
  112. package/lib/commonjs/utils/subscribeToChanges.js +0 -7
  113. package/lib/commonjs/utils/subscribeToChanges.js.map +1 -1
  114. package/lib/module/hooks/useHealthkitAuthorization.js +0 -2
  115. package/lib/module/hooks/useHealthkitAuthorization.js.map +1 -1
  116. package/lib/module/hooks/useHealthkitAuthorization.test.js +1 -1
  117. package/lib/module/hooks/useHealthkitAuthorization.test.js.map +1 -1
  118. package/lib/module/hooks/useIsHealthDataAvailable.js +0 -3
  119. package/lib/module/hooks/useIsHealthDataAvailable.js.map +1 -1
  120. package/lib/module/hooks/useIsHealthDataAvailable.test.js +1 -1
  121. package/lib/module/hooks/useIsHealthDataAvailable.test.js.map +1 -1
  122. package/lib/module/hooks/useMostRecentCategorySample.js +1 -3
  123. package/lib/module/hooks/useMostRecentCategorySample.js.map +1 -1
  124. package/lib/module/hooks/useMostRecentQuantitySample.js +0 -5
  125. package/lib/module/hooks/useMostRecentQuantitySample.js.map +1 -1
  126. package/lib/module/hooks/useMostRecentWorkout.js +0 -5
  127. package/lib/module/hooks/useMostRecentWorkout.js.map +1 -1
  128. package/lib/module/hooks/useSources.js +0 -2
  129. package/lib/module/hooks/useSources.js.map +1 -1
  130. package/lib/module/hooks/useStatisticsForQuantity.js +1 -3
  131. package/lib/module/hooks/useStatisticsForQuantity.js.map +1 -1
  132. package/lib/module/hooks/useSubscribeToChanges.js +0 -5
  133. package/lib/module/hooks/useSubscribeToChanges.js.map +1 -1
  134. package/lib/module/index.ios.js +6 -0
  135. package/lib/module/index.ios.js.map +1 -1
  136. package/lib/module/index.js +8 -8
  137. package/lib/module/index.js.map +1 -1
  138. package/lib/module/jest.setup.js +3 -0
  139. package/lib/module/jest.setup.js.map +1 -1
  140. package/lib/module/native-types.js +134 -201
  141. package/lib/module/native-types.js.map +1 -1
  142. package/lib/module/test-utils.js +0 -2
  143. package/lib/module/test-utils.js.map +1 -1
  144. package/lib/module/types.js.map +1 -1
  145. package/lib/module/utils/deleteQuantitySample.js +0 -2
  146. package/lib/module/utils/deleteQuantitySample.js.map +1 -1
  147. package/lib/module/utils/deleteSamples.js +0 -2
  148. package/lib/module/utils/deleteSamples.js.map +1 -1
  149. package/lib/module/utils/deserializeCategorySample.js +2 -2
  150. package/lib/module/utils/deserializeCategorySample.js.map +1 -1
  151. package/lib/module/utils/deserializeCategorySample.test.js +3 -2
  152. package/lib/module/utils/deserializeCategorySample.test.js.map +1 -1
  153. package/lib/module/utils/deserializeCorrelation.js +2 -4
  154. package/lib/module/utils/deserializeCorrelation.js.map +1 -1
  155. package/lib/module/utils/deserializeHeartbeatSeriesSample.js +2 -2
  156. package/lib/module/utils/deserializeHeartbeatSeriesSample.js.map +1 -1
  157. package/lib/module/utils/deserializeSample.js +2 -2
  158. package/lib/module/utils/deserializeSample.js.map +1 -1
  159. package/lib/module/utils/deserializeWorkout.js +2 -2
  160. package/lib/module/utils/deserializeWorkout.js.map +1 -1
  161. package/lib/module/utils/ensureMetadata.js +0 -1
  162. package/lib/module/utils/ensureMetadata.js.map +1 -1
  163. package/lib/module/utils/ensureUnit.js +0 -3
  164. package/lib/module/utils/ensureUnit.js.map +1 -1
  165. package/lib/module/utils/getDateOfBirth.js +0 -2
  166. package/lib/module/utils/getDateOfBirth.js.map +1 -1
  167. package/lib/module/utils/getMostRecentCategorySample.js +1 -3
  168. package/lib/module/utils/getMostRecentCategorySample.js.map +1 -1
  169. package/lib/module/utils/getMostRecentQuantitySample.js +1 -3
  170. package/lib/module/utils/getMostRecentQuantitySample.js.map +1 -1
  171. package/lib/module/utils/getMostRecentWorkout.js +0 -2
  172. package/lib/module/utils/getMostRecentWorkout.js.map +1 -1
  173. package/lib/module/utils/getPreferredUnit.js +0 -2
  174. package/lib/module/utils/getPreferredUnit.js.map +1 -1
  175. package/lib/module/utils/getPreferredUnits.js +0 -2
  176. package/lib/module/utils/getPreferredUnits.js.map +1 -1
  177. package/lib/module/utils/getPreferredUnitsTyped.js +0 -8
  178. package/lib/module/utils/getPreferredUnitsTyped.js.map +1 -1
  179. package/lib/module/utils/getRequestStatusForAuthorization.js +4 -4
  180. package/lib/module/utils/getRequestStatusForAuthorization.js.map +1 -1
  181. package/lib/module/utils/prepareOptions.js +0 -2
  182. package/lib/module/utils/prepareOptions.js.map +1 -1
  183. package/lib/module/utils/queryCategorySamples.js +3 -10
  184. package/lib/module/utils/queryCategorySamples.js.map +1 -1
  185. package/lib/module/utils/queryCategorySamplesWithAnchor.js +14 -0
  186. package/lib/module/utils/queryCategorySamplesWithAnchor.js.map +1 -0
  187. package/lib/module/utils/queryCorrelationSamples.js +1 -3
  188. package/lib/module/utils/queryCorrelationSamples.js.map +1 -1
  189. package/lib/module/utils/queryHeartbeatSeriesSamples.js +3 -9
  190. package/lib/module/utils/queryHeartbeatSeriesSamples.js.map +1 -1
  191. package/lib/module/utils/queryHeartbeatSeriesSamplesWithAnchor.js +14 -0
  192. package/lib/module/utils/queryHeartbeatSeriesSamplesWithAnchor.js.map +1 -0
  193. package/lib/module/utils/queryQuantitySamples.js +3 -10
  194. package/lib/module/utils/queryQuantitySamples.js.map +1 -1
  195. package/lib/module/utils/queryQuantitySamplesWithAnchor.js +16 -0
  196. package/lib/module/utils/queryQuantitySamplesWithAnchor.js.map +1 -0
  197. package/lib/module/utils/querySources.js +0 -2
  198. package/lib/module/utils/querySources.js.map +1 -1
  199. package/lib/module/utils/queryStatisticsForQuantity.js +3 -4
  200. package/lib/module/utils/queryStatisticsForQuantity.js.map +1 -1
  201. package/lib/module/utils/queryWorkouts.js +1 -3
  202. package/lib/module/utils/queryWorkouts.js.map +1 -1
  203. package/lib/module/utils/requestAuthorization.js +4 -4
  204. package/lib/module/utils/requestAuthorization.js.map +1 -1
  205. package/lib/module/utils/saveCategorySample.js +0 -2
  206. package/lib/module/utils/saveCategorySample.js.map +1 -1
  207. package/lib/module/utils/saveCorrelationSample.js +3 -4
  208. package/lib/module/utils/saveCorrelationSample.js.map +1 -1
  209. package/lib/module/utils/saveQuantitySample.js +0 -2
  210. package/lib/module/utils/saveQuantitySample.js.map +1 -1
  211. package/lib/module/utils/saveWorkoutSample.js +3 -5
  212. package/lib/module/utils/saveWorkoutSample.js.map +1 -1
  213. package/lib/module/utils/serializeDate.js +0 -1
  214. package/lib/module/utils/serializeDate.js.map +1 -1
  215. package/lib/module/utils/serializeDate.test.js.map +1 -1
  216. package/lib/module/utils/subscribeToChanges.js +0 -3
  217. package/lib/module/utils/subscribeToChanges.js.map +1 -1
  218. package/lib/typescript/src/hooks/useMostRecentCategorySample.d.ts +2 -3
  219. package/lib/typescript/src/hooks/useMostRecentQuantitySample.d.ts +2 -3
  220. package/lib/typescript/src/index.ios.d.ts +4 -1
  221. package/lib/typescript/src/native-types.d.ts +66 -63
  222. package/lib/typescript/src/types.d.ts +3 -3
  223. package/lib/typescript/src/utils/deleteQuantitySample.d.ts +1 -1
  224. package/lib/typescript/src/utils/deleteSamples.d.ts +1 -1
  225. package/lib/typescript/src/utils/getMostRecentCategorySample.d.ts +1 -1
  226. package/lib/typescript/src/utils/getMostRecentQuantitySample.d.ts +1 -1
  227. package/lib/typescript/src/utils/getMostRecentWorkout.d.ts +1 -1
  228. package/lib/typescript/src/utils/getPreferredUnit.d.ts +1 -1
  229. package/lib/typescript/src/utils/getPreferredUnits.d.ts +1 -1
  230. package/lib/typescript/src/utils/queryCategorySamples.d.ts +3 -8
  231. package/lib/typescript/src/utils/queryCategorySamplesWithAnchor.d.ts +10 -0
  232. package/lib/typescript/src/utils/queryCorrelationSamples.d.ts +1 -1
  233. package/lib/typescript/src/utils/queryHeartbeatSeriesSamples.d.ts +2 -2
  234. package/lib/typescript/src/utils/queryHeartbeatSeriesSamplesWithAnchor.d.ts +10 -0
  235. package/lib/typescript/src/utils/queryQuantitySamples.d.ts +4 -9
  236. package/lib/typescript/src/utils/queryQuantitySamplesWithAnchor.d.ts +12 -0
  237. package/lib/typescript/src/utils/querySources.d.ts +1 -1
  238. package/package.json +20 -18
  239. package/src/hooks/useHealthkitAuthorization.test.ts +1 -1
  240. package/src/hooks/useIsHealthDataAvailable.test.ts +1 -1
  241. package/src/hooks/useMostRecentCategorySample.ts +3 -4
  242. package/src/hooks/useMostRecentQuantitySample.ts +2 -3
  243. package/src/hooks/useStatisticsForQuantity.ts +1 -1
  244. package/src/index.ios.tsx +6 -0
  245. package/src/index.tsx +10 -5
  246. package/src/jest.setup.ts +3 -0
  247. package/src/native-types.ts +28 -7
  248. package/src/utils/deserializeCategorySample.test.ts +1 -1
  249. package/src/utils/getMostRecentCategorySample.ts +1 -1
  250. package/src/utils/getMostRecentQuantitySample.ts +1 -1
  251. package/src/utils/queryCategorySamples.ts +6 -18
  252. package/src/utils/queryCategorySamplesWithAnchor.ts +39 -0
  253. package/src/utils/queryCorrelationSamples.ts +2 -2
  254. package/src/utils/queryHeartbeatSeriesSamples.ts +3 -8
  255. package/src/utils/queryHeartbeatSeriesSamplesWithAnchor.ts +33 -0
  256. package/src/utils/queryQuantitySamples.ts +8 -18
  257. package/src/utils/queryQuantitySamplesWithAnchor.ts +46 -0
  258. package/src/utils/queryStatisticsForQuantity.ts +1 -1
  259. package/src/utils/queryWorkouts.ts +1 -1
  260. package/src/utils/saveCorrelationSample.ts +1 -1
  261. package/src/utils/saveWorkoutSample.ts +1 -1
  262. package/android/.project +0 -34
  263. package/android/.settings/org.eclipse.buildship.core.prefs +0 -13
  264. package/android/build.gradle +0 -130
  265. package/android/gradle.properties +0 -4
  266. package/android/src/main/AndroidManifest.xml +0 -4
  267. package/android/src/main/java/com/kingstinctreactnativehealthkit/ReactNativeHealthkitModule.kt +0 -24
  268. package/android/src/main/java/com/kingstinctreactnativehealthkit/ReactNativeHealthkitPackage.kt +0 -20
@@ -1,41 +1,22 @@
1
- import HealthKit;
2
- import CoreLocation;
3
-
4
- let INIT_ERROR = "HEALTHKIT_INIT_ERROR"
5
- let INIT_ERROR_MESSAGE = "HealthKit not initialized"
6
- let TYPE_IDENTIFIER_ERROR = "HEALTHKIT_TYPE_IDENTIFIER_NOT_RECOGNIZED_ERROR"
7
- let GENERIC_ERROR = "HEALTHKIT_ERROR"
8
-
9
- let HKCharacteristicTypeIdentifier_PREFIX = "HKCharacteristicTypeIdentifier"
10
- let HKQuantityTypeIdentifier_PREFIX = "HKQuantityTypeIdentifier"
11
- let HKCategoryTypeIdentifier_PREFIX = "HKCategoryTypeIdentifier"
12
- let HKCorrelationTypeIdentifier_PREFIX = "HKCorrelationTypeIdentifier"
13
- let HKActivitySummaryTypeIdentifier = "HKActivitySummaryTypeIdentifier"
14
- let HKAudiogramTypeIdentifier = "HKAudiogramTypeIdentifier"
15
- let HKWorkoutTypeIdentifier = "HKWorkoutTypeIdentifier"
16
- let HKWorkoutRouteTypeIdentifier = "HKWorkoutRouteTypeIdentifier"
17
- let HKDataTypeIdentifierHeartbeatSeries = "HKDataTypeIdentifierHeartbeatSeries"
18
-
19
- let SpeedUnit = HKUnit(from: "m/s") // HKUnit.meter().unitDivided(by: HKUnit.second())
20
- // Support for MET data: HKAverageMETs 8.24046 kcal/hr·kg
21
- let METUnit = HKUnit(from: "kcal/hr·kg")
1
+ import HealthKit
2
+ import CoreLocation
22
3
 
23
4
  @objc(ReactNativeHealthkit)
24
5
  @available(iOS 10.0, *)
25
6
  class ReactNativeHealthkit: RCTEventEmitter {
26
- var _store : HKHealthStore?
27
- var _runningQueries : Dictionary<String, HKQuery>;
28
- var _dateFormatter : ISO8601DateFormatter;
7
+ var _store: HKHealthStore?
8
+ var _runningQueries: [String: HKQuery]
9
+ var _dateFormatter: ISO8601DateFormatter
29
10
  var _hasListeners = false
30
11
 
31
12
  override init() {
32
- self._runningQueries = Dictionary<String, HKQuery>();
33
- self._dateFormatter = ISO8601DateFormatter();
13
+ self._runningQueries = [String: HKQuery]()
14
+ self._dateFormatter = ISO8601DateFormatter()
34
15
 
35
- if(HKHealthStore.isHealthDataAvailable()){
36
- self._store = HKHealthStore.init();
16
+ if HKHealthStore.isHealthDataAvailable() {
17
+ self._store = HKHealthStore.init()
37
18
  }
38
- super.init();
19
+ super.init()
39
20
  }
40
21
 
41
22
  deinit {
@@ -46,7 +27,7 @@ class ReactNativeHealthkit: RCTEventEmitter {
46
27
  }
47
28
  }
48
29
 
49
- override func stopObserving() -> Void {
30
+ override func stopObserving() {
50
31
  self._hasListeners = false
51
32
  if let store = _store {
52
33
  for query in self._runningQueries {
@@ -55,336 +36,169 @@ class ReactNativeHealthkit: RCTEventEmitter {
55
36
  }
56
37
  }
57
38
 
58
- override func startObserving() -> Void {
39
+ override func startObserving() {
59
40
  self._hasListeners = true
60
41
  }
61
42
 
62
-
63
43
  @objc(canAccessProtectedData:withRejecter:)
64
- func canAccessProtectedData(resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
65
- resolve(UIApplication.shared.isProtectedDataAvailable);
66
- }
67
-
68
-
69
- func objectTypeFromString(typeIdentifier: String) -> HKObjectType? {
70
- if(typeIdentifier.starts(with: HKCharacteristicTypeIdentifier_PREFIX)){
71
- let identifier = HKCharacteristicTypeIdentifier.init(rawValue: typeIdentifier);
72
- return HKObjectType.characteristicType(forIdentifier: identifier) as HKObjectType?
73
- }
74
-
75
- if(typeIdentifier.starts(with: HKQuantityTypeIdentifier_PREFIX)){
76
- let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier);
77
- return HKObjectType.quantityType(forIdentifier: identifier) as HKObjectType?
78
- }
79
-
80
- if(typeIdentifier.starts(with: HKCategoryTypeIdentifier_PREFIX)){
81
- let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier);
82
- return HKObjectType.categoryType(forIdentifier: identifier) as HKObjectType?
83
- }
84
-
85
- if(typeIdentifier.starts(with: HKCorrelationTypeIdentifier_PREFIX)){
86
- let identifier = HKCorrelationTypeIdentifier.init(rawValue: typeIdentifier);
87
- return HKObjectType.correlationType(forIdentifier: identifier) as HKObjectType?
88
- }
89
-
90
- if(typeIdentifier == HKActivitySummaryTypeIdentifier){
91
- return HKObjectType.activitySummaryType();
92
- }
93
-
94
- if #available(iOS 13, *) {
95
- if(typeIdentifier == HKAudiogramTypeIdentifier){
96
- return HKObjectType.audiogramSampleType();
97
- }
98
-
99
- if(typeIdentifier == HKDataTypeIdentifierHeartbeatSeries){
100
- return HKObjectType.seriesType(forIdentifier: typeIdentifier);
101
- }
102
- }
103
-
104
- if(typeIdentifier == HKWorkoutTypeIdentifier){
105
- return HKObjectType.workoutType()
106
- }
107
-
108
- if #available(iOS 11.0, *){
109
- if typeIdentifier == HKWorkoutRouteTypeIdentifier{
110
- return HKObjectType.seriesType(forIdentifier: typeIdentifier);
111
- }
112
- }
113
-
114
- return nil;
115
- }
116
-
117
- func sampleTypeFromString(typeIdentifier: String) -> HKSampleType? {
118
- if(typeIdentifier.starts(with: HKQuantityTypeIdentifier_PREFIX)){
119
- let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier);
120
- return HKSampleType.quantityType(forIdentifier: identifier) as HKSampleType?
121
- }
122
-
123
- if(typeIdentifier.starts(with: HKCategoryTypeIdentifier_PREFIX)){
124
- let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier);
125
- return HKSampleType.categoryType(forIdentifier: identifier) as HKSampleType?
126
- }
127
-
128
- if(typeIdentifier.starts(with: HKCorrelationTypeIdentifier_PREFIX)){
129
- let identifier = HKCorrelationTypeIdentifier.init(rawValue: typeIdentifier);
130
- return HKSampleType.correlationType(forIdentifier: identifier) as HKSampleType?
131
- }
132
-
133
- if #available(iOS 13, *) {
134
- if(typeIdentifier == HKAudiogramTypeIdentifier){
135
- return HKSampleType.audiogramSampleType();
136
- }
137
- }
138
-
139
- if(typeIdentifier == HKWorkoutTypeIdentifier){
140
- return HKSampleType.workoutType();
141
- }
142
-
143
- return nil;
144
- }
145
-
146
- func objectTypesFromDictionary(typeIdentifiers: NSDictionary) -> Set<HKObjectType> {
147
- var share = Set<HKObjectType>();
148
- for item in typeIdentifiers {
149
- if(item.value as! Bool){
150
- let objectType = objectTypeFromString(typeIdentifier: item.key as! String);
151
- if(objectType != nil){
152
- share.insert(objectType!);
153
- }
154
- }
155
- }
156
- return share;
157
- }
158
-
159
- func sampleTypesFromDictionary(typeIdentifiers: NSDictionary) -> Set<HKSampleType> {
160
- var share = Set<HKSampleType>();
161
- for item in typeIdentifiers {
162
- if(item.value as! Bool){
163
- let sampleType = sampleTypeFromString(typeIdentifier: item.key as! String);
164
- if(sampleType != nil){
165
- share.insert(sampleType!);
166
- }
167
- }
168
- }
169
- return share;
44
+ func canAccessProtectedData(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
45
+ resolve(UIApplication.shared.isProtectedDataAvailable)
170
46
  }
171
47
 
172
48
  @objc(isHealthDataAvailable:withRejecter:)
173
- func isHealthDataAvailable(resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
49
+ func isHealthDataAvailable(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
174
50
  resolve(HKHealthStore.isHealthDataAvailable())
175
51
  }
176
52
 
177
53
  @available(iOS 12.0, *)
178
54
  @objc(supportsHealthRecords:withRejecter:)
179
- func supportsHealthRecords(resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
55
+ func supportsHealthRecords(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
180
56
  guard let store = _store else {
181
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
57
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
182
58
  }
183
- resolve(store.supportsHealthRecords());
59
+ resolve(store.supportsHealthRecords())
184
60
  }
185
61
 
186
62
  @available(iOS 12.0, *)
187
63
  @objc(getRequestStatusForAuthorization:read:resolve:withRejecter:)
188
- func getRequestStatusForAuthorization(toShare: NSDictionary, read: NSDictionary, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
64
+ func getRequestStatusForAuthorization(toShare: NSDictionary, read: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
189
65
  guard let store = _store else {
190
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
66
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
191
67
  }
192
- let share = sampleTypesFromDictionary(typeIdentifiers: toShare);
193
- let toRead = objectTypesFromDictionary(typeIdentifiers: read);
68
+ let share = sampleTypesFromDictionary(typeIdentifiers: toShare)
69
+ let toRead = objectTypesFromDictionary(typeIdentifiers: read)
194
70
  store.getRequestStatusForAuthorization(toShare: share, read: toRead) { (status: HKAuthorizationRequestStatus, error: Error?) in
195
71
  guard let err = error else {
196
- return resolve(status.rawValue);
72
+ return resolve(status.rawValue)
197
73
  }
198
- reject(GENERIC_ERROR, err.localizedDescription, err);
74
+ reject(GENERIC_ERROR, err.localizedDescription, err)
199
75
  }
200
76
  }
201
77
 
202
78
  @objc(getPreferredUnits:resolve:reject:)
203
- func getPreferredUnits(forIdentifiers: NSArray, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
79
+ func getPreferredUnits(forIdentifiers: NSArray, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
204
80
  guard let store = _store else {
205
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
81
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
206
82
  }
207
- var quantityTypes = Set<HKQuantityType>();
83
+ var quantityTypes = Set<HKQuantityType>()
208
84
  for identifierString in forIdentifiers {
209
- let identifier = HKQuantityTypeIdentifier.init(rawValue: identifierString as! String);
210
- let type = HKSampleType.quantityType(forIdentifier: identifier);
211
- if(type != nil){
212
- quantityTypes.insert(type!);
85
+ let identifier = HKQuantityTypeIdentifier.init(rawValue: identifierString as! String)
86
+ let type = HKSampleType.quantityType(forIdentifier: identifier)
87
+ if type != nil {
88
+ quantityTypes.insert(type!)
213
89
  }
214
90
  }
215
91
 
216
- store.preferredUnits(for: quantityTypes) { (typePerUnits: [HKQuantityType : HKUnit], error: Error?) in
217
- let dic: NSMutableDictionary = NSMutableDictionary();
92
+ store.preferredUnits(for: quantityTypes) { (typePerUnits: [HKQuantityType: HKUnit], _: Error?) in
93
+ let dic: NSMutableDictionary = NSMutableDictionary()
218
94
 
219
95
  for typePerUnit in typePerUnits {
220
- dic.setObject(typePerUnit.value.unitString, forKey: typePerUnit.key.identifier as NSCopying);
96
+ dic.setObject(typePerUnit.value.unitString, forKey: typePerUnit.key.identifier as NSCopying)
221
97
  }
222
98
 
223
- resolve(dic);
99
+ resolve(dic)
224
100
  }
225
101
  }
226
102
 
227
- func serializeQuantity(unit: HKUnit, quantity: HKQuantity?) -> Dictionary<String, Any>? {
228
- guard let q = quantity else {
229
- return nil;
230
- }
231
-
232
- return [
233
- "quantity": q.doubleValue(for: unit),
234
- "unit": unit.unitString
235
- ]
236
- }
237
-
238
- func serializeQuantitySample(sample: HKQuantitySample, unit: HKUnit) -> NSDictionary {
239
- let endDate = _dateFormatter.string(from: sample.endDate)
240
- let startDate = _dateFormatter.string(from: sample.startDate);
241
-
242
- let quantity = sample.quantity.doubleValue(for: unit);
243
-
244
- return [
245
- "uuid": sample.uuid.uuidString,
246
- "device": self.serializeDevice(_device: sample.device) as Any,
247
- "quantityType": sample.quantityType.identifier,
248
- "endDate": endDate,
249
- "startDate": startDate,
250
- "quantity": quantity,
251
- "unit": unit.unitString,
252
- "metadata": self.serializeMetadata(metadata: sample.metadata),
253
- "sourceRevision": self.serializeSourceRevision(_sourceRevision: sample.sourceRevision) as Any,
254
- ]
255
- }
256
-
257
- func serializeDeletedSample(sample: HKDeletedObject) -> NSDictionary {
258
- return [
259
- "uuid": sample.uuid.uuidString,
260
- "metadata": self.serializeMetadata(metadata: sample.metadata)
261
- ]
262
- }
263
-
264
- func serializeCategorySample(sample: HKCategorySample) -> NSDictionary {
265
- let endDate = _dateFormatter.string(from: sample.endDate)
266
- let startDate = _dateFormatter.string(from: sample.startDate);
267
-
268
- return [
269
- "uuid": sample.uuid.uuidString,
270
- "device": self.serializeDevice(_device: sample.device) as Any,
271
- "categoryType": sample.categoryType.identifier,
272
- "endDate": endDate,
273
- "startDate": startDate,
274
- "value": sample.value,
275
- "metadata": self.serializeMetadata(metadata: sample.metadata),
276
- "sourceRevision": self.serializeSourceRevision(_sourceRevision: sample.sourceRevision) as Any,
277
- ]
278
- }
279
-
280
- func serializeSource(source: HKSource) -> NSDictionary {
281
-
282
- return [
283
- "bundleIdentifier": source.bundleIdentifier,
284
- "name": source.name
285
- ]
286
- }
287
-
288
103
  @objc(getBiologicalSex:withRejecter:)
289
- func getBiologicalSex(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
104
+ func getBiologicalSex(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
290
105
  guard let store = _store else {
291
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
106
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
292
107
  }
293
108
 
294
109
  do {
295
- let bioSex = try store.biologicalSex();
296
- resolve(bioSex.biologicalSex.rawValue);
110
+ let bioSex = try store.biologicalSex()
111
+ resolve(bioSex.biologicalSex.rawValue)
297
112
  } catch {
298
- reject(GENERIC_ERROR, error.localizedDescription, error);
113
+ reject(GENERIC_ERROR, error.localizedDescription, error)
299
114
  }
300
115
  }
301
116
 
302
117
  @objc(getDateOfBirth:withRejecter:)
303
- func getDateOfBirth(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
118
+ func getDateOfBirth(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
304
119
  guard let store = _store else {
305
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
120
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
306
121
  }
307
122
 
308
123
  do {
309
- let dateOfBirth = try store.dateOfBirth();
310
- resolve(_dateFormatter.string(from: dateOfBirth));
124
+ let dateOfBirth = try store.dateOfBirth()
125
+ resolve(_dateFormatter.string(from: dateOfBirth))
311
126
  } catch {
312
- reject(GENERIC_ERROR, error.localizedDescription, error);
127
+ reject(GENERIC_ERROR, error.localizedDescription, error)
313
128
  }
314
129
  }
315
130
 
316
131
  @objc(getBloodType:withRejecter:)
317
- func getBloodType(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
132
+ func getBloodType(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
318
133
  guard let store = _store else {
319
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
134
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
320
135
  }
321
136
 
322
137
  do {
323
- let bloodType = try store.bloodType();
324
- resolve(bloodType.bloodType.rawValue);
138
+ let bloodType = try store.bloodType()
139
+ resolve(bloodType.bloodType.rawValue)
325
140
  } catch {
326
- reject(GENERIC_ERROR, error.localizedDescription, error);
141
+ reject(GENERIC_ERROR, error.localizedDescription, error)
327
142
  }
328
143
  }
329
144
 
330
145
  @objc(getFitzpatrickSkinType:withRejecter:)
331
- func getFitzpatrickSkinType(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
146
+ func getFitzpatrickSkinType(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
332
147
  guard let store = _store else {
333
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
148
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
334
149
  }
335
150
 
336
151
  do {
337
- let fitzpatrickSkinType = try store.fitzpatrickSkinType();
338
- resolve(fitzpatrickSkinType.skinType.rawValue);
152
+ let fitzpatrickSkinType = try store.fitzpatrickSkinType()
153
+ resolve(fitzpatrickSkinType.skinType.rawValue)
339
154
  } catch {
340
- reject(GENERIC_ERROR, error.localizedDescription, error);
155
+ reject(GENERIC_ERROR, error.localizedDescription, error)
341
156
  }
342
157
  }
343
158
 
344
-
345
159
  @available(iOS 10.0, *)
346
160
  @objc(getWheelchairUse:withRejecter:)
347
- func getWheelchairUse(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
161
+ func getWheelchairUse(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
348
162
  guard let store = _store else {
349
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
163
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
350
164
  }
351
165
 
352
166
  do {
353
- let wheelchairUse = try store.wheelchairUse();
354
- resolve(wheelchairUse.wheelchairUse.rawValue);
167
+ let wheelchairUse = try store.wheelchairUse()
168
+ resolve(wheelchairUse.wheelchairUse.rawValue)
355
169
  } catch {
356
- reject(GENERIC_ERROR, error.localizedDescription, error);
170
+ reject(GENERIC_ERROR, error.localizedDescription, error)
357
171
  }
358
172
  }
359
173
 
360
174
  @objc(authorizationStatusFor:withResolver:withRejecter:)
361
- func authorizationStatusFor(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
175
+ func authorizationStatusFor(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
362
176
  guard let store = _store else {
363
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
177
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
364
178
  }
365
179
 
366
180
  guard let objectType = objectTypeFromString(typeIdentifier: typeIdentifier) else {
367
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
181
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
368
182
  }
369
183
 
370
- let authStatus = store.authorizationStatus(for: objectType);
371
- resolve(authStatus.rawValue);
184
+ let authStatus = store.authorizationStatus(for: objectType)
185
+ resolve(authStatus.rawValue)
372
186
  }
373
187
 
374
188
  @objc(saveQuantitySample:unitString:value:start:end:metadata:resolve:reject:)
375
- func saveQuantitySample(typeIdentifier: String, unitString: String, value: Double, start: Date, end: Date, metadata: Dictionary<String, Any>, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock){
189
+ func saveQuantitySample(typeIdentifier: String, unitString: String, value: Double, start: Date, end: Date, metadata: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
376
190
  guard let store = _store else {
377
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
191
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
378
192
  }
379
193
 
380
- let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier);
194
+ let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
381
195
 
382
196
  guard let type = HKObjectType.quantityType(forIdentifier: identifier) else {
383
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
197
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
384
198
  }
385
199
 
386
- let unit = HKUnit.init(from: unitString);
387
- let quantity = HKQuantity.init(unit: unit, doubleValue: value);
200
+ let unit = HKUnit.init(from: unitString)
201
+ let quantity = HKQuantity.init(unit: unit, doubleValue: value)
388
202
  let sample = HKQuantitySample.init(
389
203
  type: type,
390
204
  quantity: quantity,
@@ -395,72 +209,72 @@ class ReactNativeHealthkit: RCTEventEmitter {
395
209
 
396
210
  store.save(sample) { (success: Bool, error: Error?) in
397
211
  guard let err = error else {
398
- return resolve(success);
212
+ return resolve(success)
399
213
  }
400
- reject(GENERIC_ERROR, err.localizedDescription, error);
214
+ reject(GENERIC_ERROR, err.localizedDescription, error)
401
215
  }
402
216
  }
403
217
 
404
218
  @objc(deleteQuantitySample:uuid:resolve:reject:)
405
- func deleteQuantitySample(typeIdentifier: String, uuid: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock){
219
+ func deleteQuantitySample(typeIdentifier: String, uuid: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
406
220
  guard let store = _store else {
407
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
221
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
408
222
  }
409
223
 
410
- let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier);
411
- let sampleUuid = UUID.init(uuidString: uuid)!;
224
+ let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
225
+ let sampleUuid = UUID.init(uuidString: uuid)!
412
226
 
413
227
  guard let sampleType = HKObjectType.quantityType(forIdentifier: identifier) else {
414
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
228
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
415
229
  }
416
230
 
417
- let samplePredicate = HKQuery.predicateForObject(with: sampleUuid);
231
+ let samplePredicate = HKQuery.predicateForObject(with: sampleUuid)
418
232
 
419
- store.deleteObjects(of: sampleType, predicate: samplePredicate) { (success: Bool, deletedObjectCount: Int, error: Error?) in
233
+ store.deleteObjects(of: sampleType, predicate: samplePredicate) { (success: Bool, _: Int, error: Error?) in
420
234
  guard let err = error else {
421
- return resolve(success);
235
+ return resolve(success)
422
236
  }
423
- reject(GENERIC_ERROR, err.localizedDescription, error);
237
+ reject(GENERIC_ERROR, err.localizedDescription, error)
424
238
  }
425
239
  }
426
240
 
427
241
  @objc(deleteSamples:start:end:resolve:reject:)
428
- func deleteSamples(typeIdentifier: String, start: Date, end: Date, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock){
242
+ func deleteSamples(typeIdentifier: String, start: Date, end: Date, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
429
243
  guard let store = _store else {
430
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
244
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
431
245
  }
432
246
 
433
- let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier);
247
+ let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
434
248
 
435
249
  guard let sampleType = HKObjectType.quantityType(forIdentifier: identifier) else {
436
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
250
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
437
251
  }
438
252
 
439
- let samplePredicate = HKQuery.predicateForSamples(withStart: start, end: end, options: HKQueryOptions.strictStartDate);
253
+ let samplePredicate = HKQuery.predicateForSamples(withStart: start, end: end, options: HKQueryOptions.strictStartDate)
440
254
 
441
- store.deleteObjects(of: sampleType, predicate: samplePredicate) { (success: Bool, deletedObjectCount: Int, error: Error?) in
255
+ store.deleteObjects(of: sampleType, predicate: samplePredicate) { (success: Bool, _: Int, error: Error?) in
442
256
  guard let err = error else {
443
- return resolve(success);
257
+ return resolve(success)
444
258
  }
445
- reject(GENERIC_ERROR, err.localizedDescription, error);
259
+ reject(GENERIC_ERROR, err.localizedDescription, error)
446
260
  }
447
261
  }
448
262
 
449
263
  @objc(saveCorrelationSample:samples:start:end:metadata:resolve:reject:)
450
- func saveCorrelationSample(typeIdentifier: String, samples: Array<Dictionary<String, Any>>, start: Date, end: Date, metadata: Dictionary<String, Any>, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock){
264
+ func saveCorrelationSample(typeIdentifier: String, samples: [[String: Any]], start: Date, end: Date, metadata: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
451
265
  guard let store = _store else {
452
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
266
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
453
267
  }
454
268
 
455
- let identifier = HKCorrelationTypeIdentifier.init(rawValue: typeIdentifier);
269
+ let identifier = HKCorrelationTypeIdentifier.init(rawValue: typeIdentifier)
456
270
 
457
271
  guard let type = HKObjectType.correlationType(forIdentifier: identifier) else {
458
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
272
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
459
273
  }
460
274
 
461
- var initializedSamples = Set<HKSample>();
275
+ var initializedSamples = Set<HKSample>()
462
276
  for sample in samples {
463
- if(sample.keys.contains("quantityType")){
277
+ if sample.keys.contains("quantityType") {
464
278
  let typeId = HKQuantityTypeIdentifier.init(rawValue: sample["quantityType"] as! String)
465
279
  if let type = HKSampleType.quantityType(forIdentifier: typeId) {
466
280
  let unitStr = sample["unit"] as! String
@@ -472,14 +286,14 @@ class ReactNativeHealthkit: RCTEventEmitter {
472
286
  let quantitySample = HKQuantitySample.init(type: type, quantity: quantity, start: start, end: end, metadata: metadata)
473
287
  initializedSamples.insert(quantitySample)
474
288
  }
475
- } else if(sample.keys.contains("categoryType")){
289
+ } else if sample.keys.contains("categoryType") {
476
290
  let typeId = HKCategoryTypeIdentifier.init(rawValue: sample["categoryType"] as! String)
477
291
  if let type = HKSampleType.categoryType(forIdentifier: typeId) {
478
292
  let value = sample["value"] as! Int
479
293
  let metadata = sample["metadata"] as? [String: Any]
480
294
 
481
295
  let categorySample = HKCategorySample.init(type: type, value: value, start: start, end: end, metadata: metadata)
482
- initializedSamples.insert(categorySample);
296
+ initializedSamples.insert(categorySample)
483
297
  }
484
298
  }
485
299
 
@@ -489,23 +303,23 @@ class ReactNativeHealthkit: RCTEventEmitter {
489
303
 
490
304
  store.save(correlation) { (success: Bool, error: Error?) in
491
305
  guard let err = error else {
492
- return resolve(success);
306
+ return resolve(success)
493
307
  }
494
- reject(GENERIC_ERROR, err.localizedDescription, error);
308
+ reject(GENERIC_ERROR, err.localizedDescription, error)
495
309
  }
496
310
  }
497
311
 
498
312
  @objc(saveWorkoutSample:quantities:start:end:metadata:resolve:reject:)
499
- func saveWorkoutSample(typeIdentifier: UInt, quantities: Array<Dictionary<String, Any>>, start: Date, end: Date, metadata: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock){
313
+ func saveWorkoutSample(typeIdentifier: UInt, quantities: [[String: Any]], start: Date, end: Date, metadata: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
500
314
  guard let store = _store else {
501
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
315
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
502
316
  }
503
317
 
504
318
  guard let type = HKWorkoutActivityType.init(rawValue: typeIdentifier) else {
505
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier.description, nil);
319
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier.description, nil)
506
320
  }
507
321
 
508
- var initializedSamples = [HKSample]();
322
+ var initializedSamples = [HKSample]()
509
323
  var totalEnergyBurned: HKQuantity?
510
324
  var totalDistance: HKQuantity?
511
325
  var totalSwimmingStrokeCount: HKQuantity?
@@ -520,78 +334,76 @@ class ReactNativeHealthkit: RCTEventEmitter {
520
334
 
521
335
  let unit = HKUnit.init(from: unitStr)
522
336
  let quantity = HKQuantity.init(unit: unit, doubleValue: quantityVal)
523
- if(quantity.is(compatibleWith: HKUnit.kilocalorie())){
524
- totalEnergyBurned = quantity;
337
+ if quantity.is(compatibleWith: HKUnit.kilocalorie()) {
338
+ totalEnergyBurned = quantity
525
339
  }
526
- if(quantity.is(compatibleWith: HKUnit.meter())){
527
- totalDistance = quantity;
340
+ if quantity.is(compatibleWith: HKUnit.meter()) {
341
+ totalDistance = quantity
528
342
  }
529
- if(typeId == HKQuantityTypeIdentifier.swimmingStrokeCount){
530
- totalSwimmingStrokeCount = quantity;
343
+ if typeId == HKQuantityTypeIdentifier.swimmingStrokeCount {
344
+ totalSwimmingStrokeCount = quantity
531
345
  }
532
- if(typeId == HKQuantityTypeIdentifier.flightsClimbed){
533
- totalFlightsClimbed = quantity;
346
+ if typeId == HKQuantityTypeIdentifier.flightsClimbed {
347
+ totalFlightsClimbed = quantity
534
348
  }
535
349
  let quantitySample = HKQuantitySample.init(type: type, quantity: quantity, start: start, end: end, metadata: metadata)
536
350
  initializedSamples.append(quantitySample)
537
351
  }
538
352
  }
539
353
 
540
- var workout: HKWorkout?;
354
+ var workout: HKWorkout?
541
355
 
542
-
543
- if(totalSwimmingStrokeCount != nil){
356
+ if totalSwimmingStrokeCount != nil {
544
357
  workout = HKWorkout.init(activityType: type, start: start, end: end, workoutEvents: nil, totalEnergyBurned: totalEnergyBurned, totalDistance: totalDistance, totalSwimmingStrokeCount: totalSwimmingStrokeCount, device: nil, metadata: metadata)
545
358
  } else {
546
359
  if #available(iOS 11, *) {
547
- if (totalFlightsClimbed != nil ){
360
+ if totalFlightsClimbed != nil {
548
361
  workout = HKWorkout.init(activityType: type, start: start, end: end, workoutEvents: nil, totalEnergyBurned: totalEnergyBurned, totalDistance: totalDistance, totalFlightsClimbed: totalFlightsClimbed, device: nil, metadata: metadata)
549
362
  }
550
363
  }
551
364
  }
552
365
 
553
- if(workout == nil){
366
+ if workout == nil {
554
367
  workout = HKWorkout.init(activityType: type, start: start, end: end, workoutEvents: nil, totalEnergyBurned: totalEnergyBurned, totalDistance: totalDistance, metadata: metadata)
555
368
  }
556
369
 
557
370
  store.save(workout!) { (success: Bool, error: Error?) in
558
371
  guard let err = error else {
559
- if(success){
372
+ if success {
560
373
  store.add(initializedSamples, to: workout!) { (success, error: Error?) in
561
374
  guard let err = error else {
562
- return resolve(success);
375
+ return resolve(success)
563
376
  }
564
- reject(GENERIC_ERROR, err.localizedDescription, error);
377
+ reject(GENERIC_ERROR, err.localizedDescription, error)
565
378
  }
566
- return;
379
+ return
567
380
  }
568
- return resolve(success);
381
+ return resolve(success)
569
382
  }
570
- reject(GENERIC_ERROR, err.localizedDescription, error);
383
+ reject(GENERIC_ERROR, err.localizedDescription, error)
571
384
  }
572
385
 
573
-
574
386
  }
575
387
 
576
388
  @objc(saveCategorySample:value:start:end:metadata:resolve:reject:)
577
- func saveCategorySample(typeIdentifier: String, value: Double, start: Date, end: Date, metadata: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock){
389
+ func saveCategorySample(typeIdentifier: String, value: Double, start: Date, end: Date, metadata: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
578
390
  guard let store = _store else {
579
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
391
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
580
392
  }
581
393
 
582
- let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier);
394
+ let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier)
583
395
 
584
396
  guard let type = HKObjectType.categoryType(forIdentifier: identifier) else {
585
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
397
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
586
398
  }
587
399
 
588
- let sample = HKCategorySample.init(type: type, value: Int(value), start: start, end: end, metadata: metadata as? Dictionary<String, Any>)
400
+ let sample = HKCategorySample.init(type: type, value: Int(value), start: start, end: end, metadata: metadata as? [String: Any])
589
401
 
590
402
  store.save(sample) { (success: Bool, error: Error?) in
591
403
  guard let err = error else {
592
- return resolve(success);
404
+ return resolve(success)
593
405
  }
594
- reject(GENERIC_ERROR, err.localizedDescription, error);
406
+ reject(GENERIC_ERROR, err.localizedDescription, error)
595
407
  }
596
408
  }
597
409
 
@@ -600,508 +412,337 @@ class ReactNativeHealthkit: RCTEventEmitter {
600
412
  }
601
413
 
602
414
  @objc(enableBackgroundDelivery:updateFrequency:resolve:reject:)
603
- func enableBackgroundDelivery(typeIdentifier: String, updateFrequency: Int, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock){
415
+ func enableBackgroundDelivery(typeIdentifier: String, updateFrequency: Int, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
604
416
  guard let store = _store else {
605
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
417
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
606
418
  }
607
419
 
608
420
  guard let sampleType = objectTypeFromString(typeIdentifier: typeIdentifier) else {
609
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
421
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
610
422
  }
611
423
 
612
424
  guard let frequency = HKUpdateFrequency.init(rawValue: updateFrequency) else {
613
- return reject("UpdateFrequency not valid", "UpdateFrequency not valid", nil);
425
+ return reject("UpdateFrequency not valid", "UpdateFrequency not valid", nil)
614
426
  }
615
427
 
616
- store.enableBackgroundDelivery(for: sampleType, frequency:frequency ) { (success, error) in
428
+ store.enableBackgroundDelivery(for: sampleType, frequency: frequency ) { (success, error) in
617
429
  guard let err = error else {
618
- return resolve(success);
430
+ return resolve(success)
619
431
  }
620
- reject(GENERIC_ERROR, err.localizedDescription, err);
432
+ reject(GENERIC_ERROR, err.localizedDescription, err)
621
433
  }
622
434
  }
623
435
 
624
436
  @objc(disableAllBackgroundDelivery:reject:)
625
- func disableAllBackgroundDelivery(resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock){
437
+ func disableAllBackgroundDelivery(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
626
438
  guard let store = _store else {
627
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
439
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
628
440
  }
629
441
 
630
442
  store.disableAllBackgroundDelivery(completion: { (success, error) in
631
443
  guard let err = error else {
632
- return resolve(success);
444
+ return resolve(success)
633
445
  }
634
- reject(GENERIC_ERROR, err.localizedDescription, err);
446
+ reject(GENERIC_ERROR, err.localizedDescription, err)
635
447
  })
636
448
  }
637
449
 
638
450
  @objc(disableBackgroundDelivery:resolve:reject:)
639
- func disableBackgroundDelivery(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock){
451
+ func disableBackgroundDelivery(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
640
452
  guard let store = _store else {
641
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
453
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
642
454
  }
643
455
 
644
456
  guard let sampleType = objectTypeFromString(typeIdentifier: typeIdentifier) else {
645
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
457
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
646
458
  }
647
459
 
648
-
649
460
  store.disableBackgroundDelivery(for: sampleType) { (success, error) in
650
461
  guard let err = error else {
651
- return resolve(success);
462
+ return resolve(success)
652
463
  }
653
- reject(GENERIC_ERROR, err.localizedDescription, err);
464
+ reject(GENERIC_ERROR, err.localizedDescription, err)
654
465
  }
655
466
  }
656
467
 
657
468
  @objc(subscribeToObserverQuery:resolve:reject:)
658
- func subscribeToObserverQuery(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock){
469
+ func subscribeToObserverQuery(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
659
470
  guard let store = _store else {
660
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
471
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
661
472
  }
662
473
 
663
474
  guard let sampleType = sampleTypeFromString(typeIdentifier: typeIdentifier) else {
664
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
475
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
665
476
  }
666
477
 
667
478
  let predicate = HKQuery.predicateForSamples(withStart: Date.init(), end: nil, options: HKQueryOptions.strictStartDate)
668
479
 
669
480
  let queryId = UUID().uuidString
670
481
 
671
- func responder(query: HKObserverQuery, handler: @escaping HKObserverQueryCompletionHandler, error: Error?) -> Void {
672
- if(error == nil){
482
+ func responder(query: HKObserverQuery, handler: @escaping HKObserverQueryCompletionHandler, error: Error?) {
483
+ if error == nil {
673
484
  DispatchQueue.main.async {
674
- if(self.bridge != nil && self.bridge.isValid){
485
+ if self.bridge != nil && self.bridge.isValid {
675
486
  self.sendEvent(withName: "onChange", body: [
676
- "typeIdentifier": typeIdentifier,
677
- ]);
487
+ "typeIdentifier": typeIdentifier
488
+ ])
678
489
  }
679
490
 
680
491
  }
681
- handler();
492
+ handler()
682
493
  }
683
494
  }
684
495
 
685
496
  let query = HKObserverQuery(sampleType: sampleType, predicate: predicate) { (query: HKObserverQuery, handler: @escaping HKObserverQueryCompletionHandler, error: Error?) in
686
497
  guard let err = error else {
687
- return responder(query: query, handler: handler, error: error);
498
+ return responder(query: query, handler: handler, error: error)
688
499
  }
689
- reject(GENERIC_ERROR, err.localizedDescription, err);
500
+ reject(GENERIC_ERROR, err.localizedDescription, err)
690
501
  }
691
502
 
692
- store.execute(query);
503
+ store.execute(query)
693
504
 
694
- self._runningQueries.updateValue(query, forKey: queryId);
505
+ self._runningQueries.updateValue(query, forKey: queryId)
695
506
  }
696
507
 
697
508
  @objc(unsubscribeQuery:resolve:reject:)
698
- func unsubscribeQuery(queryId: String, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) {
509
+ func unsubscribeQuery(queryId: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
699
510
  guard let store = _store else {
700
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
511
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
701
512
  }
702
513
 
703
514
  guard let query = self._runningQueries[queryId] else {
704
- reject("Error", "Query with id " + queryId + " not found", nil);
705
- return;
515
+ reject("Error", "Query with id " + queryId + " not found", nil)
516
+ return
706
517
  }
707
518
 
708
- store.stop(query);
519
+ store.stop(query)
709
520
 
710
- self._runningQueries.removeValue(forKey: queryId);
521
+ self._runningQueries.removeValue(forKey: queryId)
711
522
 
712
- resolve(true);
523
+ resolve(true)
713
524
  }
714
525
 
715
-
716
526
  static override func requiresMainQueueSetup() -> Bool {
717
527
  return true
718
528
  }
719
529
 
720
530
  @objc(queryStatisticsForQuantity:unitString:from:to:options:resolve:reject:)
721
- func queryStatisticsForQuantity(typeIdentifier: String, unitString: String, from: Date, to: Date, options: NSArray, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
531
+ func queryStatisticsForQuantity(typeIdentifier: String, unitString: String, from: Date, to: Date, options: NSArray, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
722
532
  guard let store = _store else {
723
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
533
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
724
534
  }
725
535
 
726
- let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier);
536
+ let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
727
537
  guard let quantityType = HKObjectType.quantityType(forIdentifier: identifier) else {
728
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
538
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
729
539
  }
730
540
 
731
541
  let predicate = HKQuery.predicateForSamples(withStart: from, end: to, options: HKQueryOptions.strictEndDate)
732
542
 
733
- var opts = HKStatisticsOptions.init();
543
+ var opts = HKStatisticsOptions.init()
734
544
 
735
545
  for o in options {
736
- let str = o as! String;
737
- if(str == "cumulativeSum"){
546
+ let str = o as! String
547
+ if str == "cumulativeSum" {
738
548
  opts.insert(HKStatisticsOptions.cumulativeSum)
739
- }
740
- else if(str == "discreteAverage"){
549
+ } else if str == "discreteAverage" {
741
550
  opts.insert(HKStatisticsOptions.discreteAverage)
742
- }else if(str == "discreteMax"){
551
+ } else if str == "discreteMax" {
743
552
  opts.insert(HKStatisticsOptions.discreteMax)
744
- }
745
- else if(str == "discreteMin"){
553
+ } else if str == "discreteMin" {
746
554
  opts.insert(HKStatisticsOptions.discreteMin)
747
555
  }
748
556
  if #available(iOS 12, *) {
749
- if(str == "discreteMostRecent"){
557
+ if str == "discreteMostRecent" {
750
558
  opts.insert(HKStatisticsOptions.discreteMostRecent)
751
559
  }
752
560
  }
753
561
  if #available(iOS 13, *) {
754
- if(str == "duration"){
562
+ if str == "duration" {
755
563
  opts.insert(HKStatisticsOptions.duration)
756
564
  }
757
- if(str == "mostRecent"){
565
+ if str == "mostRecent" {
758
566
  opts.insert(HKStatisticsOptions.mostRecent)
759
567
  }
760
568
  }
761
569
 
762
- if(str == "separateBySource"){
570
+ if str == "separateBySource" {
763
571
  opts.insert(HKStatisticsOptions.separateBySource)
764
572
  }
765
573
  }
766
574
 
767
- let query = HKStatisticsQuery.init(quantityType: quantityType, quantitySamplePredicate: predicate, options: opts) { (query, stats: HKStatistics?, error: Error?) in
575
+ let query = HKStatisticsQuery.init(quantityType: quantityType, quantitySamplePredicate: predicate, options: opts) { (_, stats: HKStatistics?, _: Error?) in
768
576
  if let gottenStats = stats {
769
- var dic = Dictionary<String, Dictionary<String, Any>?>()
770
- let unit = HKUnit.init(from: unitString);
577
+ var dic = [String: [String: Any]?]()
578
+ let unit = HKUnit.init(from: unitString)
771
579
  if let averageQuantity = gottenStats.averageQuantity() {
772
- dic.updateValue(self.serializeQuantity(unit: unit, quantity: averageQuantity), forKey: "averageQuantity")
580
+ dic.updateValue(serializeQuantity(unit: unit, quantity: averageQuantity), forKey: "averageQuantity")
773
581
  }
774
582
  if let maximumQuantity = gottenStats.maximumQuantity() {
775
- dic.updateValue(self.serializeQuantity(unit: unit, quantity: maximumQuantity), forKey: "maximumQuantity")
583
+ dic.updateValue(serializeQuantity(unit: unit, quantity: maximumQuantity), forKey: "maximumQuantity")
776
584
  }
777
585
  if let minimumQuantity = gottenStats.minimumQuantity() {
778
- dic.updateValue(self.serializeQuantity(unit: unit, quantity: minimumQuantity), forKey: "minimumQuantity")
586
+ dic.updateValue(serializeQuantity(unit: unit, quantity: minimumQuantity), forKey: "minimumQuantity")
779
587
  }
780
588
  if let sumQuantity = gottenStats.sumQuantity() {
781
- dic.updateValue(self.serializeQuantity(unit: unit, quantity: sumQuantity), forKey: "sumQuantity")
589
+ dic.updateValue(serializeQuantity(unit: unit, quantity: sumQuantity), forKey: "sumQuantity")
782
590
  }
783
591
  if #available(iOS 12, *) {
784
592
  if let mostRecent = gottenStats.mostRecentQuantity() {
785
- dic.updateValue(self.serializeQuantity(unit: unit, quantity: mostRecent), forKey: "mostRecentQuantity")
593
+ dic.updateValue(serializeQuantity(unit: unit, quantity: mostRecent), forKey: "mostRecentQuantity")
786
594
  }
787
595
 
788
596
  if let mostRecentDateInterval = gottenStats.mostRecentQuantityDateInterval() {
789
597
  dic.updateValue([
790
598
  "start": self._dateFormatter.string(from: mostRecentDateInterval.start),
791
- "end": self._dateFormatter.string(from: mostRecentDateInterval.end),
599
+ "end": self._dateFormatter.string(from: mostRecentDateInterval.end)
792
600
  ], forKey: "mostRecentQuantityDateInterval")
793
601
  }
794
602
  }
795
603
  if #available(iOS 13, *) {
796
- let durationUnit = HKUnit.second();
604
+ let durationUnit = HKUnit.second()
797
605
  if let duration = gottenStats.duration() {
798
- dic.updateValue(self.serializeQuantity(unit: durationUnit, quantity: duration), forKey: "duration")
606
+ dic.updateValue(serializeQuantity(unit: durationUnit, quantity: duration), forKey: "duration")
799
607
  }
800
608
  }
801
609
 
802
- resolve(dic);
803
- }
804
- }
805
-
806
- store.execute(query);
807
- }
808
-
809
- func serializeUnknownQuantity(quantity: HKQuantity) -> Dictionary<String, Any>? {
810
- if(quantity.is(compatibleWith: HKUnit.percent())){
811
- return self.serializeQuantity(unit: HKUnit.percent(), quantity: quantity);
812
- }
813
-
814
- if(quantity.is(compatibleWith: HKUnit.second())){
815
- return self.serializeQuantity(unit: HKUnit.second(), quantity: quantity);
816
- }
817
-
818
- if(quantity.is(compatibleWith: HKUnit.kilocalorie())){
819
- return self.serializeQuantity(unit: HKUnit.kilocalorie(), quantity: quantity);
820
- }
821
-
822
- if(quantity.is(compatibleWith: HKUnit.count())){
823
- return self.serializeQuantity(unit: HKUnit.count(), quantity: quantity)
824
- }
825
-
826
- if(quantity.is(compatibleWith: HKUnit.meter())){
827
- return self.serializeQuantity(unit: HKUnit.meter(), quantity: quantity)
828
- }
829
-
830
- if #available(iOS 11, *) {
831
- if(quantity.is(compatibleWith: HKUnit.internationalUnit())){
832
- return self.serializeQuantity(unit: HKUnit.internationalUnit(), quantity: quantity);
833
- }
834
- }
835
-
836
- if #available(iOS 13, *) {
837
- if(quantity.is(compatibleWith: HKUnit.hertz())){
838
- return self.serializeQuantity(unit: HKUnit.hertz(), quantity: quantity);
839
- }
840
- if(quantity.is(compatibleWith: HKUnit.decibelHearingLevel())){
841
- return self.serializeQuantity(unit: HKUnit.decibelHearingLevel(), quantity: quantity);
842
- }
843
- }
844
-
845
- if(quantity.is(compatibleWith: SpeedUnit)){
846
- return self.serializeQuantity(unit: SpeedUnit, quantity: quantity);
847
- }
848
-
849
- if(quantity.is(compatibleWith: METUnit)){
850
- return self.serializeQuantity(unit: METUnit, quantity: quantity);
851
- }
852
-
853
- return nil;
854
- }
855
-
856
- func serializeMetadata(metadata: [String: Any]?) -> NSDictionary {
857
- let serialized: NSMutableDictionary = [:];
858
- if let m = metadata {
859
- for item in m {
860
- if let bool = item.value as? Bool {
861
- serialized.setValue(bool, forKey: item.key)
862
- }
863
- if let str = item.value as? String {
864
- serialized.setValue(str, forKey: item.key)
865
- }
866
-
867
- if let double = item.value as? Double {
868
- serialized.setValue(double, forKey: item.key)
869
- }
870
- if let quantity = item.value as? HKQuantity {
871
- if let s = serializeUnknownQuantity(quantity: quantity) {
872
- serialized.setValue(s, forKey: item.key)
873
- }
874
- }
610
+ resolve(dic)
875
611
  }
876
612
  }
877
- return serialized;
878
- }
879
-
880
- func serializeDevice(_device: HKDevice?) -> Dictionary<String, String?>? {
881
- guard let device = _device else {
882
- return nil;
883
- }
884
-
885
- return [
886
- "name": device.name,
887
- "firmwareVersion": device.firmwareVersion,
888
- "hardwareVersion": device.hardwareVersion,
889
- "localIdentifier": device.localIdentifier,
890
- "manufacturer": device.manufacturer,
891
- "model": device.model,
892
- "softwareVersion": device.softwareVersion,
893
- "udiDeviceIdentifier": device.udiDeviceIdentifier
894
- ]
895
- }
896
-
897
- func serializeOperatingSystemVersion(_version: OperatingSystemVersion?) -> String? {
898
- guard let version = _version else {
899
- return nil;
900
- }
901
-
902
- let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)";
903
-
904
- return versionString;
905
- }
906
-
907
- func serializeSourceRevision(_sourceRevision: HKSourceRevision?) -> Dictionary<String, Any?>? {
908
- guard let sourceRevision = _sourceRevision else {
909
- return nil;
910
- }
911
-
912
- var dict = [
913
- "source": [
914
- "name": sourceRevision.source.name,
915
- "bundleIdentifier": sourceRevision.source.bundleIdentifier
916
- ],
917
- "version": sourceRevision.version as Any
918
- ] as [String : Any];
919
613
 
920
- if #available(iOS 11, *) {
921
- dict["operatingSystemVersion"] = self.serializeOperatingSystemVersion(_version: sourceRevision.operatingSystemVersion);
922
- dict["productType"] = sourceRevision.productType;
923
- }
924
-
925
- return dict;
614
+ store.execute(query)
926
615
  }
927
616
 
928
617
  @objc(queryWorkoutSamples:distanceUnitString:from:to:limit:ascending:resolve:reject:)
929
- func queryWorkoutSamples(energyUnitString: String, distanceUnitString: String, from: Date, to: Date, limit: Int, ascending: Bool, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
618
+ func queryWorkoutSamples(energyUnitString: String, distanceUnitString: String, from: Date, to: Date, limit: Int, ascending: Bool, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
930
619
  guard let store = _store else {
931
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
620
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
932
621
  }
933
622
 
934
- let from = from.timeIntervalSince1970 > 0 ? from : nil;
935
- let to = to.timeIntervalSince1970 > 0 ? to : nil;
623
+ let from = dateOrNilIfZero(date: from)
624
+ let to = dateOrNilIfZero(date: to)
936
625
 
937
- let predicate = from != nil || to != nil ? HKQuery.predicateForSamples(withStart: from, end: to, options: [HKQueryOptions.strictEndDate, HKQueryOptions.strictStartDate]) : nil;
626
+ let predicate = createPredicate(from: from, to: to)
938
627
 
939
- let limit = limit == 0 ? HKObjectQueryNoLimit : limit;
628
+ let limit = limitOrNilIfZero(limit: limit)
940
629
 
941
630
  let energyUnit = HKUnit.init(from: energyUnitString)
942
631
  let distanceUnit = HKUnit.init(from: distanceUnitString)
943
632
 
944
- let q = HKSampleQuery(sampleType: .workoutType(), predicate: predicate, limit: limit, sortDescriptors: [NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: ascending)]) { (query: HKSampleQuery, sample: [HKSample]?, error: Error?) in
633
+ let q = HKSampleQuery(sampleType: .workoutType(), predicate: predicate, limit: limit, sortDescriptors: getSortDescriptors(ascending: ascending)) { (_: HKSampleQuery, sample: [HKSample]?, error: Error?) in
945
634
  guard let err = error else {
946
635
  guard let samples = sample else {
947
- return resolve([]);
636
+ return resolve([])
948
637
  }
949
- let arr: NSMutableArray = [];
638
+ let arr: NSMutableArray = []
950
639
 
951
640
  for s in samples {
952
641
  if let workout = s as? HKWorkout {
953
642
  let endDate = self._dateFormatter.string(from: workout.endDate)
954
- let startDate = self._dateFormatter.string(from: workout.startDate);
643
+ let startDate = self._dateFormatter.string(from: workout.startDate)
955
644
 
956
645
  let dict: NSMutableDictionary = [
957
646
  "uuid": workout.uuid.uuidString,
958
- "device": self.serializeDevice(_device: workout.device) as Any,
647
+ "device": serializeDevice(_device: workout.device) as Any,
959
648
  "duration": workout.duration,
960
- "totalDistance": self.serializeQuantity(unit: distanceUnit, quantity: workout.totalDistance) as Any,
961
- "totalEnergyBurned": self.serializeQuantity(unit: energyUnit, quantity: workout.totalEnergyBurned) as Any,
962
- "totalSwimmingStrokeCount": self.serializeQuantity(unit: HKUnit.count(), quantity: workout.totalSwimmingStrokeCount) as Any,
649
+ "totalDistance": serializeQuantity(unit: distanceUnit, quantity: workout.totalDistance) as Any,
650
+ "totalEnergyBurned": serializeQuantity(unit: energyUnit, quantity: workout.totalEnergyBurned) as Any,
651
+ "totalSwimmingStrokeCount": serializeQuantity(unit: HKUnit.count(), quantity: workout.totalSwimmingStrokeCount) as Any,
963
652
  "workoutActivityType": workout.workoutActivityType.rawValue,
964
653
  "startDate": startDate,
965
654
  "endDate": endDate,
966
- "metadata": self.serializeMetadata(metadata: workout.metadata),
967
- "sourceRevision": self.serializeSourceRevision(_sourceRevision: workout.sourceRevision) as Any
655
+ "metadata": serializeMetadata(metadata: workout.metadata),
656
+ "sourceRevision": serializeSourceRevision(_sourceRevision: workout.sourceRevision) as Any
968
657
  ]
969
658
 
970
659
  if #available(iOS 11, *) {
971
- dict.setValue(self.serializeQuantity(unit: HKUnit.count(), quantity: workout.totalFlightsClimbed), forKey: "totalFlightsClimbed")
660
+ dict.setValue(serializeQuantity(unit: HKUnit.count(), quantity: workout.totalFlightsClimbed), forKey: "totalFlightsClimbed")
972
661
  }
973
662
 
974
663
  arr.add(dict)
975
664
  }
976
665
  }
977
666
 
978
- return resolve(arr);
667
+ return resolve(arr)
979
668
  }
980
- reject(GENERIC_ERROR, err.localizedDescription, err);
669
+ reject(GENERIC_ERROR, err.localizedDescription, err)
981
670
  }
982
671
 
983
- store.execute(q);
984
- }
985
-
986
- func serializeAnchor(anchor: HKQueryAnchor?) -> String? {
987
- guard let anch = anchor else {
988
- return nil
989
- }
990
-
991
- let data = NSKeyedArchiver.archivedData(withRootObject: anch)
992
- let encoded = data.base64EncodedString();
993
-
994
- return encoded;
995
- }
996
-
997
- func base64StringToHKQueryAnchor(base64String: String) -> HKQueryAnchor? {
998
- // Step 1: Decode the base64 string to a Data object
999
- guard let data = Data(base64Encoded: base64String) else {
1000
- print("Error: Invalid base64 string")
1001
- return nil
1002
- }
1003
-
1004
- // Step 2: Use NSKeyedUnarchiver to unarchive the data and create an HKQueryAnchor object
1005
- do {
1006
- let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data)
1007
- unarchiver.requiresSecureCoding = true
1008
- let anchor = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data)
1009
-
1010
- return anchor as? HKQueryAnchor
1011
- } catch {
1012
- print("Error: Unable to unarchive HKQueryAnchor object: \(error)")
1013
- return nil
672
+ store.execute(q)
1014
673
  }
1015
- }
1016
674
 
1017
- @objc(queryQuantitySamples:unitString:from:to:limit:ascending:anchor:resolve:reject:)
675
+ @objc(queryQuantitySamples:unitString:from:to:limit:ascending:resolve:reject:)
1018
676
  func queryQuantitySamples(
1019
- typeIdentifier: String,
1020
- unitString: String,
1021
- from: Date,
1022
- to: Date,
1023
- limit: Int,
1024
- ascending: Bool,
1025
- anchor: String,
677
+ typeIdentifier: String,
678
+ unitString: String,
679
+ from: Date,
680
+ to: Date,
681
+ limit: Int,
682
+ ascending: Bool,
1026
683
  resolve: @escaping RCTPromiseResolveBlock,
1027
684
  reject: @escaping RCTPromiseRejectBlock
1028
- ) -> Void {
685
+ ) {
1029
686
  guard let store = _store else {
1030
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
687
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
1031
688
  }
1032
689
 
1033
- let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier);
690
+ let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
1034
691
  guard let sampleType = HKSampleType.quantityType(forIdentifier: identifier) else {
1035
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
692
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
1036
693
  }
1037
694
 
1038
- let from = from.timeIntervalSince1970 > 0 ? from : nil;
1039
- let to = to.timeIntervalSince1970 > 0 ? to : nil;
695
+ let from = dateOrNilIfZero(date: from)
696
+ let to = dateOrNilIfZero(date: to)
697
+ let predicate = createPredicate(from: from, to: to)
698
+ let limit = limitOrNilIfZero(limit: limit)
1040
699
 
1041
- let predicate = from != nil || to != nil ? HKQuery.predicateForSamples(withStart: from, end: to, options: [HKQueryOptions.strictEndDate, HKQueryOptions.strictStartDate]) : nil;
700
+ let q = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: limit, sortDescriptors: getSortDescriptors(ascending: ascending)) { (_: HKSampleQuery, sample: [HKSample]?, error: Error?) in
701
+ guard let err = error else {
702
+ guard let samples = sample else {
703
+ return resolve([])
704
+ }
705
+ let arr: NSMutableArray = []
1042
706
 
1043
- let limit = limit == 0 ? HKObjectQueryNoLimit : limit;
1044
-
1045
- let actualAnchor = anchor.isEmpty ? nil : base64StringToHKQueryAnchor(base64String: anchor)
1046
-
1047
- let q = HKAnchoredObjectQuery(
1048
- type: sampleType,
1049
- predicate: predicate,
1050
- anchor: actualAnchor,
1051
- limit: limit
1052
- ) { (
1053
- query: HKAnchoredObjectQuery,
1054
- s: [HKSample]?,
1055
- deletedSamples: [HKDeletedObject]?,
1056
- newAnchor: HKQueryAnchor?,
1057
- error: Error?
1058
- ) in
1059
- guard let err = error else {
1060
- guard let samples = s else {
1061
- return resolve([]);
1062
- }
707
+ for s in samples {
708
+ if let sample = s as? HKQuantitySample {
709
+ let serialized = serializeQuantitySample(sample: sample, unit: HKUnit.init(from: unitString))
1063
710
 
1064
- return resolve([
1065
- "samples": samples.map({ sample in
1066
- let serialized = self.serializeQuantitySample(sample: sample as! HKQuantitySample, unit: HKUnit.init(from: unitString))
711
+ arr.add(serialized)
712
+ }
713
+ }
1067
714
 
1068
- return serialized
1069
- }) as Any,
1070
- "deletedSamples": deletedSamples?.map({ sample in
1071
- return self.serializeDeletedSample(sample: sample)
1072
- }) as Any,
1073
- "newAnchor": self.serializeAnchor(anchor: newAnchor) as Any
1074
- ]);
1075
- }
1076
- reject(GENERIC_ERROR, err.localizedDescription, err);
715
+ return resolve(arr)
716
+ }
717
+ reject(GENERIC_ERROR, err.localizedDescription, err)
1077
718
  }
1078
719
 
1079
- store.execute(q);
720
+ store.execute(q)
1080
721
  }
1081
722
 
1082
723
  @objc(queryCorrelationSamples:from:to:resolve:reject:)
1083
- func queryCorrelationSamples(typeIdentifier: String, from: Date, to: Date, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
724
+ func queryCorrelationSamples(typeIdentifier: String, from: Date, to: Date, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
1084
725
  guard let store = _store else {
1085
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
726
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
1086
727
  }
1087
728
 
1088
- let identifier = HKCorrelationTypeIdentifier.init(rawValue: typeIdentifier);
729
+ let identifier = HKCorrelationTypeIdentifier.init(rawValue: typeIdentifier)
1089
730
  guard let sampleType = HKSampleType.correlationType(forIdentifier: identifier) else {
1090
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
731
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
1091
732
  }
1092
733
 
1093
- let from = from.timeIntervalSince1970 >= 0 ? from : nil;
1094
- let to = to.timeIntervalSince1970 >= 0 ? to : nil;
734
+ let from = from.timeIntervalSince1970 >= 0 ? from : nil
735
+ let to = to.timeIntervalSince1970 >= 0 ? to : nil
1095
736
 
1096
- let predicate = from != nil || to != nil ? HKQuery.predicateForSamples(withStart: from, end: to, options: [HKQueryOptions.strictEndDate, HKQueryOptions.strictStartDate]) : nil;
737
+ let predicate = createPredicate(from: from, to: to)
1097
738
 
1098
- let q = HKCorrelationQuery(type: sampleType, predicate: predicate, samplePredicates: nil) { (query: HKCorrelationQuery, _correlations: [HKCorrelation]?, error: Error?) in
739
+ let q = HKCorrelationQuery(type: sampleType, predicate: predicate, samplePredicates: nil) { (_: HKCorrelationQuery, _correlations: [HKCorrelation]?, error: Error?) in
1099
740
  guard let err = error else {
1100
741
  guard let correlations = _correlations else {
1101
- return resolve([]);
742
+ return resolve([])
1102
743
  }
1103
744
 
1104
- var qts = Set<HKQuantityType>();
745
+ var qts = Set<HKQuantityType>()
1105
746
  for c in correlations {
1106
747
  for object in c.objects {
1107
748
  if let quantitySample = object as? HKQuantitySample {
@@ -1109,67 +750,166 @@ class ReactNativeHealthkit: RCTEventEmitter {
1109
750
  }
1110
751
  }
1111
752
  }
1112
- return store.preferredUnits(for: qts) { (map: [HKQuantityType : HKUnit], error: Error?) in
753
+ return store.preferredUnits(for: qts) { (map: [HKQuantityType: HKUnit], error: Error?) in
1113
754
  guard let e = error else {
1114
- let collerationsToReturn: NSMutableArray = [];
755
+ let collerationsToReturn: NSMutableArray = []
1115
756
  for c in correlations {
1116
- let objects = NSMutableArray();
757
+ let objects = NSMutableArray()
1117
758
  for o in c.objects {
1118
759
  if let quantitySample = o as? HKQuantitySample {
1119
- objects.add(self.serializeQuantitySample(sample: quantitySample, unit: map[quantitySample.quantityType]!))
760
+ objects.add(serializeQuantitySample(sample: quantitySample, unit: map[quantitySample.quantityType]!))
1120
761
  }
1121
762
  if let categorySample = o as? HKCategorySample {
1122
- objects.add(self.serializeCategorySample(sample: categorySample))
763
+ objects.add(serializeCategorySample(sample: categorySample))
1123
764
  }
1124
765
  }
1125
766
 
1126
767
  collerationsToReturn.add([
1127
768
  "uuid": c.uuid.uuidString,
1128
- "device": self.serializeDevice(_device: c.device) as Any,
769
+ "device": serializeDevice(_device: c.device) as Any,
1129
770
  "correlationType": c.correlationType.identifier,
1130
771
  "objects": objects,
1131
- "metadata": self.serializeMetadata(metadata: c.metadata),
772
+ "metadata": serializeMetadata(metadata: c.metadata),
1132
773
  "startDate": self._dateFormatter.string(from: c.startDate),
1133
- "endDate": self._dateFormatter.string(from: c.endDate),
774
+ "endDate": self._dateFormatter.string(from: c.endDate)
1134
775
  ])
1135
776
  }
1136
777
 
1137
- return resolve(collerationsToReturn);
778
+ return resolve(collerationsToReturn)
1138
779
  }
1139
- reject(GENERIC_ERROR, e.localizedDescription, e);
780
+ reject(GENERIC_ERROR, e.localizedDescription, e)
1140
781
  }
1141
782
  }
1142
- reject(GENERIC_ERROR, err.localizedDescription, err);
783
+ reject(GENERIC_ERROR, err.localizedDescription, err)
1143
784
  }
1144
785
 
1145
- store.execute(q);
786
+ store.execute(q)
1146
787
  }
1147
788
 
1148
- @objc(queryCategorySamples:from:to:limit:ascending:anchor:resolve:reject:)
1149
- func queryCategorySamples(typeIdentifier: String, from: Date, to: Date, limit: Int, ascending: Bool, anchor: String, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
789
+ @objc(queryCategorySamples:from:to:limit:ascending:resolve:reject:)
790
+ func queryCategorySamples(typeIdentifier: String, from: Date, to: Date, limit: Int, ascending: Bool, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
1150
791
  guard let store = _store else {
1151
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
792
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
1152
793
  }
1153
794
 
1154
- let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier);
795
+ let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier)
1155
796
  guard let sampleType = HKSampleType.categoryType(forIdentifier: identifier) else {
1156
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
797
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
798
+ }
799
+
800
+ let from = dateOrNilIfZero(date: from)
801
+ let to = dateOrNilIfZero(date: to)
802
+ let predicate = createPredicate(from: from, to: to)
803
+ let limit = limitOrNilIfZero(limit: limit)
804
+
805
+ let q = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: limit, sortDescriptors: getSortDescriptors(ascending: ascending)) { (_: HKSampleQuery, sample: [HKSample]?, error: Error?) in
806
+ guard let err = error else {
807
+ guard let samples = sample else {
808
+ return resolve([])
809
+ }
810
+ let arr: NSMutableArray = []
811
+
812
+ for s in samples {
813
+ if let sample = s as? HKCategorySample {
814
+ let serialized = serializeCategorySample(sample: sample)
815
+
816
+ arr.add(serialized)
817
+ }
818
+ }
819
+ return resolve(arr)
820
+ }
821
+
822
+ reject(GENERIC_ERROR, err.localizedDescription, err)
823
+ }
824
+
825
+ store.execute(q)
826
+ }
827
+
828
+ @objc(queryQuantitySamplesWithAnchor:unitString:from:to:limit:anchor:resolve:reject:)
829
+ func queryQuantitySamplesWithAnchor(
830
+ typeIdentifier: String,
831
+ unitString: String,
832
+ from: Date,
833
+ to: Date,
834
+ limit: Int,
835
+ anchor: String,
836
+ resolve: @escaping RCTPromiseResolveBlock,
837
+ reject: @escaping RCTPromiseRejectBlock
838
+ ) {
839
+ guard let store = _store else {
840
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
841
+ }
842
+
843
+ let identifier = HKQuantityTypeIdentifier.init(rawValue: typeIdentifier)
844
+ guard let sampleType = HKSampleType.quantityType(forIdentifier: identifier) else {
845
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
846
+ }
847
+
848
+ let from = dateOrNilIfZero(date: from)
849
+ let to = dateOrNilIfZero(date: to)
850
+ let predicate = createPredicate(from: from, to: to)
851
+ let limit = limitOrNilIfZero(limit: limit)
852
+
853
+ let actualAnchor = deserializeHKQueryAnchor(anchor: anchor)
854
+
855
+ let q = HKAnchoredObjectQuery(
856
+ type: sampleType,
857
+ predicate: predicate,
858
+ anchor: actualAnchor,
859
+ limit: limit
860
+ ) { (
861
+ _: HKAnchoredObjectQuery,
862
+ s: [HKSample]?,
863
+ deletedSamples: [HKDeletedObject]?,
864
+ newAnchor: HKQueryAnchor?,
865
+ error: Error?
866
+ ) in
867
+ guard let err = error else {
868
+ guard let samples = s else {
869
+ return resolve([])
870
+ }
871
+
872
+ return resolve([
873
+ "samples": samples.map({ sample in
874
+ let serialized = serializeQuantitySample(sample: sample as! HKQuantitySample, unit: HKUnit.init(from: unitString))
875
+
876
+ return serialized
877
+ }) as Any,
878
+ "deletedSamples": deletedSamples?.map({ sample in
879
+ return serializeDeletedSample(sample: sample)
880
+ }) as Any,
881
+ "newAnchor": serializeAnchor(anchor: newAnchor) as Any
882
+ ])
883
+ }
884
+ reject(GENERIC_ERROR, err.localizedDescription, err)
885
+ }
886
+
887
+ store.execute(q)
888
+ }
889
+
890
+ @objc(queryCategorySamplesWithAnchor:from:to:limit:anchor:resolve:reject:)
891
+ func queryCategorySamplesWithAnchor(typeIdentifier: String, from: Date, to: Date, limit: Int, anchor: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
892
+ guard let store = _store else {
893
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
1157
894
  }
1158
895
 
1159
- let from = from.timeIntervalSince1970 > 0 ? from : nil;
1160
- let to = to.timeIntervalSince1970 > 0 ? to : nil;
896
+ let identifier = HKCategoryTypeIdentifier.init(rawValue: typeIdentifier)
897
+ guard let sampleType = HKSampleType.categoryType(forIdentifier: identifier) else {
898
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
899
+ }
1161
900
 
1162
- let predicate = from != nil || to != nil ? HKQuery.predicateForSamples(withStart: from, end: to, options: [HKQueryOptions.strictEndDate, HKQueryOptions.strictStartDate]) : nil;
901
+ let from = dateOrNilIfZero(date: from)
902
+ let to = dateOrNilIfZero(date: to)
903
+ let predicate = createPredicate(from: from, to: to)
904
+ let limit = limitOrNilIfZero(limit: limit)
1163
905
 
1164
- let limit = limit == 0 ? HKObjectQueryNoLimit : limit;
1165
-
1166
906
  let q = HKAnchoredObjectQuery(
1167
907
  type: sampleType,
1168
908
  predicate: predicate,
1169
909
  anchor: anchor != "" ? base64StringToHKQueryAnchor(base64String: anchor) : nil,
1170
910
  limit: limit
1171
911
  ) { (
1172
- query: HKAnchoredObjectQuery,
912
+ _: HKAnchoredObjectQuery,
1173
913
  s: [HKSample]?,
1174
914
  deletedSamples: [HKDeletedObject]?,
1175
915
  newAnchor: HKQueryAnchor?,
@@ -1177,14 +917,14 @@ class ReactNativeHealthkit: RCTEventEmitter {
1177
917
  ) in
1178
918
  guard let err = error else {
1179
919
  guard let samples = s else {
1180
- return resolve([]);
920
+ return resolve([])
1181
921
  }
1182
-
1183
- let arr: NSMutableArray = [];
922
+
923
+ let arr: NSMutableArray = []
1184
924
 
1185
925
  for s in samples {
1186
926
  if let sample = s as? HKCategorySample {
1187
- let serialized = self.serializeCategorySample(sample: sample);
927
+ let serialized = serializeCategorySample(sample: sample)
1188
928
 
1189
929
  arr.add(serialized)
1190
930
  }
@@ -1193,73 +933,73 @@ class ReactNativeHealthkit: RCTEventEmitter {
1193
933
  return resolve([
1194
934
  "samples": arr,
1195
935
  "deletedSamples": deletedSamples?.map({ sample in
1196
- return self.serializeDeletedSample(sample: sample)
936
+ return serializeDeletedSample(sample: sample)
1197
937
  }) as Any,
1198
- "newAnchor": self.serializeAnchor(anchor: newAnchor) as Any
1199
- ]);
938
+ "newAnchor": serializeAnchor(anchor: newAnchor) as Any
939
+ ])
1200
940
  }
1201
- reject(GENERIC_ERROR, err.localizedDescription, err);
941
+ reject(GENERIC_ERROR, err.localizedDescription, err)
1202
942
  }
1203
943
 
1204
- store.execute(q);
944
+ store.execute(q)
1205
945
  }
1206
-
946
+
1207
947
  @objc(querySources:resolve:reject:)
1208
- func querySources(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
1209
-
948
+ func querySources(typeIdentifier: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
949
+
1210
950
  guard let store = _store else {
1211
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
951
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
1212
952
  }
1213
953
 
1214
954
  guard let type = objectTypeFromString(typeIdentifier: typeIdentifier) else {
1215
- return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil);
955
+ return reject(TYPE_IDENTIFIER_ERROR, typeIdentifier, nil)
1216
956
  }
1217
-
1218
- let query = HKSourceQuery(sampleType: type as! HKSampleType, samplePredicate: nil) { (query: HKSourceQuery, source: Set<HKSource>?, error: Error?) in
957
+
958
+ let query = HKSourceQuery(sampleType: type as! HKSampleType, samplePredicate: nil) { (_: HKSourceQuery, source: Set<HKSource>?, error: Error?) in
1219
959
  guard let err = error else {
1220
960
  guard let sources = source else {
1221
- return resolve([]);
961
+ return resolve([])
1222
962
  }
1223
- let arr: NSMutableArray = [];
963
+ let arr: NSMutableArray = []
1224
964
 
1225
965
  for s in sources {
1226
966
  if let source = s as? HKSource {
1227
- let serialized = self.serializeSource(source: source);
967
+ let serialized = serializeSource(source: source)
1228
968
 
1229
969
  arr.add(serialized)
1230
970
  }
1231
971
  }
1232
972
 
1233
- return resolve(arr);
973
+ return resolve(arr)
1234
974
  }
1235
- reject(GENERIC_ERROR, err.localizedDescription, err);
1236
-
975
+ reject(GENERIC_ERROR, err.localizedDescription, err)
976
+
1237
977
  }
1238
978
 
1239
- store.execute(query);
979
+ store.execute(query)
1240
980
  }
1241
981
 
1242
982
  @objc(requestAuthorization:read:resolve:withRejecter:)
1243
- func requestAuthorization(toShare: NSDictionary, read: NSDictionary, resolve: @escaping RCTPromiseResolveBlock,reject: @escaping RCTPromiseRejectBlock) -> Void {
983
+ func requestAuthorization(toShare: NSDictionary, read: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
1244
984
  guard let store = _store else {
1245
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
985
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
1246
986
  }
1247
987
 
1248
- let share = sampleTypesFromDictionary(typeIdentifiers: toShare);
1249
- let toRead = objectTypesFromDictionary(typeIdentifiers: read);
988
+ let share = sampleTypesFromDictionary(typeIdentifiers: toShare)
989
+ let toRead = objectTypesFromDictionary(typeIdentifiers: read)
1250
990
 
1251
991
  store.requestAuthorization(toShare: share, read: toRead) { (success: Bool, error: Error?) in
1252
992
  guard let err = error else {
1253
- return resolve(success);
993
+ return resolve(success)
1254
994
  }
1255
- reject(GENERIC_ERROR, err.localizedDescription, err);
995
+ reject(GENERIC_ERROR, err.localizedDescription, err)
1256
996
  }
1257
997
  }
1258
998
 
1259
999
  @available(iOS 13.0.0, *)
1260
1000
  func getWorkoutByID(store: HKHealthStore,
1261
1001
  workoutUUID: UUID) async -> HKWorkout? {
1262
- let workoutPredicate = HKQuery.predicateForObject(with: workoutUUID);
1002
+ let workoutPredicate = HKQuery.predicateForObject(with: workoutUUID)
1263
1003
 
1264
1004
  let samples = try! await withCheckedThrowingContinuation {
1265
1005
  (continuation: CheckedContinuation<[HKSample], Error>) in
@@ -1267,7 +1007,7 @@ class ReactNativeHealthkit: RCTEventEmitter {
1267
1007
  predicate: workoutPredicate,
1268
1008
  anchor: nil,
1269
1009
  limit: 1) {
1270
- (query, samples, deletedObjects, anchor, error) in
1010
+ (_, samples, _, _, error) in
1271
1011
 
1272
1012
  if let hasError = error {
1273
1013
  continuation.resume(throwing: hasError)
@@ -1290,9 +1030,8 @@ class ReactNativeHealthkit: RCTEventEmitter {
1290
1030
  return workouts.first ?? nil
1291
1031
  }
1292
1032
 
1293
-
1294
1033
  @available(iOS 13.0.0, *)
1295
- func _getWorkoutRoutes(store: HKHealthStore, workoutUUID: UUID) async -> [HKWorkoutRoute]?{
1034
+ func _getWorkoutRoutes(store: HKHealthStore, workoutUUID: UUID) async -> [HKWorkoutRoute]? {
1296
1035
  guard let workout = await getWorkoutByID(store: store, workoutUUID: workoutUUID) else {
1297
1036
  return nil
1298
1037
  }
@@ -1304,7 +1043,7 @@ class ReactNativeHealthkit: RCTEventEmitter {
1304
1043
  predicate: workoutPredicate,
1305
1044
  anchor: nil,
1306
1045
  limit: HKObjectQueryNoLimit) {
1307
- (query, samples, deletedObjects, anchor, error) in
1046
+ (_, samples, _, _, error) in
1308
1047
 
1309
1048
  if let hasError = error {
1310
1049
  continuation.resume(throwing: hasError)
@@ -1334,7 +1073,7 @@ class ReactNativeHealthkit: RCTEventEmitter {
1334
1073
  var allLocations: [CLLocation] = []
1335
1074
 
1336
1075
  let query = HKWorkoutRouteQuery(route: route) {
1337
- (query, locationsOrNil, done, errorOrNil) in
1076
+ (_, locationsOrNil, done, errorOrNil) in
1338
1077
 
1339
1078
  if let error = errorOrNil {
1340
1079
  continuation.resume(throwing: error)
@@ -1367,21 +1106,20 @@ class ReactNativeHealthkit: RCTEventEmitter {
1367
1106
  return nil
1368
1107
  }
1369
1108
  for route in _routes {
1370
- let routeMetadata = self.serializeMetadata(metadata: route.metadata) as! Dictionary<String, Any>
1109
+ let routeMetadata = serializeMetadata(metadata: route.metadata) as! [String: Any]
1371
1110
  let routeCLLocations = (await getRouteLocations(store: store, route: route))
1372
- let routeLocations = routeCLLocations.enumerated().map{(i, loc) in serializeLocation(location: loc, previousLocation: i == 0 ? nil: routeCLLocations[i - 1])}
1373
- let routeInfos: Dictionary<String, Any> = ["locations": routeLocations]
1111
+ let routeLocations = routeCLLocations.enumerated().map {(i, loc) in serializeLocation(location: loc, previousLocation: i == 0 ? nil: routeCLLocations[i - 1])}
1112
+ let routeInfos: [String: Any] = ["locations": routeLocations]
1374
1113
  allRoutes.append(routeInfos.merging(routeMetadata) { (current, _) in current })
1375
1114
  }
1376
1115
  return allRoutes
1377
1116
  }
1378
1117
 
1379
- func serializeLocation(location: CLLocation, previousLocation: CLLocation?) -> Dictionary<String, Any> {
1118
+ func serializeLocation(location: CLLocation, previousLocation: CLLocation?) -> [String: Any] {
1380
1119
  var distance: CLLocationDistance?
1381
1120
  if let previousLocation = previousLocation {
1382
1121
  distance = location.distance(from: previousLocation)
1383
- }
1384
- else {
1122
+ } else {
1385
1123
  distance = nil
1386
1124
  }
1387
1125
  return [
@@ -1402,7 +1140,7 @@ class ReactNativeHealthkit: RCTEventEmitter {
1402
1140
  func getWorkoutRoutes(
1403
1141
  workoutUUID: String,
1404
1142
  resolve: @escaping RCTPromiseResolveBlock,
1405
- reject: @escaping RCTPromiseRejectBlock){
1143
+ reject: @escaping RCTPromiseRejectBlock) {
1406
1144
 
1407
1145
  guard let store = _store else {
1408
1146
  return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
@@ -1416,17 +1154,16 @@ class ReactNativeHealthkit: RCTEventEmitter {
1416
1154
  do {
1417
1155
  let locations = await getSerializedWorkoutLocations(store: store, workoutUUID: _workoutUUID)
1418
1156
  resolve(locations)
1419
- }
1420
- catch {
1157
+ } catch {
1421
1158
  reject("WORKOUT_LOCATION_ERROR", "Failed to retrieve workout locations", nil)
1422
1159
  }
1423
1160
  }
1424
1161
  }
1425
1162
 
1426
- typealias HKAnchoredObjectQueryResult = (samples: [HKSample], deletedSamples: [HKDeletedObject]?, newAnchor: HKQueryAnchor?);
1163
+ typealias HKAnchoredObjectQueryResult = (samples: [HKSample], deletedSamples: [HKDeletedObject]?, newAnchor: HKQueryAnchor?)
1427
1164
 
1428
1165
  @available(iOS 13.0.0, *)
1429
- func _queryHeartbeatSeriesSamples(
1166
+ func _queryHeartbeatSeriesSamplesWithAnchor(
1430
1167
  store: HKHealthStore,
1431
1168
  predicate: NSPredicate?,
1432
1169
  limit: Int,
@@ -1440,123 +1177,192 @@ class ReactNativeHealthkit: RCTEventEmitter {
1440
1177
  anchor: anchor,
1441
1178
  limit: limit
1442
1179
  ) { (
1443
- query: HKAnchoredObjectQuery,
1180
+ _: HKAnchoredObjectQuery,
1444
1181
  s: [HKSample]?,
1445
1182
  deletedSamples: [HKDeletedObject]?,
1446
1183
  newAnchor: HKQueryAnchor?,
1447
1184
  error: Error?
1448
1185
  ) in
1449
1186
  if let err = error {
1450
- continuation.resume(throwing: err);
1187
+ continuation.resume(throwing: err)
1451
1188
  }
1452
1189
 
1453
1190
  guard let samples = s else {
1454
- fatalError("Should not fail");
1191
+ fatalError("Should not fail")
1455
1192
  }
1456
-
1457
- continuation.resume(returning: HKAnchoredObjectQueryResult(samples: samples, deletedSamples: deletedSamples, newAnchor: newAnchor));
1193
+
1194
+ continuation.resume(returning: HKAnchoredObjectQueryResult(samples: samples, deletedSamples: deletedSamples, newAnchor: newAnchor))
1458
1195
  }
1459
-
1460
- store.execute(query);
1196
+
1197
+ store.execute(query)
1461
1198
  }
1462
1199
 
1463
- return queryResult;
1200
+ return queryResult
1464
1201
  }
1465
1202
 
1466
1203
  @available(iOS 13.0.0, *)
1467
1204
  func getHeartbeatSeriesHeartbeats(store: HKHealthStore, sample: HKHeartbeatSeriesSample) async throws -> [Dictionary<String, Any>] {
1468
1205
  let beatTimes = try await withCheckedThrowingContinuation {
1469
1206
  (continuation: CheckedContinuation<[Dictionary<String, Any>], Error>) in
1470
- var allBeats: [Dictionary<String, Any>] = [];
1207
+ var allBeats: [Dictionary<String, Any>] = []
1471
1208
 
1472
1209
  let query = HKHeartbeatSeriesQuery(heartbeatSeries: sample) { (
1473
- query: HKHeartbeatSeriesQuery,
1210
+ _: HKHeartbeatSeriesQuery,
1474
1211
  timeSinceSeriesStart: TimeInterval,
1475
1212
  precededByGap: Bool,
1476
1213
  done: Bool,
1477
1214
  error: Error?
1478
1215
  ) in
1479
1216
  if let err = error {
1480
- continuation.resume(throwing: err);
1217
+ continuation.resume(throwing: err)
1481
1218
  }
1482
1219
 
1483
- let timeDict: Dictionary<String, Any> = [
1220
+ let timeDict: [String: Any] = [
1484
1221
  "timeSinceSeriesStart": timeSinceSeriesStart,
1485
1222
  "precededByGap": precededByGap
1486
- ];
1487
-
1488
- allBeats.append(timeDict);
1223
+ ]
1224
+
1225
+ allBeats.append(timeDict)
1489
1226
 
1490
1227
  if done {
1491
- continuation.resume(returning: allBeats);
1228
+ continuation.resume(returning: allBeats)
1492
1229
  }
1493
1230
  }
1494
-
1495
- store.execute(query);
1231
+
1232
+ store.execute(query)
1496
1233
  }
1497
-
1498
- return beatTimes;
1234
+
1235
+ return beatTimes
1499
1236
  }
1500
1237
 
1501
1238
  @available(iOS 13.0.0, *)
1502
- func getSerializedHeartbeatSeriesSample(store: HKHealthStore, sample: HKHeartbeatSeriesSample) async throws -> Dictionary<String, Any> {
1503
- let sampleMetadata = self.serializeMetadata(metadata: sample.metadata) as! Dictionary<String, Any>;
1504
- let sampleHeartbeats = try await getHeartbeatSeriesHeartbeats(store: store, sample: sample);
1239
+ func getSerializedHeartbeatSeriesSample(store: HKHealthStore, sample: HKHeartbeatSeriesSample) async throws -> [String: Any] {
1240
+ let sampleMetadata = serializeMetadata(metadata: sample.metadata) as! [String: Any]
1241
+ let sampleHeartbeats = try await getHeartbeatSeriesHeartbeats(store: store, sample: sample)
1505
1242
 
1506
1243
  return [
1507
1244
  "uuid": sample.uuid.uuidString,
1508
- "device": self.serializeDevice(_device: sample.device) as Any,
1245
+ "device": serializeDevice(_device: sample.device) as Any,
1509
1246
  "startDate": self._dateFormatter.string(from: sample.startDate),
1510
1247
  "endDate": self._dateFormatter.string(from: sample.endDate),
1511
1248
  "heartbeats": sampleHeartbeats as Any,
1512
- "metadata": self.serializeMetadata(metadata: sample.metadata),
1513
- "sourceRevision": self.serializeSourceRevision(_sourceRevision: sample.sourceRevision) as Any
1514
- ];
1249
+ "metadata": serializeMetadata(metadata: sample.metadata),
1250
+ "sourceRevision": serializeSourceRevision(_sourceRevision: sample.sourceRevision) as Any
1251
+ ]
1515
1252
  }
1516
1253
 
1517
1254
  @available(iOS 13.0.0, *)
1518
- @objc(queryHeartbeatSeriesSamples:to:limit:ascending:anchor:resolve:reject:)
1519
- func queryHeartbeatSeriesSamples(
1255
+ @objc(queryHeartbeatSeriesSamplesWithAnchor:to:limit:anchor:resolve:reject:)
1256
+ func queryHeartbeatSeriesSamplesWithAnchor(
1520
1257
  from: Date,
1521
1258
  to: Date,
1522
1259
  limit: Int,
1523
- ascending: Bool,
1524
1260
  anchor: String,
1525
1261
  resolve: @escaping RCTPromiseResolveBlock,
1526
1262
  reject: @escaping RCTPromiseRejectBlock
1527
1263
  ) {
1528
1264
  guard let store = _store else {
1529
- return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil);
1265
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
1530
1266
  }
1531
1267
 
1532
1268
  Task {
1533
1269
  do {
1534
- let from = from.timeIntervalSince1970 > 0 ? from : nil;
1535
- let to = to.timeIntervalSince1970 > 0 ? to : nil;
1536
-
1537
- let predicate = from != nil || to != nil ? HKQuery.predicateForSamples(withStart: from, end: to, options: [HKQueryOptions.strictEndDate, HKQueryOptions.strictStartDate]) : nil;
1538
-
1539
- let limit = limit == 0 ? HKObjectQueryNoLimit : limit;
1540
-
1541
- let actualAnchor = anchor.isEmpty ? nil : base64StringToHKQueryAnchor(base64String: anchor);
1542
-
1543
- let queryResult = try await _queryHeartbeatSeriesSamples(store: store, predicate: predicate, limit: limit, anchor: actualAnchor);
1544
-
1545
- var allHeartbeatSamples: [Dictionary<String, Any>] = [];
1270
+ let from = dateOrNilIfZero(date: from)
1271
+ let to = dateOrNilIfZero(date: to)
1272
+
1273
+ let predicate = createPredicate(from: from, to: to)
1274
+
1275
+ let limit = limitOrNilIfZero(limit: limit)
1276
+
1277
+ let actualAnchor = deserializeHKQueryAnchor(anchor: anchor)
1278
+
1279
+ let queryResult = try await _queryHeartbeatSeriesSamplesWithAnchor(store: store, predicate: predicate, limit: limit, anchor: actualAnchor)
1280
+
1281
+ var allHeartbeatSamples: [Dictionary<String, Any>] = []
1546
1282
  for sample in queryResult.samples as! [HKHeartbeatSeriesSample] {
1547
- allHeartbeatSamples.append(try await getSerializedHeartbeatSeriesSample(store: store, sample: sample));
1283
+ allHeartbeatSamples.append(try await getSerializedHeartbeatSeriesSample(store: store, sample: sample))
1548
1284
  }
1549
-
1285
+
1550
1286
  resolve([
1551
1287
  "samples": allHeartbeatSamples as Any,
1552
1288
  "deletedSamples": queryResult.deletedSamples?.map({ sample in
1553
1289
  return serializeDeletedSample(sample: sample)
1554
1290
  }) as Any,
1555
1291
  "newAnchor": serializeAnchor(anchor: queryResult.newAnchor) as Any
1556
- ]);
1292
+ ])
1557
1293
  } catch {
1558
- reject(GENERIC_ERROR, error.localizedDescription, error);
1294
+ reject(GENERIC_ERROR, error.localizedDescription, error)
1559
1295
  }
1560
1296
  }
1561
1297
  }
1298
+
1299
+ @available(iOS 13.0.0, *)
1300
+ func _queryHeartbeatSeriesSamples(
1301
+ store: HKHealthStore,
1302
+ predicate: NSPredicate?,
1303
+ limit: Int,
1304
+ ascending: Bool
1305
+ ) async throws -> [HKSample] {
1306
+ let samples = try await withCheckedThrowingContinuation {
1307
+ (continuation: CheckedContinuation<[HKSample], Error>) in
1308
+
1309
+ let query = HKSampleQuery(
1310
+ sampleType: HKSeriesType.heartbeat(),
1311
+ predicate: predicate,
1312
+ limit: limit,
1313
+ sortDescriptors: [NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: ascending)]
1314
+ ) { (_: HKSampleQuery, sample: [HKSample]?, error: Error?) in
1315
+ if let err = error {
1316
+ continuation.resume(throwing: err)
1317
+ } else {
1318
+ guard let actualSamples = sample else {
1319
+ fatalError("Should not fail")
1320
+ }
1321
+ continuation.resume(returning: actualSamples)
1322
+ }
1323
+ }
1324
+
1325
+ store.execute(query)
1326
+ }
1327
+
1328
+ return samples
1329
+ }
1330
+
1331
+ @available(iOS 13.0.0, *)
1332
+ @objc(queryHeartbeatSeriesSamples:to:limit:ascending:resolve:reject:)
1333
+ func queryHeartbeatSeriesSamples(
1334
+ from: Date,
1335
+ to: Date,
1336
+ limit: Int,
1337
+ ascending: Bool,
1338
+ resolve: @escaping RCTPromiseResolveBlock,
1339
+ reject: @escaping RCTPromiseRejectBlock
1340
+ ) {
1341
+ guard let store = _store else {
1342
+ return reject(INIT_ERROR, INIT_ERROR_MESSAGE, nil)
1343
+ }
1344
+
1345
+ Task {
1346
+ do {
1347
+ let from = dateOrNilIfZero(date: from)
1348
+ let to = dateOrNilIfZero(date: to)
1349
+
1350
+ let predicate = createPredicate(from: from, to: to)
1351
+
1352
+ let limit = limitOrNilIfZero(limit: limit)
1353
+
1354
+ let samples = try await _queryHeartbeatSeriesSamples(store: store, predicate: predicate, limit: limit, ascending: ascending)
1355
+
1356
+ var allHeartbeatSamples: [Dictionary<String, Any>] = []
1357
+ for sample in samples as! [HKHeartbeatSeriesSample] {
1358
+ allHeartbeatSamples.append(try await getSerializedHeartbeatSeriesSample(store: store, sample: sample))
1359
+ }
1360
+
1361
+ resolve(allHeartbeatSamples as Any)
1362
+ } catch {
1363
+ reject(GENERIC_ERROR, error.localizedDescription, error)
1364
+ }
1365
+ }
1366
+ }
1367
+
1562
1368
  }