Using GraphQL Envelop+Helix in Redwood v0.35+

Not any more. I have removed it for this implementation.

Out of curiosity, if you run simply via yarn rw dev does it behave differently?

Or even yarn rw serve?

What is the envar CONTEXT=PORTAL_APP used for?

Ive tried with yarn rw dev and same thing happens. I use the CONTEXT var to switch my routes between portal app and admin app - it’s front-end really - shouldn’t affect this.

Not sure if it makes a different but technically I have to run with yarn rw dev --fwd="--disable-host-check=true" because I visit my app at http://app.uservitals.local:8910/

I am actually hitting the same thing now as well where the context.currentUser is now null and requests are saying unauthorized after I updated my code to use envelop + helix

Thanks @KrisCoulson myself and @danny will try to track this down and fix. If you can share your getCurrentUser function, GraphQL handler, and how you are using requireAuth— in a function or a service that can help. Also your auth provider. Thanks

Docs for using Sentry.io with redwood

Install the required libraries:

yarn add @envelop/sentry @sentry/node @sentry/tracing

Create a reusable Sentry file api/src/lib/sentry

import * as Sentry from '@sentry/node'
import * as Tracing from '@sentry/tracing'

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  tracesSampleRate: 0.5,
})

export default Sentry

Then import it into your graphql function api/src/functions/graphql

import { createGraphQLHandler } from '@redwoodjs/graphql-server'
import { useSentry } from '@envelop/sentry'
import Sentry from 'src/lib/sentry'

import { getCurrentUser } from 'src/lib/auth'
import { logger } from 'src/lib/logger'
import directives from 'src/directives/**/*.{js,ts}'
import sdls from 'src/graphql/**/*.sdl.{js,ts}'
import services from 'src/services/**/*.{js,ts}'
import { db } from 'src/lib/db'

const extraPlugins = [
  useSentry({
    includeRawResult: false, // set to `true` in order to include the execution result in the metadata collected
    includeResolverArgs: false, // set to `true` in order to include the args passed to resolvers
    includeExecuteVariables: false, // set to `true` in order to include the operation variables values
    // appendTags: (args) => { return { ... }} // if you wish to add custom "tags" to the Sentry transaction created per operation
  }),
]

export const handler = createGraphQLHandler({
  getCurrentUser,
  loggerConfig: {
    logger,
    options: { tracing: true, operationName: true },
  },
  directives,
  sdls,
  services,
  extraPlugins,
  onException: () => {
    db.$disconnect()
  },
})

For a custom function, such as api/src/functions/checkout

import Sentry from 'src/lib/sentry'
import { processOrder } from 'src/lib/wyre/order'

export const handler = async (event) => {
  // Default response
  let statusCode = 200
  let message = ''

  try {
    let body = event.body
    if (typeof body === 'string') body = JSON.parse(body)

    await processOrder({ orderId: body.orderId, referenceId: body.referenceId })

    return {
      statusCode,
      body: {
        message: 'Success!',
      },
    }
  } catch (e) {
    console.log(event)
    Sentry.captureException(e)
    return {
      statusCode, // Always return 200
      body: {
        message: 'Internal server error',
      },
    }
  }
}

:tada: Tada! Please share your experience if you use Sentry or other plugins

3 Likes

@viperfx You also set up Sentry the other day, didn’t you? Did you do it the same way?

All it’s way easier now.

There is an envelop plug-in and you add it as ‘extraPlugins’ in the createGraphQLHandler.

We’ll add some docs to help know how to setup, but that’s what @viperfx used.

The Guild recently made it easier to set the current user as well.

1 Like

Oh right, I forgot about getCurrentUser

//api/src/lib/auth.js
import Sentry from 'src/lib/sentry'

export const getCurrentUser = async (session) => {
  const member = await db.member.findUnique({ where: { id: session.id } })
  if (!member) return null
  // WARNING: Returned values here are exposed to the FE
  Sentry.setUser({ username: member.username, id: member.id })

Just sent through this and it worked like a charm. Thank you, @pi0neerpat!

2 Likes