mirror of
https://github.com/apotdevin/thunderhub.git
synced 2025-02-22 14:22:33 +01:00
* chore: 🔧 change withApollo * feat: ✨ set cookie from server * chore: 🔧 remove bcrypt dep * fix: 🐛 initialize check * chore: 🔧 remove cookies correctly * fix: 🐛 status type
159 lines
4.7 KiB
TypeScript
159 lines
4.7 KiB
TypeScript
/* eslint @typescript-eslint/no-var-requires: 0 */
|
|
import * as React from 'react';
|
|
import Head from 'next/head';
|
|
import { ApolloProvider } from '@apollo/react-hooks';
|
|
import { ApolloClient } from 'apollo-client';
|
|
import { InMemoryCache } from 'apollo-cache-inmemory';
|
|
import getConfig from 'next/config';
|
|
|
|
let globalApolloClient = null;
|
|
|
|
const { publicRuntimeConfig } = getConfig();
|
|
const { apiUrl: uri } = publicRuntimeConfig;
|
|
|
|
function createIsomorphLink(ctx) {
|
|
if (typeof window === 'undefined') {
|
|
const { SchemaLink } = require('apollo-link-schema');
|
|
const { thunderHubSchema: schema } = require('api/schemas');
|
|
return new SchemaLink({ schema, context: ctx });
|
|
} else {
|
|
const { HttpLink } = require('apollo-link-http');
|
|
|
|
return new HttpLink({
|
|
uri,
|
|
credentials: 'same-origin',
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates and configures the ApolloClient
|
|
* @param {Object} [initialState={}]
|
|
*/
|
|
function createApolloClient(ctx = {}, initialState = {}) {
|
|
const ssrMode = typeof window === 'undefined';
|
|
const cache = new InMemoryCache().restore(initialState);
|
|
|
|
// Check out https://github.com/zeit/next.js/pull/4611 if you want to use the AWSAppSyncClient
|
|
return new ApolloClient({
|
|
ssrMode,
|
|
link: createIsomorphLink(ctx),
|
|
cache,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Always creates a new apollo client on the server
|
|
* Creates or reuses apollo client in the browser.
|
|
* @param {Object} initialState
|
|
*/
|
|
function initApolloClient(ctx, initialState?) {
|
|
// Make sure to create a new client for every server-side request so that data
|
|
// isn't shared between connections (which would be bad)
|
|
if (typeof window === 'undefined') {
|
|
return createApolloClient(ctx, initialState);
|
|
}
|
|
|
|
// Reuse client on the client-side
|
|
if (!globalApolloClient) {
|
|
globalApolloClient = createApolloClient(ctx, initialState);
|
|
}
|
|
|
|
return globalApolloClient;
|
|
}
|
|
|
|
/**
|
|
* Creates and provides the apolloContext
|
|
* to a next.js PageTree. Use it by wrapping
|
|
* your PageComponent via HOC pattern.
|
|
* @param {Function|Class} PageComponent
|
|
* @param {Object} [config]
|
|
* @param {Boolean} [config.ssr=true]
|
|
*/
|
|
export function withApollo(PageComponent, { ssr = true } = {}) {
|
|
const WithApollo = ({ apolloClient, apolloState, ...pageProps }) => {
|
|
const client = apolloClient || initApolloClient(undefined, apolloState);
|
|
return (
|
|
<ApolloProvider client={client}>
|
|
<PageComponent {...pageProps} />
|
|
</ApolloProvider>
|
|
);
|
|
};
|
|
|
|
// Set the correct displayName in development
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
const displayName =
|
|
PageComponent.displayName || PageComponent.name || 'Component';
|
|
|
|
if (displayName === 'App') {
|
|
console.warn('This withApollo HOC only works with PageComponents.');
|
|
}
|
|
|
|
WithApollo.displayName = `withApollo(${displayName})`;
|
|
}
|
|
|
|
if (ssr || PageComponent.getInitialProps) {
|
|
WithApollo.getInitialProps = async ctx => {
|
|
const { AppTree } = ctx;
|
|
|
|
// Initialize ApolloClient, add it to the ctx object so
|
|
// we can use it in `PageComponent.getInitialProp`.
|
|
const apolloClient = (ctx.apolloClient = initApolloClient({
|
|
res: ctx.res,
|
|
req: ctx.req,
|
|
}));
|
|
|
|
// Run wrapped getInitialProps methods
|
|
let pageProps = {};
|
|
if (PageComponent.getInitialProps) {
|
|
pageProps = await PageComponent.getInitialProps(ctx);
|
|
}
|
|
|
|
// Only on the server:
|
|
if (typeof window === 'undefined') {
|
|
// When redirecting, the response is finished.
|
|
// No point in continuing to render
|
|
if (ctx.res && ctx.res.finished) {
|
|
return pageProps;
|
|
}
|
|
|
|
// Only if ssr is enabled
|
|
if (ssr) {
|
|
try {
|
|
// Run all GraphQL queries
|
|
const { getDataFromTree } = await import('@apollo/react-ssr');
|
|
await getDataFromTree(
|
|
<AppTree
|
|
pageProps={{
|
|
...pageProps,
|
|
apolloClient,
|
|
}}
|
|
/>
|
|
);
|
|
} catch (error) {
|
|
// Prevent Apollo Client GraphQL errors from crashing SSR.
|
|
// Handle them in components via the data.error prop:
|
|
// https://www.apollographql.com/docs/react/api/react-apollo.html#graphql-query-data-error
|
|
console.error('Error while running `getDataFromTree`', error);
|
|
}
|
|
|
|
// getDataFromTree does not call componentWillUnmount
|
|
// head side effect therefore need to be cleared manually
|
|
Head.rewind();
|
|
}
|
|
}
|
|
|
|
// Extract query data from the Apollo store
|
|
const apolloState = apolloClient.cache.extract();
|
|
|
|
console.log({ apolloState });
|
|
|
|
return {
|
|
...pageProps,
|
|
apolloState,
|
|
};
|
|
};
|
|
}
|
|
|
|
return WithApollo;
|
|
}
|