Cutting straight to the case: backend project using typescript and graphql.
We have a package /graphql_gateway
where all requests are sent to. This gateway uses graphQL mesh to stitch the schemas of our Supabase and our server which is located in the package /graphql_server
.
This is the .meshrc.yaml
file:
serve:
endpoint: /graphqlyour text
playground: true
port: 3000
sources:
- name: Supabase
handler:
graphql:
endpoint: '{env.SUPABASE_GRAPHQL_URL}'
operationHeaders:
apiKey: '{env.SUPABASE_API_KEY}'
Content-Type: application/json
schemaHeaders:
apiKey: '{env.SUPABASE_API_KEY}'
Content-Type: application/json
- name: Server
handler:
graphql:
endpoint: '{env.SERVER_GRAPHQL_URL}'
source: ./../graphql_server/src/graphql/schema.ts
additionalEnvelopPlugins: './src/envelopPlugins'
this is corresponding the envelopPlugins.ts
file:
import { ResolveUserFn, useGenericAuth } from '@envelop/generic-auth'
import { User, createClient } from '@supabase/supabase-js'
import { parse } from 'cookie'
import { IncomingMessage } from 'http'
const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_API_KEY)
type Context = {
req: IncomingMessage
}
const resolveUserFn: ResolveUserFn<User, Context> = async (context: Context) => {
// Get cookies from authorization header (temporary workaround)
const cookies = parse(context?.req?.headers?.authorization as string)
if (!cookies?.['supabase-auth-token']) {
console.error('Auth token missing')
return null
}
// Get JWT from cookie (cookie set by Supabase is array of tokens)
const tokenArray: string[] = JSON.parse(cookies?.['supabase-auth-token']) as string[]
const jwt = tokenArray?.[0]
// Get user from Supabase if JWT is valid
const {
data: { user },
error
} = await supabase.auth.getUser(jwt)
if (error) {
console.error('Error while trying to get user from Supabase', error)
return null
}
return user
}
const plugins = [
useGenericAuth({
resolveUserFn,
mode: 'protect-all'
})
]
export default plugins
Now I would assume according to the documentation of useGenericAuth, that it injects the user into the context and that I can therefore access context.currentUser
or similar in the resolvers.ts
file of /graphql_server
, in case that /graphql_gateway
decides to send forward the request to there.
that is the server.ts
file of /graphql_server
:
import Fastify from 'fastify'
import mercurius from 'mercurius'
import resolvers from './graphql/resolvers'
import schema from './graphql/schema'
const ENV = process.env.NODE_ENV || 'development'
const envToLogger = {
development: {
transport: {
target: 'pino-pretty',
options: {
translateTime: 'HH:MM:ss Z',
ignore: 'pid,hostname'
}
}
},
production: true
}
const app = Fastify({
logger: envToLogger\[ENV\]
})
app.addHook('preHandler', function (req, reply, done) {
if (req.body) {
req.log.info({ body: req.body }, 'parsed body')
}
done()
})
// https://github.com/mercurius-js/mercurius-typescript/tree/master/examples
void app.register(mercurius, {
schema,
resolvers,
graphiql: true // see http://localhost:3001/graphiql
})
export default app
In resolvers.ts
i would like to do somthing like
...
Query: {
testQuery: (parent: unknown, args: unknown, context: any, info: unknown) =\> {
console.log(context.currentUser)
return 'test'
}
}
...
As described above I tried to use the useGenericAuth
function to inject the user into the context, so that I can access it in the resolvers. But the user is not set, either because useGenericAuth does not work as expected, or because the Context is not transferred to the /graphql_server
part of our app.
How can I access the currently logged in user in the resolvers?