@opexa/portal-sdk 0.59.127 → 0.59.129

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/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { CmsPortalService, GameService, ExtensionService, FileService, WalletService, AccountService, ReportService, PortalService, TriggerService, AuthService, getFingerPrint, isIOSPlatform } from './chunk-36U3QUDP.js';
2
- import { GraphQLClient, isPlainObject } from './chunk-5WRVWQBT.js';
3
- import './chunk-ROBGEUSE.js';
1
+ import { CmsPortalService, GameService, ExtensionService, FileService, WalletService, AccountService, ReportService, PortalService, TriggerService, AuthService, getFingerPrint, isIOSPlatform } from './chunk-ROZQZKKD.js';
2
+ import { GraphQLClient, isPlainObject } from './chunk-7APXFZ5G.js';
3
+ import './chunk-WVFSGB7Y.js';
4
4
  import { ObjectId } from '@opexa/object-id';
5
5
  export { ObjectId } from '@opexa/object-id';
6
6
  import { Capacitor } from '@capacitor/core';
@@ -380,6 +380,36 @@ function createRefreshTokenStore(logger, sessionPrefix) {
380
380
  return new PreferencesRefreshTokenStore(key, logger);
381
381
  }
382
382
 
383
+ // src/sdk/session-lifecycle.ts
384
+ var SessionLifecycle = class {
385
+ controller = new AbortController();
386
+ get signal() {
387
+ return this.controller.signal;
388
+ }
389
+ renew() {
390
+ this.controller.abort();
391
+ this.controller = new AbortController();
392
+ return this.controller.signal;
393
+ }
394
+ logout() {
395
+ this.renew();
396
+ }
397
+ };
398
+ var CredentialMutationLock = class {
399
+ tail = Promise.resolve();
400
+ wait() {
401
+ return this.tail;
402
+ }
403
+ run(operation) {
404
+ const result = this.tail.then(operation, operation);
405
+ this.tail = result.then(
406
+ () => void 0,
407
+ () => void 0
408
+ );
409
+ return result;
410
+ }
411
+ };
412
+
383
413
  // src/sdk/session-manager.ts
