react-native-spike-sdk 4.3.173 → 4.3.193

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 (126) hide show
  1. package/android/build.gradle +1 -1
  2. package/android/src/main/java/com/spikesdk/SpikeSdkModule.kt +203 -1
  3. package/ios/SpikeSdk.m +54 -0
  4. package/ios/SpikeSdk.swift +368 -0
  5. package/lib/commonjs/index.js +78 -0
  6. package/lib/commonjs/index.js.map +1 -1
  7. package/lib/commonjs/v3/DataModels/ActivityTag.js +0 -1
  8. package/lib/commonjs/v3/DataModels/ActivityTag.js.map +1 -1
  9. package/lib/commonjs/v3/DataModels/NutritionFactsLabelRecognitionConfig.js +6 -0
  10. package/lib/commonjs/v3/DataModels/NutritionFactsLabelRecognitionConfig.js.map +1 -0
  11. package/lib/commonjs/v3/DataModels/NutritionFactsLabelRecognitionResult.js +6 -0
  12. package/lib/commonjs/v3/DataModels/NutritionFactsLabelRecognitionResult.js.map +1 -0
  13. package/lib/commonjs/v3/DataModels/NutritionRecord.js +6 -0
  14. package/lib/commonjs/v3/DataModels/NutritionRecord.js.map +1 -0
  15. package/lib/commonjs/v3/DataModels/NutritionRecordAnalysisMode.js +14 -0
  16. package/lib/commonjs/v3/DataModels/NutritionRecordAnalysisMode.js.map +1 -0
  17. package/lib/commonjs/v3/DataModels/NutritionRecordAnalysisResult.js +6 -0
  18. package/lib/commonjs/v3/DataModels/NutritionRecordAnalysisResult.js.map +1 -0
  19. package/lib/commonjs/v3/DataModels/NutritionRecordIngredient.js +6 -0
  20. package/lib/commonjs/v3/DataModels/NutritionRecordIngredient.js.map +1 -0
  21. package/lib/commonjs/v3/DataModels/NutritionRecordStatus.js +18 -0
  22. package/lib/commonjs/v3/DataModels/NutritionRecordStatus.js.map +1 -0
  23. package/lib/commonjs/v3/DataModels/NutritionalAnalysisConfig.js +6 -0
  24. package/lib/commonjs/v3/DataModels/NutritionalAnalysisConfig.js.map +1 -0
  25. package/lib/commonjs/v3/DataModels/NutritionalField.js +41 -0
  26. package/lib/commonjs/v3/DataModels/NutritionalField.js.map +1 -0
  27. package/lib/commonjs/v3/DataModels/NutritionalUnit.js +18 -0
  28. package/lib/commonjs/v3/DataModels/NutritionalUnit.js.map +1 -0
  29. package/lib/commonjs/v3/DataModels/Provider.js +1 -1
  30. package/lib/commonjs/v3/DataModels/ProviderSource.js +3 -7
  31. package/lib/commonjs/v3/DataModels/ProviderSource.js.map +1 -1
  32. package/lib/commonjs/v3/SpikeRNConnectionAPIv3.js +171 -0
  33. package/lib/commonjs/v3/SpikeRNConnectionAPIv3.js.map +1 -1
  34. package/lib/commonjs/v3/Utils/NutritionRecordIngredientUtils.js +108 -0
  35. package/lib/commonjs/v3/Utils/NutritionRecordIngredientUtils.js.map +1 -0
  36. package/lib/commonjs/v3/Utils/NutritionRecordUtils.js +154 -0
  37. package/lib/commonjs/v3/Utils/NutritionRecordUtils.js.map +1 -0
  38. package/lib/commonjs/version.js +1 -1
  39. package/lib/module/index.js +13 -1
  40. package/lib/module/index.js.map +1 -1
  41. package/lib/module/v3/DataModels/ActivityTag.js +0 -1
  42. package/lib/module/v3/DataModels/ActivityTag.js.map +1 -1
  43. package/lib/module/v3/DataModels/NutritionFactsLabelRecognitionConfig.js +4 -0
  44. package/lib/module/v3/DataModels/NutritionFactsLabelRecognitionConfig.js.map +1 -0
  45. package/lib/module/v3/DataModels/NutritionFactsLabelRecognitionResult.js +4 -0
  46. package/lib/module/v3/DataModels/NutritionFactsLabelRecognitionResult.js.map +1 -0
  47. package/lib/module/v3/DataModels/NutritionRecord.js +4 -0
  48. package/lib/module/v3/DataModels/NutritionRecord.js.map +1 -0
  49. package/lib/module/v3/DataModels/NutritionRecordAnalysisMode.js +10 -0
  50. package/lib/module/v3/DataModels/NutritionRecordAnalysisMode.js.map +1 -0
  51. package/lib/module/v3/DataModels/NutritionRecordAnalysisResult.js +4 -0
  52. package/lib/module/v3/DataModels/NutritionRecordAnalysisResult.js.map +1 -0
  53. package/lib/module/v3/DataModels/NutritionRecordIngredient.js +4 -0
  54. package/lib/module/v3/DataModels/NutritionRecordIngredient.js.map +1 -0
  55. package/lib/module/v3/DataModels/NutritionRecordStatus.js +14 -0
  56. package/lib/module/v3/DataModels/NutritionRecordStatus.js.map +1 -0
  57. package/lib/module/v3/DataModels/NutritionalAnalysisConfig.js +4 -0
  58. package/lib/module/v3/DataModels/NutritionalAnalysisConfig.js.map +1 -0
  59. package/lib/module/v3/DataModels/NutritionalField.js +37 -0
  60. package/lib/module/v3/DataModels/NutritionalField.js.map +1 -0
  61. package/lib/module/v3/DataModels/NutritionalUnit.js +14 -0
  62. package/lib/module/v3/DataModels/NutritionalUnit.js.map +1 -0
  63. package/lib/module/v3/DataModels/Provider.js +1 -1
  64. package/lib/module/v3/DataModels/ProviderSource.js +3 -7
  65. package/lib/module/v3/DataModels/ProviderSource.js.map +1 -1
  66. package/lib/module/v3/SpikeRNConnectionAPIv3.js +172 -1
  67. package/lib/module/v3/SpikeRNConnectionAPIv3.js.map +1 -1
  68. package/lib/module/v3/Utils/NutritionRecordIngredientUtils.js +101 -0
  69. package/lib/module/v3/Utils/NutritionRecordIngredientUtils.js.map +1 -0
  70. package/lib/module/v3/Utils/NutritionRecordUtils.js +147 -0
  71. package/lib/module/v3/Utils/NutritionRecordUtils.js.map +1 -0
  72. package/lib/module/version.js +1 -1
  73. package/lib/typescript/index.d.ts +14 -2
  74. package/lib/typescript/index.d.ts.map +1 -1
  75. package/lib/typescript/v3/DataModels/ActivityTag.d.ts +0 -1
  76. package/lib/typescript/v3/DataModels/ActivityTag.d.ts.map +1 -1
  77. package/lib/typescript/v3/DataModels/NutritionFactsLabelRecognitionConfig.d.ts +8 -0
  78. package/lib/typescript/v3/DataModels/NutritionFactsLabelRecognitionConfig.d.ts.map +1 -0
  79. package/lib/typescript/v3/DataModels/NutritionFactsLabelRecognitionResult.d.ts +8 -0
  80. package/lib/typescript/v3/DataModels/NutritionFactsLabelRecognitionResult.d.ts.map +1 -0
  81. package/lib/typescript/v3/DataModels/NutritionRecord.d.ts +22 -0
  82. package/lib/typescript/v3/DataModels/NutritionRecord.d.ts.map +1 -0
  83. package/lib/typescript/v3/DataModels/NutritionRecordAnalysisMode.d.ts +5 -0
  84. package/lib/typescript/v3/DataModels/NutritionRecordAnalysisMode.d.ts.map +1 -0
  85. package/lib/typescript/v3/DataModels/NutritionRecordAnalysisResult.d.ts +11 -0
  86. package/lib/typescript/v3/DataModels/NutritionRecordAnalysisResult.d.ts.map +1 -0
  87. package/lib/typescript/v3/DataModels/NutritionRecordIngredient.d.ts +11 -0
  88. package/lib/typescript/v3/DataModels/NutritionRecordIngredient.d.ts.map +1 -0
  89. package/lib/typescript/v3/DataModels/NutritionRecordStatus.d.ts +9 -0
  90. package/lib/typescript/v3/DataModels/NutritionRecordStatus.d.ts.map +1 -0
  91. package/lib/typescript/v3/DataModels/NutritionalAnalysisConfig.d.ts +12 -0
  92. package/lib/typescript/v3/DataModels/NutritionalAnalysisConfig.d.ts.map +1 -0
  93. package/lib/typescript/v3/DataModels/NutritionalField.d.ts +32 -0
  94. package/lib/typescript/v3/DataModels/NutritionalField.d.ts.map +1 -0
  95. package/lib/typescript/v3/DataModels/NutritionalUnit.d.ts +9 -0
  96. package/lib/typescript/v3/DataModels/NutritionalUnit.d.ts.map +1 -0
  97. package/lib/typescript/v3/DataModels/Provider.d.ts +1 -1
  98. package/lib/typescript/v3/DataModels/Provider.d.ts.map +1 -1
  99. package/lib/typescript/v3/DataModels/ProviderSource.d.ts +3 -7
  100. package/lib/typescript/v3/DataModels/ProviderSource.d.ts.map +1 -1
  101. package/lib/typescript/v3/SpikeRNConnectionAPIv3.d.ts +129 -0
  102. package/lib/typescript/v3/SpikeRNConnectionAPIv3.d.ts.map +1 -1
  103. package/lib/typescript/v3/Utils/NutritionRecordIngredientUtils.d.ts +58 -0
  104. package/lib/typescript/v3/Utils/NutritionRecordIngredientUtils.d.ts.map +1 -0
  105. package/lib/typescript/v3/Utils/NutritionRecordUtils.d.ts +74 -0
  106. package/lib/typescript/v3/Utils/NutritionRecordUtils.d.ts.map +1 -0
  107. package/lib/typescript/version.d.ts +1 -1
  108. package/package.json +2 -2
  109. package/src/index.ts +48 -0
  110. package/src/v3/DataModels/ActivityTag.ts +0 -1
  111. package/src/v3/DataModels/NutritionFactsLabelRecognitionConfig.ts +11 -0
  112. package/src/v3/DataModels/NutritionFactsLabelRecognitionResult.ts +11 -0
  113. package/src/v3/DataModels/NutritionRecord.ts +23 -0
  114. package/src/v3/DataModels/NutritionRecordAnalysisMode.ts +7 -0
  115. package/src/v3/DataModels/NutritionRecordAnalysisResult.ts +14 -0
  116. package/src/v3/DataModels/NutritionRecordIngredient.ts +12 -0
  117. package/src/v3/DataModels/NutritionRecordStatus.ts +11 -0
  118. package/src/v3/DataModels/NutritionalAnalysisConfig.ts +15 -0
  119. package/src/v3/DataModels/NutritionalField.ts +34 -0
  120. package/src/v3/DataModels/NutritionalUnit.ts +11 -0
  121. package/src/v3/DataModels/Provider.ts +1 -1
  122. package/src/v3/DataModels/ProviderSource.ts +3 -7
  123. package/src/v3/SpikeRNConnectionAPIv3.ts +271 -1
  124. package/src/v3/Utils/NutritionRecordIngredientUtils.ts +121 -0
  125. package/src/v3/Utils/NutritionRecordUtils.ts +191 -0
  126. package/src/version.ts +1 -1
