Skip to content

Commit ff3ea17

Browse files
committed
fix(perf): optimized runRoutes
1 parent 1bdfaf9 commit ff3ea17

File tree

2 files changed

+51
-58
lines changed

2 files changed

+51
-58
lines changed

src/runRoutes.tsx

+48-50
Original file line numberDiff line numberDiff line change
@@ -7,78 +7,76 @@ import { TokenParam, defaultParam } from './token';
77
* as dictated by netlify identity's communication with us via hashes
88
*/
99

10-
const routes = /(confirmation|invite|recovery|email_change)_token=([^&]+)/;
10+
const routes = /(confirmation|invite|recovery|email_change|access)_token=([^&]+)/;
1111
const errorRoute = /error=access_denied&error_description=403/;
12-
const accessTokenRoute = /access_token=/;
13-
const confirmationRoute = /confirmation_token=/;
12+
13+
const reduceHashToKeyValue = (hash: string): { [key: string]: string } =>
14+
hash.split('&').reduce((carry, pair) => {
15+
const [key, value] = pair.split('=');
16+
17+
return { ...carry, [key]: value };
18+
}, {});
19+
20+
const hashReplace = /^#\/?/;
1421

1522
export function runRoutes(
1623
gotrue: GoTrue,
1724
setUser: (value: User) => User | undefined,
1825
remember = true
1926
): TokenParam {
2027
// early terminate if no hash
28+
// also accounts for document.cookie further down
2129
if (!document?.location?.hash) {
2230
return defaultParam;
2331
}
2432

25-
const hash = document.location.hash.replace(/^#\/?/, '');
33+
const hash = document.location.hash.replace(hashReplace, '');
2634

27-
const m = hash.match(routes);
28-
if (m) {
29-
// store.verifyToken(m[1], m[2]);
30-
document.location.hash = '';
31-
}
35+
// todo: maybe replace with history.replaceState to completely clear the url?
36+
// currently keeps #
37+
document.location.hash = '';
3238

33-
const em = hash.match(errorRoute);
34-
if (em) {
35-
// store.openModal("signup");
36-
document.location.hash = '';
39+
// earliest possible bail on any match
40+
if (hash.match(errorRoute)) {
41+
return {
42+
...defaultParam,
43+
error: 'access_denied',
44+
status: 403,
45+
};
3746
}
38-
const params = {} as { [key: string]: string };
39-
hash.split('&').forEach(pair => {
40-
const [key, value] = pair.split('=');
41-
params[key] = value;
42-
});
4347

44-
const am = hash.match(accessTokenRoute);
45-
if (am) {
46-
if (!!document && params.access_token) {
47-
document.cookie = `nf_jwt=${params.access_token}`;
48+
const matchesActionHashes = hash.match(routes);
49+
50+
if (matchesActionHashes) {
51+
const params = reduceHashToKeyValue(hash);
52+
53+
if (params.confirmation_token) {
54+
gotrue
55+
.confirm(params.confirmation_token)
56+
.then(setUser)
57+
.catch(console.error);
58+
59+
// dont notify dev as this package does not export its own method for this
60+
return defaultParam;
4861
}
49-
document.location.hash = '';
50-
// store.openModal("login");
51-
// store.completeExternalLogin(params);
52-
gotrue
53-
.createUser(params, remember)
54-
.then(setUser)
55-
.catch(console.error);
56-
}
5762

58-
const cm = hash.match(confirmationRoute);
59-
if (cm) {
60-
document.location.hash = '';
61-
// store.openModal("login");
62-
// store.completeExternalLogin(params);
63-
gotrue
64-
.confirm(params.confirmation_token)
65-
.then(setUser)
66-
.catch(console.error);
67-
}
63+
if (params.access_token) {
64+
document.cookie = `nf_jwt=${params.access_token}`;
6865

69-
if (m) {
70-
return {
71-
...defaultParam,
72-
type: m[1] as TokenParam['type'],
73-
token: m[2],
74-
};
75-
}
66+
gotrue
67+
.createUser(params, remember)
68+
.then(setUser)
69+
.catch(console.error);
70+
71+
// also dont notify dev here for the same reasons as above
72+
return defaultParam;
73+
}
7674

77-
if (em) {
75+
// pass responsibility to dev in all other cases
7876
return {
7977
...defaultParam,
80-
error: 'access_denied',
81-
status: 403,
78+
type: matchesActionHashes[1] as TokenParam['type'],
79+
token: matchesActionHashes[2],
8280
};
8381
}
8482

src/token.ts

+3-8
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
export type TokenParam = {
22
token: string | undefined;
3-
type:
4-
| 'confirmation'
5-
| 'invite'
6-
| 'recovery'
7-
| 'email_change'
8-
| 'access'
9-
| 'confirmation'
10-
| undefined;
3+
type: 'invite' | 'recovery' | 'email_change' | undefined;
114
error?: 'access_denied';
125
status?: 403;
136
};
147

158
export const defaultParam: TokenParam = {
169
token: undefined,
1710
type: undefined,
11+
error: undefined,
12+
status: undefined,
1813
};

0 commit comments

Comments
 (0)