Next.js Discord

Discord Forum

Run code at NextJS server startup

Unanswered
American black bear posted this in #help-forum
Open in Discord
American black bearOP
Hi, i would like to have a database and an openid-client instance to initialize when my app boot. How can i manage to do that ?

For openid, I have the following code, but i don't know where to call it to make it working:
import { type Client, Issuer } from 'openid-client'

let openIdIssuer: Issuer<Client>
export let client: Client

export async function initOpenId (): Promise<void> {
  const issuerUrl = process.env.OPENID_ISSUER

  if (issuerUrl === undefined) {
    throw new Error('OPENID_ISSUER is not set')
  }
  if (process.env.APP_URL === undefined) {
    throw new Error('APP_URL is not set')
  }

  openIdIssuer = await Issuer.discover(issuerUrl)

  // Get the client ID and secret from the environment
  const clientId = process.env.OPENID_CLIENT_ID
  const clientSecret = process.env.OPENID_CLIENT_SECRET
  const redirectUris = process.env.OPENID_REDIRECT_URIS

  if (clientId === undefined || clientSecret === undefined) {
    throw new Error('OPENID_CLIENT_ID or OPENID_CLIENT_SECRET is not set')
  }
  if (redirectUris === undefined) {
    throw new Error('OPENID_REDIRECT_URIS is not set')
  }

  client = new openIdIssuer.Client({
    client_id: clientId,
    client_secret: clientSecret,
    redirect_uris: redirectUris.split(','),
    response_types: ['code']
  })
}

43 Replies

add the command you run before to the package.json
for example, when i start my dev server i run prisma migrate dev beforehand
when run dev this runs automatically
"dev": "prisma migrate dev && next dev"
@Luan that's a pattern for "before" scripts but I think here OP must initialize the client in every API route/page where relevant
each page and route handler/API route in Next is its own application
because we are in the serverless paradigm
there are no layouts for route handlers or api routes basically
but this is for runnign side effects
you can't say initialize a client and share it elsewhere
"When your register function is deployed, it will be called on each cold boot (but exactly once in each environment)."
maybe you can try to shove a value in "global" though to warm the client
must admit I didn't try it yet
instrumentation works well for me to do this. I haven't gotten it to work using it in a nx monorepo, but on it's own it works well.
American black bearOP
so, from what i understand, next isn't made to manage singleton for stuff like database and other stuff ?
you have a singleton db
but as many client as you need
each serverless functions handles its own lifecycle eg persisting connection to a db
but it can be the same db that's fine
instrumentation might help bypassing that but I am pretty sure it should be considered a hack
instrumentation is for instrumentation after all, which means eg counting the nb of lambda function triggered by your system
American black bearOP
what would be the "best way" to to that then ?
i always used next as a frontend for an API, but now i want to merge everything in the same project, so i'm a bit new on this subject
btw I think they have added db connection to the next.js/learn tutorial
didn't check it yet but it shows connection to Prisma
so it probably adresses your question
Next is not a framework tailored for monolithic deployment, although it handles them perfectly ok with next start
it's optimized for serverless
that's fine but can be a tad unsettling, don't be surprised if some decision looks weird
you can also use a custom server if you want
basically you can write a "normal" node server, with middlewares, initialize db calls there (I think) etc.
I think, didn't use it much either
American black bearOP
so, based on how next "should" work, i have to call my DB each time i need it ?
to be able to stay serverless?
@American black bear so, based on how next *"should"* work, i have to call my DB each time i need it ?
what I do is that I craft helpers that checks if the db is connected
and connect if not
like "const db = await getDb()"
and internally "getDb()" checks if there is a connected client and if not connects
this might sound weird but remember that's the price for inifinite scalability and flexibility
your "login" endpoint will scale faster than your "signup" endpoint and slower than your home
which is optimal
American black bearOP
hmmm, ok, i'll try this