@@ -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.3.102'
79
+ implementation 'com.spikeapi.sdk:spike-sdk:4.3.122'
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'
@@ -19,11 +19,18 @@ import com.spikeapi.apiv3.datamodels.MetricType
19
19
  import com.spikeapi.apiv3.datamodels.ActivityConfig
20
20
  import com.spikeapi.apiv3.datamodels.SleepConfig
21
21
  import com.spikeapi.apiv3.datamodels.StatisticsType
22
+ import com.spikeapi.apiv3.datamodels.NutritionRecord
23
+ import com.spikeapi.apiv3.datamodels.NutritionalAnalysisConfig
24
+ import com.spikeapi.apiv3.datamodels.NutritionFactsLabelRecognitionConfig
25
+ import com.spikeapi.apiv3.datamodels.NutritionRecordAnalysisMode
26
+ import com.spikeapi.apiv3.datamodels.NutritionalField
22
27
  import com.spikeapi.apiv3.datamodels.utils.ActivityConfigUtils
23
28
  import com.spikeapi.apiv3.datamodels.utils.SleepConfigUtils
24
29
  import com.spikeapi.apiv3.datamodels.utils.StatisticsTypeUtils
25
30
  import com.spikeapi.apiv3.datamodels.utils.StatisticsIntervalUtils
