@tryterra/react-native 2.1.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +31 -0
  2. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/Conversions.kt +103 -14
  3. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/ReadConversions.kt +250 -0
  4. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/TerraBridgeOpsImpl.kt +47 -5
  5. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/TerraBridgeStreamsImpl.kt +1 -3
  6. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/generated/BridgeOps.kt +89 -0
  7. package/android/src/bridgeCore/kotlin/co/tryterra/sdk/bridge/generated/BridgeTypes.kt +672 -0
  8. package/docs/availability.md +154 -4
  9. package/frameworks/TerraSDK.xcframework/Info.plist +5 -5
  10. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/Info.plist +0 -0
  11. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios.abi.json +1385 -226
  12. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios.package.swiftinterface +37 -1
  13. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios.private.swiftinterface +37 -1
  14. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  15. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios.swiftinterface +37 -1
  16. package/frameworks/TerraSDK.xcframework/ios-arm64/TerraSDK.framework/TerraSDK +0 -0
  17. package/frameworks/TerraSDK.xcframework/ios-arm64/dSYMs/TerraSDK.framework.dSYM/Contents/Info.plist +2 -2
  18. package/frameworks/TerraSDK.xcframework/ios-arm64/dSYMs/TerraSDK.framework.dSYM/Contents/Resources/DWARF/TerraSDK +0 -0
  19. package/frameworks/TerraSDK.xcframework/ios-arm64/dSYMs/TerraSDK.framework.dSYM/Contents/Resources/Relocations/aarch64/TerraSDK.yml +6589 -6468
  20. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Info.plist +0 -0
  21. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios-simulator.abi.json +1385 -226
  22. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios-simulator.package.swiftinterface +37 -1
  23. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +37 -1
  24. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  25. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +37 -1
  26. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/x86_64-apple-ios-simulator.abi.json +1385 -226
  27. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/x86_64-apple-ios-simulator.package.swiftinterface +37 -1
  28. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +37 -1
  29. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  30. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/Modules/TerraSDK.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +37 -1
  31. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/TerraSDK +0 -0
  32. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/TerraSDK.framework/_CodeSignature/CodeResources +21 -21
  33. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/TerraSDK.framework.dSYM/Contents/Info.plist +2 -2
  34. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/TerraSDK.framework.dSYM/Contents/Resources/DWARF/TerraSDK +0 -0
  35. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/TerraSDK.framework.dSYM/Contents/Resources/Relocations/aarch64/TerraSDK.yml +6590 -6469
  36. package/frameworks/TerraSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/TerraSDK.framework.dSYM/Contents/Resources/Relocations/x86_64/TerraSDK.yml +6508 -6387
  37. package/ios/TerraBridgeCore/Conversions+Reads.swift +259 -0
  38. package/ios/TerraBridgeCore/Conversions.swift +129 -2
  39. package/ios/TerraBridgeCore/Generated/BridgeOps.swift +172 -0
  40. package/ios/TerraBridgeCore/Generated/BridgeTypes.swift +734 -1
  41. package/ios/TerraBridgeCore/TerraBridgeOpsImpl.swift +64 -0
  42. package/lib/Terra.d.ts +74 -5
  43. package/lib/Terra.js +69 -13
  44. package/lib/generated/client.d.ts +37 -1
  45. package/lib/generated/client.js +60 -0
  46. package/lib/generated/codecs.d.ts +85 -1
  47. package/lib/generated/codecs.js +710 -2
  48. package/lib/generated/ops.d.ts +1 -1
  49. package/lib/generated/ops.js +24 -0
  50. package/lib/generated/types.d.ts +314 -1
  51. package/lib/generated/types.js +133 -1
  52. package/lib/index.d.ts +1 -1
  53. package/package.json +3 -3
  54. package/src/Terra.ts +146 -16
  55. package/src/generated/client.ts +74 -2
  56. package/src/generated/codecs.ts +705 -3
  57. package/src/generated/ops.ts +36 -0
  58. package/src/generated/types.ts +556 -1
  59. package/src/index.ts +2 -0
