Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/llms-txt-hub / apps/web/app/api/members/route.ts |
| Date | Not specified in source |
| Repository | Janady13/llms-txt-hub |
| Revision | e0f4bf978d4df168369c7601d9c5f5ea89e84377 |
| Branch | main |
| Path or archive member | apps/web/app/api/members/route.ts |
| Original SHA-256 | eda94ecebddbc1c9a708b9a299c3a701000c9a75635b40ff83b14d09ef5b29ca |
| Git blob SHA | c85dec9b15665ff8e484142652d2c392d49775ee |
| Reading-copy SHA-256 | eda94ecebddbc1c9a708b9a299c3a701000c9a75635b40ff83b14d09ef5b29ca |
Recovered source transcript
Download complete source text ↓86 lines · 2.8 KB
import { logger } from '@thedaviddias/logging'
import { withRateLimit } from '@thedaviddias/rate-limiting'
import { type NextRequest, NextResponse } from 'next/server'
import { getCachedMembers, type Member } from '@/lib/member-server-utils'
interface MembersResponse {
members: Member[]
pagination: {
page: number
limit: number
total: number
totalPages: number
hasMore: boolean
}
}
/**
* GET /api/members - Retrieves paginated list of community members
* Reads from the two-tier cache (unstable_cache + Redis) instead of Clerk directly.
*/
export async function GET(
request: NextRequest
): Promise<NextResponse<MembersResponse | { error: string }> | Response> {
return await withRateLimit(request, 'MEMBERS_API', async () => {
try {
const { searchParams } = new URL(request.url)
const page = Math.max(1, Number.parseInt(searchParams.get('page') || '1', 10) || 1)
const parsedLimit = Number.parseInt(searchParams.get('limit') || '20', 10)
const limit = Math.min(50, Math.max(1, Number.isNaN(parsedLimit) ? 20 : parsedLimit))
const search = searchParams.get('search')?.trim()
const allMembers = await getCachedMembers()
// Apply search filter if provided
let filteredMembers = allMembers
if (search) {
const query = search.toLowerCase()
filteredMembers = allMembers.filter(member => {
const displayName =
member.firstName && member.lastName
? `${member.firstName} ${member.lastName}`
: member.firstName || member.lastName || ''
const username = member.username || member.publicMetadata?.github_username || ''
return displayName.toLowerCase().includes(query) || username.toLowerCase().includes(query)
})
}
// Calculate pagination
const totalCount = filteredMembers.length
const totalPages = Math.ceil(totalCount / limit)
const offset = (page - 1) * limit
const members = filteredMembers.slice(offset, offset + limit)
const hasMore = page < totalPages
return NextResponse.json({
members,
pagination: {
page,
limit,
total: totalCount,
totalPages,
hasMore
}
})
} catch (error) {
const errorInfo: Record<string, unknown> =
error instanceof Error
? { message: error.message, name: error.name }
: { message: 'Unknown error occurred' }
if (error && typeof error === 'object') {
if ('status' in error && error.status) {
errorInfo.status = error.status
}
}
logger.error('Error fetching members:', {
data: errorInfo,
tags: { type: 'api' }
})
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 })
}
})
}