Align repo config with global development standards
Some checks failed
CI / backend-lint (push) Failing after 1m4s
CI / actions-lint (push) Failing after 6s
CI / frontend-lint (push) Successful in 59s

- Add missing tsconfig strictness flags (noUncheckedIndexedAccess,
  exactOptionalPropertyTypes, noImplicitOverride,
  noPropertyAccessFromIndexSignature) and fix all resulting type errors
- Replace ESLint/Prettier with oxlint 1.48.0 and oxfmt 0.33.0
- Pin all frontend and backend dependencies to exact versions
- Pin GitHub Actions to SHA hashes with persist-credentials: false
- Fix CI Python version mismatch (3.12 -> 3.14) and ruff target-version
- Add vitest 4.0.18 with jsdom environment for frontend testing
- Add ty 0.0.17 for Python type checking (non-blocking in CI)
- Add actionlint and zizmor CI job for workflow linting and security audit
- Add Dependabot config for npm, pip, and github-actions
- Update CLAUDE.md and pre-commit hooks to reflect new tooling
- Ignore Claude Code sandbox artifacts in gitignore

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 20:39:41 +01:00
parent e4814250db
commit 3a64661760
91 changed files with 2073 additions and 3215 deletions

View File

@@ -30,11 +30,9 @@ import type {
import type { Genlocke } from '../types/game'
// Games
export const createGame = (data: CreateGameInput) =>
api.post<Game>('/games', data)
export const createGame = (data: CreateGameInput) => api.post<Game>('/games', data)
export const updateGame = (id: number, data: UpdateGameInput) =>
api.put<Game>(`/games/${id}`, data)
export const updateGame = (id: number, data: UpdateGameInput) => api.put<Game>(`/games/${id}`, data)
export const deleteGame = (id: number) => api.del(`/games/${id}`)
@@ -42,11 +40,8 @@ export const deleteGame = (id: number) => api.del(`/games/${id}`)
export const createRoute = (gameId: number, data: CreateRouteInput) =>
api.post<Route>(`/games/${gameId}/routes`, data)
export const updateRoute = (
gameId: number,
routeId: number,
data: UpdateRouteInput
) => api.put<Route>(`/games/${gameId}/routes/${routeId}`, data)
export const updateRoute = (gameId: number, routeId: number, data: UpdateRouteInput) =>
api.put<Route>(`/games/${gameId}/routes/${routeId}`, data)
export const deleteRoute = (gameId: number, routeId: number) =>
api.del(`/games/${gameId}/routes/${routeId}`)
@@ -55,12 +50,7 @@ export const reorderRoutes = (gameId: number, routes: RouteReorderItem[]) =>
api.put<Route[]>(`/games/${gameId}/routes/reorder`, { routes })
// Pokemon
export const listPokemon = (
search?: string,
limit = 50,
offset = 0,
type?: string
) => {
export const listPokemon = (search?: string, limit = 50, offset = 0, type?: string) => {
const params = new URLSearchParams()
if (search) params.set('search', search)
if (type) params.set('type', type)
@@ -69,8 +59,7 @@ export const listPokemon = (
return api.get<PaginatedPokemon>(`/pokemon?${params}`)
}
export const createPokemon = (data: CreatePokemonInput) =>
api.post<Pokemon>('/pokemon', data)
export const createPokemon = (data: CreatePokemonInput) => api.post<Pokemon>('/pokemon', data)
export const updatePokemon = (id: number, data: UpdatePokemonInput) =>
api.put<Pokemon>(`/pokemon/${id}`, data)
@@ -97,12 +86,7 @@ export const bulkImportBosses = (gameId: number, items: unknown[]) =>
api.post<BulkImportResult>(`/games/${gameId}/bosses/bulk-import`, items)
// Evolutions
export const listEvolutions = (
search?: string,
limit = 50,
offset = 0,
trigger?: string
) => {
export const listEvolutions = (search?: string, limit = 50, offset = 0, trigger?: string) => {
const params = new URLSearchParams()
if (search) params.set('search', search)
if (trigger) params.set('trigger', trigger)
@@ -120,8 +104,7 @@ export const updateEvolution = (id: number, data: UpdateEvolutionInput) =>
export const deleteEvolution = (id: number) => api.del(`/evolutions/${id}`)
// Export
export const exportGames = () =>
api.get<Record<string, unknown>[]>('/export/games')
export const exportGames = () => api.get<Record<string, unknown>[]>('/export/games')
export const exportGameRoutes = (gameId: number) =>
api.get<{ filename: string; data: unknown }>(`/export/games/${gameId}/routes`)
@@ -129,27 +112,19 @@ export const exportGameRoutes = (gameId: number) =>
export const exportGameBosses = (gameId: number) =>
api.get<{ filename: string; data: unknown }>(`/export/games/${gameId}/bosses`)
export const exportPokemon = () =>
api.get<Record<string, unknown>[]>('/export/pokemon')
export const exportPokemon = () => api.get<Record<string, unknown>[]>('/export/pokemon')
export const exportEvolutions = () =>
api.get<Record<string, unknown>[]>('/export/evolutions')
export const exportEvolutions = () => api.get<Record<string, unknown>[]>('/export/evolutions')
// Route Encounters
export const addRouteEncounter = (
routeId: number,
data: CreateRouteEncounterInput
) => api.post<RouteEncounterDetail>(`/routes/${routeId}/pokemon`, data)
export const addRouteEncounter = (routeId: number, data: CreateRouteEncounterInput) =>
api.post<RouteEncounterDetail>(`/routes/${routeId}/pokemon`, data)
export const updateRouteEncounter = (
routeId: number,
encounterId: number,
data: UpdateRouteEncounterInput
) =>
api.put<RouteEncounterDetail>(
`/routes/${routeId}/pokemon/${encounterId}`,
data
)
) => api.put<RouteEncounterDetail>(`/routes/${routeId}/pokemon/${encounterId}`, data)
export const removeRouteEncounter = (routeId: number, encounterId: number) =>
api.del(`/routes/${routeId}/pokemon/${encounterId}`)
@@ -158,11 +133,8 @@ export const removeRouteEncounter = (routeId: number, encounterId: number) =>
export const createBossBattle = (gameId: number, data: CreateBossBattleInput) =>
api.post<BossBattle>(`/games/${gameId}/bosses`, data)
export const updateBossBattle = (
gameId: number,
bossId: number,
data: UpdateBossBattleInput
) => api.put<BossBattle>(`/games/${gameId}/bosses/${bossId}`, data)
export const updateBossBattle = (gameId: number, bossId: number, data: UpdateBossBattleInput) =>
api.put<BossBattle>(`/games/${gameId}/bosses/${bossId}`, data)
export const deleteBossBattle = (gameId: number, bossId: number) =>
api.del(`/games/${gameId}/bosses/${bossId}`)
@@ -170,11 +142,8 @@ export const deleteBossBattle = (gameId: number, bossId: number) =>
export const reorderBosses = (gameId: number, bosses: BossReorderItem[]) =>
api.put<BossBattle[]>(`/games/${gameId}/bosses/reorder`, { bosses })
export const setBossTeam = (
gameId: number,
bossId: number,
team: BossPokemonInput[]
) => api.put<BossBattle>(`/games/${gameId}/bosses/${bossId}/pokemon`, team)
export const setBossTeam = (gameId: number, bossId: number, team: BossPokemonInput[]) =>
api.put<BossBattle>(`/games/${gameId}/bosses/${bossId}/pokemon`, team)
// Genlockes
export const updateGenlocke = (id: number, data: UpdateGenlockeInput) =>

View File

@@ -1,14 +1,7 @@
import { api } from './client'
import type {
BossBattle,
BossResult,
CreateBossResultInput,
} from '../types/game'
import type { BossBattle, BossResult, CreateBossResultInput } from '../types/game'
export function getGameBosses(
gameId: number,
all?: boolean
): Promise<BossBattle[]> {
export function getGameBosses(gameId: number, all?: boolean): Promise<BossBattle[]> {
const params = all ? '?all=true' : ''
return api.get(`/games/${gameId}/bosses${params}`)
}
@@ -17,16 +10,10 @@ export function getBossResults(runId: number): Promise<BossResult[]> {
return api.get(`/runs/${runId}/boss-results`)
}
export function createBossResult(
runId: number,
data: CreateBossResultInput
): Promise<BossResult> {
export function createBossResult(runId: number, data: CreateBossResultInput): Promise<BossResult> {
return api.post(`/runs/${runId}/boss-results`, data)
}
export function deleteBossResult(
runId: number,
resultId: number
): Promise<void> {
export function deleteBossResult(runId: number, resultId: number): Promise<void> {
return api.del(`/runs/${runId}/boss-results/${resultId}`)
}

View File

@@ -1,4 +1,4 @@
const API_BASE = import.meta.env.VITE_API_URL ?? ''
const API_BASE = import.meta.env['VITE_API_URL'] ?? ''
export class ApiError extends Error {
status: number

View File

@@ -14,10 +14,7 @@ export function createEncounter(
return api.post(`/runs/${runId}/encounters`, data)
}
export function updateEncounter(
id: number,
data: UpdateEncounterInput
): Promise<EncounterDetail> {
export function updateEncounter(id: number, data: UpdateEncounterInput): Promise<EncounterDetail> {
return api.patch(`/encounters/${id}`, data)
}
@@ -25,10 +22,7 @@ export function deleteEncounter(id: number): Promise<void> {
return api.del(`/encounters/${id}`)
}
export function fetchEvolutions(
pokemonId: number,
region?: string
): Promise<Evolution[]> {
export function fetchEvolutions(pokemonId: number, region?: string): Promise<Evolution[]> {
const params = region ? `?region=${encodeURIComponent(region)}` : ''
return api.get(`/pokemon/${pokemonId}/evolutions${params}`)
}

View File

@@ -19,10 +19,7 @@ export function getGameRoutes(gameId: number): Promise<Route[]> {
return api.get(`/games/${gameId}/routes?flat=true`)
}
export function getRoutePokemon(
routeId: number,
gameId?: number
): Promise<RouteEncounterDetail[]> {
export function getRoutePokemon(routeId: number, gameId?: number): Promise<RouteEncounterDetail[]> {
const params = gameId != null ? `?game_id=${gameId}` : ''
return api.get(`/routes/${routeId}/pokemon${params}`)
}

View File

@@ -47,8 +47,5 @@ export function advanceLeg(
legOrder: number,
data?: AdvanceLegInput
): Promise<Genlocke> {
return api.post(
`/genlockes/${genlockeId}/legs/${legOrder}/advance`,
data ?? {}
)
return api.post(`/genlockes/${genlockeId}/legs/${legOrder}/advance`, data ?? {})
}

View File

@@ -16,8 +16,6 @@ export function fetchPokemonEncounterLocations(
return api.get(`/pokemon/${pokemonId}/encounter-locations`)
}
export function fetchPokemonEvolutionChain(
pokemonId: number
): Promise<EvolutionAdmin[]> {
export function fetchPokemonEvolutionChain(pokemonId: number): Promise<EvolutionAdmin[]> {
return api.get(`/pokemon/${pokemonId}/evolution-chain`)
}

View File

@@ -1,10 +1,5 @@
import { api } from './client'
import type {
NuzlockeRun,
RunDetail,
CreateRunInput,
UpdateRunInput,
} from '../types/game'
import type { NuzlockeRun, RunDetail, CreateRunInput, UpdateRunInput } from '../types/game'
export function getRuns(): Promise<NuzlockeRun[]> {
return api.get('/runs')
@@ -18,10 +13,7 @@ export function createRun(data: CreateRunInput): Promise<NuzlockeRun> {
return api.post('/runs', data)
}
export function updateRun(
id: number,
data: UpdateRunInput
): Promise<NuzlockeRun> {
export function updateRun(id: number, data: UpdateRunInput): Promise<NuzlockeRun> {
return api.patch(`/runs/${id}`, data)
}