@@ -0,0 +1,259 @@
1
+ import Foundation
2
+ import TerraSDK
3
+
4
+ extension Conversions {
5
+
6
+ static func dayTotalMetric(_ metric: TerraSDK.DayTotal.Metric) -> DayTotalMetric? {
7
+ switch metric {
8
+ case .distanceWalkingRunning: return .distanceWalkingRunning
9
+ case .distanceCycling: return .distanceCycling
10
+ case .distanceSwimming: return .distanceSwimming
11
+ case .distanceWheelchair: return .distanceWheelchair
12
+ case .activeEnergyBurned: return .activeEnergyBurned
13
+ case .basalEnergyBurned: return .basalEnergyBurned
14
+ case .flightsClimbed: return .flightsClimbed
15
+ case .appleExerciseTime: return .appleExerciseTime
16
+ case .steps, .swimmingStrokeCount, .appleMoveTime, .appleStandTime, .appleStandHours: return nil
17
+ @unknown default: return nil
18
+ }
19
+ }
20
+
21
+ static func dayTotal(_ total: TerraSDK.DayTotal) -> DayTotal? {
22
+ dayTotalMetric(total.metric).map {
23
+ DayTotal(
24
+ metric: $0,
25
+ start: BridgeInstant.format(total.interval.start),
26
+ end: BridgeInstant.format(total.interval.end),
27
+ value: total.value,
28
+ unit: total.unit,
29
+ timeZone: total.timeZone?.identifier)
30
+ }
31
+ }
32
+
33
+ static func intradayMetric(_ kind: TerraSDK.IntradaySample.Kind) -> IntradayMetric? {
34
+ switch kind {
35
+ case .activeEnergy: return .activeEnergy
36
+ case .basalEnergy: return .basalEnergy
37
+ case .distance: return .distance
38
+ case .floorsClimbed: return .floorsClimbed
39
+ @unknown default: return nil
40
+ }
41
+ }
42
+
43
+ static func intraday(_ sample: TerraSDK.IntradaySample) -> IntradaySample? {
44
+ intradayMetric(sample.kind).map {
45
+ IntradaySample(
46
+ id: sample.id.uuidString,
47
+ metric: $0,
48
+ start: BridgeInstant.format(sample.interval.start),
49
+ end: BridgeInstant.format(sample.interval.end),
50
+ value: sample.value,
51
+ source: sampleSource(sample.source),
52
+ userEntered: sample.userEntered,
53
+ timeZone: sample.timeZone?.identifier)
54
+ }
55
+ }
56
+
57
+ static func restingHeartRate(_ sample: TerraSDK.RestingHeartRateSample) -> RestingHeartRateSample {
58
+ RestingHeartRateSample(
59
+ id: sample.id.uuidString,
60
+ start: BridgeInstant.format(sample.interval.start),
61
+ end: BridgeInstant.format(sample.interval.end),
62
+ beatsPerMinute: sample.beatsPerMinute,
63
+ source: sampleSource(sample.source),
64
+ userEntered: sample.userEntered,
65
+ timeZone: sample.timeZone?.identifier)
66
+ }
67
+
68
+ static func bodyMetric(_ metric: TerraSDK.BodyMetric) -> BodyMetric? {
69
+ switch metric {
70
+ case .weight: return .weight
71
+ case .height: return .height
72
+ case .bodyFatPercentage: return .bodyFatPercentage
73
+ case .leanBodyMass: return .leanBodyMass
74
+ case .bmi: return .bmi
75
+ case .waistCircumference: return nil
76
+ @unknown default: return nil
77
+ }
78
+ }
79
+
80
+ static func glucoseUnit(_ unit: TerraSDK.BloodGlucoseUnit) -> BloodGlucoseUnit {
81
+ switch unit {
82
+ case .milligramsPerDecilitre: return .milligramsPerDecilitre
83
+ case .millimolesPerLitre: return .millimolesPerLitre
84
+ @unknown default: return .milligramsPerDecilitre
85
+ }
86
+ }
87
+
88
+ static func mealTime(_ time: TerraSDK.GlucoseMealTime) -> GlucoseMealTime {
89
+ switch time {
90
+ case .preprandial: return .preprandial
91
+ case .postprandial: return .postprandial
92
+ case .unknown: return .unknown
93
+ @unknown default: return .unknown
94
+ }
95
+ }
96
+
97
+ static func specimen(_ specimen: TerraSDK.GlucoseSpecimen) -> GlucoseSpecimen {
98
+ switch specimen {
99
+ case .capillary: return .capillary
100
+ case .interstitial: return .interstitial
101
+ case .plasma: return .plasma
102
+ case .serum: return .serum
103
+ case .tears: return .tears
104
+ case .wholeBlood: return .wholeBlood
105
+ case .unknown: return .unknown
106
+ @unknown default: return .unknown
107
+ }
108
+ }
109
+
110
+ static func temperatureMetric(_ metric: TerraSDK.BodyTemperatureMetric) -> BodyTemperatureMetric? {
111
+ switch metric {
112
+ case .body: return .body
113
+ case .basal: return .basal
114
+ case .wrist: return .wrist
115
+ case .skin: return .skin
116
+ @unknown default: return nil
117
+ }
118
+ }
119
+
120
+ static func variabilityMetric(_ metric: TerraSDK.HeartRateVariabilityMetric) -> HeartRateVariabilityMetric? {
121
+ switch metric {
122
+ case .sdnn: return .sdnn
123
+ case .rmssd: return .rmssd
124
+ @unknown default: return nil
125
+ }
126
+ }
127
+
128
+ static func testType(_ type: TerraSDK.VO2MaxTestType) -> VO2MaxTestType? {
129
+ switch type {
130
+ case .maxExercise: return .maxExercise
131
+ case .predictedSubMaxExercise: return .predictedSubMaxExercise
132
+ case .predictedNonExercise: return .predictedNonExercise
133
+ @unknown default: return nil
134
+ }
135
+ }
136
+
137
+ static func bodyReadingKind(_ kind: TerraSDK.BodyReading.Kind) -> BodyReadingKind? {
138
+ switch kind {
139
+ case .measurement(let metric, let value):
140
+ return bodyMetric(metric).map { .measurement(metric: $0, value: value) }
141
+ case .bloodPressure(let systolic, let diastolic):
142
+ return .bloodPressure(systolic: systolic, diastolic: diastolic)
143
+ case .bloodGlucose(let value, let unit, let mealTime, let specimen):
144
+ return .bloodGlucose(
145
+ value: value, unit: glucoseUnit(unit), mealTime: mealTime.map(Self.mealTime),
146
+ specimen: specimen.map(Self.specimen))
147
+ case .oxygenSaturation(let fraction):
148
+ return .oxygenSaturation(fraction: fraction)
149
+ case .temperature(let metric, let celsius):
150
+ return temperatureMetric(metric).map { .temperature(metric: $0, celsius: celsius) }
151
+ case .heartRateVariability(let metric, let milliseconds):
152
+ return variabilityMetric(metric).map { .heartRateVariability(metric: $0, milliseconds: milliseconds) }
153
+ case .respiratoryRate(let breathsPerMinute):
154
+ return .respiratoryRate(breathsPerMinute: breathsPerMinute)
155
+ case .vo2Max(let value, let type):
156
+ return .vo2Max(millilitresPerKilogramMinute: value, testType: type.flatMap(testType))
157
+ case .insulinDelivery, .electrocardiogram, .heartbeatSeries:
158
+ return nil
159
+ @unknown default:
160
+ return nil
161
+ }
162
+ }
163
+
164
+ static func bodyReading(_ reading: TerraSDK.BodyReading) -> BodyReading? {
165
+ bodyReadingKind(reading.kind).map {
166
+ BodyReading(
167
+ id: reading.id.uuidString,
168
+ kind: $0,
169
+ start: BridgeInstant.format(reading.interval.start),
170
+ end: BridgeInstant.format(reading.interval.end),
171
+ source: sampleSource(reading.source),
172
+ userEntered: reading.userEntered,
173
+ timeZone: reading.timeZone?.identifier)
174
+ }
175
+ }
176
+
177
+ static func route(_ route: TerraSDK.WorkoutRoute) -> WorkoutRoute {
178
+ WorkoutRoute(
179
+ id: route.id.uuidString,
180
+ workoutId: route.workoutId.uuidString,
181
+ start: BridgeInstant.format(route.interval.start),
182
+ end: BridgeInstant.format(route.interval.end),
183
+ points: route.points.map {
184
+ RoutePoint(time: BridgeInstant.format($0.time), latitude: $0.latitude, longitude: $0.longitude)
185
+ },
186
+ source: sampleSource(route.source),
187
+ timeZone: route.timeZone?.identifier)
188
+ }
189
+
190
+ static func intensityMetric(_ kind: TerraSDK.WorkoutIntensitySample.Kind) -> WorkoutIntensityMetric? {
191
+ switch kind {
192
+ case .speed: return .speed
193
+ case .power: return .power
194
+ case .cadence: return .cadence
195
+ @unknown default: return nil
196
+ }
197
+ }
198
+
199
+ static func intensity(_ sample: TerraSDK.WorkoutIntensitySample) -> WorkoutIntensitySample? {
200
+ intensityMetric(sample.kind).map {
201
+ WorkoutIntensitySample(
202
+ id: sample.id.uuidString,
203
+ metric: $0,
204
+ workoutId: sample.workoutId.uuidString,
205
+ start: BridgeInstant.format(sample.interval.start),
206
+ end: BridgeInstant.format(sample.interval.end),
207
+ value: sample.value,
208
+ source: sampleSource(sample.source),
209
+ userEntered: sample.userEntered,
210
+ timeZone: sample.timeZone?.identifier)
211
+ }
212
+ }
213
+
214
+ static func hydration(_ sample: TerraSDK.HydrationSample) -> HydrationSample {
215
+ HydrationSample(
216
+ id: sample.id.uuidString,
217
+ start: BridgeInstant.format(sample.interval.start),
218
+ end: BridgeInstant.format(sample.interval.end),
219
+ millilitres: sample.millilitres,
220
+ source: sampleSource(sample.source),
221
+ userEntered: sample.userEntered,
222
+ timeZone: sample.timeZone?.identifier)
223
+ }
224
+
225
+ static func availability(_ availability: TerraSDK.StoreAvailability) -> StoreAvailability {
226
+ switch availability {
227
+ case .available: return .available
228
+ case .unsupportedDevice: return .unsupportedDevice
229
+ @unknown default: return .unsupportedDevice
230
+ }
231
+ }
232
+
233
+ static func eventKind(_ kind: TerraSDK.MenstrualEvent.Kind) -> MenstrualEventKind? {
234
+ switch kind {
235
+ case .intermenstrualBleeding: return .intermenstrualBleeding
236
+ case .ovulationTest: return .ovulationTest
237
+ case .cervicalMucus: return .cervicalMucus
238
+ case .sexualActivity, .pregnancyTest, .progesteroneTest, .pregnancy, .lactation, .contraceptive,
239
+ .persistentIntermenstrualBleeding, .infrequentCycles, .irregularCycles, .prolongedPeriods,
240
+ .bleedingDuringPregnancy, .bleedingAfterPregnancy:
241
+ return nil
242
+ @unknown default: return nil
243
+ }
244
+ }
245
+
246
+ static func menstrualEvent(_ event: TerraSDK.MenstrualEvent) -> MenstrualEvent? {
247
+ eventKind(event.kind).map {
248
+ MenstrualEvent(
249
+ id: event.id.uuidString,
250
+ kind: $0,
251
+ time: BridgeInstant.format(event.instant),
252
+ value: event.value,
253
+ storeIdentifier: event.storeIdentifier,
254
+ source: sampleSource(event.source),
255
+ userEntered: event.userEntered,
256
+ timeZone: event.timeZone?.identifier)
257
+ }
258
+ }
259
+ }
@@ -77,6 +77,8 @@ enum Conversions {
77
77
  case .daily: return .daily
78
78
  case .sleep: return .sleep
79
79
  case .nutrition: return .nutrition
80
+ case .menstruation: return .menstruation
81
+ case .athlete: return .athlete
80
82
  }
