react-native-usesense 1.0.0 → 2.1.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/README.md +267 -373
- package/android/build.gradle +7 -2
- package/android/src/main/java/com/usesense/reactnative/UseSenseFlowsModule.kt +72 -0
- package/android/src/main/java/com/usesense/reactnative/UseSenseModule.kt +82 -1
- package/android/src/main/java/com/usesense/reactnative/UseSensePackage.kt +6 -1
- package/ios/UseSenseFlowsModule.m +20 -0
- package/ios/UseSenseFlowsModule.swift +111 -0
- package/ios/UseSenseModule.m +5 -0
- package/ios/UseSenseModule.swift +277 -88
- package/ios/V4BridgeDelegate.swift +62 -0
- package/lib/commonjs/flows.js +105 -0
- package/lib/commonjs/flows.js.map +1 -0
- package/lib/commonjs/index.js +171 -98
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/flows.js +99 -0
- package/lib/module/flows.js.map +1 -0
- package/lib/module/index.js +160 -97
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/flows.d.ts +72 -0
- package/lib/typescript/src/flows.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +210 -138
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +3 -1
- package/react-native-usesense.podspec +9 -3
- package/src/flows.ts +159 -0
- package/src/index.ts +313 -159
package/lib/commonjs/index.js
CHANGED
|
@@ -3,177 +3,250 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
|
|
6
|
+
Object.defineProperty(exports, "FlowError", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _flows.FlowError;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
exports.UseSense = void 0;
|
|
13
|
+
Object.defineProperty(exports, "UseSenseFlows", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function () {
|
|
16
|
+
return _flows.UseSenseFlows;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
exports.default = void 0;
|
|
7
20
|
var _reactNative = require("react-native");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
21
|
+
var _flows = require("./flows");
|
|
22
|
+
const LINKING_ERROR = `react-native-usesense: the native module could not be found.\n\n` + _reactNative.Platform.select({
|
|
23
|
+
ios: `iOS: run \`cd ios && pod install\` and rebuild the app.`,
|
|
24
|
+
android: `Android: rebuild the app after installing the package.`,
|
|
25
|
+
default: ''
|
|
26
|
+
}) + `\n\nIf you're using Expo, the plugin must be consumed through a development build; it does not support Expo Go because it wraps a native camera SDK.`;
|
|
27
|
+
const UseSenseModule = _reactNative.NativeModules.UseSenseModule;
|
|
11
28
|
if (!UseSenseModule) {
|
|
12
|
-
throw new Error(
|
|
29
|
+
throw new Error(LINKING_ERROR);
|
|
13
30
|
}
|
|
14
31
|
|
|
15
|
-
// ─── Types
|
|
32
|
+
// ─── Types ───────────────────────────────────────────────────────────────
|
|
16
33
|
|
|
17
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* Target environment for the UseSense API. `auto` asks the native SDK
|
|
36
|
+
* to detect from the API key prefix (`sk_sandbox_*` → sandbox,
|
|
37
|
+
* `sk_prod_*` → production).
|
|
38
|
+
*/
|
|
18
39
|
|
|
19
|
-
/**
|
|
40
|
+
/** Type of verification session. */
|
|
20
41
|
|
|
21
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* Decision returned by the native SDK.
|
|
44
|
+
*
|
|
45
|
+
* These values come straight from the server's verdict and are
|
|
46
|
+
* exposed to the integrator for UI feedback only. The definitive
|
|
47
|
+
* verdict arrives at your backend via an HMAC-signed webhook; never
|
|
48
|
+
* trust the client-side decision for access-control.
|
|
49
|
+
*/
|
|
22
50
|
|
|
23
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* Branding overrides applied to the native camera UI.
|
|
53
|
+
*
|
|
54
|
+
* - `logoUrl`, `primaryColor`, `buttonRadius`, `fontFamily` are
|
|
55
|
+
* honoured on both iOS and Android.
|
|
56
|
+
* - `displayName`, `redirectUrl` are Android-only fields. They're
|
|
57
|
+
* accepted on iOS for cross-platform API parity but ignored.
|
|
58
|
+
*/
|
|
24
59
|
|
|
25
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* Configuration for `UseSense.initialize`. The minimum required
|
|
62
|
+
* field is the API key; every other field has a sensible default.
|
|
63
|
+
*/
|
|
26
64
|
|
|
27
65
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* @example
|
|
31
|
-
* ```ts
|
|
32
|
-
* await UseSense.initialize({
|
|
33
|
-
* apiKey: 'your_api_key',
|
|
34
|
-
* environment: 'sandbox',
|
|
35
|
-
* });
|
|
36
|
-
* ```
|
|
66
|
+
* Request to start a verification session.
|
|
37
67
|
*/
|
|
38
68
|
|
|
39
69
|
/**
|
|
40
|
-
*
|
|
70
|
+
* Redacted decision object returned when a session completes.
|
|
41
71
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
72
|
+
* This is the ONLY shape the plugin exposes to React Native. Pillar
|
|
73
|
+
* scores (channel trust, liveness, matchsense risk) are intentionally
|
|
74
|
+
* not included — the native SDKs strip those fields before returning
|
|
75
|
+
* across the bridge to prevent reverse-engineering of the server-side
|
|
76
|
+
* scoring logic. If you need full scoring details, consume the signed
|
|
77
|
+
* webhook delivered to your backend.
|
|
44
78
|
*/
|
|
45
79
|
|
|
46
80
|
/**
|
|
47
|
-
* Error
|
|
81
|
+
* Error thrown when a verification session fails.
|
|
82
|
+
*
|
|
83
|
+
* Matches the native SDKs' error shape: machine-readable code,
|
|
84
|
+
* human-readable message, retry hint.
|
|
48
85
|
*/
|
|
49
86
|
|
|
50
87
|
/**
|
|
51
|
-
*
|
|
88
|
+
* Lifecycle event types emitted by the native SDK during a
|
|
89
|
+
* verification session.
|
|
52
90
|
*/
|
|
53
91
|
|
|
54
|
-
/**
|
|
92
|
+
/** Single event emitted during a session. */
|
|
55
93
|
|
|
56
|
-
/**
|
|
94
|
+
/** Handle returned by `UseSense.addListener`. */
|
|
57
95
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// ─── Implementation ──────────────────────────────────────────────────
|
|
96
|
+
// ─── Implementation ──────────────────────────────────────────────────────
|
|
61
97
|
|
|
62
98
|
const eventEmitter = new _reactNative.NativeEventEmitter(UseSenseModule);
|
|
63
99
|
|
|
64
100
|
/**
|
|
65
101
|
* UseSense React Native plugin.
|
|
66
102
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
103
|
+
* Human presence verification wrapping the native iOS and Android
|
|
104
|
+
* UseSense SDKs. Every session runs inside a full-screen native
|
|
105
|
+
* camera activity; the plugin is a thin bridge that forwards
|
|
106
|
+
* initialization, verification requests, and lifecycle events to
|
|
107
|
+
* the platform SDK and returns a redacted decision object.
|
|
69
108
|
*
|
|
70
109
|
* @example
|
|
71
110
|
* ```ts
|
|
72
111
|
* import { UseSense } from 'react-native-usesense';
|
|
73
112
|
*
|
|
74
|
-
* await UseSense.initialize({
|
|
75
|
-
*
|
|
76
|
-
*
|
|
113
|
+
* await UseSense.initialize({
|
|
114
|
+
* apiKey: 'sk_sandbox_...',
|
|
115
|
+
* environment: 'sandbox',
|
|
116
|
+
* });
|
|
117
|
+
*
|
|
118
|
+
* const unsubscribe = UseSense.addListener((event) => {
|
|
119
|
+
* console.log(event.type, event.data);
|
|
120
|
+
* });
|
|
121
|
+
*
|
|
122
|
+
* try {
|
|
123
|
+
* const result = await UseSense.startVerification({
|
|
124
|
+
* sessionType: 'enrollment',
|
|
125
|
+
* });
|
|
126
|
+
* console.log(result.decision); // 'APPROVE' | 'REJECT' | 'MANUAL_REVIEW'
|
|
127
|
+
* } finally {
|
|
128
|
+
* unsubscribe.remove();
|
|
129
|
+
* }
|
|
77
130
|
* ```
|
|
78
131
|
*/
|
|
79
132
|
class UseSense {
|
|
80
133
|
/**
|
|
81
|
-
* Initialize the UseSense plugin. Must be called
|
|
134
|
+
* Initialize the UseSense plugin. Must be called before any other
|
|
135
|
+
* method. Calling again with a different API key or environment
|
|
136
|
+
* replaces the previous configuration.
|
|
82
137
|
*
|
|
83
|
-
* @
|
|
84
|
-
*
|
|
138
|
+
* @throws {UseSenseError} If the API key is empty or initialization
|
|
139
|
+
* fails on the native side.
|
|
85
140
|
*/
|
|
86
141
|
static async initialize(config) {
|
|
87
142
|
if (!config.apiKey) {
|
|
88
|
-
|
|
143
|
+
const err = {
|
|
89
144
|
code: 'invalid_config',
|
|
90
|
-
message: 'apiKey is required'
|
|
145
|
+
message: 'apiKey is required',
|
|
146
|
+
isRetryable: false
|
|
91
147
|
};
|
|
148
|
+
throw err;
|
|
92
149
|
}
|
|
93
150
|
return UseSenseModule.initialize({
|
|
94
151
|
apiKey: config.apiKey,
|
|
95
|
-
environment: config.environment ?? '
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
enableAudio: config.enableAudio ?? false,
|
|
101
|
-
timeout: config.timeout ?? 60000,
|
|
102
|
-
metadata: config.metadata
|
|
152
|
+
environment: config.environment ?? 'auto',
|
|
153
|
+
apiEndpoint: config.apiEndpoint,
|
|
154
|
+
branding: config.branding,
|
|
155
|
+
antispoofOnDeviceEnabled: config.antispoofOnDeviceEnabled ?? false,
|
|
156
|
+
liveSenseV4Enabled: config.liveSenseV4Enabled ?? false
|
|
103
157
|
});
|
|
104
158
|
}
|
|
105
159
|
|
|
106
160
|
/**
|
|
107
|
-
* Start a verification session. Presents a full-screen native
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* @param options - Optional overrides for session type and identity ID.
|
|
113
|
-
* @returns The verification result (for UI feedback only).
|
|
114
|
-
* @throws {UseSenseError} On failure or cancellation.
|
|
161
|
+
* Start a verification session. Presents a full-screen native
|
|
162
|
+
* camera activity. The returned promise resolves when the session
|
|
163
|
+
* completes or rejects with a `UseSenseError` (including the
|
|
164
|
+
* `USER_CANCELLED` / `session_cancelled` cases when the user
|
|
165
|
+
* dismisses the camera screen).
|
|
115
166
|
*/
|
|
116
|
-
static async
|
|
117
|
-
return UseSenseModule.
|
|
167
|
+
static async startVerification(request) {
|
|
168
|
+
return UseSenseModule.startVerification({
|
|
169
|
+
sessionType: request.sessionType,
|
|
170
|
+
externalUserId: request.externalUserId,
|
|
171
|
+
identityId: request.identityId,
|
|
172
|
+
metadata: request.metadata
|
|
173
|
+
});
|
|
118
174
|
}
|
|
119
175
|
|
|
120
176
|
/**
|
|
121
|
-
*
|
|
177
|
+
* Subscribe to real-time lifecycle events emitted by the native
|
|
178
|
+
* SDK during a verification session. Call this **before**
|
|
179
|
+
* `startVerification` so the subscription captures the earliest
|
|
180
|
+
* events (`SESSION_CREATED`, `PERMISSIONS_REQUESTED`).
|
|
122
181
|
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
182
|
+
* Returns a subscription handle; call `.remove()` to stop
|
|
183
|
+
* receiving events.
|
|
125
184
|
*/
|
|
126
|
-
static
|
|
127
|
-
|
|
185
|
+
static addListener(callback) {
|
|
186
|
+
const subscription = eventEmitter.addListener('UseSenseEvent', raw => {
|
|
187
|
+
callback(raw);
|
|
188
|
+
});
|
|
189
|
+
return {
|
|
190
|
+
remove: () => subscription.remove()
|
|
191
|
+
};
|
|
128
192
|
}
|
|
129
193
|
|
|
130
194
|
/**
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
195
|
+
* Clear all event listeners and release native resources. Does not
|
|
196
|
+
* need to be called explicitly during normal usage; the plugin
|
|
197
|
+
* cleans up on process teardown. Useful when you want to re-
|
|
198
|
+
* initialize against a different API key or during test teardown.
|
|
135
199
|
*/
|
|
136
|
-
static async
|
|
137
|
-
return UseSenseModule.
|
|
200
|
+
static async reset() {
|
|
201
|
+
return UseSenseModule.reset();
|
|
138
202
|
}
|
|
139
203
|
|
|
140
204
|
/**
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
* @param callback - Function invoked for each event.
|
|
146
|
-
* @returns A subscription handle with a `remove()` method.
|
|
147
|
-
*
|
|
148
|
-
* @example
|
|
149
|
-
* ```ts
|
|
150
|
-
* const listener = UseSense.addListener((event) => {
|
|
151
|
-
* console.log(event.type);
|
|
152
|
-
* });
|
|
153
|
-
* // Later:
|
|
154
|
-
* listener.remove();
|
|
155
|
-
* ```
|
|
205
|
+
* Whether the native plugin has an active `UseSense` client. Set
|
|
206
|
+
* to `true` after a successful `initialize` and `false` after
|
|
207
|
+
* `reset`. Useful for feature-flagging UI that should only show
|
|
208
|
+
* when the SDK is ready.
|
|
156
209
|
*/
|
|
157
|
-
static
|
|
158
|
-
UseSenseModule.
|
|
159
|
-
const subscription = eventEmitter.addListener('UseSenseEvent', callback);
|
|
160
|
-
return {
|
|
161
|
-
remove: () => {
|
|
162
|
-
subscription.remove();
|
|
163
|
-
UseSenseModule.unsubscribeFromEvents();
|
|
164
|
-
}
|
|
165
|
-
};
|
|
210
|
+
static async isInitialized() {
|
|
211
|
+
return UseSenseModule.isInitialized();
|
|
166
212
|
}
|
|
167
213
|
|
|
214
|
+
// ─── LiveSense v4 ─────────────────────────────────────────────────────
|
|
215
|
+
// Phase 1 ticket R-1.
|
|
216
|
+
//
|
|
217
|
+
// v4 runs the perspective-distortion zoom-motion capture. Passthrough
|
|
218
|
+
// to the native SDK's startV4Session (iOS) / startV4Verification
|
|
219
|
+
// (Android). The returned promise resolves with the opaque verdict;
|
|
220
|
+
// sub-scores and pillar verdicts are never exposed.
|
|
221
|
+
|
|
168
222
|
/**
|
|
169
|
-
*
|
|
223
|
+
* Start a LiveSense v4 session.
|
|
170
224
|
*
|
|
171
|
-
*
|
|
225
|
+
* The session must already have been created on your backend and the
|
|
226
|
+
* session_token + nonce forwarded to the client. The native SDK drives
|
|
227
|
+
* the camera, signs the frame hash chain with the platform-attested
|
|
228
|
+
* key, uploads, and returns the opaque verdict.
|
|
172
229
|
*/
|
|
173
|
-
static
|
|
174
|
-
return UseSenseModule.
|
|
230
|
+
static async startV4Verification(request) {
|
|
231
|
+
return UseSenseModule.startV4Verification({
|
|
232
|
+
sessionId: request.sessionId,
|
|
233
|
+
sessionToken: request.sessionToken,
|
|
234
|
+
nonce: request.nonce,
|
|
235
|
+
apiBaseUrl: request.apiBaseUrl,
|
|
236
|
+
environment: request.environment ?? 'production',
|
|
237
|
+
displayName: request.displayName,
|
|
238
|
+
brandPrimaryColor: request.brandPrimaryColor
|
|
239
|
+
});
|
|
175
240
|
}
|
|
176
241
|
}
|
|
242
|
+
|
|
243
|
+
// ─── LiveSense v4 types (R-1) ─────────────────────────────────────────────
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Opaque verdict from POST /v1/sessions/:id/result. Matches the server
|
|
247
|
+
* contract exactly; no sub-scores leak through.
|
|
248
|
+
*/
|
|
177
249
|
exports.UseSense = UseSense;
|
|
178
|
-
var _default = exports.default = UseSense;
|
|
250
|
+
var _default = exports.default = UseSense; // Slice 5d: Flows. A parallel surface to Sessions — host apps choose one
|
|
251
|
+
// per call. See guides/flows/sessions-vs-flows in the API docs.
|
|
179
252
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","UseSenseModule","NativeModules","Error","eventEmitter","NativeEventEmitter","UseSense","initialize","config","apiKey","code","message","environment","
|
|
1
|
+
{"version":3,"names":["_reactNative","require","_flows","LINKING_ERROR","Platform","select","ios","android","default","UseSenseModule","NativeModules","Error","eventEmitter","NativeEventEmitter","UseSense","initialize","config","apiKey","err","code","message","isRetryable","environment","apiEndpoint","branding","antispoofOnDeviceEnabled","liveSenseV4Enabled","startVerification","request","sessionType","externalUserId","identityId","metadata","addListener","callback","subscription","raw","remove","reset","isInitialized","startV4Verification","sessionId","sessionToken","nonce","apiBaseUrl","displayName","brandPrimaryColor","exports","_default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Native wrapper for the UseSense Flows runner.
|
|
3
|
+
*
|
|
4
|
+
* Coexists with the existing Sessions API (`UseSense.startSession`, etc.);
|
|
5
|
+
* this is a parallel surface, not a replacement. See `guides/flows/sessions-vs-flows`
|
|
6
|
+
* in the API docs for when to use which.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
*
|
|
10
|
+
* import { UseSenseFlows, FlowError } from 'react-native-usesense';
|
|
11
|
+
*
|
|
12
|
+
* try {
|
|
13
|
+
* const result = await UseSenseFlows.runFlow({ flowRunId, sdkToken });
|
|
14
|
+
* console.log(result.outcome); // 'APPROVE' | 'REJECT' | 'MANUAL_REVIEW' | null
|
|
15
|
+
* } catch (e) {
|
|
16
|
+
* if (e instanceof FlowError) {
|
|
17
|
+
* // e.code: 'token_expired' | 'token_invalid' | ...
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { NativeModules, Platform } from 'react-native';
|
|
23
|
+
const LINKING_ERROR = `react-native-usesense (flows): the native module could not be found.\n\n` + Platform.select({
|
|
24
|
+
ios: `iOS: run \`cd ios && pod install\` and rebuild the app.`,
|
|
25
|
+
android: `Android: rebuild the app after installing the package.`,
|
|
26
|
+
default: ''
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Lazy lookup so this module doesn't throw at import time on platforms that
|
|
30
|
+
// haven't been re-linked yet. The Sessions module mirrors this pattern.
|
|
31
|
+
function nativeModule() {
|
|
32
|
+
const m = NativeModules.UseSenseFlowsModule;
|
|
33
|
+
if (!m) throw new Error(LINKING_ERROR);
|
|
34
|
+
return m;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Server-driven flow run state. Host apps see only the terminal ones via
|
|
39
|
+
* `FlowRunResult`; intermediate states drive the runner internally.
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/** Terminal outcome of a flow run. */
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Uniform error taxonomy across every SDK. See `guides/flows/errors` in the
|
|
46
|
+
* API docs for per-code recovery patterns.
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
const FLOW_ERROR_CODES = ['token_expired', 'token_invalid', 'network_unavailable', 'permission_denied', 'provider_unavailable', 'cancelled', 'unsupported_action', 'invalid_input', 'unknown'];
|
|
50
|
+
function normaliseCode(code) {
|
|
51
|
+
return typeof code === 'string' && FLOW_ERROR_CODES.includes(code) ? code : 'unknown';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Result returned to the host app's `runFlow` promise on terminal state. */
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Typed error thrown by `runFlow` when the native runner reports a failure.
|
|
58
|
+
* Mirrors the web / iOS / Android / Flutter SDKs so host apps catch one
|
|
59
|
+
* taxonomy regardless of platform.
|
|
60
|
+
*/
|
|
61
|
+
export class FlowError extends Error {
|
|
62
|
+
constructor(code, message) {
|
|
63
|
+
super(message);
|
|
64
|
+
this.name = 'FlowError';
|
|
65
|
+
this.code = code;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Options for `UseSenseFlows.runFlow`. */
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Public entry point for the Flows runner. Sessions APIs are untouched;
|
|
73
|
+
* this is a parallel namespace.
|
|
74
|
+
*/
|
|
75
|
+
export const UseSenseFlows = {
|
|
76
|
+
/**
|
|
77
|
+
* Run an operator-authored Flow inside the host app. Resolves with a
|
|
78
|
+
* [FlowRunResult] when the run reaches a terminal state (completed,
|
|
79
|
+
* cancelled, errored, abandoned). Rejects with a [FlowError] on transport
|
|
80
|
+
* / token / unsupported-action faults.
|
|
81
|
+
*/
|
|
82
|
+
async runFlow(options) {
|
|
83
|
+
try {
|
|
84
|
+
const native = await nativeModule().runFlow(options.flowRunId, options.sdkToken, options.apiBaseUrl ?? null);
|
|
85
|
+
return {
|
|
86
|
+
flowRunId: native.flowRunId,
|
|
87
|
+
state: native.state,
|
|
88
|
+
outcome: native.outcome
|
|
89
|
+
};
|
|
90
|
+
} catch (e) {
|
|
91
|
+
// RN bridge errors are surfaced as `Error` with `.code` and `.message`
|
|
92
|
+
// properties when the native side calls `reject(code, message, null)`.
|
|
93
|
+
const code = normaliseCode(e.code);
|
|
94
|
+
const message = e.message ?? 'Flow failed';
|
|
95
|
+
throw new FlowError(code, message);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=flows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeModules","Platform","LINKING_ERROR","select","ios","android","default","nativeModule","m","UseSenseFlowsModule","Error","FLOW_ERROR_CODES","normaliseCode","code","includes","FlowError","constructor","message","name","UseSenseFlows","runFlow","options","native","flowRunId","sdkToken","apiBaseUrl","state","outcome","e"],"sourceRoot":"../../src","sources":["flows.ts"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtD,MAAMC,aAAa,GACjB,0EAA0E,GAC1ED,QAAQ,CAACE,MAAM,CAAC;EACdC,GAAG,EAAE,yDAAyD;EAC9DC,OAAO,EAAE,wDAAwD;EACjEC,OAAO,EAAE;AACX,CAAC,CAAC;;AAEJ;AACA;AACA,SAASC,YAAYA,CAAA,EAAG;EACtB,MAAMC,CAAC,GAAGR,aAAa,CAACS,mBAAmB;EAC3C,IAAI,CAACD,CAAC,EAAE,MAAM,IAAIE,KAAK,CAACR,aAAa,CAAC;EACtC,OAAOM,CAAC;AACV;;AAEA;AACA;AACA;AACA;;AAWA;;AAGA;AACA;AACA;AACA;;AAeA,MAAMG,gBAA0C,GAAG,CACjD,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,WAAW,EACX,oBAAoB,EACpB,eAAe,EACf,SAAS,CACD;AAEV,SAASC,aAAaA,CAACC,IAAa,EAAiB;EACnD,OAAO,OAAOA,IAAI,KAAK,QAAQ,IAAKF,gBAAgB,CAAuBG,QAAQ,CAACD,IAAI,CAAC,GACpFA,IAAI,GACL,SAAS;AACf;;AAEA;;AAaA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAME,SAAS,SAASL,KAAK,CAAC;EAEnCM,WAAWA,CAACH,IAAmB,EAAEI,OAAe,EAAE;IAChD,KAAK,CAACA,OAAO,CAAC;IACd,IAAI,CAACC,IAAI,GAAG,WAAW;IACvB,IAAI,CAACL,IAAI,GAAGA,IAAI;EAClB;AACF;;AAEA;;AAQA;AACA;AACA;AACA;AACA,OAAO,MAAMM,aAAa,GAAG;EAC3B;AACF;AACA;AACA;AACA;AACA;EACE,MAAMC,OAAOA,CAACC,OAAuB,EAA0B;IAC7D,IAAI;MACF,MAAMC,MAAM,GAAG,MAAMf,YAAY,CAAC,CAAC,CAACa,OAAO,CACzCC,OAAO,CAACE,SAAS,EACjBF,OAAO,CAACG,QAAQ,EAChBH,OAAO,CAACI,UAAU,IAAI,IACxB,CAAC;MACD,OAAO;QACLF,SAAS,EAAED,MAAM,CAACC,SAAS;QAC3BG,KAAK,EAAEJ,MAAM,CAACI,KAAK;QACnBC,OAAO,EAAEL,MAAM,CAACK;MAClB,CAAC;IACH,CAAC,CAAC,OAAOC,CAAC,EAAE;MACV;MACA;MACA,MAAMf,IAAI,GAAGD,aAAa,CAAEgB,CAAC,CAAuBf,IAAI,CAAC;MACzD,MAAMI,OAAO,GAAIW,CAAC,CAA0BX,OAAO,IAAI,aAAa;MACpE,MAAM,IAAIF,SAAS,CAACF,IAAI,EAAEI,OAAO,CAAC;IACpC;EACF;AACF,CAAC","ignoreList":[]}
|