react-native-usesense 2.0.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +6 -6
- package/android/src/main/java/com/usesense/reactnative/UseSenseFlowsModule.kt +72 -0
- package/android/src/main/java/com/usesense/reactnative/UseSenseModule.kt +76 -0
- 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 +55 -1
- 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 +55 -3
- 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 +43 -1
- 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 +56 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +3 -1
- package/react-native-usesense.podspec +1 -1
- package/src/flows.ts +159 -0
- package/src/index.ts +96 -0
package/lib/commonjs/index.js
CHANGED
|
@@ -3,8 +3,22 @@
|
|
|
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");
|
|
21
|
+
var _flows = require("./flows");
|
|
8
22
|
const LINKING_ERROR = `react-native-usesense: the native module could not be found.\n\n` + _reactNative.Platform.select({
|
|
9
23
|
ios: `iOS: run \`cd ios && pod install\` and rebuild the app.`,
|
|
10
24
|
android: `Android: rebuild the app after installing the package.`,
|
|
@@ -137,7 +151,9 @@ class UseSense {
|
|
|
137
151
|
apiKey: config.apiKey,
|
|
138
152
|
environment: config.environment ?? 'auto',
|
|
139
153
|
apiEndpoint: config.apiEndpoint,
|
|
140
|
-
branding: config.branding
|
|
154
|
+
branding: config.branding,
|
|
155
|
+
antispoofOnDeviceEnabled: config.antispoofOnDeviceEnabled ?? false,
|
|
156
|
+
liveSenseV4Enabled: config.liveSenseV4Enabled ?? false
|
|
141
157
|
});
|
|
142
158
|
}
|
|
143
159
|
|
|
@@ -194,7 +210,43 @@ class UseSense {
|
|
|
194
210
|
static async isInitialized() {
|
|
195
211
|
return UseSenseModule.isInitialized();
|
|
196
212
|
}
|
|
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
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Start a LiveSense v4 session.
|
|
224
|
+
*
|
|
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.
|
|
229
|
+
*/
|
|
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
|
+
});
|
|
240
|
+
}
|
|
197
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
|
+
*/
|
|
198
249
|
exports.UseSense = UseSense;
|
|
199
|
-
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.
|
|
200
252
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","android","default","UseSenseModule","NativeModules","Error","eventEmitter","NativeEventEmitter","UseSense","initialize","config","apiKey","err","code","message","isRetryable","environment","apiEndpoint","branding","startVerification","request","sessionType","externalUserId","identityId","metadata","addListener","callback","subscription","raw","remove","reset","isInitialized","exports","_default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"
|
|
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":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -131,7 +131,9 @@ export class UseSense {
|
|
|
131
131
|
apiKey: config.apiKey,
|
|
132
132
|
environment: config.environment ?? 'auto',
|
|
133
133
|
apiEndpoint: config.apiEndpoint,
|
|
134
|
-
branding: config.branding
|
|
134
|
+
branding: config.branding,
|
|
135
|
+
antispoofOnDeviceEnabled: config.antispoofOnDeviceEnabled ?? false,
|
|
136
|
+
liveSenseV4Enabled: config.liveSenseV4Enabled ?? false
|
|
135
137
|
});
|
|
136
138
|
}
|
|
137
139
|
|
|
@@ -188,6 +190,46 @@ export class UseSense {
|
|
|
188
190
|
static async isInitialized() {
|
|
189
191
|
return UseSenseModule.isInitialized();
|
|
190
192
|
}
|
|
193
|
+
|
|
194
|
+
// ─── LiveSense v4 ─────────────────────────────────────────────────────
|
|
195
|
+
// Phase 1 ticket R-1.
|
|
196
|
+
//
|
|
197
|
+
// v4 runs the perspective-distortion zoom-motion capture. Passthrough
|
|
198
|
+
// to the native SDK's startV4Session (iOS) / startV4Verification
|
|
199
|
+
// (Android). The returned promise resolves with the opaque verdict;
|
|
200
|
+
// sub-scores and pillar verdicts are never exposed.
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Start a LiveSense v4 session.
|
|
204
|
+
*
|
|
205
|
+
* The session must already have been created on your backend and the
|
|
206
|
+
* session_token + nonce forwarded to the client. The native SDK drives
|
|
207
|
+
* the camera, signs the frame hash chain with the platform-attested
|
|
208
|
+
* key, uploads, and returns the opaque verdict.
|
|
209
|
+
*/
|
|
210
|
+
static async startV4Verification(request) {
|
|
211
|
+
return UseSenseModule.startV4Verification({
|
|
212
|
+
sessionId: request.sessionId,
|
|
213
|
+
sessionToken: request.sessionToken,
|
|
214
|
+
nonce: request.nonce,
|
|
215
|
+
apiBaseUrl: request.apiBaseUrl,
|
|
216
|
+
environment: request.environment ?? 'production',
|
|
217
|
+
displayName: request.displayName,
|
|
218
|
+
brandPrimaryColor: request.brandPrimaryColor
|
|
219
|
+
});
|
|
220
|
+
}
|
|
191
221
|
}
|
|
222
|
+
|
|
223
|
+
// ─── LiveSense v4 types (R-1) ─────────────────────────────────────────────
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Opaque verdict from POST /v1/sessions/:id/result. Matches the server
|
|
227
|
+
* contract exactly; no sub-scores leak through.
|
|
228
|
+
*/
|
|
229
|
+
|
|
192
230
|
export default UseSense;
|
|
231
|
+
|
|
232
|
+
// Slice 5d: Flows. A parallel surface to Sessions — host apps choose one
|
|
233
|
+
// per call. See guides/flows/sessions-vs-flows in the API docs.
|
|
234
|
+
export { UseSenseFlows, FlowError } from './flows';
|
|
193
235
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModules","NativeEventEmitter","Platform","LINKING_ERROR","select","ios","android","default","UseSenseModule","Error","eventEmitter","UseSense","initialize","config","apiKey","err","code","message","isRetryable","environment","apiEndpoint","branding","startVerification","request","sessionType","externalUserId","identityId","metadata","addListener","callback","subscription","raw","remove","reset","isInitialized"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"AAAA,SAASA,aAAa,EAAEC,kBAAkB,EAAEC,QAAQ,QAAQ,cAAc;AAE1E,MAAMC,aAAa,GACjB,kEAAkE,GAClED,QAAQ,CAACE,MAAM,CAAC;EACdC,GAAG,EAAE,yDAAyD;EAC9DC,OAAO,EAAE,wDAAwD;EACjEC,OAAO,EAAE;AACX,CAAC,CAAC,GACF,sJAAsJ;AAExJ,MAAMC,cAAc,GAAGR,aAAa,CAACQ,cAAc;AAEnD,IAAI,CAACA,cAAc,EAAE;EACnB,MAAM,IAAIC,KAAK,CAACN,aAAa,CAAC;AAChC;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAGA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAUA;AACA;AACA;AACA;;
|
|
1
|
+
{"version":3,"names":["NativeModules","NativeEventEmitter","Platform","LINKING_ERROR","select","ios","android","default","UseSenseModule","Error","eventEmitter","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","UseSenseFlows","FlowError"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
* Server-driven flow run state. Host apps see only the terminal ones via
|
|
23
|
+
* `FlowRunResult`; intermediate states drive the runner internally.
|
|
24
|
+
*/
|
|
25
|
+
export type FlowRunState = 'pending' | 'in_progress' | 'stalled' | 'awaiting_review' | 'completed' | 'errored' | 'abandoned' | 'cancelled';
|
|
26
|
+
/** Terminal outcome of a flow run. */
|
|
27
|
+
export type FlowOutcome = 'APPROVE' | 'REJECT' | 'MANUAL_REVIEW';
|
|
28
|
+
/**
|
|
29
|
+
* Uniform error taxonomy across every SDK. See `guides/flows/errors` in the
|
|
30
|
+
* API docs for per-code recovery patterns.
|
|
31
|
+
*/
|
|
32
|
+
export type FlowErrorCode = 'token_expired' | 'token_invalid' | 'network_unavailable' | 'permission_denied' | 'provider_unavailable' | 'cancelled' | 'unsupported_action'
|
|
33
|
+
/** Server form validation failed. The native runner handles this inline
|
|
34
|
+
* (per-field highlights) and never reports terminal — but if a host app
|
|
35
|
+
* drives advance() outside the runner, the 422 surfaces with this code. */
|
|
36
|
+
| 'invalid_input' | 'unknown';
|
|
37
|
+
/** Result returned to the host app's `runFlow` promise on terminal state. */
|
|
38
|
+
export interface FlowRunResult {
|
|
39
|
+
flowRunId: string;
|
|
40
|
+
state: FlowRunState;
|
|
41
|
+
outcome: FlowOutcome | null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Typed error thrown by `runFlow` when the native runner reports a failure.
|
|
45
|
+
* Mirrors the web / iOS / Android / Flutter SDKs so host apps catch one
|
|
46
|
+
* taxonomy regardless of platform.
|
|
47
|
+
*/
|
|
48
|
+
export declare class FlowError extends Error {
|
|
49
|
+
readonly code: FlowErrorCode;
|
|
50
|
+
constructor(code: FlowErrorCode, message: string);
|
|
51
|
+
}
|
|
52
|
+
/** Options for `UseSenseFlows.runFlow`. */
|
|
53
|
+
export interface RunFlowOptions {
|
|
54
|
+
flowRunId: string;
|
|
55
|
+
sdkToken: string;
|
|
56
|
+
/** Defaults to `https://api.usesense.ai`. */
|
|
57
|
+
apiBaseUrl?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Public entry point for the Flows runner. Sessions APIs are untouched;
|
|
61
|
+
* this is a parallel namespace.
|
|
62
|
+
*/
|
|
63
|
+
export declare const UseSenseFlows: {
|
|
64
|
+
/**
|
|
65
|
+
* Run an operator-authored Flow inside the host app. Resolves with a
|
|
66
|
+
* [FlowRunResult] when the run reaches a terminal state (completed,
|
|
67
|
+
* cancelled, errored, abandoned). Rejects with a [FlowError] on transport
|
|
68
|
+
* / token / unsupported-action faults.
|
|
69
|
+
*/
|
|
70
|
+
runFlow(options: RunFlowOptions): Promise<FlowRunResult>;
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=flows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flows.d.ts","sourceRoot":"","sources":["../../../src/flows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAoBH;;;GAGG;AACH,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,aAAa,GACb,SAAS,GACT,iBAAiB,GACjB,WAAW,GACX,SAAS,GACT,WAAW,GACX,WAAW,CAAC;AAEhB,sCAAsC;AACtC,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,eAAe,CAAC;AAEjE;;;GAGG;AACH,MAAM,MAAM,aAAa,GACrB,eAAe,GACf,eAAe,GACf,qBAAqB,GACrB,mBAAmB,GACnB,sBAAsB,GACtB,WAAW,GACX,oBAAoB;AACtB;;4EAE4E;GAC1E,eAAe,GACf,SAAS,CAAC;AAoBd,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,YAAY,CAAC;IACpB,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;CAC7B;AAQD;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;gBACjB,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM;CAKjD;AAED,2CAA2C;AAC3C,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa;IACxB;;;;;OAKG;qBACoB,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CAoB/D,CAAC"}
|
|
@@ -49,6 +49,26 @@ export interface UseSenseConfig {
|
|
|
49
49
|
apiEndpoint?: string;
|
|
50
50
|
/** SDK-level branding overrides. */
|
|
51
51
|
branding?: BrandingConfig;
|
|
52
|
+
/**
|
|
53
|
+
* Opt in to the on-device antispoof classifier (v4.2). When enabled the
|
|
54
|
+
* native layer runs the bundled CelebA-Spoof model during capture and
|
|
55
|
+
* attaches per-frame spoof probabilities to the uploaded metadata. When
|
|
56
|
+
* disabled (default), the watchtower backend runs the classifier server-side.
|
|
57
|
+
* See `docs/sdk-specs/antispoof-classifier-sdk-spec.md` in the watchtower
|
|
58
|
+
* repo for the rollout plan and crosscheck policy.
|
|
59
|
+
*/
|
|
60
|
+
antispoofOnDeviceEnabled?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Opt the session into the LiveSense v4 capture flow. When true the native
|
|
63
|
+
* layer:
|
|
64
|
+
* - sends `x-usesense-sdk-version: v4` on session creation
|
|
65
|
+
* - inserts a constitutive zoom-motion phase between baseline and the
|
|
66
|
+
* active challenge (additive, not a replacement)
|
|
67
|
+
* - tags every captured frame with its capture phase
|
|
68
|
+
* The org must also have `livesense_v4_enabled` set in its features map
|
|
69
|
+
* server-side.
|
|
70
|
+
*/
|
|
71
|
+
liveSenseV4Enabled?: boolean;
|
|
52
72
|
}
|
|
53
73
|
/**
|
|
54
74
|
* Request to start a verification session.
|
|
@@ -207,6 +227,42 @@ export declare class UseSense {
|
|
|
207
227
|
* when the SDK is ready.
|
|
208
228
|
*/
|
|
209
229
|
static isInitialized(): Promise<boolean>;
|
|
230
|
+
/**
|
|
231
|
+
* Start a LiveSense v4 session.
|
|
232
|
+
*
|
|
233
|
+
* The session must already have been created on your backend and the
|
|
234
|
+
* session_token + nonce forwarded to the client. The native SDK drives
|
|
235
|
+
* the camera, signs the frame hash chain with the platform-attested
|
|
236
|
+
* key, uploads, and returns the opaque verdict.
|
|
237
|
+
*/
|
|
238
|
+
static startV4Verification(request: V4VerificationRequest): Promise<V4Verdict>;
|
|
239
|
+
}
|
|
240
|
+
export interface V4VerificationRequest {
|
|
241
|
+
sessionId: string;
|
|
242
|
+
sessionToken: string;
|
|
243
|
+
nonce: string;
|
|
244
|
+
apiBaseUrl: string;
|
|
245
|
+
environment?: UseSenseEnvironment;
|
|
246
|
+
displayName?: string;
|
|
247
|
+
brandPrimaryColor?: string;
|
|
248
|
+
}
|
|
249
|
+
export type V4Decision = 'pass' | 'fail' | 'review';
|
|
250
|
+
export type V4Confidence = 'high' | 'medium' | 'low';
|
|
251
|
+
export type V4AssuranceLevel = 'mobile_hardware' | 'web_attested' | 'web_unattested';
|
|
252
|
+
export type V4CaptureChannel = 'ios' | 'android' | 'rn' | 'flutter' | 'web';
|
|
253
|
+
/**
|
|
254
|
+
* Opaque verdict from POST /v1/sessions/:id/result. Matches the server
|
|
255
|
+
* contract exactly; no sub-scores leak through.
|
|
256
|
+
*/
|
|
257
|
+
export interface V4Verdict {
|
|
258
|
+
session_id: string;
|
|
259
|
+
verdict: V4Decision;
|
|
260
|
+
confidence: V4Confidence;
|
|
261
|
+
assurance_level_achieved: V4AssuranceLevel;
|
|
262
|
+
capture_channel: V4CaptureChannel;
|
|
263
|
+
match_sense_embedding_id: string | null;
|
|
264
|
+
timestamp: string;
|
|
210
265
|
}
|
|
211
266
|
export default UseSense;
|
|
267
|
+
export { UseSenseFlows, FlowError, type FlowErrorCode, type FlowOutcome, type FlowRunResult, type FlowRunState, type RunFlowOptions, } from './flows';
|
|
212
268
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,CAAC;AAEpE,oCAAoC;AACpC,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,gBAAgB,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,eAAe,CAAC;AAE9D;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,CAAC;AAEpE,oCAAoC;AACpC,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,gBAAgB,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,eAAe,CAAC;AAE9D;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B;;;;;;;OAOG;IACH,wBAAwB,CAAC,EAAE,OAAO,CAAC;IAEnC;;;;;;;;;OASG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,WAAW,CAAC;IACzB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CACtD;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,UAAU,EAAE,OAAO,CAAC;IACpB,4CAA4C;IAC5C,UAAU,EAAE,OAAO,CAAC;IACpB,mDAAmD;IACnD,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;;;;OAYG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GACzB,iBAAiB,GACjB,uBAAuB,GACvB,qBAAqB,GACrB,oBAAoB,GACpB,iBAAiB,GACjB,gBAAgB,GAChB,mBAAmB,GACnB,sBAAsB,GACtB,wBAAwB,GACxB,mBAAmB,GACnB,qBAAqB,GACrB,gBAAgB,GAChB,iBAAiB,GACjB,kBAAkB,GAClB,kBAAkB,GAClB,mBAAmB,GACnB,qBAAqB,GACrB,OAAO,GACP,SAAS,CAAC;AAEd,6CAA6C;AAC7C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,iBAAiB,CAAC;IACxB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,iDAAiD;AACjD,MAAM,WAAW,oBAAoB;IACnC,MAAM,IAAI,IAAI,CAAC;CAChB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,QAAQ;IACnB;;;;;;;OAOG;WACU,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB9D;;;;;;OAMG;WACU,iBAAiB,CAC5B,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,cAAc,CAAC;IAS1B;;;;;;;;OAQG;IACH,MAAM,CAAC,WAAW,CAChB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GACvC,oBAAoB;IAYvB;;;;;OAKG;WACU,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAInC;;;;;OAKG;WACU,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC;IAY9C;;;;;;;OAOG;WACU,mBAAmB,CAC9B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,SAAS,CAAC;CAWtB;AAID,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;AACpD,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AACrD,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG,cAAc,GAAG,gBAAgB,CAAC;AACrF,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,UAAU,CAAC;IACpB,UAAU,EAAE,YAAY,CAAC;IACzB,wBAAwB,EAAE,gBAAgB,CAAC;IAC3C,eAAe,EAAE,gBAAgB,CAAC;IAClC,wBAAwB,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAe,QAAQ,CAAC;AAIxB,OAAO,EACL,aAAa,EACb,SAAS,EACT,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,cAAc,GACpB,MAAM,SAAS,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-usesense",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "React Native plugin for human presence verification. Wraps the native UseSense iOS and Android SDKs.",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"react-native": ">=0.73.0"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
+
"@types/jest": "^29.5.14",
|
|
63
64
|
"@types/react": "^18.2.0",
|
|
64
65
|
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
|
65
66
|
"@typescript-eslint/parser": "^7.0.0",
|
|
@@ -69,6 +70,7 @@
|
|
|
69
70
|
"react": "^18.2.0",
|
|
70
71
|
"react-native": "^0.73.0",
|
|
71
72
|
"react-native-builder-bob": "^0.23.0",
|
|
73
|
+
"ts-jest": "^29.4.11",
|
|
72
74
|
"typescript": "^5.3.0"
|
|
73
75
|
},
|
|
74
76
|
"codegenConfig": {
|
package/src/flows.ts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
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
|
+
|
|
24
|
+
const LINKING_ERROR =
|
|
25
|
+
`react-native-usesense (flows): the native module could not be found.\n\n` +
|
|
26
|
+
Platform.select({
|
|
27
|
+
ios: `iOS: run \`cd ios && pod install\` and rebuild the app.`,
|
|
28
|
+
android: `Android: rebuild the app after installing the package.`,
|
|
29
|
+
default: '',
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Lazy lookup so this module doesn't throw at import time on platforms that
|
|
33
|
+
// haven't been re-linked yet. The Sessions module mirrors this pattern.
|
|
34
|
+
function nativeModule() {
|
|
35
|
+
const m = NativeModules.UseSenseFlowsModule;
|
|
36
|
+
if (!m) throw new Error(LINKING_ERROR);
|
|
37
|
+
return m as { runFlow: (flowRunId: string, sdkToken: string, apiBaseUrl: string | null) => Promise<NativeFlowRunResult> };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Server-driven flow run state. Host apps see only the terminal ones via
|
|
42
|
+
* `FlowRunResult`; intermediate states drive the runner internally.
|
|
43
|
+
*/
|
|
44
|
+
export type FlowRunState =
|
|
45
|
+
| 'pending'
|
|
46
|
+
| 'in_progress'
|
|
47
|
+
| 'stalled'
|
|
48
|
+
| 'awaiting_review'
|
|
49
|
+
| 'completed'
|
|
50
|
+
| 'errored'
|
|
51
|
+
| 'abandoned'
|
|
52
|
+
| 'cancelled';
|
|
53
|
+
|
|
54
|
+
/** Terminal outcome of a flow run. */
|
|
55
|
+
export type FlowOutcome = 'APPROVE' | 'REJECT' | 'MANUAL_REVIEW';
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Uniform error taxonomy across every SDK. See `guides/flows/errors` in the
|
|
59
|
+
* API docs for per-code recovery patterns.
|
|
60
|
+
*/
|
|
61
|
+
export type FlowErrorCode =
|
|
62
|
+
| 'token_expired'
|
|
63
|
+
| 'token_invalid'
|
|
64
|
+
| 'network_unavailable'
|
|
65
|
+
| 'permission_denied'
|
|
66
|
+
| 'provider_unavailable'
|
|
67
|
+
| 'cancelled'
|
|
68
|
+
| 'unsupported_action'
|
|
69
|
+
/** Server form validation failed. The native runner handles this inline
|
|
70
|
+
* (per-field highlights) and never reports terminal — but if a host app
|
|
71
|
+
* drives advance() outside the runner, the 422 surfaces with this code. */
|
|
72
|
+
| 'invalid_input'
|
|
73
|
+
| 'unknown';
|
|
74
|
+
|
|
75
|
+
const FLOW_ERROR_CODES: readonly FlowErrorCode[] = [
|
|
76
|
+
'token_expired',
|
|
77
|
+
'token_invalid',
|
|
78
|
+
'network_unavailable',
|
|
79
|
+
'permission_denied',
|
|
80
|
+
'provider_unavailable',
|
|
81
|
+
'cancelled',
|
|
82
|
+
'unsupported_action',
|
|
83
|
+
'invalid_input',
|
|
84
|
+
'unknown',
|
|
85
|
+
] as const;
|
|
86
|
+
|
|
87
|
+
function normaliseCode(code: unknown): FlowErrorCode {
|
|
88
|
+
return typeof code === 'string' && (FLOW_ERROR_CODES as readonly string[]).includes(code)
|
|
89
|
+
? (code as FlowErrorCode)
|
|
90
|
+
: 'unknown';
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Result returned to the host app's `runFlow` promise on terminal state. */
|
|
94
|
+
export interface FlowRunResult {
|
|
95
|
+
flowRunId: string;
|
|
96
|
+
state: FlowRunState;
|
|
97
|
+
outcome: FlowOutcome | null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface NativeFlowRunResult {
|
|
101
|
+
flowRunId: string;
|
|
102
|
+
state: FlowRunState;
|
|
103
|
+
outcome: FlowOutcome | null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Typed error thrown by `runFlow` when the native runner reports a failure.
|
|
108
|
+
* Mirrors the web / iOS / Android / Flutter SDKs so host apps catch one
|
|
109
|
+
* taxonomy regardless of platform.
|
|
110
|
+
*/
|
|
111
|
+
export class FlowError extends Error {
|
|
112
|
+
readonly code: FlowErrorCode;
|
|
113
|
+
constructor(code: FlowErrorCode, message: string) {
|
|
114
|
+
super(message);
|
|
115
|
+
this.name = 'FlowError';
|
|
116
|
+
this.code = code;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Options for `UseSenseFlows.runFlow`. */
|
|
121
|
+
export interface RunFlowOptions {
|
|
122
|
+
flowRunId: string;
|
|
123
|
+
sdkToken: string;
|
|
124
|
+
/** Defaults to `https://api.usesense.ai`. */
|
|
125
|
+
apiBaseUrl?: string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Public entry point for the Flows runner. Sessions APIs are untouched;
|
|
130
|
+
* this is a parallel namespace.
|
|
131
|
+
*/
|
|
132
|
+
export const UseSenseFlows = {
|
|
133
|
+
/**
|
|
134
|
+
* Run an operator-authored Flow inside the host app. Resolves with a
|
|
135
|
+
* [FlowRunResult] when the run reaches a terminal state (completed,
|
|
136
|
+
* cancelled, errored, abandoned). Rejects with a [FlowError] on transport
|
|
137
|
+
* / token / unsupported-action faults.
|
|
138
|
+
*/
|
|
139
|
+
async runFlow(options: RunFlowOptions): Promise<FlowRunResult> {
|
|
140
|
+
try {
|
|
141
|
+
const native = await nativeModule().runFlow(
|
|
142
|
+
options.flowRunId,
|
|
143
|
+
options.sdkToken,
|
|
144
|
+
options.apiBaseUrl ?? null,
|
|
145
|
+
);
|
|
146
|
+
return {
|
|
147
|
+
flowRunId: native.flowRunId,
|
|
148
|
+
state: native.state,
|
|
149
|
+
outcome: native.outcome,
|
|
150
|
+
};
|
|
151
|
+
} catch (e) {
|
|
152
|
+
// RN bridge errors are surfaced as `Error` with `.code` and `.message`
|
|
153
|
+
// properties when the native side calls `reject(code, message, null)`.
|
|
154
|
+
const code = normaliseCode((e as { code?: string }).code);
|
|
155
|
+
const message = (e as { message?: string }).message ?? 'Flow failed';
|
|
156
|
+
throw new FlowError(code, message);
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
};
|