@opexa/portal-sdk 0.59.95 → 0.59.97

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,4 +1,4 @@
1
- import { CmsPortalService, GameService, ExtensionService, FileService, WalletService, AccountService, ReportService, PortalService, TriggerService, AuthService, getFingerPrint } from './chunk-RCMZBLLX.js';
1
+ import { CmsPortalService, GameService, ExtensionService, FileService, WalletService, AccountService, ReportService, PortalService, TriggerService, AuthService, getFingerPrint, isIOSPlatform } from './chunk-MJLXQ6HC.js';
2
2
  import { GraphQLClient, isPlainObject } from './chunk-7APXFZ5G.js';
3
3
  import './chunk-WVFSGB7Y.js';
4
4
  import { ObjectId } from '@opexa/object-id';
@@ -336,6 +336,48 @@ function pollable(func, config) {
336
336
  };
337
337
  }
338
338
 
339
+ // src/sdk/refresh-token-store.ts
340
+ var PreferencesRefreshTokenStore = class {
341
+ constructor(key, logger) {
342
+ this.key = key;
343
+ this.logger = logger;
344
+ }
345
+ async preferences() {
346
+ const { Preferences } = await import('@capacitor/preferences');
347
+ return Preferences;
348
+ }
349
+ async get() {
350
+ if (!isIOSPlatform()) return null;
351
+ try {
352
+ const { value } = await (await this.preferences()).get({ key: this.key });
353
+ return value ?? null;
354
+ } catch (err) {
355
+ this.logger.error(`Failed to read the refresh token: ${err}`);
356
+ return null;
357
+ }
358
+ }
359
+ async set(token) {
360
+ if (!isIOSPlatform()) return;
361
+ try {
362
+ await (await this.preferences()).set({ key: this.key, value: token });
363
+ } catch (err) {
364
+ this.logger.error(`Failed to persist the refresh token: ${err}`);
365
+ }
366
+ }
367
+ async remove() {
368
+ if (!isIOSPlatform()) return;
369
+ try {
370
+ await (await this.preferences()).remove({ key: this.key });
371
+ } catch (err) {
372
+ this.logger.error(`Failed to clear the refresh token: ${err}`);
373
+ }
374
+ }
375
+ };
376
+ function createRefreshTokenStore(logger, sessionPrefix) {
377
+ const key = sessionPrefix ? `${sessionPrefix}/session/refresh-token` : "session/refresh-token";
378
+ return new PreferencesRefreshTokenStore(key, logger);
379
+ }
380
+
339
381
  // src/sdk/session-manager.ts
