@mentra/cloud-client 3.2.0-dev.137 → 3.2.0-dev.153

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.
@@ -17,8 +17,8 @@
17
17
  *
18
18
  * See docs/issues/004-cloud-client/design.md ("cloud.auth").
19
19
  */
20
- import type { KeyValueStore } from "../../transports";
21
- import { decodeClaims } from "./jwt";
20
+ import type {KeyValueStore} from "../../transports"
21
+ import {decodeClaims} from "./jwt"
22
22
 
23
23
  /**
24
24
  * Storage key for the persisted refresh token.
@@ -26,19 +26,20 @@ import { decodeClaims } from "./jwt";
26
26
  * Namespaced so it cannot collide with anything else a host keeps in the same
27
27
  * secure store.
28
28
  */
29
- const REFRESH_TOKEN_KEY = "mentra.cloud-client.refreshToken";
29
+ export const DEFAULT_REFRESH_TOKEN_KEY = "mentra.cloud-client.refreshToken"
30
30
 
31
31
  /** The access token plus its Unix-seconds expiry, held in memory only. */
32
32
  interface AccessTokenState {
33
- accessToken: string;
34
- exp: number;
33
+ accessToken: string
34
+ exp: number
35
35
  }
36
36
 
37
37
  export class TokenStore {
38
- private readonly storage: KeyValueStore;
38
+ private readonly storage: KeyValueStore
39
+ private readonly storageKey: string
39
40
 
40
41
  /** The current access token, or null before the first exchange/refresh. */
41
- private access: AccessTokenState | null = null;
42
+ private access: AccessTokenState | null = null
42
43
 
43
44
  /**
44
45
  * In-flight operations keyed by a caller-chosen string.
@@ -46,10 +47,11 @@ export class TokenStore {
46
47
  * Holding the promise (not just a boolean) lets every concurrent caller await
47
48
  * the same result, which is the whole point of single-flight here.
48
49
  */
49
- private readonly inFlight = new Map<string, Promise<unknown>>();
50
+ private readonly inFlight = new Map<string, Promise<unknown>>()
50
51
 
51
- constructor(deps: { storage: KeyValueStore }) {
52
- this.storage = deps.storage;
52
+ constructor(deps: {storage: KeyValueStore; storageKey?: string}) {
53
+ this.storage = deps.storage
54
+ this.storageKey = deps.storageKey ?? DEFAULT_REFRESH_TOKEN_KEY
53
55
  }
54
56
 
55
57
  /**
@@ -59,7 +61,7 @@ export class TokenStore {
59
61
  * caller (auth) decides whether it is still fresh using `exp`.
60
62
  */
61
63
  current(): AccessTokenState | null {
62
- return this.access;
64
+ return this.access
63
65
  }
64
66
 
65
67
  /**
@@ -70,12 +72,12 @@ export class TokenStore {
70
72
  * relaunch. We read `exp` here (rather than in the caller) to keep all the
71
73
  * token-state bookkeeping in one place.
72
74
  */
73
- async save(tokens: { accessToken: string; refreshToken: string }): Promise<void> {
75
+ async save(tokens: {accessToken: string; refreshToken: string}): Promise<void> {
74
76
  this.access = {
75
77
  accessToken: tokens.accessToken,
76
78
  exp: decodeClaims(tokens.accessToken).exp,
77
- };
78
- await this.storage.set(REFRESH_TOKEN_KEY, tokens.refreshToken);
79
+ }
80
+ await this.storage.set(this.storageKey, tokens.refreshToken)
79
81
  }
80
82
 
81
83
  /**
@@ -85,7 +87,7 @@ export class TokenStore {
85
87
  * process or restored out of band is always the one used.
86
88
  */
87
89
  refreshToken(): Promise<string | null> {
88
- return this.storage.get(REFRESH_TOKEN_KEY);
90
+ return this.storage.get(this.storageKey)
89
91
  }
90
92
 
91
93
  /**
@@ -97,7 +99,7 @@ export class TokenStore {
97
99
  * refresh token, rather than handing back the rejected token again.
98
100
  */
99
101
  invalidateAccess(): void {
100
- this.access = null;
102
+ this.access = null
101
103
  }
102
104
 
103
105
  /**
@@ -107,8 +109,8 @@ export class TokenStore {
107
109
  * presenting a known-bad token to the cloud.
108
110
  */
109
111
  async clear(): Promise<void> {
110
- this.access = null;
111
- await this.storage.delete(REFRESH_TOKEN_KEY);
112
+ this.access = null
113
+ await this.storage.delete(this.storageKey)
112
114
  }
113
115
 
114
116
  /**
@@ -121,18 +123,18 @@ export class TokenStore {
121
123
  * refresh failed, all callers waiting on it should see that failure.
122
124
  */
123
125
  singleFlight<T>(key: string, fn: () => Promise<T>): Promise<T> {
124
- const existing = this.inFlight.get(key);
125
- if (existing) return existing as Promise<T>;
126
+ const existing = this.inFlight.get(key)
127
+ if (existing) return existing as Promise<T>
126
128
 
127
129
  const promise = (async () => {
128
130
  try {
129
- return await fn();
131
+ return await fn()
130
132
  } finally {
131
- this.inFlight.delete(key);
133
+ this.inFlight.delete(key)
132
134
  }
133
- })();
135
+ })()
134
136
 
135
- this.inFlight.set(key, promise);
136
- return promise;
137
+ this.inFlight.set(key, promise)
138
+ return promise
137
139
  }
138
140
  }