Added Backend
This commit is contained in:
125
backend/src/plugins/queryconfig.ts
Normal file
125
backend/src/plugins/queryconfig.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
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<string, string>
|
||||
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<QueryConfigPluginOptions> = 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<string, any>
|
||||
|
||||
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<string, any> = {}
|
||||
|
||||
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' })
|
||||
Reference in New Issue
Block a user