feat(api): add endpoint for team table data by season
This commit is contained in:
137
server/api/spielplan/table.get.js
Normal file
137
server/api/spielplan/table.get.js
Normal file
@@ -0,0 +1,137 @@
|
||||
import { promises as fs } from 'fs'
|
||||
import path from 'path'
|
||||
import { getCurrentSeasonSlug, validateSeasonSlug } from '../../utils/spielplan-data.js'
|
||||
import { getServerDataPath } from '../../utils/paths.js'
|
||||
import { error as loggerError } from '../../utils/logger.js'
|
||||
|
||||
const TABLES_FILE_PATTERN = /^tables_(\d{2}--\d{2})\.json$/
|
||||
|
||||
function normalizeTeamName(value) {
|
||||
return String(value || '').trim().toLowerCase().replace(/\s+/g, ' ')
|
||||
}
|
||||
|
||||
async function listTableSeasons() {
|
||||
const importDir = getServerDataPath('spielplan-import')
|
||||
|
||||
try {
|
||||
const files = await fs.readdir(importDir)
|
||||
return files
|
||||
.map((file) => {
|
||||
const match = file.match(TABLES_FILE_PATTERN)
|
||||
return match ? match[1] : null
|
||||
})
|
||||
.filter(Boolean)
|
||||
.sort()
|
||||
.reverse()
|
||||
} catch (error) {
|
||||
if (error?.code !== 'ENOENT') {
|
||||
loggerError('Fehler beim Lesen der Tabellen-Saisons', { error })
|
||||
}
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
async function readTablesBySeason(season) {
|
||||
const filePath = getServerDataPath('spielplan-import', `tables_${season}.json`)
|
||||
const content = await fs.readFile(filePath, 'utf8')
|
||||
const parsed = JSON.parse(content)
|
||||
return { filePath, parsed }
|
||||
}
|
||||
|
||||
function findTeamTable(tables, teamQuery) {
|
||||
const normalizedQuery = normalizeTeamName(teamQuery)
|
||||
|
||||
const exact = tables.find((entry) => normalizeTeamName(entry?.teamName) === normalizedQuery)
|
||||
if (exact) return exact
|
||||
|
||||
return tables.find((entry) => normalizeTeamName(entry?.teamName).includes(normalizedQuery)) || null
|
||||
}
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
try {
|
||||
const query = getQuery(event)
|
||||
const team = String(query.team || query.mannschaft || '').trim()
|
||||
|
||||
if (!team) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Query-Parameter team (oder mannschaft) fehlt',
|
||||
team: null,
|
||||
table: null
|
||||
}
|
||||
}
|
||||
|
||||
const requestedSeason = query.season ? String(query.season).trim() : null
|
||||
if (requestedSeason && !validateSeasonSlug(requestedSeason)) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Ungueltiger Saison-Slug',
|
||||
team,
|
||||
table: null,
|
||||
season: requestedSeason
|
||||
}
|
||||
}
|
||||
|
||||
const availableSeasons = await listTableSeasons()
|
||||
const defaultSeason = getCurrentSeasonSlug()
|
||||
const season = requestedSeason || defaultSeason
|
||||
|
||||
let loaded = null
|
||||
try {
|
||||
loaded = await readTablesBySeason(season)
|
||||
} catch (error) {
|
||||
if (error?.code === 'ENOENT' && !requestedSeason && availableSeasons.length > 0) {
|
||||
loaded = await readTablesBySeason(availableSeasons[0])
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
if (!loaded) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Keine Tabellen-Daten gefunden',
|
||||
team,
|
||||
table: null,
|
||||
season,
|
||||
availableSeasons
|
||||
}
|
||||
}
|
||||
|
||||
const payload = loaded.parsed || {}
|
||||
const tables = Array.isArray(payload.tables) ? payload.tables : []
|
||||
const found = findTeamTable(tables, team)
|
||||
const effectiveSeason = payload?.source?.season?.seasonSlug || season
|
||||
|
||||
if (!found) {
|
||||
return {
|
||||
success: false,
|
||||
message: 'Keine Tabellen-Daten fuer die Mannschaft gefunden',
|
||||
team,
|
||||
table: null,
|
||||
season: effectiveSeason,
|
||||
filePath: loaded.filePath,
|
||||
availableTeams: tables.map((entry) => entry?.teamName).filter(Boolean)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Tabellen-Daten erfolgreich geladen',
|
||||
team,
|
||||
table: found,
|
||||
season: effectiveSeason,
|
||||
filePath: loaded.filePath,
|
||||
importedAt: payload.importedAt || null,
|
||||
availableSeasons
|
||||
}
|
||||
} catch (error) {
|
||||
loggerError('Fehler beim Laden der Tabellen-Daten:', { error })
|
||||
return {
|
||||
success: false,
|
||||
message: 'Fehler beim Laden der Tabellen-Daten',
|
||||
team: null,
|
||||
table: null
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user