RequestContext
The RequestContext provides a way to pass data through the request lifecycle. It's available in loaders, actions, and middleware.
Import
ts
import {
createContext,
RequestContext,
getContext,
attachContext,
isRequestContext
} from '@ereo/core'createContext
Creates a new request context.
Signature
ts
function createContext(request: Request): RequestContextParameters
| Name | Type | Description |
|---|---|---|
request | Request | The incoming HTTP request |
Returns
Returns a RequestContext instance.
RequestContext Methods
get
Retrieves a value from the context.
ts
get<T>(key: string): T | undefinedts
const user = context.get<User>('user')set
Stores a value in the context.
ts
set<T>(key: string, value: T): voidts
context.set('user', { id: 1, name: 'Alice' })has
Checks if a key exists in the context.
ts
has(key: string): booleants
if (context.has('user')) {
// User is authenticated
}delete
Removes a value from the context.
ts
delete(key: string): booleants
context.delete('temporaryData')Properties
url
The parsed URL of the current request.
ts
url: URLts
// Access URL components
console.log(context.url.pathname) // '/users/123'
console.log(context.url.searchParams.get('sort')) // 'asc'env
Environment variables available in the current context.
ts
env: Record<string, string | undefined>ts
const dbUrl = context.env.DATABASE_URLcache
Access cache control for the current request.
ts
interface CacheControl {
set(options: CacheOptions): void
get(): CacheOptions | undefined
getTags(): string[]
addTags(tags: string[]): void
}
interface CacheOptions {
maxAge?: number
staleWhileRevalidate?: number
tags?: string[]
private?: boolean
}ts
// Set cache headers
context.cache.set({
maxAge: 3600,
staleWhileRevalidate: 600,
tags: ['posts', 'user:123']
})
// Get current cache settings
const cacheOptions = context.cache.get()
// Get all cache tags (accumulated from multiple set() calls)
const tags = context.cache.getTags()
// ['posts', 'user:123']
// Add additional tags dynamically (without resetting other cache options)
context.cache.addTags(['category:tech'])responseHeaders
Access response headers.
ts
responseHeaders: Headersts
context.responseHeaders.set('X-Custom-Header', 'value')
context.responseHeaders.append('Set-Cookie', 'session=abc123')Helper Functions
attachContext
Attaches a context to a request for later retrieval.
ts
function attachContext(request: Request, context: RequestContext): voidts
const context = createContext(request)
context.set('user', user)
attachContext(request, context)getContext
Retrieves the context attached to a request.
ts
function getContext(request: Request): RequestContext | undefinedts
const context = getContext(request)
if (context) {
const user = context.get('user')
}isRequestContext
Type guard for RequestContext.
ts
function isRequestContext(value: unknown): value is RequestContextts
if (isRequestContext(maybeContext)) {
const data = maybeContext.get('data')
}Examples
Using Context in Middleware
ts
// routes/_middleware.ts
export const middleware = async (request, context, next) => {
// Authenticate user
const token = request.headers.get('Authorization')?.replace('Bearer ', '')
if (token) {
const user = await verifyToken(token)
context.set('user', user)
}
return next()
}Accessing Context in Loaders
ts
// routes/dashboard.tsx
export const loader = createLoader(async ({ context }) => {
const user = context.get('user')
if (!user) {
throw new Response('Unauthorized', { status: 401 })
}
const dashboardData = await getDashboardData(user.id)
return { user, dashboardData }
})Setting Response Headers
ts
export const loader = createLoader(async ({ context }) => {
// Set custom headers
context.responseHeaders.set('X-Request-Id', crypto.randomUUID())
// Set cookies
context.responseHeaders.append('Set-Cookie', 'viewed=true; Path=/')
return { data: 'example' }
})Cache Control via Context
ts
export const loader = createLoader(async ({ params, context }) => {
const post = await db.posts.find(params.id)
// Dynamic cache based on content
if (post.isStatic) {
context.cache.set({
maxAge: 86400, // 24 hours
tags: ['posts', `post-${post.id}`]
})
} else {
context.cache.set({
maxAge: 60, // 1 minute
private: true
})
}
return { post }
})Passing Data Between Middleware
ts
// First middleware
const timingMiddleware = async (request, context, next) => {
const start = Date.now()
context.set('requestStart', start)
const response = await next()
const duration = Date.now() - start
response.headers.set('X-Response-Time', `${duration}ms`)
return response
}
// Second middleware
const loggingMiddleware = async (request, context, next) => {
const response = await next()
const start = context.get('requestStart')
console.log(`${request.method} ${request.url} - ${Date.now() - start}ms`)
return response
}cookies
Cookie jar for reading and writing cookies.
ts
cookies: CookieJarts
interface CookieJar {
get(name: string): string | undefined
getAll(): Record<string, string>
set(name: string, value: string, options?: CookieSetOptions): void
delete(name: string, options?: Pick<CookieSetOptions, 'path' | 'domain'>): void
has(name: string): boolean
}ts
// Read a cookie
const sessionId = context.cookies.get('session')
// Set a cookie
context.cookies.set('theme', 'dark', {
maxAge: 60 * 60 * 24 * 365, // 1 year
path: '/',
sameSite: 'Lax',
})
// Delete a cookie
context.cookies.delete('session')
// Check if a cookie exists
if (context.cookies.has('session')) {
// User has a session cookie
}Type Safety
Use TypeScript generics with context.get<T>() to type your context values:
ts
// In middleware
context.set('user', { id: '1', name: 'Alice' })
// In loader — provide the type explicitly
const user = context.get<{ id: string; name: string }>('user')