stacker.news/api/ssrApollo.js

204 lines
6.0 KiB
JavaScript
Raw Normal View History

2021-04-14 23:56:29 +00:00
import { ApolloClient, InMemoryCache } from '@apollo/client'
import { SchemaLink } from '@apollo/client/link/schema'
2023-07-24 22:50:12 +00:00
import { makeExecutableSchema } from '@graphql-tools/schema'
2021-04-14 23:56:29 +00:00
import resolvers from './resolvers'
import typeDefs from './typeDefs'
import models from './models'
2021-10-26 20:49:37 +00:00
import { print } from 'graphql'
2021-10-28 19:59:53 +00:00
import lnd from './lnd'
2022-01-26 15:35:14 +00:00
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]'
2021-04-14 23:56:29 +00:00
export default async function getSSRApolloClient ({ req, res, me = null }) {
const session = req && await getServerSession(req, res, getAuthOptions(req))
2022-11-24 19:22:58 +00:00
const client = new ApolloClient({
ssrMode: true,
link: new SchemaLink({
2022-11-06 17:28:58 +00:00
schema: makeExecutableSchema({
typeDefs,
resolvers
}),
context: {
2021-04-14 23:56:29 +00:00
models,
2022-04-21 22:50:02 +00:00
me: session
? session.user
2022-04-21 22:50:02 +00:00
: me,
2022-01-26 15:35:14 +00:00
lnd,
2023-08-17 00:48:45 +00:00
search
2021-04-14 23:56:29 +00:00
}
}),
cache: new InMemoryCache({
freezeResults: true
}),
assumeImmutableResults: true,
defaultOptions: {
watchQuery: {
2023-08-05 19:46:29 +00:00
fetchPolicy: 'no-cache',
nextFetchPolicy: 'no-cache',
canonizeResults: true,
ssr: true
},
query: {
2023-08-05 19:46:29 +00:00
fetchPolicy: 'no-cache',
nextFetchPolicy: 'no-cache',
canonizeResults: true,
ssr: true
}
}
})
2022-11-24 19:22:58 +00:00
return client
}
2021-10-26 20:49:37 +00:00
function oneDayReferral (request, { me }) {
if (!me) return
const refHeader = request.headers['x-stacker-news-referrer']
if (!refHeader) return
const referrers = refHeader.split('; ').filter(Boolean)
for (const referrer of referrers) {
let prismaPromise, getData
if (referrer.startsWith('item-')) {
prismaPromise = models.item.findUnique({ where: { id: parseInt(referrer.slice(5)) } })
getData = item => ({
referrerId: item.userId,
refereeId: parseInt(me.id),
type: item.parentId ? 'COMMENT' : 'POST',
typeId: String(item.id)
})
} else if (referrer.startsWith('profile-')) {
const name = referrer.slice(8)
// exclude all pages that are not user profiles
if (['api', 'auth', 'day', 'invites', 'invoices', 'referrals', 'rewards',
'satistics', 'settings', 'stackers', 'wallet', 'withdrawals', '404', '500',
'email', 'live', 'login', 'notifications', 'offline', 'search', 'share',
'signup', 'territory', 'recent', 'top', 'edit', 'post', 'rss', 'saloon',
'faq', 'story', 'privacy', 'copyright', 'tos', 'changes', 'guide', 'daily',
'anon', 'ad'].includes(name)) continue
prismaPromise = models.user.findUnique({ where: { name } })
getData = user => ({
referrerId: user.id,
refereeId: parseInt(me.id),
type: 'PROFILE',
typeId: String(user.id)
})
} else if (referrer.startsWith('territory-')) {
prismaPromise = models.sub.findUnique({ where: { name: referrer.slice(10) } })
getData = sub => ({
referrerId: sub.userId,
refereeId: parseInt(me.id),
type: 'TERRITORY',
typeId: sub.name
})
} else {
prismaPromise = models.user.findUnique({ where: { name: referrer } })
getData = user => ({
referrerId: user.id,
refereeId: parseInt(me.id),
type: 'REFERRAL',
typeId: String(user.id)
})
}
prismaPromise?.then(ref => {
if (ref && getData) {
const data = getData(ref)
// can't refer yourself
if (data.refereeId === data.referrerId) return
models.oneDayReferral.create({ data }).catch(console.error)
}
}).catch(console.error)
}
}
/**
* 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
*/
2023-08-31 00:03:05 +00:00
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: { } }
2023-08-31 00:03:05 +00:00
const variables = typeof varsOrFunc === 'function' ? varsOrFunc(realParams) : varsOrFunc
const vars = { ...realParams, ...variables }
2023-08-31 00:03:05 +00:00
const query = typeof queryOrFunc === 'function' ? queryOrFunc(vars) : queryOrFunc
const client = await getSSRApolloClient({ req, res })
2022-09-06 14:57:34 +00:00
2023-10-23 23:19:36 +00:00
const { data: { me } } = await client.query({ query: ME })
2022-09-06 14:57:34 +00:00
if (authRequired && !me) {
2024-04-08 22:54:39 +00:00
const callback = process.env.NEXT_PUBLIC_URL + req.url
2022-01-27 20:15:18 +00:00
return {
redirect: {
2024-02-23 15:32:20 +00:00
destination: `/signup?callbackUrl=${encodeURIComponent(callback)}`
}
2022-01-27 20:15:18 +00:00
}
}
const { data: { price } } = await client.query({
2023-11-10 01:05:35 +00:00
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: {}
})
2022-04-21 22:50:02 +00:00
let error = null; let data = null; let props = {}
if (query) {
2023-08-30 15:00:47 +00:00
try {
({ error, data } = await client.query({
query,
variables: vars
}))
} catch (e) {
console.error(e)
}
2021-10-26 20:49:37 +00:00
2023-11-21 23:32:22 +00:00
if (error || !data || (notFound && notFound(data, vars, me))) {
2024-04-03 00:51:30 +00:00
res.writeHead(302, {
2024-02-23 15:32:20 +00:00
Location: '/404'
}).end()
2022-04-21 22:50:02 +00:00
}
props = {
apollo: {
query: print(query),
variables: vars
2022-04-21 22:50:02 +00:00
}
2021-10-26 20:49:37 +00:00
}
}
oneDayReferral(req, { me })
2021-10-26 20:49:37 +00:00
return {
props: {
2022-04-21 22:50:02 +00:00
...props,
2021-11-28 17:29:17 +00:00
me,
price,
blockHeight,
chainFee,
ssrData: data
2021-10-26 20:49:37 +00:00
}
}
}
}