@@ -4,6 +4,9 @@ import { debugLogger } from '@/utils/debug';
4
4
5
5
import { Token } from './resources/internal' ;
6
6
7
+ /**
8
+ * Identifies a cached token entry by tokenId and optional audience.
9
+ */
7
10
interface TokenCacheKeyJSON {
8
11
audience ?: string ;
9
12
tokenId : string ;
@@ -52,11 +55,14 @@ export interface TokenBroadcastMetadata {
52
55
53
56
type Seconds = number ;
54
57
58
+ /**
59
+ * Internal cache value containing the entry, expiration metadata, and cleanup timer.
60
+ */
55
61
interface TokenCacheValue {
56
62
createdAt : Seconds ;
57
63
entry : TokenCacheEntry ;
58
- expiresIn ?: Seconds ;
59
64
expiresAt ?: Seconds ;
65
+ expiresIn ?: Seconds ;
60
66
timeoutId ?: ReturnType < typeof setTimeout > ;
61
67
}
62
68
@@ -105,7 +111,14 @@ const LEEWAY = 10;
105
111
// This value should have the same value as the INTERVAL_IN_MS in SessionCookiePoller
106
112
const SYNC_LEEWAY = 5 ;
107
113
114
+ /**
115
+ * Converts between cache key objects and string representations.
116
+ * Format: `prefix::tokenId::audience`
117
+ */
108
118
export class TokenCacheKey {
119
+ /**
120
+ * Parses a cache key string into a TokenCacheKey instance.
121
+ */
109
122
static fromKey ( key : string ) : TokenCacheKey {
110
123
const [ prefix , tokenId , audience = '' ] = key . split ( DELIMITER ) ;
111
124
return new TokenCacheKey ( prefix , { audience, tokenId } ) ;
@@ -119,16 +132,26 @@ export class TokenCacheKey {
119
132
this . data = data ;
120
133
}
121
134
135
+ /**
136
+ * Converts the key to its string representation for Map storage.
137
+ */
122
138
toKey ( ) : string {
123
139
const { tokenId, audience } = this . data ;
124
140
return [ this . prefix , tokenId , audience || '' ] . join ( DELIMITER ) ;
125
141
}
126
142
}
127
143
144
+ /**
145
+ * Generates a unique token identifier from session context.
146
+ * Format: `sessionId-template-organizationId` (omitting falsy values).
147
+ */
128
148
const computeTokenId = ( sessionId : string , template ?: string , organizationId ?: string | null ) : string => {
129
149
return [ sessionId , template , organizationId ] . filter ( Boolean ) . join ( '-' ) ;
130
150
} ;
131
151
152
+ /**
153
+ * Message format for BroadcastChannel token synchronization between tabs.
154
+ */
132
155
interface SessionTokenEvent {
133
156
organizationId ?: string | null ;
134
157
sessionId : string ;
@@ -138,6 +161,10 @@ interface SessionTokenEvent {
138
161
traceId : string ;
139
162
}
140
163
164
+ /**
165
+ * Creates an in-memory token cache with BroadcastChannel synchronization across tabs.
166
+ * Automatically manages token expiration and cleanup via scheduled timeouts.
167
+ */
141
168
const MemoryTokenCache = ( prefix = KEY_PREFIX ) : TokenCache => {
142
169
const cache = new Map < string , TokenCacheValue > ( ) ;
143
170
@@ -199,6 +226,10 @@ const MemoryTokenCache = (prefix = KEY_PREFIX): TokenCache => {
199
226
return value . entry ;
200
227
} ;
201
228
229
+ /**
230
+ * Processes token updates from other tabs via BroadcastChannel.
231
+ * Validates token ID, parses JWT, and updates cache if token is newer than existing entry.
232
+ */
202
233
const handleBroadcastMessage = async ( { data } : MessageEvent < SessionTokenEvent > ) => {
203
234
const expectedTokenId = computeTokenId ( data . sessionId , data . template , data . organizationId ) ;
204
235
if ( data . tokenId !== expectedTokenId ) {
@@ -320,6 +351,10 @@ const MemoryTokenCache = (prefix = KEY_PREFIX): TokenCache => {
320
351
}
321
352
} ;
322
353
354
+ /**
355
+ * Internal cache setter that stores an entry and schedules expiration cleanup.
356
+ * Resolves the token promise to extract expiration claims and set a deletion timeout.
357
+ */
323
358
const setInternal = ( entry : TokenCacheEntry ) => {
324
359
const cacheKey = new TokenCacheKey ( prefix , {
325
360
audience : entry . audience ,
0 commit comments