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.
@@ -3,177 +3,250 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = exports.UseSense = void 0;
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
- const {
9
- UseSenseModule
10
- } = _reactNative.NativeModules;
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('react-native-usesense: NativeModule not found. Make sure you have linked the library correctly.\n' + 'iOS: Run `cd ios && pod install`\n' + 'Android: Rebuild the app after installing the package.');
29
+ throw new Error(LINKING_ERROR);
13
30
  }
14
31
 
15
- // ─── Types ───────────────────────────────────────────────────────────
32
+ // ─── Types ───────────────────────────────────────────────────────────────
16
33
 
17
- /** Environment for the UseSense API. */
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
- /** Session type for verification. */
40
+ /** Type of verification session. */
20
41
 
21
- /** Challenge policy controlling verification difficulty. */
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
- /** Decision returned by the verification engine. */
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
- /** Processing stage during server-side analysis. */
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
- * Configuration for initializing the UseSense plugin.
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
- * Result returned when a verification session completes.
70
+ * Redacted decision object returned when a session completes.
41
71
  *
42
- * **Important:** This result is for UI feedback only.
43
- * The definitive verdict arrives at your backend via HMAC-signed webhook.
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 returned when a verification session fails.
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
- * Events emitted during the verification session lifecycle.
88
+ * Lifecycle event types emitted by the native SDK during a
89
+ * verification session.
52
90
  */
53
91
 
54
- /** Options for starting a verification session. */
92
+ /** Single event emitted during a session. */
55
93
 
56
- /** Status of a verification session. */
94
+ /** Handle returned by `UseSense.addListener`. */
57
95
 
