Some checks failed
Deploy to Production / test (push) Failing after 33s
- tighten route authorization and schema handling - update user route tests and server coverage - refresh player dashboard behavior
7 lines
10 KiB
JSON
7 lines
10 KiB
JSON
{
|
||
"timestamp": "2026-04-07T11:54:55.731Z",
|
||
"code": "import { readFile } from 'node:fs/promises';\n\nasync function inspectChessUI() {\n const filesToRead = [\n 'panel/src/games/chess/ChessGame.tsx',\n 'panel/src/games/chess/pieces.tsx',\n 'bot/lib/embeds.ts'\n ];\n\n for (const file of filesToRead) {\n try {\n console.log(`\\n--- Reading ${file} ---`);\n const content = await readFile(file, 'utf8');\n console.log(content.substring(0, 3000) + \"\\n... [truncated]\");\n } catch (e) {\n console.error(`Could not read ${file}:`, e.message);\n }\n }\n}\n\ninspectChessUI();\n",
|
||
"output": "\n--- Reading panel/src/games/chess/ChessGame.tsx ---\nimport { useState, useEffect, useCallback, useMemo, useRef } from \"react\";\nimport { Chessboard } from \"react-chessboard\";\nimport { Chess } from \"chess.js\";\nimport type { Square } from \"chess.js\";\nimport type { GameUIProps } from \"../registry\";\nimport { Flag, Handshake, X, Check, Clock } from \"lucide-react\";\nimport { chessPieces } from \"./pieces\";\n\n// ── Types matching server ChessPlayerView / ChessSpectatorView ──\n\ninterface ChessClockView {\n white: number;\n black: number;\n increment: number;\n activeColor: \"white\" | \"black\" | null;\n}\n\ninterface ChessViewBase {\n fen: string;\n pgn: string;\n turn: \"white\" | \"black\";\n clock: ChessClockView | null;\n drawOffer: \"white\" | \"black\" | null;\n result: \"white\" | \"black\" | \"draw\" | null;\n resultReason: string | null;\n moveHistory: { from: string; to: string; san: string; color: \"w\" | \"b\" }[];\n isCheck: boolean;\n}\n\ninterface PlayerView extends ChessViewBase {\n myColor: \"white\" | \"black\";\n legalMoves: { from: string; to: string; promotion?: string }[];\n}\n\ninterface SpectatorView extends ChessViewBase {\n players: { white: string; black: string };\n}\n\nfunction isPlayerView(state: unknown): state is PlayerView {\n return typeof state === \"object\" && state !== null && \"myColor\" in state;\n}\n\n// ── Clock Display ──\n\nfunction formatTime(ms: number): string {\n if (ms <= 0) return \"0:00\";\n const totalSeconds = Math.ceil(ms / 1000);\n const minutes = Math.floor(totalSeconds / 60);\n const seconds = totalSeconds % 60;\n if (minutes >= 60) {\n const hours = Math.floor(minutes / 60);\n const mins = minutes % 60;\n return `${hours}:${mins.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`;\n }\n return `${minutes}:${seconds.toString().padStart(2, \"0\")}`;\n}\n\nfunction ChessClock({ time, isActive, isLow, label }: {\n time: number;\n isActive: boolean;\n isLow: boolean;\n label: string;\n}) {\n return (\n <div className={`flex items-center gap-2 px-3 py-2 rounded-lg font-mono text-lg transition-colors ${\n isActive\n ? isLow\n ? \"bg-destructive/15 text-destructive\"\n : \"bg-primary/15 text-primary\"\n : \"bg-card text-text-tertiary\"\n }`}>\n <Clock className=\"w-4 h-4 opacity-60\" />\n <span className=\"font-semibold tabular-nums\">{formatTime(time)}</span>\n <span className=\"text-xs opacity-50 font-label\">{label}</span>\n </div>\n );\n}\n\n// ── Move History ──\n\nfunction MoveHistory({ moves, containerRef }: {\n moves: { san: string; color: \"w\" | \"b\" }[];\n containerRef: React.RefObject<HTMLDivElement | null>;\n}) {\n const pairs: { number: number; white?: string; black?: string }[] = [];\n for (let i = 0; i < moves.length; i++) {\n const moveNum = Math.floor(i / 2) + 1;\n if (i % 2 === 0) {\n pairs.push({ number: moveNum, white: moves[i]!.san });\n } else {\n const\n... [truncated]\n\n--- Reading panel/src/games/chess/pieces.tsx ---\n/**\n * Inline SVG chess pieces (cburnett set from Lichess, CC BY-SA).\n *\n * These are rendered as native <svg> JSX — not <img> tags — so they live in\n * the same React/DOM tree as react-chessboard's Piece wrapper and don't\n * interfere with dnd-kit's pointer-event pipeline.\n */\n\nimport type { PieceRenderObject } from \"react-chessboard\";\n\ntype PieceProps = { svgStyle?: React.CSSProperties };\n\nfunction svg(children: React.ReactNode) {\n return (props?: PieceProps) => (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 45 45\"\n width=\"100%\" height=\"100%\" style={props?.svgStyle}>\n {children}\n </svg>\n );\n}\n\nexport const chessPieces: PieceRenderObject = {\n // ── White ──\n\n wP: svg(\n <path fill=\"#fff\" stroke=\"#000\" strokeLinecap=\"round\" strokeWidth=\"1.5\"\n d=\"M22.5 9c-2.21 0-4 1.79-4 4 0 .89.29 1.71.78 2.38C17.33 16.5 16 18.59 16 21c0 2.03.94 3.84 2.41 5.03-3 1.06-7.41 5.55-7.41 13.47h23c0-7.92-4.41-12.41-7.41-13.47 1.47-1.19 2.41-3 2.41-5.03 0-2.41-1.33-4.5-3.28-5.62.49-.67.78-1.49.78-2.38 0-2.21-1.79-4-4-4z\" />\n ),\n\n wR: svg(\n <g fill=\"#fff\" fillRule=\"evenodd\" stroke=\"#000\" strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"1.5\">\n <path strokeLinecap=\"butt\" d=\"M9 39h27v-3H9zm3-3v-4h21v4zm-1-22V9h4v2h5V9h5v2h5V9h4v5\" />\n <path d=\"m34 14-3 3H14l-3-3\" />\n <path strokeLinecap=\"butt\" strokeLinejoin=\"miter\" d=\"M31 17v12.5H14V17\" />\n <path d=\"m31 29.5 1.5 2.5h-20l1.5-2.5\" />\n <path fill=\"none\" strokeLinejoin=\"miter\" d=\"M11 14h23\" />\n </g>\n ),\n\n wN: svg(\n <g fill=\"none\" fillRule=\"evenodd\" stroke=\"#000\" strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"1.5\">\n <path fill=\"#fff\" d=\"M22 10c10.5 1 16.5 8 16 29H15c0-9 10-6.5 8-21\" />\n <path fill=\"#fff\" d=\"M24 18c.38 2.91-5.55 7.37-8 9-3 2-2.82 4.34-5 4-1.042-.94 1.41-3.04 0-3-1 0 .19 1.23-1 2-1 0-4.003 1-4-4 0-2 6-12 6-12s1.89-1.9 2-3.5c-.73-.994-.5-2-.5-3 1-1 3 2.5 3 2.5h2s.78-1.992 2.5-3c1 0 1 3 1 3\" />\n <path fill=\"#000\" d=\"M9.5 25.5a.5.5 0 1 1-1 0 .5.5 0 1 1 1 0m5.433-9.75a.5 1.5 30 1 1-.866-.5.5 1.5 30 1 1 .866.5\" />\n </g>\n ),\n\n wB: svg(\n <g fill=\"none\" fillRule=\"evenodd\" stroke=\"#000\" strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth=\"1.5\">\n <g fill=\"#fff\" strokeLinecap=\"butt\">\n <path d=\"M9 36c3.39-.97 10.11.43 13.5-2 3.39 2.43 10.11 1.03 13.5 2 0 0 1.65.54 3 2-.68.97-1.65.99-3 .5-3.39-.97-10.11.46-13.5-1-3.39 1.46-10.11.03-13.5 1-1.35.49-2.32.47-3-.5 1.35-1.94 3-2 3-2z\" />\n <path d=\"M15 32c2.5 2.5 12.5 2.5 15 0 .5-1.5 0-2 0-2 0-2.5-2.5-4-2.5-4 5.5-1.5 6-11.5-5-15.5-11 4-10.5 14-5 15.5 0 0-2.5 1.5-2.5 4 0 0-.5.5 0 2z\" />\n <path d=\"M25 8a2.5 2.5 0 1 1-5 0 2.5 2.5 0 1 1 5 0z\" />\n </g>\n <path strokeLinejoin=\"miter\" d=\"M17.5 26h10M15 30h15m-7.5-14.5v5M20 18h5\" />\n </g>\n ),\n\n wQ: svg(\n <g fil\n... [truncated]\n\n--- Reading bot/lib/embeds.ts ---\nimport { Colors, type ColorResolvable, EmbedBuilder } from \"discord.js\";\nimport { BRANDING } from \"@shared/lib/constants\";\nimport pkg from \"../../package.json\";\n\n/**\n * Applies standard branding to an embed.\n */\nfunction applyBranding(embed: EmbedBuilder): EmbedBuilder {\n return embed.setFooter({ \n text: `${BRANDING.FOOTER_TEXT} v${pkg.version}` \n });\n}\n\n/**\n * Creates a standardized error embed.\n * @param message The error message to display.\n * @param title Optional title for the embed. Defaults to \"Error\".\n * @returns An EmbedBuilder instance configured as an error.\n */\nexport function createErrorEmbed(message: string, title: string = \"Error\"): EmbedBuilder {\n const embed = new EmbedBuilder()\n .setTitle(`❌ ${title}`)\n .setDescription(message)\n .setColor(Colors.Red)\n .setTimestamp();\n \n return applyBranding(embed);\n}\n\n/**\n * Creates a standardized warning embed.\n * @param message The warning message to display.\n * @param title Optional title for the embed. Defaults to \"Warning\".\n * @returns An EmbedBuilder instance configured as a warning.\n */\nexport function createWarningEmbed(message: string, title: string = \"Warning\"): EmbedBuilder {\n const embed = new EmbedBuilder()\n .setTitle(`⚠️ ${title}`)\n .setDescription(message)\n .setColor(Colors.Yellow)\n .setTimestamp();\n\n return applyBranding(embed);\n}\n\n/**\n * Creates a standardized success embed.\n * @param message The success message to display.\n * @param title Optional title for the embed. Defaults to \"Success\".\n * @returns An EmbedBuilder instance configured as a success.\n */\nexport function createSuccessEmbed(message: string, title: string = \"Success\"): EmbedBuilder {\n const embed = new EmbedBuilder()\n .setTitle(`✅ ${title}`)\n .setDescription(message)\n .setColor(Colors.Green)\n .setTimestamp();\n\n return applyBranding(embed);\n}\n\n/**\n * Creates a standardized info embed.\n * @param message The info message to display.\n * @param title Optional title for the embed. Defaults to \"Info\".\n * @returns An EmbedBuilder instance configured as info.\n */\nexport function createInfoEmbed(message: string, title: string = \"Info\"): EmbedBuilder {\n const embed = new EmbedBuilder()\n .setTitle(`ℹ️ ${title}`)\n .setDescription(message)\n .setColor(Colors.Blue)\n .setTimestamp();\n\n return applyBranding(embed);\n}\n\n/**\n * Creates a standardized base embed with common configuration.\n * @param title Optional title for the embed.\n * @param description Optional description for the embed.\n * @param color Optional color for the embed.\n * @returns An EmbedBuilder instance with base configuration.\n */\nexport function createBaseEmbed(title?: string, description?: string, color?: ColorResolvable): EmbedBuilder {\n const embed = new EmbedBuilder()\n .setTimestamp()\n .setColor(color ?? BRANDING.COLOR);\n\n if (title) embed.setTitle(title);\n if (description) embed.setDesc\n... [truncated]\n",
|
||
"exitCode": 0,
|
||
"durationMs": 23
|
||
} |