@opexa/portal-sdk 0.59.94 → 0.59.96

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.
@@ -39,5 +39,5 @@ function callIfFn(value, ...args) {
39
39
  }
40
40
 
41
41
  export { callIfFn, gql, statusCodeToOperationError };
42
- //# sourceMappingURL=chunk-ROBGEUSE.js.map
43
- //# sourceMappingURL=chunk-ROBGEUSE.js.map
42
+ //# sourceMappingURL=chunk-WVFSGB7Y.js.map
43
+ //# sourceMappingURL=chunk-WVFSGB7Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/gql.ts","../src/utils/status-code-to-operation-error.ts","../src/utils/call-if-fn.ts"],"names":[],"mappings":";AAAO,SAAS,GAAA,CAAI,YAAkC,MAAA,EAAmB;AACxE,EAAA,IAAI,MAAA,GAAS,EAAA;AAEb,EAAA,KAAA,MAAW,CAAC,KAAA,EAAO,MAAM,CAAA,IAAK,OAAA,CAAQ,SAAQ,EAAG;AAChD,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,EAAA,CAAG,KAAK,CAAA,IAAK,EAAA;AAElC,IAAA,MAAA,GAAS,CAAA,EAAG,MAAM,CAAA,EAAG,MAAM,GAAG,KAAK,CAAA,CAAA;AAAA,EACpC;AAEA,EAAA,OAAO,OAAO,IAAA,EAAK;AACpB;;;ACRO,SAAS,0BAAA,CACf,OACA,OAAA,EAC4B;AAC5B,EAAA,MAAM,CAAA,GAAI,UAAU,KAAK,CAAA,GAAI,UAAU,KAAK,CAAA,GAAI,UAAU,GAAG,CAAA;AAE7D,EAAA,OAAO;AAAA,IACN,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,OAAA,EAAS,WAAW,CAAA,CAAE;AAAA,GACvB;AACD;AAEA,IAAM,SAAA,GAAuD;AAAA,EAC5D,GAAA,EAAK,EAAE,IAAA,EAAM,gBAAA,EAAkB,SAAS,aAAA,EAAc;AAAA,EACtD,GAAA,EAAK,EAAE,IAAA,EAAM,kBAAA,EAAoB,SAAS,cAAA,EAAe;AAAA,EACzD,GAAA,EAAK,EAAE,IAAA,EAAM,eAAA,EAAiB,SAAS,WAAA,EAAY;AAAA,EACnD,GAAA,EAAK,EAAE,IAAA,EAAM,cAAA,EAAgB,SAAS,WAAA,EAAY;AAAA,EAClD,GAAA,EAAK,EAAE,IAAA,EAAM,oBAAA,EAAsB,SAAS,iBAAA,EAAkB;AAAA,EAC9D,GAAA,EAAK,EAAE,IAAA,EAAM,qBAAA,EAAuB,SAAS,mBAAA,EAAoB;AAAA,EACjE,GAAA,EAAK,EAAE,IAAA,EAAM,yBAAA,EAA2B,SAAS,uBAAA;AAClD,CAAA;;;ACtBA,SAAS,WACR,KAAA,EACuC;AACvC,EAAA,OAAO,OAAO,KAAA,KAAU,UAAA;AACzB;AAEO,SAAS,QAAA,CACf,UACG,IAAA,EACF;AACD,EAAA,IAAI,UAAA,CAAyB,KAAK,CAAA,EAAG;AACpC,IAAA,OAAO,KAAA,CAAM,GAAG,IAAI,CAAA;AAAA,EACrB,CAAA,MAAO;AACN,IAAA,OAAO,KAAA;AAAA,EACR;AACD","file":"chunk-WVFSGB7Y.js","sourcesContent":["export function gql(strings: TemplateStringsArray, ...values: unknown[]) {\r\n\tlet result = '';\r\n\r\n\tfor (const [index, string] of strings.entries()) {\r\n\t\tconst value = values.at(index) ?? '';\r\n\r\n\t\tresult = `${result}${string}${value}`;\r\n\t}\r\n\r\n\treturn result.trim();\r\n}\r\n","import type { HttpError, OperationError } from '../types/index.js';\r\n\r\nexport function statusCodeToOperationError(\r\n\tvalue: number,\r\n\tmessage?: string,\r\n): OperationError<HttpError> {\r\n\tconst e = ERROR_MAP[value] ? ERROR_MAP[value] : ERROR_MAP[500];\r\n\r\n\treturn {\r\n\t\tname: e.name,\r\n\t\tmessage: message ?? e.message,\r\n\t};\r\n}\r\n\r\nconst ERROR_MAP: Record<number, OperationError<HttpError>> = {\r\n\t400: { name: 'HttpBadRequest', message: 'Bad Request' },\r\n\t401: { name: 'HttpUnauthorized', message: 'Unauthorized' },\r\n\t403: { name: 'HttpForbidden', message: 'Forbidden' },\r\n\t404: { name: 'HttpNotFound', message: 'Not Found' },\r\n\t408: { name: 'HttpRequestTimeout', message: 'Request Timeout' },\r\n\t429: { name: 'HttpTooManyRequests', message: 'Too Many Requests' },\r\n\t500: { name: 'HttpInternalServerError', message: 'Internal Server Error' },\r\n};\r\n","function isFunction<Return, Args = never>(\r\n\tvalue: unknown | ((...args: Args[]) => Return),\r\n): value is (...args: Args[]) => Return {\r\n\treturn typeof value === 'function';\r\n}\r\n\r\nexport function callIfFn<Return, Args = never>(\r\n\tvalue: Return | ((...args: Args[]) => Return),\r\n\t...args: Args[]\r\n) {\r\n\tif (isFunction<Return, Args>(value)) {\r\n\t\treturn value(...args);\r\n\t} else {\r\n\t\treturn value;\r\n\t}\r\n}\r\n"]}
package/dist/index.cjs CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var objectId = require('@opexa/object-id');
4
+ var app = require('@capacitor/app');
4
5
  var core = require('@capacitor/core');
