import fp from 'fastify-plugin' import { FastifyPluginAsync, FastifyRequest } from 'fastify' export interface QueryConfigPagination { page: number limit: number offset: number } export interface QueryConfigSort { field: string direction: 'asc' | 'desc' } export interface QueryConfig { pagination: QueryConfigPagination | null sort: QueryConfigSort[] filters: Record paginationDisabled: boolean } declare module 'fastify' { interface FastifyRequest { queryConfig: QueryConfig } } interface QueryConfigPluginOptions { routes?: string[] } function matchRoutePattern(currentPath: string, patterns: string[]): boolean { return patterns.some(pattern => { // Beispiel: /users/:id -> /^\/users\/[^/]+$/ const regex = new RegExp( '^' + pattern .replace(/\*/g, '.*') // wildcard .replace(/:[^/]+/g, '[^/]+') + '$' ) return regex.test(currentPath) }) } const queryConfigPlugin: FastifyPluginAsync = async ( fastify, opts ) => { const routePatterns = opts.routes || [] fastify.addHook('preHandler', async (req: FastifyRequest, reply) => { const path = req.routeOptions.url || req.raw.url || '' if (!matchRoutePattern(path, routePatterns)) { return } const query = req.query as Record console.log(query) // Pagination deaktivieren? const disablePagination = query.noPagination === 'true' || query.pagination === 'false' || query.limit === '0' // Pagination berechnen let pagination: QueryConfigPagination | null = null if (!disablePagination) { const page = Math.max(parseInt(query.page) || 1, 1) const limit = Math.max(parseInt(query.limit) || 25, 1) const offset = (page - 1) * limit pagination = { page, limit, offset } } // Sortierung const sort: QueryConfigSort[] = [] if (typeof query.sort === 'string') { const items = query.sort.split(',') for (const item of items) { const [field, direction] = item.split(':') sort.push({ field: field.trim(), direction: (direction || 'asc').toLowerCase() === 'desc' ? 'desc' : 'asc' }) } } // Filterung const filters: Record = {} for (const [key, value] of Object.entries(query)) { const match = key.match(/^filter\[(.+)\]$/) if (!match) continue const filterKey = match[1] if (typeof value === 'string') { // Split bei Komma → mehrere Werte const parts = value.split(',').map(v => v.trim()).filter(Boolean) // Automatische Typkonvertierung je Element const parsedValues = parts.map(v => { if (v === 'true') return true if (v === 'false') return false if (v === 'null') return null return v }) filters[filterKey] = parsedValues.length > 1 ? parsedValues : parsedValues[0] } } req.queryConfig = { pagination, sort, filters, paginationDisabled: disablePagination } }) } export default fp(queryConfigPlugin, { name: 'query-config' })