26
31
  import com.spikeapi.apiv3.datamodels.utils.MetricTypeUtils
32
+ import com.spikeapi.apiv3.datamodels.utils.NutritionFactsLabelRecognitionConfigUtils
33
+ import com.spikeapi.apiv3.datamodels.utils.NutritionRecordUtils
27
34
  import com.spikeapi.apiv3.datamodels.StatisticsInterval
28
35
  import com.spikeapi.apiv3.datamodels.StatisticsFilter
29
36
  import com.spikeapi.apiv3.datamodels.Provider
@@ -1388,7 +1395,202 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
1388
1395
 
1389
1396
 
1390
1397
 
1391
- /// ---
1398
+ /// --- Nutrition AI ---
1399
+
1400
+ @ReactMethod
1401
+ fun analyzeNutrition(
1402
+ connectionUUID: String,
1403
+ imageBase64: String,
1404
+ consumedAt: String?,
1405
+ config: String?,
1406
+ promise: Promise
1407
+ ) {
1408
+ executeV3MethodWithConnection("analyzeNutrition", connectionUUID, promise) { connection ->
1409
+ val consumedAtInstant = consumedAt?.let { convertIsoStringToInstant(it) }
1410
+ val configObject = config?.let { parseNutritionalAnalysisConfig(it) }
1411
+
1412
+ val result = connection.analyzeNutrition(
1413
+ imageBase64 = imageBase64,
1414
+ consumedAt = consumedAtInstant,
1415
+ config = configObject
1416
+ )
1417
+
1418
+ promise.resolve(SpikeConnectionAPIv3.convertToJson(result))
1419
+ }
1420
+ }
1421
+
1422
+ @ReactMethod
1423
+ fun submitNutritionForAnalysis(
1424
+ connectionUUID: String,
1425
+ imageBase64: String,
1426
+ consumedAt: String?,
1427
+ config: String?,
1428
+ promise: Promise
1429
+ ) {
1430
+ executeV3MethodWithConnection("submitNutritionForAnalysis", connectionUUID, promise) { connection ->
1431
+ val consumedAtInstant = consumedAt?.let { convertIsoStringToInstant(it) }
1432
+ val configObject = config?.let { parseNutritionalAnalysisConfig(it) }
1433
+
1434
+ val result = connection.submitNutritionForAnalysis(
1435
+ imageBase64 = imageBase64,
1436
+ consumedAt = consumedAtInstant,
1437
+ config = configObject
1438
+ )
1439
+
1440
+ promise.resolve(result.toString())
1441
+ }
1442
+ }
1443
+
1444
+ private fun parseNutritionalAnalysisConfig(json: String): NutritionalAnalysisConfig? {
1445
+ return try {
1446
+ NutritionalAnalysisConfigUtils.fromValue(json)
1447
+ } catch (e: Exception) {
1448
+ Log.e("SpikeSdkModule", "Error parsing NutritionalAnalysisConfig: ${e.message}")
1449
+ null
1450
+ }
1451
+ }
1452
+
1453
+ @ReactMethod
1454
+ fun getNutritionRecords(
1455
+ connectionUUID: String,
1456
+ from: String,
1457
+ to: String,
1458
+ promise: Promise
1459
+ ) {
1460
+ executeV3MethodWithConnection("getNutritionRecords", connectionUUID, promise) { connection ->
1461
+ val dateFrom = convertIsoStringToInstant(from)
1462
+ val dateTo = convertIsoStringToInstant(to)
1463
+
1464
+ val result = connection.getNutritionRecords(
1465
+ from = dateFrom,
1466
+ to = dateTo
1467
+ )
1468
+
1469
+ promise.resolve(SpikeConnectionAPIv3.convertToJson(result))
1470
+ }
1471
+ }
1472
+
1473
+ @ReactMethod
1474
+ fun getNutritionRecord(
1475
+ connectionUUID: String,
1476
+ recordId: String,
1477
+ promise: Promise
1478
+ ) {
1479
+ executeV3MethodWithConnection("getNutritionRecord", connectionUUID, promise) { connection ->
1480
+ val uuid = UUID.fromString(recordId)
1481
+
1482
+ val result = connection.getNutritionRecord(id = uuid)
1483
+
1484
+ if (result != null) {
1485
+ promise.resolve(SpikeConnectionAPIv3.convertToJson(result))
1486
+ } else {
1487
+ promise.resolve(null)
1488
+ }
1489
+ }
1490
+ }
1491
+
1492
+ @ReactMethod
1493
+ fun deleteNutritionRecord(
1494
+ connectionUUID: String,
1495
+ recordId: String,
1496
+ promise: Promise
1497
+ ) {
1498
+ executeV3MethodWithConnection("deleteNutritionRecord", connectionUUID, promise) { connection ->
1499
+ val uuid = UUID.fromString(recordId)
1500
+
1501
+ connection.deleteNutritionRecord(id = uuid)
1502
+
1503
+ promise.resolve(true)
1504
+ }
1505
+ }
1506
+
1507
+ @ReactMethod
1508
+ fun updateNutritionRecordServingSize(
1509
+ connectionUUID: String,
1510
+ recordId: String,
1511
+ servingSize: Double,
1512
+ promise: Promise
1513
+ ) {
1514
+ executeV3MethodWithConnection("updateNutritionRecordServingSize", connectionUUID, promise) { connection ->
1515
+ val uuid = UUID.fromString(recordId)
1516
+
1517
+ val result = connection.updateNutritionRecordServingSize(
1518
+ id = uuid,
1519
+ servingSize = servingSize
1520
+ )
1521
+
1522
+ promise.resolve(SpikeConnectionAPIv3.convertToJson(result))
1523
+ }
1524
+ }
1525
+
1526
+ @ReactMethod
1527
+ fun recognizeNutritionFactsLabel(
1528
+ connectionUUID: String,
1529
+ imageBase64: String,
1530
+ config: String?,
1531
+ promise: Promise
1532
+ ) {
1533
+ executeV3MethodWithConnection("recognizeNutritionFactsLabel", connectionUUID, promise) { connection ->
1534
+ val configObject = config?.let { parseNutritionFactsLabelRecognitionConfig(it) }
1535
+
1536
+ val result = connection.recognizeNutritionFactsLabel(
1537
+ imageBase64 = imageBase64,
1538
+ config = configObject
1539
+ )
1540
+
1541
+ promise.resolve(SpikeConnectionAPIv3.convertToJson(result))
1542
+ }
1543
+ }
1544
+
1545
+ private fun parseNutritionFactsLabelRecognitionConfig(json: String): NutritionFactsLabelRecognitionConfig? {
1546
+ return try {
1547
+ NutritionFactsLabelRecognitionConfigUtils.fromValue(json)
1548
+ } catch (e: Exception) {
1549
+ Log.e("SpikeSdkModule", "Error parsing NutritionFactsLabelRecognitionConfig: ${e.message}")
1550
+ null
1551
+ }
1552
+ }
1553
+
1554
+ @ReactMethod
1555
+ fun createNutritionRecord(
1556
+ connectionUUID: String,
1557
+ nutritionRecord: String,
1558
+ promise: Promise
1559
+ ) {
1560
+ executeV3MethodWithConnection("createNutritionRecord", connectionUUID, promise) { connection ->
1561
+ val recordObject = parseNutritionRecord(nutritionRecord)
1562
+ ?: throw SpikeExceptions.SpikeException("Failed to parse nutrition record")
1563
+
1564
+ val result = connection.createNutritionRecord(recordObject)
1565
+
1566
+ promise.resolve(SpikeConnectionAPIv3.convertToJson(result))
1567
+ }
1568
+ }
1569
+
1570
+ @ReactMethod
1571
+ fun replaceNutritionRecord(
1572
+ connectionUUID: String,
1573
+ nutritionRecord: String,
1574
+ promise: Promise
1575
+ ) {
1576
+ executeV3MethodWithConnection("replaceNutritionRecord", connectionUUID, promise) { connection ->
1577
+ val recordObject = parseNutritionRecord(nutritionRecord)
1578
+ ?: throw SpikeExceptions.SpikeException("Failed to parse nutrition record")
1579
+
1580
+ val result = connection.replaceNutritionRecord(recordObject)
1581
+
1582
+ promise.resolve(SpikeConnectionAPIv3.convertToJson(result))
1583
+ }
1584
+ }
1585
+
1586
+ private fun parseNutritionRecord(json: String): NutritionRecord? {
1587
+ return try {
1588
+ NutritionRecordUtils.fromValue(json)
1589
+ } catch (e: Exception) {
1590
+ Log.e("SpikeSdkModule", "Error parsing NutritionRecord: ${e.message}")
1591
+ null
1592
+ }
1593
+ }
1392
1594
 
