@tryvital/vital-core-react-native 5.2.3 → 5.3.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.
- package/android/build.gradle +1 -1
- package/android/src/main/java/com/vitalcorereactnative/ReactNativeAuthenticateRequest.kt +19 -0
- package/android/src/main/java/com/vitalcorereactnative/VitalCoreReactNativeModule.kt +70 -0
- package/ios/VitalCoreReactNative.m +13 -0
- package/ios/VitalCoreReactNative.swift +96 -1
- package/lib/commonjs/index.js +76 -13
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/AuthenticateRequest.js +2 -0
- package/lib/commonjs/models/AuthenticateRequest.js.map +1 -0
- package/lib/commonjs/models/BloodPressureSample.js.map +1 -1
- package/lib/commonjs/models/Provider.js.map +1 -1
- package/lib/commonjs/models/QuantitySample.js.map +1 -1
- package/lib/commonjs/models/TimeSeriesData.js.map +1 -1
- package/lib/commonjs/models/VitalCoreStatus.js.map +1 -1
- package/lib/module/index.js +75 -14
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/AuthenticateRequest.js +2 -0
- package/lib/module/models/AuthenticateRequest.js.map +1 -0
- package/lib/module/models/BloodPressureSample.js +1 -1
- package/lib/module/models/BloodPressureSample.js.map +1 -1
- package/lib/module/models/Provider.js +0 -2
- package/lib/module/models/Provider.js.map +1 -1
- package/lib/module/models/QuantitySample.js +1 -1
- package/lib/module/models/QuantitySample.js.map +1 -1
- package/lib/module/models/TimeSeriesData.js +0 -2
- package/lib/module/models/TimeSeriesData.js.map +1 -1
- package/lib/module/models/VitalCoreStatus.js +1 -1
- package/lib/module/models/VitalCoreStatus.js.map +1 -1
- package/lib/typescript/index.d.ts +42 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/models/AuthenticateRequest.d.ts +15 -0
- package/lib/typescript/models/AuthenticateRequest.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +86 -10
- package/src/models/AuthenticateRequest.ts +17 -0
- package/ios/VitalCoreReactNative.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- package/ios/VitalCoreReactNative.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- package/ios/VitalCoreReactNative.xcodeproj/project.xcworkspace/xcuserdata/anders.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/VitalCoreReactNative.xcodeproj/xcuserdata/anders.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- package/lib/commonjs/package.json +0 -1
- package/lib/module/package.json +0 -1
package/android/build.gradle
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
package com.vitalcorereactnative
|
|
2
|
+
|
|
3
|
+
import com.squareup.moshi.JsonClass
|
|
4
|
+
import com.squareup.moshi.adapters.PolymorphicJsonAdapterFactory
|
|
5
|
+
|
|
6
|
+
sealed class ReactNativeAuthenticateRequest {
|
|
7
|
+
@JsonClass(generateAdapter = true)
|
|
8
|
+
data class SignInToken(val type: String, val rawToken: String): ReactNativeAuthenticateRequest()
|
|
9
|
+
|
|
10
|
+
@JsonClass(generateAdapter = true)
|
|
11
|
+
data class APIKey(val type: String, val key: String, val userId: String, val region: String, val environment: String): ReactNativeAuthenticateRequest()
|
|
12
|
+
|
|
13
|
+
companion object {
|
|
14
|
+
val jsonAdapter = PolymorphicJsonAdapterFactory.of(ReactNativeAuthenticateRequest::class.java, "type")
|
|
15
|
+
.withSubtype(SignInToken::class.java, "signInToken")
|
|
16
|
+
.withSubtype(APIKey::class.java, "apiKey")
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
@@ -11,6 +11,7 @@ import com.facebook.react.module.annotations.ReactModule
|
|
|
11
11
|
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
12
12
|
import com.squareup.moshi.Moshi
|
|
13
13
|
import com.squareup.moshi.adapter
|
|
14
|
+
import com.squareup.moshi.adapters.EnumJsonAdapter
|
|
14
15
|
import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter
|
|
15
16
|
import io.tryvital.client.*
|
|
16
17
|
import io.tryvital.client.services.data.DataStage
|
|
@@ -25,13 +26,18 @@ import kotlinx.coroutines.MainScope
|
|
|
25
26
|
import kotlinx.coroutines.flow.collect
|
|
26
27
|
import kotlinx.coroutines.flow.onEach
|
|
27
28
|
import kotlinx.coroutines.launch
|
|
29
|
+
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
28
30
|
import java.time.ZoneId
|
|
29
31
|
import java.util.*
|
|
32
|
+
import kotlin.coroutines.Continuation
|
|
33
|
+
import kotlin.coroutines.resume
|
|
30
34
|
|
|
31
35
|
const val VITAL_CORE_ERROR = "VitalCoreError"
|
|
36
|
+
const val IDENTIFY_EXTERNAL_USER_REQUEST = "IdentifyExternalUserRequest"
|
|
32
37
|
|
|
33
38
|
internal val moshi by lazy {
|
|
34
39
|
Moshi.Builder()
|
|
40
|
+
.add(ReactNativeAuthenticateRequest.jsonAdapter)
|
|
35
41
|
.add(Date::class.java, Rfc3339DateJsonAdapter())
|
|
36
42
|
.build()
|
|
37
43
|
}
|
|
@@ -45,6 +51,8 @@ class VitalCoreReactNativeModule(reactContext: ReactApplicationContext) :
|
|
|
45
51
|
private var listenerCount = 0
|
|
46
52
|
private var statusObserver: Job? = null
|
|
47
53
|
|
|
54
|
+
private val pendingIdentifyCalls = mutableMapOf<String, Continuation<String>>()
|
|
55
|
+
|
|
48
56
|
override fun getName(): String {
|
|
49
57
|
return NAME
|
|
50
58
|
}
|
|
@@ -100,6 +108,68 @@ class VitalCoreReactNativeModule(reactContext: ReactApplicationContext) :
|
|
|
100
108
|
promise.resolve(VitalClient.currentUserId)
|
|
101
109
|
}
|
|
102
110
|
|
|
111
|
+
@ReactMethod
|
|
112
|
+
fun identifiedExternalUser(promise: Promise) {
|
|
113
|
+
// Ensure that the SDK is initialized.
|
|
114
|
+
VitalClient.getOrCreate(reactApplicationContext)
|
|
115
|
+
|
|
116
|
+
promise.resolve(VitalClient.identifiedExternalUser)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@ReactMethod
|
|
120
|
+
fun identifyExternalUser(externalUserId: String, callId: String, promise: Promise) {
|
|
121
|
+
mainScope.launch {
|
|
122
|
+
try {
|
|
123
|
+
VitalClient.identifyExternalUser(
|
|
124
|
+
reactApplicationContext,
|
|
125
|
+
externalUserId
|
|
126
|
+
) { innerExternalUserId ->
|
|
127
|
+
val jsonPayload = suspendCancellableCoroutine<String> { continuation ->
|
|
128
|
+
synchronized(this) {
|
|
129
|
+
pendingIdentifyCalls[callId] = continuation
|
|
130
|
+
}
|
|
131
|
+
eventEmitter().emit(
|
|
132
|
+
IDENTIFY_EXTERNAL_USER_REQUEST,
|
|
133
|
+
WritableNativeArray().apply {
|
|
134
|
+
pushString(callId)
|
|
135
|
+
pushString(innerExternalUserId)
|
|
136
|
+
}
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
val request = moshi.adapter(ReactNativeAuthenticateRequest::class.java).fromJson(jsonPayload)
|
|
141
|
+
?: throw RuntimeException("failed to deserialize ReactNativeAuthenticateRequest")
|
|
142
|
+
|
|
143
|
+
when (request) {
|
|
144
|
+
is ReactNativeAuthenticateRequest.SignInToken -> {
|
|
145
|
+
AuthenticateRequest.SignInToken(request.rawToken)
|
|
146
|
+
}
|
|
147
|
+
is ReactNativeAuthenticateRequest.APIKey -> {
|
|
148
|
+
AuthenticateRequest.APIKey(
|
|
149
|
+
request.key,
|
|
150
|
+
request.userId,
|
|
151
|
+
Environment.valueOf(request.environment.lowercase().replaceFirstChar { it.uppercase() }),
|
|
152
|
+
Region.valueOf(request.region.uppercase())
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
promise.resolve(null)
|
|
159
|
+
|
|
160
|
+
} catch (e: Throwable) {
|
|
161
|
+
promise.reject(VITAL_CORE_ERROR, e.message, e)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
@ReactMethod
|
|
167
|
+
fun identifyExternalUserResponse(jsonPayload: String, callId: String, promise: Promise) {
|
|
168
|
+
val continuation = synchronized(this) { pendingIdentifyCalls.remove(callId) }
|
|
169
|
+
continuation?.resume(jsonPayload)
|
|
170
|
+
promise.resolve(null)
|
|
171
|
+
}
|
|
172
|
+
|
|
103
173
|
@ReactMethod
|
|
104
174
|
fun setUserId(userId: String, promise: Promise) {
|
|
105
175
|
try {
|
|
@@ -8,6 +8,19 @@ RCT_EXTERN_METHOD(status:(RCTPromiseResolveBlock)resolve
|
|
|
8
8
|
RCT_EXTERN_METHOD(currentUserId:(RCTPromiseResolveBlock)resolve
|
|
9
9
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
10
10
|
|
|
11
|
+
RCT_EXTERN_METHOD(identifiedExternalUser:(RCTPromiseResolveBlock)resolve
|
|
12
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
13
|
+
|
|
14
|
+
RCT_EXTERN_METHOD(identifyExternalUser:(NSString *)externalUserId
|
|
15
|
+
callId:(NSString *)callId
|
|
16
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
17
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
18
|
+
|
|
19
|
+
RCT_EXTERN_METHOD(identifyExternalUserResponse:(NSString *)payload
|
|
20
|
+
callId:(NSString *)callId
|
|
21
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
22
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
23
|
+
|
|
11
24
|
RCT_EXTERN_METHOD(signIn:(NSString *)token
|
|
12
25
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
13
26
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
@@ -2,13 +2,17 @@ import VitalCore
|
|
|
2
2
|
|
|
3
3
|
private let errorKey = "VitalCoreError"
|
|
4
4
|
private let statusEventKey = "VitalClientStatus"
|
|
5
|
+
private let identifyExternalUserRequestKey = "IdentifyExternalUserRequest"
|
|
5
6
|
|
|
6
7
|
@objc(VitalCoreReactNative)
|
|
7
8
|
class VitalCoreReactNative: RCTEventEmitter {
|
|
8
9
|
private var statusObservation: Task<Void, Never>?
|
|
9
10
|
|
|
11
|
+
private let lock = NSLock()
|
|
12
|
+
private var pendingIdentifyResponses: [String: CheckedContinuation<String, Never>] = [:]
|
|
13
|
+
|
|
10
14
|
override func supportedEvents() -> [String]! {
|
|
11
|
-
[statusEventKey]
|
|
15
|
+
[statusEventKey, identifyExternalUserRequestKey]
|
|
12
16
|
}
|
|
13
17
|
|
|
14
18
|
override func startObserving() {
|
|
@@ -33,6 +37,48 @@ class VitalCoreReactNative: RCTEventEmitter {
|
|
|
33
37
|
func currentUserId(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
34
38
|
resolve(VitalClient.currentUserId)
|
|
35
39
|
}
|
|
40
|
+
@objc(identifiedExternalUser:rejecter:)
|
|
41
|
+
func identifiedExternalUser(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
42
|
+
resolve(VitalClient.identifiedExternalUser)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@objc(identifyExternalUser:callId:resolver:rejecter:)
|
|
46
|
+
func identifyExternalUser(_ externalUserId: String, callId: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
47
|
+
Task {
|
|
48
|
+
do {
|
|
49
|
+
try await VitalClient.identifyExternalUser(externalUserId) { @MainActor externalUserId in
|
|
50
|
+
// Setup a listener
|
|
51
|
+
let rawResponse: String = await withCheckedContinuation { continuation in
|
|
52
|
+
|
|
53
|
+
// Register the continuation
|
|
54
|
+
lock.withLock { self.pendingIdentifyResponses[callId] = continuation }
|
|
55
|
+
|
|
56
|
+
// Send the request to JS land, which should eventually invoke the continuation
|
|
57
|
+
// via `identifyExternalUserResponse(4)`.
|
|
58
|
+
self.sendEvent(withName: identifyExternalUserRequestKey, body: [callId, externalUserId])
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let decoder = JSONDecoder()
|
|
62
|
+
switch try decoder.decode(ReactNativeAuthenticateRequest.self, from: rawResponse.data(using: .utf8)!) {
|
|
63
|
+
case let .apiKey(userId, key, environment):
|
|
64
|
+
return .apiKey(key: key, userId: userId, environment)
|
|
65
|
+
case let .signInToken(token):
|
|
66
|
+
return .signInToken(rawToken: token)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
resolve(())
|
|
70
|
+
} catch let error {
|
|
71
|
+
reject("VitalCoreError", "\(error)", error)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@objc(identifyExternalUserResponse:callId:resolver:rejecter:)
|
|
77
|
+
func identifyExternalUserResponse(_ jsonPayload: String, _ callId: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
78
|
+
let continuation = lock.withLock { self.pendingIdentifyResponses.removeValue(forKey: callId) }
|
|
79
|
+
defer { resolve(()) }
|
|
80
|
+
continuation?.resume(returning: jsonPayload)
|
|
81
|
+
}
|
|
36
82
|
|
|
37
83
|
@objc(signIn:resolver:rejecter:)
|
|
38
84
|
func signIn(withToken token: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
@@ -260,3 +306,52 @@ extension VitalClient.Status {
|
|
|
260
306
|
return strings
|
|
261
307
|
}
|
|
262
308
|
}
|
|
309
|
+
|
|
310
|
+
enum ReactNativeAuthenticateRequest: Decodable {
|
|
311
|
+
case signInToken(String)
|
|
312
|
+
case apiKey(userId: String, key: String, environment: Environment)
|
|
313
|
+
|
|
314
|
+
enum CodingKeys: CodingKey {
|
|
315
|
+
case type
|
|
316
|
+
case rawToken
|
|
317
|
+
case userId
|
|
318
|
+
case key
|
|
319
|
+
case environment
|
|
320
|
+
case region
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
init(from decoder: any Decoder) throws {
|
|
324
|
+
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
325
|
+
|
|
326
|
+
switch try container.decode(String.self, forKey: .type) {
|
|
327
|
+
case "signInToken":
|
|
328
|
+
self = .signInToken(try container.decode(String.self, forKey: .rawToken))
|
|
329
|
+
case "apiKey":
|
|
330
|
+
|
|
331
|
+
let env: Environment
|
|
332
|
+
let rawEnv = try container.decode(String.self, forKey: .environment)
|
|
333
|
+
let rawRegion = try container.decode(String.self, forKey: .region)
|
|
334
|
+
|
|
335
|
+
switch (rawEnv, rawRegion) {
|
|
336
|
+
case ("production", "us"):
|
|
337
|
+
env = .production(.us)
|
|
338
|
+
case ("production", "eu"):
|
|
339
|
+
env = .production(.eu)
|
|
340
|
+
case ("sandbox", "us"):
|
|
341
|
+
env = .sandbox(.us)
|
|
342
|
+
case ("sandbox", "eu"):
|
|
343
|
+
env = .sandbox(.eu)
|
|
344
|
+
default:
|
|
345
|
+
throw DecodingError.dataCorruptedError(forKey: .environment, in: container, debugDescription: "unsupported: \(rawEnv) \(rawRegion)")
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
self = .apiKey(
|
|
349
|
+
userId: try container.decode(String.self, forKey: .userId),
|
|
350
|
+
key: try container.decode(String.self, forKey: .key),
|
|
351
|
+
environment: env
|
|
352
|
+
)
|
|
353
|
+
case let value:
|
|
354
|
+
throw DecodingError.dataCorruptedError(forKey: .type, in: container, debugDescription: "unrecognized: \(value)")
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -52,7 +52,7 @@ Object.keys(_TimeSeriesData).forEach(function (key) {
|
|
|
52
52
|
});
|
|
53
53
|
});
|
|
54
54
|
var _Provider = require("./models/Provider");
|
|
55
|
-
function _interopRequireDefault(
|
|
55
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
56
56
|
const LINKING_ERROR = `The package 'vital-core-react-native' doesn't seem to be linked. Make sure: \n\n` + _reactNative.Platform.select({
|
|
57
57
|
ios: "- You have run 'pod install'\n",
|
|
58
58
|
default: ''
|
|
@@ -70,29 +70,92 @@ class VitalCore {
|
|
|
70
70
|
static currentUserId() {
|
|
71
71
|
return VitalCoreReactNative.currentUserId();
|
|
72
72
|
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The currently identified External User ID of the Mobile SDK.
|
|
76
|
+
* This has meaning only if you have migrated to [identifyExternalUser].
|
|
77
|
+
*/
|
|
78
|
+
static identifiedExternalUser() {
|
|
79
|
+
return VitalCoreReactNative.identifiedExternalUser();
|
|
80
|
+
}
|
|
73
81
|
static status() {
|
|
74
82
|
return VitalCoreReactNative.status();
|
|
75
83
|
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Identify your user to the Vital Mobile SDK with an external user identifier from your system.
|
|
87
|
+
*
|
|
88
|
+
* This is _external_ with respect to the SDK. From your perspective, this would be your _internal_ user identifier.
|
|
89
|
+
*
|
|
90
|
+
* If the identified external user is not what the SDK has last seen, or has last successfully signed-in:
|
|
91
|
+
* 1. The SDK calls your supplied [authenticate] lambda.
|
|
92
|
+
* 2. Your lambda obtains a Vital Sign-In Token **from your backend service** and returns it.
|
|
93
|
+
* 3. The SDK performs the following actions:
|
|
94
|
+
*
|
|
95
|
+
* | SDK Signed-In User | The supplied Sign-In Token | Outcome |
|
|
96
|
+
* | ------ | ------ | ------ |
|
|
97
|
+
* | User A | User B | Sign out user A, then Sign in user B |
|
|
98
|
+
* | User A | User A | No-op |
|
|
99
|
+
* | None | User A | Sign In user A |
|
|
100
|
+
*
|
|
101
|
+
* Your [authenticate] lambda can throw CancellationError to abort the identify operation.
|
|
102
|
+
*
|
|
103
|
+
* You should identify at regular and significant moments in your app user lifecycle to ensure that it stays in sync with
|
|
104
|
+
* the Vital Mobile SDK user state. For example:
|
|
105
|
+
*
|
|
106
|
+
* 1. Identify your user after you signed in a new user.
|
|
107
|
+
* 2. Identify your user again after you have reloaded user state from persistent storage (e.g. [SharedPreferences]) post app launch.
|
|
108
|
+
*
|
|
109
|
+
* You can query the current identified user through [identifiedExternalUser].
|
|
110
|
+
*
|
|
111
|
+
* ## Notes on migrating from [signIn]
|
|
112
|
+
*
|
|
113
|
+
* [identifyExternalUser] does not perform any action or [VitalCore.signOut] when the Sign-In Token you supplied belongs
|
|
114
|
+
* to the already signed-in Vital User — regardless of whether the sign-in happened prior to or after the introduction of
|
|
115
|
+
* [identifyExternalUser].
|
|
116
|
+
*
|
|
117
|
+
* Because of this behaviour, you can migrate by simply replacing [signIn] with [identifyExternalUser].
|
|
118
|
+
* There is no precaution in SDK State — e.g., the Health SDK data sync state — being unintentionally reset.
|
|
119
|
+
*/
|
|
120
|
+
static async identifyExternalUser(externalUserId, authenticate) {
|
|
121
|
+
const callId = new Date().getTime().toString();
|
|
122
|
+
|
|
123
|
+
// Android/iOS sends IdentifyExternalUserRequest when the SDK detects an external user ID change,
|
|
124
|
+
// and needs new credentials to sign-in the new user.
|
|
125
|
+
const listener = this.eventEmitter.addListener("IdentifyExternalUserRequest", args => {
|
|
126
|
+
const [eventCallId, eventExternalUserId] = args;
|
|
127
|
+
if (eventCallId !== callId) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
authenticate(eventExternalUserId).then(request => {
|
|
131
|
+
VitalCoreReactNative.identifyExternalUserResponse(JSON.stringify(request), callId);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
try {
|
|
135
|
+
await VitalCoreReactNative.identifyExternalUser(externalUserId, callId);
|
|
136
|
+
} finally {
|
|
137
|
+
listener.remove();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
76
140
|
static signIn(token) {
|
|
77
141
|
return VitalCoreReactNative.signIn(token);
|
|
78
142
|
}
|
|
79
143
|
static observeStatusChange(listener) {
|
|
80
144
|
var isCancelled = false;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
145
|
+
const wrappedListener = status => {
|
|
146
|
+
if (isCancelled) {
|
|
147
|
+
return;
|
|
84
148
|
}
|
|
149
|
+
listener(status);
|
|
85
150
|
};
|
|
86
|
-
this.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
};
|
|
151
|
+
const subscription = this.eventEmitter.addListener("VitalClientStatus", wrappedListener);
|
|
152
|
+
this.status().then(wrappedListener);
|
|
153
|
+
return {
|
|
154
|
+
remove() {
|
|
155
|
+
isCancelled = true;
|
|
156
|
+
subscription.remove();
|
|
93
157
|
}
|
|
94
|
-
}
|
|
95
|
-
return subscription;
|
|
158
|
+
};
|
|
96
159
|
}
|
|
97
160
|
static setUserId(userId) {
|
|
98
161
|
return VitalCoreReactNative.setUserId(userId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","_VitalCoreStatus","_QuantitySample","_interopRequireDefault","_BloodPressureSample","_TimeSeriesData","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_Provider","
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_VitalCoreStatus","_QuantitySample","_interopRequireDefault","_BloodPressureSample","_TimeSeriesData","Object","keys","forEach","key","prototype","hasOwnProperty","call","_exportNames","exports","defineProperty","enumerable","get","_Provider","obj","__esModule","default","LINKING_ERROR","Platform","select","ios","VitalCoreReactNative","NativeModules","Proxy","Error","VitalCore","eventEmitter","NativeEventEmitter","setEventEmitter","emitter","currentUserId","identifiedExternalUser","status","identifyExternalUser","externalUserId","authenticate","callId","Date","getTime","toString","listener","addListener","args","eventCallId","eventExternalUserId","then","request","identifyExternalUserResponse","JSON","stringify","remove","signIn","token","observeStatusChange","isCancelled","wrappedListener","subscription","setUserId","userId","configure","apiKey","environment","region","enableLogs","hasUserConnectedTo","provider","userConnections","deregisterProvider","getAccessToken","refreshToken","getVitalAPIHeaders","accessToken","sdkVersion","Promise","all","versionKey","OS","headers","signOut"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/AuthenticateRequest.ts"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/BloodPressureSample.ts"],"mappings":""
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/BloodPressureSample.ts"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ManualProviderSlug","exports","ProviderSlug"],"sourceRoot":"../../../src","sources":["models/Provider.ts"],"mappings":";;;;;;IAAYA,kBAAkB,GAAAC,OAAA,CAAAD,kBAAA,0BAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAA,OAAlBA,kBAAkB;AAAA;AAAA,IAWlBE,YAAY,GAAAD,OAAA,CAAAC,YAAA,0BAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAA,OAAZA,YAAY;AAAA"
|
|
1
|
+
{"version":3,"names":["ManualProviderSlug","exports","ProviderSlug"],"sourceRoot":"../../../src","sources":["models/Provider.ts"],"mappings":";;;;;;IAAYA,kBAAkB,GAAAC,OAAA,CAAAD,kBAAA,0BAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAA,OAAlBA,kBAAkB;AAAA;AAAA,IAWlBE,YAAY,GAAAD,OAAA,CAAAC,YAAA,0BAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAA,OAAZA,YAAY;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/QuantitySample.ts"],"mappings":""
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/QuantitySample.ts"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/TimeSeriesData.ts"],"mappings":""
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/TimeSeriesData.ts"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/VitalCoreStatus.ts"],"mappings":""
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/VitalCoreStatus.ts"],"mappings":""}
|
package/lib/module/index.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
1
|
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
|
|
4
2
|
export { VitalCoreStatus } from './models/VitalCoreStatus';
|
|
5
3
|
export { default as QuantitySample } from './models/QuantitySample';
|
|
@@ -23,29 +21,92 @@ export class VitalCore {
|
|
|
23
21
|
static currentUserId() {
|
|
24
22
|
return VitalCoreReactNative.currentUserId();
|
|
25
23
|
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The currently identified External User ID of the Mobile SDK.
|
|
27
|
+
* This has meaning only if you have migrated to [identifyExternalUser].
|
|
28
|
+
*/
|
|
29
|
+
static identifiedExternalUser() {
|
|
30
|
+
return VitalCoreReactNative.identifiedExternalUser();
|
|
31
|
+
}
|
|
26
32
|
static status() {
|
|
27
33
|
return VitalCoreReactNative.status();
|
|
28
34
|
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Identify your user to the Vital Mobile SDK with an external user identifier from your system.
|
|
38
|
+
*
|
|
39
|
+
* This is _external_ with respect to the SDK. From your perspective, this would be your _internal_ user identifier.
|
|
40
|
+
*
|
|
41
|
+
* If the identified external user is not what the SDK has last seen, or has last successfully signed-in:
|
|
42
|
+
* 1. The SDK calls your supplied [authenticate] lambda.
|
|
43
|
+
* 2. Your lambda obtains a Vital Sign-In Token **from your backend service** and returns it.
|
|
44
|
+
* 3. The SDK performs the following actions:
|
|
45
|
+
*
|
|
46
|
+
* | SDK Signed-In User | The supplied Sign-In Token | Outcome |
|
|
47
|
+
* | ------ | ------ | ------ |
|
|
48
|
+
* | User A | User B | Sign out user A, then Sign in user B |
|
|
49
|
+
* | User A | User A | No-op |
|
|
50
|
+
* | None | User A | Sign In user A |
|
|
51
|
+
*
|
|
52
|
+
* Your [authenticate] lambda can throw CancellationError to abort the identify operation.
|
|
53
|
+
*
|
|
54
|
+
* You should identify at regular and significant moments in your app user lifecycle to ensure that it stays in sync with
|
|
55
|
+
* the Vital Mobile SDK user state. For example:
|
|
56
|
+
*
|
|
57
|
+
* 1. Identify your user after you signed in a new user.
|
|
58
|
+
* 2. Identify your user again after you have reloaded user state from persistent storage (e.g. [SharedPreferences]) post app launch.
|
|
59
|
+
*
|
|
60
|
+
* You can query the current identified user through [identifiedExternalUser].
|
|
61
|
+
*
|
|
62
|
+
* ## Notes on migrating from [signIn]
|
|
63
|
+
*
|
|
64
|
+
* [identifyExternalUser] does not perform any action or [VitalCore.signOut] when the Sign-In Token you supplied belongs
|
|
65
|
+
* to the already signed-in Vital User — regardless of whether the sign-in happened prior to or after the introduction of
|
|
66
|
+
* [identifyExternalUser].
|
|
67
|
+
*
|
|
68
|
+
* Because of this behaviour, you can migrate by simply replacing [signIn] with [identifyExternalUser].
|
|
69
|
+
* There is no precaution in SDK State — e.g., the Health SDK data sync state — being unintentionally reset.
|
|
70
|
+
*/
|
|
71
|
+
static async identifyExternalUser(externalUserId, authenticate) {
|
|
72
|
+
const callId = new Date().getTime().toString();
|
|
73
|
+
|
|
74
|
+
// Android/iOS sends IdentifyExternalUserRequest when the SDK detects an external user ID change,
|
|
75
|
+
// and needs new credentials to sign-in the new user.
|
|
76
|
+
const listener = this.eventEmitter.addListener("IdentifyExternalUserRequest", args => {
|
|
77
|
+
const [eventCallId, eventExternalUserId] = args;
|
|
78
|
+
if (eventCallId !== callId) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
authenticate(eventExternalUserId).then(request => {
|
|
82
|
+
VitalCoreReactNative.identifyExternalUserResponse(JSON.stringify(request), callId);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
try {
|
|
86
|
+
await VitalCoreReactNative.identifyExternalUser(externalUserId, callId);
|
|
87
|
+
} finally {
|
|
88
|
+
listener.remove();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
29
91
|
static signIn(token) {
|
|
30
92
|
return VitalCoreReactNative.signIn(token);
|
|
31
93
|
}
|
|
32
94
|
static observeStatusChange(listener) {
|
|
33
95
|
var isCancelled = false;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
96
|
+
const wrappedListener = status => {
|
|
97
|
+
if (isCancelled) {
|
|
98
|
+
return;
|
|
37
99
|
}
|
|
100
|
+
listener(status);
|
|
38
101
|
};
|
|
39
|
-
this.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
};
|
|
102
|
+
const subscription = this.eventEmitter.addListener("VitalClientStatus", wrappedListener);
|
|
103
|
+
this.status().then(wrappedListener);
|
|
104
|
+
return {
|
|
105
|
+
remove() {
|
|
106
|
+
isCancelled = true;
|
|
107
|
+
subscription.remove();
|
|
46
108
|
}
|
|
47
|
-
}
|
|
48
|
-
return subscription;
|
|
109
|
+
};
|
|
49
110
|
}
|
|
50
111
|
static setUserId(userId) {
|
|
51
112
|
return VitalCoreReactNative.setUserId(userId);
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeEventEmitter","NativeModules","Platform","VitalCoreStatus","default","QuantitySample","BloodPressureSample","ManualProviderSlug","LINKING_ERROR","select","ios","VitalCoreReactNative","Proxy","get","Error","VitalCore","eventEmitter","setEventEmitter","emitter","currentUserId","status","
|
|
1
|
+
{"version":3,"names":["NativeEventEmitter","NativeModules","Platform","VitalCoreStatus","default","QuantitySample","BloodPressureSample","ManualProviderSlug","LINKING_ERROR","select","ios","VitalCoreReactNative","Proxy","get","Error","VitalCore","eventEmitter","setEventEmitter","emitter","currentUserId","identifiedExternalUser","status","identifyExternalUser","externalUserId","authenticate","callId","Date","getTime","toString","listener","addListener","args","eventCallId","eventExternalUserId","then","request","identifyExternalUserResponse","JSON","stringify","remove","signIn","token","observeStatusChange","isCancelled","wrappedListener","subscription","setUserId","userId","configure","apiKey","environment","region","enableLogs","hasUserConnectedTo","provider","userConnections","deregisterProvider","getAccessToken","refreshToken","getVitalAPIHeaders","accessToken","sdkVersion","Promise","all","versionKey","OS","headers","signOut"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/AuthenticateRequest.ts"],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
//# sourceMappingURL=BloodPressureSample.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/BloodPressureSample.ts"],"mappings":""
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/BloodPressureSample.ts"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ManualProviderSlug","ProviderSlug"],"sourceRoot":"../../../src","sources":["models/Provider.ts"],"mappings":"
|
|
1
|
+
{"version":3,"names":["ManualProviderSlug","ProviderSlug"],"sourceRoot":"../../../src","sources":["models/Provider.ts"],"mappings":"AAAA,WAAYA,kBAAkB,0BAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAlBA,kBAAkB;EAAA,OAAlBA,kBAAkB;AAAA;AAW9B,WAAYC,YAAY,0BAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAZA,YAAY;EAAA,OAAZA,YAAY;AAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
//# sourceMappingURL=QuantitySample.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/QuantitySample.ts"],"mappings":""
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/QuantitySample.ts"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/TimeSeriesData.ts"],"mappings":""
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/TimeSeriesData.ts"],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
//# sourceMappingURL=VitalCoreStatus.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/VitalCoreStatus.ts"],"mappings":""
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["models/VitalCoreStatus.ts"],"mappings":""}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NativeEventEmitter } from 'react-native';
|
|
2
2
|
import type { ManualProviderSlug, ProviderSlug, UserConnection } from './models/Provider';
|
|
3
3
|
import type { VitalCoreStatus } from './models/VitalCoreStatus';
|
|
4
|
+
import type { AuthenticateRequest } from './models/AuthenticateRequest';
|
|
4
5
|
export { VitalCoreStatus } from './models/VitalCoreStatus';
|
|
5
6
|
export { default as QuantitySample } from './models/QuantitySample';
|
|
6
7
|
export { default as BloodPressureSample } from './models/BloodPressureSample';
|
|
@@ -13,7 +14,48 @@ export declare class VitalCore {
|
|
|
13
14
|
private static eventEmitter;
|
|
14
15
|
static setEventEmitter(emitter: NativeEventEmitter): void;
|
|
15
16
|
static currentUserId(): Promise<string | null>;
|
|
17
|
+
/**
|
|
18
|
+
* The currently identified External User ID of the Mobile SDK.
|
|
19
|
+
* This has meaning only if you have migrated to [identifyExternalUser].
|
|
20
|
+
*/
|
|
21
|
+
static identifiedExternalUser(): Promise<string | null>;
|
|
16
22
|
static status(): Promise<VitalCoreStatus[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Identify your user to the Vital Mobile SDK with an external user identifier from your system.
|
|
25
|
+
*
|
|
26
|
+
* This is _external_ with respect to the SDK. From your perspective, this would be your _internal_ user identifier.
|
|
27
|
+
*
|
|
28
|
+
* If the identified external user is not what the SDK has last seen, or has last successfully signed-in:
|
|
29
|
+
* 1. The SDK calls your supplied [authenticate] lambda.
|
|
30
|
+
* 2. Your lambda obtains a Vital Sign-In Token **from your backend service** and returns it.
|
|
31
|
+
* 3. The SDK performs the following actions:
|
|
32
|
+
*
|
|
33
|
+
* | SDK Signed-In User | The supplied Sign-In Token | Outcome |
|
|
34
|
+
* | ------ | ------ | ------ |
|
|
35
|
+
* | User A | User B | Sign out user A, then Sign in user B |
|
|
36
|
+
* | User A | User A | No-op |
|
|
37
|
+
* | None | User A | Sign In user A |
|
|
38
|
+
*
|
|
39
|
+
* Your [authenticate] lambda can throw CancellationError to abort the identify operation.
|
|
40
|
+
*
|
|
41
|
+
* You should identify at regular and significant moments in your app user lifecycle to ensure that it stays in sync with
|
|
42
|
+
* the Vital Mobile SDK user state. For example:
|
|
43
|
+
*
|
|
44
|
+
* 1. Identify your user after you signed in a new user.
|
|
45
|
+
* 2. Identify your user again after you have reloaded user state from persistent storage (e.g. [SharedPreferences]) post app launch.
|
|
46
|
+
*
|
|
47
|
+
* You can query the current identified user through [identifiedExternalUser].
|
|
48
|
+
*
|
|
49
|
+
* ## Notes on migrating from [signIn]
|
|
50
|
+
*
|
|
51
|
+
* [identifyExternalUser] does not perform any action or [VitalCore.signOut] when the Sign-In Token you supplied belongs
|
|
52
|
+
* to the already signed-in Vital User — regardless of whether the sign-in happened prior to or after the introduction of
|
|
53
|
+
* [identifyExternalUser].
|
|
54
|
+
*
|
|
55
|
+
* Because of this behaviour, you can migrate by simply replacing [signIn] with [identifyExternalUser].
|
|
56
|
+
* There is no precaution in SDK State — e.g., the Health SDK data sync state — being unintentionally reset.
|
|
57
|
+
*/
|
|
58
|
+
static identifyExternalUser(externalUserId: string, authenticate: (externalUserId: string) => Promise<AuthenticateRequest>): Promise<void>;
|
|
17
59
|
static signIn(token: string): Promise<void>;
|
|
18
60
|
static observeStatusChange(listener: (status: VitalCoreStatus[]) => void): Subscription;
|
|
19
61
|
static setUserId(userId: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA2B,MAAM,cAAc,CAAC;AAC3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC1F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA2B,MAAM,cAAc,CAAC;AAC3E,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC1F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAExE,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAmBvD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,YAAY,CAA8D;IAEzF,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,kBAAkB;IAIlD,MAAM,CAAC,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI9C;;;OAGG;IACH,MAAM,CAAC,sBAAsB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIvD,MAAM,CAAC,MAAM,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAI3C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;WACU,oBAAoB,CAAC,cAAc,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IA4BhJ,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,IAAI,GAAG,YAAY;IAoBvF,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI/C,MAAM,CAAC,SAAS,CACd,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,OAAO,GAClB,OAAO,CAAC,IAAI,CAAC;IAShB,MAAM,CAAC,kBAAkB,CACvB,QAAQ,EAAE,kBAAkB,GAC3B,OAAO,CAAC,OAAO,CAAC;IAInB,MAAM,CAAC,eAAe,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAInD,MAAM,CAAC,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,MAAM,CAAC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAIxC,MAAM,CAAC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;WAIvB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAiBlE,MAAM,CAAC,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAIpC,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAGhC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type Environment = "dev" | "sandbox" | "production";
|
|
2
|
+
export type Region = "us" | "eu";
|
|
3
|
+
export interface AuthenticateRequestSignInToken {
|
|
4
|
+
type: "signInToken";
|
|
5
|
+
rawToken: string;
|
|
6
|
+
}
|
|
7
|
+
export interface AuthenticateRequestAPIKey {
|
|
8
|
+
type: "apiKey";
|
|
9
|
+
key: string;
|
|
10
|
+
environment: Environment;
|
|
11
|
+
region: Region;
|
|
12
|
+
userId: string;
|
|
13
|
+
}
|
|
14
|
+
export type AuthenticateRequest = AuthenticateRequestSignInToken | AuthenticateRequestAPIKey;
|
|
15
|
+
//# sourceMappingURL=AuthenticateRequest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuthenticateRequest.d.ts","sourceRoot":"","sources":["../../../src/models/AuthenticateRequest.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GAAG,KAAK,GAAG,SAAS,GAAG,YAAY,CAAC;AAC3D,MAAM,MAAM,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;AAEjC,MAAM,WAAW,8BAA8B;IAC3C,IAAI,EAAE,aAAa,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,yBAAyB;IACtC,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,EAAE,WAAW,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,mBAAmB,GAAG,8BAA8B,GAAG,yBAAyB,CAAC"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
|
|
2
2
|
import type { ManualProviderSlug, ProviderSlug, UserConnection } from './models/Provider';
|
|
3
3
|
import type { VitalCoreStatus } from './models/VitalCoreStatus';
|
|
4
|
+
import type { AuthenticateRequest } from './models/AuthenticateRequest';
|
|
4
5
|
|
|
5
6
|
export { VitalCoreStatus } from './models/VitalCoreStatus';
|
|
6
7
|
export { default as QuantitySample } from './models/QuantitySample';
|
|
@@ -40,28 +41,103 @@ export class VitalCore {
|
|
|
40
41
|
return VitalCoreReactNative.currentUserId();
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
/**
|
|
45
|
+
* The currently identified External User ID of the Mobile SDK.
|
|
46
|
+
* This has meaning only if you have migrated to [identifyExternalUser].
|
|
47
|
+
*/
|
|
48
|
+
static identifiedExternalUser(): Promise<string | null> {
|
|
49
|
+
return VitalCoreReactNative.identifiedExternalUser();
|
|
50
|
+
}
|
|
51
|
+
|
|
43
52
|
static status(): Promise<VitalCoreStatus[]> {
|
|
44
53
|
return VitalCoreReactNative.status();
|
|
45
54
|
}
|
|
46
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Identify your user to the Vital Mobile SDK with an external user identifier from your system.
|
|
58
|
+
*
|
|
59
|
+
* This is _external_ with respect to the SDK. From your perspective, this would be your _internal_ user identifier.
|
|
60
|
+
*
|
|
61
|
+
* If the identified external user is not what the SDK has last seen, or has last successfully signed-in:
|
|
62
|
+
* 1. The SDK calls your supplied [authenticate] lambda.
|
|
63
|
+
* 2. Your lambda obtains a Vital Sign-In Token **from your backend service** and returns it.
|
|
64
|
+
* 3. The SDK performs the following actions:
|
|
65
|
+
*
|
|
66
|
+
* | SDK Signed-In User | The supplied Sign-In Token | Outcome |
|
|
67
|
+
* | ------ | ------ | ------ |
|
|
68
|
+
* | User A | User B | Sign out user A, then Sign in user B |
|
|
69
|
+
* | User A | User A | No-op |
|
|
70
|
+
* | None | User A | Sign In user A |
|
|
71
|
+
*
|
|
72
|
+
* Your [authenticate] lambda can throw CancellationError to abort the identify operation.
|
|
73
|
+
*
|
|
74
|
+
* You should identify at regular and significant moments in your app user lifecycle to ensure that it stays in sync with
|
|
75
|
+
* the Vital Mobile SDK user state. For example:
|
|
76
|
+
*
|
|
77
|
+
* 1. Identify your user after you signed in a new user.
|
|
78
|
+
* 2. Identify your user again after you have reloaded user state from persistent storage (e.g. [SharedPreferences]) post app launch.
|
|
79
|
+
*
|
|
80
|
+
* You can query the current identified user through [identifiedExternalUser].
|
|
81
|
+
*
|
|
82
|
+
* ## Notes on migrating from [signIn]
|
|
83
|
+
*
|
|
84
|
+
* [identifyExternalUser] does not perform any action or [VitalCore.signOut] when the Sign-In Token you supplied belongs
|
|
85
|
+
* to the already signed-in Vital User — regardless of whether the sign-in happened prior to or after the introduction of
|
|
86
|
+
* [identifyExternalUser].
|
|
87
|
+
*
|
|
88
|
+
* Because of this behaviour, you can migrate by simply replacing [signIn] with [identifyExternalUser].
|
|
89
|
+
* There is no precaution in SDK State — e.g., the Health SDK data sync state — being unintentionally reset.
|
|
90
|
+
*/
|
|
91
|
+
static async identifyExternalUser(externalUserId: string, authenticate: (externalUserId: string) => Promise<AuthenticateRequest>): Promise<void> {
|
|
92
|
+
const callId = (new Date().getTime()).toString();
|
|
93
|
+
|
|
94
|
+
// Android/iOS sends IdentifyExternalUserRequest when the SDK detects an external user ID change,
|
|
95
|
+
// and needs new credentials to sign-in the new user.
|
|
96
|
+
const listener = this.eventEmitter.addListener(
|
|
97
|
+
"IdentifyExternalUserRequest",
|
|
98
|
+
(args) => {
|
|
99
|
+
const [eventCallId, eventExternalUserId] = args;
|
|
100
|
+
|
|
101
|
+
if (eventCallId !== callId) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
authenticate(eventExternalUserId).then((request) => {
|
|
106
|
+
VitalCoreReactNative.identifyExternalUserResponse(JSON.stringify(request), callId);
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
await VitalCoreReactNative.identifyExternalUser(externalUserId, callId);
|
|
113
|
+
|
|
114
|
+
} finally {
|
|
115
|
+
listener.remove()
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
47
119
|
static signIn(token: string): Promise<void> {
|
|
48
120
|
return VitalCoreReactNative.signIn(token);
|
|
49
121
|
}
|
|
50
122
|
|
|
51
123
|
static observeStatusChange(listener: (status: VitalCoreStatus[]) => void): Subscription {
|
|
52
124
|
var isCancelled = false
|
|
53
|
-
var subscription = { remove: () => { isCancelled = true } };
|
|
54
125
|
|
|
55
|
-
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
let emitterSub = this.eventEmitter.addListener("VitalClientStatus", listener)
|
|
60
|
-
subscription.remove = () => { emitterSub.remove() }
|
|
126
|
+
const wrappedListener = (status: VitalCoreStatus[]) => {
|
|
127
|
+
if (isCancelled) {
|
|
128
|
+
return;
|
|
61
129
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
130
|
+
listener(status);
|
|
131
|
+
}
|
|
132
|
+
const subscription = this.eventEmitter.addListener("VitalClientStatus", wrappedListener);
|
|
133
|
+
this.status().then(wrappedListener);
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
remove() {
|
|
137
|
+
isCancelled = true;
|
|
138
|
+
subscription.remove();
|
|
139
|
+
},
|
|
140
|
+
};
|
|
65
141
|
}
|
|
66
142
|
|
|
67
143
|
static setUserId(userId: string): Promise<void> {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type Environment = "dev" | "sandbox" | "production";
|
|
2
|
+
export type Region = "us" | "eu";
|
|
3
|
+
|
|
4
|
+
export interface AuthenticateRequestSignInToken {
|
|
5
|
+
type: "signInToken";
|
|
6
|
+
rawToken: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface AuthenticateRequestAPIKey {
|
|
10
|
+
type: "apiKey";
|
|
11
|
+
key: string;
|
|
12
|
+
environment: Environment;
|
|
13
|
+
region: Region;
|
|
14
|
+
userId: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type AuthenticateRequest = AuthenticateRequestSignInToken | AuthenticateRequestAPIKey;
|
|
Binary file
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
-
<plist version="1.0">
|
|
4
|
-
<dict>
|
|
5
|
-
<key>SchemeUserState</key>
|
|
6
|
-
<dict>
|
|
7
|
-
<key>VitalCoreReactNative.xcscheme_^#shared#^_</key>
|
|
8
|
-
<dict>
|
|
9
|
-
<key>orderHint</key>
|
|
10
|
-
<integer>0</integer>
|
|
11
|
-
</dict>
|
|
12
|
-
</dict>
|
|
13
|
-
</dict>
|
|
14
|
-
</plist>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"type":"commonjs"}
|
package/lib/module/package.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"type":"module"}
|