@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.cjs CHANGED
@@ -344,9 +344,6 @@ var CREATE_GAME_SESSION_MUTATION = gql`
344
344
  ... on GameTypeNotEnabledError {
345
345
  __typename
346
346
  }
347
- ... on GameNotEnabledError {
348
- __typename
349
- }
350
347
  }
351
348
  }
352
349
  `;
@@ -4097,7 +4094,6 @@ function createOperationError(code) {
4097
4094
  FileNotReadyError: "File is not yet ready",
4098
4095
  FileSizeTooBigError: "File size is too big",
4099
4096
  GameDoesNotExistError: "Game does not exist",
4100
- GameNotEnabledError: "Game is not enabled",
4101
4097
  InsufficientPointsError: "Insufficient points",
4102
4098
  InvalidPlatformError: "Invalid platform",
4103
4099
  InvalidReCAPTCHAResponseError: "Invalid reCAPTCHA",
@@ -4886,6 +4882,15 @@ var ERROR_MAP = {
4886
4882
  };
4887
4883
 
4888
4884
  // src/services/auth.service.ts
4885
+ function getCompatibleSignal(signal) {
4886
+ if (!signal) return void 0;
4887
+ try {
4888
+ new Request("about:blank", { signal });
4889
+ return signal;
4890
+ } catch {
4891
+ return void 0;
4892
+ }
4893
+ }
4889
4894
  var AuthService = class {
4890
4895
  url;
4891
4896
  graphqlClient;
@@ -5053,7 +5058,7 @@ var AuthService = class {
5053
5058
  }
5054
5059
  throw new Error("Invalid input 'type'");
5055
5060
  }
5056
- async refreshSession(refreshToken, version = 1) {
5061
+ async refreshSession(refreshToken, version = 1, signal) {
5057
5062
  const headers = new Headers(this.headers);
5058
5063
  if (version !== 4 || refreshToken) {
5059
5064
  headers.append("Authorization", `Bearer ${refreshToken}`);
@@ -5072,6 +5077,7 @@ var AuthService = class {
5072
5077
  {
5073
5078
  method: "POST",
5074
5079
  headers,
5080
+ signal: getCompatibleSignal(signal),
5075
5081
  ...version === 4 && { credentials: "include" }
5076
5082
  }
5077
5083
  );
@@ -5140,13 +5146,14 @@ var AuthService = class {
5140
5146
  return { ok: false, error: statusCodeToOperationError(500) };
5141
5147
  }
5142
5148
  }
5143
- async verifySession(accessToken) {
5149
+ async verifySession(accessToken, signal) {
5144
5150
  const headers = new Headers(this.headers);
5145
5151
  headers.append("Authorization", `Bearer ${accessToken}`);
5146
5152
  try {
5147
5153
  const res = await fetch(`${this.url}/session`, {
5148
5154
  method: "GET",
5149
- headers
5155
+ headers,
5156
+ signal: getCompatibleSignal(signal)
5150
5157
  });
5151
5158
  return res.ok;
5152
5159
  } catch {
@@ -7741,6 +7748,36 @@ function createRefreshTokenStore(logger, sessionPrefix) {
7741
7748
  return new PreferencesRefreshTokenStore(key, logger);
7742
7749
  }
7743
7750
 
7751
+ // src/sdk/session-lifecycle.ts
7752
+ var SessionLifecycle = class {
7753
+ controller = new AbortController();
7754
+ get signal() {
7755
+ return this.controller.signal;
7756
+ }
7757
+ renew() {
7758
+ this.controller.abort();
7759
+ this.controller = new AbortController();
7760
+ return this.controller.signal;
7761
+ }
7762
+ logout() {
7763
+ this.renew();
7764
+ }
7765
+ };
7766
+ var CredentialMutationLock = class {
7767
+ tail = Promise.resolve();
7768
+ wait() {
7769
+ return this.tail;
7770
+ }
7771
+ run(operation) {
7772
+ const result = this.tail.then(operation, operation);
7773
+ this.tail = result.then(
7774
+ () => void 0,
7775
+ () => void 0
7776
+ );
7777
+ return result;
7778
+ }
7779
+ };
7780
+
7744
7781
  // src/sdk/session-manager.ts
7745
7782
  var SessionManager = class {
7746
7783
  logger;
@@ -7749,6 +7786,8 @@ var SessionManager = class {
7749
7786
  authService;
7750
7787
  walletService;
7751
7788
  _refreshing = false;
7789
+ lifecycle = new SessionLifecycle();
7790
+ mutations = new CredentialMutationLock();
7752
7791
  /*
7753
7792
  * v4 access tokens live in memory only, so an XSS-readable storage layer
7754
7793
  * never holds a live one. Re-minted from the HttpOnly cookie, or from
@@ -7778,38 +7817,44 @@ var SessionManager = class {
7778
7817
  set refreshing(value) {
7779
7818
  this._refreshing = value;
7780
7819
  }
7781
- async persist(data, version) {
7782
- const now = /* @__PURE__ */ new Date();
7783
- if (version === 4) {
7784
- if (!data.session || !data.accessToken) {
7785
- this.logger.error(
7786
- "Malformed session response: expected 'session' and 'accessToken'."
7820
+ async persist(data, version, signal) {
7821
+ return this.mutations.run(async () => {
7822
+ if (signal.aborted) return true;
7823
+ const now = /* @__PURE__ */ new Date();
7824
+ this.refreshing = false;
7825
+ this.v4RefreshPromise = null;
7826
+ if (version === 4) {
7827
+ if (!data.session || !data.accessToken) {
7828
+ this.logger.error(
7829
+ "Malformed session response: expected 'session' and 'accessToken'."
7830
+ );
7831
+ return false;
7832
+ }
7833
+ this.v4AccessToken = data.accessToken;
7834
+ this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
7835
+ this.invalidReason = null;
7836
+ if (data.refreshToken) {
7837
+ await this.refreshTokenStore.set(data.refreshToken);
7838
+ }
7839
+ if (signal.aborted) return true;
7840
+ localStorage.setItem(
7841
+ this.storageKey,
7842
+ JSON.stringify({ version, session: data.session })
7787
7843
  );
7788
- return false;
7844
+ return true;
7789
7845
  }
7790
- this.v4AccessToken = data.accessToken;
7791
- this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
7792
7846
  this.invalidReason = null;
7793
- if (data.refreshToken) {
7794
- await this.refreshTokenStore.set(data.refreshToken);
7795
- }
7796
7847
  localStorage.setItem(
7797
7848
  this.storageKey,
7798
- JSON.stringify({ version, session: data.session })
7849
+ JSON.stringify({
7850
+ version,
7851
+ ...data,
7852
+ accessTokenExpiresAt: addMinutes(now, 8).getTime(),
7853
+ refreshTokenExpiresAt: subMinutes(addDays(now, 1), 2).getTime()
7854
+ })
7799
7855
  );
7800
7856
  return true;
7801
- }
7802
- this.invalidReason = null;
7803
- localStorage.setItem(
7804
- this.storageKey,
7805
- JSON.stringify({
7806
- version,
7807
- ...data,
7808
- accessTokenExpiresAt: addMinutes(now, 8).getTime(),
7809
- refreshTokenExpiresAt: subMinutes(addDays(now, 1), 2).getTime()
7810
- })
7811
- );
7812
- return true;
7857
+ });
7813
7858
  }
7814
7859
  malformedResponseError() {
7815
7860
  return {
@@ -7821,6 +7866,10 @@ var SessionManager = class {
7821
7866
  };
7822
7867
  }
7823
7868
  async create(input, version = 1) {
7869
+ const waitingSignal = this.lifecycle.signal;
7870
+ await this.mutations.wait();
7871
+ if (waitingSignal.aborted) return { ok: true, data: null };
7872
+ const signal = this.lifecycle.renew();
7824
7873
  if (this.isServer) {
7825
7874
  this.logger.warn("'localStorage' is not available on the server.");
7826
7875
  return {
@@ -7856,7 +7905,7 @@ var SessionManager = class {
7856
7905
  maxAttempt: 5
7857
7906
  })();
7858
7907
  if (!r1.ok) return r1;
7859
- if (!await this.persist(r1.data, version))
7908
+ if (!await this.persist(r1.data, version, signal))
7860
7909
  return this.malformedResponseError();
7861
7910
  return {
7862
7911
  ok: true,
@@ -7866,7 +7915,7 @@ var SessionManager = class {
7866
7915
  if (input.type === "MOBILE_NUMBER") {
7867
7916
  const res2 = await this.authService.createSession(input, version);
7868
7917
  if (res2.ok) {
7869
- if (!await this.persist(res2.data, version))
7918
+ if (!await this.persist(res2.data, version, signal))
7870
7919
  return this.malformedResponseError();
7871
7920
  return {
7872
7921
  ok: true,
@@ -7885,7 +7934,7 @@ var SessionManager = class {
7885
7934
  version
7886
7935
  );
7887
7936
  if (res2.ok) {
7888
- if (!await this.persist(res2.data, version))
7937
+ if (!await this.persist(res2.data, version, signal))
7889
7938
  return this.malformedResponseError();
7890
7939
  return {
7891
7940
  ok: true,
@@ -7898,7 +7947,7 @@ var SessionManager = class {
7898
7947
  localStorage.setItem(this.platformStorageKey, "CABINET");
7899
7948
  const res2 = await this.authService.createSession(input, version);
7900
7949
  if (res2.ok) {
7901
- if (!await this.persist(res2.data, version))
7950
+ if (!await this.persist(res2.data, version, signal))
7902
7951
  return this.malformedResponseError();
7903
7952
  return {
7904
7953
  ok: true,
@@ -7917,7 +7966,7 @@ var SessionManager = class {
7917
7966
  }
7918
7967
  };
7919
7968
  }
7920
- if (!await this.persist(res.data, version))
7969
+ if (!await this.persist(res.data, version, signal))
7921
7970
  return this.malformedResponseError();
7922
7971
  return {
7923
7972
  ok: true,
@@ -7925,11 +7974,15 @@ var SessionManager = class {
7925
7974
  };
7926
7975
  }
7927
7976
  async createFromAuthenticator(input) {
7977
+ const waitingSignal = this.lifecycle.signal;
7978
+ await this.mutations.wait();
7979
+ if (waitingSignal.aborted) return { ok: true };
7980
+ const signal = this.lifecycle.renew();
7928
7981
  const res = await this.authService.authenticate(input);
7929
7982
  if (res.ok) {
7930
7983
  if (this.isServer) {
7931
7984
  this.logger.warn("'localStorage' is not available on the server.");
7932
- } else if (!await this.persist(res.data, 1)) {
7985
+ } else if (!await this.persist(res.data, 1, signal)) {
7933
7986
  return this.malformedResponseError();
7934
7987
  }
7935
7988
  return { ok: true };
@@ -7938,6 +7991,7 @@ var SessionManager = class {
7938
7991
  }
7939
7992
  }
7940
7993
  async get() {
7994
+ const signal = this.lifecycle.signal;
7941
7995
  if (this.isServer) {
7942
7996
  this.logger.warn("'localStorage' is not available on the server.");
7943
7997
  return {
@@ -7947,6 +8001,7 @@ var SessionManager = class {
7947
8001
  }
7948
8002
  if (this.refreshing) {
7949
8003
  await sleep(1e3);
8004
+ if (signal.aborted) return { ok: true, data: null };
7950
8005
  return await this.get();
7951
8006
  }
7952
8007
  const val = localStorage.getItem(this.storageKey);
@@ -7981,8 +8036,10 @@ var SessionManager = class {
7981
8036
  this.refreshing = true;
7982
8037
  const res = await this.authService.refreshSession(
7983
8038
  obj.refreshToken,
7984
- obj.version ?? 1
8039
+ obj.version ?? 1,
8040
+ signal
7985
8041
  );
8042
+ if (signal.aborted) return { ok: true, data: null };
7986
8043
  this.refreshing = false;
7987
8044
  if (!res.ok) {
7988
8045
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
@@ -8015,6 +8072,8 @@ var SessionManager = class {
8015
8072
  data: obj
8016
8073
  };
8017
8074
  } catch {
8075
+ if (signal.aborted) return { ok: true, data: null };
8076
+ this.refreshing = false;
8018
8077
  return {
8019
8078
  ok: false,
8020
8079
  error: {
@@ -8039,6 +8098,7 @@ var SessionManager = class {
8039
8098
  return await this.refreshV4(session);
8040
8099
  }
8041
8100
  async refresh() {
8101
+ const signal = this.lifecycle.signal;
8042
8102
  if (this.isServer) {
8043
8103
  this.logger.warn("'localStorage' is not available on the server.");
8044
8104
  return {
@@ -8064,8 +8124,10 @@ var SessionManager = class {
8064
8124
  this.refreshing = true;
8065
8125
  const res = await this.authService.refreshSession(
8066
8126
  obj.refreshToken,
8067
- obj.version ?? 1
8127
+ obj.version ?? 1,
8128
+ signal
8068
8129
  );
8130
+ if (signal.aborted) return { ok: true, data: null };
8069
8131
  this.refreshing = false;
8070
8132
  if (!res.ok) {
8071
8133
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
@@ -8098,6 +8160,8 @@ var SessionManager = class {
8098
8160
  data: obj
8099
8161
  };
8100
8162
  } catch {
8163
+ if (signal.aborted) return { ok: true, data: null };
8164
+ this.refreshing = false;
8101
8165
  return {
8102
8166
  ok: false,
8103
8167
  error: {
@@ -8109,18 +8173,20 @@ var SessionManager = class {
8109
8173
  }
8110
8174
  async refreshV4(session) {
8111
8175
  if (this.v4RefreshPromise) return await this.v4RefreshPromise;
8112
- this.v4RefreshPromise = this.requestV4Refresh(session);
8176
+ const promise = this.requestV4Refresh(session, this.lifecycle.signal);
8177
+ this.v4RefreshPromise = promise;
8113
8178
  try {
8114
- return await this.v4RefreshPromise;
8179
+ return await promise;
8115
8180
  } finally {
8116
- this.v4RefreshPromise = null;
8181
+ if (this.v4RefreshPromise === promise) this.v4RefreshPromise = null;
8117
8182
  }
8118
8183
  }
8119
- async requestV4Refresh(session) {
8184
+ async requestV4Refresh(session, signal) {
8120
8185
  this.logger.info("Refreshing session...");
8121
8186
  let refreshToken;
8122
8187
  if (isIOSPlatform()) {
8123
8188
  refreshToken = await this.refreshTokenStore.get() ?? void 0;
8189
+ if (signal.aborted) return { ok: true, data: null };
8124
8190
  if (!refreshToken) {
8125
8191
  this.logger.warn("No stored refresh token. Session expired.");
8126
8192
  this.v4AccessToken = null;
@@ -8137,7 +8203,8 @@ var SessionManager = class {
8137
8203
  }
8138
8204
  }
8139
8205
  this.refreshing = true;
8140
- const res = await this.authService.refreshSession(refreshToken, 4);
8206
+ const res = await this.authService.refreshSession(refreshToken, 4, signal);
8207
+ if (signal.aborted) return { ok: true, data: null };
8141
8208
  if (!res.ok) {
8142
8209
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
8143
8210
  const terminal = res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError";
@@ -8149,6 +8216,7 @@ var SessionManager = class {
8149
8216
  }
8150
8217
  this.refreshing = false;
8151
8218
  if (terminal) await this.refreshTokenStore.remove();
8219
+ if (signal.aborted) return { ok: true, data: null };
8152
8220
  return {
8153
8221
  ok: false,
8154
8222
  error: res.error
@@ -8158,8 +8226,13 @@ var SessionManager = class {
8158
8226
  this.logger.success("Session refreshed!");
8159
8227
  this.invalidReason = null;
8160
8228
  if (res.data.refreshToken) {
8161
- await this.refreshTokenStore.set(res.data.refreshToken);
8229
+ await this.mutations.run(async () => {
8230
+ if (!signal.aborted && res.data.refreshToken) {
8231
+ await this.refreshTokenStore.set(res.data.refreshToken);
8232
+ }
8233
+ });
8162
8234
  }
8235
+ if (signal.aborted) return { ok: true, data: null };
8163
8236
  const now = /* @__PURE__ */ new Date();
8164
8237
  this.v4AccessToken = res.data.accessToken;
8165
8238
  this.v4AccessTokenExpiresAt = addMinutes(now, 4).getTime();
@@ -8177,26 +8250,53 @@ var SessionManager = class {
8177
8250
  this.logger.warn("'localStorage' is not available on the server.");
8178
8251
  return;
8179
8252
  }
8180
- let version = 1;
8253
+ let version = this.v4AccessToken ? 4 : 1;
8254
+ let accessToken = this.v4AccessToken ?? void 0;
8255
+ let accessTokenExpiresAt = this.v4AccessTokenExpiresAt;
8256
+ let refreshToken;
8181
8257
  const val = localStorage.getItem(this.storageKey);
8182
8258
  if (val) {
8183
8259
  try {
8184
8260
  const stored = JSON.parse(val);
8185
8261
  version = stored.version ?? 1;
8262
+ accessToken = stored.version === 4 ? this.v4AccessToken ?? void 0 : stored.accessToken;
8263
+ accessTokenExpiresAt = stored.version === 4 ? this.v4AccessTokenExpiresAt : stored.accessTokenExpiresAt;
8264
+ if (stored.version !== 4) refreshToken = stored.refreshToken;
8186
8265
  } catch {
8187
8266
  }
8188
8267
  }
8189
- const res = await this.get();
8190
- if (res.data?.accessToken) {
8191
- await this.authService.destroySession(res.data.accessToken, version);
8192
- }
8268
+ this.lifecycle.logout();
8269
+ this.refreshing = false;
8270
+ this.v4RefreshPromise = null;
8193
8271
  this.v4AccessToken = null;
8194
8272
  this.v4AccessTokenExpiresAt = null;
8195
8273
  this.invalidReason = null;
8196
- await this.refreshTokenStore.remove();
8197
8274
  localStorage.removeItem(this.storageKey);
8275
+ await this.mutations.run(async () => {
8276
+ try {
8277
+ if (val && (!accessToken || !accessTokenExpiresAt || Date.now() > accessTokenExpiresAt)) {
8278
+ if (version === 4 && isIOSPlatform()) {
8279
+ refreshToken = await this.refreshTokenStore.get() ?? void 0;
8280
+ }
8281
+ if (refreshToken || version === 4 && !isIOSPlatform()) {
8282
+ accessToken = void 0;
8283
+ const res = await this.authService.refreshSession(
8284
+ refreshToken,
8285
+ version
8286
+ );
8287
+ if (res.ok) accessToken = res.data.accessToken;
8288
+ }
8289
+ }
8290
+ if (accessToken) {
8291
+ await this.authService.destroySession(accessToken, version);
8292
+ }
8293
+ } finally {
8294
+ if (version === 4) await this.refreshTokenStore.remove();
8295
+ }
8296
+ });
8198
8297
  }
8199
8298
  async verify() {
8299
+ const signal = this.lifecycle.signal;
8200
8300
  if (this.isServer) {
8201
8301
  this.logger.warn("'localStorage' is not available on the server.");
8202
8302
  return { valid: true };
@@ -8209,7 +8309,8 @@ var SessionManager = class {
8209
8309
  try {
8210
8310
  const stored = JSON.parse(val);
8211
8311
  if (stored.version === 4) {
8212
- const res = await this.verifyV4(stored.session);
8312
+ const res = await this.verifyV4(stored.session, signal);
8313
+ if (signal.aborted) return { valid: true };
8213
8314
  if (!res.valid) localStorage.removeItem(this.storageKey);
8214
8315
  return res;
8215
8316
  }
@@ -8217,32 +8318,37 @@ var SessionManager = class {
8217
8318
  }
8218
8319
  }
8219
8320
  const s = await this.get();
8321
+ if (signal.aborted) return { valid: true };
8220
8322
  if (s.error?.name === "InvalidTokenError" || s.error?.name === "SessionExpiredError" || s.error?.name === "AccountBlacklistedError") {
8221
8323
  this.invalidReason = "INVALID_SESSION";
8222
8324
  return { valid: false, reason: "INVALID_SESSION" };
8223
8325
  }
8224
8326
  if (!s.data) return { valid: true };
8225
- const v = await this.authService.verifySession(s.data.accessToken);
8327
+ const v = await this.authService.verifySession(s.data.accessToken, signal);
8328
+ if (signal.aborted) return { valid: true };
8226
8329
  if (!v) {
8227
8330
  this.invalidReason = "INVALID_SESSION";
8228
8331
  localStorage.removeItem(this.storageKey);
8229
8332
  }
8230
8333
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
8231
8334
  }
8232
- async verifyV4(session) {
8335
+ async verifyV4(session, signal) {
8233
8336
  if (!this.v4AccessToken || !this.v4AccessTokenExpiresAt || isAfter(/* @__PURE__ */ new Date(), new Date(this.v4AccessTokenExpiresAt))) {
8234
8337
  const res = await this.refreshV4(session);
8338
+ if (signal.aborted) return { valid: true };
8235
8339
  if (res.ok) return { valid: true };
8236
8340
  if (!this.invalidReason) return { valid: true };
8237
8341
  return { valid: false, reason: this.invalidReason };
8238
8342
  }
8239
- const v = await this.authService.verifySession(this.v4AccessToken);
8343
+ const v = await this.authService.verifySession(this.v4AccessToken, signal);
8344
+ if (signal.aborted) return { valid: true };
8240
8345
  if (!v) {
8241
8346
  localStorage.removeItem(this.storageKey);
8242
8347
  this.v4AccessToken = null;
8243
8348
  this.v4AccessTokenExpiresAt = null;
8244
8349
  this.invalidReason = "INVALID_SESSION";
8245
8350
  await this.refreshTokenStore.remove();
8351
+ if (signal.aborted) return { valid: true };
8246
8352
  }
8247
8353
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
8248
8354
  }
@@ -8271,6 +8377,8 @@ var SessionManagerCookie = class {
8271
8377
  authService;
8272
8378
  walletService;
8273
8379
  _refreshing = false;
8380
+ lifecycle = new SessionLifecycle();
8381
+ mutations = new CredentialMutationLock();
8274
8382
  /*
8275
8383
  * v4 access tokens live in memory only, so an XSS-readable storage layer
8276
8384
  * never holds a live one. Re-minted from the HttpOnly cookie, or from
@@ -8293,34 +8401,44 @@ var SessionManagerCookie = class {
8293
8401
  set refreshing(value) {
8294
8402
  this._refreshing = value;
8295
8403
  }
8296
- async persist(data, version) {
8297
- const now = /* @__PURE__ */ new Date();
8298
- this.invalidReason = null;
8299
- if (version === 4) {
8300
- this.v4AccessToken = data.accessToken ?? null;
8301
- this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
8302
- if (data.refreshToken) {
8303
- await this.refreshTokenStore.set(data.refreshToken);
8404
+ async persist(data, version, signal) {
8405
+ return this.mutations.run(async () => {
8406
+ if (signal.aborted) return;
8407
+ const now = /* @__PURE__ */ new Date();
8408
+ this.refreshing = false;
8409
+ this.v4RefreshPromise = null;
8410
+ this.invalidReason = null;
8411
+ if (version === 4) {
8412
+ this.v4AccessToken = data.accessToken ?? null;
8413
+ this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
8414
+ if (data.refreshToken) {
8415
+ await this.refreshTokenStore.set(data.refreshToken);
8416
+ }
8417
+ if (signal.aborted) return;
8418
+ cookies__default.default.set(
8419
+ this.storageKey,
8420
+ JSON.stringify({ version, session: data.session }),
8421
+ { expires: subMinutes(addDays(now, 15), 2) }
8422
+ );
8423
+ return;
8304
8424
  }
8305
8425
  cookies__default.default.set(
8306
8426
  this.storageKey,
8307
- JSON.stringify({ version, session: data.session }),
8308
- { expires: subMinutes(addDays(now, 15), 2) }
8427
+ JSON.stringify({
8428
+ version,
8429
+ ...data,
8430
+ accessTokenExpiresAt: addMinutes(now, 8).getTime(),
8431
+ refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
8432
+ }),
8433
+ { expires: subMinutes(addDays(now, 30), 2) }
8309
8434
  );
8310
- return;
8311
- }
8312
- cookies__default.default.set(
8313
- this.storageKey,
8314
- JSON.stringify({
8315
- version,
8316
- ...data,
8317
- accessTokenExpiresAt: addMinutes(now, 8).getTime(),
8318
- refreshTokenExpiresAt: subMinutes(addDays(now, 30), 2).getTime()
8319
- }),
8320
- { expires: subMinutes(addDays(now, 30), 2) }
8321
- );
8435
+ });
8322
8436
  }
8323
8437
  async create(input, version = 1) {
8438
+ const waitingSignal = this.lifecycle.signal;
8439
+ await this.mutations.wait();
8440
+ if (waitingSignal.aborted) return { ok: true, data: null };
8441
+ const signal = this.lifecycle.renew();
8324
8442
  if (input.type === "MAYA") {
8325
8443
  localStorage.setItem(this.platformStorageKey, "MAYA");
8326
8444
  const f0 = () => this.walletService.mayaSession({ id: input.sessionId });
@@ -8346,7 +8464,7 @@ var SessionManagerCookie = class {
8346
8464
  maxAttempt: 5
8347
8465
  })();
8348
8466
  if (!r1.ok) return r1;
8349
- await this.persist(r1.data, version);
8467
+ await this.persist(r1.data, version, signal);
8350
8468
  return {
8351
8469
  ok: true,
8352
8470
  data: null
@@ -8355,7 +8473,7 @@ var SessionManagerCookie = class {
8355
8473
  if (input.type === "MOBILE_NUMBER") {
8356
8474
  const res2 = await this.authService.createSession(input, version);
8357
8475
  if (res2.ok) {
8358
- await this.persist(res2.data, version);
8476
+ await this.persist(res2.data, version, signal);
8359
8477
  return {
8360
8478
  ok: true,
8361
8479
  data: null
@@ -8372,7 +8490,7 @@ var SessionManagerCookie = class {
8372
8490
  version
8373
8491
  );
8374
8492
  if (res2.ok) {
8375
- await this.persist(res2.data, version);
8493
+ await this.persist(res2.data, version, signal);
8376
8494
  return {
8377
8495
  ok: true,
8378
8496
  data: null
@@ -8384,7 +8502,7 @@ var SessionManagerCookie = class {
8384
8502
  localStorage.setItem(this.platformStorageKey, "CABINET");
8385
8503
  const res2 = await this.authService.createSession(input, version);
8386
8504
  if (res2.ok) {
8387
- await this.persist(res2.data, version);
8505
+ await this.persist(res2.data, version, signal);
8388
8506
  return {
8389
8507
  ok: true,
8390
8508
  data: null
@@ -8402,19 +8520,23 @@ var SessionManagerCookie = class {
8402
8520
  }
8403
8521
  };
8404
8522
  }
8405
- await this.persist(res.data, version);
8523
+ await this.persist(res.data, version, signal);
8406
8524
  return {
8407
8525
  ok: true,
8408
8526
  data: null
8409
8527
  };
8410
8528
  }
8411
8529
  async createFromAuthenticator(input) {
8530
+ const waitingSignal = this.lifecycle.signal;
8531
+ await this.mutations.wait();
8532
+ if (waitingSignal.aborted) return { ok: true };
8533
+ const signal = this.lifecycle.renew();
8412
8534
  const res = await this.authService.authenticate(input);
8413
8535
  if (res.ok) {
8414
8536
  if (this.isServer) {
8415
8537
  this.logger.warn("'client cookies' is not available on the server.");
8416
8538
  } else {
8417
- await this.persist(res.data, 1);
8539
+ await this.persist(res.data, 1, signal);
8418
8540
  }
8419
8541
  return { ok: true };
8420
8542
  } else {
@@ -8422,6 +8544,7 @@ var SessionManagerCookie = class {
8422
8544
  }
8423
8545
  }
8424
8546
  async get() {
8547
+ const signal = this.lifecycle.signal;
8425
8548
  if (this.isServer) {
8426
8549
  this.logger.warn("'client cookies' is not available on the server.");
8427
8550
  return {
@@ -8431,6 +8554,7 @@ var SessionManagerCookie = class {
8431
8554
  }
8432
8555
  if (this.refreshing) {
8433
8556
  await sleep(1e3);
8557
+ if (signal.aborted) return { ok: true, data: null };
8434
8558
  return await this.get();
8435
8559
  }
8436
8560
  const val = cookies__default.default.get(this.storageKey);
@@ -8465,8 +8589,10 @@ var SessionManagerCookie = class {
8465
8589
  this.refreshing = true;
8466
8590
  const res = await this.authService.refreshSession(
8467
8591
  obj.refreshToken,
8468
- obj.version ?? 1
8592
+ obj.version ?? 1,
8593
+ signal
8469
8594
  );
8595
+ if (signal.aborted) return { ok: true, data: null };
8470
8596
  this.refreshing = false;
8471
8597
  if (!res.ok) {
8472
8598
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
@@ -8502,6 +8628,8 @@ var SessionManagerCookie = class {
8502
8628
  data: obj
8503
8629
  };
8504
8630
  } catch {
8631
+ if (signal.aborted) return { ok: true, data: null };
8632
+ this.refreshing = false;
8505
8633
  return {
8506
8634
  ok: false,
8507
8635
  error: {
@@ -8526,6 +8654,7 @@ var SessionManagerCookie = class {
8526
8654
  return await this.refreshV4(session);
8527
8655
  }
8528
8656
  async refresh() {
8657
+ const signal = this.lifecycle.signal;
8529
8658
  if (this.isServer) {
8530
8659
  this.logger.warn("'client cookies' is not available on the server.");
8531
8660
  return {
@@ -8551,8 +8680,10 @@ var SessionManagerCookie = class {
8551
8680
  this.refreshing = true;
8552
8681
  const res = await this.authService.refreshSession(
8553
8682
  obj.refreshToken,
8554
- obj.version ?? 1
8683
+ obj.version ?? 1,
8684
+ signal
8555
8685
  );
8686
+ if (signal.aborted) return { ok: true, data: null };
8556
8687
  this.refreshing = false;
8557
8688
  if (!res.ok) {
8558
8689
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
@@ -8587,6 +8718,8 @@ var SessionManagerCookie = class {
8587
8718
  data: obj
8588
8719
  };
8589
8720
  } catch {
8721
+ if (signal.aborted) return { ok: true, data: null };
8722
+ this.refreshing = false;
8590
8723
  return {
8591
8724
  ok: false,
8592
8725
  error: {
@@ -8598,18 +8731,20 @@ var SessionManagerCookie = class {
8598
8731
  }
8599
8732
  async refreshV4(session) {
8600
8733
  if (this.v4RefreshPromise) return await this.v4RefreshPromise;
8601
- this.v4RefreshPromise = this.requestV4Refresh(session);
8734
+ const promise = this.requestV4Refresh(session, this.lifecycle.signal);
8735
+ this.v4RefreshPromise = promise;
8602
8736
  try {
8603
- return await this.v4RefreshPromise;
8737
+ return await promise;
8604
8738
  } finally {
8605
- this.v4RefreshPromise = null;
8739
+ if (this.v4RefreshPromise === promise) this.v4RefreshPromise = null;
8606
8740
  }
8607
8741
  }
8608
- async requestV4Refresh(session) {
8742
+ async requestV4Refresh(session, signal) {
8609
8743
  this.logger.info("Refreshing session...");
8610
8744
  let refreshToken;
8611
8745
  if (isIOSPlatform()) {
8612
8746
  refreshToken = await this.refreshTokenStore.get() ?? void 0;
8747
+ if (signal.aborted) return { ok: true, data: null };
8613
8748
  if (!refreshToken) {
8614
8749
  this.logger.warn("No stored refresh token. Session expired.");
8615
8750
  this.v4AccessToken = null;
@@ -8626,7 +8761,8 @@ var SessionManagerCookie = class {
8626
8761
  }
8627
8762
  }
8628
8763
  this.refreshing = true;
8629
- const res = await this.authService.refreshSession(refreshToken, 4);
8764
+ const res = await this.authService.refreshSession(refreshToken, 4, signal);
8765
+ if (signal.aborted) return { ok: true, data: null };
8630
8766
  if (!res.ok) {
8631
8767
  this.logger.error(`Failed to refresh session: ${res.error.message}`);
8632
8768
  const terminal = res.error.name === "InvalidTokenError" || res.error.name === "AccountBlacklistedError" || res.error.name === "VerificationLockedError" || res.error.name === "SessionExpiredError";
@@ -8638,6 +8774,7 @@ var SessionManagerCookie = class {
8638
8774
  }
8639
8775
  this.refreshing = false;
8640
8776
  if (terminal) await this.refreshTokenStore.remove();
8777
+ if (signal.aborted) return { ok: true, data: null };
8641
8778
  return {
8642
8779
  ok: false,
8643
8780
  error: res.error
@@ -8647,8 +8784,13 @@ var SessionManagerCookie = class {
8647
8784
  this.logger.success("Session refreshed!");
8648
8785
  this.invalidReason = null;
8649
8786
  if (res.data.refreshToken) {
8650
- await this.refreshTokenStore.set(res.data.refreshToken);
8787
+ await this.mutations.run(async () => {
8788
+ if (!signal.aborted && res.data.refreshToken) {
8789
+ await this.refreshTokenStore.set(res.data.refreshToken);
8790
+ }
8791
+ });
8651
8792
  }
8793
+ if (signal.aborted) return { ok: true, data: null };
8652
8794
  const now = /* @__PURE__ */ new Date();
8653
8795
  this.v4AccessToken = res.data.accessToken;
8654
8796
  this.v4AccessTokenExpiresAt = addMinutes(now, 5).getTime();
@@ -8666,26 +8808,53 @@ var SessionManagerCookie = class {
8666
8808
  this.logger.warn("'client cookies' is not available on the server.");
8667
8809
  return;
8668
8810
  }
8669
- let version = 1;
8811
+ let version = this.v4AccessToken ? 4 : 1;
8812
+ let accessToken = this.v4AccessToken ?? void 0;
8813
+ let accessTokenExpiresAt = this.v4AccessTokenExpiresAt;
8814
+ let refreshToken;
8670
8815
  const val = cookies__default.default.get(this.storageKey);
8671
8816
  if (val) {
8672
8817
  try {
8673
8818
  const stored = JSON.parse(val);
8674
8819
  version = stored.version ?? 1;
8820
+ accessToken = stored.version === 4 ? this.v4AccessToken ?? void 0 : stored.accessToken;
8821
+ accessTokenExpiresAt = stored.version === 4 ? this.v4AccessTokenExpiresAt : stored.accessTokenExpiresAt;
8822
+ if (stored.version !== 4) refreshToken = stored.refreshToken;
8675
8823
  } catch {
8676
8824
  }
8677
8825
  }
8678
- const res = await this.get();
8679
- if (res.data?.accessToken) {
8680
- await this.authService.destroySession(res.data.accessToken, version);
8681
- }
8826
+ this.lifecycle.logout();
8827
+ this.refreshing = false;
8828
+ this.v4RefreshPromise = null;
8682
8829
  this.v4AccessToken = null;
8683
8830
  this.v4AccessTokenExpiresAt = null;
8684
8831
  this.invalidReason = null;
8685
- await this.refreshTokenStore.remove();
8686
8832
  cookies__default.default.remove(this.storageKey);
8833
+ await this.mutations.run(async () => {
8834
+ try {
8835
+ if (val && (!accessToken || !accessTokenExpiresAt || Date.now() > accessTokenExpiresAt)) {
8836
+ if (version === 4 && isIOSPlatform()) {
8837
+ refreshToken = await this.refreshTokenStore.get() ?? void 0;
8838
+ }
8839
+ if (refreshToken || version === 4 && !isIOSPlatform()) {
8840
+ accessToken = void 0;
8841
+ const res = await this.authService.refreshSession(
8842
+ refreshToken,
8843
+ version
8844
+ );
8845
+ if (res.ok) accessToken = res.data.accessToken;
8846
+ }
8847
+ }
8848
+ if (accessToken) {
8849
+ await this.authService.destroySession(accessToken, version);
8850
+ }
8851
+ } finally {
8852
+ if (version === 4) await this.refreshTokenStore.remove();
8853
+ }
8854
+ });
8687
8855
  }
8688
8856
  async verify() {
8857
+ const signal = this.lifecycle.signal;
8689
8858
  if (this.isServer) {
8690
8859
  this.logger.warn("'client cookies' is not available on the server.");
8691
8860
  return { valid: true };
@@ -8698,7 +8867,8 @@ var SessionManagerCookie = class {
8698
8867
  try {
8699
8868
  const stored = JSON.parse(val);
8700
8869
  if (stored.version === 4) {
8701
- const res = await this.verifyV4(stored.session);
8870
+ const res = await this.verifyV4(stored.session, signal);
8871
+ if (signal.aborted) return { valid: true };
8702
8872
  if (!res.valid) cookies__default.default.remove(this.storageKey);
8703
8873
  return res;
8704
8874
  }
@@ -8706,32 +8876,37 @@ var SessionManagerCookie = class {
8706
8876
  }
8707
8877
  }
8708
8878
  const s = await this.get();
8879
+ if (signal.aborted) return { valid: true };
8709
8880
  if (s.error?.name === "InvalidTokenError" || s.error?.name === "SessionExpiredError" || s.error?.name === "AccountBlacklistedError") {
8710
8881
  this.invalidReason = "INVALID_SESSION";
8711
8882
  return { valid: false, reason: "INVALID_SESSION" };
8712
8883
  }
8713
8884
  if (!s.data) return { valid: true };
8714
- const v = await this.authService.verifySession(s.data.accessToken);
8885
+ const v = await this.authService.verifySession(s.data.accessToken, signal);
8886
+ if (signal.aborted) return { valid: true };
8715
8887
  if (!v) {
8716
8888
  this.invalidReason = "INVALID_SESSION";
8717
8889
  cookies__default.default.remove(this.storageKey);
8718
8890
  }
8719
8891
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
8720
8892
  }
8721
- async verifyV4(session) {
8893
+ async verifyV4(session, signal) {
8722
8894
  if (!this.v4AccessToken || !this.v4AccessTokenExpiresAt || isAfter(/* @__PURE__ */ new Date(), new Date(this.v4AccessTokenExpiresAt))) {
8723
8895
  const res = await this.refreshV4(session);
8896
+ if (signal.aborted) return { valid: true };
8724
8897
  if (res.ok) return { valid: true };
8725
8898
  if (!this.invalidReason) return { valid: true };
8726
8899
  return { valid: false, reason: this.invalidReason };
8727
8900
  }
8728
- const v = await this.authService.verifySession(this.v4AccessToken);
8901
+ const v = await this.authService.verifySession(this.v4AccessToken, signal);
8902
+ if (signal.aborted) return { valid: true };
8729
8903
  if (!v) {
8730
8904
  cookies__default.default.remove(this.storageKey);
8731
8905
  this.v4AccessToken = null;
8732
8906
  this.v4AccessTokenExpiresAt = null;
8733
8907
  this.invalidReason = "INVALID_SESSION";
8734
8908
  await this.refreshTokenStore.remove();
8909
+ if (signal.aborted) return { valid: true };
8735
8910
  }
8736
8911
  return v ? { valid: true } : { valid: false, reason: "INVALID_SESSION" };
8737
8912
  }