-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwithTokensUpdate.tsx
94 lines (78 loc) · 2.65 KB
/
withTokensUpdate.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { differenceInMilliseconds } from 'date-fns';
import omit from 'lodash/omit';
import Cookie from 'universal-cookie';
import UpdateToken from 'graphql/mutations/updateToken.graphql';
import CurrentUser from 'graphql/queries/currentUser.graphql';
import { ACCESS_TOKEN_KEY, ACCESS_TOKEN_MINIMAL_LIFE_TIME, REFRESH_TOKEN_KEY } from 'config/jwt';
import { ApolloPageContext, TApolloClient, TNextPage } from 'lib/apollo/types';
import { parseJWT, setTokensToCookies } from './tokens';
const updateTokensMutation = (apolloClient: TApolloClient) =>
apolloClient.mutate({
mutation: UpdateToken,
fetchPolicy: 'no-cache', // to not leak tokens data in apolloState $ROOT_MUTATION
});
const updateTokensServerSide = async ({ req, res, apolloClient }: ApolloPageContext) => {
try {
const {
data: {
updateToken: { me, refreshToken, accessToken },
},
} = await updateTokensMutation(apolloClient);
apolloClient.writeQuery({
query: CurrentUser,
data: {
me,
},
});
if (!res.writableEnded) setTokensToCookies({ refreshToken, accessToken, req, res });
} catch (error) {
console.error(error);
}
};
const getCurrentUserQuery = (apolloClient: TApolloClient) =>
apolloClient.query({
query: CurrentUser,
fetchPolicy: 'no-cache', // to not leak tokens data in apolloState $ROOT_MUTATION
});
const updateCurrentUserServerSide = async ({ apolloClient }: ApolloPageContext) => {
try {
const {
data: { me },
} = await getCurrentUserQuery(apolloClient);
apolloClient.writeQuery({
query: CurrentUser,
data: {
me,
},
});
} catch (error) {
console.error(error);
}
};
const withTokensUpdate = (Page: TNextPage): TNextPage => {
const WithTokensUpdate: TNextPage = ({ ...pageProps }) => {
return <Page {...pageProps} />;
};
WithTokensUpdate.getInitialProps = async context => {
const { req, res } = context;
const ctx = omit(context, ['req', 'res']);
if (!!req && !!res) {
const cookie = new Cookie(req.headers.cookie);
const accessToken = cookie.get(ACCESS_TOKEN_KEY);
const jwtAccess = parseJWT(accessToken);
if (
!accessToken ||
!jwtAccess.exp ||
differenceInMilliseconds(jwtAccess.exp * 1000, Date.now()) <= ACCESS_TOKEN_MINIMAL_LIFE_TIME
) {
const refreshToken = cookie.get(REFRESH_TOKEN_KEY);
if (refreshToken) await updateTokensServerSide(context);
} else {
await updateCurrentUserServerSide(context);
}
}
return Page.getInitialProps ? Page.getInitialProps(context) : ctx;
};
return WithTokensUpdate;
};
export default withTokensUpdate;