Remove redundant .js extensions from import paths.
- TypeScript 소스 파일 내 모든 import 구문에서 불필요한 `.js` 확장자를 제거하여 모듈 참조 방식을 표준화했습니다. - 핸들러, 서비스, 리포지토리 및 테스트 코드를 포함한 프로젝트 전반의 import 경로를 일관성 있게 정리했습니다.
This commit is contained in:
parent
7496cb7de7
commit
c94ce69e4f
@ -1,4 +1,4 @@
|
||||
import type { DailyJudgment } from "../types/panit.js";
|
||||
import type { DailyJudgment } from "../types/panit";
|
||||
|
||||
export interface Thresholds {
|
||||
success: number;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { TierName } from "../types/panit.js";
|
||||
import type { TierName } from "../types/panit";
|
||||
|
||||
interface TierStep {
|
||||
name: TierName;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { onRequest } from "firebase-functions/https";
|
||||
import { requireAdmin } from "../middleware/admin.js";
|
||||
import { sendError } from "../middleware/errors.js";
|
||||
import { markGameEnded } from "../services/gameResultService.js";
|
||||
import { requireAdmin } from "../middleware/admin";
|
||||
import { sendError } from "../middleware/errors";
|
||||
import { markGameEnded } from "../services/gameResultService";
|
||||
|
||||
export const admin = onRequest(async (req, res) => {
|
||||
const segs = req.path.replace(/^\/+|\/+$/g, "").split("/");
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { onRequest } from "firebase-functions/https";
|
||||
import { logger } from "firebase-functions";
|
||||
import { runDailyArchive } from "../scheduled/dailyArchive.js";
|
||||
import { syncYesterdayFromLive } from "../services/gameSyncService.js";
|
||||
import { sendError } from "../middleware/errors.js";
|
||||
import { daysAgoKst, parseDateString } from "../types/dateString.js";
|
||||
import { runDailyArchive } from "../scheduled/dailyArchive";
|
||||
import { syncYesterdayFromLive } from "../services/gameSyncService";
|
||||
import { sendError } from "../middleware/errors";
|
||||
import { daysAgoKst, parseDateString } from "../types/dateString";
|
||||
|
||||
/**
|
||||
* 임시 디버그 핸들러. 인증 없음 — 운영 안정화 후 제거할 것.
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { onRequest } from "firebase-functions/https";
|
||||
import { getRank } from "../services/rankService.js";
|
||||
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 { TeamCode } from "../types/panit.js";
|
||||
import { getRank } from "../services/rankService";
|
||||
import { getSchedule } from "../services/scheduleService";
|
||||
import { getPlayerStats, getValidPlayerTypes } from "../services/playerService";
|
||||
import { getGameList } from "../services/gameListService";
|
||||
import { getGameDetail } from "../services/gameDetailService";
|
||||
import { TeamCode } from "../types/panit";
|
||||
|
||||
enum KboPath {
|
||||
Rank = "rank",
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
import { onRequest } from "firebase-functions/https";
|
||||
import { requireAuth } from "../middleware/auth.js";
|
||||
import { HttpError, sendError } from "../middleware/errors.js";
|
||||
import { requireAuth } from "../middleware/auth";
|
||||
import { HttpError, sendError } from "../middleware/errors";
|
||||
import {
|
||||
createPrediction,
|
||||
updatePrediction,
|
||||
getMyVotes,
|
||||
getSummary,
|
||||
listGamesByDate,
|
||||
} from "../services/predictionService.js";
|
||||
import { getScoreboard } from "../services/scoreboardService.js";
|
||||
} from "../services/predictionService";
|
||||
import { getScoreboard } from "../services/scoreboardService";
|
||||
|
||||
export const prediction = onRequest(async (req, res) => {
|
||||
const segs = req.path.replace(/^\/+|\/+$/g, "").split("/");
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { onRequest } from "firebase-functions/https";
|
||||
import { requireAuth } from "../middleware/auth.js";
|
||||
import { sendError } from "../middleware/errors.js";
|
||||
import { getStats, getHistory } from "../services/statsService.js";
|
||||
import { requireAuth } from "../middleware/auth";
|
||||
import { sendError } from "../middleware/errors";
|
||||
import { getStats, getHistory } from "../services/statsService";
|
||||
|
||||
export const stats = onRequest(async (req, res) => {
|
||||
const segs = req.path.replace(/^\/+|\/+$/g, "").split("/");
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { onRequest } from "firebase-functions/https";
|
||||
import { requireAuthToken } from "../middleware/auth.js";
|
||||
import { sendError } from "../middleware/errors.js";
|
||||
import { requireAuthToken } from "../middleware/auth";
|
||||
import { sendError } from "../middleware/errors";
|
||||
import {
|
||||
checkNickname,
|
||||
createMe,
|
||||
deleteMe,
|
||||
getMe,
|
||||
updateMe,
|
||||
} from "../services/userService.js";
|
||||
} from "../services/userService";
|
||||
|
||||
export const user = onRequest(async (req, res) => {
|
||||
try {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { extractHiddenField } from "./html-utils.js";
|
||||
import { extractHiddenField } from "./html-utils";
|
||||
|
||||
export const PREFIX =
|
||||
"ctl00$ctl00$ctl00$cphContents$cphContents$cphContents$";
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
* --series=값 시리즈 필터 (schedule: 정규/시범/포스트)
|
||||
*/
|
||||
|
||||
import { padCell } from "./html-utils.js";
|
||||
import { padCell } from "./html-utils";
|
||||
import {
|
||||
fetchTeamRankInitial,
|
||||
fetchTeamRank,
|
||||
@ -22,7 +22,7 @@ import {
|
||||
type TeamVsRecord,
|
||||
type TeamRankResult,
|
||||
type WinLossDraw,
|
||||
} from "./team-rank.js";
|
||||
} from "./team-rank";
|
||||
import {
|
||||
fetchPlayerStatsInitial,
|
||||
fetchPlayerStats,
|
||||
@ -31,25 +31,25 @@ import {
|
||||
type PlayerPageConfig,
|
||||
type PlayerFilters,
|
||||
type PlayerStatsResult,
|
||||
} from "./player/common.js";
|
||||
import { HITTER_CONFIG } from "./player/hitter.js";
|
||||
import { PITCHER_CONFIG } from "./player/pitcher.js";
|
||||
import { DEFENSE_CONFIG } from "./player/defense.js";
|
||||
import { RUNNER_CONFIG } from "./player/runner.js";
|
||||
} from "./player/common";
|
||||
import { HITTER_CONFIG } from "./player/hitter";
|
||||
import { PITCHER_CONFIG } from "./player/pitcher";
|
||||
import { DEFENSE_CONFIG } from "./player/defense";
|
||||
import { RUNNER_CONFIG } from "./player/runner";
|
||||
import {
|
||||
fetchSchedule,
|
||||
SERIES_CODES,
|
||||
type ScheduleGame,
|
||||
type ScheduleResult,
|
||||
} from "./schedule.js";
|
||||
} from "./schedule";
|
||||
import {
|
||||
fetchGameList,
|
||||
LEAGUE_CODES,
|
||||
LeagueCode,
|
||||
type GameListRecord,
|
||||
type GameListResult,
|
||||
} from "./game-list.js";
|
||||
import { fetchGameDetail, type GameDetail } from "./game-detail.js";
|
||||
} from "./game-list";
|
||||
import { fetchGameDetail, type GameDetail } from "./game-detail";
|
||||
|
||||
const PLAYER_CONFIGS: Record<string, PlayerPageConfig> = {
|
||||
hitter: HITTER_CONFIG,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { stripTags, decodeHtmlEntities } from "./html-utils.js";
|
||||
import { LeagueCode, LEAGUE_CODES } from "./game-list.js";
|
||||
import { SERIES_ID } from "./schedule.js";
|
||||
import { fetchScoringPlays, type GameScoringPlays } from "./play-by-play.js";
|
||||
import { stripTags, decodeHtmlEntities } from "./html-utils";
|
||||
import { LeagueCode, LEAGUE_CODES } from "./game-list";
|
||||
import { SERIES_ID } from "./schedule";
|
||||
import { fetchScoringPlays, type GameScoringPlays } from "./play-by-play";
|
||||
|
||||
const BASE_URL = "https://www.koreabaseball.com/ws/Schedule.asmx";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { SERIES_CODES } from "./schedule.js";
|
||||
import { SERIES_CODES } from "./schedule";
|
||||
|
||||
export { SERIES_CODES };
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { stripTags, decodeHtmlEntities } from "../html-utils.js";
|
||||
import { stripTags, decodeHtmlEntities } from "../html-utils";
|
||||
import {
|
||||
PREFIX,
|
||||
postback,
|
||||
getInitialPageState,
|
||||
type PageState,
|
||||
type PostbackResponse,
|
||||
} from "../aspnet-client.js";
|
||||
} from "../aspnet-client";
|
||||
|
||||
const SM_KEY = `${PREFIX}smData`;
|
||||
const UPDATE_PANEL = `${PREFIX}udpContent`;
|
||||
@ -39,7 +39,7 @@ export interface PlayerPageConfig {
|
||||
* 구체적인 컬럼 타입이 필요하면 각 페이지 모듈의 타입으로 캐스팅한다.
|
||||
*
|
||||
* @example
|
||||
* import type { HitterStats } from "./hitter.js";
|
||||
* import type { HitterStats } from "./hitter";
|
||||
* const hitter = record as HitterStats;
|
||||
* console.log(hitter.avg, hitter.hr);
|
||||
*/
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { PlayerPageConfig, PlayerValue } from "./common.js";
|
||||
import type { PlayerPageConfig, PlayerValue } from "./common";
|
||||
|
||||
export const DEFENSE_COLUMNS = [
|
||||
"rank", "player", "team", "pos", "games", "gs", "ip",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { PlayerPageConfig, PlayerValue } from "./common.js";
|
||||
import type { PlayerPageConfig, PlayerValue } from "./common";
|
||||
|
||||
export const HITTER_COLUMNS = [
|
||||
"rank", "player", "team", "avg", "games", "pa", "ab",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { PlayerPageConfig, PlayerValue } from "./common.js";
|
||||
import type { PlayerPageConfig, PlayerValue } from "./common";
|
||||
|
||||
export const PITCHER_COLUMNS = [
|
||||
"rank", "player", "team", "era", "games", "wins", "losses",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { PlayerPageConfig, PlayerValue } from "./common.js";
|
||||
import type { PlayerPageConfig, PlayerValue } from "./common";
|
||||
|
||||
export const RUNNER_COLUMNS = [
|
||||
"rank", "player", "team", "games", "sba", "sb", "cs",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { stripTags, decodeHtmlEntities } from "./html-utils.js";
|
||||
import { TEAM_CODES } from "./player/common.js";
|
||||
import { fetchGameList, type PersonRef } from "./game-list.js";
|
||||
import { stripTags, decodeHtmlEntities } from "./html-utils";
|
||||
import { TEAM_CODES } from "./player/common";
|
||||
import { fetchGameList, type PersonRef } from "./game-list";
|
||||
|
||||
function toTeamCode(name: string): string {
|
||||
return TEAM_CODES[name] ?? name;
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { stripTags, decodeHtmlEntities } from "./html-utils.js";
|
||||
import { stripTags, decodeHtmlEntities } from "./html-utils";
|
||||
import {
|
||||
PREFIX,
|
||||
postback,
|
||||
getInitialPageState,
|
||||
type PageState,
|
||||
type PostbackResponse,
|
||||
} from "./aspnet-client.js";
|
||||
} from "./aspnet-client";
|
||||
|
||||
const PAGE_URL =
|
||||
"https://www.koreabaseball.com/Record/TeamRank/TeamRank.aspx";
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { Request } from "firebase-functions/https";
|
||||
import { auth } from "../firebase.js";
|
||||
import { HttpError } from "./errors.js";
|
||||
import { auth } from "../firebase";
|
||||
import { HttpError } from "./errors";
|
||||
|
||||
export async function requireAdmin(req: Request): Promise<string> {
|
||||
const header = req.get("authorization") ?? req.get("Authorization");
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { Request } from "firebase-functions/https";
|
||||
import type { DecodedIdToken } from "firebase-admin/auth";
|
||||
import { auth } from "../firebase.js";
|
||||
import { HttpError } from "./errors.js";
|
||||
import { auth } from "../firebase";
|
||||
import { HttpError } from "./errors";
|
||||
|
||||
export async function requireAuthToken(req: Request): Promise<DecodedIdToken> {
|
||||
const header = req.get("authorization") ?? req.get("Authorization");
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Timestamp } from "firebase-admin/firestore";
|
||||
import { firestore } from "../firebase.js";
|
||||
import type { Game } from "../types/panit.js";
|
||||
import { startOfDayKst, type DateString } from "../types/dateString.js";
|
||||
import { firestore } from "../firebase";
|
||||
import type { Game } from "../types/panit";
|
||||
import { startOfDayKst, type DateString } from "../types/dateString";
|
||||
|
||||
const COLLECTION = "games";
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { FieldValue } from "firebase-admin/firestore";
|
||||
import { firestore } from "../firebase.js";
|
||||
import { firestore } from "../firebase";
|
||||
|
||||
const CACHE_COLLECTION = "kboCache";
|
||||
const LOCK_COLLECTION = "kboLocks";
|
||||
|
||||
@ -2,14 +2,14 @@ import {
|
||||
fetchTeamRankInitial,
|
||||
fetchTeamRank,
|
||||
type TeamRankResult,
|
||||
} from "../kbo/team-rank.js";
|
||||
} from "../kbo/team-rank";
|
||||
import {
|
||||
fetchSchedule,
|
||||
type ScheduleFilters,
|
||||
type ScheduleResult,
|
||||
type ScheduleGame,
|
||||
type GameStatus,
|
||||
} from "../kbo/schedule.js";
|
||||
} from "../kbo/schedule";
|
||||
import {
|
||||
fetchPlayerStatsInitial,
|
||||
fetchPlayerStats,
|
||||
@ -17,17 +17,17 @@ import {
|
||||
type PlayerPageConfig,
|
||||
type PlayerFilters,
|
||||
type PlayerStatsResult,
|
||||
} from "../kbo/player/common.js";
|
||||
} from "../kbo/player/common";
|
||||
import {
|
||||
encodeKey,
|
||||
getOrFetch,
|
||||
setCached,
|
||||
acquireLock,
|
||||
releaseLock,
|
||||
} from "./kboCacheRepository.js";
|
||||
import { firestore } from "../firebase.js";
|
||||
import { getGameList } from "../services/gameListService.js";
|
||||
import type { GameListRecord } from "../kbo/game-list.js";
|
||||
} from "./kboCacheRepository";
|
||||
import { firestore } from "../firebase";
|
||||
import { getGameList } from "../services/gameListService";
|
||||
import type { GameListRecord } from "../kbo/game-list";
|
||||
|
||||
const TTL_MS = 60 * 60 * 1000; // 1 hour
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { rtdb } from "../firebase.js";
|
||||
import { HttpError } from "../middleware/errors.js";
|
||||
import { rtdb } from "../firebase";
|
||||
import { HttpError } from "../middleware/errors";
|
||||
|
||||
export const RESERVATION_TTL_MS = 10 * 60 * 1000;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { rtdb } from "../firebase.js";
|
||||
import type { DateString } from "../types/dateString.js";
|
||||
import type { TeamCode } from "../types/panit.js";
|
||||
import type { ScoreboardScopeCache } from "../types/scoreboard.js";
|
||||
import { rtdb } from "../firebase";
|
||||
import type { DateString } from "../types/dateString";
|
||||
import type { TeamCode } from "../types/panit";
|
||||
import type { ScoreboardScopeCache } from "../types/scoreboard";
|
||||
|
||||
const BASE = "/scoreboardCache";
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { firestore } from "../firebase.js";
|
||||
import type { VoteHistoryDoc } from "../types/panit.js";
|
||||
import type { DateString } from "../types/dateString.js";
|
||||
import { firestore } from "../firebase";
|
||||
import type { VoteHistoryDoc } from "../types/panit";
|
||||
import type { DateString } from "../types/dateString";
|
||||
|
||||
/**
|
||||
* 특정 유저의 voteHistory 서브컬렉션 레퍼런스를 반환한다.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { ServerValue } from "firebase-admin/database";
|
||||
import { rtdb } from "../firebase.js";
|
||||
import type { VoteEntry } from "../types/panit.js";
|
||||
import type { DateString } from "../types/dateString.js";
|
||||
import { rtdb } from "../firebase";
|
||||
import type { VoteEntry } from "../types/panit";
|
||||
import type { DateString } from "../types/dateString";
|
||||
|
||||
/**
|
||||
* 특정 경기의 해당 유저 투표를 조회한다.
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
import { onSchedule } from "firebase-functions/scheduler";
|
||||
import { logger } from "firebase-functions";
|
||||
import { rtdb } from "../firebase.js";
|
||||
import { setDay } from "../repositories/voteHistoryRepository.js";
|
||||
import { invalidateStats } from "../services/statsService.js";
|
||||
import { judgeDay, judgeWeekIfNeeded } from "../services/judgmentService.js";
|
||||
import { rtdb } from "../firebase";
|
||||
import { setDay } from "../repositories/voteHistoryRepository";
|
||||
import { invalidateStats } from "../services/statsService";
|
||||
import { judgeDay, judgeWeekIfNeeded } from "../services/judgmentService";
|
||||
import {
|
||||
precomputeScoreboardCache,
|
||||
snapshotRankForUser,
|
||||
} from "../services/rankSnapshotService.js";
|
||||
import { todayKst } from "../types/dateString.js";
|
||||
import { getGame } from "../repositories/gameRepository.js";
|
||||
import { deleteUserVoteGame } from "../repositories/voteRepository.js";
|
||||
import { processGameEndWithGame } from "../services/gameResultService.js";
|
||||
import type { VoteHistoryDoc } from "../types/panit.js";
|
||||
} from "../services/rankSnapshotService";
|
||||
import { todayKst } from "../types/dateString";
|
||||
import { getGame } from "../repositories/gameRepository";
|
||||
import { deleteUserVoteGame } from "../repositories/voteRepository";
|
||||
import { processGameEndWithGame } from "../services/gameResultService";
|
||||
import type { VoteHistoryDoc } from "../types/panit";
|
||||
import {
|
||||
dayOfWeekKst,
|
||||
daysAgoKst,
|
||||
type DateString,
|
||||
} from "../types/dateString.js";
|
||||
} from "../types/dateString";
|
||||
|
||||
interface RawVote {
|
||||
team: string;
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import { onSchedule } from "firebase-functions/scheduler";
|
||||
import { logger } from "firebase-functions";
|
||||
import { firestore } from "../firebase.js";
|
||||
import { firestore } from "../firebase";
|
||||
import {
|
||||
fetchRankFromKbo,
|
||||
fetchScheduleFromKbo,
|
||||
} from "../repositories/kboRepository.js";
|
||||
} from "../repositories/kboRepository";
|
||||
import {
|
||||
syncGamesForMonth,
|
||||
syncYesterdayFromLive,
|
||||
} from "../services/gameSyncService.js";
|
||||
import { daysAgoKst } from "../types/dateString.js";
|
||||
} from "../services/gameSyncService";
|
||||
import { daysAgoKst } from "../types/dateString";
|
||||
|
||||
const CACHE_COLLECTION = "kboCache";
|
||||
|
||||
|
||||
@ -3,14 +3,14 @@ import {
|
||||
type GameDetail,
|
||||
type GameDetailFilters,
|
||||
type ScoreBoardMeta,
|
||||
} from "../kbo/game-detail.js";
|
||||
} from "../kbo/game-detail";
|
||||
import {
|
||||
encodeKey,
|
||||
getCached,
|
||||
setCached,
|
||||
acquireLock,
|
||||
releaseLock,
|
||||
} from "../repositories/kboCacheRepository.js";
|
||||
} from "../repositories/kboCacheRepository";
|
||||
|
||||
const SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
|
||||
const ONE_HOUR_MS = 60 * 60 * 1000;
|
||||
|
||||
@ -4,8 +4,8 @@ import {
|
||||
LeagueCode,
|
||||
SERIES_CODES,
|
||||
type GameListResult,
|
||||
} from "../kbo/game-list.js";
|
||||
import { MemCache } from "../lib/memCache.js";
|
||||
} from "../kbo/game-list";
|
||||
import { MemCache } from "../lib/memCache";
|
||||
|
||||
// 게임센터(GetKboGameList)는 다른 KBO 데이터와 달리 Firestore 공유 캐시
|
||||
// (kboCacheRepository) 대신 인스턴스 단위 인메모리 캐시를 쓴다.
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { FieldValue } from "firebase-admin/firestore";
|
||||
import { logger } from "firebase-functions";
|
||||
import { firestore, rtdb } from "../firebase.js";
|
||||
import { HttpError } from "../middleware/errors.js";
|
||||
import { getGame } from "../repositories/gameRepository.js";
|
||||
import { getAllUserVotes, deleteGameVotes } from "../repositories/voteRepository.js";
|
||||
import { invalidateStats } from "./statsService.js";
|
||||
import { fromTimestamp } from "../types/dateString.js";
|
||||
import type { Game } from "../types/panit.js";
|
||||
import { firestore, rtdb } from "../firebase";
|
||||
import { HttpError } from "../middleware/errors";
|
||||
import { getGame } from "../repositories/gameRepository";
|
||||
import { getAllUserVotes, deleteGameVotes } from "../repositories/voteRepository";
|
||||
import { invalidateStats } from "./statsService";
|
||||
import { fromTimestamp } from "../types/dateString";
|
||||
import type { Game } from "../types/panit";
|
||||
|
||||
export async function processGameEnd(gameId: string): Promise<{ processed: number }> {
|
||||
const game = await getGame(gameId);
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { Timestamp } from "firebase-admin/firestore";
|
||||
import { firestore } from "../firebase.js";
|
||||
import { firestore } from "../firebase";
|
||||
import {
|
||||
fetchScheduleFromKbo,
|
||||
statusFromRecord,
|
||||
} from "../repositories/kboRepository.js";
|
||||
import { getGameList } from "./gameListService.js";
|
||||
import type { GameListRecord } from "../kbo/game-list.js";
|
||||
import type { ScheduleGame, GameStatus } from "../kbo/schedule.js";
|
||||
import type { Game } from "../types/panit.js";
|
||||
} from "../repositories/kboRepository";
|
||||
import { getGameList } from "./gameListService";
|
||||
import type { GameListRecord } from "../kbo/game-list";
|
||||
import type { ScheduleGame, GameStatus } from "../kbo/schedule";
|
||||
import type { Game } from "../types/panit";
|
||||
|
||||
const COLLECTION = "games";
|
||||
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
import { logger } from "firebase-functions";
|
||||
import { listByDate } from "../repositories/gameRepository.js";
|
||||
import { getRange, setDay } from "../repositories/voteHistoryRepository.js";
|
||||
import { listByDate } from "../repositories/gameRepository";
|
||||
import { getRange, setDay } from "../repositories/voteHistoryRepository";
|
||||
import {
|
||||
applyDailyJudgmentTx,
|
||||
applyWeeklyMasterTx,
|
||||
getUser,
|
||||
} from "../repositories/userRepository.js";
|
||||
} from "../repositories/userRepository";
|
||||
import {
|
||||
judgeByCounts,
|
||||
streakBonus,
|
||||
thresholdsFor,
|
||||
} from "../constants/judgment.js";
|
||||
import type { DailyJudgment, VoteHistoryDoc } from "../types/panit.js";
|
||||
import { addDaysKst, tuesdayOf, type DateString } from "../types/dateString.js";
|
||||
} from "../constants/judgment";
|
||||
import type { DailyJudgment, VoteHistoryDoc } from "../types/panit";
|
||||
import { addDaysKst, tuesdayOf, type DateString } from "../types/dateString";
|
||||
|
||||
/**
|
||||
* `(lastJudged, upTo)` 구간(양 끝 제외)에 **실제 판정 가능한 경기일**(=`thresholdsFor`가
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { fetchPlayerFromKbo } from "../repositories/kboRepository.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";
|
||||
import { RUNNER_CONFIG } from "../kbo/player/runner.js";
|
||||
import { fetchPlayerFromKbo } from "../repositories/kboRepository";
|
||||
import type { PlayerFilters, PlayerPageConfig, PlayerStatsResult } from "../types/kbo";
|
||||
import { TeamCode } from "../types/panit";
|
||||
import { HITTER_CONFIG } from "../kbo/player/hitter";
|
||||
import { PITCHER_CONFIG } from "../kbo/player/pitcher";
|
||||
import { DEFENSE_CONFIG } from "../kbo/player/defense";
|
||||
import { RUNNER_CONFIG } from "../kbo/player/runner";
|
||||
|
||||
const PLAYER_CONFIGS: Record<string, PlayerPageConfig> = {
|
||||
hitter: HITTER_CONFIG,
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import { HttpError } from "../middleware/errors.js";
|
||||
import { getGame, listByDate, type GameWithId } from "../repositories/gameRepository.js";
|
||||
import { HttpError } from "../middleware/errors";
|
||||
import { getGame, listByDate, type GameWithId } from "../repositories/gameRepository";
|
||||
import {
|
||||
getUserVote,
|
||||
submitVote,
|
||||
changeVote,
|
||||
getCounts,
|
||||
getUserDateVotes,
|
||||
} from "../repositories/voteRepository.js";
|
||||
import type { Game, VoteEntry } from "../types/panit.js";
|
||||
import { fromTimestamp, parseDateString, type DateString } from "../types/dateString.js";
|
||||
import { MemCache } from "../lib/memCache.js";
|
||||
} from "../repositories/voteRepository";
|
||||
import type { Game, VoteEntry } from "../types/panit";
|
||||
import { fromTimestamp, parseDateString, type DateString } from "../types/dateString";
|
||||
import { MemCache } from "../lib/memCache";
|
||||
|
||||
type SummaryCounts = { homeCount: number; awayCount: number };
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { fetchRankFromKbo } from "../repositories/kboRepository.js";
|
||||
import type { TeamRankResult } from "../types/kbo.js";
|
||||
import { fetchRankFromKbo } from "../repositories/kboRepository";
|
||||
import type { TeamRankResult } from "../types/kbo";
|
||||
|
||||
export async function getRank(years: number[]): Promise<TeamRankResult[]> {
|
||||
return fetchRankFromKbo(years);
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
import { logger } from "firebase-functions";
|
||||
import { firestore } from "../firebase.js";
|
||||
import { firestore } from "../firebase";
|
||||
import {
|
||||
countRankedUsers,
|
||||
countUsersAboveTierPoints,
|
||||
getUser,
|
||||
listTopByTierPoints,
|
||||
type ScoreboardUserEntry,
|
||||
} from "../repositories/userRepository.js";
|
||||
import { writeScope, type Scope } from "../repositories/scoreboardCacheRepository.js";
|
||||
import { computePercentile, deltaFor } from "./scoreboardHelpers.js";
|
||||
import type { DateString } from "../types/dateString.js";
|
||||
import { TeamCode, type RankSnapshot } from "../types/panit.js";
|
||||
} from "../repositories/userRepository";
|
||||
import { writeScope, type Scope } from "../repositories/scoreboardCacheRepository";
|
||||
import { computePercentile, deltaFor } from "./scoreboardHelpers";
|
||||
import type { DateString } from "../types/dateString";
|
||||
import { TeamCode, type RankSnapshot } from "../types/panit";
|
||||
import type {
|
||||
ScoreboardEntry,
|
||||
ScoreboardScopeCache,
|
||||
} from "../types/scoreboard.js";
|
||||
} from "../types/scoreboard";
|
||||
|
||||
/**
|
||||
* 유저 1명의 현재 `tierPoints` 기반 rank를 count aggregation으로 계산해
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { fetchScheduleFromKbo } from "../repositories/kboRepository.js";
|
||||
import { SERIES_CODES } from "../types/kbo.js";
|
||||
import type { ScheduleResult } from "../types/kbo.js";
|
||||
import type { TeamCode } from "../types/panit.js";
|
||||
import { fetchScheduleFromKbo } from "../repositories/kboRepository";
|
||||
import { SERIES_CODES } from "../types/kbo";
|
||||
import type { ScheduleResult } from "../types/kbo";
|
||||
import type { TeamCode } from "../types/panit";
|
||||
|
||||
export async function getSchedule(
|
||||
year: number,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { Scope } from "../repositories/scoreboardCacheRepository.js";
|
||||
import type { RankSnapshot } from "../types/panit.js";
|
||||
import type { Scope } from "../repositories/scoreboardCacheRepository";
|
||||
import type { RankSnapshot } from "../types/panit";
|
||||
|
||||
export function computePercentile(rank: number, totalCount: number): number {
|
||||
if (totalCount <= 0) return 0;
|
||||
|
||||
@ -1,22 +1,22 @@
|
||||
import { MemCache } from "../lib/memCache.js";
|
||||
import { MemCache } from "../lib/memCache";
|
||||
import {
|
||||
countUsersAboveTierPoints,
|
||||
getUser,
|
||||
} from "../repositories/userRepository.js";
|
||||
} from "../repositories/userRepository";
|
||||
import {
|
||||
readScope,
|
||||
type Scope,
|
||||
} from "../repositories/scoreboardCacheRepository.js";
|
||||
import { HttpError } from "../middleware/errors.js";
|
||||
import { computePercentile, deltaFor } from "./scoreboardHelpers.js";
|
||||
import { todayKst } from "../types/dateString.js";
|
||||
import { type TeamCode } from "../types/panit.js";
|
||||
} from "../repositories/scoreboardCacheRepository";
|
||||
import { HttpError } from "../middleware/errors";
|
||||
import { computePercentile, deltaFor } from "./scoreboardHelpers";
|
||||
import { todayKst } from "../types/dateString";
|
||||
import { type TeamCode } from "../types/panit";
|
||||
import type {
|
||||
ScoreboardEntry,
|
||||
ScoreboardResponse,
|
||||
ScoreboardScopeCache,
|
||||
ScoreboardType,
|
||||
} from "../types/scoreboard.js";
|
||||
} from "../types/scoreboard";
|
||||
|
||||
const BURST_TTL_MS = 30_000;
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import {rtdb} from "../firebase.js";
|
||||
import {HttpError} from "../middleware/errors.js";
|
||||
import {computeLevel} from "../constants/levels.js";
|
||||
import {tierOf} from "../constants/tiers.js";
|
||||
import {getAll, getDay} from "../repositories/voteHistoryRepository.js";
|
||||
import {getUser} from "../repositories/userRepository.js";
|
||||
import {hasMissedGameDayBetween} from "./judgmentService.js";
|
||||
import type {DailyJudgment, StatsResponse, VoteHistoryDoc} from "../types/panit.js";
|
||||
import {rtdb} from "../firebase";
|
||||
import {HttpError} from "../middleware/errors";
|
||||
import {computeLevel} from "../constants/levels";
|
||||
import {tierOf} from "../constants/tiers";
|
||||
import {getAll, getDay} from "../repositories/voteHistoryRepository";
|
||||
import {getUser} from "../repositories/userRepository";
|
||||
import {hasMissedGameDayBetween} from "./judgmentService";
|
||||
import type {DailyJudgment, StatsResponse, VoteHistoryDoc} from "../types/panit";
|
||||
import {
|
||||
addDaysKst,
|
||||
parseDateString,
|
||||
@ -14,7 +14,7 @@ import {
|
||||
todayKst,
|
||||
tuesdayOf as tuesdayOfUtil,
|
||||
type DateString,
|
||||
} from "../types/dateString.js";
|
||||
} from "../types/dateString";
|
||||
|
||||
type Period =
|
||||
| "current"
|
||||
|
||||
@ -1,27 +1,27 @@
|
||||
import type { DecodedIdToken } from "firebase-admin/auth";
|
||||
import { FieldValue } from "firebase-admin/firestore";
|
||||
import { HttpError } from "../middleware/errors.js";
|
||||
import { auth } from "../firebase.js";
|
||||
import { HttpError } from "../middleware/errors";
|
||||
import { auth } from "../firebase";
|
||||
import {
|
||||
createUser,
|
||||
deleteUser,
|
||||
findUidByDisplayName,
|
||||
getUser,
|
||||
updateUser,
|
||||
} from "../repositories/userRepository.js";
|
||||
} from "../repositories/userRepository";
|
||||
import {
|
||||
deleteReservation,
|
||||
releaseReservation,
|
||||
reserveNickname,
|
||||
verifyReservation,
|
||||
} from "../repositories/nicknameRepository.js";
|
||||
} from "../repositories/nicknameRepository";
|
||||
import {
|
||||
KnowledgeLevel,
|
||||
TeamCode,
|
||||
type Provider,
|
||||
type User,
|
||||
type UserProfile,
|
||||
} from "../types/panit.js";
|
||||
} from "../types/panit";
|
||||
|
||||
/**
|
||||
* 내부 User 문서를 클라이언트 응답용 프로필로 변환한다.
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
import {onDocumentUpdated} from "firebase-functions/firestore";
|
||||
import {logger} from "firebase-functions";
|
||||
import {rtdb} from "../firebase.js";
|
||||
import {processGameEndWithGame} from "../services/gameResultService.js";
|
||||
import {rtdb} from "../firebase";
|
||||
import {processGameEndWithGame} from "../services/gameResultService";
|
||||
import {
|
||||
getAllUserVotes,
|
||||
deleteGameVotes,
|
||||
} from "../repositories/voteRepository.js";
|
||||
import {invalidateStats} from "../services/statsService.js";
|
||||
import {fromTimestamp} from "../types/dateString.js";
|
||||
import type {Game} from "../types/panit.js";
|
||||
} from "../repositories/voteRepository";
|
||||
import {invalidateStats} from "../services/statsService";
|
||||
import {fromTimestamp} from "../types/dateString";
|
||||
import type {Game} from "../types/panit";
|
||||
|
||||
/**
|
||||
* `games/{gameId}` 문서 업데이트를 받아 유저 투표를 정리하는 Firestore 트리거.
|
||||
|
||||
@ -6,32 +6,32 @@ export type {
|
||||
WinLossDraw,
|
||||
TeamVsRecord,
|
||||
TeamRankResult,
|
||||
} from "../kbo/team-rank.js";
|
||||
} from "../kbo/team-rank";
|
||||
|
||||
export type {
|
||||
GameStatus,
|
||||
ScheduleGame,
|
||||
ScheduleFilters,
|
||||
ScheduleResult,
|
||||
} from "../kbo/schedule.js";
|
||||
} from "../kbo/schedule";
|
||||
|
||||
export type {
|
||||
PlayerPageConfig,
|
||||
PlayerRecord,
|
||||
PlayerFilters,
|
||||
PlayerStatsResult,
|
||||
} from "../kbo/player/common.js";
|
||||
} from "../kbo/player/common";
|
||||
|
||||
export { SERIES_CODES } from "../kbo/schedule.js";
|
||||
export { SERIES_CODES } from "../kbo/schedule";
|
||||
|
||||
export type {
|
||||
GameListFilters,
|
||||
GameListRecord,
|
||||
GameListResult,
|
||||
PersonRef,
|
||||
} from "../kbo/game-list.js";
|
||||
} from "../kbo/game-list";
|
||||
|
||||
export { LeagueCode, LEAGUE_CODES } from "../kbo/game-list.js";
|
||||
export { LeagueCode, LEAGUE_CODES } from "../kbo/game-list";
|
||||
|
||||
export type {
|
||||
GameDetail,
|
||||
@ -50,7 +50,7 @@ export type {
|
||||
KeyPlayerRanking,
|
||||
KeyPlayerItem,
|
||||
KeyPlayerGroup,
|
||||
} from "../kbo/game-detail.js";
|
||||
} from "../kbo/game-detail";
|
||||
|
||||
export type {
|
||||
GameScoringPlays,
|
||||
@ -61,6 +61,6 @@ export type {
|
||||
ScoringOutcome,
|
||||
BaseState,
|
||||
BaseRunner,
|
||||
} from "../kbo/play-by-play.js";
|
||||
} from "../kbo/play-by-play";
|
||||
|
||||
export { SERIES_ID } from "../kbo/schedule.js";
|
||||
export { SERIES_ID } from "../kbo/schedule";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { Timestamp } from "firebase-admin/firestore";
|
||||
import type { DateString } from "./dateString.js";
|
||||
import type { DateString } from "./dateString";
|
||||
|
||||
export type Provider = "google" | "apple";
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { TeamCode } from "./panit.js";
|
||||
import type { TeamCode } from "./panit";
|
||||
|
||||
export interface ScoreboardEntry {
|
||||
uid: string;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { Timestamp } from "firebase-admin/firestore";
|
||||
import { firestore } from "../../src/firebase.js";
|
||||
import { getGame, listByDate } from "../../src/repositories/gameRepository.js";
|
||||
import type { DateString } from "../../src/types/dateString.js";
|
||||
import { firestore } from "../../src/firebase";
|
||||
import { getGame, listByDate } from "../../src/repositories/gameRepository";
|
||||
import type { DateString } from "../../src/types/dateString";
|
||||
|
||||
describe("gameRepository", () => {
|
||||
beforeEach(async () => {
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { firestore } from "../../src/firebase.js";
|
||||
import { firestore } from "../../src/firebase";
|
||||
import {
|
||||
fetchRankFromKbo,
|
||||
fetchScheduleFromKbo,
|
||||
} from "../../src/repositories/kboRepository.js";
|
||||
} from "../../src/repositories/kboRepository";
|
||||
|
||||
describe("kboRepository (실제 KBO 사이트 호출)", () => {
|
||||
beforeEach(async () => {
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { firestore } from "../../src/firebase.js";
|
||||
import { firestore } from "../../src/firebase";
|
||||
import {
|
||||
getAll,
|
||||
getDay,
|
||||
getRange,
|
||||
setDay,
|
||||
} from "../../src/repositories/voteHistoryRepository.js";
|
||||
import type { DateString } from "../../src/types/dateString.js";
|
||||
import type { VoteHistoryDoc } from "../../src/types/panit.js";
|
||||
} from "../../src/repositories/voteHistoryRepository";
|
||||
import type { DateString } from "../../src/types/dateString";
|
||||
import type { VoteHistoryDoc } from "../../src/types/panit";
|
||||
|
||||
const uid = "test-uid-1";
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { rtdb } from "../../src/firebase.js";
|
||||
import { rtdb } from "../../src/firebase";
|
||||
import {
|
||||
changeVote,
|
||||
deleteGameVotes,
|
||||
@ -8,8 +8,8 @@ import {
|
||||
getUserDateVotes,
|
||||
getUserVote,
|
||||
submitVote,
|
||||
} from "../../src/repositories/voteRepository.js";
|
||||
import type { DateString } from "../../src/types/dateString.js";
|
||||
} from "../../src/repositories/voteRepository";
|
||||
import type { DateString } from "../../src/types/dateString";
|
||||
|
||||
const gameId = "20260412HTLG0";
|
||||
const gameId2 = "20260412WOSK0";
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { firestore } from "../../src/firebase.js";
|
||||
import { getGameDetail } from "../../src/services/gameDetailService.js";
|
||||
import { firestore } from "../../src/firebase";
|
||||
import { getGameDetail } from "../../src/services/gameDetailService";
|
||||
|
||||
// 실제 KBO 게임센터 + Firestore 에뮬레이터를 함께 사용한다.
|
||||
// nested-array Firestore 거부, parseGameStartTs NPE 등 회귀를 잡기 위함.
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { firestore } from "../../src/firebase.js";
|
||||
import { firestore } from "../../src/firebase";
|
||||
import {
|
||||
toGameDoc,
|
||||
toTime,
|
||||
syncGamesForMonth,
|
||||
gameUpdateFromRecord,
|
||||
} from "../../src/services/gameSyncService.js";
|
||||
import type { ScheduleGame } from "../../src/kbo/schedule.js";
|
||||
import type { GameListRecord } from "../../src/kbo/game-list.js";
|
||||
} from "../../src/services/gameSyncService";
|
||||
import type { ScheduleGame } from "../../src/kbo/schedule";
|
||||
import type { GameListRecord } from "../../src/kbo/game-list";
|
||||
|
||||
function baseGame(overrides: Partial<ScheduleGame> = {}): ScheduleGame {
|
||||
return {
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { Timestamp } from "firebase-admin/firestore";
|
||||
import { firestore } from "../../src/firebase.js";
|
||||
import { firestore } from "../../src/firebase";
|
||||
import {
|
||||
judgeDay,
|
||||
judgeWeekIfNeeded,
|
||||
} from "../../src/services/judgmentService.js";
|
||||
import { setDay } from "../../src/repositories/voteHistoryRepository.js";
|
||||
import type { DateString } from "../../src/types/dateString.js";
|
||||
} from "../../src/services/judgmentService";
|
||||
import { setDay } from "../../src/repositories/voteHistoryRepository";
|
||||
import type { DateString } from "../../src/types/dateString";
|
||||
import type {
|
||||
DailyJudgment,
|
||||
Game,
|
||||
GameStatus,
|
||||
User,
|
||||
VoteHistoryDoc,
|
||||
} from "../../src/types/panit.js";
|
||||
} from "../../src/types/panit";
|
||||
|
||||
const uid = "judge-uid";
|
||||
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { firestore, rtdb } from "../../src/firebase.js";
|
||||
import { firestore, rtdb } from "../../src/firebase";
|
||||
import {
|
||||
__resetScoreboardCaches,
|
||||
getScoreboard,
|
||||
} from "../../src/services/scoreboardService.js";
|
||||
} from "../../src/services/scoreboardService";
|
||||
import {
|
||||
precomputeScoreboardCache,
|
||||
snapshotRankForUser,
|
||||
} from "../../src/services/rankSnapshotService.js";
|
||||
import { todayKst } from "../../src/types/dateString.js";
|
||||
import { TeamCode, type RankSnapshot } from "../../src/types/panit.js";
|
||||
} from "../../src/services/rankSnapshotService";
|
||||
import { todayKst } from "../../src/types/dateString";
|
||||
import { TeamCode, type RankSnapshot } from "../../src/types/panit";
|
||||
|
||||
interface SeedUser {
|
||||
uid: string;
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { Timestamp } from "firebase-admin/firestore";
|
||||
import { firestore, rtdb } from "../../src/firebase.js";
|
||||
import { getStats } from "../../src/services/statsService.js";
|
||||
import { firestore, rtdb } from "../../src/firebase";
|
||||
import { getStats } from "../../src/services/statsService";
|
||||
import {
|
||||
addDaysKst,
|
||||
todayKst,
|
||||
type DateString,
|
||||
} from "../../src/types/dateString.js";
|
||||
} from "../../src/types/dateString";
|
||||
import type {
|
||||
Game,
|
||||
GameStatus,
|
||||
StatsResponse,
|
||||
User,
|
||||
} from "../../src/types/panit.js";
|
||||
} from "../../src/types/panit";
|
||||
|
||||
const uid = "stats-uid";
|
||||
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import type { DecodedIdToken } from "firebase-admin/auth";
|
||||
import { firestore, rtdb } from "../../src/firebase.js";
|
||||
import { firestore, rtdb } from "../../src/firebase";
|
||||
import {
|
||||
checkNickname,
|
||||
createMe,
|
||||
deleteMe,
|
||||
getMe,
|
||||
updateMe,
|
||||
} from "../../src/services/userService.js";
|
||||
import { HttpError } from "../../src/middleware/errors.js";
|
||||
} from "../../src/services/userService";
|
||||
import { HttpError } from "../../src/middleware/errors";
|
||||
import {
|
||||
RESERVATION_TTL_MS,
|
||||
reserveNickname,
|
||||
} from "../../src/repositories/nicknameRepository.js";
|
||||
} from "../../src/repositories/nicknameRepository";
|
||||
|
||||
const uid = "user-1";
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user