fix: Remove Number() conversions that corrupt uint64 IDs

JavaScript's Number type cannot accurately represent uint64 values exceeding
Number.MAX_SAFE_INTEGER (2^53-1). Converting these IDs to numbers causes
precision loss and API errors.

Root cause found:
- match/[id]/+layout.ts: `Number(params.id)` corrupted match IDs
- player/[id]/+page.ts: `Number(params.id)` corrupted player IDs

Example of the bug:
- URL param: "3638078243082338615" (correct)
- After Number(): 3638078243082339000 (rounded!)
- API response: "Match 3638078243082339000 not found"

Changes:
- Remove Number() conversions in route loaders
- Keep params.id as string throughout the application
- Update API functions to only accept string (not string | number)
- Update MatchesQueryParams.player_id type to string
- Add comprehensive transformers for legacy API responses
- Transform player stats: duo→mk_2, triple→mk_3, steamid64→id
- Build full Steam avatar URLs
- Make share_code optional (not always present)

This ensures uint64 IDs maintain full precision from URL → API → response.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-04 23:38:37 +01:00
parent 43c50084c6
commit f583ff54a9
11 changed files with 158 additions and 40 deletions

View File

@@ -7,7 +7,7 @@ import { z } from 'zod';
/** MatchPlayer schema */
export const matchPlayerSchema = z.object({
id: z.number().positive(),
id: z.string().min(1), // Steam ID uint64 as string to preserve precision
name: z.string().min(1),
avatar: z.string().url(),
team_id: z.number().int().min(2).max(3), // 2 = T, 3 = CT
@@ -59,10 +59,11 @@ export const matchPlayerSchema = z.object({
/** Match schema */
export const matchSchema = z.object({
match_id: z.number().positive(),
match_id: z.string().min(1), // uint64 as string to preserve precision
share_code: z
.string()
.regex(/^CSGO-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}$/),
.regex(/^(CSGO-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5}-[A-Z0-9]{5})?$/)
.optional(),
map: z.string().min(1),
date: z.string().datetime(),
score_team_a: z.number().int().nonnegative(),
@@ -79,7 +80,7 @@ export const matchSchema = z.object({
/** MatchListItem schema */
export const matchListItemSchema = z.object({
match_id: z.number().positive(),
match_id: z.string().min(1), // uint64 as string to preserve precision
map: z.string().min(1),
date: z.string().datetime(),
score_team_a: z.number().int().nonnegative(),