@cariva-dev/exercise-sdk 2.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 (82) hide show
  1. package/CarivaExerciseSdk.podspec +20 -0
  2. package/README.md +374 -0
  3. package/android/build.gradle +66 -0
  4. package/android/src/main/AndroidManifest.xml +40 -0
  5. package/android/src/main/java/com/carivaexercisesdk/CarivaExerciseSdkPackage.kt +30 -0
  6. package/android/src/main/java/com/carivaexercisesdk/HealthConnectModule.kt +222 -0
  7. package/android/src/main/java/com/carivaexercisesdk/HealthConnectPermissionUsageActivity.kt +11 -0
  8. package/android/src/main/java/com/carivaexercisesdk/HealthConnectPermissionsRationaleActivity.kt +11 -0
  9. package/android/src/main/java/com/carivaexercisesdk/Pagination.kt +23 -0
  10. package/android/src/main/java/com/carivaexercisesdk/application/connection/command/ConnectCommand.kt +12 -0
  11. package/android/src/main/java/com/carivaexercisesdk/application/connection/dto/ConnectResultDto.kt +13 -0
  12. package/android/src/main/java/com/carivaexercisesdk/application/connection/handler/ConnectHandler.kt +79 -0
  13. package/android/src/main/java/com/carivaexercisesdk/application/connection/port/HealthConnectConnectionPort.kt +16 -0
  14. package/android/src/main/java/com/carivaexercisesdk/application/connection/port/PermissionRequestPort.kt +5 -0
  15. package/android/src/main/java/com/carivaexercisesdk/application/datasource/command/SetDatasourcePolicyCommand.kt +6 -0
  16. package/android/src/main/java/com/carivaexercisesdk/application/datasource/handler/GetDatasourcePolicyHandler.kt +10 -0
  17. package/android/src/main/java/com/carivaexercisesdk/application/datasource/handler/SetDatasourcePolicyHandler.kt +22 -0
  18. package/android/src/main/java/com/carivaexercisesdk/application/datasource/port/DatasourcePolicyRepository.kt +9 -0
  19. package/android/src/main/java/com/carivaexercisesdk/application/exercise/dto/BasalReadResultDto.kt +11 -0
  20. package/android/src/main/java/com/carivaexercisesdk/application/exercise/dto/ExerciseDataDto.kt +41 -0
  21. package/android/src/main/java/com/carivaexercisesdk/application/exercise/handler/GetExerciseDataHandler.kt +346 -0
  22. package/android/src/main/java/com/carivaexercisesdk/application/exercise/port/ExerciseRecordPort.kt +45 -0
  23. package/android/src/main/java/com/carivaexercisesdk/application/exercise/query/GetExerciseDataQuery.kt +9 -0
  24. package/android/src/main/java/com/carivaexercisesdk/domain/connection/entity/ConnectionAggregate.kt +13 -0
  25. package/android/src/main/java/com/carivaexercisesdk/domain/connection/service/ConnectionDecisionService.kt +37 -0
  26. package/android/src/main/java/com/carivaexercisesdk/domain/connection/valueobject/ConnectionNextAction.kt +8 -0
  27. package/android/src/main/java/com/carivaexercisesdk/domain/connection/valueobject/HealthConnectStatus.kt +8 -0
  28. package/android/src/main/java/com/carivaexercisesdk/domain/connection/valueobject/PermissionScope.kt +36 -0
  29. package/android/src/main/java/com/carivaexercisesdk/domain/datasource/entity/DatasourcePolicy.kt +8 -0
  30. package/android/src/main/java/com/carivaexercisesdk/domain/datasource/valueobject/DatasourceType.kt +14 -0
  31. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/ExerciseDomainService.kt +89 -0
  32. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectCaloriesFallbackMerger.kt +351 -0
  33. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectInternalsConstants.kt +55 -0
  34. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectModuleInternals.kt +316 -0
  35. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectOverlapNormalizer.kt +400 -0
  36. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectSourceTrust.kt +249 -0
  37. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectUnifiedRecordBuilder.kt +316 -0
  38. package/android/src/main/java/com/carivaexercisesdk/infrastructure/healthconnect/HealthConnectConnectionAdapter.kt +156 -0
  39. package/android/src/main/java/com/carivaexercisesdk/infrastructure/healthconnect/HealthConnectExerciseRecordAdapter.kt +464 -0
  40. package/android/src/main/java/com/carivaexercisesdk/infrastructure/persistence/InMemoryDatasourcePolicyRepository.kt +21 -0
  41. package/android/src/main/java/com/carivaexercisesdk/infrastructure/reactnative/ConnectResultMapper.kt +23 -0
  42. package/android/src/main/java/com/carivaexercisesdk/infrastructure/reactnative/DatasourcePolicyJsonParser.kt +51 -0
  43. package/android/src/main/java/com/carivaexercisesdk/infrastructure/reactnative/DatasourcePolicyMapper.kt +46 -0
  44. package/android/src/main/java/com/carivaexercisesdk/infrastructure/reactnative/ExerciseDataMapper.kt +99 -0
  45. package/android/src/test/java/com/carivaexercisesdk/ArchitectureDependencyRuleTest.kt +60 -0
  46. package/android/src/test/java/com/carivaexercisesdk/HealthConnectModuleDatasourceParserTest.kt +69 -0
  47. package/android/src/test/java/com/carivaexercisesdk/HealthConnectModuleInternalsTest.kt +406 -0
  48. package/android/src/test/java/com/carivaexercisesdk/application/connection/handler/ConnectHandlerTest.kt +153 -0
  49. package/android/src/test/java/com/carivaexercisesdk/application/datasource/handler/DatasourcePolicyRoundTripTest.kt +63 -0
  50. package/android/src/test/java/com/carivaexercisesdk/application/datasource/handler/SetDatasourcePolicyHandlerTest.kt +42 -0
  51. package/android/src/test/java/com/carivaexercisesdk/domain/connection/service/ConnectionDecisionServiceTest.kt +68 -0
  52. package/android/src/test/java/com/carivaexercisesdk/infrastructure/reactnative/DatasourcePolicyMapperTest.kt +22 -0
  53. package/ios/CarivaExerciseSdk.h +5 -0
  54. package/ios/CarivaExerciseSdk.mm +7 -0
  55. package/lib/module/connect/index.js +7 -0
  56. package/lib/module/connect/index.js.map +1 -0
  57. package/lib/module/datasource/index.js +10 -0
  58. package/lib/module/datasource/index.js.map +1 -0
  59. package/lib/module/exercise/index.js +7 -0
  60. package/lib/module/exercise/index.js.map +1 -0
  61. package/lib/module/index.js +6 -0
  62. package/lib/module/index.js.map +1 -0
  63. package/lib/module/native/module.js +13 -0
  64. package/lib/module/native/module.js.map +1 -0
  65. package/lib/module/package.json +1 -0
  66. package/lib/typescript/package.json +1 -0
  67. package/lib/typescript/src/connect/index.d.ts +16 -0
  68. package/lib/typescript/src/connect/index.d.ts.map +1 -0
  69. package/lib/typescript/src/datasource/index.d.ts +12 -0
  70. package/lib/typescript/src/datasource/index.d.ts.map +1 -0
  71. package/lib/typescript/src/exercise/index.d.ts +64 -0
  72. package/lib/typescript/src/exercise/index.d.ts.map +1 -0
  73. package/lib/typescript/src/index.d.ts +4 -0
  74. package/lib/typescript/src/index.d.ts.map +1 -0
  75. package/lib/typescript/src/native/module.d.ts +14 -0
  76. package/lib/typescript/src/native/module.d.ts.map +1 -0
  77. package/package.json +127 -0
  78. package/src/connect/index.ts +34 -0
  79. package/src/datasource/index.ts +20 -0
  80. package/src/exercise/index.ts +75 -0
  81. package/src/index.tsx +22 -0
  82. package/src/native/module.ts +23 -0
