react-native-spike-sdk 2.4.4 → 2.5.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 (34) hide show
  1. package/android/src/main/java/com/spikesdk/SpikeSdkModule.kt +174 -124
  2. package/ios/SpikeDataTypeMapper.swift +16 -0
  3. package/lib/commonjs/DataModels/SpikeDataTypes.js +2 -1
  4. package/lib/commonjs/DataModels/SpikeDataTypes.js.map +1 -1
  5. package/lib/commonjs/DataModels/SpikeEcgDataEntry.js +2 -0
  6. package/lib/commonjs/DataModels/SpikeEcgDataEntry.js.map +1 -0
  7. package/lib/commonjs/DataTypes/SpikeDataType.js +5 -1
  8. package/lib/commonjs/DataTypes/SpikeDataType.js.map +1 -1
  9. package/lib/commonjs/SpikeConnection.js +48 -0
  10. package/lib/commonjs/SpikeConnection.js.map +1 -1
  11. package/lib/module/DataModels/SpikeDataTypes.js +3 -2
  12. package/lib/module/DataModels/SpikeDataTypes.js.map +1 -1
  13. package/lib/module/DataModels/SpikeEcgDataEntry.js +2 -0
  14. package/lib/module/DataModels/SpikeEcgDataEntry.js.map +1 -0
  15. package/lib/module/DataTypes/SpikeDataType.js +3 -0
  16. package/lib/module/DataTypes/SpikeDataType.js.map +1 -1
  17. package/lib/module/SpikeConnection.js +49 -1
  18. package/lib/module/SpikeConnection.js.map +1 -1
  19. package/lib/typescript/DataModels/SpikeDataTypes.d.ts +2 -1
  20. package/lib/typescript/DataModels/SpikeDataTypes.d.ts.map +1 -1
  21. package/lib/typescript/DataModels/SpikeEcgDataEntry.d.ts +13 -0
  22. package/lib/typescript/DataModels/SpikeEcgDataEntry.d.ts.map +1 -0
  23. package/lib/typescript/DataTypes/SpikeDataType.d.ts +6 -1
  24. package/lib/typescript/DataTypes/SpikeDataType.d.ts.map +1 -1
  25. package/lib/typescript/SpikeConnection.d.ts +3 -1
  26. package/lib/typescript/SpikeConnection.d.ts.map +1 -1
  27. package/lib/typescript/SpikeConnectionTypes.d.ts +12 -4
  28. package/lib/typescript/SpikeConnectionTypes.d.ts.map +1 -1
  29. package/package.json +2 -2
  30. package/src/DataModels/SpikeDataTypes.ts +2 -0
  31. package/src/DataModels/SpikeEcgDataEntry.ts +12 -0
  32. package/src/DataTypes/SpikeDataType.ts +9 -1
  33. package/src/SpikeConnection.ts +60 -0
  34. package/src/SpikeConnectionTypes.ts +14 -3
@@ -18,6 +18,8 @@ import kotlinx.coroutines.CoroutineScope
18
18
  import kotlinx.coroutines.Dispatchers
19
19
  import kotlinx.coroutines.SupervisorJob
20
20
  import kotlinx.coroutines.launch
21
+ import kotlinx.coroutines.sync.Mutex
22
+ import kotlinx.coroutines.sync.withLock
21
23
  import java.time.OffsetDateTime
22
24
  import java.util.UUID
23
25
 
