@kingstinct/react-native-healthkit 9.0.6 → 9.0.8

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 (67) hide show
  1. package/ios/CategoryTypeModule.swift +18 -21
  2. package/ios/CharacteristicTypeModule.swift +36 -21
  3. package/ios/CorrelationTypeModule.swift +18 -18
  4. package/ios/HeartbeatSeriesModule.swift +32 -32
  5. package/ios/QuantityTypeModule.swift +56 -57
  6. package/ios/Serializers.swift +12 -16
  7. package/ios/StateOfMindModule.swift +17 -17
  8. package/ios/WorkoutsModule.swift +59 -110
  9. package/lib/commonjs/healthkit.js +225 -0
  10. package/lib/commonjs/hooks/useStatisticsForQuantity.js +1 -1
  11. package/lib/commonjs/index.js +6 -209
  12. package/lib/module/healthkit.js +203 -0
  13. package/lib/module/hooks/useStatisticsForQuantity.js +1 -1
  14. package/lib/module/index.js +3 -203
  15. package/lib/typescript/healthkit.d.ts +69 -0
  16. package/lib/typescript/{index.ios.d.ts → healthkit.ios.d.ts} +11 -11
  17. package/lib/typescript/hooks/useHealthkitAuthorization.d.ts +1 -1
  18. package/lib/typescript/index.d.ts +3 -69
  19. package/lib/typescript/specs/CategoryTypeModule.nitro.d.ts +1 -1
  20. package/lib/typescript/specs/CharacteristicTypeModule.nitro.d.ts +2 -2
  21. package/lib/typescript/specs/CoreModule.nitro.d.ts +3 -3
  22. package/lib/typescript/specs/WorkoutsModule.nitro.d.ts +3 -0
  23. package/lib/typescript/types/Shared.d.ts +3 -3
  24. package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Bridge.cpp +7 -48
  25. package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Bridge.hpp +54 -154
  26. package/nitrogen/generated/ios/ReactNativeHealthkit-Swift-Cxx-Umbrella.hpp +0 -14
  27. package/nitrogen/generated/ios/c++/HybridCharacteristicTypeModuleSpecSwift.hpp +3 -2
  28. package/nitrogen/generated/ios/swift/Func_void_std__optional_std__chrono__system_clock__time_point_.swift +52 -0
  29. package/nitrogen/generated/ios/swift/HybridCharacteristicTypeModuleSpec.swift +2 -2
  30. package/nitrogen/generated/ios/swift/HybridCharacteristicTypeModuleSpec_cxx.swift +23 -11
  31. package/nitrogen/generated/shared/c++/HybridCharacteristicTypeModuleSpec.hpp +3 -2
  32. package/package.json +2 -2
  33. package/src/healthkit.ts +422 -0
  34. package/src/hooks/useHealthkitAuthorization.ts +2 -2
  35. package/src/hooks/useStatisticsForQuantity.ts +1 -3
  36. package/src/index.ts +3 -419
  37. package/src/specs/CategoryTypeModule.nitro.ts +1 -1
  38. package/src/specs/CharacteristicTypeModule.nitro.ts +2 -2
  39. package/src/specs/CoreModule.nitro.ts +5 -5
  40. package/src/specs/WorkoutsModule.nitro.ts +3 -0
  41. package/src/test-setup.ts +0 -1
  42. package/src/types/QueryOptions.ts +3 -3
  43. package/src/types/Shared.ts +6 -8
  44. package/ios/WorkoutSessionModule.swift +0 -182
  45. package/lib/commonjs/specs/WorkoutSessionModule.nitro.js +0 -19
  46. package/lib/module/specs/WorkoutSessionModule.nitro.js +0 -16
  47. package/lib/typescript/specs/WorkoutSessionModule.nitro.d.ts +0 -47
  48. package/nitrogen/generated/ios/c++/HybridWorkoutSessionModuleSpecSwift.cpp +0 -11
  49. package/nitrogen/generated/ios/c++/HybridWorkoutSessionModuleSpecSwift.hpp +0 -107
  50. package/nitrogen/generated/ios/swift/Func_void_WorkoutEventType.swift +0 -46
  51. package/nitrogen/generated/ios/swift/Func_void_WorkoutSessionState_WorkoutSessionState_std__chrono__system_clock__time_point.swift +0 -46
  52. package/nitrogen/generated/ios/swift/Func_void_std__chrono__system_clock__time_point.swift +0 -46
  53. package/nitrogen/generated/ios/swift/Func_void_std__vector_RemoteSessionSharableData_.swift +0 -46
  54. package/nitrogen/generated/ios/swift/HybridWorkoutSessionModuleSpec.swift +0 -49
  55. package/nitrogen/generated/ios/swift/HybridWorkoutSessionModuleSpec_cxx.swift +0 -133
  56. package/nitrogen/generated/ios/swift/RemoteSessionSharableData.swift +0 -46
  57. package/nitrogen/generated/ios/swift/WorkoutSessionMirroringStartHandlerOptions.swift +0 -118
  58. package/nitrogen/generated/ios/swift/WorkoutSessionState.swift +0 -56
  59. package/nitrogen/generated/shared/c++/HybridWorkoutSessionModuleSpec.cpp +0 -22
  60. package/nitrogen/generated/shared/c++/HybridWorkoutSessionModuleSpec.hpp +0 -68
  61. package/nitrogen/generated/shared/c++/RemoteSessionSharableData.hpp +0 -75
  62. package/nitrogen/generated/shared/c++/WorkoutSessionMirroringStartHandlerOptions.hpp +0 -92
  63. package/nitrogen/generated/shared/c++/WorkoutSessionState.hpp +0 -68
  64. package/src/specs/WorkoutSessionModule.nitro.ts +0 -71
  65. /package/lib/commonjs/{index.ios.js → healthkit.ios.js} +0 -0
  66. /package/lib/module/{index.ios.js → healthkit.ios.js} +0 -0
  67. /package/src/{index.ios.ts → healthkit.ios.ts} +0 -0