384
414
  var SessionManager = class {
385
415
  logger;
@@ -388,6 +418,8 @@ var SessionManager = class {
388
418
  authService;
389
419
  walletService;
390
420
  _refreshing = false;
421
+ lifecycle = new SessionLifecycle();
422
+ mutations = new CredentialMutationLock();
391
423
  /*
392
424
  * v4 access tokens live in memory only, so an XSS-readable storage layer
393
425
  * never holds a live one. Re-minted from the HttpOnly cookie, or from
@@ -417,38 +449,44 @@ var SessionManager = class {
417
449
  set refreshing(value) {
418
450
  this._refreshing = value;
419
451
  }
420
- async persist(data, version) {
421
- const now = /* @__PURE__ */ new Date();
422
- if (version === 4) {
423
- if (!data.session || !data.accessToken) {
424
- this.logger.error(
425
- "Malformed session response: expected 'session' and 'accessToken'."
452
+ async persist(data, version, signal) {
453
+ return this.mutations.run(async () => {
454
+ if (signal.aborted) return true;
455
+ const now = /* @__PURE__ */ new Date();
456
+ this.refreshing = false;
457
+ this.v4RefreshPromise = null;
458
+ if (version === 4) {
459
+ if (!data.session || !data.accessToken) {
460
+ this.logger.error(
461
+ "Malformed session response: expected 'session' and 'accessToken'."
462
+ );
463
+ return false;
464
+ }
465
+ this.v4AccessToken = data.accessToken;
466
+ this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
467
+ this.invalidReason = null;
468
+ if (data.refreshToken) {
469
+ await this.refreshTokenStore.set(data.refreshToken);
470
+ }
471
+ if (signal.aborted) return true;
472
+ localStorage.setItem(
473
+ this.storageKey,
474
+ JSON.stringify({ version, session: data.session })
426
475
  );
427
- return false;
476
+ return true;
428
477
  }
429
- this.v4AccessToken = data.accessToken;
430
- this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
431
478
  this.invalidReason = null;
432
- if (data.refreshToken) {
433
- await this.refreshTokenStore.set(data.refreshToken);
434
- }
435
479
  localStorage.setItem(
436
480
  this.storageKey,
437
- JSON.stringify({ version, session: data.session })
481
+ JSON.stringify({
482
+ version,
483
+ ...data,
484
+ accessTokenExpiresAt: addMinutes(now, 8).getTime(),
485
+ refreshTokenExpiresAt: subMinutes(addDays(now, 1), 2).getTime()
486
+ })
438
487
  );
439
488
  return true;
440
- }
441
- this.invalidReason = null;
442
- localStorage.setItem(
443
- this.storageKey,
444
- JSON.stringify({
445
- version,
446
- ...data,
447
- accessTokenExpiresAt: addMinutes(now, 8).getTime(),
448
- refreshTokenExpiresAt: subMinutes(addDays(now, 1), 2).getTime()
449
- })
450
- );
451
- return true;
489
+ });
452
490
  }
453
491
  malformedResponseError() {
454
492
  return {
@@ -460,6 +498,10 @@ var SessionManager = class {
460
498
  };
461
499
  }
462
500
  async create(input, version = 1) {
501
+ const waitingSignal = this.lifecycle.signal;
502
+ await this.mutations.wait();
503
+ if (waitingSignal.aborted) return { ok: true, data: null };
504
+ const signal = this.lifecycle.renew();
463
505
  if (this.isServer) {
464
506
  this.logger.warn("'localStorage' is not available on the server.");
465
507
  return {
@@ -495,7 +537,7 @@ var SessionManager = class {
495
537
  maxAttempt: 5
496
538
  })();
497
539
  if (!r1.ok) return r1;
498
- if (!await this.persist(r1.data, version))
540
+ if (!await this.persist(r1.data, version, signal))
499
541
  return this.malformedResponseError();
500
542
  return {
501
543
  ok: true,
@@ -505,7 +547,7 @@ var SessionManager = class {
505
547
  if (input.type === "MOBILE_NUMBER") {
506
548
  const res2 = await this.authService.createSession(input, version);
507
549
  if (res2.ok) {
508
- if (!await this.persist(res2.data, version))
550
+ if (!await this.persist(res2.data, version, signal))
509
551
  return this.malformedResponseError();
510
552
  return {
511
553
  ok: true,
@@ -524,7 +566,7 @@ var SessionManager = class {
524
566
  version
525
567
  );
526
568
  if (res2.ok) {
527
- if (!await this.persist(res2.data, version))
569
+ if (!await this.persist(res2.data, version, signal))
528
570
  return this.malformedResponseError();
529
571
  return {
530
572
  ok: true,
@@ -537,7 +579,7 @@ var SessionManager = class {
537
579
  localStorage.setItem(this.platformStorageKey, "CABINET");
538
580
  const res2 = await this.authService.createSession(input, version);
539
581
  if (res2.ok) {
540
- if (!await this.persist(res2.data, version))
582
+ if (!await this.persist(res2.data, version, signal))
541
583
  return this.malformedResponseError();
542
584
  return {
543
585
  ok: true,
@@ -556,7 +598,7 @@ var SessionManager = class {
556
598
  }
557
599
  };
558
600
  }
559
- if (!await this.persist(res.data, version))
601
+ if (!await this.persist(res.data, version, signal))
560
602
  return this.malformedResponseError();
561
603
  return {
562
604
  ok: true,
@@ -564,11 +606,15 @@ var SessionManager = class {
564
606
  };
565
607
  }
566
608
  async createFromAuthenticator(input) {
609
+ const waitingSignal = this.lifecycle.signal;
610
+ await this.mutations.wait();
611
+ if (waitingSignal.aborted) return { ok: true };
612
+ const signal = this.lifecycle.renew();
567
613
  const res = await this.authService.authenticate(input);
568
614
  if (res.ok) {
569
615
  if (this.isServer) {
570
616
  this.logger.warn("'localStorage' is not available on the server.");
571
- } else if (!await this.persist(res.data, 1)) {
617
+ } else if (!await this.persist(res.data, 1, signal)) {
572
618
  return this.malformedResponseError();
573
619
  }
574
620
  return { ok: true };
@@ -577,6 +623,7 @@ var SessionManager = class {
577
623
  }
578
624
  }
579
625
  async get() {
626
+ const signal = this.lifecycle.signal;
580
627
  if (this.isServer) {
581
628
  this.logger.warn("'localStorage' is not available on the server.");
582
629
  return {
@@ -586,6 +633,7 @@ var SessionManager = class {
586
633
  }
587
634
  if (this.refreshing) {
588
635
  await sleep(1e3);
636
+ if (signal.aborted) return { ok: true, data: null };
589
637
  return await this.get();
590
638
  }
591
639
  const val = localStorage.getItem(this.storageKey);
@@ -620,8 +668,10 @@ var SessionManager = class {
620
668
  this.refreshing = true;
621
669
  const res = await this.authService.refreshSession(
622
670
  obj.refreshToken,
623
- obj.version ?? 1
671
+ obj.version ?? 1,
672
+ signal
624
673
  );
674
+ if (signal.aborted) return { ok: true, data: null };
625
675
  this.refreshing = false;
626
676
  if (!res.ok) {
627
677
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
@@ -654,6 +704,8 @@ var SessionManager = class {
654
704
  data: obj
655
705
  };
656
706
  } catch {
707
+ if (signal.aborted) return { ok: true, data: null };
708
+ this.refreshing = false;
657
709
  return {
658
710
  ok: false,
659
711
  error: {
@@ -678,6 +730,7 @@ var SessionManager = class {
678
730
  return await this.refreshV4(session);
679
731
  }
680
732
  async refresh() {
733
+ const signal = this.lifecycle.signal;
681
734
  if (this.isServer) {
682
735
  this.logger.warn("'localStorage' is not available on the server.");
683
736
  return {
@@ -703,8 +756,10 @@ var SessionManager = class {
703
756
  this.refreshing = true;
704
757
  const res = await this.authService.refreshSession(
705
758
  obj.refreshToken,
706
- obj.version ?? 1
759
+ obj.version ?? 1,
760
+ signal
707
761
  );
762
+ if (signal.aborted) return { ok: true, data: null };
708
763
  this.refreshing = false;
709
764
  if (!res.ok) {
710
765
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
@@ -737,6 +792,8 @@ var SessionManager = class {
737
792
  data: obj
738
793
  };
739
794
  } catch {
795
+ if (signal.aborted) return { ok: true, data: null };
796
+ this.refreshing = false;
740
797
  return {
741
798
  ok: false,
742
799
  error: {
@@ -748,18 +805,20 @@ var SessionManager = class {
748
805
  }
749
806
  async refreshV4(session) {
750
807
  if (this.v4RefreshPromise) return await this.v4RefreshPromise;
751
- this.v4RefreshPromise = this.requestV4Refresh(session);
808
+ const promise = this.requestV4Refresh(session, this.lifecycle.signal);
809
+ this.v4RefreshPromise = promise;
752
810
  try {
753
- return await this.v4RefreshPromise;
811
+ return await promise;
754
812
  } finally {
755
- this.v4RefreshPromise = null;
813
+ if (this.v4RefreshPromise === promise) this.v4RefreshPromise = null;
756
814
  }
757
815
  }
758
- async requestV4Refresh(session) {
816
+ async requestV4Refresh(session, signal) {
759
817
  this.logger.info("Refreshing session...");
760
818
  let refreshToken;
761
819
  if (isIOSPlatform()) {
762
820
  refreshToken = await this.refreshTokenStore.get() ?? void 0;
821
+ if (signal.aborted) return { ok: true, data: null };
763
822
  if (!refreshToken) {
764
823
  this.logger.warn("No stored refresh token. Session expired.");
765
824
  this.v4AccessToken = null;
@@ -776,7 +835,8 @@ var SessionManager = class {
776
835
  }
777
836
  }
778
837
  this.refreshing = true;
779
- const res = await this.authService.refreshSession(refreshToken, 4);
838
+ const res = await this.authService.refreshSession(refreshToken, 4, signal);
839
+ if (signal.aborted) return { ok: true, data: null };
780
840
  if (!res.ok) {
781
841
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
782
842
  const terminal = res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError";
@@ -788,6 +848,7 @@ var SessionManager = class {
788
848
  }
789
849
  this.refreshing = false;
790
850
  if (terminal) await this.refreshTokenStore.remove();
851
+ if (signal.aborted) return { ok: true, data: null };
791
852
  return {
792
853
  ok: false,
793
854
  error: res.error
@@ -797,8 +858,13 @@ var SessionManager = class {
797
858
  this.logger.success("Session refreshed!");
798
859
  this.invalidReason = null;
799
860
  if (res.data.refreshToken) {
800
- await this.refreshTokenStore.set(res.data.refreshToken);
861
+ await this.mutations.run(async () => {
862
+ if (!signal.aborted && res.data.refreshToken) {
863
+ await this.refreshTokenStore.set(res.data.refreshToken);
864
+ }
865
+ });
801
866
  }
867
+ if (signal.aborted) return { ok: true, data: null };
802
868
  const now = /* @__PURE__ */ new Date();
803
869
  this.v4AccessToken = res.data.accessToken;
804
870
  this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
@@ -816,26 +882,53 @@ var SessionManager = class {
816
882
  this.logger.warn("'localStorage' is not available on the server.");
817
883
  return;
818
884
  }
819
- let version = 1;
885
+ let version = this.v4AccessToken ? 4 : 1;
886
+ let accessToken = this.v4AccessToken ?? void 0;
887
+ let accessTokenExpiresAt = this.v4AccessTokenExpiresAt;
888
+ let refreshToken;
820
889
  const val = localStorage.getItem(this.storageKey);
821
890
  if (val) {
822
891
  try {
823
892
  const stored = JSON.parse(val);
824
893
  version = stored.version ?? 1;
894
+ accessToken = stored.version === 4 ? this.v4AccessToken ?? void 0 : stored.accessToken;
895
+ accessTokenExpiresAt = stored.version === 4 ? this.v4AccessTokenExpiresAt : stored.accessTokenExpiresAt;
896
+ if (stored.version !== 4) refreshToken = stored.refreshToken;
825
897
  } catch {
826
898
  }
827
899
  }
828
- const res = await this.get();
829
- if (res.data?.accessToken) {
830
- await this.authService.destroySession(res.data.accessToken, version);
831
- }
900
+ this.lifecycle.logout();
901
+ this.refreshing = false;
902
+ this.v4RefreshPromise = null;
832
903
  this.v4AccessToken = null;
833
904
  this.v4AccessTokenExpiresAt = null;
834
905
  this.invalidReason = null;
835
- await this.refreshTokenStore.remove();
836
906
  localStorage.removeItem(this.storageKey);
907
+ await this.mutations.run(async () => {
908
+ try {
909
+ if (val && (!accessToken || !accessTokenExpiresAt || Date.now() > accessTokenExpiresAt)) {
910
+ if (version === 4 && isIOSPlatform()) {
911
+ refreshToken = await this.refreshTokenStore.get() ?? void 0;
912
+ }
913
+ if (refreshToken || version === 4 && !isIOSPlatform()) {
914
+ accessToken = void 0;
915
+ const res = await this.authService.refreshSession(
916
+ refreshToken,
917
+ version
918
+ );
919
+ if (res.ok) accessToken = res.data.accessToken;
920
+ }
921
+ }
922
+ if (accessToken) {
923
+ await this.authService.destroySession(accessToken, version);
924
+ }
925
+ } finally {
926
+ if (version === 4) await this.refreshTokenStore.remove();
927
+ }
928
+ });
837
929
  }
838
930
  async verify() {
931
+ const signal = this.lifecycle.signal;
839
932
  if (this.isServer) {
840
933
  this.logger.warn("'localStorage' is not available on the server.");
841
934
  return { valid: true };
@@ -848,7 +941,8 @@ var SessionManager = class {
848
941
  try {
849
942
  const stored = JSON.parse(val);
850
943
  if (stored.version === 4) {
851
- const res = await this.verifyV4(stored.session);
944
+ const res = await this.verifyV4(stored.session, signal);
945
+ if (signal.aborted) return { valid: true };
852
946
  if (!res.valid) localStorage.removeItem(this.storageKey);
853
947
  return res;
854
948
  }
@@ -856,32 +950,37 @@ var SessionManager = class {
856
950
  }
857
951
  }
858
952
  const s = await this.get();
953
+ if (signal.aborted) return { valid: true };
859
954
  if (s.error?.name === "InvalidTokenError" || s.error?.name === "SessionExpiredError" || s.error?.name === "AccountBlacklistedError") {
860
955
  this.invalidReason = "INVALID_SESSION";
861
956
  return { valid: false, reason: "INVALID_SESSION" };
862
957
  }
863
958
  if (!s.data) return { valid: true };
864
- const v = await this.authService.verifySession(s.data.accessToken);
959
+ const v = await this.authService.verifySession(s.data.accessToken, signal);
960
+ if (signal.aborted) return { valid: true };
865
961
  if (!v) {
866
962
  this.invalidReason = "INVALID_SESSION";
867
963
  localStorage.removeItem(this.storageKey);
868
964
  }
869
965
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
870
966
  }
871
- async verifyV4(session) {
967
+ async verifyV4(session, signal) {
872
968
  if (!this.v4AccessToken || !this.v4AccessTokenExpiresAt || isAfter(/* @__PURE__ */ new Date(), new Date(this.v4AccessTokenExpiresAt))) {
873
969
  const res = await this.refreshV4(session);
970
+ if (signal.aborted) return { valid: true };
874
971
  if (res.ok) return { valid: true };
875
972
  if (!this.invalidReason) return { valid: true };
876
973
  return { valid: false, reason: this.invalidReason };
877
974
  }
878
- const v = await this.authService.verifySession(this.v4AccessToken);
975
+ const v = await this.authService.verifySession(this.v4AccessToken, signal);
976
+ if (signal.aborted) return { valid: true };
879
977
  if (!v) {
880
978
  localStorage.removeItem(this.storageKey);
881
979
  this.v4AccessToken = null;
882
980
  this.v4AccessTokenExpiresAt = null;
883
981
  this.invalidReason = "INVALID_SESSION";
884
982
  await this.refreshTokenStore.remove();
983
+ if (signal.aborted) return { valid: true };
885
984
  }
886
985
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
887
986
  }
@@ -910,6 +1009,8 @@ var SessionManagerCookie = class {
910
1009
  authService;
911
1010
  walletService;
912
1011
  _refreshing = false;
1012
+ lifecycle = new SessionLifecycle();
1013
+ mutations = new CredentialMutationLock();
913
1014
  /*
914
1015
  * v4 access tokens live in memory only, so an XSS-readable storage layer
915
1016
  * never holds a live one. Re-minted from the HttpOnly cookie, or from
@@ -932,34 +1033,44 @@ var SessionManagerCookie = class {
932
1033
  set refreshing(value) {
933
1034
  this._refreshing = value;
934
1035
  }
935
- async persist(data, version) {
936
- const now = /* @__PURE__ */ new Date();
937
- this.invalidReason = null;
938
- if (version === 4) {
939
- this.v4AccessToken = data.accessToken ?? null;
940
- this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
941
- if (data.refreshToken) {
942
- await this.refreshTokenStore.set(data.refreshToken);
1036
+ async persist(data, version, signal) {
1037
+ return this.mutations.run(async () => {
1038
+ if (signal.aborted) return;
1039
+ const now = /* @__PURE__ */ new Date();
1040
+ this.refreshing = false;
1041
+ this.v4RefreshPromise = null;
1042
+ this.invalidReason = null;
1043
+ if (version === 4) {
1044
+ this.v4AccessToken = data.accessToken ?? null;
1045
+ this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
1046
+ if (data.refreshToken) {
1047
+ await this.refreshTokenStore.set(data.refreshToken);
1048
+ }
1049
+ if (signal.aborted) return;
1050
+ cookies.set(
1051
+ this.storageKey,
1052
+ JSON.stringify({ version, session: data.session }),
1053
+ { expires: subMinutes(addDays(now, 15), 2) }
1054
+ );
1055
+ return;
943
1056
  }
944
1057
  cookies.set(
945
1058
  this.storageKey,
946
- JSON.stringify({ version, session: data.session }),
947
- { expires: subMinutes(addDays(now, 15), 2) }
1059
+ JSON.stringify({
1060
+ version,
1061
+ ...data,
1062
+ accessTokenExpiresAt: addMinutes(now, 8).getTime(),
1063
+ refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
1064
+ }),
1065
+ { expires: subMinutes(addDays(now, 30), 2) }
948
1066
  );
949
- return;
950
- }
951
- cookies.set(
952
- this.storageKey,
953
- JSON.stringify({
954
- version,
955
- ...data,
956
- accessTokenExpiresAt: addMinutes(now, 8).getTime(),
957
- refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
958
- }),
959
- { expires: subMinutes(addDays(now, 30), 2) }
960
- );
1067
+ });
961
1068
  }
962
1069
  async create(input, version = 1) {
1070
+ const waitingSignal = this.lifecycle.signal;
1071
+ await this.mutations.wait();
1072
+ if (waitingSignal.aborted) return { ok: true, data: null };
1073
+ const signal = this.lifecycle.renew();
963
1074
  if (input.type === "MAYA") {
964
1075
  localStorage.setItem(this.platformStorageKey, "MAYA");
965
1076
  const f0 = () => this.walletService.mayaSession({ id: input.sessionId });
@@ -985,7 +1096,7 @@ var SessionManagerCookie = class {
985
1096
  maxAttempt: 5
986
1097
  })();
987
1098
  if (!r1.ok) return r1;
988
- await this.persist(r1.data, version);
1099
+ await this.persist(r1.data, version, signal);
989
1100
  return {
990
1101
  ok: true,
991
1102
  data: null
@@ -994,7 +1105,7 @@ var SessionManagerCookie = class {
994
1105
  if (input.type === "MOBILE_NUMBER") {
995
1106
  const res2 = await this.authService.createSession(input, version);
996
1107
  if (res2.ok) {
997
- await this.persist(res2.data, version);
1108
+ await this.persist(res2.data, version, signal);
998
1109
  return {
999
1110
  ok: true,
1000
1111
  data: null
@@ -1011,7 +1122,7 @@ var SessionManagerCookie = class {
1011
1122
  version
1012
1123
  );
1013
1124
  if (res2.ok) {
1014
- await this.persist(res2.data, version);
1125
+ await this.persist(res2.data, version, signal);
1015
1126
  return {
1016
1127
  ok: true,
1017
1128
  data: null
@@ -1023,7 +1134,7 @@ var SessionManagerCookie = class {
1023
1134
  localStorage.setItem(this.platformStorageKey, "CABINET");
1024
1135
  const res2 = await this.authService.createSession(input, version);
1025
1136
  if (res2.ok) {
1026
- await this.persist(res2.data, version);
1137
+ await this.persist(res2.data, version, signal);
1027
1138
  return {
1028
1139
  ok: true,
1029
1140
  data: null
@@ -1041,19 +1152,23 @@ var SessionManagerCookie = class {
1041
1152
  }
1042
1153
  };
1043
1154
  }
1044
- await this.persist(res.data, version);
1155
+ await this.persist(res.data, version, signal);
1045
1156
  return {
1046
1157
  ok: true,
1047
1158
  data: null
1048
1159
  };
1049
1160
  }
1050
1161
  async createFromAuthenticator(input) {
1162
+ const waitingSignal = this.lifecycle.signal;
1163
+ await this.mutations.wait();
1164
+ if (waitingSignal.aborted) return { ok: true };
1165
+ const signal = this.lifecycle.renew();
1051
1166
  const res = await this.authService.authenticate(input);
1052
1167
  if (res.ok) {
1053
1168
  if (this.isServer) {
1054
1169
  this.logger.warn("'client cookies' is not available on the server.");
1055
1170
  } else {
1056
- await this.persist(res.data, 1);
1171
+ await this.persist(res.data, 1, signal);
1057
1172
  }
1058
1173
  return { ok: true };
1059
1174
  } else {
@@ -1061,6 +1176,7 @@ var SessionManagerCookie = class {
1061
1176
  }
1062
1177
  }
1063
1178
  async get() {
1179
+ const signal = this.lifecycle.signal;
1064
1180
  if (this.isServer) {
1065
1181
  this.logger.warn("'client cookies' is not available on the server.");
1066
1182
  return {
@@ -1070,6 +1186,7 @@ var SessionManagerCookie = class {
1070
1186
  }
1071
1187
  if (this.refreshing) {
1072
1188
  await sleep(1e3);
1189
+ if (signal.aborted) return { ok: true, data: null };
1073
1190
  return await this.get();
1074
1191
  }
1075
1192
  const val = cookies.get(this.storageKey);
@@ -1104,8 +1221,10 @@ var SessionManagerCookie = class {
1104
1221
  this.refreshing = true;
1105
1222
  const res = await this.authService.refreshSession(
1106
1223
  obj.refreshToken,
1107
- obj.version ?? 1
1224
+ obj.version ?? 1,
1225
+ signal
1108
1226
  );
1227
+ if (signal.aborted) return { ok: true, data: null };
1109
1228
  this.refreshing = false;
1110
1229
  if (!res.ok) {
1111
1230
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
@@ -1141,6 +1260,8 @@ var SessionManagerCookie = class {
1141
1260
  data: obj
1142
1261
  };
1143
1262
  } catch {
1263
+ if (signal.aborted) return { ok: true, data: null };
1264
+ this.refreshing = false;
1144
1265
  return {
1145
1266
  ok: false,
1146
1267
  error: {
@@ -1165,6 +1286,7 @@ var SessionManagerCookie = class {
1165
1286
  return await this.refreshV4(session);
1166
1287
  }
1167
1288
  async refresh() {
1289
+ const signal = this.lifecycle.signal;
1168
1290
  if (this.isServer) {
1169
1291
  this.logger.warn("'client cookies' is not available on the server.");
1170
1292
  return {
@@ -1190,8 +1312,10 @@ var SessionManagerCookie = class {
1190
1312
  this.refreshing = true;
1191
1313
  const res = await this.authService.refreshSession(
1192
1314
  obj.refreshToken,
1193
- obj.version ?? 1
1315
+ obj.version ?? 1,
1316
+ signal
1194
1317
  );
1318
+ if (signal.aborted) return { ok: true, data: null };
1195
1319
  this.refreshing = false;
1196
1320
  if (!res.ok) {
1197
1321
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
@@ -1226,6 +1350,8 @@ var SessionManagerCookie = class {
1226
1350
  data: obj
1227
1351
  };
1228
1352
  } catch {
1353
+ if (signal.aborted) return { ok: true, data: null };
1354
+ this.refreshing = false;
1229
1355
  return {
1230
1356
  ok: false,
1231
1357
  error: {
@@ -1237,18 +1363,20 @@ var SessionManagerCookie = class {
1237
1363
  }
1238
1364
  async refreshV4(session) {
1239
1365
  if (this.v4RefreshPromise) return await this.v4RefreshPromise;
1240
- this.v4RefreshPromise = this.requestV4Refresh(session);
1366
+ const promise = this.requestV4Refresh(session, this.lifecycle.signal);
1367
+ this.v4RefreshPromise = promise;
1241
1368
  try {
1242
- return await this.v4RefreshPromise;
1369
+ return await promise;
1243
1370
  } finally {
1244
- this.v4RefreshPromise = null;
1371
+ if (this.v4RefreshPromise === promise) this.v4RefreshPromise = null;
1245
1372
  }
1246
1373
  }
1247
- async requestV4Refresh(session) {
1374
+ async requestV4Refresh(session, signal) {
1248
1375
  this.logger.info("Refreshing session...");
1249
1376
  let refreshToken;
1250
1377
  if (isIOSPlatform()) {
1251
1378
  refreshToken = await this.refreshTokenStore.get() ?? void 0;
1379
+ if (signal.aborted) return { ok: true, data: null };
1252
1380
  if (!refreshToken) {
1253
1381
  this.logger.warn("No stored refresh token. Session expired.");
1254
1382
  this.v4AccessToken = null;
@@ -1265,7 +1393,8 @@ var SessionManagerCookie = class {
1265
1393
  }
1266
1394
  }
1267
1395
  this.refreshing = true;
1268
- const res = await this.authService.refreshSession(refreshToken, 4);
1396
+ const res = await this.authService.refreshSession(refreshToken, 4, signal);
1397
+ if (signal.aborted) return { ok: true, data: null };
1269
1398
  if (!res.ok) {
1270
1399
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
1271
1400
  const terminal = res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError";
@@ -1277,6 +1406,7 @@ var SessionManagerCookie = class {
1277
1406
  }
1278
1407
  this.refreshing = false;
1279
1408
  if (terminal) await this.refreshTokenStore.remove();
1409
+ if (signal.aborted) return { ok: true, data: null };
1280
1410
  return {
1281
1411
  ok: false,
1282
1412
  error: res.error
@@ -1286,8 +1416,13 @@ var SessionManagerCookie = class {
1286
1416
  this.logger.success("Session refreshed!");
1287
1417
  this.invalidReason = null;
1288
1418
  if (res.data.refreshToken) {
1289
- await this.refreshTokenStore.set(res.data.refreshToken);
1419
+ await this.mutations.run(async () => {
1420
+ if (!signal.aborted && res.data.refreshToken) {
1421
+ await this.refreshTokenStore.set(res.data.refreshToken);
1422
+ }
1423
+ });
1290
1424
  }
1425
+ if (signal.aborted) return { ok: true, data: null };
1291
1426
  const now = /* @__PURE__ */ new Date();
1292
1427
  this.v4AccessToken = res.data.accessToken;
1293
1428
  this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
@@ -1305,26 +1440,53 @@ var SessionManagerCookie = class {
1305
1440
  this.logger.warn("'client cookies' is not available on the server.");
1306
1441
  return;
1307
1442
  }
1308
- let version = 1;
1443
+ let version = this.v4AccessToken ? 4 : 1;
1444
+ let accessToken = this.v4AccessToken ?? void 0;
1445
+ let accessTokenExpiresAt = this.v4AccessTokenExpiresAt;
1446
+ let refreshToken;
1309
1447
  const val = cookies.get(this.storageKey);
1310
1448
  if (val) {
1311
1449
  try {
1312
1450
  const stored = JSON.parse(val);
1313
1451
  version = stored.version ?? 1;
1452
+ accessToken = stored.version === 4 ? this.v4AccessToken ?? void 0 : stored.accessToken;
1453
+ accessTokenExpiresAt = stored.version === 4 ? this.v4AccessTokenExpiresAt : stored.accessTokenExpiresAt;
1454
+ if (stored.version !== 4) refreshToken = stored.refreshToken;
1314
1455
  } catch {
1315
1456
  }
1316
1457
  }
1317
- const res = await this.get();
1318
- if (res.data?.accessToken) {
1319
- await this.authService.destroySession(res.data.accessToken, version);
1320
- }
1458
+ this.lifecycle.logout();
1459
+ this.refreshing = false;
1460
+ this.v4RefreshPromise = null;
1321
1461
  this.v4AccessToken = null;
1322
1462
  this.v4AccessTokenExpiresAt = null;
1323
1463
  this.invalidReason = null;
1324
- await this.refreshTokenStore.remove();
1325
1464
  cookies.remove(this.storageKey);
1465
+ await this.mutations.run(async () => {
1466
+ try {
1467
+ if (val && (!accessToken || !accessTokenExpiresAt || Date.now() > accessTokenExpiresAt)) {
1468
+ if (version === 4 && isIOSPlatform()) {
1469
+ refreshToken = await this.refreshTokenStore.get() ?? void 0;
1470
+ }
1471
+ if (refreshToken || version === 4 && !isIOSPlatform()) {
1472
+ accessToken = void 0;
1473
+ const res = await this.authService.refreshSession(
1474
+ refreshToken,
1475
+ version
1476
+ );
1477
+ if (res.ok) accessToken = res.data.accessToken;
1478
+ }
1479
+ }
1480
+ if (accessToken) {
1481
+ await this.authService.destroySession(accessToken, version);
1482
+ }
1483
+ } finally {
1484
+ if (version === 4) await this.refreshTokenStore.remove();
1485
+ }
1486
+ });
1326
1487
  }
1327
1488
  async verify() {
1489
+ const signal = this.lifecycle.signal;
1328
1490
  if (this.isServer) {
1329
1491
  this.logger.warn("'client cookies' is not available on the server.");
1330
1492
  return { valid: true };
@@ -1337,7 +1499,8 @@ var SessionManagerCookie = class {
1337
1499
  try {
1338
1500
  const stored = JSON.parse(val);
1339
1501
  if (stored.version === 4) {
1340
- const res = await this.verifyV4(stored.session);
1502
+ const res = await this.verifyV4(stored.session, signal);
1503
+ if (signal.aborted) return { valid: true };
1341
1504
  if (!res.valid) cookies.remove(this.storageKey);
1342
1505
  return res;
1343
1506
  }
@@ -1345,32 +1508,37 @@ var SessionManagerCookie = class {
1345
1508
  }
1346
1509
  }
1347
1510
  const s = await this.get();
1511
+ if (signal.aborted) return { valid: true };
1348
1512
  if (s.error?.name === "InvalidTokenError" || s.error?.name === "SessionExpiredError" || s.error?.name === "AccountBlacklistedError") {
1349
1513
  this.invalidReason = "INVALID_SESSION";
1350
1514
  return { valid: false, reason: "INVALID_SESSION" };
1351
1515
  }
1352
1516
  if (!s.data) return { valid: true };
1353
- const v = await this.authService.verifySession(s.data.accessToken);
1517
+ const v = await this.authService.verifySession(s.data.accessToken, signal);
1518
+ if (signal.aborted) return { valid: true };
1354
1519
  if (!v) {
1355
1520
  this.invalidReason = "INVALID_SESSION";
1356
1521
  cookies.remove(this.storageKey);
1357
1522
  }
1358
1523
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
1359
1524
  }
1360
- async verifyV4(session) {
1525
+ async verifyV4(session, signal) {
1361
1526
  if (!this.v4AccessToken || !this.v4AccessTokenExpiresAt || isAfter(/* @__PURE__ */ new Date(), new Date(this.v4AccessTokenExpiresAt))) {
1362
1527
  const res = await this.refreshV4(session);
1528
+ if (signal.aborted) return { valid: true };
1363
1529
  if (res.ok) return { valid: true };
1364
1530
  if (!this.invalidReason) return { valid: true };
1365
1531
  return { valid: false, reason: this.invalidReason };
1366
1532
  }
1367
- const v = await this.authService.verifySession(this.v4AccessToken);
1533
+ const v = await this.authService.verifySession(this.v4AccessToken, signal);
1534
+ if (signal.aborted) return { valid: true };
1368
1535
  if (!v) {
1369
1536
  cookies.remove(this.storageKey);
1370
1537
  this.v4AccessToken = null;
1371
1538
  this.v4AccessTokenExpiresAt = null;
1372
1539
  this.invalidReason = "INVALID_SESSION";
1373
1540
  await this.refreshTokenStore.remove();
1541
+ if (signal.aborted) return { valid: true };
1374
1542
  }
1375
1543
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
1376
1544
  }