58
- /** Subscription handle returned by {@link UseSense.addListener}. */
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
- * Provides human presence verification by wrapping the native UseSense
68
- * iOS and Android SDKs into a single cross-platform API.
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({ apiKey: 'your_key', environment: 'sandbox' });
75
- * const result = await UseSense.startSession({ sessionType: 'enrollment' });
76
- * console.log(result.decision);
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 once before any other method.
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
- * @param config - Plugin configuration including API key and environment.
84
- * @throws {UseSenseError} If the API key is invalid or configuration is malformed.
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
- throw {
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 ?? 'sandbox',
96
- organizationId: config.organizationId,
97
- sessionType: config.sessionType ?? 'enrollment',
98
- identityId: config.identityId,
99
- challengePolicy: config.challengePolicy ?? 'standard',
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 camera UI.
108
- *
109
- * The returned promise resolves when the session completes and the modal
110
- * dismisses, or rejects if an error occurs.
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 startSession(options) {
117
- return UseSenseModule.startSession(options ?? {});
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
- * Cancel an in-progress verification session.
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
- * The camera UI is dismissed and the `startSession` promise rejects
124
- * with a `session_cancelled` error.
182
+ * Returns a subscription handle; call `.remove()` to stop
183
+ * receiving events.
125
184
  */
126
- static async cancelSession() {
127
- return UseSenseModule.cancelSession();
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
- * Get the status of a verification session by ID.
132
- *
133
- * @param sessionId - The session ID to query.
134
- * @returns The current status and optional result.
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 getSessionStatus(sessionId) {
137
- return UseSenseModule.getSessionStatus(sessionId);
200
+ static async reset() {
201
+ return UseSenseModule.reset();
138
202
  }
139
203
 
140
204
  /**
141
- * Subscribe to real-time events during the verification lifecycle.
142
- *
143
- * Call this before `startSession()` to receive all events.
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 addListener(callback) {
158
- UseSenseModule.subscribeToEvents();
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
- * Get the native SDK version string.
223
+ * Start a LiveSense v4 session.
170
224
  *
171
- * @returns Version string in semver format (e.g. `"1.0.0"`).
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 getSdkVersion() {
174
- return UseSenseModule.getSdkVersion();
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","organizationId","sessionType","identityId","challengePolicy","enableAudio","timeout","metadata","startSession","options","cancelSession","getSessionStatus","sessionId","addListener","callback","subscribeToEvents","subscription","remove","unsubscribeFromEvents","getSdkVersion","exports","_default","default"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA,MAAM;EAAEC;AAAe,CAAC,GAAGC,0BAAa;AAExC,IAAI,CAACD,cAAc,EAAE;EACnB,MAAM,IAAIE,KAAK,CACb,mGAAmG,GACjG,oCAAoC,GACpC,wDACJ,CAAC;AACH;;AAEA;;AAEA;;AAGA;;AAGA;;AAGA;;AAGA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAsBA;AACA;AACA;AACA;AACA;AACA;;AAwBA;AACA;AACA;;AAUA;AACA;AACA;;AASA;;AAQA;;AAQA;;AAMA;;AAEA,MAAMC,YAAY,GAAG,IAAIC,+BAAkB,CAACJ,cAAc,CAAC;;AAE3D;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMK,QAAQ,CAAC;EACpB;AACF;AACA;AACA;AACA;AACA;EACE,aAAaC,UAAUA,CAACC,MAAsB,EAAiB;IAC7D,IAAI,CAACA,MAAM,CAACC,MAAM,EAAE;MAClB,MAAM;QAAEC,IAAI,EAAE,gBAAgB;QAAEC,OAAO,EAAE;MAAqB,CAAC;IACjE;IACA,OAAOV,cAAc,CAACM,UAAU,CAAC;MAC/BE,MAAM,EAAED,MAAM,CAACC,MAAM;MACrBG,WAAW,EAAEJ,MAAM,CAACI,WAAW,IAAI,SAAS;MAC5CC,cAAc,EAAEL,MAAM,CAACK,cAAc;MACrCC,WAAW,EAAEN,MAAM,CAACM,WAAW,IAAI,YAAY;MAC/CC,UAAU,EAAEP,MAAM,CAACO,UAAU;MAC7BC,eAAe,EAAER,MAAM,CAACQ,eAAe,IAAI,UAAU;MACrDC,WAAW,EAAET,MAAM,CAACS,WAAW,IAAI,KAAK;MACxCC,OAAO,EAAEV,MAAM,CAACU,OAAO,IAAI,KAAK;MAChCC,QAAQ,EAAEX,MAAM,CAACW;IACnB,CAAC,CAAC;EACJ;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACE,aAAaC,YAAYA,CAACC,OAA6B,EAA2B;IAChF,OAAOpB,cAAc,CAACmB,YAAY,CAACC,OAAO,IAAI,CAAC,CAAC,CAAC;EACnD;;EAEA;AACF;AACA;AACA;AACA;AACA;EACE,aAAaC,aAAaA,CAAA,EAAkB;IAC1C,OAAOrB,cAAc,CAACqB,aAAa,CAAC,CAAC;EACvC;;EAEA;AACF;AACA;AACA;AACA;AACA;EACE,aAAaC,gBAAgBA,CAACC,SAAiB,EAA0B;IACvE,OAAOvB,cAAc,CAACsB,gBAAgB,CAACC,SAAS,CAAC;EACnD;;EAEA;AACF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACE,OAAOC,WAAWA,CAACC,QAAwC,EAAwB;IACjFzB,cAAc,CAAC0B,iBAAiB,CAAC,CAAC;IAClC,MAAMC,YAAY,GAAGxB,YAAY,CAACqB,WAAW,CAAC,eAAe,EAAEC,QAAQ,CAAC;IACxE,OAAO;MACLG,MAAM,EAAEA,CAAA,KAAM;QACZD,YAAY,CAACC,MAAM,CAAC,CAAC;QACrB5B,cAAc,CAAC6B,qBAAqB,CAAC,CAAC;MACxC;IACF,CAAC;EACH;;EAEA;AACF;AACA;AACA;AACA;EACE,OAAOC,aAAaA,CAAA,EAAW;IAC7B,OAAO9B,cAAc,CAAC8B,aAAa,CAAC,CAAC;EACvC;AACF;AAACC,OAAA,CAAA1B,QAAA,GAAAA,QAAA;AAAA,IAAA2B,QAAA,GAAAD,OAAA,CAAAE,OAAA,GAEc5B,QAAQ","ignoreList":[]}
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":[]}