@@ -1,9 +1,7 @@
1
1
  import HealthKit
2
2
  import NitroModules
3
3
 
4
-
5
-
6
- class CategoryTypeModule : HybridCategoryTypeModuleSpec {
4
+ class CategoryTypeModule: HybridCategoryTypeModuleSpec {
7
5
  func saveCategorySample(
8
6
  identifier: CategoryTypeIdentifier,
9
7
  value: Double,
@@ -12,7 +10,7 @@ class CategoryTypeModule : HybridCategoryTypeModuleSpec {
12
10
  metadata: AnyMapHolder
13
11
  ) throws -> Promise<Bool> {
14
12
  let type = try initializeCategoryType(identifier.stringValue)
15
-
13
+
16
14
  let sample = HKCategorySample(
17
15
  type: type,
18
16
  value: Int(value),
@@ -20,7 +18,7 @@ class CategoryTypeModule : HybridCategoryTypeModuleSpec {
20
18
  end: endDate,
21
19
  metadata: anyMapToDictionary(metadata)
22
20
  )
23
-
21
+
24
22
  return Promise.async {
25
23
  try await withCheckedThrowingContinuation { continuation in
26
24
  store.save(sample) { (success: Bool, error: Error?) in
@@ -33,15 +31,15 @@ class CategoryTypeModule : HybridCategoryTypeModuleSpec {
33
31
  }
34
32
  }
35
33
  }
36
-
34
+
37
35
  func queryCategorySamples(
38
36
  identifier: CategoryTypeIdentifier,
39
- options: QueryOptionsWithSortOrder?,
37
+ options: QueryOptionsWithSortOrder?
40
38
  ) throws -> Promise<[CategorySample]> {
41
39
  let sampleType = try initializeCategoryType(identifier.stringValue)
42
40
  let predicate = try createPredicate(filter: options?.filter)
43
41
  let queryLimit = getQueryLimit(options?.limit)
44
-
42
+
45
43
  return Promise.async {
46
44
  try await withCheckedThrowingContinuation { continuation in
47
45
  let query = HKSampleQuery(
@@ -54,36 +52,35 @@ class CategoryTypeModule : HybridCategoryTypeModuleSpec {
54
52
  continuation.resume(throwing: error)
55
53
  return
56
54
  }
57
-
55
+
58
56
  guard let samples = samples else {
59
57
  continuation.resume(returning: [])
60
58
  return
61
59
  }
62
-
60
+
63
61
  let categorySamples = samples.compactMap { sample -> CategorySample? in
64
62
  guard let categorySample = sample as? HKCategorySample else { return nil }
65
63
  return serializeCategorySample(sample: categorySample)
66
64
  }
67
-
65
+
68
66
  continuation.resume(returning: categorySamples)
69
67
  }
70
-
68
+
71
69
  store.execute(query)
72
70
  }
73
71
  }
74
72
  }
75
-
76
-
73
+
77
74
  func queryCategorySamplesWithAnchor(
78
75
  identifier: CategoryTypeIdentifier,
79
76
  options: QueryOptionsWithAnchor
80
77
  ) throws -> Promise<CategorySamplesWithAnchorResponse> {
81
78
  let sampleType = try initializeCategoryType(identifier.stringValue)
82
-
79
+
83
80
  let predicate = try createPredicate(filter: options.filter)
84
81
  let queryLimit = getQueryLimit(options.limit)
85
82
  let queryAnchor = try deserializeHKQueryAnchor(base64String: options.anchor)
86
-
83
+
87
84
  return Promise.async {
88
85
  try await withCheckedThrowingContinuation { continuation in
89
86
  let query = HKAnchoredObjectQuery(
@@ -96,7 +93,7 @@ class CategoryTypeModule : HybridCategoryTypeModuleSpec {
96
93
  continuation.resume(throwing: error)
97
94
  return
98
95
  }
99
-
96
+
100
97
  guard let samples = samples else {
101
98
  let response = CategorySamplesWithAnchorResponse(
102
99
  samples: [],
@@ -106,21 +103,21 @@ class CategoryTypeModule : HybridCategoryTypeModuleSpec {
106
103
  continuation.resume(returning: response)
107
104
  return
108
105
  }
109
-
106
+
110
107
  let categorySamples = samples.compactMap { sample -> CategorySample? in
111
108
  guard let categorySample = sample as? HKCategorySample else { return nil }
112
109
  return serializeCategorySample(sample: categorySample)
113
110
  }
114
-
111
+
115
112
  let response = CategorySamplesWithAnchorResponse(
116
113
  samples: categorySamples,
117
114
  deletedSamples: deletedSamples?.map { serializeDeletedSample(sample: $0) } ?? [],
118
115
  newAnchor: serializeAnchor(anchor: newAnchor) ?? ""
119
116
  )
120
-
117
+
121
118
  continuation.resume(returning: response)
122
119
  }
123
-
120
+
124
121
  store.execute(query)
125
122
  }
126
123
  }
@@ -1,4 +1,3 @@
1
-
2
1
  import HealthKit
3
2
  import NitroModules
4
3
 
@@ -6,23 +5,23 @@ class CharacteristicTypeModule: HybridCharacteristicTypeModuleSpec {
6
5
  func getBloodTypeAsync() throws -> Promise<BloodType> {
7
6
  return Promise.resolved(withResult: try self.getBloodType())
8
7
  }
9
-
10
- func getDateOfBirthAsync() throws -> Promise<Date> {
8
+
9
+ func getDateOfBirthAsync() throws -> Promise<Date?> {
11
10
  return Promise.resolved(withResult: try self.getDateOfBirth())
12
11
  }
13
-
12
+
14
13
  func getBiologicalSexAsync() throws -> Promise<BiologicalSex> {
15
14
  return Promise.resolved(withResult: try self.getBiologicalSex())
16
15
  }
17
-
16
+
18
17
  func getFitzpatrickSkinTypeAsync() throws -> Promise<FitzpatrickSkinType> {
19
18
  return Promise.resolved(withResult: try self.getFitzpatrickSkinType())
20
19
  }
21
-
20
+
22
21
  func getWheelchairUseAsync() throws -> Promise<WheelchairUse> {
23
22
  return Promise.resolved(withResult: try self.getWheelchairUse())
24
23
  }
25
-
24
+
26
25
  // Using the global 'store' instance defined in Auth.swift
27
26
 
28
27
  func getBiologicalSex() throws -> BiologicalSex {
@@ -33,34 +32,50 @@ class CharacteristicTypeModule: HybridCharacteristicTypeModuleSpec {
33
32
  throw RuntimeError.error(withMessage: "[react-native-healthkit] Got unknown biological sex value: \(biologicalSexObject.biologicalSex.rawValue)")
34
33
  }
35
34
 
36
- func getDateOfBirth() throws -> Date {
37
- let dateOfBirthComponents = try store.dateOfBirthComponents()
38
-
39
- if let date = dateOfBirthComponents.date {
40
- return date
41
- }
42
-
43
- throw RuntimeError.error(withMessage: "[react-native-healthkit] Date of birth is not available or not set")
44
- }
35
+ func getDateOfBirth() throws -> Date? {
36
+ do {
37
+ let components = try store.dateOfBirthComponents()
38
+ return components.date
39
+ } catch {
40
+ let nsError = error as NSError
41
+
42
+ // 1️⃣ HealthKit’s documented “no data” error
43
+ if nsError.domain == HKError.errorDomain,
44
+ nsError.code == HKError.Code.errorNoData.rawValue {
45
+ return nil
46
+ }
47
+
48
+ // 2️⃣ The undocumented generic Obj-C error some OS versions emit
49
+ if nsError.domain == "Foundation._GenericObjCError",
50
+ nsError.code == 0 {
51
+ return nil
52
+ }
53
+
54
+ // Anything else is a real failure – surface it to JS
55
+ throw RuntimeError.error(
56
+ withMessage: "[react-native-healthkit] Failed to get date of birth: \(nsError.localizedDescription)"
57
+ )
58
+ }
59
+ }
45
60
 
46
61
  func getBloodType() throws -> BloodType {
47
62
  let bloodTypeObject = try store.bloodType()
48
-
49
- if let bloodType = BloodType(rawValue: Int32(bloodTypeObject.bloodType.rawValue)){
63
+
64
+ if let bloodType = BloodType(rawValue: Int32(bloodTypeObject.bloodType.rawValue)) {
50
65
  return bloodType
51
66
  }
52
-
67
+
53
68
  throw RuntimeError.error(withMessage: "[react-native-healthkit] Got unknown blood type value: \(bloodTypeObject.bloodType.rawValue)")
54
69
  }
55
70
 
56
71
  func getFitzpatrickSkinType() throws -> FitzpatrickSkinType {
57
72
  if #available(iOS 9.0, *) {
58
73
  let skinTypeObject = try store.fitzpatrickSkinType()
59
-
74
+
60
75
  if let skinType = FitzpatrickSkinType(rawValue: Int32(skinTypeObject.skinType.rawValue)) {
61
76
  return skinType
62
77
  }
63
-
78
+
64
79
  throw RuntimeError.error(withMessage: "[react-native-healthkit] Got unknown Fitzpatrick skin type value: \(skinTypeObject.skinType.rawValue)")
65
80
  } else {
66
81
  throw RuntimeError.error(withMessage: "Fitzpatrick skin type is not available before iOS 9.0")
@@ -1,7 +1,7 @@
1
1
  import HealthKit
2
2
  import NitroModules
3
3
 
4
- class CorrelationTypeModule : HybridCorrelationTypeModuleSpec {
4
+ class CorrelationTypeModule: HybridCorrelationTypeModuleSpec {
5
5
  func saveCorrelationSample(
6
6
  typeIdentifier: CorrelationTypeIdentifier,
7
7
  samples: [SampleForSaving],
@@ -10,16 +10,16 @@ class CorrelationTypeModule : HybridCorrelationTypeModuleSpec {
10
10
  metadata: AnyMapHolder
11
11
  ) throws -> Promise<Bool> {
12
12
  let correlationType = try initializeCorrelationType(typeIdentifier.stringValue)
13
-
13
+
14
14
  var initializedSamples = Set<HKSample>()
15
-
15
+
16
16
  for sample in samples {
17
17
  if let quantitySample = sample as? QuantitySampleForSaving {
18
18
  let quantityTypeId = HKQuantityTypeIdentifier(rawValue: quantitySample.quantityType.stringValue)
19
19
  guard let quantityType = HKSampleType.quantityType(forIdentifier: quantityTypeId) else {
20
20
  continue
21
21
  }
22
-
22
+
23
23
  let unit = HKUnit(from: quantitySample.unit)
24
24
  let quantity = HKQuantity(unit: unit, doubleValue: quantitySample.quantity)
25
25
  let hkQuantitySample = HKQuantitySample(
@@ -30,10 +30,10 @@ class CorrelationTypeModule : HybridCorrelationTypeModuleSpec {
30
30
  metadata: anyMapToDictionary(quantitySample.metadata)
31
31
  )
32
32
  initializedSamples.insert(hkQuantitySample)
33
-
33
+
34
34
  } else if let categorySample = sample as? CategorySampleForSaving {
35
35
  let categoryType = try initializeCategoryType(categorySample.categoryType.stringValue)
36
-
36
+
37
37
  let hkCategorySample = HKCategorySample(
38
38
  type: categoryType,
39
39
  value: Int(categorySample.value),
@@ -44,7 +44,7 @@ class CorrelationTypeModule : HybridCorrelationTypeModuleSpec {
44
44
  initializedSamples.insert(hkCategorySample)
45
45
  }
46
46
  }
47
-
47
+
48
48
  let correlation = HKCorrelation(
49
49
  type: correlationType,
50
50
  start: start,
@@ -52,7 +52,7 @@ class CorrelationTypeModule : HybridCorrelationTypeModuleSpec {
52
52
  objects: initializedSamples,
53
53
  metadata: anyMapToDictionary(metadata)
54
54
  )
55
-
55
+
56
56
  return Promise.async {
57
57
  try await withCheckedThrowingContinuation { continuation in
58
58
  store.save(correlation) { (success: Bool, error: Error?) in
@@ -65,7 +65,7 @@ class CorrelationTypeModule : HybridCorrelationTypeModuleSpec {
65
65
  }
66
66
  }
67
67
  }
68
-
68
+
69
69
  func queryCorrelationSamples(
70
70
  typeIdentifier: CorrelationTypeIdentifier,
71
71
  from: Date,
@@ -82,7 +82,7 @@ class CorrelationTypeModule : HybridCorrelationTypeModuleSpec {
82
82
  )
83
83
  )
84
84
  )
85
-
85
+
86
86
  return Promise.async {
87
87
  try await withCheckedThrowingContinuation { continuation in
88
88
  let query = HKCorrelationQuery(
@@ -94,12 +94,12 @@ class CorrelationTypeModule : HybridCorrelationTypeModuleSpec {
94
94
  continuation.resume(throwing: error)
95
95
  return
96
96
  }
97
-
97
+
98
98
  guard let correlations = correlations else {
99
99
  continuation.resume(returning: [])
100
100
  return
101
101
  }
102
-
102
+
103
103
  // Collect all quantity types to get preferred units
104
104
  var quantityTypes = Set<HKQuantityType>()
105
105
  for correlation in correlations {
@@ -109,13 +109,13 @@ class CorrelationTypeModule : HybridCorrelationTypeModuleSpec {
109
109
  }
110
110
  }
111
111
  }
112
-
112
+
113
113
  store.preferredUnits(for: quantityTypes) { (unitMap: [HKQuantityType: HKUnit], error: Error?) in
114
114
  if let error = error {
115
115
  continuation.resume(throwing: error)
116
116
  return
117
117
  }
118
-
118
+
119
119
  let serializedCorrelations = correlations.map { correlation -> CorrelationSample in
120
120
  let objects = correlation.objects.compactMap { object -> CorrelationObject? in
121
121
  if let quantitySample = object as? HKQuantitySample,
@@ -126,13 +126,13 @@ class CorrelationTypeModule : HybridCorrelationTypeModuleSpec {
126
126
  } catch {
127
127
  print(error.localizedDescription)
128
128
  }
129
-
129
+
130
130
  } else if let categorySample = object as? HKCategorySample {
131
131
  return CorrelationObject.first(serializeCategorySample(sample: categorySample))
132
132
  }
133
133
  return nil
134
134
  }
135
-
135
+
136
136
  return CorrelationSample(
137
137
  correlationType: CorrelationTypeIdentifier(fromString: correlation.correlationType.identifier)!,
138
138
  objects: objects,
@@ -141,11 +141,11 @@ class CorrelationTypeModule : HybridCorrelationTypeModuleSpec {
141
141
  endDate: correlation.endDate
142
142
  )
143
143
  }
144
-
144
+
145
145
  continuation.resume(returning: serializedCorrelations)
146
146
  }
147
147
  }
148
-
148
+
149
149
  store.execute(query)
150
150
  }
151
151
  }
@@ -5,7 +5,7 @@ func getHeartbeatSeriesByID(
5
5
  seriesUUID: UUID
6
6
  ) async -> HKHeartbeatSeriesSample? {
7
7
  let seriesPredicate = HKQuery.predicateForObject(with: seriesUUID)
8
-
8
+
9
9
  let samples = try! await withCheckedThrowingContinuation {
10
10
  (continuation: CheckedContinuation<[HKSample], Error>) in
11
11
  let query = HKSampleQuery(
@@ -14,36 +14,36 @@ func getHeartbeatSeriesByID(
14
14
  limit: 1,
15
15
  sortDescriptors: nil
16
16
  ) { (_, results, error) in
17
-
17
+
18
18
  if let hasError = error {
19
19
  continuation.resume(throwing: hasError)
20
20
  return
21
21
  }
22
-
22
+
23
23
  guard let samples = results else {
24
24
  return continuation.resume(throwing: RuntimeError.error(withMessage: "Empty response"))
25
25
  }
26
-
26
+
27
27
  continuation.resume(returning: samples)
28
28
  }
29
29
  store.execute(query)
30
30
  }
31
-
31
+
32
32
  guard let heartbeatSeries = samples as? [HKHeartbeatSeriesSample] else {
33
33
  return nil
34
34
  }
35
-
35
+
36
36
  return heartbeatSeries.first ?? nil
37
37
  }
38
38
 
39
39
  @available(iOS 13.0.0, *)
40
- class HeartbeatSeriesModule : HybridHeartbeatSeriesModuleSpec {
40
+ class HeartbeatSeriesModule: HybridHeartbeatSeriesModuleSpec {
41
41
  func queryHeartbeatSeriesSamples(
42
42
  options: QueryOptionsWithSortOrder?
43
43
  ) throws -> Promise<[HeartbeatSeriesSample]> {
44
44
  let predicate = try createPredicate(filter: options?.filter)
45
45
  let queryLimit = getQueryLimit(options?.limit)
46
-
46
+
47
47
  return Promise.async {
48
48
  try await withCheckedThrowingContinuation { continuation in
49
49
  let query = HKSampleQuery(
@@ -58,42 +58,42 @@ class HeartbeatSeriesModule : HybridHeartbeatSeriesModuleSpec {
58
58
  continuation.resume(throwing: error)
59
59
  return
60
60
  }
61
-
61
+
62
62
  guard let samples = samples else {
63
63
  continuation.resume(returning: [])
64
64
  return
65
65
  }
66
-
66
+
67
67
  Task {
68
68
  do {
69
69
  var serializedSamples: [HeartbeatSeriesSample] = []
70
-
70
+
71
71
  for sample in samples {
72
72
  guard let heartbeatSample = sample as? HKHeartbeatSeriesSample else { continue }
73
-
73
+
74
74
  let serialized = try await self.serializeHeartbeatSeriesSample(sample: heartbeatSample)
75
75
  serializedSamples.append(serialized)
76
76
  }
77
-
77
+
78
78
  continuation.resume(returning: serializedSamples)
79
79
  } catch {
80
80
  continuation.resume(throwing: error)
81
81
  }
82
82
  }
83
83
  }
84
-
84
+
85
85
  store.execute(query)
86
86
  }
87
87
  }
88
88
  }
89
-
89
+
90
90
  func queryHeartbeatSeriesSamplesWithAnchor(
91
91
  options: QueryOptionsWithAnchor
92
92
  ) throws -> Promise<HeartbeatSeriesSamplesWithAnchorResponse> {
93
93
  let predicate = try createPredicate(filter: options.filter)
94
94
  let queryLimit = getQueryLimit(options.limit)
95
95
  let queryAnchor = try deserializeHKQueryAnchor(base64String: options.anchor)
96
-
96
+
97
97
  return Promise.async {
98
98
  try await withCheckedThrowingContinuation { continuation in
99
99
  let query = HKAnchoredObjectQuery(
@@ -106,7 +106,7 @@ class HeartbeatSeriesModule : HybridHeartbeatSeriesModuleSpec {
106
106
  continuation.resume(throwing: error)
107
107
  return
108
108
  }
109
-
109
+
110
110
  guard let samples = samples else {
111
111
  let response = HeartbeatSeriesSamplesWithAnchorResponse(
112
112
  samples: [],
@@ -116,38 +116,38 @@ class HeartbeatSeriesModule : HybridHeartbeatSeriesModuleSpec {
116
116
  continuation.resume(returning: response)
117
117
  return
118
118
  }
119
-
119
+
120
120
  Task {
121
121
  do {
122
122
  var serializedSamples: [HeartbeatSeriesSample] = []
123
-
123
+
124
124
  for sample in samples {
125
125
  guard let heartbeatSample = sample as? HKHeartbeatSeriesSample else { continue }
126
126
  let serialized = try await self.serializeHeartbeatSeriesSample(sample: heartbeatSample)
127
127
  serializedSamples.append(serialized)
128
128
  }
129
-
129
+
130
130
  let response = HeartbeatSeriesSamplesWithAnchorResponse(
131
131
  samples: serializedSamples,
132
132
  deletedSamples: deletedSamples?.map { serializeDeletedSample(sample: $0) } ?? [],
133
133
  newAnchor: serializeAnchor(anchor: newAnchor) ?? ""
134
134
  )
135
-
135
+
136
136
  continuation.resume(returning: response)
137
137
  } catch {
138
138
  continuation.resume(throwing: error)
139
139
  }
140
140
  }
141
141
  }
142
-
142
+
143
143
  store.execute(query)
144
144
  }
145
145
  }
146
146
  }
147
-
147
+
148
148
  private func serializeHeartbeatSeriesSample(sample: HKHeartbeatSeriesSample) async throws -> HeartbeatSeriesSample {
149
149
  let heartbeats = try await getHeartbeatSeriesHeartbeats(sample: sample)
150
-
150
+
151
151
  return HeartbeatSeriesSample(
152
152
  uuid: sample.uuid.uuidString,
153
153
  device: serializeDevice(hkDevice: sample.device),
@@ -158,31 +158,31 @@ class HeartbeatSeriesModule : HybridHeartbeatSeriesModuleSpec {
158
158
  sourceRevision: serializeSourceRevision(sample.sourceRevision)
159
159
  )
160
160
  }
161
-
161
+
162
162
  private func getHeartbeatSeriesHeartbeats(sample: HKHeartbeatSeriesSample) async throws -> [Heartbeat] {
163
163
  return try await withCheckedThrowingContinuation { continuation in
164
164
  var allBeats: [Heartbeat] = []
165
-
166
- let query = HKHeartbeatSeriesQuery(heartbeatSeries: sample) {
165
+
166
+ let query = HKHeartbeatSeriesQuery(heartbeatSeries: sample) {
167
167
  (_: HKHeartbeatSeriesQuery, timeSinceSeriesStart: TimeInterval, precededByGap: Bool, done: Bool, error: Error?) in
168
-
168
+
169
169
  if let error = error {
170
170
  continuation.resume(throwing: error)
171
171
  return
172
172
  }
173
-
173
+
174
174
  let heartbeat = Heartbeat(
175
175
  timeSinceSeriesStart: timeSinceSeriesStart,
176
176
  precededByGap: precededByGap
177
177
  )
178
-
178
+
179
179
  allBeats.append(heartbeat)
180
-
180
+
181
181
  if done {
182
182
  continuation.resume(returning: allBeats)
183
183
  }
184
184
  }
185
-
185
+
186
186
  store.execute(query)
187
187
  }
188
188
  }