@glideidentity/web-client-sdk 4.4.8-beta.1 → 4.4.8-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/adapters/react/usePhoneAuth.d.ts +1 -1
  2. package/dist/adapters/vue/useClient.d.ts +3 -3
  3. package/dist/adapters/vue/usePhoneAuth.d.ts +1 -1
  4. package/dist/browser/web-client-sdk.min.js +1 -1
  5. package/dist/core/phone-auth/api-types.d.ts +112 -27
  6. package/dist/core/phone-auth/client.d.ts +13 -11
  7. package/dist/core/phone-auth/client.js +263 -248
  8. package/dist/core/phone-auth/index.d.ts +1 -1
  9. package/dist/core/phone-auth/index.js +7 -2
  10. package/dist/core/phone-auth/strategies/desktop.d.ts +1 -0
  11. package/dist/core/phone-auth/strategies/desktop.js +64 -18
  12. package/dist/core/phone-auth/strategies/link.js +97 -5
  13. package/dist/core/phone-auth/type-guards.d.ts +61 -43
  14. package/dist/core/phone-auth/type-guards.js +82 -44
  15. package/dist/core/phone-auth/ui/modal.js +14 -1
  16. package/dist/core/version.js +1 -1
  17. package/dist/esm/adapters/react/usePhoneAuth.d.ts +1 -1
  18. package/dist/esm/adapters/vue/useClient.d.ts +3 -3
  19. package/dist/esm/adapters/vue/usePhoneAuth.d.ts +1 -1
  20. package/dist/esm/core/phone-auth/api-types.d.ts +112 -27
  21. package/dist/esm/core/phone-auth/client.d.ts +13 -11
  22. package/dist/esm/core/phone-auth/client.js +263 -248
  23. package/dist/esm/core/phone-auth/index.d.ts +1 -1
  24. package/dist/esm/core/phone-auth/index.js +3 -1
  25. package/dist/esm/core/phone-auth/strategies/desktop.d.ts +1 -0
  26. package/dist/esm/core/phone-auth/strategies/desktop.js +64 -18
  27. package/dist/esm/core/phone-auth/strategies/link.js +97 -5
  28. package/dist/esm/core/phone-auth/type-guards.d.ts +61 -43
  29. package/dist/esm/core/phone-auth/type-guards.js +76 -41
  30. package/dist/esm/core/phone-auth/ui/modal.js +14 -1
  31. package/dist/esm/core/version.js +1 -1
  32. package/dist/esm/index.d.ts +2 -2
  33. package/dist/esm/index.js +3 -1
  34. package/dist/index.d.ts +2 -2
  35. package/dist/index.js +7 -2
  36. package/package.json +1 -1
@@ -6,42 +6,45 @@
6
6
  * without having to write their own type checking logic.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.isHeadlessResult = isHeadlessResult;
9
+ exports.requiresUserAction = exports.requiresPolling = exports.isHeadlessResult = void 0;
10
+ exports.isExtendedResponse = isExtendedResponse;
10
11
  exports.isCredential = isCredential;
12
+ exports.isAuthCredential = isAuthCredential;
11
13
  exports.isLinkStrategy = isLinkStrategy;
12
14
  exports.isTS43Strategy = isTS43Strategy;
13
15
  exports.isDesktopStrategy = isDesktopStrategy;
14
16
  exports.getStrategy = getStrategy;
15
- exports.requiresPolling = requiresPolling;
16
- exports.requiresUserAction = requiresUserAction;
17
+ exports.hasPollingControls = hasPollingControls;
18
+ exports.hasTrigger = hasTrigger;
17
19
  /**
18
- * Type guard to check if the result is a HeadlessResult (headless mode)
19
- * or a Credential (UI mode).
20
+ * Type guard to check if the result is an ExtendedResponse (extended mode)
21
+ * or a Credential (standard mode).
20
22
  *
21
23
  * @example
22
24
  * ```typescript
23
- * const result = await invokeSecurePrompt(sdkRequest);
25
+ * const result = await invokeSecurePrompt(sdkRequest, { executionMode: 'extended' });
24
26
  *
25
- * if (isHeadlessResult(result)) {
26
- * // TypeScript knows this is HeadlessResult
27
+ * if (isExtendedResponse(result)) {
28
+ * // TypeScript knows this is ExtendedResponse
27
29
  * console.log(result.strategy);
28
- * await result.trigger();
30
+ * await result.cancel();
29
31
  * } else {
30
32
  * // TypeScript knows this is a Credential
31
33
  * const processedResult = await verifyPhoneNumberCredential(result, session);
32
34
  * }
33
35
  * ```
34
36
  */
