11import * as React from 'react' ;
2+ import { ApolloClient , ApolloQueryResult } from 'apollo-boost' ;
23import gql from 'graphql-tag' ;
34import Router from 'next/router' ;
45import cookie from 'cookie' ;
6+ import { Account , Query } from '@graphql-model' ;
7+ import { NextDocumentContext } from 'next/document' ;
58
6- const checkLoggedIn = ( apolloClient : any ) : Promise < { loggedInUser : any } > => {
9+ interface LoggedInUserResponse {
10+ readonly loggedInUser : Pick < Account , 'id' | 'firstName' | 'lastName' > ;
11+ }
12+
13+ const checkLoggedIn = ( apolloClient : ApolloClient < any > ) : Promise < Partial < LoggedInUserResponse > > => {
714 return apolloClient
815 . query ( {
916 query : gql `
@@ -16,54 +23,54 @@ const checkLoggedIn = (apolloClient: any): Promise<{loggedInUser: any}> => {
1623 }
1724 ` ,
1825 } )
19- . then ( ( { data} : any ) => {
20- return { loggedInUser : data } ;
26+ . then ( ( { data} : ApolloQueryResult < Query > ) => {
27+ if ( ! data || ! data . me ) {
28+ throw new Error ( 'User is not logged' ) ;
29+ }
30+ return { loggedInUser : data . me } ;
2131 } )
2232 . catch ( ( ) => {
2333 // Fail gracefully
24- return { loggedInUser : { } } ;
34+ return { loggedInUser : undefined } ;
2535 } ) ;
2636} ;
2737
28- const redirect = ( context : any , target : string ) => {
29- if ( context . res ) {
30- // server
31- // 303: "See other"
38+ const redirect = async ( target : string , context ?: NextDocumentContext ) : Promise < boolean > => {
39+ if ( context && context . res ) {
3240 context . res . writeHead ( 303 , { Location : target } ) ;
3341 context . res . end ( ) ;
42+ return true ;
3443 } else {
35- // In the browser, we just pretend like this never even happened ;)
36- Router . replace ( target ) ;
44+ return await Router . replace ( target ) ;
3745 }
3846} ;
3947
40- export const withAuthAdmin = ( BaseComponent : any ) => {
41- return class extends React . Component {
42- signout = ( apolloClient : any ) => ( ) => {
48+ export interface WithAuthAdminProps extends LoggedInUserResponse {
49+ readonly logout : ( client : ApolloClient < any > ) => ( ) => Promise < void > ;
50+ }
51+
52+ export const withAuthAdmin = ( BaseComponent : React . ComponentType < WithAuthAdminProps > ) => {
53+ return class extends React . Component < LoggedInUserResponse > {
54+ handleOnLogout = ( apolloClient : ApolloClient < any > ) => async ( ) => {
4355 document . cookie = cookie . serialize ( 'token' , '' , {
4456 maxAge : - 1 , // Expire the cookie immediately
4557 } ) ;
46-
47- // Force a reload of all the current queries now that the user is
48- // logged in, so we don't accidentally leave any state around.
49- apolloClient . cache . reset ( ) . then ( ( ) => {
50- // Redirect to a more useful page when signed out
51- redirect ( { } , '/login' ) ;
52- } ) ;
58+ await apolloClient . cache . reset ( ) ;
59+ await redirect ( '/login' ) ;
5360 } ;
5461
55- static async getInitialProps ( context : any , _ : any ) {
62+ static async getInitialProps ( context : NextDocumentContext & { apolloClient : ApolloClient < any > } ) {
5663 const { loggedInUser} = await checkLoggedIn ( context . apolloClient ) ;
57- if ( ! loggedInUser . me ) {
64+ if ( ! loggedInUser ) {
5865 // If not signed in, send them somewhere more useful
59- redirect ( context , '/login' ) ;
66+ await redirect ( '/login' , context ) ;
6067 }
6168
6269 return { loggedInUser} ;
6370 }
6471
6572 render ( ) {
66- return < BaseComponent { ...this . props } logout = { this . signout } /> ;
73+ return < BaseComponent { ...this . props } logout = { this . handleOnLogout } /> ;
6774 }
6875 } ;
6976} ;
0 commit comments