stacker.news/api/ssrApollo.js

139 lines
3.7 KiB
JavaScript

import { ApolloClient, InMemoryCache } from '@apollo/client'
import { SchemaLink } from '@apollo/client/link/schema'
import { makeExecutableSchema } from '@graphql-tools/schema'
import resolvers from './resolvers'
import typeDefs from './typeDefs'
import models from './models'
import { print } from 'graphql'
import lnd from './lnd'
import search from './search'
import { ME } from '../fragments/users'
import { PRICE } from '../fragments/price'
import { BLOCK_HEIGHT } from '../fragments/blockHeight'
import { CHAIN_FEE } from '../fragments/chainFee'
import { getServerSession } from 'next-auth/next'
import { getAuthOptions } from '../pages/api/auth/[...nextauth]'
export default async function getSSRApolloClient ({ req, res, me = null }) {
const session = req && await getServerSession(req, res, getAuthOptions(req))
const client = new ApolloClient({
ssrMode: true,
link: new SchemaLink({
schema: makeExecutableSchema({
typeDefs,
resolvers
}),
context: {
models,
me: session
? session.user
: me,
lnd,
search
}
}),
cache: new InMemoryCache({
freezeResults: true
}),
assumeImmutableResults: true,
defaultOptions: {
watchQuery: {
fetchPolicy: 'no-cache',
nextFetchPolicy: 'no-cache',
canonizeResults: true,
ssr: true
},
query: {
fetchPolicy: 'no-cache',
nextFetchPolicy: 'no-cache',
canonizeResults: true,
ssr: true
}
}
})
return client
}
/**
* Takes a query and variables and returns a getServerSideProps function
*
* @param opts Options
* @param opts.query graphql query or function that return graphql query
* @param opts.variables graphql variables or function that return graphql variables
* @param opts.notFound function that tests data to determine if 404
* @param opts.authRequired boolean that determines if auth is required
*/
export function getGetServerSideProps (
{ query: queryOrFunc, variables: varsOrFunc, notFound, authRequired }) {
return async function ({ req, res, query: params }) {
const { nodata, ...realParams } = params
// we want to use client-side cache
if (nodata) return { props: { } }
const variables = typeof varsOrFunc === 'function' ? varsOrFunc(realParams) : varsOrFunc
const vars = { ...realParams, ...variables }
const query = typeof queryOrFunc === 'function' ? queryOrFunc(vars) : queryOrFunc
const client = await getSSRApolloClient({ req, res })
const { data: { me } } = await client.query({ query: ME })
if (authRequired && !me) {
const callback = process.env.PUBLIC_URL + req.url
return {
redirect: {
destination: `/login?callbackUrl=${encodeURIComponent(callback)}`
}
}
}
const { data: { price } } = await client.query({
query: PRICE, variables: { fiatCurrency: me?.privates?.fiatCurrency }
})
const { data: { blockHeight } } = await client.query({
query: BLOCK_HEIGHT, variables: {}
})
const { data: { chainFee } } = await client.query({
query: CHAIN_FEE, variables: {}
})
let error = null; let data = null; let props = {}
if (query) {
try {
({ error, data } = await client.query({
query,
variables: vars
}))
} catch (e) {
console.error(e)
}
if (error || !data || (notFound && notFound(data, vars, me))) {
return {
notFound: true
}
}
props = {
apollo: {
query: print(query),
variables: vars
}
}
}
return {
props: {
...props,
me,
price,
blockHeight,
chainFee,
ssrData: data
}
}
}
}