35
- function isHeadlessResult(result) {
37
+ function isExtendedResponse(result) {
36
38
  return result &&
37
39
  typeof result === 'object' &&
38
40
  'strategy' in result &&
39
- 'trigger' in result &&
40
- typeof result.trigger === 'function';
41
+ 'credential' in result &&
42
+ 'cancel' in result &&
43
+ typeof result.cancel === 'function';
41
44
  }
42
45
  /**
43
- * Type guard to check if the result is a Credential (UI mode response).
44
- * A credential is either a string token or an object without HeadlessResult properties.
46
+ * Type guard to check if the result is a Credential (standard mode response).
47
+ * A credential is either a string token or an object without ExtendedResponse properties.
45
48
  *
46
49
  * @example
47
50
  * ```typescript
@@ -57,22 +60,40 @@ function isCredential(result) {
57
60
  // String credentials are valid
58
61
  if (typeof result === 'string')
59
62
  return true;
60
- // Object credentials should NOT have HeadlessResult properties
63
+ // Object credentials should NOT have ExtendedResponse properties
61
64
  if (typeof result === 'object') {
62
- return !('strategy' in result) && !('trigger' in result);
65
+ return !('strategy' in result) && !('credential' in result) && !('cancel' in result);
63
66
  }
64
67
  return false;
65
68
  }
66
69
  /**
67
- * Type guard to check if a HeadlessResult is using the Link strategy.
70
+ * Type guard to check if the result is an AuthCredential object.
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * if (isAuthCredential(result)) {
75
+ * console.log(result.credential);
76
+ * console.log(result.authenticated);
77
+ * }
78
+ * ```
79
+ */
80
+ function isAuthCredential(result) {
81
+ return result &&
82
+ typeof result === 'object' &&
83
+ 'credential' in result &&
84
+ 'authenticated' in result &&
85
+ 'session' in result;
86
+ }
87
+ /**
88
+ * Type guard to check if an ExtendedResponse is using the Link strategy.
68
89
  * Link strategy involves opening an app link (App Clip on iOS, app on Android).
69
90
  *
70
91
  * @example
71
92
  * ```typescript
72
- * if (isHeadlessResult(result) && isLinkStrategy(result)) {
73
- * // Show custom button for opening app
74
- * myButton.onclick = () => result.trigger();
75
- * await result.pollingPromise;
93
+ * if (isExtendedResponse(result) && isLinkStrategy(result)) {
94
+ * // Re-trigger app opening if needed
95
+ * result.trigger();
96
+ * await result.credential;
76
97
  * }
77
98
  * ```
78
99
  */
@@ -80,14 +101,14 @@ function isLinkStrategy(result) {
80
101
  return result.strategy === 'link';
81
102
  }
82
103
  /**
83
- * Type guard to check if a HeadlessResult is using the TS43 strategy.
104
+ * Type guard to check if an ExtendedResponse is using the TS43 strategy.
84
105
  * TS43 strategy uses the browser's Digital Credentials API.
85
106
  *
86
107
  * @example
87
108
  * ```typescript
88
- * if (isHeadlessResult(result) && isTS43Strategy(result)) {
89
- * // Invoke credential API immediately or on button click
90
- * const credential = await result.trigger();
109
+ * if (isExtendedResponse(result) && isTS43Strategy(result)) {
110
+ * // Re-trigger credential request if needed
111
+ * await result.trigger();
91
112
  * }
92
113
  * ```
93
114
  */
@@ -95,15 +116,15 @@ function isTS43Strategy(result) {
95
116
  return result.strategy === 'ts43';
96
117
  }
97
118
  /**
98
- * Type guard to check if a HeadlessResult is using the Desktop strategy.
119
+ * Type guard to check if an ExtendedResponse is using the Desktop strategy.
99
120
  * Desktop strategy involves QR codes for cross-device authentication.
100
121
  *
101
122
  * @example
102
123
  * ```typescript
103
- * if (isHeadlessResult(result) && isDesktopStrategy(result)) {
124
+ * if (isExtendedResponse(result) && isDesktopStrategy(result)) {
104
125
  * // Show custom QR code UI
105
- * displayQRCode(result.qrCodeUrl);
106
- * await result.pollingPromise;
126
+ * displayQRCode(result.qr_code_data);
127
+ * await result.start_polling();
107
128
  * }
108
129
  * ```
109
130
  */
@@ -112,7 +133,7 @@ function isDesktopStrategy(result) {
112
133
  }
113
134
  /**
114
135
  * Helper function to safely get the authentication strategy from any result.
115
- * Returns undefined if the result is not a HeadlessResult.
136
+ * Returns undefined if the result is not an ExtendedResponse.
116
137
  *
117
138
  * @example
118
139
  * ```typescript
@@ -123,38 +144,55 @@ function isDesktopStrategy(result) {
123
144
  * ```
124
145
  */
125
146
  function getStrategy(result) {
126
- if (isHeadlessResult(result)) {
147
+ if (isExtendedResponse(result)) {
127
148
  return result.strategy;
128
149
  }
129
150
  return undefined;
130
151
  }
131
152
  /**
132
- * Helper function to determine if a result requires polling.
133
- * Link and Desktop strategies require polling, TS43 does not.
153
+ * Helper function to determine if a result has polling controls.
154
+ * Link and Desktop strategies have polling controls in extended mode.
134
155
  *
135
156
  * @example
136
157
  * ```typescript
137
- * if (requiresPolling(result)) {
138
- * await result.pollingPromise;
158
+ * if (hasPollingControls(result)) {
159
+ * await result.start_polling();
139
160
  * }
140
161
  * ```
141
162
  */
142
- function requiresPolling(result) {
143
- if (!isHeadlessResult(result))
163
+ function hasPollingControls(result) {
164
+ if (!isExtendedResponse(result))
144
165
  return false;
145
- return result.strategy === 'link' || result.strategy === 'desktop';
166
+ return (result.strategy === 'link' && 'start_polling' in result) ||
167
+ (result.strategy === 'desktop' && 'start_polling' in result);
146
168
  }
147
169
  /**
148
- * Helper function to determine if a result requires user interaction.
149
- * All headless strategies require some form of user interaction.
170
+ * Helper function to determine if a result has a trigger method.
171
+ * Link and TS43 strategies have trigger methods in extended mode.
150
172
  *
151
173
  * @example
152
174
  * ```typescript
153
- * if (requiresUserAction(result)) {
154
- * showActionButton();
175
+ * if (hasTrigger(result)) {
176
+ * result.trigger();
155
177
  * }
156
178
  * ```
157
179
  */
158
- function requiresUserAction(result) {
159
- return isHeadlessResult(result);
180
+ function hasTrigger(result) {
181
+ if (!isExtendedResponse(result))
182
+ return false;
183
+ return 'trigger' in result && typeof result.trigger === 'function';
160
184
  }
185
+ // Export legacy function names as deprecated aliases for backward compatibility
186
+ /**
187
+ * @deprecated Use isExtendedResponse instead
188
+ */
189
+ exports.isHeadlessResult = isExtendedResponse;
190
+ /**
191
+ * @deprecated Use hasPollingControls instead
192
+ */
193
+ exports.requiresPolling = hasPollingControls;
194
+ /**
195
+ * @deprecated This function is no longer needed as extended mode handles user actions differently
196
+ */
197
+ const requiresUserAction = (result) => false;
198
+ exports.requiresUserAction = requiresUserAction;
@@ -53,6 +53,11 @@ class AuthModal {
53
53
  */
54
54
  showQRCode(qrCodeData, statusMessage = 'Scan QR code with your phone') {
55
55
  console.log('[Modal] showQRCode called with:', qrCodeData);
56
+ // If modal is already open, don't recreate it
57
+ if (this.isOpen) {
58
+ console.log('[Modal] Modal already open, skipping recreation');
59
+ return;
60
+ }
56
61
  // Check if it's the new dual-platform format with VALID Android QR code
57
62
  if (typeof qrCodeData === 'object' && qrCodeData.iosQRCode) {
58
63
  const hasValidAndroidQR = qrCodeData.androidQRCode &&
@@ -62,6 +67,8 @@ class AuthModal {
62
67
  if (hasValidAndroidQR) {
63
68
  console.log('[Modal] Using dual-platform modal');
64
69
  this.createDualPlatformQRModal(qrCodeData, statusMessage);
70
+ // Note: createDualPlatformQRModal calls show() internally
71
+ return;
65
72
  }
66
73
  else {
67
74
  console.log('[Modal] Android QR missing/empty, using single iOS QR');
@@ -122,6 +129,8 @@ class AuthModal {
122
129
  <p class="glide-auth-status" id="glide-platform-message">Scan with your iPhone to authenticate</p>
123
130
  </div>
124
131
  `);
132
+ // IMPORTANT: Call show() to actually display the modal!
133
+ this.show();
125
134
  }
126
135
  /**
127
136
  * Sets a callback to be called when the modal is cancelled/closed
@@ -295,7 +304,11 @@ class AuthModal {
295
304
  // Add close button handler
296
305
  const closeBtn = this.container.querySelector('.glide-auth-close');
297
306
  if (closeBtn) {
298
- closeBtn.addEventListener('click', () => this.close());
307
+ closeBtn.addEventListener('click', () => {
308
+ var _a;
309
+ (_a = this.closeCallback) === null || _a === void 0 ? void 0 : _a.call(this); // Call cancellation callback if set
310
+ this.close();
311
+ });
299
312
  }
300
313
  // Add backdrop click handler
301
314
  this.backdrop.addEventListener('click', (e) => {
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SDK_VERSION = void 0;
4
4
  // SDK version - injected at build time
5
- exports.SDK_VERSION = '4.4.8-beta.1';
5
+ exports.SDK_VERSION = '4.4.8-beta.3';
@@ -16,7 +16,7 @@ export declare function usePhoneAuth(config?: UsePhoneAuthOptions): {
16
16
  preparePhoneRequest: (options: PhoneAuthOptions) => Promise<import("../../core/phone-auth").PrepareResponse>;
17
17
  invokeSecurePrompt: (prepareResponse: any) => Promise<{
18
18
  [aggregator_id: string]: string | string[];
19
- } | import("../../core/phone-auth").HeadlessResult>;
19
+ } | import("../../core/phone-auth").AuthCredential | import("../../core/phone-auth").AnyExtendedResponse>;
20
20
  getPhoneNumberCredential: (credentialResponse: any, session: any) => Promise<import("../../core/phone-auth").GetPhoneNumberResponse>;
21
21
  verifyPhoneNumberCredential: (credentialResponse: any, session: any) => Promise<import("../../core/phone-auth").VerifyPhoneNumberResponse>;
22
22
  client: PhoneAuthClient;
@@ -15,7 +15,7 @@ export declare function useClient<T>(config: ClientConfig): {
15
15
  getPhoneNumberComplete: (options?: Omit<PhoneAuthOptions, "use_case" | "phone_number">) => Promise<PhoneAuthResult>;
16
16
  verifyPhoneNumberComplete: (phoneNumber: string, options?: Omit<PhoneAuthOptions, "use_case" | "phone_number">) => Promise<PhoneAuthResult>;
17
17
  preparePhoneRequest: (options: PhoneAuthOptions) => Promise<import("../../core/phone-auth").PrepareResponse>;
18
- invokeSecurePrompt: (prepareResponse: import("../../core/phone-auth").PrepareResponse, options?: import("../../core/phone-auth").InvokeOptions | import("../..").DesktopAuthOptions) => Promise<import("../../core/phone-auth").SecureCredentialResponse["vp_token"] | import("../../core/phone-auth").HeadlessResult>;
18
+ invokeSecurePrompt: (prepareResponse: import("../../core/phone-auth").PrepareResponse, options?: import("../../core/phone-auth").InvokeOptions | import("../..").DesktopAuthOptions) => Promise<import("../../core/phone-auth").AuthCredential | import("../../core/phone-auth").SecureCredentialResponse["vp_token"] | import("../../core/phone-auth").AnyExtendedResponse>;
19
19
  getPhoneNumber: (credentialResponse: import("../../core/phone-auth").SecureCredentialResponse["vp_token"] | string, session: import("../../core/phone-auth").SessionInfo) => Promise<import("../../core/phone-auth").GetPhoneNumberResponse>;
20
20
  verifyPhoneNumber: (credentialResponse: import("../../core/phone-auth").SecureCredentialResponse["vp_token"] | string, session: import("../../core/phone-auth").SessionInfo) => Promise<import("../../core/phone-auth").VerifyPhoneNumberResponse>;
21
21
  };
@@ -107,9 +107,9 @@ export declare function useClient<T>(config: ClientConfig): {
107
107
  getPhoneNumber: (options?: Omit<PhoneAuthOptions, "useCase" | "phoneNumber">) => Promise<PhoneAuthResult>;
108
108
  verifyPhoneNumber: (phoneNumber: string, options?: Omit<PhoneAuthOptions, "useCase" | "phoneNumber">) => Promise<PhoneAuthResult>;
109
109
  preparePhoneRequest: (options: Parameters<(options: PhoneAuthOptions) => Promise<import("../../core/phone-auth").PrepareResponse>>[0]) => Promise<import("../../core/phone-auth").PrepareResponse>;
110
- invokeSecurePrompt: (request: Parameters<(prepareResponse: import("../../core/phone-auth").PrepareResponse, options?: import("../../core/phone-auth").InvokeOptions | import("../..").DesktopAuthOptions) => Promise<import("../../core/phone-auth").SecureCredentialResponse["vp_token"] | import("../../core/phone-auth").HeadlessResult>>[0]) => Promise<{
110
+ invokeSecurePrompt: (request: Parameters<(prepareResponse: import("../../core/phone-auth").PrepareResponse, options?: import("../../core/phone-auth").InvokeOptions | import("../..").DesktopAuthOptions) => Promise<import("../../core/phone-auth").AuthCredential | import("../../core/phone-auth").SecureCredentialResponse["vp_token"] | import("../../core/phone-auth").AnyExtendedResponse>>[0]) => Promise<{
111
111
  [aggregator_id: string]: string | string[];
112
- } | import("../../core/phone-auth").HeadlessResult>;
112
+ } | import("../../core/phone-auth").AuthCredential | import("../../core/phone-auth").AnyExtendedResponse>;
113
113
  };
114
114
  };
115
115
  export declare const useVueClient: typeof useClient;
@@ -87,7 +87,7 @@ export declare function usePhoneAuth(config?: UsePhoneAuthOptions): {
87
87
  }>;
88
88
  reset: () => void;
89
89
  preparePhoneRequest: (options: PhoneAuthOptions) => Promise<API.PrepareResponse>;
90
- invokeSecurePrompt: (prepareResponse: API.PrepareResponse, options?: API.InvokeOptions | import("../..").DesktopAuthOptions) => Promise<API.SecureCredentialResponse["vp_token"] | API.HeadlessResult>;
90
+ invokeSecurePrompt: (prepareResponse: API.PrepareResponse, options?: API.InvokeOptions | import("../..").DesktopAuthOptions) => Promise<API.AuthCredential | API.SecureCredentialResponse["vp_token"] | API.AnyExtendedResponse>;
91
91
  getPhoneNumberCredential: (credentialResponse: API.SecureCredentialResponse["vp_token"] | string, session: API.SessionInfo) => Promise<API.GetPhoneNumberResponse>;
92
92
  verifyPhoneNumberCredential: (credentialResponse: API.SecureCredentialResponse["vp_token"] | string, session: API.SessionInfo) => Promise<API.VerifyPhoneNumberResponse>;
93
93
  client: PhoneAuthClient;
@@ -386,16 +386,30 @@ export declare function isLinkData(data: any): data is LinkData;
386
386
  * Check if response is an error
387
387
  */
388
388
  export declare function isErrorResponse(response: any): response is ErrorResponse;
389
+ /**
390
+ * Execution mode for authentication flow
391
+ */
392
+ export type ExecutionMode = 'standard' | 'extended';
389
393
  /**
390
394
  * Options for invokeSecurePrompt to control UI behavior
391
395
  */
392
396
  export interface InvokeOptions {
393
397
  /**
394
- * If true, returns raw data without showing any UI
395
- * If false/undefined, shows appropriate UI (modal/button)
398
+ * Prevents SDK from showing its own UI components.
399
+ * Only affects Desktop strategy (shows modal by default).
400
+ * Link/TS43 never show SDK UI, so this has no effect on them.
401
+ *
396
402
  * @default false
397
403
  */
398
- headless?: boolean;
404
+ preventDefaultUI?: boolean;
405
+ /**
406
+ * Controls the response type:
407
+ * - 'standard': Returns credential when complete (Promise<AuthCredential>)
408
+ * - 'extended': Returns control methods + credential promise
409
+ *
410
+ * @default 'standard'
411
+ */
412
+ executionMode?: ExecutionMode;
399
413
  /**
400
414
  * UI theme to use for modals and components
401
415
  * @default 'dark'
@@ -420,7 +434,7 @@ export interface InvokeOptions {
420
434
  error?: any;
421
435
  }) => void;
422
436
  /**
423
- * Options for customizing the modal UI (only used when headless=false)
437
+ * Options for customizing the modal UI (only used when preventDefaultUI=false)
424
438
  * Simplified to only include commonly used options
425
439
  */
426
440
  modalOptions?: {
@@ -440,7 +454,7 @@ export interface InvokeOptions {
440
454
  closeOnEscape?: boolean;
441
455
  };
442
456
  /**
443
- * Callback functions for UI events (only used when headless=false)
457
+ * Callback functions for UI events (only used when preventDefaultUI=false)
444
458
  */
445
459
  callbacks?: {
446
460
  /** Called when modal is opened */
@@ -454,35 +468,106 @@ export interface InvokeOptions {
454
468
  /** Called on error */
455
469
  onError?: (error: Error) => void;
456
470
  };
457
- }
458
- /**
459
- * Result returned in headless mode
460
- */
461
- export interface HeadlessResult {
462
- /** The authentication strategy being used */
463
- strategy: AuthenticationStrategy;
464
- /** For Link strategy: the URL to open */
465
- url?: string;
466
- /** For Desktop strategy: the QR code data */
467
- qrCode?: string;
468
- /** For TS43: the credential request data */
469
- credentialRequest?: any;
470
471
  /**
471
- * Promise that resolves when authentication completes
472
- * - For Link/Desktop: polls for completion
473
- * - For TS43: not used (trigger returns credential directly)
472
+ * Custom polling endpoint for Desktop/Link strategies
473
+ * Overrides the SDK configured endpoint and backend-provided status URL
474
+ * Useful for testing or using a proxy endpoint
475
+ * @example '/api/phone-auth/status' or 'https://custom-polling.example.com/status'
476
+ */
477
+ pollingEndpoint?: string;
478
+ /**
479
+ * Custom polling interval in milliseconds
480
+ * @default 2000 (2 seconds)
474
481
  */
475
- pollingPromise?: Promise<any>;
482
+ pollingInterval?: number;
476
483
  /**
477
- * Function to trigger authentication action
478
- * - For Link: opens App Clip URL (can be called multiple times)
479
- * - For TS43: invokes Digital Credentials API (returns credential)
480
- * - For Desktop: not used (QR code is shown)
484
+ * Maximum number of polling attempts before timeout
485
+ * @default 30 (1 minute with 2s interval)
481
486
  */
482
- trigger?: (() => void) | (() => Promise<any>);
487
+ maxPollingAttempts?: number;
488
+ }
489
+ /**
490
+ * Authentication credential result
491
+ */
492
+ export interface AuthCredential {
493
+ /** Authentication credential token */
494
+ credential: string;
495
+ /** Phone number if available */
496
+ phone_number?: PhoneNumber;
483
497
  /** Session information */
484
498
  session: SessionInfo;
499
+ /** Whether authentication was successful */
500
+ authenticated: boolean;
485
501
  }
502
+ /**
503
+ * Base interface for extended mode responses
504
+ */
505
+ export interface ExtendedResponse {
506
+ /** Authentication strategy */
507
+ strategy: AuthenticationStrategy;
508
+ /** Session information */
509
+ session: SessionInfo;
510
+ /** Promise that resolves to the credential */
511
+ credential: Promise<AuthCredential>;
512
+ /** Cancel the authentication flow */
513
+ cancel: () => void;
514
+ }
515
+ /**
516
+ * Extended response for Desktop strategy
517
+ */
518
+ export interface DesktopExtendedResponse extends ExtendedResponse {
519
+ strategy: 'desktop';
520
+ /** QR code data for custom UI */
521
+ qr_code_data: {
522
+ /** iOS QR code image */
523
+ ios_qr_image?: string;
524
+ /** Android QR code image */
525
+ android_qr_image?: string;
526
+ /** Generic QR code image */
527
+ qr_code?: string;
528
+ /** Challenge pattern */
529
+ challenge?: any;
530
+ };
531
+ /** Start or restart polling */
532
+ start_polling: () => Promise<AuthCredential>;
533
+ /** Stop polling */
534
+ stop_polling: () => void;
535
+ /** Whether currently polling */
536
+ is_polling: boolean;
537
+ /** Modal reference if UI was shown */
538
+ modal_ref?: any;
539
+ }
540
+ /**
541
+ * Extended response for Link strategy
542
+ */
543
+ export interface LinkExtendedResponse extends ExtendedResponse {
544
+ strategy: 'link';
545
+ /** Additional data for Link strategy */
546
+ data: {
547
+ /** App URL that was opened */
548
+ app_url: string;
549
+ };
550
+ /** Re-open the app link */
551
+ trigger: () => void;
552
+ /** Start or restart polling */
553
+ start_polling?: () => Promise<AuthCredential>;
554
+ /** Stop polling */
555
+ stop_polling?: () => void;
556
+ /** Whether currently polling */
557
+ is_polling?: boolean;
558
+ }
559
+ /**
560
+ * Extended response for TS43 strategy
561
+ */
562
+ export interface TS43ExtendedResponse extends ExtendedResponse {
563
+ strategy: 'ts43';
564
+ /** Re-trigger credential request */
565
+ trigger: () => Promise<void>;
566
+ }
567
+ /**
568
+ * Combined type for all extended responses
569
+ */
570
+ export type AnyExtendedResponse = DesktopExtendedResponse | LinkExtendedResponse | TS43ExtendedResponse;
486
571
  declare const _default: {
487
572
  USE_CASE: {
488
573
  readonly GET_PHONE_NUMBER: "GetPhoneNumber";
@@ -1,4 +1,4 @@
1
- import type { PrepareResponse, GetPhoneNumberResponse, VerifyPhoneNumberResponse, SecureCredentialResponse, SessionInfo, InvokeOptions, HeadlessResult } from './api-types';
1
+ import type { PrepareResponse, GetPhoneNumberResponse, VerifyPhoneNumberResponse, SecureCredentialResponse, SessionInfo, InvokeOptions, AuthCredential, AnyExtendedResponse } from './api-types';
2
2
  import type { AuthConfig, PhoneAuthOptions, PhoneAuthResult } from './types';
3
3
  import type { DesktopAuthOptions } from './strategies/desktop';
4
4
  export declare class PhoneAuthClient {
@@ -86,25 +86,27 @@ export declare class PhoneAuthClient {
86
86
  * });
87
87
  * ```
88
88
  *
89
- * @example Headless Mode (returns data)
89
+ * @example Extended Mode (returns control methods)
90
90
  * ```typescript
91
- * // Get raw data without showing UI
91
+ * // Get control methods for custom implementation
92
92
  * const result = await phoneAuth.invokeSecurePrompt(prepareResult, {
93
- * headless: true
93
+ * executionMode: 'extended',
94
+ * preventDefaultUI: true // Desktop: no modal
94
95
  * });
95
96
  *
96
- * if (result.strategy === 'link') {
97
- * // Open URL yourself
98
- * window.open(result.url);
99
- * await result.pollingPromise; // Wait for completion
97
+ * if (result.strategy === 'desktop') {
98
+ * // Show custom QR UI
99
+ * showCustomQR(result.qr_code_data);
100
+ * // Start polling
101
+ * await result.start_polling();
100
102
  * }
101
103
  * ```
102
104
  *
103
105
  * @param prepareResponse - Response from prepare() with strategy and data
104
- * @param options - Control UI behavior or enable headless mode
105
- * @returns Credential or HeadlessResult based on mode
106
+ * @param options - Control UI behavior and response type
107
+ * @returns Credential or ExtendedResponse based on executionMode
106
108
  */
107
- invokeSecurePrompt(prepareResponse: PrepareResponse, options?: InvokeOptions | DesktopAuthOptions): Promise<SecureCredentialResponse['vp_token'] | HeadlessResult>;
109
+ invokeSecurePrompt(prepareResponse: PrepareResponse, options?: InvokeOptions | DesktopAuthOptions): Promise<AuthCredential | SecureCredentialResponse['vp_token'] | AnyExtendedResponse>;
108
110
  /**
109
111
  * Step 3A: Get phone number from credential
110
112
  *