Files
analiticaNucleo/nuxt4-app/server/services/query-parser.ts

54 lines
1.5 KiB
TypeScript

import type { ParsedQuery, QueryFilter } from '../data-sources/types'
function isValidFilter(filter: Partial<QueryFilter>): filter is QueryFilter {
return typeof filter.field === 'string' && filter.field.length > 0 && filter.value !== undefined
}
function decodeBase64Url(value: string) {
const normalized = value.replace(/-/g, '+').replace(/_/g, '/')
const paddingNeeded = (4 - (normalized.length % 4)) % 4
const padded = normalized + '='.repeat(paddingNeeded)
return Buffer.from(padded, 'base64').toString('utf-8')
}
export function parseQuerySegment(segment?: string | string[]): ParsedQuery | null {
if (!segment) {
return null
}
const value = Array.isArray(segment) ? segment[0] : segment
try {
const decoded = decodeBase64Url(value)
const parsed = JSON.parse(decoded)
const result: ParsedQuery = {
filters: []
}
if (Array.isArray(parsed.filters)) {
result.filters = parsed.filters.filter(isValidFilter)
}
if (parsed.limit && Number.isInteger(parsed.limit) && parsed.limit > 0) {
result.limit = Math.min(parsed.limit, 500)
}
if (parsed.offset && Number.isInteger(parsed.offset) && parsed.offset >= 0) {
result.offset = parsed.offset
}
if (parsed.orderBy && typeof parsed.orderBy.field === 'string') {
result.orderBy = {
field: parsed.orderBy.field,
ascending: parsed.orderBy.ascending !== false
}
}
return result
} catch (error) {
console.warn('Failed to parse query segment', error)
return null
}
}