diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-02-14 20:32:47 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-02-14 20:32:47 +0900 |
| commit | 9185367fcd7d95af89fac36dd892d8b064dbd94f (patch) | |
| tree | 6085f0c4ab695d0f83348f32b49b5481f1da6548 /frontend/app/api/schema.d.ts | |
| parent | 6bd35e345a4c5d74578b0f8a5c969027e7e15f02 (diff) | |
| download | phperkaigi-2026-albatross-9185367fcd7d95af89fac36dd892d8b064dbd94f.tar.gz phperkaigi-2026-albatross-9185367fcd7d95af89fac36dd892d8b064dbd94f.tar.zst phperkaigi-2026-albatross-9185367fcd7d95af89fac36dd892d8b064dbd94f.zip | |
feat(openapi): generate OpenAPI specs from TypeSpec sources
Migrate hand-written OpenAPI YAML to TypeSpec (.tsp) source files.
TypeSpec compiles to OpenAPI 3.0 YAML, enabling type-safe API definitions.
- Add typespec/ directory with api-server and fortee definitions
- Integrate TypeSpec build into `just gen` and `just build` pipelines
- Update backend handler code to match new generated type names
(inlined error responses, separate GameType/ProblemLanguage enums)
- Regenerate frontend TypeScript types from new OpenAPI output
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'frontend/app/api/schema.d.ts')
| -rw-r--r-- | frontend/app/api/schema.d.ts | 589 |
1 files changed, 355 insertions, 234 deletions
diff --git a/frontend/app/api/schema.d.ts b/frontend/app/api/schema.d.ts index 6f9e270..6d27df0 100644 --- a/frontend/app/api/schema.d.ts +++ b/frontend/app/api/schema.d.ts @@ -4,66 +4,62 @@ */ export interface paths { - "/login": { + "/games": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get?: never; + get: operations["getGames"]; put?: never; - /** User login */ - post: operations["postLogin"]; + post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/logout": { + "/games/{game_id}": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get?: never; + get: operations["getGame"]; put?: never; - /** User logout */ - post: operations["postLogout"]; + post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/me": { + "/games/{game_id}/play/code": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get current user */ - get: operations["getMe"]; + get?: never; put?: never; - post?: never; + post: operations["postGamePlayCode"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/games": { + "/games/{game_id}/play/latest_state": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** List games */ - get: operations["getGames"]; + get: operations["getGamePlayLatestState"]; put?: never; post?: never; delete?: never; @@ -72,32 +68,30 @@ export interface paths { patch?: never; trace?: never; }; - "/games/{game_id}": { + "/games/{game_id}/play/submit": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get a game */ - get: operations["getGame"]; + get?: never; put?: never; - post?: never; + post: operations["postGamePlaySubmit"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/games/{game_id}/play/latest_state": { + "/games/{game_id}/watch/latest_states": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get the latest execution result for player */ - get: operations["getGamePlayLatestState"]; + get: operations["getGameWatchLatestStates"]; put?: never; post?: never; delete?: never; @@ -106,24 +100,23 @@ export interface paths { patch?: never; trace?: never; }; - "/games/{game_id}/play/code": { + "/games/{game_id}/watch/ranking": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - get?: never; + get: operations["getGameWatchRanking"]; put?: never; - /** Post the latest code */ - post: operations["postGamePlayCode"]; + post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/games/{game_id}/play/submit": { + "/login": { parameters: { query?: never; header?: never; @@ -132,40 +125,37 @@ export interface paths { }; get?: never; put?: never; - /** Submit the answer */ - post: operations["postGamePlaySubmit"]; + post: operations["postLogin"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/games/{game_id}/watch/ranking": { + "/logout": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get the latest player ranking */ - get: operations["getGameWatchRanking"]; + get?: never; put?: never; - post?: never; + post: operations["postLogout"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; - "/games/{game_id}/watch/latest_states": { + "/me": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - /** Get all the latest game states of the main players */ - get: operations["getGameWatchLatestStates"]; + get: operations["getMe"]; put?: never; post?: never; delete?: never; @@ -181,7 +171,6 @@ export interface paths { path?: never; cookie?: never; }; - /** Get tournament bracket data */ get: operations["getTournament"]; put?: never; post?: never; @@ -196,409 +185,517 @@ export type webhooks = Record<string, never>; export interface components { schemas: { Error: { - /** @example Invalid request */ message: string; }; - User: { - /** @example 123 */ - user_id: number; - /** @example john */ - username: string; - /** @example John Doe */ - display_name: string; - /** @example /images/john.jpg */ - icon_path?: string; - /** @example false */ - is_admin: boolean; - /** @example staff */ - label: string | null; - }; + /** @enum {string} */ + ExecutionStatus: "none" | "running" | "success" | "wrong_answer" | "timeout" | "compile_error" | "runtime_error" | "internal_error"; Game: { - /** @example 1 */ game_id: number; - /** - * @example 1v1 - * @enum {string} - */ - game_type: "1v1" | "multiplayer"; - /** @example true */ + game_type: components["schemas"]["GameType"]; is_public: boolean; - /** @example Game 1 */ display_name: string; - /** @example 360 */ duration_seconds: number; - /** @example 946684800 */ started_at?: number; problem: components["schemas"]["Problem"]; main_players: components["schemas"]["User"][]; }; - Problem: { - /** @example 1 */ - problem_id: number; - /** @example Problem 1 */ - title: string; - /** @example This is a problem */ - description: string; - /** - * @example php - * @enum {string} - */ - language: "php" | "swift"; - /** @example echo 'hello world'; */ - sample_code: string; - }; - /** - * @example success - * @enum {string} - */ - ExecutionStatus: "none" | "running" | "success" | "wrong_answer" | "timeout" | "compile_error" | "runtime_error" | "internal_error"; + /** @enum {string} */ + GameType: "1v1" | "multiplayer"; LatestGameState: { - /** @example echo 'hello world'; */ code: string; - /** @example 100 */ score: number | null; - /** @example 946684800 */ best_score_submitted_at: number | null; status: components["schemas"]["ExecutionStatus"]; }; + Problem: { + problem_id: number; + title: string; + description: string; + language: components["schemas"]["ProblemLanguage"]; + sample_code: string; + }; + /** @enum {string} */ + ProblemLanguage: "php" | "swift"; RankingEntry: { player: components["schemas"]["User"]; - /** @example 100 */ score: number; - /** @example 946684800 */ submitted_at: number; - /** @example echo 'hello world'; */ code: string | null; }; Tournament: { matches: components["schemas"]["TournamentMatch"][]; }; TournamentMatch: { - /** @example 1 */ game_id: number; player1?: components["schemas"]["User"]; player2?: components["schemas"]["User"]; - /** @example 1 */ player1_score?: number; - /** @example 1 */ player2_score?: number; - /** @example 1 */ winner?: number; }; - }; - responses: { - /** @description Bad request */ - BadRequest: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Error"]; - }; - }; - /** @description Unauthorized */ - Unauthorized: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Error"]; - }; - }; - /** @description Forbidden */ - Forbidden: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Error"]; - }; - }; - /** @description Not found */ - NotFound: { - headers: { - [name: string]: unknown; - }; - content: { - "application/json": components["schemas"]["Error"]; - }; + User: { + user_id: number; + username: string; + display_name: string; + icon_path?: string; + is_admin: boolean; + label: string | null; }; }; - parameters: { - path_game_id: number; - }; + responses: never; + parameters: never; requestBodies: never; headers: never; pathItems: never; } export type $defs = Record<string, never>; export interface operations { - postLogin: { + getGames: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; - requestBody: { - content: { - "application/json": { - /** @example john */ - username: string; - /** @example password123 */ - password: string; - }; - }; - }; + requestBody?: never; responses: { - /** @description Successfully authenticated */ + /** @description The request has succeeded. */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": { - user: components["schemas"]["User"]; + games: components["schemas"]["Game"][]; }; }; }; - 401: components["responses"]["Unauthorized"]; + /** @description Access is unauthorized. */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description Access is forbidden. */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; }; }; - postLogout: { + getGame: { parameters: { query?: never; header?: never; - path?: never; + path: { + game_id: number; + }; cookie?: never; }; requestBody?: never; responses: { - /** @description Successfully logged out */ + /** @description The request has succeeded. */ 200: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": { + game: components["schemas"]["Game"]; + }; + }; + }; + /** @description Access is unauthorized. */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description Access is forbidden. */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description The server cannot find the requested resource. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; }; - 401: components["responses"]["Unauthorized"]; }; }; - getMe: { + postGamePlayCode: { parameters: { query?: never; header?: never; - path?: never; + path: { + game_id: number; + }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": { + code: string; + }; + }; + }; responses: { - /** @description Current user info */ + /** @description The request has succeeded. */ 200: { headers: { [name: string]: unknown; }; + content?: never; + }; + /** @description Access is unauthorized. */ + 401: { + headers: { + [name: string]: unknown; + }; content: { - "application/json": { - user: components["schemas"]["User"]; - }; + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description Access is forbidden. */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description The server cannot find the requested resource. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; }; }; - 401: components["responses"]["Unauthorized"]; }; }; - getGames: { + getGamePlayLatestState: { parameters: { query?: never; header?: never; - path?: never; + path: { + game_id: number; + }; cookie?: never; }; requestBody?: never; responses: { - /** @description List of games */ + /** @description The request has succeeded. */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": { - games: components["schemas"]["Game"][]; + state: components["schemas"]["LatestGameState"]; }; }; }; - 401: components["responses"]["Unauthorized"]; - 403: components["responses"]["Forbidden"]; + /** @description Access is unauthorized. */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description Access is forbidden. */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description The server cannot find the requested resource. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; }; }; - getGame: { + postGamePlaySubmit: { parameters: { query?: never; header?: never; path: { - game_id: components["parameters"]["path_game_id"]; + game_id: number; }; cookie?: never; }; - requestBody?: never; + requestBody: { + content: { + "application/json": { + code: string; + }; + }; + }; responses: { - /** @description A game */ + /** @description The request has succeeded. */ 200: { headers: { [name: string]: unknown; }; + content?: never; + }; + /** @description Access is unauthorized. */ + 401: { + headers: { + [name: string]: unknown; + }; content: { - "application/json": { - game: components["schemas"]["Game"]; - }; + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description Access is forbidden. */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description The server cannot find the requested resource. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; }; }; - 401: components["responses"]["Unauthorized"]; - 403: components["responses"]["Forbidden"]; - 404: components["responses"]["NotFound"]; }; }; - getGamePlayLatestState: { + getGameWatchLatestStates: { parameters: { query?: never; header?: never; path: { - game_id: components["parameters"]["path_game_id"]; + game_id: number; }; cookie?: never; }; requestBody?: never; responses: { - /** @description Your latest game state */ + /** @description The request has succeeded. */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": { - state: components["schemas"]["LatestGameState"]; + states: { + [key: string]: components["schemas"]["LatestGameState"]; + }; }; }; }; - 401: components["responses"]["Unauthorized"]; - 403: components["responses"]["Forbidden"]; - 404: components["responses"]["NotFound"]; + /** @description Access is unauthorized. */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description Access is forbidden. */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description The server cannot find the requested resource. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; }; }; - postGamePlayCode: { + getGameWatchRanking: { parameters: { query?: never; header?: never; path: { - game_id: components["parameters"]["path_game_id"]; + game_id: number; }; cookie?: never; }; - requestBody: { - content: { - "application/json": { - /** @example echo 'hello world'; */ - code: string; - }; - }; - }; + requestBody?: never; responses: { - /** @description Successfully updated */ + /** @description The request has succeeded. */ 200: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": { + ranking: components["schemas"]["RankingEntry"][]; + }; + }; + }; + /** @description Access is unauthorized. */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description Access is forbidden. */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description The server cannot find the requested resource. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; }; - 401: components["responses"]["Unauthorized"]; - 403: components["responses"]["Forbidden"]; - 404: components["responses"]["NotFound"]; }; }; - postGamePlaySubmit: { + postLogin: { parameters: { query?: never; header?: never; - path: { - game_id: components["parameters"]["path_game_id"]; - }; + path?: never; cookie?: never; }; requestBody: { content: { "application/json": { - /** @example echo 'hello world'; */ - code: string; + username: string; + password: string; }; }; }; responses: { - /** @description Successfully submitted */ + /** @description The request has succeeded. */ 200: { headers: { [name: string]: unknown; }; - content?: never; + content: { + "application/json": { + user: components["schemas"]["User"]; + }; + }; + }; + /** @description Access is unauthorized. */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; }; - 401: components["responses"]["Unauthorized"]; - 403: components["responses"]["Forbidden"]; - 404: components["responses"]["NotFound"]; }; }; - getGameWatchRanking: { + postLogout: { parameters: { query?: never; header?: never; - path: { - game_id: components["parameters"]["path_game_id"]; - }; + path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description Player ranking */ + /** @description The request has succeeded. */ 200: { headers: { [name: string]: unknown; }; + content?: never; + }; + /** @description Access is unauthorized. */ + 401: { + headers: { + [name: string]: unknown; + }; content: { - "application/json": { - ranking: components["schemas"]["RankingEntry"][]; - }; + "application/json": components["schemas"]["Error"]; }; }; - 401: components["responses"]["Unauthorized"]; - 403: components["responses"]["Forbidden"]; - 404: components["responses"]["NotFound"]; }; }; - getGameWatchLatestStates: { + getMe: { parameters: { query?: never; header?: never; - path: { - game_id: components["parameters"]["path_game_id"]; - }; + path?: never; cookie?: never; }; requestBody?: never; responses: { - /** @description All the latest game states of the main players */ + /** @description The request has succeeded. */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": { - states: { - [key: string]: components["schemas"]["LatestGameState"]; - }; + user: components["schemas"]["User"]; }; }; }; - 401: components["responses"]["Unauthorized"]; - 403: components["responses"]["Forbidden"]; - 404: components["responses"]["NotFound"]; + /** @description Access is unauthorized. */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; }; }; getTournament: { @@ -616,7 +713,7 @@ export interface operations { }; requestBody?: never; responses: { - /** @description Tournament data */ + /** @description The request has succeeded. */ 200: { headers: { [name: string]: unknown; @@ -627,9 +724,33 @@ export interface operations { }; }; }; - 401: components["responses"]["Unauthorized"]; - 403: components["responses"]["Forbidden"]; - 404: components["responses"]["NotFound"]; + /** @description Access is unauthorized. */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description Access is forbidden. */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; + /** @description The server cannot find the requested resource. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["Error"]; + }; + }; }; }; } |
