@fluidframework/tool-utils 2.0.0-internal.3.0.2 → 2.0.0-internal.3.2.0

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.
Files changed (48) hide show
  1. package/.eslintrc.js +19 -23
  2. package/.mocharc.js +2 -2
  3. package/api-extractor.json +2 -2
  4. package/dist/fluidToolRC.d.ts.map +1 -1
  5. package/dist/fluidToolRC.js.map +1 -1
  6. package/dist/httpHelpers.d.ts.map +1 -1
  7. package/dist/httpHelpers.js +6 -2
  8. package/dist/httpHelpers.js.map +1 -1
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/odspTokenManager.d.ts.map +1 -1
  13. package/dist/odspTokenManager.js +5 -2
  14. package/dist/odspTokenManager.js.map +1 -1
  15. package/dist/packageVersion.d.ts +1 -1
  16. package/dist/packageVersion.js +1 -1
  17. package/dist/packageVersion.js.map +1 -1
  18. package/dist/snapshotNormalizer.d.ts.map +1 -1
  19. package/dist/snapshotNormalizer.js +13 -10
  20. package/dist/snapshotNormalizer.js.map +1 -1
  21. package/lib/fluidToolRC.d.ts.map +1 -1
  22. package/lib/fluidToolRC.js.map +1 -1
  23. package/lib/httpHelpers.d.ts.map +1 -1
  24. package/lib/httpHelpers.js +6 -2
  25. package/lib/httpHelpers.js.map +1 -1
  26. package/lib/index.d.ts +1 -1
  27. package/lib/index.d.ts.map +1 -1
  28. package/lib/index.js +1 -1
  29. package/lib/index.js.map +1 -1
  30. package/lib/odspTokenManager.d.ts.map +1 -1
  31. package/lib/odspTokenManager.js +5 -2
  32. package/lib/odspTokenManager.js.map +1 -1
  33. package/lib/packageVersion.d.ts +1 -1
  34. package/lib/packageVersion.js +1 -1
  35. package/lib/packageVersion.js.map +1 -1
  36. package/lib/snapshotNormalizer.d.ts.map +1 -1
  37. package/lib/snapshotNormalizer.js +14 -11
  38. package/lib/snapshotNormalizer.js.map +1 -1
  39. package/package.json +40 -39
  40. package/prettier.config.cjs +1 -1
  41. package/src/fluidToolRC.ts +36 -36
  42. package/src/httpHelpers.ts +58 -44
  43. package/src/index.ts +5 -1
  44. package/src/odspTokenManager.ts +301 -309
  45. package/src/packageVersion.ts +1 -1
  46. package/src/snapshotNormalizer.ts +178 -171
  47. package/tsconfig.esnext.json +6 -6
  48. package/tsconfig.json +10 -16
@@ -5,14 +5,14 @@
5
5
 
6
6
  import { unreachableCase } from "@fluidframework/common-utils";
7
7
  import {
8
- IOdspTokens,
9
- IClientConfig,
10
- fetchTokens,
11
- refreshTokens,
12
- getOdspScope,
13
- pushScope,
14
- getLoginPageUrl,
15
- TokenRequestCredentials,
8
+ IOdspTokens,
9
+ IClientConfig,
10
+ fetchTokens,
11
+ refreshTokens,
12
+ getOdspScope,
13
+ pushScope,
14
+ getLoginPageUrl,
15
+ TokenRequestCredentials,
16
16
  } from "@fluidframework/odsp-doclib-utils";
17
17
  import jwtDecode from "jwt-decode";
18
18
  import { Mutex } from "async-mutex";
@@ -25,345 +25,337 @@ const odspAuthRedirectOrigin = `http://localhost:${odspAuthRedirectPort}`;
25
25
  const odspAuthRedirectUri = new URL("/auth/callback", odspAuthRedirectOrigin).href;
26
26
 