@@ -32,7 +34,8 @@ fun <I, O> ComponentActivity.registerActivityResultLauncher(
32
34
  class SpikeSdkModule(reactContext: ReactApplicationContext) :
33
35
  ReactContextBaseJavaModule(reactContext), LifecycleEventListener {
34
36
 
35
- private val connections = mutableMapOf<String, SpikeConnection>()
37
+ // Do not use this directly, use `addConnection` and `getConnection` instead
38
+ private val _connections = mutableMapOf<String, SpikeConnection>()
36
39
 
37
40
  private val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
38
41
 
@@ -85,7 +88,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
85
88
  } else {
86
89
  null
87
90
  }
88
- connections[uuid] = SpikeConnection.createConnection(
91
+ addConnection(connection = SpikeConnection.createConnection(
89
92
  context = reactApplicationContext,
90
93
  authToken = authToken,
91
94
  customerEndUserId = customerEndUserId,
@@ -93,7 +96,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
93
96
  callbackUrl = callbackUrl,
94
97
  env = SpikeEnvironment.PROD,
95
98
  logger = logger,
96
- )
99
+ ), uuid = uuid)
97
100
  promise.resolve(uuid)
98
101
  } catch (e: SpikeExceptions) {
99
102
  promise.reject(e.mapException(), e.message)
@@ -103,38 +106,43 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
103
106
 
104
107
  @ReactMethod
105
108
  fun getAppId(uuid: String, promise: Promise) {
106
- try {
107
- val connection = connections[uuid] ?: return promise.reject(
108
- SpikeExceptions.SpikeException(
109
- "Connection not found"
110
- ).mapException(), "Connection not found"
111
- )
112
- val appId = connection.getAppId()
113
- promise.resolve(appId)
114
- } catch (e: SpikeExceptions) {
115
- promise.reject(e.mapException(), e.message)
109
+ scope.launch {
110
+ try {
111
+ val connection = getConnection(uuid) ?: return@launch promise.reject(
112
+ SpikeExceptions.SpikeException(
113
+ "Connection not found"
114
+ ).mapException(), "Connection not found"
115
+ )
116
+ val appId = connection.getAppId()
117
+ promise.resolve(appId)
118
+ } catch (e: SpikeExceptions) {
119
+ promise.reject(e.mapException(), e.message)
120
+ }
116
121
  }
117
122
  }
118
123
 
119
124
  @ReactMethod
120
125
  fun getSpikeEndUserId(uuid: String, promise: Promise) {
121
- try {
122
- val connection = connections[uuid] ?: return promise.reject(
123
- SpikeExceptions.SpikeException(
124
- "Connection not found"
125
- ).mapException(), "Connection not found"
126
- )
127
- val spikeEndUserId = connection.getSpikeUserId()
128
- promise.resolve(spikeEndUserId)
129
- } catch (e: SpikeExceptions) {
130
- promise.reject(e.mapException(), e.message)
126
+ scope.launch {
127
+ try {
128
+ val connection = getConnection(uuid) ?: return@launch promise.reject(
129
+ SpikeExceptions.SpikeException(
130
+ "Connection not found"
131
+ ).mapException(), "Connection not found"
132
+ )
133
+ val spikeEndUserId = connection.getSpikeUserId()
134
+ promise.resolve(spikeEndUserId)
135
+ } catch (e: SpikeExceptions) {
136
+ promise.reject(e.mapException(), e.message)
137
+ }
131
138
  }
132
139
  }
133
140
 
134
141
  @ReactMethod
135
142
  fun getCustomerEndUserId(uuid: String, promise: Promise) {
143
+ scope.launch {
136
144
  try {
137
- val connection = connections[uuid] ?: return promise.reject(
145
+ val connection = getConnection(uuid) ?: return@launch promise.reject(
138
146
  SpikeExceptions.SpikeException(
139
147
  "Connection not found"
140
148
  ).mapException(), "Connection not found"
@@ -144,21 +152,23 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
144
152
  } catch (e: SpikeExceptions) {
145
153
  promise.reject(e.mapException(), e.message)
146
154
  }
155
+ }
147
156
  }
148
157
 
149
158
  @ReactMethod
150
159
  fun getCallbackUrl(uuid: String, promise: Promise) {
151
- try {
152
- val connection =
153
- connections[uuid] ?: return promise.reject(
160
+ scope.launch {
161
+ try {
162
+ val connection = getConnection(uuid) ?: return@launch promise.reject(
154
163
  SpikeExceptions.SpikeException(
155
164
  "Connection not found"
156
165
  ).mapException(), "Connection not found"
157
166
  )
158
- val callbackUrl = connection.getPostbackUrl()
159
- promise.resolve(callbackUrl)
160
- } catch (e: SpikeExceptions) {
161
- promise.reject(e.mapException(), e.message)
167
+ val callbackUrl = connection.getPostbackUrl()
168
+ promise.resolve(callbackUrl)
169
+ } catch (e: SpikeExceptions) {
170
+ promise.reject(e.mapException(), e.message)
171
+ }
162
172
  }
163
173
  }
164
174
 
@@ -167,7 +177,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
167
177
  fun close(uuid: String, promise: Promise) {
168
178
  scope.launch {
169
179
  try {
170
- val connection = connections[uuid] ?: return@launch promise.reject(
180
+ val connection = getConnection(uuid) ?: return@launch promise.reject(
171
181
  SpikeExceptions.SpikeException(
172
182
  "Connection not found"
173
183
  ).mapException(), "Connection not found"
@@ -190,7 +200,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
190
200
  ) {
191
201
  scope.launch {
192
202
  try {
193
- val connection = connections[connectionUUID] ?: return@launch promise.reject(
203
+ val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
194
204
  SpikeExceptions.SpikeException(
195
205
  "Connection not found"
196
206
  ).mapException(), "Connection not found"
@@ -217,7 +227,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
217
227
  ) {
218
228
  scope.launch {
219
229
  try {
220
- val connection = connections[connectionUUID] ?: return@launch promise.reject(
230
+ val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
221
231
  SpikeExceptions.SpikeException(
222
232
  "Connection not found"
223
233
  ).mapException(), "Connection not found"
@@ -242,7 +252,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
242
252
  ) {
243
253
  scope.launch {
244
254
  try {
245
- val connection = connections[connectionUUID] ?: return@launch promise.reject(
255
+ val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
246
256
  SpikeExceptions.SpikeException(
247
257
  "Connection not found"
248
258
  ).mapException(), "Connection not found"
@@ -265,7 +275,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
265
275
  ) {
266
276
  scope.launch {
267
277
  try {
268
- val connection = connections[connectionUUID] ?: return@launch promise.reject(
278
+ val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
269
279
  SpikeExceptions.SpikeException(
270
280
  "Connection not found"
271
281
  ).mapException(), "Connection not found"
@@ -282,16 +292,18 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
282
292
 
283
293
  @ReactMethod
284
294
  fun manageHealthConnect(connectionUUID: String, promise: Promise) {
285
- try {
286
- val connection = connections[connectionUUID] ?: return promise.reject(
287
- SpikeExceptions.SpikeException(
288
- "Connection not found"
289
- ).mapException(), "Connection not found"
290
- )
291
- connection.manageHealthConnect()
292
- promise.resolve(true)
293
- } catch (e: SpikeExceptions) {
294
- promise.reject(e.mapException(), e.message)
295
+ scope.launch {
296
+ try {
297
+ val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
298
+ SpikeExceptions.SpikeException(
299
+ "Connection not found"
300
+ ).mapException(), "Connection not found"
301
+ )
302
+ connection.manageHealthConnect()
303
+ promise.resolve(true)
304
+ } catch (e: SpikeExceptions) {
305
+ promise.reject(e.mapException(), e.message)
306
+ }
295
307
  }
296
308
  }
297
309
 
@@ -299,7 +311,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
299
311
  fun checkPermissionsGranted(connectionUUID: String, dataType: String, promise: Promise) {
300
312
  scope.launch {
301
313
  try {
302
- val connection = connections[connectionUUID] ?: return@launch promise.reject(
314
+ val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
303
315
  SpikeExceptions.SpikeException(
304
316
  "Connection not found"
305
317
  ).mapException(), "Connection not found"
@@ -320,7 +332,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
320
332
  fun getHealthConnectAvailability(connectionUUID: String, promise: Promise) {
321
333
  scope.launch {
322
334
  try {
323
- val connection = connections[connectionUUID] ?: return@launch promise.reject(
335
+ val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
324
336
  SpikeExceptions.SpikeException(
325
337
  "Connection not found"
326
338
  ).mapException(), "Connection not found"
@@ -337,7 +349,7 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
337
349
  fun revokeAllPermissions(connectionUUID: String, promise: Promise) {
338
350
  scope.launch {
339
351
  try {
340
- val connection = connections[connectionUUID] ?: return@launch promise.reject(
352
+ val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
341
353
  SpikeExceptions.SpikeException(
342
354
  "Connection not found"
343
355
  ).mapException(), "Connection not found"
@@ -352,98 +364,117 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
352
364
 
353
365
  @ReactMethod
354
366
  fun requestHealthPermissions(connectionUUID: String, dataType: String, promise: Promise) {
355
- val connection = connections[connectionUUID] ?: return promise.reject(
356
- SpikeExceptions.SpikeException(
357
- "Connection not found"
358
- ).mapException(), "Connection not found"
359
- )
360
-
361
- val permissions =
362
- connection.getRequiredHealthPermissionsMetadata(dataType.toSpikeDataType())
363
-
364
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) {
365
- val intent = SpikeConnection.requestReadAuthorization().createIntent(
366
- reactApplicationContext, permissions
367
- )
368
-
369
- val availability = connection.getHealthConnectAvailability()
370
- if (availability == HealthConnectAvailability.INSTALLED) {
371
- reactApplicationContext.currentActivity?.startActivityForResult(
372
- intent,
373
- REQUEST_CODE
367
+ scope.launch {
368
+ val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
369
+ SpikeExceptions.SpikeException(
370
+ "Connection not found"
371
+ ).mapException(), "Connection not found"
372
+ )
373
+
374
+ val permissions =
375
+ connection.getRequiredHealthPermissionsMetadata(dataType.toSpikeDataType())
376
+
377
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) {
378
+ val intent = SpikeConnection.requestReadAuthorization().createIntent(
379
+ reactApplicationContext, permissions
374
380
  )
375
- promise.resolve(true)
376
- } else {
377
- promise.reject(SpikeExceptions.SpikeException().mapException(), SpikeExceptions.SpikeException().message)
378
- }
379
- } else {
380
- val activity = reactApplicationContext.currentActivity
381
- if (activity is ComponentActivity) {
382
- checkPermissionsFor = Triple(connectionUUID, setOf(dataType), promise)
383
- val launcher =
384
- activity.registerActivityResultLauncher(
385
- SpikeConnection.requestReadAuthorization()
386
- ) {
387
381
 
382
+ val availability = connection.getHealthConnectAvailability()
383
+ if (availability == HealthConnectAvailability.INSTALLED) {
384
+ reactApplicationContext.currentActivity?.startActivityForResult(
385
+ intent,
386
+ REQUEST_CODE
387
+ )
388
+ promise.resolve(true)
389
+ } else {
390
+ promise.reject(
391
+ SpikeExceptions.SpikeException().mapException(),
392
+ SpikeExceptions.SpikeException().message
393
+ )
394
+ }
395
+ } else {
396
+ val activity = reactApplicationContext.currentActivity
397
+ if (activity is ComponentActivity) {
398
+ checkPermissionsFor = Triple(connectionUUID, setOf(dataType), promise)
399
+ val launcher =
400
+ activity.registerActivityResultLauncher(
401
+ SpikeConnection.requestReadAuthorization()
402
+ ) {
403
+
404
+ }
405
+
406
+ if (permissions.isNotEmpty()) {
407
+ launcher.launch(permissions)
408
+ } else {
409
+ promise.resolve(false)
388
410
  }
389
-
390
- if (permissions.isNotEmpty()) {
391
- launcher.launch(permissions)
392
411
  } else {
393
412
  promise.resolve(false)
394
413
  }
395
- } else {
396
- promise.resolve(false)
397
414
  }
398
415
  }
399
416
  }
400
417
 
401
418
  @ReactMethod
402
419
  fun requestMultipleHealthPermissions(connectionUUID: String, dataTypes: ReadableArray, promise: Promise) {
403
- val connection = connections[connectionUUID] ?: return promise.reject(
404
- SpikeExceptions.SpikeException(
405
- "Connection not found"
406
- ).mapException(), "Connection not found"
407
- )
408
-
409
- val permissions = mutableSetOf<String>()
410
- dataTypes.toArrayList().forEach {
411
- connection.getRequiredHealthPermissionsMetadata((it as String).toSpikeDataType()).forEach {
412
- permissions.add(it)
413
- }
414
- }
415
-
416
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) {
417
- val availability = connection.getHealthConnectAvailability()
418
- if (permissions.isNotEmpty() && availability == HealthConnectAvailability.INSTALLED) {
419
- val intent = SpikeConnection.requestReadAuthorization().createIntent(
420
- reactApplicationContext, permissions
421
- )
420
+ scope.launch {
421
+ val connection = getConnection(connectionUUID) ?: return@launch promise.reject(
422
+ SpikeExceptions.SpikeException(
423
+ "Connection not found"
424
+ ).mapException(), "Connection not found"
425
+ )
422
426
 
423
- reactApplicationContext.currentActivity?.startActivityForResult(
424
- intent,
425
- REQUEST_CODE
426
- )
427
- promise.resolve(true)
428
- } else {
429
- promise.reject(SpikeExceptions.SpikeException().mapException(), SpikeExceptions.SpikeException().message)
427
+ val permissions = mutableSetOf<String>()
428
+ dataTypes.toArrayList().forEach {
429
+ connection.getRequiredHealthPermissionsMetadata((it as String).toSpikeDataType())
430
+ .forEach {
431
+ permissions.add(it)
432
+ }
430
433
  }
431
- } else {
432
- val activity = reactApplicationContext.currentActivity
433
- if (activity is ComponentActivity) {
434
- checkPermissionsFor = Triple(connectionUUID, dataTypes.toArrayList().toSet() as Set<String>, promise)
435
- val launcher =
436
- activity.registerActivityResultLauncher(
437
- SpikeConnection.requestReadAuthorization()
438
- ) {
439
434
 
440
- }
441
- if (permissions.isNotEmpty()) {
442
- launcher.launch(permissions)
435
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) {
436
+ val availability = connection.getHealthConnectAvailability()
437
+ if (permissions.isNotEmpty() && availability == HealthConnectAvailability.INSTALLED) {
438
+ val intent = SpikeConnection.requestReadAuthorization().createIntent(
439
+ reactApplicationContext, permissions
440
+ )
441
+
442
+ reactApplicationContext.currentActivity?.startActivityForResult(
443
+ intent,
444
+ REQUEST_CODE
445
+ )
446
+ promise.resolve(true)
443
447
  } else {
444
- promise.reject(SpikeExceptions.SpikeException().mapException(), SpikeExceptions.SpikeException().message) }
448
+ promise.reject(
449
+ SpikeExceptions.SpikeException().mapException(),
450
+ SpikeExceptions.SpikeException().message
451
+ )
452
+ }
445
453
  } else {
446
- promise.resolve(false)
454
+ val activity = reactApplicationContext.currentActivity
455
+ if (activity is ComponentActivity) {
456
+ checkPermissionsFor = Triple(
457
+ connectionUUID,
458
+ dataTypes.toArrayList().toSet() as Set<String>,
459
+ promise
460
+ )
461
+ val launcher =
462
+ activity.registerActivityResultLauncher(
463
+ SpikeConnection.requestReadAuthorization()
464
+ ) {
465
+
466
+ }
467
+ if (permissions.isNotEmpty()) {
468
+ launcher.launch(permissions)
469
+ } else {
470
+ promise.reject(
471
+ SpikeExceptions.SpikeException().mapException(),
472
+ SpikeExceptions.SpikeException().message
473
+ )
474
+ }
475
+ } else {
476
+ promise.resolve(false)
477
+ }
447
478
  }
448
479
  }
449
480
  }
@@ -504,4 +535,23 @@ class SpikeSdkModule(reactContext: ReactApplicationContext) :
504
535
  const val NAME = "SpikeSdk"
505
536
  const val REQUEST_CODE = 4200
506
537
  }
538
+
539
+ // Connections
540
+
541
+ private val mutex = Mutex()
542
+
543
+ // Add new connection to the dictionary in a thread-safe manner
544
+ private suspend fun addConnection(connection: SpikeConnection, uuid: String) {
545
+ mutex.withLock {
546
+ _connections[uuid] = connection
547
+ }
548
+ }
549
+
550
+ // Synchronised read for safe multithreaded usage
551
+ private suspend fun getConnection(uuid: String): SpikeConnection? {
552
+ mutex.withLock {
553
+ return _connections[uuid]
554
+ }
555
+ }
556
+
507
557
  }
@@ -29,6 +29,8 @@ class SpikeDataTypeMapper {
29
29
  return SpikeDataTypes.stepsIntraday
30
30
  case "body":
31
31
  return SpikeDataTypes.body
32
+ case "ecg":
33
+ return SpikeDataTypes.ecg
32
34
  default:
33
35
  return SpikeDataTypes.activitiesSummary
34
36
  }
@@ -60,6 +62,8 @@ class SpikeDataTypeMapper {
60
62
  return "steps_intraday"
61
63
  case is SpikeBodyDataType:
62
64
  return "body"
65
+ case is SpikeECGDataType:
66
+ return "ecg"
63
67
  default:
64
68
  return "activities_summary"
65
69
  }
@@ -103,6 +107,9 @@ class SpikeDataTypeMapper {
103
107
  case "body":
104
108
  let value = try await connection.extractData(SpikeDataTypes.body)
105
109
  return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
110
+ case "ecg":
111
+ let value = try await connection.extractData(SpikeDataTypes.ecg)
112
+ return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
106
113
  default:
107
114
  return nil
108
115
  }
@@ -146,6 +153,9 @@ class SpikeDataTypeMapper {
146
153
  case "body":
147
154
  let value = try await connection.extractData(SpikeDataTypes.body, from: from, to: to)
148
155
  return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
156
+ case "ecg":
157
+ let value = try await connection.extractData(SpikeDataTypes.ecg, from: from, to: to)
158
+ return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
149
159
  default:
150
160
  return nil
151
161
  }
@@ -189,6 +199,9 @@ class SpikeDataTypeMapper {
189
199
  case "body":
190
200
  let value = try await connection.extractAndPostData(SpikeDataTypes.body)
191
201
  return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
202
+ case "ecg":
203
+ let value = try await connection.extractAndPostData(SpikeDataTypes.ecg)
204
+ return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
192
205
  default:
193
206
  return nil
194
207
  }
@@ -232,6 +245,9 @@ class SpikeDataTypeMapper {
232
245
  case "body":
233
246
  let value = try await connection.extractAndPostData(SpikeDataTypes.body, from: from, to: to)
234
247
  return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
248
+ case "ecg":
249
+ let value = try await connection.extractAndPostData(SpikeDataTypes.ecg, from: from, to: to)
250
+ return try? String(data: JSONEncoder().encode(value), encoding: .utf8)
235
251
  default:
236
252
  return nil
237
253
  }
@@ -17,6 +17,7 @@ const SpikeDataTypes = exports.SpikeDataTypes = {
17
17
  sleep: new _SpikeDataType.SpikeSleepDataType(),
18
18
  steps: new _SpikeDataType.SpikeStepsDataType(),
19
19
  stepsIntraday: new _SpikeDataType.SpikeStepsIntradayDataType(),
20
- body: new _SpikeDataType.SpikeBodyDataType()
20
+ body: new _SpikeDataType.SpikeBodyDataType(),
21
+ ecg: new _SpikeDataType.SpikeEcgDataType()
21
22
  };
22
23
  //# sourceMappingURL=SpikeDataTypes.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_SpikeDataType","require","SpikeDataTypes","exports","activitiesSummary","SpikeActivitiesSummaryDataType","activitiesStream","SpikeActivitiesStreamDataType","breathing","SpikeBreathingDataType","calories","SpikeCaloriesDataType","distance","SpikeDistanceDataType","glucose","SpikeGlucoseDataType","heart","SpikeHeartDataType","oxygenSaturation","SpikeOxygenSaturationDataType","sleep","SpikeSleepDataType","steps","SpikeStepsDataType","stepsIntraday","SpikeStepsIntradayDataType","body","SpikeBodyDataType"],"sourceRoot":"../../../src","sources":["DataModels/SpikeDataTypes.ts"],"mappings":";;;;;;AAAA,IAAAA,cAAA,GAAAC,OAAA;AAeO,MAAMC,cAAc,GAAAC,OAAA,CAAAD,cAAA,GAAG;EAC5BE,iBAAiB,EAAE,IAAIC,6CAA8B,CAAC,CAAC;EACvDC,gBAAgB,EAAE,IAAIC,4CAA6B,CAAC,CAAC;EACrDC,SAAS,EAAE,IAAIC,qCAAsB,CAAC,CAAC;EACvCC,QAAQ,EAAE,IAAIC,oCAAqB,CAAC,CAAC;EACrCC,QAAQ,EAAE,IAAIC,oCAAqB,CAAC,CAAC;EACrCC,OAAO,EAAE,IAAIC,mCAAoB,CAAC,CAAC;EACnCC,KAAK,EAAE,IAAIC,iCAAkB,CAAC,CAAC;EAC/BC,gBAAgB,EAAE,IAAIC,4CAA6B,CAAC,CAAC;EACrDC,KAAK,EAAE,IAAIC,iCAAkB,CAAC,CAAC;EAC/BC,KAAK,EAAE,IAAIC,iCAAkB,CAAC,CAAC;EAC/BC,aAAa,EAAE,IAAIC,yCAA0B,CAAC,CAAC;EAC/CC,IAAI,EAAE,IAAIC,gCAAiB,CAAC;AAC9B,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["_SpikeDataType","require","SpikeDataTypes","exports","activitiesSummary","SpikeActivitiesSummaryDataType","activitiesStream","SpikeActivitiesStreamDataType","breathing","SpikeBreathingDataType","calories","SpikeCaloriesDataType","distance","SpikeDistanceDataType","glucose","SpikeGlucoseDataType","heart","SpikeHeartDataType","oxygenSaturation","SpikeOxygenSaturationDataType","sleep","SpikeSleepDataType","steps","SpikeStepsDataType","stepsIntraday","SpikeStepsIntradayDataType","body","SpikeBodyDataType","ecg","SpikeEcgDataType"],"sourceRoot":"../../../src","sources":["DataModels/SpikeDataTypes.ts"],"mappings":";;;;;;AAAA,IAAAA,cAAA,GAAAC,OAAA;AAgBO,MAAMC,cAAc,GAAAC,OAAA,CAAAD,cAAA,GAAG;EAC5BE,iBAAiB,EAAE,IAAIC,6CAA8B,CAAC,CAAC;EACvDC,gBAAgB,EAAE,IAAIC,4CAA6B,CAAC,CAAC;EACrDC,SAAS,EAAE,IAAIC,qCAAsB,CAAC,CAAC;EACvCC,QAAQ,EAAE,IAAIC,oCAAqB,CAAC,CAAC;EACrCC,QAAQ,EAAE,IAAIC,oCAAqB,CAAC,CAAC;EACrCC,OAAO,EAAE,IAAIC,mCAAoB,CAAC,CAAC;EACnCC,KAAK,EAAE,IAAIC,iCAAkB,CAAC,CAAC;EAC/BC,gBAAgB,EAAE,IAAIC,4CAA6B,CAAC,CAAC;EACrDC,KAAK,EAAE,IAAIC,iCAAkB,CAAC,CAAC;EAC/BC,KAAK,EAAE,IAAIC,iCAAkB,CAAC,CAAC;EAC/BC,aAAa,EAAE,IAAIC,yCAA0B,CAAC,CAAC;EAC/CC,IAAI,EAAE,IAAIC,gCAAiB,CAAC,CAAC;EAC7BC,GAAG,EAAE,IAAIC,+BAAgB,CAAC;AAC5B,CAAC","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=SpikeEcgDataEntry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sourceRoot":"../../../src","sources":["DataModels/SpikeEcgDataEntry.ts"],"mappings":"","ignoreList":[]}
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.SpikeStepsIntradayDataType = exports.SpikeStepsDataType = exports.SpikeSleepDataType = exports.SpikeOxygenSaturationDataType = exports.SpikeHeartDataType = exports.SpikeGlucoseDataType = exports.SpikeDistanceDataType = exports.SpikeCaloriesDataType = exports.SpikeBreathingDataType = exports.SpikeBodyDataType = exports.SpikeActivitiesSummaryDataType = exports.SpikeActivitiesStreamDataType = void 0;
6
+ exports.SpikeStepsIntradayDataType = exports.SpikeStepsDataType = exports.SpikeSleepDataType = exports.SpikeOxygenSaturationDataType = exports.SpikeHeartDataType = exports.SpikeGlucoseDataType = exports.SpikeEcgDataType = exports.SpikeDistanceDataType = exports.SpikeCaloriesDataType = exports.SpikeBreathingDataType = exports.SpikeBodyDataType = exports.SpikeActivitiesSummaryDataType = exports.SpikeActivitiesStreamDataType = void 0;
7
7
  class SpikeActivitiesStreamDataType {
8
8
  rawValue = 'activities_stream';
9
9
  }
@@ -52,4 +52,8 @@ class SpikeBodyDataType {
52
52
  rawValue = 'body';
53
53
  }
54
54
  exports.SpikeBodyDataType = SpikeBodyDataType;
55
+ class SpikeEcgDataType {
56
+ rawValue = 'ecg';
57
+ }
58
+ exports.SpikeEcgDataType = SpikeEcgDataType;
55
59
  //# sourceMappingURL=SpikeDataType.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["SpikeActivitiesStreamDataType","rawValue","exports","SpikeActivitiesSummaryDataType","SpikeBreathingDataType","SpikeCaloriesDataType","SpikeDistanceDataType","SpikeGlucoseDataType","SpikeHeartDataType","SpikeOxygenSaturationDataType","SpikeSleepDataType","SpikeStepsDataType","SpikeStepsIntradayDataType","SpikeBodyDataType"],"sourceRoot":"../../../src","sources":["DataTypes/SpikeDataType.ts"],"mappings":";;;;;;AA0BO,MAAMA,6BAA6B,CAAC;EACzCC,QAAQ,GAAwB,mBAAmB;AAErD;AAACC,OAAA,CAAAF,6BAAA,GAAAA,6BAAA;AAEM,MAAMG,8BAA8B,CAAC;EAC1CF,QAAQ,GAAwB,oBAAoB;AAEtD;AAACC,OAAA,CAAAC,8BAAA,GAAAA,8BAAA;AAEM,MAAMC,sBAAsB,CAAC;EAClCH,QAAQ,GAAwB,WAAW;AAE7C;AAACC,OAAA,CAAAE,sBAAA,GAAAA,sBAAA;AAEM,MAAMC,qBAAqB,CAAC;EACjCJ,QAAQ,GAAwB,UAAU;AAE5C;AAACC,OAAA,CAAAG,qBAAA,GAAAA,qBAAA;AAEM,MAAMC,qBAAqB,CAAC;EACjCL,QAAQ,GAAwB,UAAU;AAE5C;AAACC,OAAA,CAAAI,qBAAA,GAAAA,qBAAA;AAEM,MAAMC,oBAAoB,CAAC;EAChCN,QAAQ,GAAwB,SAAS;AAE3C;AAACC,OAAA,CAAAK,oBAAA,GAAAA,oBAAA;AAEM,MAAMC,kBAAkB,CAAC;EAC9BP,QAAQ,GAAwB,OAAO;AAEzC;AAACC,OAAA,CAAAM,kBAAA,GAAAA,kBAAA;AAEM,MAAMC,6BAA6B,CAAC;EACzCR,QAAQ,GAAwB,mBAAmB;AAErD;AAACC,OAAA,CAAAO,6BAAA,GAAAA,6BAAA;AAEM,MAAMC,kBAAkB,CAAC;EAC9BT,QAAQ,GAAwB,OAAO;AAEzC;AAACC,OAAA,CAAAQ,kBAAA,GAAAA,kBAAA;AAEM,MAAMC,kBAAkB,CAAC;EAC9BV,QAAQ,GAAwB,OAAO;AAEzC;AAACC,OAAA,CAAAS,kBAAA,GAAAA,kBAAA;AAEM,MAAMC,0BAA0B,CAAC;EACtCX,QAAQ,GAAwB,gBAAgB;AAElD;AAACC,OAAA,CAAAU,0BAAA,GAAAA,0BAAA;AAEM,MAAMC,iBAAiB,CAAC;EAC7BZ,QAAQ,GAAwB,MAAM;AAExC;AAACC,OAAA,CAAAW,iBAAA,GAAAA,iBAAA","ignoreList":[]}
1
+ {"version":3,"names":["SpikeActivitiesStreamDataType","rawValue","exports","SpikeActivitiesSummaryDataType","SpikeBreathingDataType","SpikeCaloriesDataType","SpikeDistanceDataType","SpikeGlucoseDataType","SpikeHeartDataType","SpikeOxygenSaturationDataType","SpikeSleepDataType","SpikeStepsDataType","SpikeStepsIntradayDataType","SpikeBodyDataType","SpikeEcgDataType"],"sourceRoot":"../../../src","sources":["DataTypes/SpikeDataType.ts"],"mappings":";;;;;;AA6BO,MAAMA,6BAA6B,CAAC;EACzCC,QAAQ,GAAwB,mBAAmB;AAErD;AAACC,OAAA,CAAAF,6BAAA,GAAAA,6BAAA;AAEM,MAAMG,8BAA8B,CAAC;EAC1CF,QAAQ,GAAwB,oBAAoB;AAEtD;AAACC,OAAA,CAAAC,8BAAA,GAAAA,8BAAA;AAEM,MAAMC,sBAAsB,CAAC;EAClCH,QAAQ,GAAwB,WAAW;AAE7C;AAACC,OAAA,CAAAE,sBAAA,GAAAA,sBAAA;AAEM,MAAMC,qBAAqB,CAAC;EACjCJ,QAAQ,GAAwB,UAAU;AAE5C;AAACC,OAAA,CAAAG,qBAAA,GAAAA,qBAAA;AAEM,MAAMC,qBAAqB,CAAC;EACjCL,QAAQ,GAAwB,UAAU;AAE5C;AAACC,OAAA,CAAAI,qBAAA,GAAAA,qBAAA;AAEM,MAAMC,oBAAoB,CAAC;EAChCN,QAAQ,GAAwB,SAAS;AAE3C;AAACC,OAAA,CAAAK,oBAAA,GAAAA,oBAAA;AAEM,MAAMC,kBAAkB,CAAC;EAC9BP,QAAQ,GAAwB,OAAO;AAEzC;AAACC,OAAA,CAAAM,kBAAA,GAAAA,kBAAA;AAEM,MAAMC,6BAA6B,CAAC;EACzCR,QAAQ,GAAwB,mBAAmB;AAErD;AAACC,OAAA,CAAAO,6BAAA,GAAAA,6BAAA;AAEM,MAAMC,kBAAkB,CAAC;EAC9BT,QAAQ,GAAwB,OAAO;AAEzC;AAACC,OAAA,CAAAQ,kBAAA,GAAAA,kBAAA;AAEM,MAAMC,kBAAkB,CAAC;EAC9BV,QAAQ,GAAwB,OAAO;AAEzC;AAACC,OAAA,CAAAS,kBAAA,GAAAA,kBAAA;AAEM,MAAMC,0BAA0B,CAAC;EACtCX,QAAQ,GAAwB,gBAAgB;AAElD;AAACC,OAAA,CAAAU,0BAAA,GAAAA,0BAAA;AAEM,MAAMC,iBAAiB,CAAC;EAC7BZ,QAAQ,GAAwB,MAAM;AAExC;AAACC,OAAA,CAAAW,iBAAA,GAAAA,iBAAA;AAEM,MAAMC,gBAAgB,CAAC;EAC5Bb,QAAQ,GAAwB,KAAK;AAEvC;AAACC,OAAA,CAAAY,gBAAA,GAAAA,gBAAA","ignoreList":[]}
@@ -118,6 +118,31 @@ class SpikeConnection {
118
118
  }
119
119
  async extractData(config) {
120
120
  if (!_SpikeSdk.SpikeSdk) throw new _SpikeException.SpikeException();
121
+ if (_reactNative.Platform.OS === 'android' && config.dataType.rawValue === 'ecg') {
122
+ let dateFrom;
123
+ let dateTo;
124
+ let collectedAt = new Date();
125
+ if ('from' in config) {
126
+ dateFrom = config.from;
127
+ dateTo = config.to;
128
+ } else {
129
+ dateFrom = new Date();
130
+ dateTo = new Date();
131
+ }
132
+ const result = {
133
+ dateFrom: dateFrom.toISOString(),
134
+ dateTo: dateTo.toISOString(),
135
+ collectedAt: collectedAt.toISOString(),
136
+ endUserId: await this.getSpikeEndUserId(),
137
+ sources: [{
138
+ name: 'android',
139
+ isSuccess: false,
140
+ message: 'No ECG data on android health connect'
141
+ }],
142
+ entries: []
143
+ };
144
+ return result;
145
+ }
121
146
  try {
122
147
  let json = '';
123
148
  if ('from' in config) {
@@ -133,6 +158,27 @@ class SpikeConnection {
133
158
  }
134
159
  async extractAndPostData(config) {
135
160
  if (!_SpikeSdk.SpikeSdk) throw new _SpikeException.SpikeException();
161
+ if (_reactNative.Platform.OS === 'android' && config.dataType.rawValue === 'ecg') {
162
+ let dateFrom;
163
+ let dateTo;
164
+ let collectedAt = new Date();
165
+ if ('from' in config) {
166
+ dateFrom = config.from;
167
+ dateTo = config.to;
168
+ } else {
169
+ dateFrom = new Date();
170
+ dateTo = new Date();
171
+ }
172
+ const result = {
173
+ dataType: config.dataType.rawValue,
174
+ payloadSize: 0,
175
+ callbackUrl: new URL(await this.getCallbackUrl()),
176
+ dateFrom: dateFrom,
177
+ dateTo: dateTo,
178
+ collectedAt: collectedAt
179
+ };
180
+ return result;
181
+ }
136
182
  try {
137
183
  let json = '';
138
184
  if ('from' in config) {
@@ -245,6 +291,8 @@ class SpikeConnection {
245
291
  return new _SpikeDataType.SpikeStepsDataType();
246
292
  } else if (dataType === 'body') {
247
293
  return new _SpikeDataType.SpikeBodyDataType();
294
+ } else if (dataType === 'ecg') {
295
+ return new _SpikeDataType.SpikeEcgDataType();
248
296
  }
249
297
  return new _SpikeDataType.SpikeStepsDataType();
250
298
  }