Skip to content

Commit ef9e7e0

Browse files
authored
Merge pull request #68 from Navigraph/feat/token-buffers
2 parents 22cb853 + 2c364c2 commit ef9e7e0

File tree

3 files changed

+43
-7
lines changed

3 files changed

+43
-7
lines changed

.changeset/giant-dryers-fetch.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@navigraph/auth": patch
3+
---
4+
5+
Added request buffers to all token requests, including user verification.
6+
This ensures that the SDK does not send multiple identical token requests in parallel and instead returns one response for all requests, ultimately increasing both speed and reliability.

packages/auth/src/api/requestToken.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,32 @@ import axios from "axios";
22
import { getIdentityTokenEndpoint } from "../constants";
33
import { NavigraphCancelToken } from "../lib/navigraphRequest";
44
import { TokenResponse } from "./types";
5-
import { AuthenticationAbortedError, Scope } from "@navigraph/app";
5+
import { AuthenticationAbortedError, Logger, NotInitializedError, Scope, getApp } from "@navigraph/app";
66
import { tokenStorage } from "../internals/storage";
77
import { setUser } from "../internals/user";
88
import { decodeUser } from "../util";
99

10+
const requests = new Map<string, Promise<TokenResponse> | null>();
11+
1012
/** Requests a token using provided options and updates the credential stores with the result. Also sets the user variable. */
1113
export async function requestToken(params: Record<string, string>, cancelToken?: NavigraphCancelToken) {
12-
return axios
14+
const app = getApp();
15+
if (!app) throw new NotInitializedError("Auth");
16+
17+
const key = JSON.stringify(params);
18+
const ongoingRequest = requests.get(key);
19+
20+
if (ongoingRequest) {
21+
Logger.debug("Found ongoing request with key " + key);
22+
return ongoingRequest;
23+
}
24+
25+
Logger.debug("No ongoing request found with key " + key);
26+
27+
const requestPromise = axios
1328
.post<TokenResponse>(getIdentityTokenEndpoint(), new URLSearchParams(params), {
1429
cancelToken,
15-
withCredentials: params.scope?.includes(Scope.TILES) ? true : undefined,
30+
withCredentials: app.scopes.includes(Scope.TILES) ? true : undefined,
1631
headers: { "Content-Type": "application/x-www-form-urlencoded" },
1732
})
1833
.then(async ({ data }) => {
@@ -27,5 +42,9 @@ export async function requestToken(params: Record<string, string>, cancelToken?:
2742
if (axios.isCancel(err)) throw new AuthenticationAbortedError();
2843

2944
throw err;
30-
});
45+
})
46+
.finally(() => requests.delete(key));
47+
48+
requests.set(key, requestPromise);
49+
return requestPromise;
3150
}

packages/auth/src/internals/verifyUser.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import { NotInitializedError, getApp } from "@navigraph/app";
1+
import { Logger, NotInitializedError, getApp } from "@navigraph/app";
22
import { tokenStorage } from "./storage";
33
import { isExpiredToken, decodeUser, runWithLock } from "../util";
44
import { setUser, USER, User } from "./user";
55
import { requestToken } from "../api/requestToken";
66

7+
let verifyUserPromise: Promise<User | null> | null = null;
8+
79
/**
810
* Verifies the validity of the currently stored access token. If the token is invalid or expired, a refresh attempt will be made.
911
* @returns {Promise<User|null>} The currently authenticated user
@@ -21,7 +23,12 @@ export default async function verifyUser() {
2123
return user;
2224
}
2325

24-
return new Promise<User | null>((resolve, reject) => {
26+
if (verifyUserPromise) {
27+
Logger.debug("Found ongoing verification request, returning promise early");
28+
return verifyUserPromise;
29+
}
30+
31+
verifyUserPromise = new Promise<User | null>((resolve, reject) => {
2532
runWithLock("NAVIGRAPH_SDK_INIT", async () => {
2633
const REFRESH_TOKEN = await tokenStorage.getRefreshToken();
2734

@@ -35,6 +42,10 @@ export default async function verifyUser() {
3542
}
3643

3744
resolve(USER);
38-
}).catch(reject);
45+
})
46+
.catch(reject)
47+
.finally(() => (verifyUserPromise = null));
3948
});
49+
50+
return verifyUserPromise;
4051
}

0 commit comments

Comments
 (0)