react-native-spike-sdk 4.3.53 → 4.3.73-beta.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 (61) hide show
  1. package/android/build.gradle +2 -2
  2. package/android/src/main/java/com/spikesdk/SpikeSdkModule.kt +192 -6
  3. package/app.plugin.js +269 -29
  4. package/lib/commonjs/index.js +7 -0
  5. package/lib/commonjs/index.js.map +1 -1
  6. package/lib/commonjs/v3/DataModels/MetricType.js +3 -3
  7. package/lib/commonjs/v3/DataModels/Provider.js +1 -0
  8. package/lib/commonjs/v3/DataModels/Provider.js.map +1 -1
  9. package/lib/commonjs/v3/DataModels/ProviderSource.js +1 -0
  10. package/lib/commonjs/v3/DataModels/ProviderSource.js.map +1 -1
  11. package/lib/commonjs/v3/DataModels/SamsungHealthDataAvailability.js +6 -0
  12. package/lib/commonjs/v3/DataModels/SamsungHealthDataAvailability.js.map +1 -0
  13. package/lib/commonjs/v3/DataModels/SamsungHealthDataAvailabilityStatus.js +37 -0
  14. package/lib/commonjs/v3/DataModels/SamsungHealthDataAvailabilityStatus.js.map +1 -0
  15. package/lib/commonjs/v3/SpikeRNConnectionAPIv3.js +111 -1
  16. package/lib/commonjs/v3/SpikeRNConnectionAPIv3.js.map +1 -1
  17. package/lib/commonjs/version.js +1 -1
  18. package/lib/commonjs/version.js.map +1 -1
  19. package/lib/module/index.js +2 -1
  20. package/lib/module/index.js.map +1 -1
  21. package/lib/module/v3/DataModels/MetricType.js +3 -3
  22. package/lib/module/v3/DataModels/Provider.js +1 -0
  23. package/lib/module/v3/DataModels/Provider.js.map +1 -1
  24. package/lib/module/v3/DataModels/ProviderSource.js +1 -0
  25. package/lib/module/v3/DataModels/ProviderSource.js.map +1 -1
  26. package/lib/module/v3/DataModels/SamsungHealthDataAvailability.js +4 -0
  27. package/lib/module/v3/DataModels/SamsungHealthDataAvailability.js.map +1 -0
  28. package/lib/module/v3/DataModels/SamsungHealthDataAvailabilityStatus.js +33 -0
  29. package/lib/module/v3/DataModels/SamsungHealthDataAvailabilityStatus.js.map +1 -0
  30. package/lib/module/v3/SpikeRNConnectionAPIv3.js +111 -1
  31. package/lib/module/v3/SpikeRNConnectionAPIv3.js.map +1 -1
  32. package/lib/module/version.js +1 -1
  33. package/lib/module/version.js.map +1 -1
  34. package/lib/typescript/index.d.ts +4 -2
  35. package/lib/typescript/index.d.ts.map +1 -1
  36. package/lib/typescript/v3/DataModels/BackgroundDeliveryConfig.d.ts +2 -0
  37. package/lib/typescript/v3/DataModels/BackgroundDeliveryConfig.d.ts.map +1 -1
  38. package/lib/typescript/v3/DataModels/MetricType.d.ts +3 -3
  39. package/lib/typescript/v3/DataModels/MetricType.d.ts.map +1 -1
  40. package/lib/typescript/v3/DataModels/Provider.d.ts +1 -0
  41. package/lib/typescript/v3/DataModels/Provider.d.ts.map +1 -1
  42. package/lib/typescript/v3/DataModels/ProviderSource.d.ts +1 -0
  43. package/lib/typescript/v3/DataModels/ProviderSource.d.ts.map +1 -1
  44. package/lib/typescript/v3/DataModels/SamsungHealthDataAvailability.d.ts +7 -0
  45. package/lib/typescript/v3/DataModels/SamsungHealthDataAvailability.d.ts.map +1 -0
  46. package/lib/typescript/v3/DataModels/SamsungHealthDataAvailabilityStatus.d.ts +28 -0
  47. package/lib/typescript/v3/DataModels/SamsungHealthDataAvailabilityStatus.d.ts.map +1 -0
  48. package/lib/typescript/v3/SpikeRNConnectionAPIv3.d.ts +57 -1
  49. package/lib/typescript/v3/SpikeRNConnectionAPIv3.d.ts.map +1 -1
  50. package/lib/typescript/version.d.ts +1 -1
  51. package/lib/typescript/version.d.ts.map +1 -1
  52. package/package.json +1 -1
  53. package/src/index.ts +4 -0
  54. package/src/v3/DataModels/BackgroundDeliveryConfig.ts +2 -0
  55. package/src/v3/DataModels/MetricType.ts +3 -3
  56. package/src/v3/DataModels/Provider.ts +1 -0
  57. package/src/v3/DataModels/ProviderSource.ts +1 -0
  58. package/src/v3/DataModels/SamsungHealthDataAvailability.ts +9 -0
  59. package/src/v3/DataModels/SamsungHealthDataAvailabilityStatus.ts +34 -0
  60. package/src/v3/SpikeRNConnectionAPIv3.ts +127 -1
  61. package/src/version.ts +1 -1
@@ -9,7 +9,7 @@ buildscript {
9
9
  }
10
10
 
11
11
  dependencies {
12
- classpath "com.android.tools.build:gradle:7.2.1"
12
+ classpath "com.android.tools.build:gradle:8.6.0"
13
13
  // noinspection DifferentKotlinGradleVersion
14
14
  classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
15
15
  }