27
27
  export const getMicrosoftConfiguration = (): IClientConfig => ({
28
- get clientId() {
29
- if (!process.env.login__microsoft__clientId) {
30
- throw new Error("Client ID environment variable not set: login__microsoft__clientId.");
31
- }
32
- return process.env.login__microsoft__clientId;
33
- },
34
- get clientSecret() {
35
- if (!process.env.login__microsoft__secret) {
36
- throw new Error("Client Secret environment variable not set: login__microsoft__secret.");
37
- }
38
- return process.env.login__microsoft__secret;
39
- },
28
+ get clientId() {
29
+ if (!process.env.login__microsoft__clientId) {
30
+ throw new Error("Client ID environment variable not set: login__microsoft__clientId.");
31
+ }
32
+ return process.env.login__microsoft__clientId;
33
+ },
34
+ get clientSecret() {
35
+ if (!process.env.login__microsoft__secret) {
36
+ throw new Error(
37
+ "Client Secret environment variable not set: login__microsoft__secret.",
38
+ );
39
+ }
40
+ return process.env.login__microsoft__secret;
41
+ },
40
42
  });
41
43
 
42
- export type OdspTokenConfig = {
43
- type: "password";
44
- username: string;
45
- password: string;
46
- } | {
47
- type: "browserLogin";
48
- navigator: (url: string) => void;
49
- redirectUriCallback?: (tokens: IOdspTokens) => Promise<string>;
50
- };
44
+ export type OdspTokenConfig =
45
+ | {
46
+ type: "password";
47
+ username: string;
48
+ password: string;
49
+ }
50
+ | {
51
+ type: "browserLogin";
52
+ navigator: (url: string) => void;
53
+ redirectUriCallback?: (tokens: IOdspTokens) => Promise<string>;
54
+ };
51
55
 
52
56
  export interface IOdspTokenManagerCacheKey {
53
- readonly isPush: boolean;
54
- readonly userOrServer: string;
57
+ readonly isPush: boolean;
58
+ readonly userOrServer: string;
55
59
  }
56
60
 
57
61
  const isValidToken = (token: string) => {
58
- // Return false for undefined or empty tokens.
59
- if (!token || token.length === 0) {
60
- return false;
61
- }
62
+ // Return false for undefined or empty tokens.
63
+ if (!token || token.length === 0) {
64
+ return false;
65
+ }
62
66
 
63
- const decodedToken = jwtDecode<any>(token);
64
- // Give it a 60s buffer
65
- return (decodedToken.exp - 60 >= (new Date().getTime() / 1000));
67
+ const decodedToken = jwtDecode<any>(token);
68
+ // Give it a 60s buffer
69
+ return decodedToken.exp - 60 >= new Date().getTime() / 1000;
66
70
  };
67
71
 
68
72
  const cacheKeyToString = (key: IOdspTokenManagerCacheKey) => {
69
- return `${key.userOrServer}${key.isPush ? "[Push]" : ""}`;
73
+ return `${key.userOrServer}${key.isPush ? "[Push]" : ""}`;
70
74
  };
71
75
 