81
83
  }
82
84
 
@@ -88,7 +90,9 @@ enum Conversions {
88
90
  case .daily: return .daily
89
91
  case .sleep: return .sleep
90
92
  case .nutrition: return .nutrition
91
- case .menstruation, .athlete, .healthObservation: return nil
93
+ case .menstruation: return .menstruation
94
+ case .athlete: return .athlete
95
+ case .healthObservation: return nil
92
96
  @unknown default: return nil
93
97
  }
94
98
  }
@@ -270,7 +274,130 @@ enum Conversions {
270
274
  distanceMeters: workout.distanceMeters,
271
275
  source: sampleSource(workout.source),
272
276
  userEntered: workout.userEntered,
273
- timeZone: workout.timeZone?.identifier)
277
+ timeZone: workout.timeZone?.identifier,
278
+ title: workout.title)
279
+ }
280
+
281
+ static func nutrient(_ nutrient: TerraSDK.Nutrient) -> Nutrient? {
282
+ switch nutrient {
283
+ case .energyConsumed: return .energyConsumed
284
+ case .protein: return .protein
285
+ case .carbohydrates: return .carbohydrates
286
+ case .fatTotal: return .fatTotal
287
+ case .fatSaturated: return .fatSaturated
288
+ case .fatMonounsaturated: return .fatMonounsaturated
289
+ case .fatPolyunsaturated: return .fatPolyunsaturated
290
+ case .sugar: return .sugar
291
+ case .fiber: return .fiber
292
+ case .cholesterol: return .cholesterol
293
+ case .sodium: return .sodium
294
+ case .potassium: return .potassium
295
+ case .calcium: return .calcium
296
+ case .iron: return .iron
297
+ case .magnesium: return .magnesium
298
+ case .zinc: return .zinc
299
+ case .phosphorus: return .phosphorus
300
+ case .iodine: return .iodine
301
+ case .manganese: return .manganese
302
+ case .molybdenum: return .molybdenum
303
+ case .selenium: return .selenium
304
+ case .copper: return .copper
305
+ case .chromium: return .chromium
306
+ case .chloride: return .chloride
307
+ case .caffeine: return .caffeine
308
+ case .vitaminA: return .vitaminA
309
+ case .vitaminC: return .vitaminC
310
+ case .vitaminD: return .vitaminD
311
+ case .vitaminE: return .vitaminE
312
+ case .vitaminK: return .vitaminK
313
+ case .vitaminB6: return .vitaminB6
314
+ case .vitaminB12: return .vitaminB12
315
+ case .thiamin: return .thiamin
316
+ case .riboflavin: return .riboflavin
317
+ case .niacin: return .niacin
318
+ case .folate: return .folate
319
+ case .biotin: return .biotin
320
+ case .pantothenicAcid: return .pantothenicAcid
321
+ @unknown default: return nil
322
+ }
323
+ }
324
+
325
+ static func mealType(_ type: TerraSDK.MealType) -> MealType {
326
+ switch type {
327
+ case .breakfast: return .breakfast
328
+ case .lunch: return .lunch
329
+ case .dinner: return .dinner
330
+ case .snack: return .snack
331
+ case .unknown: return .unknown
332
+ @unknown default: return .unknown
333
+ }
334
+ }
335
+
336
+ static func flow(_ flow: TerraSDK.MenstruationFlowDay.Flow) -> MenstruationFlow {
337
+ switch flow {
338
+ case .unspecified: return .unspecified
339
+ case .light: return .light
340
+ case .medium: return .medium
341
+ case .heavy: return .heavy
342
+ case .noFlow: return .noFlow
343
+ @unknown default: return .unspecified
344
+ }
345
+ }
346
+
347
+ static func biologicalSex(_ sex: TerraSDK.AthleteProfile.BiologicalSex) -> BiologicalSex {
348
+ switch sex {
349
+ case .female: return .female
350
+ case .male: return .male
351
+ case .other: return .other
352
+ case .notSet: return .notSet
353
+ @unknown default: return .notSet
354
+ }
355
+ }
356
+
357
+ static func moveMode(_ mode: TerraSDK.AthleteProfile.ActivityMoveMode) -> ActivityMoveMode? {
358
+ switch mode {
359
+ case .activeEnergy: return .activeEnergy
360
+ case .appleMoveTime: return .appleMoveTime
361
+ @unknown default: return nil
362
+ }
363
+ }
364
+
365
+ static func quantity(_ quantity: TerraSDK.DietaryQuantity) -> DietaryQuantity? {
366
+ guard let nutrient = nutrient(quantity.nutrient) else { return nil }
367
+ return DietaryQuantity(
368
+ id: quantity.id.uuidString,
369
+ nutrient: nutrient,
370
+ value: quantity.value,
371
+ start: BridgeInstant.format(quantity.interval.start),
372
+ end: BridgeInstant.format(quantity.interval.end),
373
+ mealType: mealType(quantity.mealType),
374
+ name: quantity.name,
375
+ foodCorrelationId: quantity.foodCorrelationID?.uuidString,
376
+ source: sampleSource(quantity.source),
377
+ userEntered: quantity.userEntered,
378
+ timeZone: quantity.timeZone?.identifier)
379
+ }
380
+
381
+ static func flowDay(_ day: TerraSDK.MenstruationFlowDay) -> MenstruationFlowDay {
382
+ MenstruationFlowDay(
383
+ id: day.id.uuidString,
384
+ start: BridgeInstant.format(day.interval.start),
385
+ end: BridgeInstant.format(day.interval.end),
386
+ flow: flow(day.flow),
387
+ cycleStart: day.cycleStart,
388
+ source: sampleSource(day.source),
389
+ userEntered: day.userEntered,
390
+ timeZone: day.timeZone?.identifier)
391
+ }
392
+
393
+ /// The birth date is a calendar day. HealthKit hands back components, which the store turns into
394
+ /// a `Date` at midnight in the device's zone, so the same zone reads the same day back out.
395
+ static func athleteProfile(_ profile: TerraSDK.AthleteProfile, zone: TimeZone) -> AthleteProfile {
396
+ AthleteProfile(
397
+ biologicalSex: biologicalSex(profile.biologicalSex),
398
+ dateOfBirth: profile.dateOfBirth.map { localDate($0, in: zone) },
399
+ wheelchairUse: profile.wheelchairUse,
400
+ activityMoveMode: profile.activityMoveMode.flatMap(moveMode))
274
401
  }
275
402
 
276
403
  /// A day, not an instant: sending the instant would let the receiver re-derive the day in its