340
382
  var SessionManager = class {
341
383
  logger;
@@ -345,17 +387,23 @@ var SessionManager = class {
345
387
  walletService;
346
388
  _refreshing = false;
347
389
  /*
348
- * v4 access tokens are never persisted (localStorage/cookie) so that an
349
- * XSS-readable storage layer never holds a live access token. They only
350
- * live in memory and get re-minted from the HttpOnly refresh cookie.
390
+ * v4 access tokens live in memory only, so an XSS-readable storage layer
391
+ * never holds a live one. Re-minted from the HttpOnly cookie, or from
392
+ * `refreshTokenStore` on iOS.
351
393
  */
352
394
  v4AccessToken = null;
353
395
  v4AccessTokenExpiresAt = null;
354
396
  v4RefreshPromise = null;
397
+ invalidReason = null;
398
+ refreshTokenStore;
355
399
  constructor(config) {
356
400
  this.authService = config.authService;
357
401
  this.walletService = config.walletService;
358
402
  this.logger = config.logger;
403
+ this.refreshTokenStore = createRefreshTokenStore(
404
+ config.logger,
405
+ config.sessionPrefix
406
+ );
359
407
  if (config.sessionPrefix) {
360
408
  this.storageKey = `${config.sessionPrefix}/${this.storageKey}`;
361
409
  this.platformStorageKey = `${config.sessionPrefix}/${this.platformStorageKey}`;
@@ -367,7 +415,7 @@ var SessionManager = class {
367
415
  set refreshing(value) {
368
416
  this._refreshing = value;
369
417
  }
370
- persist(data, version) {
418
+ async persist(data, version) {
371
419
  const now = /* @__PURE__ */ new Date();
372
420
  if (version === 4) {
373
421
  if (!data.session || !data.accessToken) {
@@ -378,12 +426,17 @@ var SessionManager = class {
378
426
  }
379
427
  this.v4AccessToken = data.accessToken;
380
428
  this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
429
+ this.invalidReason = null;
430
+ if (data.refreshToken) {
431
+ await this.refreshTokenStore.set(data.refreshToken);
432
+ }
381
433
  localStorage.setItem(
382
434
  this.storageKey,
383
435
  JSON.stringify({ version, session: data.session })
384
436
  );
385
437
  return true;
386
438
  }
439
+ this.invalidReason = null;
387
440
  localStorage.setItem(
388
441
  this.storageKey,
389
442
  JSON.stringify({
@@ -440,7 +493,8 @@ var SessionManager = class {
440
493
  maxAttempt: 5
441
494
  })();
442
495
  if (!r1.ok) return r1;
443
- if (!this.persist(r1.data, version)) return this.malformedResponseError();
496
+ if (!await this.persist(r1.data, version))
497
+ return this.malformedResponseError();
444
498
  return {
445
499
  ok: true,
446
500
  data: null
@@ -449,7 +503,7 @@ var SessionManager = class {
449
503
  if (input.type === "MOBILE_NUMBER") {
450
504
  const res2 = await this.authService.createSession(input, version);
451
505
  if (res2.ok) {
452
- if (!this.persist(res2.data, version))
506
+ if (!await this.persist(res2.data, version))
453
507
  return this.malformedResponseError();
454
508
  return {
455
509
  ok: true,
@@ -468,7 +522,7 @@ var SessionManager = class {
468
522
  version
469
523
  );
470
524
  if (res2.ok) {
471
- if (!this.persist(res2.data, version))
525
+ if (!await this.persist(res2.data, version))
472
526
  return this.malformedResponseError();
473
527
  return {
474
528
  ok: true,
@@ -481,7 +535,7 @@ var SessionManager = class {
481
535
  localStorage.setItem(this.platformStorageKey, "CABINET");
482
536
  const res2 = await this.authService.createSession(input, version);
483
537
  if (res2.ok) {
484
- if (!this.persist(res2.data, version))
538
+ if (!await this.persist(res2.data, version))
485
539
  return this.malformedResponseError();
486
540
  return {
487
541
  ok: true,
@@ -500,7 +554,8 @@ var SessionManager = class {
500
554
  }
501
555
  };
502
556
  }
503
- if (!this.persist(res.data, version)) return this.malformedResponseError();
557
+ if (!await this.persist(res.data, version))
558
+ return this.malformedResponseError();
504
559
  return {
505
560
  ok: true,
506
561
  data: null
@@ -511,7 +566,7 @@ var SessionManager = class {
511
566
  if (res.ok) {
512
567
  if (this.isServer) {
513
568
  this.logger.warn("'localStorage' is not available on the server.");
514
- } else if (!this.persist(res.data, 1)) {
569
+ } else if (!await this.persist(res.data, 1)) {
515
570
  return this.malformedResponseError();
516
571
  }
517
572
  return { ok: true };
@@ -607,6 +662,20 @@ var SessionManager = class {
607
662
  };
608
663
  }
609
664
  }
665
+ async getV4(session) {
666
+ const now = /* @__PURE__ */ new Date();
667
+ if (this.v4AccessToken && this.v4AccessTokenExpiresAt && !isAfter(now, new Date(this.v4AccessTokenExpiresAt))) {
668
+ return {
669
+ ok: true,
670
+ data: {
671
+ session,
672
+ accessToken: this.v4AccessToken,
673
+ accessTokenExpiresAt: this.v4AccessTokenExpiresAt
674
+ }
675
+ };
676
+ }
677
+ return await this.refreshV4(session);
678
+ }
610
679
  async refresh() {
611
680
  if (this.isServer) {
612
681
  this.logger.warn("'localStorage' is not available on the server.");
@@ -676,20 +745,6 @@ var SessionManager = class {
676
745
  };
677
746
  }
678
747
  }
679
- async getV4(session) {
680
- const now = /* @__PURE__ */ new Date();
681
- if (this.v4AccessToken && this.v4AccessTokenExpiresAt && !isAfter(now, new Date(this.v4AccessTokenExpiresAt))) {
682
- return {
683
- ok: true,
684
- data: {
685
- session,
686
- accessToken: this.v4AccessToken,
687
- accessTokenExpiresAt: this.v4AccessTokenExpiresAt
688
- }
689
- };
690
- }
691
- return await this.refreshV4(session);
692
- }
693
748
  async refreshV4(session) {
694
749
  if (this.v4RefreshPromise) return await this.v4RefreshPromise;
695
750
  this.v4RefreshPromise = this.requestV4Refresh(session);
@@ -701,21 +756,48 @@ var SessionManager = class {
701
756
  }
702
757
  async requestV4Refresh(session) {
703
758
  this.logger.info("Refreshing session...");
759
+ let refreshToken;
760
+ if (isIOSPlatform()) {
761
+ refreshToken = await this.refreshTokenStore.get() ?? void 0;
762
+ if (!refreshToken) {
763
+ this.logger.warn("No stored refresh token. Session expired.");
764
+ this.v4AccessToken = null;
765
+ this.v4AccessTokenExpiresAt = null;
766
+ this.invalidReason = "REFRESH_TOKEN_EXPIRED";
767
+ localStorage.removeItem(this.storageKey);
768
+ return {
769
+ ok: false,
770
+ error: {
771
+ name: "SessionExpiredError",
772
+ message: "Session expired."
773
+ }
774
+ };
775
+ }
776
+ }
704
777
  this.refreshing = true;
705
- const res = await this.authService.refreshSession(void 0, 4);
706
- this.refreshing = false;
778
+ const res = await this.authService.refreshSession(refreshToken, 4);
707
779
  if (!res.ok) {
708
780
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
709
- if (res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError") {
781
+ const terminal = res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError";
782
+ if (terminal) {
710
783
  this.v4AccessToken = null;
711
784
  this.v4AccessTokenExpiresAt = null;
785
+ this.invalidReason = res.error.name === "SessionExpiredError" ? "REFRESH_TOKEN_EXPIRED" : "INVALID_SESSION";
786
+ localStorage.removeItem(this.storageKey);
712
787
  }
788
+ this.refreshing = false;
789
+ if (terminal) await this.refreshTokenStore.remove();
713
790
  return {
714
791
  ok: false,
715
792
  error: res.error
716
793
  };
717
794
  }
795
+ this.refreshing = false;
718
796
  this.logger.success("Session refreshed!");
797
+ this.invalidReason = null;
798
+ if (res.data.refreshToken) {
799
+ await this.refreshTokenStore.set(res.data.refreshToken);
800
+ }
719
801
  const now = /* @__PURE__ */ new Date();
720
802
  this.v4AccessToken = res.data.accessToken;
721
803
  this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
@@ -748,6 +830,8 @@ var SessionManager = class {
748
830
  }
749
831
  this.v4AccessToken = null;
750
832
  this.v4AccessTokenExpiresAt = null;
833
+ this.invalidReason = null;
834
+ await this.refreshTokenStore.remove();
751
835
  localStorage.removeItem(this.storageKey);
752
836
  }
753
837
  async verify() {
@@ -755,6 +839,9 @@ var SessionManager = class {
755
839
  this.logger.warn("'localStorage' is not available on the server.");
756
840
  return { valid: true };
757
841
  }
842
+ if (this.invalidReason) {
843
+ return { valid: false, reason: this.invalidReason };
844
+ }
758
845
  const val = localStorage.getItem(this.storageKey);
759
846
  if (val) {
760
847
  try {
@@ -769,11 +856,13 @@ var SessionManager = class {
769
856
  }
770
857
  const s = await this.get();
771
858
  if (s.error?.name === "InvalidTokenError" || s.error?.name === "SessionExpiredError" || s.error?.name === "AccountBlacklistedError") {
859
+ this.invalidReason = "INVALID_SESSION";
772
860
  return { valid: false, reason: "INVALID_SESSION" };
773
861
  }
774
862
  if (!s.data) return { valid: true };
775
863
  const v = await this.authService.verifySession(s.data.accessToken);
776
864
  if (!v) {
865
+ this.invalidReason = "INVALID_SESSION";
777
866
  localStorage.removeItem(this.storageKey);
778
867
  }
779
868
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
@@ -781,16 +870,17 @@ var SessionManager = class {
781
870
  async verifyV4(session) {
782
871
  if (!this.v4AccessToken || !this.v4AccessTokenExpiresAt || isAfter(/* @__PURE__ */ new Date(), new Date(this.v4AccessTokenExpiresAt))) {
783
872
  const res = await this.refreshV4(session);
784
- return res.ok ? { valid: true } : {
785
- valid: false,
786
- reason: res.error.name === "SessionExpiredError" ? "REFRESH_TOKEN_EXPIRED" : "INVALID_SESSION"
787
- };
873
+ if (res.ok) return { valid: true };
874
+ if (!this.invalidReason) return { valid: true };
875
+ return { valid: false, reason: this.invalidReason };
788
876
  }
789
877
  const v = await this.authService.verifySession(this.v4AccessToken);
790
878
  if (!v) {
791
879
  localStorage.removeItem(this.storageKey);
792
880
  this.v4AccessToken = null;
793
881
  this.v4AccessTokenExpiresAt = null;
882
+ this.invalidReason = "INVALID_SESSION";
883
+ await this.refreshTokenStore.remove();
794
884
  }
795
885
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
796
886
  }
@@ -820,16 +910,20 @@ var SessionManagerCookie = class {
820
910
  walletService;
821
911
  _refreshing = false;
822
912
  /*
823
- * v4 access tokens are never persisted (localStorage/cookie) so that an
824
- * XSS-readable storage layer never holds a live access token. They only
825
- * live in memory and get re-minted from the HttpOnly refresh cookie.
913
+ * v4 access tokens live in memory only, so an XSS-readable storage layer
914
+ * never holds a live one. Re-minted from the HttpOnly cookie, or from
915
+ * `refreshTokenStore` on iOS.
826
916
  */
827
917
  v4AccessToken = null;
828
918
  v4AccessTokenExpiresAt = null;
919
+ v4RefreshPromise = null;
920
+ invalidReason = null;
921
+ refreshTokenStore;
829
922
  constructor(config) {
830
923
  this.authService = config.authService;
831
924
  this.walletService = config.walletService;
832
925
  this.logger = config.logger;
926
+ this.refreshTokenStore = createRefreshTokenStore(config.logger);
833
927
  }
834
928
  get refreshing() {
835
929
  return this._refreshing;
@@ -837,15 +931,19 @@ var SessionManagerCookie = class {
837
931
  set refreshing(value) {
838
932
  this._refreshing = value;
839
933
  }
840
- persist(data, version) {
934
+ async persist(data, version) {
841
935
  const now = /* @__PURE__ */ new Date();
936
+ this.invalidReason = null;
842
937
  if (version === 4) {
843
938
  this.v4AccessToken = data.accessToken ?? null;
844
939
  this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
940
+ if (data.refreshToken) {
941
+ await this.refreshTokenStore.set(data.refreshToken);
942
+ }
845
943
  cookies.set(
846
944
  this.storageKey,
847
945
  JSON.stringify({ version, session: data.session }),
848
- { expires: subMinutes(addDays(now, 15), 2).getTime() }
946
+ { expires: subMinutes(addDays(now, 15), 2) }
849
947
  );
850
948
  return;
851
949
  }
@@ -857,7 +955,7 @@ var SessionManagerCookie = class {
857
955
  accessTokenExpiresAt: addMinutes(now, 8).getTime(),
858
956
  refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
859
957
  }),
860
- { expires: subMinutes(addDays(now, 30), 2).getTime() }
958
+ { expires: subMinutes(addDays(now, 30), 2) }
861
959
  );
862
960
  }
863
961
  async create(input, version = 1) {
@@ -886,7 +984,7 @@ var SessionManagerCookie = class {
886
984
  maxAttempt: 5
887
985
  })();
888
986
  if (!r1.ok) return r1;
889
- this.persist(r1.data, version);
987
+ await this.persist(r1.data, version);
890
988
  return {
891
989
  ok: true,
892
990
  data: null
@@ -895,7 +993,7 @@ var SessionManagerCookie = class {
895
993
  if (input.type === "MOBILE_NUMBER") {
896
994
  const res2 = await this.authService.createSession(input, version);
897
995
  if (res2.ok) {
898
- this.persist(res2.data, version);
996
+ await this.persist(res2.data, version);
899
997
  return {
900
998
  ok: true,
901
999
  data: null
@@ -912,7 +1010,7 @@ var SessionManagerCookie = class {
912
1010
  version
913
1011
  );
914
1012
  if (res2.ok) {
915
- this.persist(res2.data, version);
1013
+ await this.persist(res2.data, version);
916
1014
  return {
917
1015
  ok: true,
918
1016
  data: null
@@ -924,7 +1022,7 @@ var SessionManagerCookie = class {
924
1022
  localStorage.setItem(this.platformStorageKey, "CABINET");
925
1023
  const res2 = await this.authService.createSession(input, version);
926
1024
  if (res2.ok) {
927
- this.persist(res2.data, version);
1025
+ await this.persist(res2.data, version);
928
1026
  return {
929
1027
  ok: true,
930
1028
  data: null
@@ -942,7 +1040,7 @@ var SessionManagerCookie = class {
942
1040
  }
943
1041
  };
944
1042
  }
945
- this.persist(res.data, version);
1043
+ await this.persist(res.data, version);
946
1044
  return {
947
1045
  ok: true,
948
1046
  data: null
@@ -954,7 +1052,7 @@ var SessionManagerCookie = class {
954
1052
  if (this.isServer) {
955
1053
  this.logger.warn("'client cookies' is not available on the server.");
956
1054
  } else {
957
- this.persist(res.data, 1);
1055
+ await this.persist(res.data, 1);
958
1056
  }
959
1057
  return { ok: true };
960
1058
  } else {
@@ -1034,7 +1132,7 @@ var SessionManagerCookie = class {
1034
1132
  refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
1035
1133
  };
1036
1134
  cookies.set(this.storageKey, JSON.stringify(obj), {
1037
- expires: subMinutes(addDays(now, 30), 2).getTime()
1135
+ expires: subMinutes(addDays(now, 30), 2)
1038
1136
  });
1039
1137
  }
1040
1138
  return {
@@ -1051,6 +1149,20 @@ var SessionManagerCookie = class {
1051
1149
  };
1052
1150
  }
1053
1151
  }
1152
+ async getV4(session) {
1153
+ const now = /* @__PURE__ */ new Date();
1154
+ if (this.v4AccessToken && this.v4AccessTokenExpiresAt && !isAfter(now, new Date(this.v4AccessTokenExpiresAt))) {
1155
+ return {
1156
+ ok: true,
1157
+ data: {
1158
+ session,
1159
+ accessToken: this.v4AccessToken,
1160
+ accessTokenExpiresAt: this.v4AccessTokenExpiresAt
1161
+ }
1162
+ };
1163
+ }
1164
+ return await this.refreshV4(session);
1165
+ }
1054
1166
  async refresh() {
1055
1167
  if (this.isServer) {
1056
1168
  this.logger.warn("'client cookies' is not available on the server.");
@@ -1106,7 +1218,7 @@ var SessionManagerCookie = class {
1106
1218
  refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
1107
1219
  };
1108
1220
  cookies.set(this.storageKey, JSON.stringify(obj), {
1109
- expires: subMinutes(addDays(now, 30), 2).getTime()
1221
+ expires: subMinutes(addDays(now, 30), 2)
1110
1222
  });
1111
1223
  return {
1112
1224
  ok: true,
@@ -1122,37 +1234,59 @@ var SessionManagerCookie = class {
1122
1234
  };
1123
1235
  }
1124
1236
  }
1125
- async getV4(session) {
1126
- const now = /* @__PURE__ */ new Date();
1127
- if (this.v4AccessToken && this.v4AccessTokenExpiresAt && !isAfter(now, new Date(this.v4AccessTokenExpiresAt))) {
1128
- return {
1129
- ok: true,
1130
- data: {
1131
- session,
1132
- accessToken: this.v4AccessToken,
1133
- accessTokenExpiresAt: this.v4AccessTokenExpiresAt
1134
- }
1135
- };
1237
+ async refreshV4(session) {
1238
+ if (this.v4RefreshPromise) return await this.v4RefreshPromise;
1239
+ this.v4RefreshPromise = this.requestV4Refresh(session);
1240
+ try {
1241
+ return await this.v4RefreshPromise;
1242
+ } finally {
1243
+ this.v4RefreshPromise = null;
1136
1244
  }
1137
- return await this.refreshV4(session);
1138
1245
  }
1139
- async refreshV4(session) {
1246
+ async requestV4Refresh(session) {
1140
1247
  this.logger.info("Refreshing session...");
1248
+ let refreshToken;
1249
+ if (isIOSPlatform()) {
1250
+ refreshToken = await this.refreshTokenStore.get() ?? void 0;
1251
+ if (!refreshToken) {
1252
+ this.logger.warn("No stored refresh token. Session expired.");
1253
+ this.v4AccessToken = null;
1254
+ this.v4AccessTokenExpiresAt = null;
1255
+ this.invalidReason = "REFRESH_TOKEN_EXPIRED";
1256
+ cookies.remove(this.storageKey);
1257
+ return {
1258
+ ok: false,
1259
+ error: {
1260
+ name: "SessionExpiredError",
1261
+ message: "Session expired."
1262
+ }
1263
+ };
1264
+ }
1265
+ }
1141
1266
  this.refreshing = true;
1142
- const res = await this.authService.refreshSession(void 0, 4);
1143
- this.refreshing = false;
1267
+ const res = await this.authService.refreshSession(refreshToken, 4);
1144
1268
  if (!res.ok) {
1145
1269
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
1146
- if (res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError") {
1270
+ const terminal = res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError";
1271
+ if (terminal) {
1147
1272
  this.v4AccessToken = null;
1148
1273
  this.v4AccessTokenExpiresAt = null;
1274
+ this.invalidReason = res.error.name === "SessionExpiredError" ? "REFRESH_TOKEN_EXPIRED" : "INVALID_SESSION";
1275
+ cookies.remove(this.storageKey);
1149
1276
  }
1277
+ this.refreshing = false;
1278
+ if (terminal) await this.refreshTokenStore.remove();
1150
1279
  return {
1151
1280
  ok: false,
1152
1281
  error: res.error
1153
1282
  };
1154
1283
  }
1284
+ this.refreshing = false;
1155
1285
  this.logger.success("Session refreshed!");
1286
+ this.invalidReason = null;
1287
+ if (res.data.refreshToken) {
1288
+ await this.refreshTokenStore.set(res.data.refreshToken);
1289
+ }
1156
1290
  const now = /* @__PURE__ */ new Date();
1157
1291
  this.v4AccessToken = res.data.accessToken;
1158
1292
  this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
@@ -1185,6 +1319,8 @@ var SessionManagerCookie = class {
1185
1319
  }
1186
1320
  this.v4AccessToken = null;
1187
1321
  this.v4AccessTokenExpiresAt = null;
1322
+ this.invalidReason = null;
1323
+ await this.refreshTokenStore.remove();
1188
1324
  cookies.remove(this.storageKey);
1189
1325
  }
1190
1326
  async verify() {
@@ -1192,6 +1328,9 @@ var SessionManagerCookie = class {
1192
1328
  this.logger.warn("'client cookies' is not available on the server.");
1193
1329
  return { valid: true };
1194
1330
  }
1331
+ if (this.invalidReason) {
1332
+ return { valid: false, reason: this.invalidReason };
1333
+ }
1195
1334
  const val = cookies.get(this.storageKey);
1196
1335
  if (val) {
1197
1336
  try {
@@ -1206,11 +1345,13 @@ var SessionManagerCookie = class {
1206
1345
  }
1207
1346
  const s = await this.get();
1208
1347
  if (s.error?.name === "InvalidTokenError" || s.error?.name === "SessionExpiredError" || s.error?.name === "AccountBlacklistedError") {
1348
+ this.invalidReason = "INVALID_SESSION";
1209
1349
  return { valid: false, reason: "INVALID_SESSION" };
1210
1350
  }
1211
1351
  if (!s.data) return { valid: true };
1212
1352
  const v = await this.authService.verifySession(s.data.accessToken);
1213
1353
  if (!v) {
1354
+ this.invalidReason = "INVALID_SESSION";
1214
1355
  cookies.remove(this.storageKey);
1215
1356
  }
1216
1357
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
@@ -1218,16 +1359,17 @@ var SessionManagerCookie = class {
1218
1359
  async verifyV4(session) {
1219
1360
  if (!this.v4AccessToken || !this.v4AccessTokenExpiresAt || isAfter(/* @__PURE__ */ new Date(), new Date(this.v4AccessTokenExpiresAt))) {
1220
1361
  const res = await this.refreshV4(session);
1221
- return res.ok ? { valid: true } : {
1222
- valid: false,
1223
- reason: res.error.name === "SessionExpiredError" ? "REFRESH_TOKEN_EXPIRED" : "INVALID_SESSION"
1224
- };
1362
+ if (res.ok) return { valid: true };
1363
+ if (!this.invalidReason) return { valid: true };
1364
+ return { valid: false, reason: this.invalidReason };
1225
1365
  }
1226
1366
  const v = await this.authService.verifySession(this.v4AccessToken);
1227
1367
  if (!v) {
1228
1368
  cookies.remove(this.storageKey);
1229
1369
  this.v4AccessToken = null;
1230
1370
  this.v4AccessTokenExpiresAt = null;
1371
+ this.invalidReason = "INVALID_SESSION";
1372
+ await this.refreshTokenStore.remove();
1231
1373
  }
1232
1374
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
1233
1375
  }
@@ -3532,9 +3674,18 @@ var Sdk = class {
3532
3674
  let counter = 0;
3533
3675
  let timeout = null;
3534
3676
  let isForeground = true;
3677
+ let stopped = false;
3535
3678
  const listener = App.addListener("appStateChange", ({ isActive }) => {
3536
3679
  isForeground = isActive;
3537
3680
  });
3681
+ const stop = () => {
3682
+ stopped = true;
3683
+ if (timeout) {
3684
+ clearTimeout(timeout);
3685
+ timeout = null;
3686
+ }
3687
+ listener.then((handle) => handle.remove());
3688
+ };
3538
3689
  const assignTimeout = () => {
3539
3690
  const duration = counter <= 0 ? interval * 0.5 : interval;
3540
3691
  return setTimeout(async () => {
@@ -3543,10 +3694,13 @@ var Sdk = class {
3543
3694
  try {
3544
3695
  res = await this.sessionManager.verify();
3545
3696
  } catch {
3546
- res = { valid: false, reason: "INVALID_SESSION" };
3697
+ res = null;
3547
3698
  }
3548
- if (!res.valid) {
3699
+ if (stopped) return;
3700
+ if (res && !res.valid) {
3701
+ stop();
3549
3702
  await input.onInvalid(res.reason ?? "INVALID_SESSION");
3703
+ return;
3550
3704
  }
3551
3705
  }
3552
3706
  counter += 1;
@@ -3555,10 +3709,7 @@ var Sdk = class {
3555
3709
  };
3556
3710
  timeout = assignTimeout();
3557
3711
  return function unsubscribe() {
3558
- if (timeout) {
3559
- clearTimeout(timeout);
3560
- }
3561
- listener.then((handle) => handle.remove());
3712
+ stop();
3562
3713
  };
3563
3714
  }
3564
3715
  async session() {