1393
1595
  }
1394
1596
 
package/ios/SpikeSdk.m CHANGED
@@ -196,4 +196,58 @@ RCT_EXTERN_METHOD(isHealthKitIntegrationEnabled: (NSString)connectionUUID
196
196
  withResolver: (RCTPromiseResolveBlock)resolve
197
197
  withRejecter: (RCTPromiseRejectBlock)reject)
198
198
 
199
+ // MARK: Nutrition AI
200
+
201
+ RCT_EXTERN_METHOD(analyzeNutrition: (NSString)connectionUUID
202
+ imageBase64: (NSString)imageBase64
203
+ consumedAt: (NSString)consumedAt
204
+ config: (NSString)config
205
+ withResolver: (RCTPromiseResolveBlock)resolve
206
+ withRejecter: (RCTPromiseRejectBlock)reject)
207
+
208
+ RCT_EXTERN_METHOD(submitNutritionForAnalysis: (NSString)connectionUUID
209
+ imageBase64: (NSString)imageBase64
210
+ consumedAt: (NSString)consumedAt
211
+ config: (NSString)config
212
+ withResolver: (RCTPromiseResolveBlock)resolve
213
+ withRejecter: (RCTPromiseRejectBlock)reject)
214
+
215
+ RCT_EXTERN_METHOD(getNutritionRecords: (NSString)connectionUUID
216
+ from: (NSString)from
217
+ to: (NSString)to
218
+ withResolver: (RCTPromiseResolveBlock)resolve
219
+ withRejecter: (RCTPromiseRejectBlock)reject)
220
+
221
+ RCT_EXTERN_METHOD(getNutritionRecord: (NSString)connectionUUID
222
+ recordId: (NSString)recordId
223
+ withResolver: (RCTPromiseResolveBlock)resolve
224
+ withRejecter: (RCTPromiseRejectBlock)reject)
225
+
226
+ RCT_EXTERN_METHOD(deleteNutritionRecord: (NSString)connectionUUID
227
+ recordId: (NSString)recordId
228
+ withResolver: (RCTPromiseResolveBlock)resolve
229
+ withRejecter: (RCTPromiseRejectBlock)reject)
230
+
231
+ RCT_EXTERN_METHOD(updateNutritionRecordServingSize: (NSString)connectionUUID
232
+ recordId: (NSString)recordId
233
+ servingSize: (double)servingSize
234
+ withResolver: (RCTPromiseResolveBlock)resolve
235
+ withRejecter: (RCTPromiseRejectBlock)reject)
236
+
237
+ RCT_EXTERN_METHOD(recognizeNutritionFactsLabel: (NSString)connectionUUID
238
+ imageBase64: (NSString)imageBase64
239
+ config: (NSString)config
240
+ withResolver: (RCTPromiseResolveBlock)resolve
241
+ withRejecter: (RCTPromiseRejectBlock)reject)
242
+
243
+ RCT_EXTERN_METHOD(createNutritionRecord: (NSString)connectionUUID
244
+ nutritionRecord: (NSString)nutritionRecord
245
+ withResolver: (RCTPromiseResolveBlock)resolve
246
+ withRejecter: (RCTPromiseRejectBlock)reject)
247
+
248
+ RCT_EXTERN_METHOD(replaceNutritionRecord: (NSString)connectionUUID
249
+ nutritionRecord: (NSString)nutritionRecord
250
+ withResolver: (RCTPromiseResolveBlock)resolve
251
+ withRejecter: (RCTPromiseRejectBlock)reject)
252
+
199
253
  @end
