Files
harheimertc/server/api/spielplan/table.get.js
Torsten Schulz (local) bf4db389ff
Some checks failed
Code Analysis and Production Deploy / analyze (push) Failing after 2m39s
Code Analysis and Production Deploy / deploy-production (push) Has been skipped
Code Analysis and Production Deploy / deploy-test (push) Has been skipped
feat(api): add endpoint for team table data by season
2026-05-20 17:38:17 +02:00

137 lines
3.8 KiB
JavaScript

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
}
}
})