@glideidentity/web-client-sdk 4.4.8 → 4.4.10

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.
@@ -513,7 +513,8 @@ export interface ExtendedResponse {
513
513
  cancel: () => void;
514
514
  }
515
515
  /**
516
- * Extended response for Desktop strategy
516
+ * Extended response for Desktop strategy.
517
+ * Note: Polling starts immediately even with preventDefaultUI: true (consistent with Link strategy)
517
518
  */
518
519
  export interface DesktopExtendedResponse extends ExtendedResponse {
519
520
  strategy: 'desktop';
@@ -528,7 +529,7 @@ export interface DesktopExtendedResponse extends ExtendedResponse {
528
529
  /** Challenge pattern */
529
530
  challenge?: any;
530
531
  };
531
- /** Start or restart polling */
532
+ /** Returns the existing polling promise (polling starts immediately) */
532
533
  start_polling: () => Promise<AuthCredential>;
533
534
  /** Stop polling */
534
535
  stop_polling: () => void;
@@ -531,19 +531,13 @@ class PhoneAuthClient {
531
531
  console.log('[PhoneAuth] Session cache size:', this.sessionCache.size);
532
532
  console.log('[PhoneAuth] Retry count:', this.retryCount);
533
533
  console.log('[PhoneAuth] PrepareResponse received:', JSON.stringify(plainResponse, null, 2));
534
- // Check if we're using new InvokeOptions format
535
- // Properly detect InvokeOptions by checking for any of its properties
536
- const invokeOptions = options && ('preventDefaultUI' in options ||
537
- 'executionMode' in options ||
538
- 'theme' in options ||
539
- 'modalOptions' in options ||
540
- 'callbacks' in options) ? options : undefined;
541
- // Get configuration from options
534
+ // Treat options as InvokeOptions (the modern format)
535
+ // Legacy DesktopAuthOptions properties will still work through property access
536
+ const opts = options;
537
+ // Get configuration from options - access properties directly
542
538
  const strategy = plainResponse.authentication_strategy;
543
- const preventDefaultUI = (_a = invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.preventDefaultUI) !== null && _a !== void 0 ? _a : false;
544
- const executionMode = (_b = invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.executionMode) !== null && _b !== void 0 ? _b : 'standard';
545
- // DesktopAuthOptions is only used if not InvokeOptions
546
- const desktopOptions = options && !invokeOptions ? options : undefined;
539
+ const preventDefaultUI = (_a = opts === null || opts === void 0 ? void 0 : opts.preventDefaultUI) !== null && _a !== void 0 ? _a : false;
540
+ const executionMode = (_b = opts === null || opts === void 0 ? void 0 : opts.executionMode) !== null && _b !== void 0 ? _b : 'standard';
547
541
  // Handle based on authentication strategy
548
542
  if (plainResponse.authentication_strategy === API.AUTHENTICATION_STRATEGY.TS43) {
549
543
  // Check browser support for TS43 strategy which requires Digital Credentials API
@@ -665,14 +659,14 @@ class PhoneAuthClient {
665
659
  var _a, _b;
666
660
  try {
667
661
  const result = yield triggerTS43();
668
- (_a = invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.onTriggerAttempt) === null || _a === void 0 ? void 0 : _a.call(invokeOptions, {
662
+ (_a = opts === null || opts === void 0 ? void 0 : opts.onTriggerAttempt) === null || _a === void 0 ? void 0 : _a.call(opts, {
669
663
  strategy: API.AUTHENTICATION_STRATEGY.TS43,
670
664
  success: true
671
665
  });
672
666
  return result;
673
667
  }
674
668
  catch (error) {
675
- (_b = invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.onTriggerAttempt) === null || _b === void 0 ? void 0 : _b.call(invokeOptions, {
669
+ (_b = opts === null || opts === void 0 ? void 0 : opts.onTriggerAttempt) === null || _b === void 0 ? void 0 : _b.call(opts, {
676
670
  strategy: API.AUTHENTICATION_STRATEGY.TS43,
677
671
  success: false,
678
672
  error
@@ -763,11 +757,10 @@ class PhoneAuthClient {
763
757
  qr_code: ((_k = desktopData.data) === null || _k === void 0 ? void 0 : _k.qr_code_image) || desktopData.qr_code_image || desktopData.qr_code,
764
758
  challenge: (_l = desktopData.data) === null || _l === void 0 ? void 0 : _l.challenge
765
759
  };
766
- // Polling options
767
- const pollingEndpointToUse = (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.pollingEndpoint) ||
768
- (desktopOptions === null || desktopOptions === void 0 ? void 0 : desktopOptions.pollingEndpoint) ||
760
+ // Polling options - gather from any options format
761
+ const pollingEndpointToUse = (opts === null || opts === void 0 ? void 0 : opts.pollingEndpoint) ||
769
762
  ((_m = this.config.endpoints) === null || _m === void 0 ? void 0 : _m.polling);
770
- const pollingOptions = Object.assign(Object.assign({}, desktopOptions), { pollingEndpoint: pollingEndpointToUse, pollingInterval: (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.pollingInterval) || (desktopOptions === null || desktopOptions === void 0 ? void 0 : desktopOptions.pollingInterval) || this.config.pollingInterval || 2000, maxPollingAttempts: (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.maxPollingAttempts) || (desktopOptions === null || desktopOptions === void 0 ? void 0 : desktopOptions.maxPollingAttempts) || this.config.maxPollingAttempts || 30, onQRCodeReady: undefined, onStatusUpdate: undefined });
763
+ const pollingOptions = Object.assign(Object.assign({}, opts), { pollingEndpoint: pollingEndpointToUse, pollingInterval: (opts === null || opts === void 0 ? void 0 : opts.pollingInterval) || this.config.pollingInterval || 2000, maxPollingAttempts: (opts === null || opts === void 0 ? void 0 : opts.maxPollingAttempts) || this.config.maxPollingAttempts || 30, onQRCodeReady: undefined, onStatusUpdate: undefined });
771
764
  // Decide whether to show modal based on preventDefaultUI
772
765
  const showModal = !preventDefaultUI;
773
766
  let modal;
@@ -776,13 +769,12 @@ class PhoneAuthClient {
776
769
  preventDefaultUI,
777
770
  showModal,
778
771
  executionMode,
779
- hasInvokeOptions: !!invokeOptions,
780
- hasDesktopOptions: !!desktopOptions
772
+ hasOptions: !!opts
781
773
  });
782
774
  if (showModal) {
783
775
  console.log('[Desktop] Creating modal with QR data:', qrCodeData);
784
776
  // Create and setup modal
785
- modal = new modal_1.AuthModal(invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.modalOptions, invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.callbacks);
777
+ modal = new modal_1.AuthModal(opts === null || opts === void 0 ? void 0 : opts.modalOptions, opts === null || opts === void 0 ? void 0 : opts.callbacks);
786
778
  modal.setCloseCallback(() => {
787
779
  this.log('Desktop QR modal closed by user, cancelling polling');
788
780
  handler.cancel();
@@ -830,41 +822,20 @@ class PhoneAuthClient {
830
822
  // Handle based on execution mode
831
823
  if (executionMode === 'extended') {
832
824
  // Extended mode - return control methods
833
- let credentialResolve = null;
834
- let credentialReject = null;
835
- let pollingStarted = false;
836
- // Create a promise that will remain pending until polling starts
825
+ // Create a promise and always start polling immediately
837
826
  const credentialPromise = new Promise((resolve, reject) => {
838
- credentialResolve = resolve;
839
- credentialReject = reject;
840
- // If modal is shown, start polling immediately
841
- if (showModal) {
842
- pollingStarted = true;
843
- startPolling()
844
- .then(resolve)
845
- .catch(reject);
846
- }
847
- // Otherwise, promise remains pending until start_polling() is called
827
+ // Always start polling immediately in extended mode (consistent with Link)
828
+ // This prevents the "unresolved promise trap" where developers might await
829
+ // the credential before calling start_polling()
830
+ startPolling()
831
+ .then(resolve)
832
+ .catch(reject);
848
833
  });
849
834
  // Create wrapped functions
850
835
  const wrappedStartPolling = () => __awaiter(this, void 0, void 0, function* () {
851
- if (pollingStarted) {
852
- throw this.createError(error_utils_1.PhoneAuthErrorCode.INVALID_SESSION_STATE, 'Polling has already been started');
853
- }
854
- pollingStarted = true;
855
- try {
856
- const result = yield startPolling();
857
- if (credentialResolve) {
858
- credentialResolve(result);
859
- }
860
- return result;
861
- }
862
- catch (err) {
863
- if (credentialReject) {
864
- credentialReject(err);
865
- }
866
- throw err;
867
- }
836
+ // Polling has already started automatically in extended mode
837
+ // This method just returns the existing credential promise for consistency
838
+ return credentialPromise;
868
839
  });
869
840
  const wrappedStopPolling = () => {
870
841
  handler.cleanup();
@@ -876,10 +847,7 @@ class PhoneAuthClient {
876
847
  handler.cleanup();
877
848
  if (modal)
878
849
  modal.close();
879
- // Reject the credential promise if it's still pending
880
- if (!pollingStarted && credentialReject) {
881
- credentialReject(this.createError(error_utils_1.PhoneAuthErrorCode.USER_DENIED, 'Desktop authentication cancelled by user'));
882
- }
850
+ // The credential promise will be rejected by the handler.cancel() call
883
851
  };
884
852
  // Create the response object with a getter for is_polling
885
853
  const response = {
@@ -937,14 +905,14 @@ class PhoneAuthClient {
937
905
  var _a, _b;
938
906
  try {
939
907
  window.open(linkData.url, '_blank');
940
- (_a = invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.onTriggerAttempt) === null || _a === void 0 ? void 0 : _a.call(invokeOptions, {
908
+ (_a = opts === null || opts === void 0 ? void 0 : opts.onTriggerAttempt) === null || _a === void 0 ? void 0 : _a.call(opts, {
941
909
  strategy: API.AUTHENTICATION_STRATEGY.LINK,
942
910
  url: linkData.url,
943
911
  success: true
944
912
  });
945
913
  }
946
914
  catch (error) {
947
- (_b = invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.onTriggerAttempt) === null || _b === void 0 ? void 0 : _b.call(invokeOptions, {
915
+ (_b = opts === null || opts === void 0 ? void 0 : opts.onTriggerAttempt) === null || _b === void 0 ? void 0 : _b.call(opts, {
948
916
  strategy: API.AUTHENTICATION_STRATEGY.LINK,
949
917
  url: linkData.url,
950
918
  success: false,
@@ -954,71 +922,75 @@ class PhoneAuthClient {
954
922
  };
955
923
  // Link always auto-opens the app (no SDK UI by default)
956
924
  // Open immediately to preserve user gesture context
957
- if ((invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.autoTrigger) !== false) {
925
+ if ((opts === null || opts === void 0 ? void 0 : opts.autoTrigger) !== false) {
958
926
  triggerLink();
959
927
  }
960
928
  // Start polling in the background
961
929
  console.log('[PhoneAuth Client] Link polling config:', {
962
- fromInvokeOptions: invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.pollingEndpoint,
930
+ fromOptions: opts === null || opts === void 0 ? void 0 : opts.pollingEndpoint,
963
931
  fromClientConfig: (_o = this.config.endpoints) === null || _o === void 0 ? void 0 : _o.polling,
964
- finalPollingEndpoint: (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.pollingEndpoint) || ((_p = this.config.endpoints) === null || _p === void 0 ? void 0 : _p.polling)
932
+ finalPollingEndpoint: (opts === null || opts === void 0 ? void 0 : opts.pollingEndpoint) || ((_p = this.config.endpoints) === null || _p === void 0 ? void 0 : _p.polling)
965
933
  });
966
934
  const pollingOptions = {
967
- pollingEndpoint: (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.pollingEndpoint) || ((_q = this.config.endpoints) === null || _q === void 0 ? void 0 : _q.polling),
968
- pollingInterval: (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.pollingInterval) || this.config.pollingInterval || 2000,
969
- maxPollingAttempts: (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.maxPollingAttempts) || this.config.maxPollingAttempts || 30,
935
+ pollingEndpoint: (opts === null || opts === void 0 ? void 0 : opts.pollingEndpoint) || ((_q = this.config.endpoints) === null || _q === void 0 ? void 0 : _q.polling),
936
+ pollingInterval: (opts === null || opts === void 0 ? void 0 : opts.pollingInterval) || this.config.pollingInterval || 2000,
937
+ maxPollingAttempts: (opts === null || opts === void 0 ? void 0 : opts.maxPollingAttempts) || this.config.maxPollingAttempts || 30,
970
938
  onLinkOpened: undefined,
971
939
  onStatusUpdate: undefined
972
940
  };
973
941
  console.log('[PhoneAuth Client] Final Link polling options:', pollingOptions);
974
942
  // Handle based on execution mode
975
943
  if (executionMode === 'extended') {
976
- // Extended mode - return control methods without starting polling immediately
977
- let credentialResolve = null;
978
- let credentialReject = null;
944
+ // Extended mode - return control methods and start polling immediately
979
945
  let pollingStarted = false;
980
946
  let pollingPromise = null;
981
- // Create a pending promise that will be resolved when polling completes
982
- const credentialPromise = new Promise((resolve, reject) => {
983
- credentialResolve = resolve;
984
- credentialReject = reject;
947
+ // Start polling immediately (Link always polls automatically unlike Desktop)
948
+ pollingPromise = handler.invoke(plainResponse, pollingOptions);
949
+ pollingStarted = true;
950
+ // Create credential promise from the polling result
951
+ const credentialPromise = pollingPromise.then(result => {
952
+ if (result.authenticated && result.credential) {
953
+ return {
954
+ credential: result.credential,
955
+ session: plainResponse.session,
956
+ authenticated: true
957
+ };
958
+ }
959
+ else {
960
+ throw this.createError(error_utils_1.PhoneAuthErrorCode.USER_DENIED, result.error || 'Link authentication failed');
961
+ }
985
962
  });
986
- // Function to start polling (only once)
963
+ // Function to restart polling (for retry scenarios)
987
964
  const startPolling = () => __awaiter(this, void 0, void 0, function* () {
988
- if (pollingStarted) {
989
- throw this.createError(error_utils_1.PhoneAuthErrorCode.INVALID_SESSION_STATE, 'Polling has already been started');
990
- }
991
- pollingStarted = true;
992
- try {
993
- // Store the polling promise to ensure we use the same one
965
+ if (!pollingStarted) {
966
+ // This is here for API consistency, but for Link it's already polling
967
+ pollingStarted = true;
994
968
  if (!pollingPromise) {
995
969
  pollingPromise = handler.invoke(plainResponse, pollingOptions);
996
970
  }
997
971
  const result = yield pollingPromise;
998
972
  if (result.authenticated && result.credential) {
999
- const authCredential = {
973
+ return {
1000
974
  credential: result.credential,
1001
975
  session: plainResponse.session,
1002
976
  authenticated: true
1003
977
  };
1004
- if (credentialResolve) {
1005
- credentialResolve(authCredential);
1006
- }
1007
- return authCredential;
1008
978
  }
1009
979
  else {
1010
- const error = this.createError(error_utils_1.PhoneAuthErrorCode.USER_DENIED, result.error || 'Link authentication failed');
1011
- if (credentialReject) {
1012
- credentialReject(error);
1013
- }
1014
- throw error;
980
+ throw this.createError(error_utils_1.PhoneAuthErrorCode.USER_DENIED, result.error || 'Link authentication failed');
1015
981
  }
1016
982
  }
1017
- catch (err) {
1018
- if (credentialReject) {
1019
- credentialReject(err);
1020
- }
1021
- throw err;
983
+ // If already polling, just return the existing promise result
984
+ const result = yield pollingPromise;
985
+ if (result.authenticated && result.credential) {
986
+ return {
987
+ credential: result.credential,
988
+ session: plainResponse.session,
989
+ authenticated: true
990
+ };
991
+ }
992
+ else {
993
+ throw this.createError(error_utils_1.PhoneAuthErrorCode.USER_DENIED, result.error || 'Link authentication failed');
1022
994
  }
1023
995
  });
1024
996
  const response = {
@@ -1036,10 +1008,8 @@ class PhoneAuthClient {
1036
1008
  cancel: () => {
1037
1009
  handler.cancel();
1038
1010
  handler.cleanup();
1039
- // Reject the credential promise if polling hasn't started
1040
- if (!pollingStarted && credentialReject) {
1041
- credentialReject(this.createError(error_utils_1.PhoneAuthErrorCode.USER_DENIED, 'Link authentication cancelled by user'));
1042
- }
1011
+ // Note: For Link, polling is already started, so the promise
1012
+ // will be rejected by the handler.cancel() call
1043
1013
  },
1044
1014
  // This will be replaced with a getter
1045
1015
  is_polling: false // Initial value, will be overridden by getter
@@ -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';
5
+ exports.SDK_VERSION = '4.4.10';
@@ -513,7 +513,8 @@ export interface ExtendedResponse {
513
513
  cancel: () => void;
514
514
  }
515
515
  /**
516
- * Extended response for Desktop strategy
516
+ * Extended response for Desktop strategy.
517
+ * Note: Polling starts immediately even with preventDefaultUI: true (consistent with Link strategy)
517
518
  */
518
519
  export interface DesktopExtendedResponse extends ExtendedResponse {
519
520
  strategy: 'desktop';
@@ -528,7 +529,7 @@ export interface DesktopExtendedResponse extends ExtendedResponse {
528
529
  /** Challenge pattern */
529
530
  challenge?: any;
530
531
  };
531
- /** Start or restart polling */
532
+ /** Returns the existing polling promise (polling starts immediately) */
532
533
  start_polling: () => Promise<AuthCredential>;
533
534
  /** Stop polling */
534
535
  stop_polling: () => void;
@@ -495,19 +495,13 @@ export class PhoneAuthClient {
495
495
  console.log('[PhoneAuth] Session cache size:', this.sessionCache.size);
496
496
  console.log('[PhoneAuth] Retry count:', this.retryCount);
497
497
  console.log('[PhoneAuth] PrepareResponse received:', JSON.stringify(plainResponse, null, 2));
498
- // Check if we're using new InvokeOptions format
499
- // Properly detect InvokeOptions by checking for any of its properties
500
- const invokeOptions = options && ('preventDefaultUI' in options ||
501
- 'executionMode' in options ||
502
- 'theme' in options ||
503
- 'modalOptions' in options ||
504
- 'callbacks' in options) ? options : undefined;
505
- // Get configuration from options
498
+ // Treat options as InvokeOptions (the modern format)
499
+ // Legacy DesktopAuthOptions properties will still work through property access
500
+ const opts = options;
501
+ // Get configuration from options - access properties directly
506
502
  const strategy = plainResponse.authentication_strategy;
507
- const preventDefaultUI = (_a = invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.preventDefaultUI) !== null && _a !== void 0 ? _a : false;
508
- const executionMode = (_b = invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.executionMode) !== null && _b !== void 0 ? _b : 'standard';
509
- // DesktopAuthOptions is only used if not InvokeOptions
510
- const desktopOptions = options && !invokeOptions ? options : undefined;
503
+ const preventDefaultUI = (_a = opts === null || opts === void 0 ? void 0 : opts.preventDefaultUI) !== null && _a !== void 0 ? _a : false;
504
+ const executionMode = (_b = opts === null || opts === void 0 ? void 0 : opts.executionMode) !== null && _b !== void 0 ? _b : 'standard';
511
505
  // Handle based on authentication strategy
512
506
  if (plainResponse.authentication_strategy === API.AUTHENTICATION_STRATEGY.TS43) {
513
507
  // Check browser support for TS43 strategy which requires Digital Credentials API
@@ -629,14 +623,14 @@ export class PhoneAuthClient {
629
623
  var _a, _b;
630
624
  try {
631
625
  const result = yield triggerTS43();
632
- (_a = invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.onTriggerAttempt) === null || _a === void 0 ? void 0 : _a.call(invokeOptions, {
626
+ (_a = opts === null || opts === void 0 ? void 0 : opts.onTriggerAttempt) === null || _a === void 0 ? void 0 : _a.call(opts, {
633
627
  strategy: API.AUTHENTICATION_STRATEGY.TS43,
634
628
  success: true
635
629
  });
636
630
  return result;
637
631
  }
638
632
  catch (error) {
639
- (_b = invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.onTriggerAttempt) === null || _b === void 0 ? void 0 : _b.call(invokeOptions, {
633
+ (_b = opts === null || opts === void 0 ? void 0 : opts.onTriggerAttempt) === null || _b === void 0 ? void 0 : _b.call(opts, {
640
634
  strategy: API.AUTHENTICATION_STRATEGY.TS43,
641
635
  success: false,
642
636
  error
@@ -727,11 +721,10 @@ export class PhoneAuthClient {
727
721
  qr_code: ((_k = desktopData.data) === null || _k === void 0 ? void 0 : _k.qr_code_image) || desktopData.qr_code_image || desktopData.qr_code,
728
722
  challenge: (_l = desktopData.data) === null || _l === void 0 ? void 0 : _l.challenge
729
723
  };
730
- // Polling options
731
- const pollingEndpointToUse = (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.pollingEndpoint) ||
732
- (desktopOptions === null || desktopOptions === void 0 ? void 0 : desktopOptions.pollingEndpoint) ||
724
+ // Polling options - gather from any options format
725
+ const pollingEndpointToUse = (opts === null || opts === void 0 ? void 0 : opts.pollingEndpoint) ||
733
726
  ((_m = this.config.endpoints) === null || _m === void 0 ? void 0 : _m.polling);
734
- const pollingOptions = Object.assign(Object.assign({}, desktopOptions), { pollingEndpoint: pollingEndpointToUse, pollingInterval: (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.pollingInterval) || (desktopOptions === null || desktopOptions === void 0 ? void 0 : desktopOptions.pollingInterval) || this.config.pollingInterval || 2000, maxPollingAttempts: (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.maxPollingAttempts) || (desktopOptions === null || desktopOptions === void 0 ? void 0 : desktopOptions.maxPollingAttempts) || this.config.maxPollingAttempts || 30, onQRCodeReady: undefined, onStatusUpdate: undefined });
727
+ const pollingOptions = Object.assign(Object.assign({}, opts), { pollingEndpoint: pollingEndpointToUse, pollingInterval: (opts === null || opts === void 0 ? void 0 : opts.pollingInterval) || this.config.pollingInterval || 2000, maxPollingAttempts: (opts === null || opts === void 0 ? void 0 : opts.maxPollingAttempts) || this.config.maxPollingAttempts || 30, onQRCodeReady: undefined, onStatusUpdate: undefined });
735
728
  // Decide whether to show modal based on preventDefaultUI
736
729
  const showModal = !preventDefaultUI;
737
730
  let modal;
@@ -740,13 +733,12 @@ export class PhoneAuthClient {
740
733
  preventDefaultUI,
741
734
  showModal,
742
735
  executionMode,
743
- hasInvokeOptions: !!invokeOptions,
744
- hasDesktopOptions: !!desktopOptions
736
+ hasOptions: !!opts
745
737
  });
746
738
  if (showModal) {
747
739
  console.log('[Desktop] Creating modal with QR data:', qrCodeData);
748
740
  // Create and setup modal
749
- modal = new AuthModal(invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.modalOptions, invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.callbacks);
741
+ modal = new AuthModal(opts === null || opts === void 0 ? void 0 : opts.modalOptions, opts === null || opts === void 0 ? void 0 : opts.callbacks);
750
742
  modal.setCloseCallback(() => {
751
743
  this.log('Desktop QR modal closed by user, cancelling polling');
752
744
  handler.cancel();
@@ -794,41 +786,20 @@ export class PhoneAuthClient {
794
786
  // Handle based on execution mode
795
787
  if (executionMode === 'extended') {
796
788
  // Extended mode - return control methods
797
- let credentialResolve = null;
798
- let credentialReject = null;
799
- let pollingStarted = false;
800
- // Create a promise that will remain pending until polling starts
789
+ // Create a promise and always start polling immediately
801
790
  const credentialPromise = new Promise((resolve, reject) => {
802
- credentialResolve = resolve;
803
- credentialReject = reject;
804
- // If modal is shown, start polling immediately
805
- if (showModal) {
806
- pollingStarted = true;
807
- startPolling()
808
- .then(resolve)
809
- .catch(reject);
810
- }
811
- // Otherwise, promise remains pending until start_polling() is called
791
+ // Always start polling immediately in extended mode (consistent with Link)
792
+ // This prevents the "unresolved promise trap" where developers might await
793
+ // the credential before calling start_polling()
794
+ startPolling()
795
+ .then(resolve)
796
+ .catch(reject);
812
797
  });
813
798
  // Create wrapped functions
814
799
  const wrappedStartPolling = () => __awaiter(this, void 0, void 0, function* () {
815
- if (pollingStarted) {
816
- throw this.createError(PhoneAuthErrorCode.INVALID_SESSION_STATE, 'Polling has already been started');
817
- }
818
- pollingStarted = true;
819
- try {
820
- const result = yield startPolling();
821
- if (credentialResolve) {
822
- credentialResolve(result);
823
- }
824
- return result;
825
- }
826
- catch (err) {
827
- if (credentialReject) {
828
- credentialReject(err);
829
- }
830
- throw err;
831
- }
800
+ // Polling has already started automatically in extended mode
801
+ // This method just returns the existing credential promise for consistency
802
+ return credentialPromise;
832
803
  });
833
804
  const wrappedStopPolling = () => {
834
805
  handler.cleanup();
@@ -840,10 +811,7 @@ export class PhoneAuthClient {
840
811
  handler.cleanup();
841
812
  if (modal)
842
813
  modal.close();
843
- // Reject the credential promise if it's still pending
844
- if (!pollingStarted && credentialReject) {
845
- credentialReject(this.createError(PhoneAuthErrorCode.USER_DENIED, 'Desktop authentication cancelled by user'));
846
- }
814
+ // The credential promise will be rejected by the handler.cancel() call
847
815
  };
848
816
  // Create the response object with a getter for is_polling
849
817
  const response = {
@@ -901,14 +869,14 @@ export class PhoneAuthClient {
901
869
  var _a, _b;
902
870
  try {
903
871
  window.open(linkData.url, '_blank');
904
- (_a = invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.onTriggerAttempt) === null || _a === void 0 ? void 0 : _a.call(invokeOptions, {
872
+ (_a = opts === null || opts === void 0 ? void 0 : opts.onTriggerAttempt) === null || _a === void 0 ? void 0 : _a.call(opts, {
905
873
  strategy: API.AUTHENTICATION_STRATEGY.LINK,
906
874
  url: linkData.url,
907
875
  success: true
908
876
  });
909
877
  }
910
878
  catch (error) {
911
- (_b = invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.onTriggerAttempt) === null || _b === void 0 ? void 0 : _b.call(invokeOptions, {
879
+ (_b = opts === null || opts === void 0 ? void 0 : opts.onTriggerAttempt) === null || _b === void 0 ? void 0 : _b.call(opts, {
912
880
  strategy: API.AUTHENTICATION_STRATEGY.LINK,
913
881
  url: linkData.url,
914
882
  success: false,
@@ -918,71 +886,75 @@ export class PhoneAuthClient {
918
886
  };
919
887
  // Link always auto-opens the app (no SDK UI by default)
920
888
  // Open immediately to preserve user gesture context
921
- if ((invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.autoTrigger) !== false) {
889
+ if ((opts === null || opts === void 0 ? void 0 : opts.autoTrigger) !== false) {
922
890
  triggerLink();
923
891
  }
924
892
  // Start polling in the background
925
893
  console.log('[PhoneAuth Client] Link polling config:', {
926
- fromInvokeOptions: invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.pollingEndpoint,
894
+ fromOptions: opts === null || opts === void 0 ? void 0 : opts.pollingEndpoint,
927
895
  fromClientConfig: (_o = this.config.endpoints) === null || _o === void 0 ? void 0 : _o.polling,
928
- finalPollingEndpoint: (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.pollingEndpoint) || ((_p = this.config.endpoints) === null || _p === void 0 ? void 0 : _p.polling)
896
+ finalPollingEndpoint: (opts === null || opts === void 0 ? void 0 : opts.pollingEndpoint) || ((_p = this.config.endpoints) === null || _p === void 0 ? void 0 : _p.polling)
929
897
  });
930
898
  const pollingOptions = {
931
- pollingEndpoint: (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.pollingEndpoint) || ((_q = this.config.endpoints) === null || _q === void 0 ? void 0 : _q.polling),
932
- pollingInterval: (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.pollingInterval) || this.config.pollingInterval || 2000,
933
- maxPollingAttempts: (invokeOptions === null || invokeOptions === void 0 ? void 0 : invokeOptions.maxPollingAttempts) || this.config.maxPollingAttempts || 30,
899
+ pollingEndpoint: (opts === null || opts === void 0 ? void 0 : opts.pollingEndpoint) || ((_q = this.config.endpoints) === null || _q === void 0 ? void 0 : _q.polling),
900
+ pollingInterval: (opts === null || opts === void 0 ? void 0 : opts.pollingInterval) || this.config.pollingInterval || 2000,
901
+ maxPollingAttempts: (opts === null || opts === void 0 ? void 0 : opts.maxPollingAttempts) || this.config.maxPollingAttempts || 30,
934
902
  onLinkOpened: undefined,
935
903
  onStatusUpdate: undefined
936
904
  };
937
905
  console.log('[PhoneAuth Client] Final Link polling options:', pollingOptions);
938
906
  // Handle based on execution mode
939
907
  if (executionMode === 'extended') {
940
- // Extended mode - return control methods without starting polling immediately
941
- let credentialResolve = null;
942
- let credentialReject = null;
908
+ // Extended mode - return control methods and start polling immediately
943
909
  let pollingStarted = false;
944
910
  let pollingPromise = null;
945
- // Create a pending promise that will be resolved when polling completes
946
- const credentialPromise = new Promise((resolve, reject) => {
947
- credentialResolve = resolve;
948
- credentialReject = reject;
911
+ // Start polling immediately (Link always polls automatically unlike Desktop)
912
+ pollingPromise = handler.invoke(plainResponse, pollingOptions);
913
+ pollingStarted = true;
914
+ // Create credential promise from the polling result
915
+ const credentialPromise = pollingPromise.then(result => {
916
+ if (result.authenticated && result.credential) {
917
+ return {
918
+ credential: result.credential,
919
+ session: plainResponse.session,
920
+ authenticated: true
921
+ };
922
+ }
923
+ else {
924
+ throw this.createError(PhoneAuthErrorCode.USER_DENIED, result.error || 'Link authentication failed');
925
+ }
949
926
  });
950
- // Function to start polling (only once)
927
+ // Function to restart polling (for retry scenarios)
951
928
  const startPolling = () => __awaiter(this, void 0, void 0, function* () {
952
- if (pollingStarted) {
953
- throw this.createError(PhoneAuthErrorCode.INVALID_SESSION_STATE, 'Polling has already been started');
954
- }
955
- pollingStarted = true;
956
- try {
957
- // Store the polling promise to ensure we use the same one
929
+ if (!pollingStarted) {
930
+ // This is here for API consistency, but for Link it's already polling
931
+ pollingStarted = true;
958
932
  if (!pollingPromise) {
959
933
  pollingPromise = handler.invoke(plainResponse, pollingOptions);
960
934
  }
961
935
  const result = yield pollingPromise;
962
936
  if (result.authenticated && result.credential) {
963
- const authCredential = {
937
+ return {
964
938
  credential: result.credential,
965
939
  session: plainResponse.session,
966
940
  authenticated: true
967
941
  };
968
- if (credentialResolve) {
969
- credentialResolve(authCredential);
970
- }
971
- return authCredential;
972
942
  }
973
943
  else {
974
- const error = this.createError(PhoneAuthErrorCode.USER_DENIED, result.error || 'Link authentication failed');
975
- if (credentialReject) {
976
- credentialReject(error);
977
- }
978
- throw error;
944
+ throw this.createError(PhoneAuthErrorCode.USER_DENIED, result.error || 'Link authentication failed');
979
945
  }
980
946
  }
981
- catch (err) {
982
- if (credentialReject) {
983
- credentialReject(err);
984
- }
985
- throw err;
947
+ // If already polling, just return the existing promise result
948
+ const result = yield pollingPromise;
949
+ if (result.authenticated && result.credential) {
950
+ return {
951
+ credential: result.credential,
952
+ session: plainResponse.session,
953
+ authenticated: true
954
+ };
955
+ }
956
+ else {
957
+ throw this.createError(PhoneAuthErrorCode.USER_DENIED, result.error || 'Link authentication failed');
986
958
  }
987
959
  });
988
960
  const response = {
@@ -1000,10 +972,8 @@ export class PhoneAuthClient {
1000
972
  cancel: () => {
1001
973
  handler.cancel();
1002
974
  handler.cleanup();
1003
- // Reject the credential promise if polling hasn't started
1004
- if (!pollingStarted && credentialReject) {
1005
- credentialReject(this.createError(PhoneAuthErrorCode.USER_DENIED, 'Link authentication cancelled by user'));
1006
- }
975
+ // Note: For Link, polling is already started, so the promise
976
+ // will be rejected by the handler.cancel() call
1007
977
  },
1008
978
  // This will be replaced with a getter
1009
979
  is_polling: false // Initial value, will be overridden by getter
@@ -1,2 +1,2 @@
1
1
  // SDK version - injected at build time
2
- export const SDK_VERSION = '4.4.8';
2
+ export const SDK_VERSION = '4.4.10';