@spacelr/sdk 0.9.0 → 0.9.2

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.mjs CHANGED
@@ -385,7 +385,7 @@ var BrowserTokenStorage = class {
385
385
 
386
386
  // libs/sdk/src/core/token-manager.ts
387
387
  var TokenManager = class {
388
- constructor(storage, refreshBufferSeconds = 60) {
388
+ constructor(storage, refreshBufferSeconds = 60, refreshLockName = "spacelr_token_refresh") {
389
389
  this.refreshCallback = null;
390
390
  this.refreshPromise = null;
391
391
  this.tokenRefreshedListeners = /* @__PURE__ */ new Set();
@@ -396,6 +396,7 @@ var TokenManager = class {
396
396
  this.authLostEmitted = false;
397
397
  this.storage = storage ?? new MemoryTokenStorage();
398
398
  this.refreshBufferSeconds = refreshBufferSeconds;
399
+ this.refreshLockName = refreshLockName;
399
400
  }
400
401
  setRefreshCallback(callback) {
401
402
  this.refreshCallback = callback;
@@ -425,7 +426,7 @@ var TokenManager = class {
425
426
  this.authLostEmitted = false;
426
427
  }
427
428
  async getStoredTokens() {
428
- return this.storage.getTokens();
429
+ return this.safeGetTokens();
429
430
  }
430
431
  /**
431
432
  * Force a refresh using the current stored refresh token.
@@ -492,9 +493,18 @@ var TokenManager = class {
492
493
  }
493
494
  }
494
495
  async executeRefresh(refreshToken) {
496
+ return this.withCrossTabLock(() => this.doRefresh(refreshToken));
497
+ }
498
+ async doRefresh(refreshToken) {
495
499
  const callback = this.refreshCallback;
500
+ const current = await this.safeGetTokens();
501
+ if (current && current.refreshToken && current.refreshToken !== refreshToken && !this.isTokenExpired(current)) {
502
+ this.emitTokenRefreshed(current);
503
+ return current;
504
+ }
505
+ const activeRefreshToken = current?.refreshToken || refreshToken;
496
506
  try {
497
- const newTokens = await callback(refreshToken);
507
+ const newTokens = await callback(activeRefreshToken);
498
508
  await this.storage.setTokens(newTokens);
499
509
  this.emitTokenRefreshed(newTokens);
500
510
  return newTokens;
@@ -503,6 +513,22 @@ var TokenManager = class {
503
513
  throw error;
504
514
  }
505
515
  }
516
+ async safeGetTokens() {
517
+ try {
518
+ return await this.storage.getTokens();
519
+ } catch {
520
+ return null;
521
+ }
522
+ }
523
+ withCrossTabLock(fn) {
524
+ const locks = typeof navigator !== "undefined" ? navigator.locks : void 0;
525
+ if (!locks) return fn();
526
+ try {
527
+ return locks.request(this.refreshLockName, fn);
528
+ } catch {
529
+ return fn();
530
+ }
531
+ }
506
532
  emitTokenRefreshed(tokens) {
507
533
  for (const listener of this.tokenRefreshedListeners) {
508
534
  try {
@@ -1261,6 +1287,16 @@ function localStorageCursorStorage(prefix = "spacelr:cursor:") {
1261
1287
  }
1262
1288
 
1263
1289
  // libs/sdk/src/modules/auth.module.ts
1290
+ function mapProfile(u) {
1291
+ const name = u.name ?? ([u.firstName, u.lastName].filter(Boolean).join(" ") || void 0) ?? u.displayName;
1292
+ return {
1293
+ id: u.id ?? u._id ?? u.userId ?? u.sub ?? "",
1294
+ email: u.email ?? "",
1295
+ username: u.username,
1296
+ name,
1297
+ roles: u.roles ?? []
1298
+ };
1299
+ }
1264
1300
  var AuthModule = class {
1265
1301
  constructor(http, tokenManager, config) {
1266
1302
  this.stateListeners = /* @__PURE__ */ new Set();
@@ -1384,11 +1420,12 @@ var AuthModule = class {
1384
1420
  });
1385
1421
  }
1386
1422
  async getProfile() {
1387
- return this.http.request({
1423
+ const data = await this.http.request({
1388
1424
  method: "GET",
1389
1425
  path: "/auth/me",
1390
1426
  authenticated: true
1391
1427
  });
1428
+ return mapProfile(data.user ?? data);
1392
1429
  }
1393
1430
  async logout() {
1394
1431
  try {
@@ -3020,7 +3057,8 @@ function createClient(config) {
3020
3057
  const tokenStorage = config.tokenStorage ?? (typeof window !== "undefined" && typeof window.localStorage !== "undefined" ? new BrowserTokenStorage() : new MemoryTokenStorage());
3021
3058
  const tokenManager = new TokenManager(
3022
3059
  tokenStorage,
3023
- config.refreshBufferSeconds ?? 60
3060
+ config.refreshBufferSeconds ?? 60,
3061
+ `spacelr_token_refresh:${config.projectId}`
3024
3062
  );
3025
3063
  const httpClient = new HttpClient(config, tokenManager);
3026
3064
  const realtime = new RealtimeClient({
@@ -3047,6 +3085,9 @@ function createClient(config) {
3047
3085
  clearTokens() {
3048
3086
  return tokenManager.clearTokens();
3049
3087
  },
3088
+ hasStoredSession() {
3089
+ return tokenManager.getStoredTokens().then((tokens) => !!tokens);
3090
+ },
3050
3091
  disconnect() {
3051
3092
  realtime.disconnect();
3052
3093
  },