diff --git a/src/handlers/kboHandlers.ts b/src/handlers/kboHandlers.ts index 68a06c8..6cf2309 100644 --- a/src/handlers/kboHandlers.ts +++ b/src/handlers/kboHandlers.ts @@ -4,7 +4,7 @@ import { getSchedule } from "../services/scheduleService.js"; import { getPlayerStats, getValidPlayerTypes } from "../services/playerService.js"; import { getGameList } from "../services/gameListService.js"; import { getGameDetail } from "../services/gameDetailService.js"; -import type { PlayerFilters } from "../types/kbo.js"; +import { TeamCode } from "../types/panit.js"; enum KboPath { Rank = "rank", @@ -59,7 +59,6 @@ export const kbo = onRequest(async (req, res) => { const now = new Date(); const year = parseIntParam(req.query.year, now.getFullYear()); const month = parseIntParam(req.query.month, now.getMonth() + 1); - const team = req.query.team ? String(req.query.team) : undefined; const series = req.query.series ? String(req.query.series) : undefined; const day = req.query.day !== undefined ? parseIntParam(req.query.day, NaN) @@ -78,6 +77,19 @@ export const kbo = onRequest(async (req, res) => { return; } + let team: TeamCode | undefined; + if (req.query.team) { + const raw = String(req.query.team); + const validCodes = Object.values(TeamCode) as string[]; + if (!validCodes.includes(raw)) { + res.status(400).json({ + error: `Invalid team: "${raw}". Use: ${validCodes.join(", ")}`, + }); + return; + } + team = raw as TeamCode; + } + const result = await getSchedule(year, month, team, series, day); res.status(200).json(result); return; @@ -141,16 +153,30 @@ export const kbo = onRequest(async (req, res) => { return; } - const filters: PlayerFilters = {}; - if (req.query.team) filters.team = String(req.query.team); - if (req.query.series) filters.series = String(req.query.series); - if (req.query.pos) filters.pos = String(req.query.pos); - if (req.query.situation) filters.situation = String(req.query.situation); - if (req.query.situationDetail) { - filters.situationDetail = String(req.query.situationDetail); + let team: TeamCode | undefined; + if (req.query.team) { + const raw = String(req.query.team); + const validCodes = Object.values(TeamCode) as string[]; + if (!validCodes.includes(raw)) { + res.status(400).json({ + error: `Invalid team: "${raw}". Use: ${validCodes.join(", ")}`, + }); + return; + } + team = raw as TeamCode; } - const result = await getPlayerStats(type, year, filters, allPages); + const result = await getPlayerStats({ + type, + year, + team, + series: req.query.series ? String(req.query.series) : undefined, + pos: req.query.pos ? String(req.query.pos) : undefined, + situation: req.query.situation ? String(req.query.situation) : undefined, + situationDetail: req.query.situationDetail ? + String(req.query.situationDetail) : undefined, + allPages, + }); res.status(200).json(result); return; } diff --git a/src/kbo/player/common.ts b/src/kbo/player/common.ts index 0b7e431..c3037a1 100644 --- a/src/kbo/player/common.ts +++ b/src/kbo/player/common.ts @@ -82,10 +82,24 @@ export interface PlayerStatsResult { } /** - * KBO 팀 코드 매핑. + * 팀 표기명(shortName/한글) → KBO 사이트 코드 매핑. * * KBO 사이트의 팀 드롭다운은 현재 팀명이 아닌 구단 역사상의 코드를 value로 사용한다. * 예: SSG는 SK 시절 코드 "SK", 키움은 우리 히어로즈 시절 코드 "WO" 등. + * + * ## 존재 이유 + * 외부 API의 `team` 파라미터는 `TeamCode` enum으로 받기 때문에 요청 단계에서는 + * 더 이상 매핑이 필요 없다 (TeamCode 값이 곧 KBO 사이트 코드와 동일). + * + * 그럼에도 이 맵이 필요한 곳: + * 1. 응답 파싱 — `kbo/schedule.ts`의 `toTeamCode()`가 스크래핑된 HTML 속 + * 한국어 팀명("두산", "한화" 등)을 응답의 `awayTeamCode`/`homeTeamCode` + * 필드용 코드로 정규화할 때 사용한다. + * 2. CLI 입력 편의 — `kbo/cli.ts`에서 사람이 직접 입력하는 한글/shortName을 + * KBO 코드로 변환할 때 사용한다. + * + * 즉 이 맵은 "사람이 읽는 표기 → KBO 내부 코드" 어댑터이며, + * 서비스 레이어의 외부 API 매개변수에는 더 이상 사용하지 않는다. */ export const TEAM_CODES: Record = { KT: "KT", diff --git a/src/services/playerService.ts b/src/services/playerService.ts index 8136b45..b1fb756 100644 --- a/src/services/playerService.ts +++ b/src/services/playerService.ts @@ -1,6 +1,6 @@ import { fetchPlayerFromKbo } from "../repositories/kboRepository.js"; -import { TEAM_CODES } from "../types/kbo.js"; import type { PlayerFilters, PlayerPageConfig, PlayerStatsResult } from "../types/kbo.js"; +import { TeamCode } from "../types/panit.js"; import { HITTER_CONFIG } from "../kbo/player/hitter.js"; import { PITCHER_CONFIG } from "../kbo/player/pitcher.js"; import { DEFENSE_CONFIG } from "../kbo/player/defense.js"; @@ -21,12 +21,22 @@ export function getValidPlayerTypes(): string[] { return Object.keys(PLAYER_CONFIGS); } +export interface GetPlayerStatsArgs { + type: string; + year: number; + team?: TeamCode; + series?: string; + pos?: string; + situation?: string; + situationDetail?: string; + allPages: boolean; +} + export async function getPlayerStats( - type: string, - year: number, - filters: PlayerFilters, - allPages: boolean + args: GetPlayerStatsArgs ): Promise { + const { type, year, team, series, pos, situation, situationDetail, allPages } = args; + const config = PLAYER_CONFIGS[type]; if (!config) { throw new Error( @@ -34,10 +44,12 @@ export async function getPlayerStats( ); } - const resolvedFilters = { ...filters }; - if (resolvedFilters.team) { - resolvedFilters.team = TEAM_CODES[resolvedFilters.team] ?? resolvedFilters.team; - } + const filters: PlayerFilters = {}; + if (team) filters.team = team; + if (series) filters.series = series; + if (pos) filters.pos = pos; + if (situation) filters.situation = situation; + if (situationDetail) filters.situationDetail = situationDetail; - return fetchPlayerFromKbo(type, config, year, resolvedFilters, allPages); -} + return fetchPlayerFromKbo(type, config, year, filters, allPages); +} \ No newline at end of file diff --git a/src/services/scheduleService.ts b/src/services/scheduleService.ts index b9b19cb..dbf124a 100644 --- a/src/services/scheduleService.ts +++ b/src/services/scheduleService.ts @@ -1,15 +1,15 @@ import { fetchScheduleFromKbo } from "../repositories/kboRepository.js"; -import { TEAM_CODES, SERIES_CODES } from "../types/kbo.js"; +import { SERIES_CODES } from "../types/kbo.js"; import type { ScheduleResult } from "../types/kbo.js"; +import type { TeamCode } from "../types/panit.js"; export async function getSchedule( year: number, month: number, - team?: string, + team?: TeamCode, series?: string, day?: number ): Promise { - const resolvedTeam = team ? (TEAM_CODES[team] ?? team) : undefined; const resolvedSeries = series ? (SERIES_CODES[series] ?? series) : undefined; return fetchScheduleFromKbo({ @@ -17,6 +17,6 @@ export async function getSchedule( month, day, series: resolvedSeries, - team: resolvedTeam, + team, }); -} +} \ No newline at end of file diff --git a/src/types/kbo.ts b/src/types/kbo.ts index 26f9287..11f46fd 100644 --- a/src/types/kbo.ts +++ b/src/types/kbo.ts @@ -22,7 +22,6 @@ export type { PlayerStatsResult, } from "../kbo/player/common.js"; -export { TEAM_CODES } from "../kbo/player/common.js"; export { SERIES_CODES } from "../kbo/schedule.js"; export type {