72
76
  export class OdspTokenManager {
73
- private readonly storageCache = new Map<string, IOdspTokens>();
74
- private readonly pushCache = new Map<string, IOdspTokens>();
75
- private readonly cacheMutex = new Mutex();
76
- constructor(
77
- private readonly tokenCache?: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens>,
78
- ) { }
77
+ private readonly storageCache = new Map<string, IOdspTokens>();
78
+ private readonly pushCache = new Map<string, IOdspTokens>();
79
+ private readonly cacheMutex = new Mutex();
80
+ constructor(
81
+ private readonly tokenCache?: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens>,
82
+ ) {}
79
83
 
80
- public async updateTokensCache(key: IOdspTokenManagerCacheKey, value: IOdspTokens) {
81
- await this.cacheMutex.runExclusive(async () => {
82
- await this.updateTokensCacheWithoutLock(key, value);
83
- });
84
- }
84
+ public async updateTokensCache(key: IOdspTokenManagerCacheKey, value: IOdspTokens) {
85
+ await this.cacheMutex.runExclusive(async () => {
86
+ await this.updateTokensCacheWithoutLock(key, value);
87
+ });
88
+ }
85
89
 
86
- private async updateTokensCacheWithoutLock(key: IOdspTokenManagerCacheKey, value: IOdspTokens) {
87
- debug(`${cacheKeyToString(key)}: Saving tokens`);
88
- const memoryCache = key.isPush ? this.pushCache : this.storageCache;
89
- memoryCache.set(key.userOrServer, value);
90
- await this.tokenCache?.save(key, value);
91
- }
90
+ private async updateTokensCacheWithoutLock(key: IOdspTokenManagerCacheKey, value: IOdspTokens) {
91
+ debug(`${cacheKeyToString(key)}: Saving tokens`);
92
+ const memoryCache = key.isPush ? this.pushCache : this.storageCache;
93
+ memoryCache.set(key.userOrServer, value);
94
+ await this.tokenCache?.save(key, value);
95
+ }
92
96
 
93
- public async getOdspTokens(
94
- server: string,
95
- clientConfig: IClientConfig,
96
- tokenConfig: OdspTokenConfig,
97
- forceRefresh = false,
98
- forceReauth = false,
99
- ): Promise<IOdspTokens> {
100
- return this.getTokens(
101
- false,
102
- server,
103
- clientConfig,
104
- tokenConfig,
105
- forceRefresh,
106
- forceReauth,
107
- );
108
- }
97
+ public async getOdspTokens(
98
+ server: string,
99
+ clientConfig: IClientConfig,
100
+ tokenConfig: OdspTokenConfig,
101
+ forceRefresh = false,
102
+ forceReauth = false,
103
+ ): Promise<IOdspTokens> {
104
+ return this.getTokens(false, server, clientConfig, tokenConfig, forceRefresh, forceReauth);
105
+ }
109
106
 
110
- public async getPushTokens(
111
- server: string,
112
- clientConfig: IClientConfig,
113
- tokenConfig: OdspTokenConfig,
114
- forceRefresh = false,
115
- forceReauth = false,
116
- ): Promise<IOdspTokens> {
117
- return this.getTokens(
118
- true,
119
- server,
120
- clientConfig,
121
- tokenConfig,
122
- forceRefresh,
123
- forceReauth,
124
- );
125
- }
107
+ public async getPushTokens(
108
+ server: string,
109
+ clientConfig: IClientConfig,
110
+ tokenConfig: OdspTokenConfig,
111
+ forceRefresh = false,
112
+ forceReauth = false,
113
+ ): Promise<IOdspTokens> {
114
+ return this.getTokens(true, server, clientConfig, tokenConfig, forceRefresh, forceReauth);
115
+ }
126
116
 
127
- private async getTokenFromCache(
128
- cacheKey: IOdspTokenManagerCacheKey,
129
- ) {
130
- const memoryCache = cacheKey.isPush ? this.pushCache : this.storageCache;
131
- const memoryToken = memoryCache.get(cacheKey.userOrServer);
132
- if (memoryToken) {
133
- debug(`${cacheKeyToString(cacheKey)}: Token found in memory `);
134
- return memoryToken;
135
- }
136
- const fileToken = await this.tokenCache?.get(cacheKey);
137
- if (fileToken) {
138
- debug(`${cacheKeyToString(cacheKey)}: Token found in file`);
139
- memoryCache.set(cacheKey.userOrServer, fileToken);
140
- return fileToken;
141
- }
142
- }
117
+ private async getTokenFromCache(cacheKey: IOdspTokenManagerCacheKey) {
118
+ const memoryCache = cacheKey.isPush ? this.pushCache : this.storageCache;
119
+ const memoryToken = memoryCache.get(cacheKey.userOrServer);
120
+ if (memoryToken) {
121
+ debug(`${cacheKeyToString(cacheKey)}: Token found in memory `);
122
+ return memoryToken;
123
+ }
124
+ const fileToken = await this.tokenCache?.get(cacheKey);
125
+ if (fileToken) {
126
+ debug(`${cacheKeyToString(cacheKey)}: Token found in file`);
127
+ memoryCache.set(cacheKey.userOrServer, fileToken);
128
+ return fileToken;
129
+ }
130
+ }
143
131
 
144
- private static getCacheKey(
145
- isPush: boolean,
146
- tokenConfig: OdspTokenConfig,
147
- server: string,
148
- ): IOdspTokenManagerCacheKey {
149
- // If we are using password, we should cache the token per user instead of per server
150
- return { isPush, userOrServer: tokenConfig.type === "password" ? tokenConfig.username : server };
151
- }
132
+ private static getCacheKey(
133
+ isPush: boolean,
134
+ tokenConfig: OdspTokenConfig,
135
+ server: string,
136
+ ): IOdspTokenManagerCacheKey {
137
+ // If we are using password, we should cache the token per user instead of per server
138
+ return {
139
+ isPush,
140
+ userOrServer: tokenConfig.type === "password" ? tokenConfig.username : server,
141
+ };
142
+ }
152
143
 
153
- private async getTokens(
154
- isPush: boolean,
155
- server: string,
156
- clientConfig: IClientConfig,
157
- tokenConfig: OdspTokenConfig,
158
- forceRefresh: boolean,
159
- forceReauth: boolean,
160
- ): Promise<IOdspTokens> {
161
- const invokeGetTokensCore = async () => {
162
- // Don't solely rely on tokenCache lock, ensure serialized execution of
163
- // cache update to avoid multiple fetch.
164
- return this.cacheMutex.runExclusive(async () => {
165
- return this.getTokensCore(
166
- isPush,
167
- server,
168
- clientConfig,
169
- tokenConfig,
170
- forceRefresh,
171
- forceReauth);
172
- });
173
- };
174
- if (!forceReauth && !forceRefresh) {
175
- // check and return if it exists without lock
176
- const cacheKey = OdspTokenManager.getCacheKey(isPush, tokenConfig, server);
177
- const tokensFromCache = await this.getTokenFromCache(cacheKey);
178
- if (tokensFromCache) {
179
- if (isValidToken(tokensFromCache.accessToken)) {
180
- debug(`${cacheKeyToString(cacheKey)}: Token reused from cache `);
181
- await this.onTokenRetrievalFromCache(tokenConfig, tokensFromCache);
182
- return tokensFromCache;
183
- }
184
- debug(`${cacheKeyToString(cacheKey)}: Token expired from cache `);
185
- }
186
- }
187
- if (this.tokenCache) {
188
- // check with lock, used to prevent concurrent auth attempts
189
- return this.tokenCache.lock(invokeGetTokensCore);
190
- }
191
- return invokeGetTokensCore();
192
- }
144
+ private async getTokens(
145
+ isPush: boolean,
146
+ server: string,
147
+ clientConfig: IClientConfig,
148
+ tokenConfig: OdspTokenConfig,
149
+ forceRefresh: boolean,
150
+ forceReauth: boolean,
151
+ ): Promise<IOdspTokens> {
152
+ const invokeGetTokensCore = async () => {
153
+ // Don't solely rely on tokenCache lock, ensure serialized execution of
154
+ // cache update to avoid multiple fetch.
155
+ return this.cacheMutex.runExclusive(async () => {
156
+ return this.getTokensCore(
157
+ isPush,
158
+ server,
159
+ clientConfig,
160
+ tokenConfig,
161
+ forceRefresh,
162
+ forceReauth,
163
+ );
164
+ });
165
+ };
166
+ if (!forceReauth && !forceRefresh) {
167
+ // check and return if it exists without lock
168
+ const cacheKey = OdspTokenManager.getCacheKey(isPush, tokenConfig, server);
169
+ const tokensFromCache = await this.getTokenFromCache(cacheKey);
170
+ if (tokensFromCache) {
171
+ if (isValidToken(tokensFromCache.accessToken)) {
172
+ debug(`${cacheKeyToString(cacheKey)}: Token reused from cache `);
173
+ await this.onTokenRetrievalFromCache(tokenConfig, tokensFromCache);
174
+ return tokensFromCache;
175
+ }
176
+ debug(`${cacheKeyToString(cacheKey)}: Token expired from cache `);
177
+ }
178
+ }
179
+ if (this.tokenCache) {
180
+ // check with lock, used to prevent concurrent auth attempts
181
+ return this.tokenCache.lock(invokeGetTokensCore);
182
+ }
183
+ return invokeGetTokensCore();
184
+ }
193
185
 
194
- private async getTokensCore(
195
- isPush: boolean,
196
- server: string,
197
- clientConfig: IClientConfig,
198
- tokenConfig: OdspTokenConfig,
199
- forceRefresh,
200
- forceReauth,
201
- ): Promise<IOdspTokens> {
202
- const scope = isPush ? pushScope : getOdspScope(server);
203
- const cacheKey = OdspTokenManager.getCacheKey(isPush, tokenConfig, server);
204
- let tokens: IOdspTokens | undefined;
205
- if (!forceReauth) {
206
- // check the cache again under the lock (if it is there)
207
- const tokensFromCache = await this.getTokenFromCache(cacheKey);
208
- if (tokensFromCache) {
209
- if (forceRefresh || !isValidToken(tokensFromCache.accessToken)) {
210
- try {
211
- // This updates the tokens in tokensFromCache
212
- tokens = await refreshTokens(server, scope, clientConfig, tokensFromCache);
213
- await this.updateTokensCacheWithoutLock(cacheKey, tokens);
214
- } catch (error) {
215
- debug(`${cacheKeyToString(cacheKey)}: Error in refreshing token. ${error}`);
216
- }
217
- } else {
218
- tokens = tokensFromCache;
219
- debug(`${cacheKeyToString(cacheKey)}: Token reused from locked cache `);
220
- }
221
- }
222
- }
186
+ private async getTokensCore(
187
+ isPush: boolean,
188
+ server: string,
189
+ clientConfig: IClientConfig,
190
+ tokenConfig: OdspTokenConfig,
191
+ forceRefresh,
192
+ forceReauth,
193
+ ): Promise<IOdspTokens> {
194
+ const scope = isPush ? pushScope : getOdspScope(server);
195
+ const cacheKey = OdspTokenManager.getCacheKey(isPush, tokenConfig, server);
196
+ let tokens: IOdspTokens | undefined;
197
+ if (!forceReauth) {
198
+ // check the cache again under the lock (if it is there)
199
+ const tokensFromCache = await this.getTokenFromCache(cacheKey);
200
+ if (tokensFromCache) {
201
+ if (forceRefresh || !isValidToken(tokensFromCache.accessToken)) {
202
+ try {
203
+ // This updates the tokens in tokensFromCache
204
+ tokens = await refreshTokens(server, scope, clientConfig, tokensFromCache);
205
+ await this.updateTokensCacheWithoutLock(cacheKey, tokens);
206
+ } catch (error) {
207
+ debug(`${cacheKeyToString(cacheKey)}: Error in refreshing token. ${error}`);
208
+ }
209
+ } else {
210
+ tokens = tokensFromCache;
211
+ debug(`${cacheKeyToString(cacheKey)}: Token reused from locked cache `);
212
+ }
213
+ }
214
+ }
223
215
 
224
- if (tokens) {
225
- await this.onTokenRetrievalFromCache(tokenConfig, tokens);
226
- return tokens;
227
- }
216
+ if (tokens) {
217
+ await this.onTokenRetrievalFromCache(tokenConfig, tokens);
218
+ return tokens;
219
+ }
228
220
 
229
- switch (tokenConfig.type) {
230
- case "password":
231
- tokens = await this.acquireTokensWithPassword(
232
- server,
233
- scope,
234
- clientConfig,
235
- tokenConfig.username,
236
- tokenConfig.password,
237
- );
238
- break;
239
- case "browserLogin":
240
- tokens = await this.acquireTokensViaBrowserLogin(
241
- getLoginPageUrl(server, clientConfig, scope, odspAuthRedirectUri),
242
- server,
243
- clientConfig,
244
- scope,
245
- tokenConfig.navigator,
246
- tokenConfig.redirectUriCallback,
247
- );
248
- break;
249
- default:
250
- unreachableCase(tokenConfig);
251
- }
221
+ switch (tokenConfig.type) {
222
+ case "password":
223
+ tokens = await this.acquireTokensWithPassword(
224
+ server,
225
+ scope,
226
+ clientConfig,
227
+ tokenConfig.username,
228
+ tokenConfig.password,
229
+ );
230
+ break;
231
+ case "browserLogin":
232
+ tokens = await this.acquireTokensViaBrowserLogin(
233
+ getLoginPageUrl(server, clientConfig, scope, odspAuthRedirectUri),
234
+ server,
235
+ clientConfig,
236
+ scope,
237
+ tokenConfig.navigator,
238
+ tokenConfig.redirectUriCallback,
239
+ );
240
+ break;
241
+ default:
242
+ unreachableCase(tokenConfig);
243
+ }
252
244
 
253
- await this.updateTokensCacheWithoutLock(cacheKey, tokens);
254
- return tokens;
255
- }
245
+ await this.updateTokensCacheWithoutLock(cacheKey, tokens);
246
+ return tokens;
247
+ }
256
248
 
257
- private async acquireTokensWithPassword(
258
- server: string,
259
- scope: string,
260
- clientConfig: IClientConfig,
261
- username: string,
262
- password: string,
263
- ): Promise<IOdspTokens> {
264
- const credentials: TokenRequestCredentials = {
265
- grant_type: "password",
266
- username,
267
- password,
268
- };
269
- return fetchTokens(server, scope, clientConfig, credentials);
270
- }
249
+ private async acquireTokensWithPassword(
250
+ server: string,
251
+ scope: string,
252
+ clientConfig: IClientConfig,
253
+ username: string,
254
+ password: string,
255
+ ): Promise<IOdspTokens> {
256
+ const credentials: TokenRequestCredentials = {
257
+ grant_type: "password",
258
+ username,
259
+ password,
260
+ };
261
+ return fetchTokens(server, scope, clientConfig, credentials);
262
+ }
271
263
 
272
- private async acquireTokensViaBrowserLogin(
273
- loginPageUrl: string,
274
- server: string,
275
- clientConfig: IClientConfig,
276
- scope: string,
277
- navigator: (url: string) => void,
278
- redirectUriCallback?: (tokens: IOdspTokens) => Promise<string>,
279
- ): Promise<IOdspTokens> {
280
- // Start up a local auth redirect handler service to receive the tokens after login
281
- const tokenGetter = await serverListenAndHandle(odspAuthRedirectPort, async (req, res) => {
282
- // extract code from request URL and fetch the tokens
283
- const credentials: TokenRequestCredentials = {
284
- grant_type: "authorization_code",
285
- code: this.extractAuthorizationCode(req.url),
286
- redirect_uri: odspAuthRedirectUri,
287
- };
288
- const tokens = await fetchTokens(server, scope, clientConfig, credentials);
264
+ private async acquireTokensViaBrowserLogin(
265
+ loginPageUrl: string,
266
+ server: string,
267
+ clientConfig: IClientConfig,
268
+ scope: string,
269
+ navigator: (url: string) => void,
270
+ redirectUriCallback?: (tokens: IOdspTokens) => Promise<string>,
271
+ ): Promise<IOdspTokens> {
272
+ // Start up a local auth redirect handler service to receive the tokens after login
273
+ const tokenGetter = await serverListenAndHandle(odspAuthRedirectPort, async (req, res) => {
274
+ // extract code from request URL and fetch the tokens
275
+ const credentials: TokenRequestCredentials = {
276
+ grant_type: "authorization_code",
277
+ code: this.extractAuthorizationCode(req.url),
278
+ redirect_uri: odspAuthRedirectUri,
279
+ };
280
+ const tokens = await fetchTokens(server, scope, clientConfig, credentials);
289
281
 
290
- // redirect now that the browser is done with auth
291
- if (redirectUriCallback) {
292
- res.writeHead(301, { Location: await redirectUriCallback(tokens) });
293
- await endResponse(res);
294
- } else {
295
- res.write("Please close the window");
296
- await endResponse(res);
297
- }
282
+ // redirect now that the browser is done with auth
283
+ if (redirectUriCallback) {
284
+ res.writeHead(301, { Location: await redirectUriCallback(tokens) });
285
+ await endResponse(res);
286
+ } else {
287
+ res.write("Please close the window");
288
+ await endResponse(res);
289
+ }
298
290
 
299
- return tokens;
300
- });
291
+ return tokens;
292
+ });
301
293
 
302
- // Now that our local redirect handler is up, navigate the browser to the login page
303
- navigator(loginPageUrl);
294
+ // Now that our local redirect handler is up, navigate the browser to the login page
295
+ navigator(loginPageUrl);
304
296
 
305
- // Receive and extract the tokens
306
- const odspTokens = await tokenGetter();
297
+ // Receive and extract the tokens
298
+ const odspTokens = await tokenGetter();
307
299
 
308
- return odspTokens;
309
- }
300
+ return odspTokens;
301
+ }
310
302
 
311
- private async onTokenRetrievalFromCache(config: OdspTokenConfig, tokens: IOdspTokens) {
312
- if (config.type === "browserLogin" && config.redirectUriCallback) {
313
- config.navigator(await config.redirectUriCallback(tokens));
314
- }
315
- }
303
+ private async onTokenRetrievalFromCache(config: OdspTokenConfig, tokens: IOdspTokens) {
304
+ if (config.type === "browserLogin" && config.redirectUriCallback) {
305
+ config.navigator(await config.redirectUriCallback(tokens));
306
+ }
307
+ }
316
308
 
317
- private extractAuthorizationCode(relativeUrl: string | undefined): string {
318
- if (relativeUrl === undefined) {
319
- throw Error("Failed to get authorization");
320
- }
321
- const parsedUrl = new URL(relativeUrl, odspAuthRedirectOrigin);
322
- const code = parsedUrl.searchParams.get("code");
323
- if (!code) {
324
- throw Error("Failed to get authorization");
325
- }
326
- return code;
327
- }
309
+ private extractAuthorizationCode(relativeUrl: string | undefined): string {
310
+ if (relativeUrl === undefined) {
311
+ throw Error("Failed to get authorization");
312
+ }
313
+ const parsedUrl = new URL(relativeUrl, odspAuthRedirectOrigin);
314
+ const code = parsedUrl.searchParams.get("code");
315
+ if (!code) {
316
+ throw Error("Failed to get authorization");
317
+ }
318
+ return code;
319
+ }
328
320
  }