@@ -0,0 +1,153 @@
1
+ package com.carivaexercisesdk.application.connection.handler
2
+
3
+ import com.carivaexercisesdk.application.connection.command.ConnectCommand
4
+ import com.carivaexercisesdk.application.connection.command.MissingAppBehavior
5
+ import com.carivaexercisesdk.application.connection.port.HealthConnectConnectionPort
6
+ import com.carivaexercisesdk.application.connection.port.PermissionRequestPort
7
+ import com.carivaexercisesdk.domain.connection.valueobject.ConnectionNextAction
8
+ import com.carivaexercisesdk.domain.connection.valueobject.HealthConnectStatus
9
+ import com.carivaexercisesdk.domain.connection.valueobject.PermissionScope
10
+ import kotlinx.coroutines.runBlocking
11
+ import org.junit.Assert.assertEquals
12
+ import org.junit.Assert.assertFalse
13
+ import org.junit.Assert.assertTrue
14
+ import org.junit.Test
15
+
16
+ class ConnectHandlerTest {
17
+
18
+ @Test
19
+ fun handle_requestPermissionFalse_doesNotLaunchPermissionDialog() = runBlocking {
20
+ val connectionPort =
21
+ FakeConnectionPort(
22
+ status = HealthConnectStatus.AVAILABLE,
23
+ installed = true,
24
+ grantedPermissions = mutableSetOf()
25
+ )
26
+ val permissionPort = FakePermissionRequestPort()
27
+ val handler = ConnectHandler(connectionPort, permissionPort)
28
+
29
+ val result =
30
+ handler.handle(
31
+ ConnectCommand(
32
+ requestPermission = false,
33
+ permissionScope = listOf("steps")
34
+ )
35
+ )
36
+
37
+ assertEquals(ConnectionNextAction.REQUEST_PERMISSION, result.nextAction)
38
+ assertEquals(0, permissionPort.requestCalls)
39
+ assertFalse(result.ready)
40
+ }
41
+
42
+ @Test
43
+ fun handle_requestPermissionTrue_requestsAndUsesLatestGrantState() = runBlocking {
44
+ val connectionPort =
45
+ FakeConnectionPort(
46
+ status = HealthConnectStatus.AVAILABLE,
47
+ installed = true,
48
+ grantedPermissions = mutableSetOf()
49
+ )
50
+ val permissionPort =
51
+ FakePermissionRequestPort {
52
+ connectionPort.grantedPermissions += "perm.steps"
53
+ }
54
+ val handler = ConnectHandler(connectionPort, permissionPort)
55
+
56
+ val result =
57
+ handler.handle(
58
+ ConnectCommand(
59
+ requestPermission = true,
60
+ permissionScope = listOf("steps")
61
+ )
62
+ )
63
+
64
+ assertEquals(1, permissionPort.requestCalls)
65
+ assertEquals(ConnectionNextAction.NONE, result.nextAction)
66
+ assertTrue(result.ready)
67
+ }
68
+
69
+ @Test
70
+ fun handle_openMode_missingHealthConnect_opensHealthConnectStore() = runBlocking {
71
+ val connectionPort =
72
+ FakeConnectionPort(
73
+ status = HealthConnectStatus.UNAVAILABLE,
74
+ installed = false,
75
+ grantedPermissions = mutableSetOf()
76
+ )
77
+ val permissionPort = FakePermissionRequestPort()
78
+ val handler = ConnectHandler(connectionPort, permissionPort)
79
+
80
+ val result =
81
+ handler.handle(
82
+ ConnectCommand(
83
+ onMissingApp = MissingAppBehavior.OPEN,
84
+ requestPermission = false,
85
+ permissionScope = listOf("steps")
86
+ )
87
+ )
88
+
89
+ assertTrue(connectionPort.openStoreCalled)
90
+ assertEquals(ConnectionNextAction.INSTALL_HEALTH_CONNECT, result.nextAction)
91
+ assertFalse(result.ready)
92
+ }
93
+
94
+ @Test
95
+ fun handle_invalidPermissionScope_throwsValidationError() = runBlocking {
96
+ val connectionPort =
97
+ FakeConnectionPort(
98
+ status = HealthConnectStatus.AVAILABLE,
99
+ installed = true,
100
+ grantedPermissions = mutableSetOf()
101
+ )
102
+ val permissionPort = FakePermissionRequestPort()
103
+ val handler = ConnectHandler(connectionPort, permissionPort)
104
+
105
+ try {
106
+ handler.handle(ConnectCommand(permissionScope = listOf("unknown_scope")))
107
+ } catch (e: InvalidPermissionScopeException) {
108
+ assertTrue(e.unsupportedScopes.contains("unknown_scope"))
109
+ return@runBlocking
110
+ }
111
+
112
+ throw AssertionError("Expected InvalidPermissionScopeException")
113
+ }
114
+
115
+ private class FakeConnectionPort(
116
+ val status: HealthConnectStatus,
117
+ val installed: Boolean,
118
+ val grantedPermissions: MutableSet<String>
119
+ ) : HealthConnectConnectionPort {
120
+ var openStoreCalled: Boolean = false
121
+
122
+ override suspend fun getHealthConnectStatus(): HealthConnectStatus {
123
+ return status
124
+ }
125
+
126
+ override fun isHealthConnectInstalled(): Boolean {
127
+ return installed
128
+ }
129
+
130
+ override suspend fun getGrantedPermissions(): Set<String> {
131
+ return grantedPermissions
132
+ }
133
+
134
+ override fun resolvePermissions(scopes: Set<PermissionScope>): Set<String> {
135
+ return scopes.mapTo(mutableSetOf()) { "perm.${it.wireValue}" }
136
+ }
137
+
138
+ override fun openHealthConnectStore() {
139
+ openStoreCalled = true
140
+ }
141
+ }
142
+
143
+ private class FakePermissionRequestPort(
144
+ private val onRequest: () -> Unit = {}
145
+ ) : PermissionRequestPort {
146
+ var requestCalls: Int = 0
147
+
148
+ override suspend fun requestPermissions(permissions: Set<String>) {
149
+ requestCalls += 1
150
+ onRequest()
151
+ }
152
+ }
153
+ }
@@ -0,0 +1,63 @@
1
+ package com.carivaexercisesdk.application.datasource.handler
2
+
3
+ import com.carivaexercisesdk.application.datasource.command.SetDatasourcePolicyCommand
4
+ import com.carivaexercisesdk.domain.datasource.valueobject.DatasourceType
5
+ import com.carivaexercisesdk.infrastructure.persistence.InMemoryDatasourcePolicyRepository
6
+ import com.carivaexercisesdk.infrastructure.reactnative.DatasourcePolicyJsonParser
7
+ import com.carivaexercisesdk.infrastructure.reactnative.DatasourcePolicyMapper
8
+ import org.junit.Assert.assertEquals
9
+ import org.junit.Test
10
+
11
+ class DatasourcePolicyRoundTripTest {
12
+ @Test
13
+ fun setThenGet_returnsCanonicalEquivalentConfig() {
14
+ val repository = InMemoryDatasourcePolicyRepository()
15
+ val handler = SetDatasourcePolicyHandler(repository)
16
+ val allowlist =
17
+ DatasourcePolicyJsonParser.resolveAllowlist(
18
+ hasAllowlistKey = true,
19
+ parsedAllowlist = listOf("DEVICE", " app ", "manual_inputx")
20
+ )
21
+ val scopePackages =
22
+ DatasourcePolicyJsonParser.resolveScopePackages(
23
+ listOf(" COM.FIT.APP ", "com.fit.app", "com.google.fit", "")
24
+ )
25
+
26
+ handler.handle(
27
+ SetDatasourcePolicyCommand(
28
+ allowlist = allowlist,
29
+ packageAllowlist = scopePackages
30
+ )
31
+ )
32
+
33
+ val canonical = DatasourcePolicyMapper.toCanonicalConfig(repository.get())
34
+ assertEquals(listOf("app", "device"), canonical.allowlist)
35
+ assertEquals(listOf("com.fit.app", "com.google.fit"), canonical.packages)
36
+ }
37
+
38
+ @Test
39
+ fun setMissingAllowlist_defaultsToAllSources() {
40
+ val repository = InMemoryDatasourcePolicyRepository()
41
+ val handler = SetDatasourcePolicyHandler(repository)
42
+ val allowlist =
43
+ DatasourcePolicyJsonParser.resolveAllowlist(
44
+ hasAllowlistKey = false,
45
+ parsedAllowlist = emptyList()
46
+ )
47
+ val scopePackages = DatasourcePolicyJsonParser.resolveScopePackages(emptyList())
48
+
49
+ handler.handle(
50
+ SetDatasourcePolicyCommand(
51
+ allowlist = allowlist,
52
+ packageAllowlist = scopePackages
53
+ )
54
+ )
55
+
56
+ val canonical = DatasourcePolicyMapper.toCanonicalConfig(repository.get())
57
+ assertEquals(
58
+ DatasourceType.entries.map { it.wireValue }.sorted(),
59
+ canonical.allowlist
60
+ )
61
+ assertEquals(emptyList<String>(), canonical.packages)
62
+ }
63
+ }
@@ -0,0 +1,42 @@
1
+ package com.carivaexercisesdk.application.datasource.handler
2
+
3
+ import com.carivaexercisesdk.application.datasource.command.SetDatasourcePolicyCommand
4
+ import com.carivaexercisesdk.domain.datasource.valueobject.DatasourceType
5
+ import com.carivaexercisesdk.infrastructure.persistence.InMemoryDatasourcePolicyRepository
6
+ import org.junit.Assert.assertEquals
7
+ import org.junit.Test
8
+
9
+ class SetDatasourcePolicyHandlerTest {
10
+ @Test
11
+ fun handle_ignoresUnknownSources_andNormalizesPackageAllowlist() {
12
+ val handler = SetDatasourcePolicyHandler(InMemoryDatasourcePolicyRepository())
13
+
14
+ val policy =
15
+ handler.handle(
16
+ SetDatasourcePolicyCommand(
17
+ allowlist = listOf("DEVICE", " app ", "manual_inputx"),
18
+ packageAllowlist =
19
+ listOf(" com.Fit.App ", "COM.fit.app", "", "com.google.fit")
20
+ )
21
+ )
22
+
23
+ assertEquals(setOf(DatasourceType.DEVICE, DatasourceType.APP), policy.allowlist)
24
+ assertEquals(setOf("com.fit.app", "com.google.fit"), policy.packageAllowlist)
25
+ }
26
+
27
+ @Test
28
+ fun handle_emptyAllowlist_keepsNoAllowedSources() {
29
+ val handler = SetDatasourcePolicyHandler(InMemoryDatasourcePolicyRepository())
30
+
31
+ val policy =
32
+ handler.handle(
33
+ SetDatasourcePolicyCommand(
34
+ allowlist = emptyList(),
35
+ packageAllowlist = emptyList()
36
+ )
37
+ )
38
+
39
+ assertEquals(emptySet<DatasourceType>(), policy.allowlist)
40
+ assertEquals(emptySet<String>(), policy.packageAllowlist)
41
+ }
42
+ }
@@ -0,0 +1,68 @@
1
+ package com.carivaexercisesdk.domain.connection.service
2
+
3
+ import com.carivaexercisesdk.domain.connection.valueobject.ConnectionNextAction
4
+ import com.carivaexercisesdk.domain.connection.valueobject.HealthConnectStatus
5
+ import org.junit.Assert.assertEquals
6
+ import org.junit.Assert.assertFalse
7
+ import org.junit.Assert.assertTrue
8
+ import org.junit.Test
9
+
10
+ class ConnectionDecisionServiceTest {
11
+ private val service = ConnectionDecisionService()
12
+
13
+ @Test
14
+ fun decide_healthConnectMissing_requestsInstall() {
15
+ val result =
16
+ service.decide(
17
+ healthConnectInstalled = false,
18
+ healthConnectStatus = HealthConnectStatus.UNAVAILABLE,
19
+ hasPermissions = false,
20
+ requestedPermissions = setOf("perm")
21
+ )
22
+
23
+ assertEquals(ConnectionNextAction.INSTALL_HEALTH_CONNECT, result.nextAction)
24
+ assertFalse(result.ready)
25
+ }
26
+
27
+ @Test
28
+ fun decide_providerUpdateRequired_requestsUpdate() {
29
+ val result =
30
+ service.decide(
31
+ healthConnectInstalled = true,
32
+ healthConnectStatus = HealthConnectStatus.PROVIDER_UPDATE_REQUIRED,
33
+ hasPermissions = true,
34
+ requestedPermissions = emptySet()
35
+ )
36
+
37
+ assertEquals(ConnectionNextAction.UPDATE_HEALTH_CONNECT, result.nextAction)
38
+ assertFalse(result.ready)
39
+ }
40
+
41
+ @Test
42
+ fun decide_missingPermissions_requestsPermission() {
43
+ val result =
44
+ service.decide(
45
+ healthConnectInstalled = true,
46
+ healthConnectStatus = HealthConnectStatus.AVAILABLE,
47
+ hasPermissions = false,
48
+ requestedPermissions = setOf("perm")
49
+ )
50
+
51
+ assertEquals(ConnectionNextAction.REQUEST_PERMISSION, result.nextAction)
52
+ assertFalse(result.ready)
53
+ }
54
+
55
+ @Test
56
+ fun decide_availableAndPermitted_isReady() {
57
+ val result =
58
+ service.decide(
59
+ healthConnectInstalled = true,
60
+ healthConnectStatus = HealthConnectStatus.AVAILABLE,
61
+ hasPermissions = true,
62
+ requestedPermissions = setOf("perm")
63
+ )
64
+
65
+ assertEquals(ConnectionNextAction.NONE, result.nextAction)
66
+ assertTrue(result.ready)
67
+ }
68
+ }
@@ -0,0 +1,22 @@
1
+ package com.carivaexercisesdk.infrastructure.reactnative
2
+
3
+ import com.carivaexercisesdk.domain.datasource.entity.DatasourcePolicy
4
+ import com.carivaexercisesdk.domain.datasource.valueobject.DatasourceType
5
+ import org.junit.Assert.assertEquals
6
+ import org.junit.Test
7
+
8
+ class DatasourcePolicyMapperTest {
9
+ @Test
10
+ fun toCanonicalConfig_returnsCanonicalSortedAllowlistAndScopePackages() {
11
+ val policy =
12
+ DatasourcePolicy(
13
+ allowlist = setOf(DatasourceType.UNKNOWN, DatasourceType.DEVICE),
14
+ packageAllowlist = setOf("b.pkg", "a.pkg")
15
+ )
16
+
17
+ val config = DatasourcePolicyMapper.toCanonicalConfig(policy)
18
+
19
+ assertEquals(listOf("device", "unknown"), config.allowlist)
20
+ assertEquals(listOf("a.pkg", "b.pkg"), config.packages)
21
+ }
22
+ }
@@ -0,0 +1,5 @@
1
+ #import <React/RCTBridgeModule.h>
2
+
3
+ @interface CarivaExerciseSdk : NSObject <RCTBridgeModule>
4
+
5
+ @end
@@ -0,0 +1,7 @@
1
+ #import "CarivaExerciseSdk.h"
2
+
3
+ @implementation CarivaExerciseSdk
4
+
5
+ RCT_EXPORT_MODULE()
6
+
7
+ @end
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+
3
+ import { getHealthConnectModule } from "../native/module.js";
4
+ export function connect(options = {}) {
5
+ return getHealthConnectModule().connect(JSON.stringify(options));
6
+ }
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getHealthConnectModule","connect","options","JSON","stringify"],"sourceRoot":"../../../src","sources":["connect/index.ts"],"mappings":";;AAAA,SAASA,sBAAsB,QAAQ,qBAAkB;AA+BzD,OAAO,SAASC,OAAOA,CAACC,OAAuB,GAAG,CAAC,CAAC,EAA0B;EAC5E,OAAOF,sBAAsB,CAAC,CAAC,CAACC,OAAO,CAACE,IAAI,CAACC,SAAS,CAACF,OAAO,CAAC,CAAC;AAClE","ignoreList":[]}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ import { getHealthConnectModule } from "../native/module.js";
4
+ export function setAllowDatasource(config) {
5
+ return getHealthConnectModule().setAllowDatasource(JSON.stringify(config));
6
+ }
7
+ export function getAllowDatasource() {
8
+ return getHealthConnectModule().getAllowDatasource();
9
+ }
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getHealthConnectModule","setAllowDatasource","config","JSON","stringify","getAllowDatasource"],"sourceRoot":"../../../src","sources":["datasource/index.ts"],"mappings":";;AAAA,SAASA,sBAAsB,QAAQ,qBAAkB;AAWzD,OAAO,SAASC,kBAAkBA,CAChCC,MAAwB,EACO;EAC/B,OAAOF,sBAAsB,CAAC,CAAC,CAACC,kBAAkB,CAACE,IAAI,CAACC,SAAS,CAACF,MAAM,CAAC,CAAC;AAC5E;AAEA,OAAO,SAASG,kBAAkBA,CAAA,EAA8B;EAC9D,OAAOL,sBAAsB,CAAC,CAAC,CAACK,kBAAkB,CAAC,CAAC;AACtD","ignoreList":[]}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+
3
+ import { getHealthConnectModule } from "../native/module.js";
4
+ export function getExerciseData(options) {
5
+ return getHealthConnectModule().getExerciseData(JSON.stringify(options));
6
+ }
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["getHealthConnectModule","getExerciseData","options","JSON","stringify"],"sourceRoot":"../../../src","sources":["exercise/index.ts"],"mappings":";;AAAA,SAASA,sBAAsB,QAAQ,qBAAkB;AAsEzD,OAAO,SAASC,eAAeA,CAC7BC,OAA+B,EACR;EACvB,OAAOF,sBAAsB,CAAC,CAAC,CAACC,eAAe,CAACE,IAAI,CAACC,SAAS,CAACF,OAAO,CAAC,CAAC;AAC1E","ignoreList":[]}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ export { connect } from "./connect/index.js";
4
+ export { getExerciseData } from "./exercise/index.js";
5
+ export { getAllowDatasource, setAllowDatasource } from "./datasource/index.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["connect","getExerciseData","getAllowDatasource","setAllowDatasource"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SACEA,OAAO,QAIF,oBAAW;AAElB,SACEC,eAAe,QAMV,qBAAY;AAEnB,SACEC,kBAAkB,EAClBC,kBAAkB,QAGb,uBAAc","ignoreList":[]}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ import { NativeModules } from 'react-native';
4
+ const {
5
+ HealthConnectModule
6
+ } = NativeModules;
7
+ export function getHealthConnectModule() {
8
+ if (!HealthConnectModule) {
9
+ throw new Error('HealthConnectModule is not linked or unavailable.');
10
+ }
11
+ return HealthConnectModule;
12
+ }
13
+ //# sourceMappingURL=module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeModules","HealthConnectModule","getHealthConnectModule","Error"],"sourceRoot":"../../../src","sources":["native/module.ts"],"mappings":";;AAAA,SAASA,aAAa,QAAQ,cAAc;AAa5C,MAAM;EAAEC;AAAoB,CAAC,GAAGD,aAE/B;AAED,OAAO,SAASE,sBAAsBA,CAAA,EAA4B;EAChE,IAAI,CAACD,mBAAmB,EAAE;IACxB,MAAM,IAAIE,KAAK,CAAC,mDAAmD,CAAC;EACtE;EACA,OAAOF,mBAAmB;AAC5B","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,16 @@
1
+ export type PermissionScope = 'steps' | 'activetimes' | 'calories' | 'distances';
2
+ export type ConnectOptions = {
3
+ onMissingApp?: 'status' | 'open';
4
+ requestPermission?: boolean;
5
+ permissionScope?: PermissionScope[];
6
+ };
7
+ export type ConnectResult = {
8
+ ready: boolean;
9
+ healthConnectInstalled: boolean;
10
+ healthConnectStatus: 'AVAILABLE' | 'PROVIDER_UPDATE_REQUIRED' | 'UNAVAILABLE' | 'UNKNOWN';
11
+ hasPermissions: boolean;
12
+ nextAction: 'INSTALL_HEALTH_CONNECT' | 'UPDATE_HEALTH_CONNECT' | 'REQUEST_PERMISSION' | 'NONE';
13
+ requestedPermissions?: string[];
14
+ };
15
+ export declare function connect(options?: ConnectOptions): Promise<ConnectResult>;
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/connect/index.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,eAAe,GACvB,OAAO,GACP,aAAa,GACb,UAAU,GACV,WAAW,CAAC;AAEhB,MAAM,MAAM,cAAc,GAAG;IAC3B,YAAY,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IACjC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,eAAe,EAAE,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,sBAAsB,EAAE,OAAO,CAAC;IAChC,mBAAmB,EACf,WAAW,GACX,0BAA0B,GAC1B,aAAa,GACb,SAAS,CAAC;IACd,cAAc,EAAE,OAAO,CAAC;IACxB,UAAU,EACN,wBAAwB,GACxB,uBAAuB,GACvB,oBAAoB,GACpB,MAAM,CAAC;IACX,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC,CAAC;AAEF,wBAAgB,OAAO,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAE5E"}
@@ -0,0 +1,12 @@
1
+ export type DatasourceType = 'manual_input' | 'device' | 'app' | 'unknown';
2
+ export type DatasourceConfig = {
3
+ allowlist: DatasourceType[];
4
+ scope?: {
5
+ packages?: string[];
6
+ };
7
+ };
8
+ export declare function setAllowDatasource(config: DatasourceConfig): Promise<{
9
+ success: boolean;
10
+ }>;
11
+ export declare function getAllowDatasource(): Promise<DatasourceConfig>;
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/datasource/index.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG,cAAc,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;AAE3E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,KAAK,CAAC,EAAE;QACN,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH,CAAC;AAEF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAE/B;AAED,wBAAgB,kBAAkB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAE9D"}
@@ -0,0 +1,64 @@
1
+ export type TrustLevel = 'trusted' | 'low_confidence';
2
+ export type UnifiedRecordMeta = {
3
+ source: string;
4
+ device: string;
5
+ deviceModel: string;
6
+ trustLevel: TrustLevel;
7
+ };
8
+ export type UnifiedIntervalRecord = {
9
+ steps: number;
10
+ activeCalories: number;
11
+ activeCaloriesUnit: 'kcal';
12
+ distance: number;
13
+ distanceUnit: 'km';
14
+ activeTime: number;
15
+ activeTimeUnit: 'milliseconds';
16
+ startDate: string;
17
+ endDate: string;
18
+ meta: UnifiedRecordMeta;
19
+ };
20
+ export type ExerciseData = {
21
+ totalKcal: number;
22
+ totalSteps: number;
23
+ totalActiveTimeMillis: number;
24
+ totalActiveTime?: number;
25
+ totalDistanceMeters: number;
26
+ timeZone: string;
27
+ records: UnifiedIntervalRecord[];
28
+ warnings?: string[];
29
+ integrity?: {
30
+ projectionPreserved: boolean;
31
+ roundingScale: number;
32
+ };
33
+ diagnostics?: {
34
+ fallbackUsedSegments: number;
35
+ fallbackSuppressedSegments: number;
36
+ idleGateSuppressedSegments: number;
37
+ basalSeedApplied: boolean;
38
+ seededFromBeforeSince: boolean;
39
+ basalSeedAgeHours?: number;
40
+ };
41
+ debug?: {
42
+ directActiveCaloriesKcal: number;
43
+ totalCaloriesKcal: number;
44
+ basalCaloriesKcal: number;
45
+ mergedActiveCaloriesKcal: number;
46
+ fallbackContributionKcal: number;
47
+ fallbackUsedSegments: number;
48
+ fallbackSuppressedSegments: number;
49
+ idleGateSuppressedSegments: number;
50
+ basalSeedApplied: boolean;
51
+ seededFromBeforeSince: boolean;
52
+ basalSeedAgeHours?: number;
53
+ basalIntervalsCount: number;
54
+ };
55
+ };
56
+ export type GetExerciseDataOptions = {
57
+ sinceMillis: number;
58
+ untilMillis: number;
59
+ type?: 'steps' | 'activetimes' | 'calories' | 'distances' | 'all';
60
+ bucketPeriod?: 'daily' | 'hourly';
61
+ debug?: boolean;
62
+ };
63
+ export declare function getExerciseData(options: GetExerciseDataOptions): Promise<ExerciseData>;
64
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/exercise/index.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,gBAAgB,CAAC;AAEtD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,UAAU,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,cAAc,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,iBAAiB,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB,EAAE,MAAM,CAAC;IAE9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE;QACV,mBAAmB,EAAE,OAAO,CAAC;QAC7B,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,WAAW,CAAC,EAAE;QACZ,oBAAoB,EAAE,MAAM,CAAC;QAC7B,0BAA0B,EAAE,MAAM,CAAC;QACnC,0BAA0B,EAAE,MAAM,CAAC;QACnC,gBAAgB,EAAE,OAAO,CAAC;QAC1B,qBAAqB,EAAE,OAAO,CAAC;QAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,KAAK,CAAC,EAAE;QACN,wBAAwB,EAAE,MAAM,CAAC;QACjC,iBAAiB,EAAE,MAAM,CAAC;QAC1B,iBAAiB,EAAE,MAAM,CAAC;QAC1B,wBAAwB,EAAE,MAAM,CAAC;QACjC,wBAAwB,EAAE,MAAM,CAAC;QACjC,oBAAoB,EAAE,MAAM,CAAC;QAC7B,0BAA0B,EAAE,MAAM,CAAC;QACnC,0BAA0B,EAAE,MAAM,CAAC;QACnC,gBAAgB,EAAE,OAAO,CAAC;QAC1B,qBAAqB,EAAE,OAAO,CAAC;QAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,mBAAmB,EAAE,MAAM,CAAC;KAC7B,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,OAAO,GAAG,aAAa,GAAG,UAAU,GAAG,WAAW,GAAG,KAAK,CAAC;IAClE,YAAY,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,wBAAgB,eAAe,CAC7B,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,YAAY,CAAC,CAEvB"}
@@ -0,0 +1,4 @@
1
+ export { connect, type ConnectOptions, type ConnectResult, type PermissionScope, } from './connect';
2
+ export { getExerciseData, type ExerciseData, type GetExerciseDataOptions, type TrustLevel, type UnifiedIntervalRecord, type UnifiedRecordMeta, } from './exercise';
3
+ export { getAllowDatasource, setAllowDatasource, type DatasourceConfig, type DatasourceType, } from './datasource';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,eAAe,EACf,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,GACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,KAAK,cAAc,GACpB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { ConnectResult } from '../connect';
2
+ import type { DatasourceConfig } from '../datasource';
3
+ import type { ExerciseData } from '../exercise';
4
+ type HealthConnectModuleSpec = {
5
+ connect(optionsJson: string): Promise<ConnectResult>;
6
+ getExerciseData(optionsJson: string): Promise<ExerciseData>;
7
+ setAllowDatasource(configJson: string): Promise<{
8
+ success: boolean;
9
+ }>;
10
+ getAllowDatasource(): Promise<DatasourceConfig>;
11
+ };
12
+ export declare function getHealthConnectModule(): HealthConnectModuleSpec;
13
+ export {};
14
+ //# sourceMappingURL=module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../../src/native/module.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,KAAK,uBAAuB,GAAG;IAC7B,OAAO,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACrD,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5D,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACtE,kBAAkB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;CACjD,CAAC;AAMF,wBAAgB,sBAAsB,IAAI,uBAAuB,CAKhE"}