@@ -1023,6 +1023,19 @@ class SpikeSdk: RCTEventEmitter {
1023
1023
  return config
1024
1024
  }
1025
1025
 
1026
+ private func makeNutritionalAnalysisConfig(fromString string: String?) throws -> NutritionalAnalysisConfig? {
1027
+ guard let string else {
1028
+ return nil
1029
+ }
1030
+ guard let data = string.data(using: .utf8) else {
1031
+ throw SpikeDataDecodingException()
1032
+ }
1033
+ let decoder = SpikeSDK.JSONDecoder.spikeDefaultJsonDecoder
1034
+ let config = try decoder.decode(NutritionalAnalysisConfig.self, from: data)
1035
+
1036
+ return config
1037
+ }
1038
+
1026
1039
  @objc(getUserProperties:withMetrics:withResolver:withRejecter:)
1027
1040
  func getUserProperties(
1028
1041
  connectionUUID: String,
@@ -1099,4 +1112,359 @@ class SpikeSdk: RCTEventEmitter {
1099
1112
  }
1100
1113
  }
1101
1114
 
1115
+ // MARK: - Nutrition AI
1116
+
1117
+ @objc(analyzeNutrition:
1118
+ imageBase64:
1119
+ consumedAt:
1120
+ config:
1121
+ withResolver:
1122
+ withRejecter:)
1123
+ func analyzeNutrition(
1124
+ connectionUUID: String,
1125
+ imageBase64: String,
1126
+ consumedAt: String?,
1127
+ config: String?,
1128
+ resolve: @escaping RCTPromiseResolveBlock,
1129
+ reject: @escaping RCTPromiseRejectBlock
1130
+ ) {
1131
+ Task {
1132
+ do {
1133
+ guard let connection = getConnectionV3(withUUID: connectionUUID) else {
1134
+ spikeReject(with: SpikeConnectionNotFoundException(), reject: reject)
1135
+ return
1136
+ }
1137
+
1138
+ let consumedAtDate = try consumedAt != nil ? makeDate(fromString: consumedAt!) : nil
1139
+ let configObject = try makeNutritionalAnalysisConfig(fromString: config)
1140
+
1141
+ let result = try await connection.analyzeNutrition(
1142
+ imageBase64: imageBase64,
1143
+ consumedAt: consumedAtDate,
1144
+ config: configObject
1145
+ )
1146
+
1147
+ let encoder = SpikeSDK.JSONEncoder.spikeDefaultJsonEncoder
1148
+ let jsonResult = try encoder.encode(result)
1149
+ let stringResult = String(data: jsonResult, encoding: .utf8)
1150
+
1151
+ resolve(stringResult)
1152
+ } catch let error {
1153
+ spikeReject(with: error, reject: reject)
1154
+ }
1155
+ }
1156
+ }
1157
+
1158
+ @objc(submitNutritionForAnalysis:
1159
+ imageBase64:
1160
+ consumedAt:
1161
+ config:
1162
+ withResolver:
1163
+ withRejecter:)
1164
+ func submitNutritionForAnalysis(
1165
+ connectionUUID: String,
1166
+ imageBase64: String,
1167
+ consumedAt: String?,
1168
+ config: String?,
1169
+ resolve: @escaping RCTPromiseResolveBlock,
1170
+ reject: @escaping RCTPromiseRejectBlock
1171
+ ) {
1172
+ Task {
1173
+ do {
1174
+ guard let connection = getConnectionV3(withUUID: connectionUUID) else {
1175
+ spikeReject(with: SpikeConnectionNotFoundException(), reject: reject)
1176
+ return
1177
+ }
1178
+
1179
+ let consumedAtDate = try consumedAt != nil ? makeDate(fromString: consumedAt!) : nil
1180
+ let configObject = try makeNutritionalAnalysisConfig(fromString: config)
1181
+
1182
+ let result = try await connection.submitNutritionForAnalysis(
1183
+ imageBase64: imageBase64,
1184
+ consumedAt: consumedAtDate,
1185
+ config: configObject
1186
+ )
1187
+
1188
+ resolve(result.uuidString)
1189
+ } catch let error {
1190
+ spikeReject(with: error, reject: reject)
1191
+ }
1192
+ }
1193
+ }
1194
+
1195
+ @objc(getNutritionRecords:
1196
+ from:
1197
+ to:
1198
+ withResolver:
1199
+ withRejecter:)
1200
+ func getNutritionRecords(
1201
+ connectionUUID: String,
1202
+ from: String,
1203
+ to: String,
1204
+ resolve: @escaping RCTPromiseResolveBlock,
1205
+ reject: @escaping RCTPromiseRejectBlock
1206
+ ) {
1207
+ Task {
1208
+ do {
1209
+ guard let connection = getConnectionV3(withUUID: connectionUUID) else {
1210
+ spikeReject(with: SpikeConnectionNotFoundException(), reject: reject)
1211
+ return
1212
+ }
1213
+
1214
+ let dateFrom = try makeDate(fromString: from)
1215
+ let dateTo = try makeDate(fromString: to)
1216
+
1217
+ let result = try await connection.getNutritionRecords(
1218
+ from: dateFrom,
1219
+ to: dateTo
1220
+ )
1221
+
1222
+ let encoder = SpikeSDK.JSONEncoder.spikeDefaultJsonEncoder
1223
+ let jsonResult = try encoder.encode(result)
1224
+ let stringResult = String(data: jsonResult, encoding: .utf8)
1225
+
1226
+ resolve(stringResult)
1227
+ } catch let error {
1228
+ spikeReject(with: error, reject: reject)
1229
+ }
1230
+ }
1231
+ }
1232
+
1233
+ @objc(getNutritionRecord:
1234
+ recordId:
1235
+ withResolver:
1236
+ withRejecter:)
1237
+ func getNutritionRecord(
1238
+ connectionUUID: String,
1239
+ recordId: String,
1240
+ resolve: @escaping RCTPromiseResolveBlock,
1241
+ reject: @escaping RCTPromiseRejectBlock
1242
+ ) {
1243
+ Task {
1244
+ do {
1245
+ guard let connection = getConnectionV3(withUUID: connectionUUID) else {
1246
+ spikeReject(with: SpikeConnectionNotFoundException(), reject: reject)
1247
+ return
1248
+ }
1249
+
1250
+ guard let uuid = UUID(uuidString: recordId) else {
1251
+ throw SpikeDataDecodingException()
1252
+ }
1253
+
1254
+ let result = try await connection.getNutritionRecord(id: uuid)
1255
+
1256
+ if let result = result {
1257
+ let encoder = SpikeSDK.JSONEncoder.spikeDefaultJsonEncoder
1258
+ let jsonResult = try encoder.encode(result)
1259
+ let stringResult = String(data: jsonResult, encoding: .utf8)
1260
+ resolve(stringResult)
1261
+ } else {
1262
+ resolve(nil)
1263
+ }
1264
+ } catch let error {
1265
+ spikeReject(with: error, reject: reject)
1266
+ }
1267
+ }
1268
+ }
1269
+
1270
+ @objc(deleteNutritionRecord:
1271
+ recordId:
1272
+ withResolver:
1273
+ withRejecter:)
1274
+ func deleteNutritionRecord(
1275
+ connectionUUID: String,
1276
+ recordId: String,
1277
+ resolve: @escaping RCTPromiseResolveBlock,
1278
+ reject: @escaping RCTPromiseRejectBlock
1279
+ ) {
1280
+ Task {
1281
+ do {
1282
+ guard let connection = getConnectionV3(withUUID: connectionUUID) else {
1283
+ spikeReject(with: SpikeConnectionNotFoundException(), reject: reject)
1284
+ return
1285
+ }
1286
+
1287
+ guard let uuid = UUID(uuidString: recordId) else {
1288
+ throw SpikeDataDecodingException()
1289
+ }
1290
+
1291
+ try await connection.deleteNutritionRecord(id: uuid)
1292
+
1293
+ resolve(Void())
1294
+ } catch let error {
1295
+ spikeReject(with: error, reject: reject)
1296
+ }
1297
+ }
1298
+ }
1299
+
1300
+ @objc(updateNutritionRecordServingSize:
1301
+ recordId:
1302
+ servingSize:
1303
+ withResolver:
1304
+ withRejecter:)
1305
+ func updateNutritionRecordServingSize(
1306
+ connectionUUID: String,
1307
+ recordId: String,
1308
+ servingSize: Double,
1309
+ resolve: @escaping RCTPromiseResolveBlock,
1310
+ reject: @escaping RCTPromiseRejectBlock
1311
+ ) {
1312
+ Task {
1313
+ do {
1314
+ guard let connection = getConnectionV3(withUUID: connectionUUID) else {
1315
+ spikeReject(with: SpikeConnectionNotFoundException(), reject: reject)
1316
+ return
1317
+ }
1318
+
1319
+ guard let uuid = UUID(uuidString: recordId) else {
1320
+ throw SpikeDataDecodingException()
1321
+ }
1322
+
1323
+ let result = try await connection.updateNutritionRecordServingSize(
1324
+ id: uuid,
1325
+ servingSize: servingSize
1326
+ )
1327
+
1328
+ let encoder = SpikeSDK.JSONEncoder.spikeDefaultJsonEncoder
1329
+ let jsonResult = try encoder.encode(result)
1330
+ let stringResult = String(data: jsonResult, encoding: .utf8)
1331
+
1332
+ resolve(stringResult)
1333
+ } catch let error {
1334
+ spikeReject(with: error, reject: reject)
1335
+ }
1336
+ }
1337
+ }
1338
+
1339
+ @objc(recognizeNutritionFactsLabel:
1340
+ imageBase64:
1341
+ config:
1342
+ withResolver:
1343
+ withRejecter:)
1344
+ func recognizeNutritionFactsLabel(
1345
+ connectionUUID: String,
1346
+ imageBase64: String,
1347
+ config: String?,
1348
+ resolve: @escaping RCTPromiseResolveBlock,
1349
+ reject: @escaping RCTPromiseRejectBlock
1350
+ ) {
1351
+ Task {
1352
+ do {
1353
+ guard let connection = getConnectionV3(withUUID: connectionUUID) else {
1354
+ spikeReject(with: SpikeConnectionNotFoundException(), reject: reject)
1355
+ return
1356
+ }
1357
+
1358
+ let configObject = try makeNutritionFactsLabelRecognitionConfig(fromString: config)
1359
+
1360
+ let result = try await connection.recognizeNutritionFactsLabel(
1361
+ imageBase64: imageBase64,
1362
+ config: configObject
1363
+ )
1364
+
1365
+ let encoder = SpikeSDK.JSONEncoder.spikeDefaultJsonEncoder
1366
+ let jsonResult = try encoder.encode(result)
1367
+ let stringResult = String(data: jsonResult, encoding: .utf8)
1368
+
1369
+ resolve(stringResult)
1370
+ } catch let error {
1371
+ spikeReject(with: error, reject: reject)
1372
+ }
1373
+ }
1374
+ }
1375
+
1376
+ @objc(createNutritionRecord:
1377
+ nutritionRecord:
1378
+ withResolver:
1379
+ withRejecter:)
1380
+ func createNutritionRecord(
1381
+ connectionUUID: String,
1382
+ nutritionRecord: String,
1383
+ resolve: @escaping RCTPromiseResolveBlock,
1384
+ reject: @escaping RCTPromiseRejectBlock
1385
+ ) {
1386
+ Task {
1387
+ do {
1388
+ guard let connection = getConnectionV3(withUUID: connectionUUID) else {
1389
+ spikeReject(with: SpikeConnectionNotFoundException(), reject: reject)
1390
+ return
1391
+ }
1392
+
1393
+ guard let recordObject = try makeNutritionRecord(fromString: nutritionRecord) else {
1394
+ throw SpikeDataDecodingException()
1395
+ }
1396
+
1397
+ let result = try await connection.createNutritionRecord(recordObject)
1398
+
1399
+ let encoder = SpikeSDK.JSONEncoder.spikeDefaultJsonEncoder
1400
+ let jsonResult = try encoder.encode(result)
1401
+ let stringResult = String(data: jsonResult, encoding: .utf8)
1402
+
1403
+ resolve(stringResult)
1404
+ } catch let error {
1405
+ spikeReject(with: error, reject: reject)
1406
+ }
1407
+ }
1408
+ }
1409
+
1410
+ @objc(replaceNutritionRecord:
1411
+ nutritionRecord:
1412
+ withResolver:
1413
+ withRejecter:)
1414
+ func replaceNutritionRecord(
1415
+ connectionUUID: String,
1416
+ nutritionRecord: String,
1417
+ resolve: @escaping RCTPromiseResolveBlock,
1418
+ reject: @escaping RCTPromiseRejectBlock
1419
+ ) {
1420
+ Task {
1421
+ do {
1422
+ guard let connection = getConnectionV3(withUUID: connectionUUID) else {
1423
+ spikeReject(with: SpikeConnectionNotFoundException(), reject: reject)
1424
+ return
1425
+ }
1426
+
1427
+ guard let recordObject = try makeNutritionRecord(fromString: nutritionRecord) else {
1428
+ throw SpikeDataDecodingException()
1429
+ }
1430
+
1431
+ let result = try await connection.replaceNutritionRecord(recordObject)
1432
+
1433
+ let encoder = SpikeSDK.JSONEncoder.spikeDefaultJsonEncoder
1434
+ let jsonResult = try encoder.encode(result)
1435
+ let stringResult = String(data: jsonResult, encoding: .utf8)
1436
+
1437
+ resolve(stringResult)
1438
+ } catch let error {
1439
+ spikeReject(with: error, reject: reject)
1440
+ }
1441
+ }
1442
+ }
1443
+
1444
+ private func makeNutritionFactsLabelRecognitionConfig(fromString string: String?) throws -> NutritionFactsLabelRecognitionConfig? {
1445
+ guard let string else {
1446
+ return nil
1447
+ }
1448
+ guard let data = string.data(using: .utf8) else {
1449
+ throw SpikeDataDecodingException()
1450
+ }
1451
+ let decoder = SpikeSDK.JSONDecoder.spikeDefaultJsonDecoder
1452
+ let config = try decoder.decode(NutritionFactsLabelRecognitionConfig.self, from: data)
1453
+
1454
+ return config
1455
+ }
1456
+
1457
+ private func makeNutritionRecord(fromString string: String?) throws -> NutritionRecord? {
1458
+ guard let string else {
1459
+ return nil
1460
+ }
1461
+ guard let data = string.data(using: .utf8) else {
1462
+ throw SpikeDataDecodingException()
1463
+ }
1464
+ let decoder = SpikeSDK.JSONDecoder.spikeDefaultJsonDecoder
1465
+ let record = try decoder.decode(NutritionRecord.self, from: data)
1466
+
1467
+ return record
1468
+ }
1469
+
1102
1470
  }