Skip to content

Commit 2b2773d

Browse files
committed
feat: Add RequestContext util for API routes
1 parent 14b0892 commit 2b2773d

File tree

5 files changed

+76
-15
lines changed

5 files changed

+76
-15
lines changed

apps/next/app/(main)/api/health/route.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
import { NextRequest, NextResponse } from 'next/server'
22
import { healthCheck } from '@app/core/resolvers/healthCheck'
3+
import { createRequestContext } from '@app/core/middleware/createRequestContext'
34

45
/* --- Types ----------------------------------------------------------------------------------- */
56

6-
type RequestContext<T = Record<string, unknown>> = {
7+
type NextRequestContext<T = Record<string, unknown>> = {
78
params: T
89
}
910

1011
/* --- Handlers -------------------------------------------------------------------------------- */
1112

12-
const handler = async (req: NextRequest, context: RequestContext) => {
13+
const handler = async (req: NextRequest, nextRequestContext: NextRequestContext) => {
1314
// Input
1415
const searchParams = req.nextUrl.searchParams
1516
const echo = searchParams.get('echo') || null
1617

18+
// Build Context
19+
const context = await createRequestContext({ req, ...nextRequestContext })
20+
1721
// Run Resolver
18-
const serverHealth = await healthCheck({ echo, req })
22+
const serverHealth = await healthCheck({ args: { echo }, context })
1923

2024
// Respond
2125
return NextResponse.json(serverHealth)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { NextRequest, NextResponse } from 'next/server'
2+
3+
/* --- Types ----------------------------------------------------------------------------------- */
4+
5+
export type RequestContext = {
6+
// -i- Next.js app API router request and response objects
7+
req: NextRequest,
8+
res: NextResponse,
9+
// -i- GraphQL context properties
10+
parent?: unknown,
11+
info?: unknown,
12+
// -i- Anything else you might want to attach as context through middleware, e.g.
13+
// user: ...
14+
// permissions: ...
15+
}
16+
17+
export type CreateRequestContextArgs = Partial<Omit<RequestContext, 'req' | 'res'>> & {
18+
req: NextRequest,
19+
res?: NextResponse,
20+
}
21+
22+
/** --- createRequestContext() ----------------------------------------------------------------- */
23+
/** -i- Server-only util for Next.js API routes and graphql to add more context to requests for resolvers to use */
24+
export const createRequestContext = async (baseContext: CreateRequestContextArgs): Promise<RequestContext> => {
25+
// Inputs
26+
const { req, res = new NextResponse(), ...restContext } = baseContext
27+
28+
// -- Custom context retrieval --
29+
30+
// TODO: Add custom context retrieval here
31+
// e.g. Parse header info
32+
// e.g. Verify JWT / user session
33+
34+
// -- Return --
35+
36+
return {
37+
// -i- Next.js app API router request and response objects
38+
req,
39+
res,
40+
// -i- GraphQL context properties?
41+
...restContext,
42+
// -i- Anything else you might want to attach as context through middleware, e.g.
43+
// user: ...
44+
// permissions: ...
45+
}
46+
}

features/app-core/resolvers/healthCheck.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import type { NextApiRequest } from 'next'
21
import * as OS from 'os'
2+
import type { NextRequest } from 'next/server'
3+
import type { RequestContext } from '../middleware/createRequestContext'
34

45
/* --- Constants ------------------------------------------------------------------------------- */
56

@@ -9,25 +10,30 @@ const ALIVE_SINCE = new Date()
910

1011
type HealthCheckArgs = {
1112
echo: string
12-
req: Request | NextApiRequest
13+
}
14+
15+
type HealthCheckInputs = {
16+
args: HealthCheckArgs,
17+
context: RequestContext
1318
}
1419

1520
/** --- healthCheck() -------------------------------------------------------------------------- */
1621
/** -i- Check the health status of the server. Includes relevant urls, server time(zone), versions and more */
17-
export const healthCheck = async (args: HealthCheckArgs) => {
18-
// Input
19-
const { echo, req } = args
22+
export const healthCheck = async ({ args, context }: HealthCheckInputs) => {
23+
// Inputs
24+
const { echo } = args
25+
const { req } = context
2026

2127
// Vars
2228
const now = new Date()
2329
const aliveTime = now.getTime() - ALIVE_SINCE.getTime()
2430

2531
// Urls
2632
const r = req as Request
27-
const rn = req as NextApiRequest
28-
const reqHost = rn?.headers?.host
29-
const reqProtocol = rn?.headers?.['x-forwarded-proto'] ?? 'http'
30-
const requestURL = r?.url ?? `${reqProtocol}://${reqHost}/api/health`
33+
const rn = req as NextRequest
34+
const requestHost = rn?.headers?.get?.('host')
35+
const requestProtocol = rn?.headers?.get?.['x-forwarded-proto'] ?? 'http'
36+
const requestURL = r?.url ?? `${requestProtocol}://${requestHost}/api/health`
3137
const baseURL = process.env.BACKEND_URL || requestURL?.split('/api/')[0]
3238
const apiURL = baseURL ? `${baseURL}/api` : null
3339

@@ -46,6 +52,8 @@ export const healthCheck = async (args: HealthCheckArgs) => {
4652
aliveSince: ALIVE_SINCE.toISOString(),
4753
serverTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
4854
// URLS
55+
requestHost,
56+
requestProtocol,
4957
requestURL,
5058
baseURL,
5159
apiURL,

features/app-core/screens/SlugScreen.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react'
22
import { StyleSheet, Text, View } from 'react-native'
3-
import { useRouteParams } from '@app/core/navigation/useRouteParams'
3+
import { useRouteParams } from '../navigation/useRouteParams'
44
import { Link } from '../navigation/Link'
55
import { useRouter } from '../navigation/useRouter'
66

features/app-core/tsconfig.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@
2020
"include": [
2121
"next-env.d.ts",
2222
"**/*.ts",
23-
"**/*.tsx"
24-
, "../../apps/expo/app/ExpoRootLayout.tsx", "../../apps/next/app/NextRootLayout.tsx../../apps/next/app/ServerStylesProvider.tsx.tsx" ],
23+
"**/*.tsx",
24+
"../../apps/expo/app/ExpoRootLayout.tsx",
25+
"../../apps/next/app/NextRootLayout.tsx",
26+
"../../apps/next/app/ServerStylesProvider.tsx.tsx",
27+
],
2528
"exclude": [
2629
"node_modules"
2730
],

0 commit comments

Comments
 (0)