329
321
 
330
322
  async function loadAndPatchRC() {
331
- const rc = await loadRC();
332
- if (rc.tokens && rc.tokens.version === undefined) {
333
- // Clean up older versions
334
- delete (rc as any).tokens;
335
- delete (rc as any).pushTokens;
336
- }
337
- return rc;
323
+ const rc = await loadRC();
324
+ if (rc.tokens && rc.tokens.version === undefined) {
325
+ // Clean up older versions
326
+ delete (rc as any).tokens;
327
+ delete (rc as any).pushTokens;
328
+ }
329
+ return rc;
338
330
  }
339
331
 
340
332
  export const odspTokensCache: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens> = {
341
- async get(key: IOdspTokenManagerCacheKey): Promise<IOdspTokens | undefined> {
342
- const rc = await loadAndPatchRC();
343
- return rc.tokens?.data[key.userOrServer]?.[key.isPush ? "push" : "storage"];
344
- },
345
- async save(key: IOdspTokenManagerCacheKey, tokens: IOdspTokens): Promise<void> {
346
- const rc = await loadAndPatchRC();
347
- if (!rc.tokens) {
348
- rc.tokens = {
349
- version: 1,
350
- data: {},
351
- };
352
- }
353
- let prevTokens = rc.tokens.data[key.userOrServer];
354
- if (!prevTokens) {
355
- prevTokens = {};
356
- rc.tokens.data[key.userOrServer] = prevTokens;
357
- }
358
- prevTokens[key.isPush ? "push" : "storage"] = tokens;
359
- return saveRC(rc);
360
- },
361
- async lock<T>(callback: () => Promise<T>): Promise<T> {
362
- const release = await lockRC();
363
- try {
364
- return await callback();
365
- } finally {
366
- await release();
367
- }
368
- },
333
+ async get(key: IOdspTokenManagerCacheKey): Promise<IOdspTokens | undefined> {
334
+ const rc = await loadAndPatchRC();
335
+ return rc.tokens?.data[key.userOrServer]?.[key.isPush ? "push" : "storage"];
336
+ },
337
+ async save(key: IOdspTokenManagerCacheKey, tokens: IOdspTokens): Promise<void> {
338
+ const rc = await loadAndPatchRC();
339
+ if (!rc.tokens) {
340
+ rc.tokens = {
341
+ version: 1,
342
+ data: {},
343
+ };
344
+ }
345
+ let prevTokens = rc.tokens.data[key.userOrServer];
346
+ if (!prevTokens) {
347
+ prevTokens = {};
348
+ rc.tokens.data[key.userOrServer] = prevTokens;
349
+ }
350
+ prevTokens[key.isPush ? "push" : "storage"] = tokens;
351
+ return saveRC(rc);
352
+ },
353
+ async lock<T>(callback: () => Promise<T>): Promise<T> {
354
+ const release = await lockRC();
355
+ try {
356
+ return await callback();
357
+ } finally {
358
+ await release();
359
+ }
360
+ },
369
361
  };