Skip to content

Commit aba3bad

Browse files
authored
Emit custom event when token is refreshed (#51)
1 parent 0c9cd63 commit aba3bad

File tree

4 files changed

+85
-1
lines changed

4 files changed

+85
-1
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
/node_modules
22
/dist
33
.idea/
4+
.DS_Store
5+
*.log

.prettierrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

src/utils/session-data.test.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { setSessionData } from "./session-data";
2+
import { storageKeys } from "./storage-keys";
3+
import { memoryStorage } from "./memory-storage";
4+
import { User } from "../interfaces/user.interface";
5+
6+
const mockUser: User = {
7+
object: "user",
8+
id: "123",
9+
10+
emailVerified: true,
11+
profilePictureUrl: "https://example.com/profile.png",
12+
firstName: "Test",
13+
lastName: "User",
14+
externalId: "123",
15+
lastSignInAt: new Date("2021-01-01").toISOString(),
16+
createdAt: new Date("2021-01-01").toISOString(),
17+
updatedAt: new Date("2021-01-01").toISOString(),
18+
};
19+
20+
describe("setSessionData", () => {
21+
// Valid JWT token for testing (not a real token, just for testing purposes)
22+
const validToken =
23+
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRlc3Qta2V5In0.eyJpc3MiOiJodHRwczovL2V4YW1wbGUuY29tIiwic3ViIjoiMTIzNDU2Nzg5MCIsImF1ZCI6WyJhdWRpZW5jZTEiLCJhdWRpZW5jZTIiXSwiZXhwIjoxNzM1Njg5NjAwLCJpYXQiOjE3MzU2MDMyMDAsImp0aSI6InVuaXF1ZS1pZCIsImN1c3RvbSI6InZhbHVlIiwibmVzdGVkIjp7ImtleSI6InZhbHVlIn19.signature";
24+
25+
const tokenchangeListener = jest.fn();
26+
beforeEach(() => {
27+
window.addEventListener("authkit:tokenchange", tokenchangeListener);
28+
});
29+
afterEach(() => {
30+
window.removeEventListener("authkit:tokenchange", tokenchangeListener);
31+
memoryStorage.reset();
32+
});
33+
34+
it("updates storage when the access token is set", () => {
35+
const currentAccessToken = memoryStorage.getItem(storageKeys.accessToken);
36+
setSessionData({
37+
accessToken: validToken,
38+
refreshToken: "refresh_token",
39+
user: mockUser,
40+
});
41+
expect(memoryStorage.getItem(storageKeys.accessToken)).toBe(validToken);
42+
expect(memoryStorage.getItem(storageKeys.accessToken)).not.toBe(
43+
currentAccessToken,
44+
);
45+
});
46+
47+
it("dispatches a tokenchange event when the access token is set", () => {
48+
setSessionData({
49+
accessToken: validToken,
50+
refreshToken: "refresh_token",
51+
user: mockUser,
52+
});
53+
expect(tokenchangeListener).toHaveBeenCalledWith(
54+
expect.objectContaining({
55+
detail: { accessToken: validToken },
56+
}),
57+
);
58+
});
59+
});

src/utils/session-data.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,15 @@ export function setSessionData(
1818
) {
1919
const { user, accessToken, refreshToken } = data;
2020
memoryStorage.setItem(storageKeys.user, user);
21-
memoryStorage.setItem(storageKeys.accessToken, accessToken);
21+
const currentAccessToken = memoryStorage.getItem(storageKeys.accessToken);
22+
if (currentAccessToken !== accessToken) {
23+
globalThis.dispatchEvent(
24+
new CustomEvent("authkit:tokenchange", {
25+
detail: { accessToken },
26+
}),
27+
);
28+
memoryStorage.setItem(storageKeys.accessToken, accessToken);
29+
}
2230
(devMode ? window.localStorage : memoryStorage).setItem(
2331
storageKeys.refreshToken,
2432
refreshToken,
@@ -44,3 +52,17 @@ export function getRefreshToken({ devMode = false } = {}) {
4452
storageKeys.refreshToken,
4553
) as string | undefined;
4654
}
55+
56+
interface CustomEventMap {
57+
"authkit:tokenchange": CustomEvent<{ accessToken: string }>;
58+
}
59+
60+
declare global {
61+
interface Window {
62+
addEventListener<K extends keyof CustomEventMap>(
63+
type: K,
64+
listener: (this: Document, ev: CustomEventMap[K]) => void,
65+
): void;
66+
dispatchEvent<K extends keyof CustomEventMap>(ev: CustomEventMap[K]): void;
67+
}
68+
}

0 commit comments

Comments
 (0)