@@ -76,7 +76,7 @@ dependencies {
76
76
  //noinspection GradleDynamicVersion
77
77
  implementation "com.facebook.react:react-android:0.71.3"
78
78
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
79
- implementation 'com.spikeapi.sdk:spike-sdk:4.2.82'
79
+ implementation 'com.spikeapi.sdk:spike-sdk:4.3.12'
80
80
  implementation 'androidx.core:core-ktx:1.9.0'
81
81
  implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1'
82
82
  implementation 'com.google.code.gson:gson:2.10.1'
@@ -1026,8 +1026,11 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
1026
1026
  promise: Promise
1027
1027
  ) {
1028
1028
  executeV3MethodWithConnection("enableBackgroundDelivery", connectionUUID, promise) { connection ->
1029
- if (!connection.isHealthConnectIntegrationEnabled()) {
1030
- throw SpikeExceptions.SpikeException("Health Connect should be enabled before calling enableBackgroundDelivery")
1029
+ val healthConnectEnabled = connection.isHealthConnectIntegrationEnabled()
1030
+ val samsungHealthDataEnabled = connection.isSamsungHealthDataIntegrationEnabled()
1031
+
1032
+ if (!healthConnectEnabled && !samsungHealthDataEnabled) {
1033
+ throw SpikeExceptions.SpikeException("Either Health Connect or Samsung Health Data should be enabled before calling enableBackgroundDelivery")
1031
1034
  }
1032
1035
 
1033
1036
  val statTypes = statisticTypes.toArrayList().mapNotNull {
@@ -1063,8 +1066,11 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
1063
1066
  promise: Promise
1064
1067
  ) {
1065
1068
  executeV3MethodWithConnection("disableBackgroundDelivery", connectionUUID, promise) { connection ->
1066
- if (!connection.isHealthConnectIntegrationEnabled()) {
1067
- throw SpikeExceptions.SpikeException("Health Connect should be enabled before calling disableBackgroundDelivery")
1069
+ val healthConnectEnabled = connection.isHealthConnectIntegrationEnabled()
1070
+ val samsungHealthDataEnabled = connection.isSamsungHealthDataIntegrationEnabled()
1071
+
1072
+ if (!healthConnectEnabled && !samsungHealthDataEnabled) {
1073
+ throw SpikeExceptions.SpikeException("Either Health Connect or Samsung Health Data should be enabled before calling disableBackgroundDelivery")
1068
1074
  }
1069
1075
  connection.disableBackgroundDelivery()
1070
1076
  promise.resolve(true)
@@ -1077,8 +1083,11 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
1077
1083
  promise: Promise
1078
1084
  ) {
1079
1085
  executeV3MethodWithConnection("getBackgroundDeliveryConfig", connectionUUID, promise) { connection ->
1080
- if (!connection.isHealthConnectIntegrationEnabled()) {
1081
- throw SpikeExceptions.SpikeException("Health Connect should be enabled before calling getBackgroundDeliveryConfig")
1086
+ val healthConnectEnabled = connection.isHealthConnectIntegrationEnabled()
1087
+ val samsungHealthDataEnabled = connection.isSamsungHealthDataIntegrationEnabled()
1088
+
1089
+ if (!healthConnectEnabled && !samsungHealthDataEnabled) {
1090
+ throw SpikeExceptions.SpikeException("Either Health Connect or Samsung Health Data should be enabled before calling getBackgroundDeliveryConfig")
1082
1091
  }
1083
1092
  val result = connection.getBackgroundDeliveryConfig()
1084
1093
  if (result == null) {
@@ -1148,6 +1157,183 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
1148
1157
  }
1149
1158
  }
1150
1159
 
1160
+ /// --- Samsung Health Data permissions ---
1161
+
1162
+ @ReactMethod
1163
+ fun checkSamsungHealthDataAvailability(connectionUUID: String, promise: Promise) {
1164
+ executeV3MethodWithConnection("checkSamsungHealthDataAvailability", connectionUUID, promise) { connection ->
1165
+ val activity = reactApplicationContext.currentActivity
1166
+ if (activity == null) {
1167
+ throw SpikeExceptions.SpikeException("Activity is required to check Samsung Health Data availability")
1168
+ }
1169
+ val result = connection.checkSamsungHealthDataAvailability(activity)
1170
+ promise.resolve(SpikeConnectionAPIv3.convertToJson(result))
1171
+ }
1172
+ }
1173
+
1174
+ @ReactMethod
1175
+ fun enableSamsungHealthDataIntegration(connectionUUID: String, promise: Promise) {
1176
+ executeV3MethodWithConnection("enableSamsungHealthDataIntegration", connectionUUID, promise) { connection ->
1177
+ val activity = reactApplicationContext.currentActivity
1178
+ if (activity == null) {
1179
+ throw SpikeExceptions.SpikeException("Activity is required to enable Samsung Health Data integration")
1180
+ }
1181
+ connection.enableSamsungHealthDataIntegration(activity)
1182
+ Log.d("SpikeSdkModule", "Samsung Health Data integration enabled")
1183
+ promise.resolve(true)
1184
+ }
1185
+ }
1186
+
1187
+ @ReactMethod
1188
+ fun disableSamsungHealthDataIntegration(connectionUUID: String, promise: Promise) {
1189
+ executeV3MethodWithConnection("disableSamsungHealthDataIntegration", connectionUUID, promise) { connection ->
1190
+ connection.disableSamsungHealthDataIntegration()
1191
+ Log.d("SpikeSdkModule", "Samsung Health Data integration disabled")
1192
+ promise.resolve(true)
1193
+ }
1194
+ }
1195
+
1196
+ @ReactMethod
1197
+ fun isSamsungHealthDataIntegrationEnabled(connectionUUID: String, promise: Promise) {
1198
+ executeV3MethodWithConnection("isSamsungHealthDataIntegrationEnabled", connectionUUID, promise) { connection ->
1199
+ val result = connection.isSamsungHealthDataIntegrationEnabled()
1200
+ Log.d("SpikeSdkModule", "Samsung Health Data integration is " + if (result) { "enabled" } else ( "disabled" ))
1201
+ promise.resolve(result)
1202
+ }
1203
+ }
1204
+
1205
+ @ReactMethod
1206
+ fun getGrantedSamsungHealthDataPermissions(connectionUUID: String, promise: Promise) {
1207
+ executeV3MethodWithConnection("getGrantedSamsungHealthDataPermissions", connectionUUID, promise) { connection ->
1208
+ if (!connection.isSamsungHealthDataIntegrationEnabled()) {
1209
+ throw SpikeExceptions.SpikeException("Samsung Health Data should be enabled before calling getGrantedSamsungHealthDataPermissions")
1210
+ }
1211
+
1212
+ val permissions = connection
1213
+ .getSamsungHealthDataPermissionManager()
1214
+ .getGrantedPermissions()
1215
+
1216
+ val result = Arguments.createArray()
1217
+ permissions.forEach {
1218
+ result.pushString(it)
1219
+ }
1220
+
1221
+ Log.w("SpikeSdkModule", "$permissions")
1222
+ promise.resolve(result)
1223
+ }
1224
+ }
1225
+
1226
+ @ReactMethod
1227
+ fun getSamsungHealthDataPermissions(
1228
+ connectionUUID: String,
1229
+ statisticTypes: ReadableArray,
1230
+ metricTypes: ReadableArray,
1231
+ activityConfigs: ReadableArray,
1232
+ sleepConfigs: ReadableArray,
1233
+ promise: Promise
1234
+ ) {
1235
+ executeV3MethodWithConnection("getSamsungHealthDataPermissions", connectionUUID, promise) { connection ->
1236
+ if (!connection.isSamsungHealthDataIntegrationEnabled()) {
1237
+ throw SpikeExceptions.SpikeException("Samsung Health Data should be enabled before calling getSamsungHealthDataPermissions")
1238
+ }
1239
+ val permissionManager = connection.getSamsungHealthDataPermissionManager()
1240
+
1241
+ val statTypes = statisticTypes.toArrayList().mapNotNull {
1242
+ StatisticsTypeUtils.fromValue(it as String)
1243
+ }.toSet()
1244
+
1245
+ val mTypes = metricTypes.toArrayList().mapNotNull {
1246
+ MetricTypeUtils.fromValue(it as String)
1247
+ }.toSet()
1248
+
1249
+ val aConfigs = activityConfigs.toArrayList().mapNotNull {
1250
+ ActivityConfigUtils.fromValue(it as String)
1251
+ }.toSet()
1252
+
1253
+ val sConfigs = sleepConfigs.toArrayList().mapNotNull {
1254
+ SleepConfigUtils.fromValue(it as String)
1255
+ }.toSet()
1256
+
1257
+ val permissions = permissionManager
1258
+ .getPermissions(
1259
+ statisticsTypes = statTypes,
1260
+ metricTypes = mTypes,
1261
+ activityConfigs = aConfigs,
1262
+ sleepConfigs = sConfigs
1263
+ )
1264
+
1265
+ val result = Arguments.createArray()
1266
+ permissions.forEach {
1267
+ result.pushString(it)
1268
+ }
1269
+
1270
+ promise.resolve(result)
1271
+ }
1272
+ }
1273
+
1274
+ @ReactMethod
1275
+ fun requestPermissionsFromSamsungHealthData(
1276
+ connectionUUID: String,
1277
+ statisticTypes: ReadableArray,
1278
+ metricTypes: ReadableArray,
1279
+ activityConfigs: ReadableArray,
1280
+ sleepConfigs: ReadableArray,
1281
+ promise: Promise
1282
+ ) {
1283
+ executeV3MethodWithConnection("requestPermissionsFromSamsungHealthData", connectionUUID, promise) { connection ->
1284
+ if (!connection.isSamsungHealthDataIntegrationEnabled()) {
1285
+ throw SpikeExceptions.SpikeException("Samsung Health Data should be enabled before calling requestPermissionsFromSamsungHealthData")
1286
+ }
1287
+
1288
+ val permissionManager = connection.getSamsungHealthDataPermissionManager()
1289
+
1290
+ val statTypes = statisticTypes.toArrayList().mapNotNull {
1291
+ StatisticsTypeUtils.fromValue(it as String)
1292
+ }.toSet()
1293
+
1294
+ val mTypes = metricTypes.toArrayList().mapNotNull {
1295
+ MetricTypeUtils.fromValue(it as String)
1296
+ }.toSet()
1297
+
1298
+ val aConfigs = activityConfigs.toArrayList().mapNotNull {
1299
+ ActivityConfigUtils.fromValue(it as String)
1300
+ }.toSet()
1301
+
1302
+ val sConfigs = sleepConfigs.toArrayList().mapNotNull {
1303
+ SleepConfigUtils.fromValue(it as String)
1304
+ }.toSet()
1305
+
1306
+ Log.d("SpikeSdkModule", "Will ask for Samsung Health Data permissions with: statTypes=$statTypes, metricTypes=$mTypes, activityConfigs=$aConfigs, sleepConfigs=$sConfigs")
1307
+
1308
+ val activity = reactApplicationContext.currentActivity
1309
+ if (activity == null) {
1310
+ throw SpikeExceptions.SpikeException("Activity is required to request Samsung Health Data permissions")
1311
+ }
1312
+
1313
+ try {
1314
+ val grantedPermissions = permissionManager.requestPermissions(
1315
+ statisticsTypes = statTypes,
1316
+ metricTypes = mTypes,
1317
+ activityConfigs = aConfigs,
1318
+ sleepConfigs = sConfigs
1319
+ )
1320
+
1321
+ val result = Arguments.createArray()
1322
+ grantedPermissions.forEach {
1323
+ result.pushString(it)
1324
+ }
1325
+
1326
+ promise.resolve(result)
1327
+ } catch (e: Exception) {
1328
+ promise.reject(e.toString(), e.message)
1329
+ }
1330
+ }
1331
+ }
1332
+
1333
+
1334
+
1335
+ /// ---
1336
+
1151
1337
  }
1152
1338
 
1153
1339
  private fun convertIsoStringToInstant(isoString: String): Instant {
package/app.plugin.js CHANGED
@@ -1,21 +1,29 @@
1
1
  const {
2
2
  withEntitlementsPlist,
3
3
  withInfoPlist,
4
+ withProjectBuildGradle,
5
+ withAndroidManifest,
4
6
  } = require('@expo/config-plugins');
5
7
 
6
- const HEALTH_SHARE = 'Allow $(PRODUCT_NAME) to check health info';
7
- const HEALTH_UPDATE = 'Allow $(PRODUCT_NAME) to update health info';
8
- const HEALTH_CLINIC_SHARE =
9
- 'Allow $(PRODUCT_NAME) to check health clinical info';
8
+ // Default permission descriptions - these are used as fallbacks if no custom descriptions are provided
9
+ const DEFAULT_HEALTH_SHARE_DESCRIPTION = 'Allow $(PRODUCT_NAME) to check health info';
10
+ const DEFAULT_HEALTH_UPDATE_DESCRIPTION = 'Allow $(PRODUCT_NAME) to update health info';
10
11
 
12
+ /**
13
+ * Configures HealthKit permissions and entitlements for iOS
14
+ * @param {Object} config - Expo config object
15
+ * @param {Object} options - Configuration options
16
+ * @param {string} [options.healthSharePermission] - Custom description for health share permission (NSHealthShareUsageDescription)
17
+ * @param {string} [options.healthUpdatePermission] - Custom description for health update permission (NSHealthUpdateUsageDescription)
18
+ * @param {boolean} [options.isBackgroundDeliveryEnabled=true] - Whether to enable background health data deliveries (defaults to true)
19
+ * @returns {Object} Modified config object
20
+ */
11
21
  const withSpikeHealthKit = (
12
22
  config,
13
23
  {
14
24
  healthSharePermission,
15
25
  healthUpdatePermission,
16
- isClinicalDataEnabled,
17
- healthClinicalDescription,
18
- isBackgroundDeliveriesEnabled,
26
+ isBackgroundDeliveryEnabled = true,
19
27
  } = {}
20
28
  ) => {
21
29
  // Add permissions
@@ -23,18 +31,11 @@ const withSpikeHealthKit = (
23
31
  config.modResults.NSHealthShareUsageDescription =
24
32
  healthSharePermission ||
25
33
  config.modResults.NSHealthShareUsageDescription ||
26
- HEALTH_SHARE;
34
+ DEFAULT_HEALTH_SHARE_DESCRIPTION;
27
35
  config.modResults.NSHealthUpdateUsageDescription =
28
36
  healthUpdatePermission ||
29
37
  config.modResults.NSHealthUpdateUsageDescription ||
30
- HEALTH_UPDATE;
31
- isClinicalDataEnabled
32
- ? (config.modResults.NSHealthClinicalHealthRecordsShareUsageDescription =
33
- healthClinicalDescription ||
34
- config.modResults
35
- .NSHealthClinicalHealthRecordsShareUsageDescription ||
36
- HEALTH_CLINIC_SHARE)
37
- : null;
38
+ DEFAULT_HEALTH_UPDATE_DESCRIPTION;
38
39
 
39
40
  return config;
40
41
  });
@@ -48,18 +49,7 @@ const withSpikeHealthKit = (
48
49
  config.modResults['com.apple.developer.healthkit.access'] = [];
49
50
  }
50
51
 
51
- if (isClinicalDataEnabled != false) {
52
- config.modResults['com.apple.developer.healthkit.access'].push(
53
- 'health-records'
54
- );
55
-
56
- // Remove duplicates
57
- config.modResults['com.apple.developer.healthkit.access'] = [
58
- ...new Set(config.modResults['com.apple.developer.healthkit.access']),
59
- ];
60
- }
61
-
62
- if (isBackgroundDeliveriesEnabled) {
52
+ if (isBackgroundDeliveryEnabled) {
63
53
  config.modResults[
64
54
  'com.apple.developer.healthkit.background-delivery'
65
55
  ] = true;
@@ -70,4 +60,254 @@ const withSpikeHealthKit = (
70
60
 
71
61
  return config;
72
62
  };
73
- module.exports = withSpikeHealthKit;
63
+
64
+ /**
65
+ * Configures Android-specific settings for the Spike SDK
66
+ * @param {Object} config - Expo config object
67
+ * @param {Object} options - Configuration options
68
+ * @param {boolean} [options.isBackgroundDeliveryEnabled=true] - Whether to enable background health data deliveries
69
+ * @param {string[]} [options.healthConnectPermissions=[]] - Array of Health Connect Android permissions to add to the manifest
70
+ * @returns {Object} Modified config object
71
+ */
72
+ const withSpikeAndroid = (config, { isBackgroundDeliveryEnabled = true, healthConnectPermissions = [] } = {}) => {
73
+ // Add Maven repository to allprojects repositories
74
+ config = withProjectBuildGradle(config, (config) => {
75
+ const mavenUrl = 'https://gitlab.com/api/v4/projects/43396247/packages/maven';
76
+ // Find the allprojects block
77
+ const allprojectsRegex = /allprojects\s*\{[\s\S]*?repositories\s*\{([\s\S]*?)\}/;
78
+ const match = config.modResults.contents.match(allprojectsRegex);
79
+ if (match) {
80
+ // Check if the maven repository is already in the repositories block
81
+ if (!match[1].includes(`url '${mavenUrl}'`)) {
82
+ // Add the maven repository to the repositories block
83
+ const updatedContents = config.modResults.contents.replace(
84
+ allprojectsRegex,
85
+ (allBlock) =>
86
+ allBlock.replace(
87
+ /repositories\s*\{/,
88
+ `repositories {\n maven {\n url '${mavenUrl}'\n }`
89
+ )
90
+ );
91
+ config.modResults.contents = updatedContents;
92
+ }
93
+ } else {
94
+ // No allprojects block found, add it at the end of the file
95
+ if (!config.modResults.contents.includes(`url '${mavenUrl}'`)) {
96
+ const insertPosition = config.modResults.contents.lastIndexOf('}');
97
+ if (insertPosition !== -1) {
98
+ const beforeInsert = config.modResults.contents.substring(0, insertPosition);
99
+ const afterInsert = config.modResults.contents.substring(insertPosition);
100
+ config.modResults.contents = `${beforeInsert}\n\nallprojects {\n repositories {\n maven {\n url '${mavenUrl}'\n }\n }\n}${afterInsert}`;
101
+ }
102
+ }
103
+ }
104
+ return config;
105
+ });
106
+
107
+ // Set minSdkVersion to 28 if it's less than 28 or not set
108
+ config = withProjectBuildGradle(config, (config) => {
109
+ // Find the buildscript.ext block and update minSdkVersion
110
+ const buildscriptExtRegex = /buildscript\s*\{\s*ext\s*\{([\s\S]*?)\}/;
111
+ const match = config.modResults.contents.match(buildscriptExtRegex);
112
+
113
+ if (match) {
114
+ const extBlock = match[1];
115
+ const minSdkRegex = /minSdkVersion\s*=\s*(\d+)/;
116
+ const minSdkMatch = extBlock.match(minSdkRegex);
117
+
118
+ if (minSdkMatch) {
119
+ const currentMinSdk = parseInt(minSdkMatch[1], 10);
120
+ if (currentMinSdk < 28) {
121
+ // Replace the existing minSdkVersion
122
+ config.modResults.contents = config.modResults.contents.replace(
123
+ minSdkRegex,
124
+ 'minSdkVersion = 28'
125
+ );
126
+ }
127
+ } else {
128
+ // No minSdkVersion found, add it to the ext block
129
+ config.modResults.contents = config.modResults.contents.replace(
130
+ buildscriptExtRegex,
131
+ (fullMatch, extBlock) => {
132
+ // Find the closing brace of the ext block
133
+ const lines = extBlock.split('\n');
134
+ const lastLineIndex = lines.length - 1;
135
+ const lastLine = lines[lastLineIndex];
136
+
137
+ // Add minSdkVersion before the closing brace
138
+ lines.splice(lastLineIndex, 0, ' minSdkVersion = 28');
139
+
140
+ return `buildscript {\n ext {\n${lines.join('\n')}\n }`;
141
+ }
142
+ );
143
+ }
144
+ } else {
145
+ // No buildscript.ext block found, add it
146
+ const buildscriptRegex = /buildscript\s*\{/;
147
+ const buildscriptMatch = config.modResults.contents.match(buildscriptRegex);
148
+
149
+ if (buildscriptMatch) {
150
+ // Insert ext block after the opening buildscript brace
151
+ config.modResults.contents = config.modResults.contents.replace(
152
+ buildscriptRegex,
153
+ 'buildscript {\n ext {\n minSdkVersion = 28\n }'
154
+ );
155
+ }
156
+ }
157
+
158
+ return config;
159
+ });
160
+
161
+ // Add tools replacement attributes to the AndroidManifest.xml file
162
+ config = withCustomAndroidManifest(config, { isBackgroundDeliveryEnabled, healthConnectPermissions });
163
+
164
+ return config;
165
+ };
166
+
167
+ /**
168
+ * Configures Android manifest with Spike SDK specific settings
169
+ * @param {Object} config - Expo config object
170
+ * @param {Object} options - Configuration options
171
+ * @param {boolean} [options.isBackgroundDeliveryEnabled=true] - Whether to enable background health data deliveries
172
+ * @param {string[]} [options.healthConnectPermissions=[]] - Array of Health Connect Android permissions to add to the manifest
173
+ * @returns {Object} Modified config object
174
+ */
175
+ function withCustomAndroidManifest(config, { isBackgroundDeliveryEnabled = true, healthConnectPermissions = [] } = {}) {
176
+ return withAndroidManifest(config, async (config) => {
177
+ const androidManifest = config.modResults;
178
+ const manifest = androidManifest.manifest;
179
+
180
+ // Ensure xmlns:tools is present in the <manifest> tag
181
+ if (!manifest.$['xmlns:tools']) {
182
+ manifest.$['xmlns:tools'] = 'http://schemas.android.com/tools';
183
+ }
184
+
185
+ // Add background health data permission to healthConnectPermissions when background delivery is enabled
186
+ if (isBackgroundDeliveryEnabled) {
187
+ const backgroundPermission = 'android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND';
188
+ if (!healthConnectPermissions.includes(backgroundPermission)) {
189
+ healthConnectPermissions = [backgroundPermission, ...healthConnectPermissions];
190
+ }
191
+ }
192
+
193
+ // Add health connect permissions if provided
194
+ if (healthConnectPermissions && healthConnectPermissions.length > 0) {
195
+ if (!manifest['uses-permission']) {
196
+ manifest['uses-permission'] = [];
197
+ }
198
+ for (const permission of healthConnectPermissions) {
199
+ if (!manifest['uses-permission'].some(p => p['$'] && p['$']['android:name'] === permission)) {
200
+ manifest['uses-permission'].push({
201
+ $: {
202
+ 'android:name': permission
203
+ }
204
+ });
205
+ }
206
+ }
207
+ }
208
+
209
+ const application = manifest.application[0];
210
+
211
+ // Add tools:replace attribute for dataExtractionRules and fullBackupContent
212
+ application['$']['tools:replace'] = 'android:dataExtractionRules, android:fullBackupContent';
213
+
214
+ // Set dataExtractionRules and fullBackupContent as attributes within <application>
215
+ application['$']['android:dataExtractionRules'] = '@xml/secure_store_data_extraction_rules';
216
+ application['$']['android:fullBackupContent'] = '@xml/secure_store_backup_rules';
217
+
218
+ // Find the main activity and add the intent filter for permissions rationale
219
+ if (application.activity) {
220
+ for (const activity of application.activity) {
221
+ if (activity['$'] && activity['$']['android:name'] &&
222
+ activity['$']['android:name'].endsWith('.MainActivity')) {
223
+
224
+ // Initialize intent-filter array if it doesn't exist
225
+ if (!activity['intent-filter']) {
226
+ activity['intent-filter'] = [];
227
+ }
228
+
229
+ // Check if the permissions rationale intent filter already exists
230
+ const hasPermissionsRationale = activity['intent-filter'].some(filter =>
231
+ filter.action && filter.action.some(action =>
232
+ action['$']['android:name'] === 'androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE'
233
+ )
234
+ );
235
+
236
+ if (!hasPermissionsRationale) {
237
+ activity['intent-filter'].push({
238
+ action: [{
239
+ $: {
240
+ 'android:name': 'androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE'
241
+ }
242
+ }]
243
+ });
244
+ }
245
+ break;
246
+ }
247
+ }
248
+ }
249
+
250
+ // Add activity-alias for ViewPermissionUsageActivity
251
+ if (!application['activity-alias']) {
252
+ application['activity-alias'] = [];
253
+ }
254
+
255
+ // Check if the activity-alias already exists
256
+ const hasViewPermissionUsageActivity = application['activity-alias'].some(alias =>
257
+ alias['$'] && alias['$']['android:name'] === 'ViewPermissionUsageActivity'
258
+ );
259
+
260
+ if (!hasViewPermissionUsageActivity) {
261
+ application['activity-alias'].push({
262
+ $: {
263
+ 'android:name': 'ViewPermissionUsageActivity',
264
+ 'android:exported': 'true',
265
+ 'android:targetActivity': '.MainActivity',
266
+ 'android:permission': 'android.permission.START_VIEW_PERMISSION_USAGE'
267
+ },
268
+ 'intent-filter': [{
269
+ action: [{
270
+ $: {
271
+ 'android:name': 'android.intent.action.VIEW_PERMISSION_USAGE'
272
+ }
273
+ }],
274
+ category: [{
275
+ $: {
276
+ 'android:name': 'android.intent.category.HEALTH_PERMISSIONS'
277
+ }
278
+ }]
279
+ }]
280
+ });
281
+ }
282
+
283
+ return config;
284
+ });
285
+ };
286
+
287
+ /**
288
+ * Main plugin function that configures the Spike SDK for both iOS and Android
289
+ * @param {Object} config - Expo config object
290
+ * @param {Object} props - Configuration properties
291
+ * @param {Object} [props.ios] - iOS-specific configuration
292
+ * @param {string} [props.ios.healthSharePermission] - Custom description for health share permission (NSHealthShareUsageDescription)
293
+ * @param {string} [props.ios.healthUpdatePermission] - Custom description for health update permission (NSHealthUpdateUsageDescription)
294
+ * @param {boolean} [props.ios.isBackgroundDeliveryEnabled=true] - Whether to enable background health data deliveries (defaults to true)
295
+ * @param {Object} [props.android] - Android-specific configuration
296
+ * @param {boolean} [props.android.isBackgroundDeliveryEnabled=true] - Whether to enable background health data deliveries (defaults to true)
297
+ * @param {string[]} [props.android.healthConnectPermissions=[]] - Array of Health Connect Android permissions to add to the manifest
298
+ * @returns {Object} Modified config object
299
+ *
300
+ */
301
+ const withSpikeSdk = (config, props = {}) => {
302
+ const { ios = {}, android = {} } = props;
303
+
304
+ // Apply iOS configuration
305
+ config = withSpikeHealthKit(config, ios);
306
+
307
+ // Apply Android configuration
308
+ config = withSpikeAndroid(config, android);
309
+
310
+ return config;
311
+ };
312
+
313
+ module.exports = withSpikeSdk;
@@ -57,6 +57,12 @@ Object.defineProperty(exports, "ProviderSource", {
57
57
  return _ProviderSource.ProviderSource;
58
58
  }
59
59
  });
60
+ Object.defineProperty(exports, "SamsungHealthDataAvailabilityStatus", {
61
+ enumerable: true,
62
+ get: function () {
63
+ return _SamsungHealthDataAvailabilityStatus.SamsungHealthDataAvailabilityStatus;
64
+ }
65
+ });
60
66
  Object.defineProperty(exports, "SleepConfig", {
61
67
  enumerable: true,
62
68
  get: function () {
@@ -182,6 +188,7 @@ var _StatisticsInterval = require("./v3/DataModels/StatisticsInterval");
182
188
  var _Unit = require("./v3/DataModels/Unit");
183
189
  var _StatisticsFilter = require("./v3/StatisticsFilter");
184
190
  var _HealthConnectAvailabilityStatus = require("./v3/DataModels/HealthConnectAvailabilityStatus");
191
+ var _SamsungHealthDataAvailabilityStatus = require("./v3/DataModels/SamsungHealthDataAvailabilityStatus");
185
192
  var _ActivityAdditionalData = require("./v3/DataModels/ActivityAdditionalData");
186
193
  var _ActivityConfig = require("./v3/DataModels/ActivityConfig");
187
194
  var _SleepConfig = require("./v3/DataModels/SleepConfig");
@@ -1 +1 @@
1
- {"version":3,"names":["_SpikeDataTypes","require","_Spike","_SpikeConnection","_SpikeException","_SpikeRNConnectionAPIv","_ActivityTag","_ActivityType","_InputMethod","_MetricType","_Provider","_ProviderSource","_StatisticsType","_StatisticsInterval","_Unit","_StatisticsFilter","_HealthConnectAvailabilityStatus","_ActivityAdditionalData","_ActivityConfig","_SleepConfig","_default","exports","default","createConnection","getBackgroundConnections","ensurePermissionsAreGranted","isPackageInstalled","isHealthDataAvailable","createConnectionAPIv3","createConnectionAPIv3Legacy"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,eAAA,GAAAC,OAAA;AAEA,IAAAC,MAAA,GAAAD,OAAA;AAUA,IAAAE,gBAAA,GAAAF,OAAA;AAIA,IAAAG,eAAA,GAAAH,OAAA;AAqEA,IAAAI,sBAAA,GAAAJ,OAAA;AACA,IAAAK,YAAA,GAAAL,OAAA;AACA,IAAAM,aAAA,GAAAN,OAAA;AACA,IAAAO,YAAA,GAAAP,OAAA;AACA,IAAAQ,WAAA,GAAAR,OAAA;AACA,IAAAS,SAAA,GAAAT,OAAA;AACA,IAAAU,eAAA,GAAAV,OAAA;AACA,IAAAW,eAAA,GAAAX,OAAA;AACA,IAAAY,mBAAA,GAAAZ,OAAA;AACA,IAAAa,KAAA,GAAAb,OAAA;AACA,IAAAc,iBAAA,GAAAd,OAAA;AACA,IAAAe,gCAAA,GAAAf,OAAA;AACA,IAAAgB,uBAAA,GAAAhB,OAAA;AACA,IAAAiB,eAAA,GAAAjB,OAAA;AAIA,IAAAkB,YAAA,GAAAlB,OAAA;AAA2F,IAAAmB,QAAA,GAAAC,OAAA,CAAAC,OAAA,GA9D5E;EACbC,gBAAgB,EAAhBA,uBAAgB;EAChBC,wBAAwB,EAAxBA,+BAAwB;EACxBC,2BAA2B,EAA3BA,kCAA2B;EAC3BC,kBAAkB,EAAlBA,yBAAkB;EAClBC,qBAAqB,EAArBA,4BAAqB;EACrB;EACAC,qBAAqB,EAArBA,4BAAqB;EACrBC,2BAA2B,EAA3BA;AACF,CAAC,EAmCD","ignoreList":[]}
1
+ {"version":3,"names":["_SpikeDataTypes","require","_Spike","_SpikeConnection","_SpikeException","_SpikeRNConnectionAPIv","_ActivityTag","_ActivityType","_InputMethod","_MetricType","_Provider","_ProviderSource","_StatisticsType","_StatisticsInterval","_Unit","_StatisticsFilter","_HealthConnectAvailabilityStatus","_SamsungHealthDataAvailabilityStatus","_ActivityAdditionalData","_ActivityConfig","_SleepConfig","_default","exports","default","createConnection","getBackgroundConnections","ensurePermissionsAreGranted","isPackageInstalled","isHealthDataAvailable","createConnectionAPIv3","createConnectionAPIv3Legacy"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,eAAA,GAAAC,OAAA;AAEA,IAAAC,MAAA,GAAAD,OAAA;AAUA,IAAAE,gBAAA,GAAAF,OAAA;AAIA,IAAAG,eAAA,GAAAH,OAAA;AAqEA,IAAAI,sBAAA,GAAAJ,OAAA;AACA,IAAAK,YAAA,GAAAL,OAAA;AACA,IAAAM,aAAA,GAAAN,OAAA;AACA,IAAAO,YAAA,GAAAP,OAAA;AACA,IAAAQ,WAAA,GAAAR,OAAA;AACA,IAAAS,SAAA,GAAAT,OAAA;AACA,IAAAU,eAAA,GAAAV,OAAA;AACA,IAAAW,eAAA,GAAAX,OAAA;AACA,IAAAY,mBAAA,GAAAZ,OAAA;AACA,IAAAa,KAAA,GAAAb,OAAA;AACA,IAAAc,iBAAA,GAAAd,OAAA;AACA,IAAAe,gCAAA,GAAAf,OAAA;AACA,IAAAgB,oCAAA,GAAAhB,OAAA;AACA,IAAAiB,uBAAA,GAAAjB,OAAA;AACA,IAAAkB,eAAA,GAAAlB,OAAA;AAIA,IAAAmB,YAAA,GAAAnB,OAAA;AAA2F,IAAAoB,QAAA,GAAAC,OAAA,CAAAC,OAAA,GA/D5E;EACbC,gBAAgB,EAAhBA,uBAAgB;EAChBC,wBAAwB,EAAxBA,+BAAwB;EACxBC,2BAA2B,EAA3BA,kCAA2B;EAC3BC,kBAAkB,EAAlBA,yBAAkB;EAClBC,qBAAqB,EAArBA,4BAAqB;EACrB;EACAC,qBAAqB,EAArBA,4BAAqB;EACrBC,2BAA2B,EAA3BA;AACF,CAAC,EAmCD","ignoreList":[]}
@@ -54,9 +54,9 @@ let MetricType = exports.MetricType = /*#__PURE__*/function (MetricType) {
54
54
  MetricType["vo2Max"] = "vo2max";
55
55
  MetricType["bodyTemperature"] = "body_temperature";
56
56
  MetricType["skinTemperature"] = "skin_temperature";
57
- MetricType["sleepBreathingRate"] = "sleep_breathing_rate";
58
- MetricType["sleepBreathingRateMin"] = "sleep_breathing_rate_min";
59
- MetricType["sleepBreathingRateMax"] = "sleep_breathing_rate_max";
57
+ MetricType["breathingRate"] = "breathing_rate";
58
+ MetricType["breathingRateMin"] = "breathing_rate_min";
59
+ MetricType["breathingRateMax"] = "breathing_rate_max";
60
60
  MetricType["bodyFat"] = "body_fat";
61
61
  MetricType["bodyFatMax"] = "body_fat_max";
62
62
  MetricType["bodyFatMin"] = "body_fat_min";
@@ -18,6 +18,7 @@ let Provider = exports.Provider = /*#__PURE__*/function (Provider) {
18
18
  Provider["apple"] = "apple";
19
19
  Provider["healthConnect"] = "health_connect";
20
20
  Provider["ultrahuman"] = "ultrahuman";
21
+ Provider["samsungHealthData"] = "samsung_health_data";
21
22
  Provider["unknown"] = "_unknown";
22
23
  return Provider;
23
24
  }({});
@@ -1 +1 @@
1
- {"version":3,"names":["Provider","exports"],"sourceRoot":"../../../../src","sources":["v3/DataModels/Provider.ts"],"mappings":";;;;;;AACA;AACA;AAAA,IACYA,QAAQ,GAAAC,OAAA,CAAAD,QAAA,0BAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAAA,OAARA,QAAQ;AAAA","ignoreList":[]}
1
+ {"version":3,"names":["Provider","exports"],"sourceRoot":"../../../../src","sources":["v3/DataModels/Provider.ts"],"mappings":";;;;;;AACA;AACA;AAAA,IACYA,QAAQ,GAAAC,OAAA,CAAAD,QAAA,0BAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAARA,QAAQ;EAAA,OAARA,QAAQ;AAAA","ignoreList":[]}
@@ -45,6 +45,7 @@ let ProviderSource = exports.ProviderSource = /*#__PURE__*/function (ProviderSou
45
45
  ProviderSource["withingsMeasureGetActivity"] = "withings_measure_get_activity";
46
46
  ProviderSource["withingsMeasureGetMeas"] = "withings_measure_get_meas";
47
47
  ProviderSource["wahooWorkoutSummary"] = "wahoo_workout_summary";
48
+ ProviderSource["samsungHealthDataAggregation"] = "samsung_health_data_aggregation";
48
49
  ProviderSource["unknown"] = "_unknown";
49
50
  return ProviderSource;
50
51
  }({});
@@ -1 +1 @@
1
- {"version":3,"names":["ProviderSource","exports"],"sourceRoot":"../../../../src","sources":["v3/DataModels/ProviderSource.ts"],"mappings":";;;;;;AACA;AACA;AAAA,IACYA,cAAc,GAAAC,OAAA,CAAAD,cAAA,0BAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAA,OAAdA,cAAc;AAAA","ignoreList":[]}
1
+ {"version":3,"names":["ProviderSource","exports"],"sourceRoot":"../../../../src","sources":["v3/DataModels/ProviderSource.ts"],"mappings":";;;;;;AACA;AACA;AAAA,IACYA,cAAc,GAAAC,OAAA,CAAAD,cAAA,0BAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAdA,cAAc;EAAA,OAAdA,cAAc;AAAA","ignoreList":[]}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ //# sourceMappingURL=SamsungHealthDataAvailability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../../src","sources":["v3/DataModels/SamsungHealthDataAvailability.ts"],"mappings":"","ignoreList":[]}