5
6
  var thumbmarkjs = require('@thumbmarkjs/thumbmarkjs');
6
7
  var cookies = require('js-cookie');
@@ -4708,6 +4709,20 @@ async function getFingerPrint() {
4708
4709
  return null;
4709
4710
  }
4710
4711
  }
4712
+ function isWebPlatform() {
4713
+ try {
4714
+ return core.Capacitor.getPlatform() === "web";
4715
+ } catch {
4716
+ return true;
4717
+ }
4718
+ }
4719
+ function isIOSPlatform() {
4720
+ try {
4721
+ return core.Capacitor.getPlatform() === "ios";
4722
+ } catch {
4723
+ return false;
4724
+ }
4725
+ }
4711
4726
 
4712
4727
  // src/utils/status-code-to-operation-error.ts
4713
4728
  function statusCodeToOperationError(value, message) {
@@ -4728,13 +4743,6 @@ var ERROR_MAP = {
4728
4743
  };
4729
4744
 
4730
4745
  // src/services/auth.service.ts
4731
- function isWebPlatform() {
4732
- try {
4733
- return core.Capacitor.getPlatform() === "web";
4734
- } catch {
4735
- return false;
4736
- }
4737
- }
4738
4746
  var AuthService = class {
4739
4747
  url;
4740
4748
  options;
@@ -4790,12 +4798,15 @@ var AuthService = class {
4790
4798
  try {
4791
4799
  const isWeb = isWebPlatform();
4792
4800
  const queryParam = isWeb && version === 4 ? "?type=web" : "";
4793
- const res = await fetch(`${this.url}${version !== 1 ? `/v${version}/sessions` : "/sessions"}${queryParam}`, {
4794
- method: "POST",
4795
- headers,
4796
- body: JSON.stringify(input),
4797
- ...version === 4 && { credentials: "include" }
4798
- });
4801
+ const res = await fetch(
4802
+ `${this.url}${version !== 1 ? `/v${version}/sessions` : "/sessions"}${queryParam}`,
4803
+ {
4804
+ method: "POST",
4805
+ headers,
4806
+ body: JSON.stringify(input),
4807
+ ...version === 4 && { credentials: "include" }
4808
+ }
4809
+ );
4799
4810
  const body = await res.json();
4800
4811
  if (res.ok) {
4801
4812
  return {
@@ -4878,7 +4889,7 @@ var AuthService = class {
4878
4889
  }
4879
4890
  async refreshSession(refreshToken, version = 1) {
4880
4891
  const headers = new Headers(this.headers);
4881
- if (version !== 4) {
4892
+ if (version !== 4 || refreshToken) {
4882
4893
  headers.append("Authorization", `Bearer ${refreshToken}`);
4883
4894
  }
4884
4895
  try {
@@ -4992,11 +5003,14 @@ var AuthService = class {
4992
5003
  }
4993
5004
  }
4994
5005
  try {
4995
- const res = await fetch(`${this.url}${version !== 1 ? `/v${version}/otps` : "/otps"}`, {
4996
- method: "POST",
4997
- headers: this.headers,
4998
- body: JSON.stringify(input)
4999
- });
5006
+ const res = await fetch(
5007
+ `${this.url}${version !== 1 ? `/v${version}/otps` : "/otps"}`,
5008
+ {
5009
+ method: "POST",
5010
+ headers: this.headers,
5011
+ body: JSON.stringify(input)
5012
+ }
5013
+ );
5000
5014
  if (res.status === 403) {
5001
5015
  const data = await res.json();
5002
5016
  const code = getErrorCode(data.message);
@@ -7456,6 +7470,48 @@ function pollable(func, config) {
7456
7470
  };
7457
7471
  }
7458
7472
 
7473
+ // src/sdk/refresh-token-store.ts
7474
+ var PreferencesRefreshTokenStore = class {
7475
+ constructor(key, logger) {
7476
+ this.key = key;
7477
+ this.logger = logger;
7478
+ }
7479
+ async preferences() {
7480
+ const { Preferences } = await import('@capacitor/preferences');
7481
+ return Preferences;
7482
+ }
7483
+ async get() {
7484
+ if (!isIOSPlatform()) return null;
7485
+ try {
7486
+ const { value } = await (await this.preferences()).get({ key: this.key });
7487
+ return value ?? null;
7488
+ } catch (err) {
7489
+ this.logger.error(`Failed to read the refresh token: ${err}`);
7490
+ return null;
7491
+ }
7492
+ }
7493
+ async set(token) {
7494
+ if (!isIOSPlatform()) return;
7495
+ try {
7496
+ await (await this.preferences()).set({ key: this.key, value: token });
7497
+ } catch (err) {
7498
+ this.logger.error(`Failed to persist the refresh token: ${err}`);
7499
+ }
7500
+ }
7501
+ async remove() {
7502
+ if (!isIOSPlatform()) return;
7503
+ try {
7504
+ await (await this.preferences()).remove({ key: this.key });
7505
+ } catch (err) {
7506
+ this.logger.error(`Failed to clear the refresh token: ${err}`);
7507
+ }
7508
+ }
7509
+ };
7510
+ function createRefreshTokenStore(logger, sessionPrefix) {
7511
+ const key = sessionPrefix ? `${sessionPrefix}/session/refresh-token` : "session/refresh-token";
7512
+ return new PreferencesRefreshTokenStore(key, logger);
7513
+ }
7514
+
7459
7515
  // src/sdk/session-manager.ts
7460
7516
  var SessionManager = class {
7461
7517
  logger;
@@ -7465,17 +7521,22 @@ var SessionManager = class {
7465
7521
  walletService;
7466
7522
  _refreshing = false;
7467
7523
  /*
7468
- * v4 access tokens are never persisted (localStorage/cookie) so that an
7469
- * XSS-readable storage layer never holds a live access token. They only
7470
- * live in memory and get re-minted from the HttpOnly refresh cookie.
7524
+ * v4 access tokens live in memory only, so an XSS-readable storage layer
7525
+ * never holds a live one. Re-minted from the HttpOnly cookie, or from
7526
+ * `refreshTokenStore` on iOS.
7471
7527
  */
7472
7528
  v4AccessToken = null;
7473
7529
  v4AccessTokenExpiresAt = null;
7474
7530
  v4RefreshPromise = null;
7531
+ refreshTokenStore;
7475
7532
  constructor(config) {
7476
7533
  this.authService = config.authService;
7477
7534
  this.walletService = config.walletService;
7478
7535
  this.logger = config.logger;
7536
+ this.refreshTokenStore = createRefreshTokenStore(
7537
+ config.logger,
7538
+ config.sessionPrefix
7539
+ );
7479
7540
  if (config.sessionPrefix) {
7480
7541
  this.storageKey = `${config.sessionPrefix}/${this.storageKey}`;
7481
7542
  this.platformStorageKey = `${config.sessionPrefix}/${this.platformStorageKey}`;
@@ -7487,7 +7548,7 @@ var SessionManager = class {
7487
7548
  set refreshing(value) {
7488
7549
  this._refreshing = value;
7489
7550
  }
7490
- persist(data, version) {
7551
+ async persist(data, version) {
7491
7552
  const now = /* @__PURE__ */ new Date();
7492
7553
  if (version === 4) {
7493
7554
  if (!data.session || !data.accessToken) {
@@ -7498,6 +7559,9 @@ var SessionManager = class {
7498
7559
  }
7499
7560
  this.v4AccessToken = data.accessToken;
7500
7561
  this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
7562
+ if (data.refreshToken) {
7563
+ await this.refreshTokenStore.set(data.refreshToken);
7564
+ }
7501
7565
  localStorage.setItem(
7502
7566
  this.storageKey,
7503
7567
  JSON.stringify({ version, session: data.session })
@@ -7560,7 +7624,8 @@ var SessionManager = class {
7560
7624
  maxAttempt: 5
7561
7625
  })();
7562
7626
  if (!r1.ok) return r1;
7563
- if (!this.persist(r1.data, version)) return this.malformedResponseError();
7627
+ if (!await this.persist(r1.data, version))
7628
+ return this.malformedResponseError();
7564
7629
  return {
7565
7630
  ok: true,
7566
7631
  data: null
@@ -7569,7 +7634,7 @@ var SessionManager = class {
7569
7634
  if (input.type === "MOBILE_NUMBER") {
7570
7635
  const res2 = await this.authService.createSession(input, version);
7571
7636
  if (res2.ok) {
7572
- if (!this.persist(res2.data, version))
7637
+ if (!await this.persist(res2.data, version))
7573
7638
  return this.malformedResponseError();
7574
7639
  return {
7575
7640
  ok: true,
@@ -7588,7 +7653,7 @@ var SessionManager = class {
7588
7653
  version
7589
7654
  );
7590
7655
  if (res2.ok) {
7591
- if (!this.persist(res2.data, version))
7656
+ if (!await this.persist(res2.data, version))
7592
7657
  return this.malformedResponseError();
7593
7658
  return {
7594
7659
  ok: true,
@@ -7601,7 +7666,7 @@ var SessionManager = class {
7601
7666
  localStorage.setItem(this.platformStorageKey, "CABINET");
7602
7667
  const res2 = await this.authService.createSession(input, version);
7603
7668
  if (res2.ok) {
7604
- if (!this.persist(res2.data, version))
7669
+ if (!await this.persist(res2.data, version))
7605
7670
  return this.malformedResponseError();
7606
7671
  return {
7607
7672
  ok: true,
@@ -7620,7 +7685,8 @@ var SessionManager = class {
7620
7685
  }
7621
7686
  };
7622
7687
  }
7623
- if (!this.persist(res.data, version)) return this.malformedResponseError();
7688
+ if (!await this.persist(res.data, version))
7689
+ return this.malformedResponseError();
7624
7690
  return {
7625
7691
  ok: true,
7626
7692
  data: null
@@ -7631,7 +7697,7 @@ var SessionManager = class {
7631
7697
  if (res.ok) {
7632
7698
  if (this.isServer) {
7633
7699
  this.logger.warn("'localStorage' is not available on the server.");
7634
- } else if (!this.persist(res.data, 1)) {
7700
+ } else if (!await this.persist(res.data, 1)) {
7635
7701
  return this.malformedResponseError();
7636
7702
  }
7637
7703
  return { ok: true };
@@ -7821,14 +7887,31 @@ var SessionManager = class {
7821
7887
  }
7822
7888
  async requestV4Refresh(session) {
7823
7889
  this.logger.info("Refreshing session...");
7890
+ let refreshToken;
7891
+ if (isIOSPlatform()) {
7892
+ refreshToken = await this.refreshTokenStore.get() ?? void 0;
7893
+ if (!refreshToken) {
7894
+ this.logger.warn("No stored refresh token. Session expired.");
7895
+ this.v4AccessToken = null;
7896
+ this.v4AccessTokenExpiresAt = null;
7897
+ return {
7898
+ ok: false,
7899
+ error: {
7900
+ name: "SessionExpiredError",
7901
+ message: "Session expired."
7902
+ }
7903
+ };
7904
+ }
7905
+ }
7824
7906
  this.refreshing = true;
7825
- const res = await this.authService.refreshSession(void 0, 4);
7907
+ const res = await this.authService.refreshSession(refreshToken, 4);
7826
7908
  this.refreshing = false;
7827
7909
  if (!res.ok) {
7828
7910
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
7829
7911
  if (res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError") {
7830
7912
  this.v4AccessToken = null;
7831
7913
  this.v4AccessTokenExpiresAt = null;
7914
+ await this.refreshTokenStore.remove();
7832
7915
  }
7833
7916
  return {
7834
7917
  ok: false,
@@ -7836,6 +7919,9 @@ var SessionManager = class {
7836
7919
  };
7837
7920
  }
7838
7921
  this.logger.success("Session refreshed!");
7922
+ if (res.data.refreshToken) {
7923
+ await this.refreshTokenStore.set(res.data.refreshToken);
7924
+ }
7839
7925
  const now = /* @__PURE__ */ new Date();
7840
7926
  this.v4AccessToken = res.data.accessToken;
7841
7927
  this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
@@ -7868,6 +7954,7 @@ var SessionManager = class {
7868
7954
  }
7869
7955
  this.v4AccessToken = null;
7870
7956
  this.v4AccessTokenExpiresAt = null;
7957
+ await this.refreshTokenStore.remove();
7871
7958
  localStorage.removeItem(this.storageKey);
7872
7959
  }
7873
7960
  async verify() {
@@ -7911,6 +7998,7 @@ var SessionManager = class {
7911
7998
  localStorage.removeItem(this.storageKey);
7912
7999
  this.v4AccessToken = null;
7913
8000
  this.v4AccessTokenExpiresAt = null;
8001
+ await this.refreshTokenStore.remove();
7914
8002
  }
7915
8003
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
7916
8004
  }
@@ -7940,16 +8028,19 @@ var SessionManagerCookie = class {
7940
8028
  walletService;
7941
8029
  _refreshing = false;
7942
8030
  /*
7943
- * v4 access tokens are never persisted (localStorage/cookie) so that an
7944
- * XSS-readable storage layer never holds a live access token. They only
7945
- * live in memory and get re-minted from the HttpOnly refresh cookie.
8031
+ * v4 access tokens live in memory only, so an XSS-readable storage layer
8032
+ * never holds a live one. Re-minted from the HttpOnly cookie, or from
8033
+ * `refreshTokenStore` on iOS.
7946
8034
  */
7947
8035
  v4AccessToken = null;
7948
8036
  v4AccessTokenExpiresAt = null;
8037
+ v4RefreshPromise = null;
8038
+ refreshTokenStore;
7949
8039
  constructor(config) {
7950
8040
  this.authService = config.authService;
7951
8041
  this.walletService = config.walletService;
7952
8042
  this.logger = config.logger;
8043
+ this.refreshTokenStore = createRefreshTokenStore(config.logger);
7953
8044
  }
7954
8045
  get refreshing() {
7955
8046
  return this._refreshing;
@@ -7957,15 +8048,18 @@ var SessionManagerCookie = class {
7957
8048
  set refreshing(value) {
7958
8049
  this._refreshing = value;
7959
8050
  }
7960
- persist(data, version) {
8051
+ async persist(data, version) {
7961
8052
  const now = /* @__PURE__ */ new Date();
7962
8053
  if (version === 4) {
7963
8054
  this.v4AccessToken = data.accessToken ?? null;
7964
8055
  this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
8056
+ if (data.refreshToken) {
8057
+ await this.refreshTokenStore.set(data.refreshToken);
8058
+ }
7965
8059
  cookies__default.default.set(
7966
8060
  this.storageKey,
7967
8061
  JSON.stringify({ version, session: data.session }),
7968
- { expires: subMinutes(addDays(now, 15), 2).getTime() }
8062
+ { expires: subMinutes(addDays(now, 15), 2) }
7969
8063
  );
7970
8064
  return;
7971
8065
  }
@@ -7977,7 +8071,7 @@ var SessionManagerCookie = class {
7977
8071
  accessTokenExpiresAt: addMinutes(now, 8).getTime(),
7978
8072
  refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
7979
8073
  }),
7980
- { expires: subMinutes(addDays(now, 30), 2).getTime() }
8074
+ { expires: subMinutes(addDays(now, 30), 2) }
7981
8075
  );
7982
8076
  }
7983
8077
  async create(input, version = 1) {
@@ -8006,7 +8100,7 @@ var SessionManagerCookie = class {
8006
8100
  maxAttempt: 5
8007
8101
  })();
8008
8102
  if (!r1.ok) return r1;
8009
- this.persist(r1.data, version);
8103
+ await this.persist(r1.data, version);
8010
8104
  return {
8011
8105
  ok: true,
8012
8106
  data: null
@@ -8015,7 +8109,7 @@ var SessionManagerCookie = class {
8015
8109
  if (input.type === "MOBILE_NUMBER") {
8016
8110
  const res2 = await this.authService.createSession(input, version);
8017
8111
  if (res2.ok) {
8018
- this.persist(res2.data, version);
8112
+ await this.persist(res2.data, version);
8019
8113
  return {
8020
8114
  ok: true,
8021
8115
  data: null
@@ -8032,7 +8126,7 @@ var SessionManagerCookie = class {
8032
8126
  version
8033
8127
  );
8034
8128
  if (res2.ok) {
8035
- this.persist(res2.data, version);
8129
+ await this.persist(res2.data, version);
8036
8130
  return {
8037
8131
  ok: true,
8038
8132
  data: null
@@ -8044,7 +8138,7 @@ var SessionManagerCookie = class {
8044
8138
  localStorage.setItem(this.platformStorageKey, "CABINET");
8045
8139
  const res2 = await this.authService.createSession(input, version);
8046
8140
  if (res2.ok) {
8047
- this.persist(res2.data, version);
8141
+ await this.persist(res2.data, version);
8048
8142
  return {
8049
8143
  ok: true,
8050
8144
  data: null
@@ -8062,7 +8156,7 @@ var SessionManagerCookie = class {
8062
8156
  }
8063
8157
  };
8064
8158
  }
8065
- this.persist(res.data, version);
8159
+ await this.persist(res.data, version);
8066
8160
  return {
8067
8161
  ok: true,
8068
8162
  data: null
@@ -8074,7 +8168,7 @@ var SessionManagerCookie = class {
8074
8168
  if (this.isServer) {
8075
8169
  this.logger.warn("'client cookies' is not available on the server.");
8076
8170
  } else {
8077
- this.persist(res.data, 1);
8171
+ await this.persist(res.data, 1);
8078
8172
  }
8079
8173
  return { ok: true };
8080
8174
  } else {
@@ -8154,7 +8248,7 @@ var SessionManagerCookie = class {
8154
8248
  refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
8155
8249
  };
8156
8250
  cookies__default.default.set(this.storageKey, JSON.stringify(obj), {
8157
- expires: subMinutes(addDays(now, 30), 2).getTime()
8251
+ expires: subMinutes(addDays(now, 30), 2)
8158
8252
  });
8159
8253
  }
8160
8254
  return {
@@ -8226,7 +8320,7 @@ var SessionManagerCookie = class {
8226
8320
  refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
8227
8321
  };
8228
8322
  cookies__default.default.set(this.storageKey, JSON.stringify(obj), {
8229
- expires: subMinutes(addDays(now, 30), 2).getTime()
8323
+ expires: subMinutes(addDays(now, 30), 2)
8230
8324
  });
8231
8325
  return {
8232
8326
  ok: true,
@@ -8257,15 +8351,41 @@ var SessionManagerCookie = class {
8257
8351
  return await this.refreshV4(session);
8258
8352
  }
8259
8353
  async refreshV4(session) {
8354
+ if (this.v4RefreshPromise) return await this.v4RefreshPromise;
8355
+ this.v4RefreshPromise = this.requestV4Refresh(session);
8356
+ try {
8357
+ return await this.v4RefreshPromise;
8358
+ } finally {
8359
+ this.v4RefreshPromise = null;
8360
+ }
8361
+ }
8362
+ async requestV4Refresh(session) {
8260
8363
  this.logger.info("Refreshing session...");
8364
+ let refreshToken;
8365
+ if (isIOSPlatform()) {
8366
+ refreshToken = await this.refreshTokenStore.get() ?? void 0;
8367
+ if (!refreshToken) {
8368
+ this.logger.warn("No stored refresh token. Session expired.");
8369
+ this.v4AccessToken = null;
8370
+ this.v4AccessTokenExpiresAt = null;
8371
+ return {
8372
+ ok: false,
8373
+ error: {
8374
+ name: "SessionExpiredError",
8375
+ message: "Session expired."
8376
+ }
8377
+ };
8378
+ }
8379
+ }
8261
8380
  this.refreshing = true;
8262
- const res = await this.authService.refreshSession(void 0, 4);
8381
+ const res = await this.authService.refreshSession(refreshToken, 4);
8263
8382
  this.refreshing = false;
8264
8383
  if (!res.ok) {
8265
8384
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
8266
8385
  if (res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError") {
8267
8386
  this.v4AccessToken = null;
8268
8387
  this.v4AccessTokenExpiresAt = null;
8388
+ await this.refreshTokenStore.remove();
8269
8389
  }
8270
8390
  return {
8271
8391
  ok: false,
@@ -8273,6 +8393,9 @@ var SessionManagerCookie = class {
8273
8393
  };
8274
8394
  }
8275
8395
  this.logger.success("Session refreshed!");
8396
+ if (res.data.refreshToken) {
8397
+ await this.refreshTokenStore.set(res.data.refreshToken);
8398
+ }
8276
8399
  const now = /* @__PURE__ */ new Date();
8277
8400
  this.v4AccessToken = res.data.accessToken;
8278
8401
  this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
@@ -8305,6 +8428,7 @@ var SessionManagerCookie = class {
8305
8428
  }
8306
8429
  this.v4AccessToken = null;
8307
8430
  this.v4AccessTokenExpiresAt = null;
8431
+ await this.refreshTokenStore.remove();
8308
8432
  cookies__default.default.remove(this.storageKey);
8309
8433
  }
8310
8434
  async verify() {
@@ -8348,6 +8472,7 @@ var SessionManagerCookie = class {
8348
8472
  cookies__default.default.remove(this.storageKey);
8349
8473
  this.v4AccessToken = null;
8350
8474
  this.v4AccessTokenExpiresAt = null;
8475
+ await this.refreshTokenStore.remove();
8351
8476
  }
8352
8477
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
8353
8478
  }
@@ -10651,10 +10776,14 @@ var Sdk = class {
10651
10776
  const interval = clamp(input.interval ?? 3e4, 5e3, 6e4);
10652
10777
  let counter = 0;
10653
10778
  let timeout = null;
10779
+ let isForeground = true;
10780
+ const listener = app.App.addListener("appStateChange", ({ isActive }) => {
10781
+ isForeground = isActive;
10782
+ });
10654
10783
  const assignTimeout = () => {
10655
10784
  const duration = counter <= 0 ? interval * 0.5 : interval;
10656
10785
  return setTimeout(async () => {
10657
- {
10786
+ if (isForeground) {
10658
10787
  let res;
10659
10788
  try {
10660
10789
  res = await this.sessionManager.verify();
@@ -10674,6 +10803,7 @@ var Sdk = class {
10674
10803
  if (timeout) {
10675
10804
  clearTimeout(timeout);
10676
10805
  }
10806
+ listener.then((handle) => handle.remove());
10677
10807
  };
10678
10808
  }
10679
10809
  async session() {