From 729bd4e58ebfc1a46fa69f09179effe83b5b28cb Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 11 Aug 2024 12:10:06 +0900 Subject: refactor: move openapi.yaml to openapi/ --- backend/gen/gen.go | 2 +- backend/gen/oapi-codegen.api-server.yaml | 11 + backend/gen/oapi-codegen.yaml | 11 - frontend/package.json | 2 +- openapi.yaml | 551 ------------------------------- openapi/api-server.yaml | 551 +++++++++++++++++++++++++++++++ 6 files changed, 564 insertions(+), 564 deletions(-) create mode 100644 backend/gen/oapi-codegen.api-server.yaml delete mode 100644 backend/gen/oapi-codegen.yaml delete mode 100644 openapi.yaml create mode 100644 openapi/api-server.yaml diff --git a/backend/gen/gen.go b/backend/gen/gen.go index 276bc05..2b39122 100644 --- a/backend/gen/gen.go +++ b/backend/gen/gen.go @@ -1,6 +1,6 @@ package gen //go:generate go run github.com/sqlc-dev/sqlc/cmd/sqlc generate -//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config oapi-codegen.yaml ../../openapi.yaml +//go:generate go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen -config oapi-codegen.api-server.yaml ../../openapi/api-server.yaml //go:generate go run ./api/handler_wrapper_gen.go -i ../api/generated.go -o ../api/handler_wrapper.go //go:generate go run ./taskqueue/processor_wrapper_gen.go -i ../taskqueue/tasks.go -o ../taskqueue/processor_wrapper.go diff --git a/backend/gen/oapi-codegen.api-server.yaml b/backend/gen/oapi-codegen.api-server.yaml new file mode 100644 index 0000000..a581c6c --- /dev/null +++ b/backend/gen/oapi-codegen.api-server.yaml @@ -0,0 +1,11 @@ +package: api +generate: + models: true + echo-server: true + strict-server: true + embedded-spec: true +output: ../api/generated.go +output-options: + skip-prune: true + nullable-type: true + name-normalizer: ToCamelCaseWithInitialisms diff --git a/backend/gen/oapi-codegen.yaml b/backend/gen/oapi-codegen.yaml deleted file mode 100644 index a581c6c..0000000 --- a/backend/gen/oapi-codegen.yaml +++ /dev/null @@ -1,11 +0,0 @@ -package: api -generate: - models: true - echo-server: true - strict-server: true - embedded-spec: true -output: ../api/generated.go -output-options: - skip-prune: true - nullable-type: true - name-normalizer: ToCamelCaseWithInitialisms diff --git a/frontend/package.json b/frontend/package.json index 4c630a0..b8b9e93 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,7 +10,7 @@ "check:eslint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "check:ts": "tsc", "dev": "remix vite:dev", - "openapi-typescript": "openapi-typescript --output ./app/.server/api/schema.d.ts ../openapi.yaml", + "openapi-typescript": "openapi-typescript --output ./app/.server/api/schema.d.ts ../openapi/api-server.yaml", "start": "remix-serve ./build/server/index.js" }, "dependencies": { diff --git a/openapi.yaml b/openapi.yaml deleted file mode 100644 index 54f9f3c..0000000 --- a/openapi.yaml +++ /dev/null @@ -1,551 +0,0 @@ -openapi: 3.0.0 -info: - title: Albatross internal web API - version: 0.1.0 -paths: - /login: - post: - operationId: postLogin - summary: User login - requestBody: - required: true - content: - application/json: - schema: - type: object - properties: - username: - type: string - example: "john" - password: - type: string - example: "password123" - registration_token: - type: string - example: "xxxxxxxxxxxxxxxx" - required: - - username - - password - responses: - '200': - description: Successfully authenticated - content: - application/json: - schema: - type: object - properties: - token: - type: string - example: "xxxxx.xxxxx.xxxxx" - required: - - token - '401': - $ref: '#/components/responses/Unauthorized' - /token: - get: - operationId: getToken - summary: Get a short-lived access token - parameters: - - $ref: '#/components/parameters/header_authorization' - responses: - '200': - description: Successfully authenticated - content: - application/json: - schema: - type: object - properties: - token: - type: string - example: "xxxxx.xxxxx.xxxxx" - required: - - token - '401': - $ref: '#/components/responses/Unauthorized' - /games: - get: - operationId: getGames - summary: List games - parameters: - - $ref: '#/components/parameters/header_authorization' - responses: - '200': - description: List of games - content: - application/json: - schema: - type: object - properties: - games: - type: array - items: - $ref: '#/components/schemas/Game' - required: - - games - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - /games/{game_id}: - get: - operationId: getGame - summary: Get a game - parameters: - - $ref: '#/components/parameters/header_authorization' - - $ref: '#/components/parameters/path_game_id' - responses: - '200': - description: A game - content: - application/json: - schema: - type: object - properties: - game: - $ref: '#/components/schemas/Game' - required: - - game - '401': - $ref: '#/components/responses/Unauthorized' - '403': - $ref: '#/components/responses/Forbidden' - '404': - $ref: '#/components/responses/NotFound' -components: - parameters: - header_authorization: - in: header - name: Authorization - schema: - type: string - required: true - path_game_id: - in: path - name: game_id - schema: - type: integer - required: true - responses: - BadRequest: - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - Unauthorized: - description: Unauthorized - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - Forbidden: - description: Forbidden - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - NotFound: - description: Not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - schemas: - Error: - type: object - properties: - message: - type: string - example: "Invalid request" - required: - - message - User: - type: object - properties: - user_id: - type: integer - example: 123 - username: - type: string - example: "john" - display_name: - type: string - example: "John Doe" - icon_path: - type: string - example: "/images/john.jpg" - is_admin: - type: boolean - example: false - required: - - user_id - - username - - display_name - - is_admin - Game: - type: object - properties: - game_id: - type: integer - example: 1 - game_type: - type: string - example: "1v1" - enum: - - 1v1 - - multiplayer - state: - type: string - example: "closed" - enum: - - closed - - waiting_entries - - waiting_start - - prepare - - starting - - gaming - - finished - display_name: - type: string - example: "Game 1" - duration_seconds: - type: integer - example: 360 - started_at: - type: integer - example: 946684800 - problem: - $ref: '#/components/schemas/Problem' - players: - type: array - items: - $ref: '#/components/schemas/User' - verification_steps: - type: array - items: - $ref: '#/components/schemas/VerificationStep' - required: - - game_id - - game_type - - state - - display_name - - duration_seconds - - players - - verification_steps - VerificationStep: - type: object - properties: - testcase_id: - type: integer - nullable: true - example: 1 - label: - type: string - example: "Test case 1" - required: - - testcase_id - - label - Problem: - type: object - properties: - problem_id: - type: integer - example: 1 - title: - type: string - example: "Problem 1" - description: - type: string - example: "This is a problem" - required: - - problem_id - - title - - description - GamePlayerMessage: - oneOf: - - $ref: '#/components/schemas/GamePlayerMessageS2C' - - $ref: '#/components/schemas/GamePlayerMessageC2S' - GamePlayerMessageS2C: - oneOf: - - $ref: '#/components/schemas/GamePlayerMessageS2CPrepare' - - $ref: '#/components/schemas/GamePlayerMessageS2CStart' - - $ref: '#/components/schemas/GamePlayerMessageS2CExecResult' - GamePlayerMessageS2CPrepare: - type: object - properties: - type: - type: string - const: "player:s2c:prepare" - data: - $ref: '#/components/schemas/GamePlayerMessageS2CPreparePayload' - required: - - type - - data - GamePlayerMessageS2CPreparePayload: - type: object - properties: - problem: - $ref: '#/components/schemas/Problem' - required: - - problem - GamePlayerMessageS2CStart: - type: object - properties: - type: - type: string - const: "player:s2c:start" - data: - $ref: '#/components/schemas/GamePlayerMessageS2CStartPayload' - required: - - type - - data - GamePlayerMessageS2CStartPayload: - type: object - properties: - start_at: - type: integer - example: 946684800 - required: - - start_at - GamePlayerMessageS2CExecResult: - type: object - properties: - type: - type: string - const: "player:s2c:execresult" - data: - $ref: '#/components/schemas/GamePlayerMessageS2CExecResultPayload' - required: - - type - - data - GamePlayerMessageS2CExecResultPayload: - type: object - properties: - status: - type: string - example: "success" - enum: - - success - - failure - - timeout - - internal_error - - compile_error - - wrong_answer - score: - type: integer - nullable: true - example: 100 - required: - - status - - score - GamePlayerMessageC2S: - oneOf: - - $ref: '#/components/schemas/GamePlayerMessageC2SEntry' - - $ref: '#/components/schemas/GamePlayerMessageC2SReady' - - $ref: '#/components/schemas/GamePlayerMessageC2SCode' - - $ref: '#/components/schemas/GamePlayerMessageC2SSubmit' - GamePlayerMessageC2SEntry: - type: object - properties: - type: - type: string - const: "player:c2s:entry" - required: - - type - GamePlayerMessageC2SReady: - type: object - properties: - type: - type: string - const: "player:c2s:ready" - required: - - type - GamePlayerMessageC2SCode: - type: object - properties: - type: - type: string - const: "player:c2s:code" - data: - $ref: '#/components/schemas/GamePlayerMessageC2SCodePayload' - required: - - type - - data - GamePlayerMessageC2SCodePayload: - type: object - properties: - code: - type: string - example: "print('Hello, world!')" - required: - - code - GamePlayerMessageC2SSubmit: - type: object - properties: - type: - type: string - const: "player:c2s:submit" - data: - $ref: '#/components/schemas/GamePlayerMessageC2SSubmitPayload' - required: - - type - - data - GamePlayerMessageC2SSubmitPayload: - type: object - properties: - code: - type: string - example: "print('Hello, world!')" - required: - - code - GameWatcherMessage: - oneOf: - - $ref: '#/components/schemas/GameWatcherMessageS2C' - # - $ref: '#/components/schemas/GameWatcherMessageC2S' - GameWatcherMessageS2C: - oneOf: - - $ref: '#/components/schemas/GameWatcherMessageS2CStart' - - $ref: '#/components/schemas/GameWatcherMessageS2CCode' - - $ref: '#/components/schemas/GameWatcherMessageS2CSubmit' - - $ref: '#/components/schemas/GameWatcherMessageS2CExecResult' - - $ref: '#/components/schemas/GameWatcherMessageS2CSubmitResult' - GameWatcherMessageS2CStart: - type: object - properties: - type: - type: string - const: "watcher:s2c:start" - data: - $ref: '#/components/schemas/GameWatcherMessageS2CStartPayload' - required: - - type - - data - GameWatcherMessageS2CStartPayload: - type: object - properties: - start_at: - type: integer - example: 946684800 - required: - - start_at - GameWatcherMessageS2CCode: - type: object - properties: - type: - type: string - const: "watcher:s2c:code" - data: - $ref: '#/components/schemas/GameWatcherMessageS2CCodePayload' - required: - - type - - data - GameWatcherMessageS2CCodePayload: - type: object - properties: - player_id: - type: integer - example: 1 - code: - type: string - example: "print('Hello, world!')" - required: - - player_id - - code - GameWatcherMessageS2CSubmit: - type: object - properties: - type: - type: string - const: "watcher:s2c:submit" - data: - $ref: '#/components/schemas/GameWatcherMessageS2CSubmitPayload' - required: - - type - - data - GameWatcherMessageS2CSubmitPayload: - type: object - properties: - player_id: - type: integer - example: 1 - preliminary_score: - type: integer - example: 100 - required: - - player_id - - preliminary_score - GameWatcherMessageS2CExecResult: - type: object - properties: - type: - type: string - const: "watcher:s2c:execresult" - data: - $ref: '#/components/schemas/GameWatcherMessageS2CExecResultPayload' - required: - - type - - data - GameWatcherMessageS2CExecResultPayload: - type: object - properties: - player_id: - type: integer - example: 1 - testcase_id: - type: integer - nullable: true - example: 1 - status: - type: string - example: "success" - enum: - - success - - wrong_answer - - timeout - - runtime_error - - internal_error - - compile_error - stdout: - type: string - example: "Hello, world!" - stderr: - type: string - example: "" - required: - - player_id - - testcase_id - - status - - stdout - - stderr - GameWatcherMessageS2CSubmitResult: - type: object - properties: - type: - type: string - const: "watcher:s2c:submitresult" - data: - $ref: '#/components/schemas/GameWatcherMessageS2CSubmitResultPayload' - required: - - type - - data - GameWatcherMessageS2CSubmitResultPayload: - type: object - properties: - player_id: - type: integer - example: 1 - status: - type: string - example: "success" - enum: - - success - - wrong_answer - - timeout - - runtime_error - - internal_error - - compile_error - required: - - player_id - - status - # GameWatcherMessageC2S: - # oneOf: diff --git a/openapi/api-server.yaml b/openapi/api-server.yaml new file mode 100644 index 0000000..54f9f3c --- /dev/null +++ b/openapi/api-server.yaml @@ -0,0 +1,551 @@ +openapi: 3.0.0 +info: + title: Albatross internal web API + version: 0.1.0 +paths: + /login: + post: + operationId: postLogin + summary: User login + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + username: + type: string + example: "john" + password: + type: string + example: "password123" + registration_token: + type: string + example: "xxxxxxxxxxxxxxxx" + required: + - username + - password + responses: + '200': + description: Successfully authenticated + content: + application/json: + schema: + type: object + properties: + token: + type: string + example: "xxxxx.xxxxx.xxxxx" + required: + - token + '401': + $ref: '#/components/responses/Unauthorized' + /token: + get: + operationId: getToken + summary: Get a short-lived access token + parameters: + - $ref: '#/components/parameters/header_authorization' + responses: + '200': + description: Successfully authenticated + content: + application/json: + schema: + type: object + properties: + token: + type: string + example: "xxxxx.xxxxx.xxxxx" + required: + - token + '401': + $ref: '#/components/responses/Unauthorized' + /games: + get: + operationId: getGames + summary: List games + parameters: + - $ref: '#/components/parameters/header_authorization' + responses: + '200': + description: List of games + content: + application/json: + schema: + type: object + properties: + games: + type: array + items: + $ref: '#/components/schemas/Game' + required: + - games + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + /games/{game_id}: + get: + operationId: getGame + summary: Get a game + parameters: + - $ref: '#/components/parameters/header_authorization' + - $ref: '#/components/parameters/path_game_id' + responses: + '200': + description: A game + content: + application/json: + schema: + type: object + properties: + game: + $ref: '#/components/schemas/Game' + required: + - game + '401': + $ref: '#/components/responses/Unauthorized' + '403': + $ref: '#/components/responses/Forbidden' + '404': + $ref: '#/components/responses/NotFound' +components: + parameters: + header_authorization: + in: header + name: Authorization + schema: + type: string + required: true + path_game_id: + in: path + name: game_id + schema: + type: integer + required: true + responses: + BadRequest: + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + Unauthorized: + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + Forbidden: + description: Forbidden + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + NotFound: + description: Not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + schemas: + Error: + type: object + properties: + message: + type: string + example: "Invalid request" + required: + - message + User: + type: object + properties: + user_id: + type: integer + example: 123 + username: + type: string + example: "john" + display_name: + type: string + example: "John Doe" + icon_path: + type: string + example: "/images/john.jpg" + is_admin: + type: boolean + example: false + required: + - user_id + - username + - display_name + - is_admin + Game: + type: object + properties: + game_id: + type: integer + example: 1 + game_type: + type: string + example: "1v1" + enum: + - 1v1 + - multiplayer + state: + type: string + example: "closed" + enum: + - closed + - waiting_entries + - waiting_start + - prepare + - starting + - gaming + - finished + display_name: + type: string + example: "Game 1" + duration_seconds: + type: integer + example: 360 + started_at: + type: integer + example: 946684800 + problem: + $ref: '#/components/schemas/Problem' + players: + type: array + items: + $ref: '#/components/schemas/User' + verification_steps: + type: array + items: + $ref: '#/components/schemas/VerificationStep' + required: + - game_id + - game_type + - state + - display_name + - duration_seconds + - players + - verification_steps + VerificationStep: + type: object + properties: + testcase_id: + type: integer + nullable: true + example: 1 + label: + type: string + example: "Test case 1" + required: + - testcase_id + - label + Problem: + type: object + properties: + problem_id: + type: integer + example: 1 + title: + type: string + example: "Problem 1" + description: + type: string + example: "This is a problem" + required: + - problem_id + - title + - description + GamePlayerMessage: + oneOf: + - $ref: '#/components/schemas/GamePlayerMessageS2C' + - $ref: '#/components/schemas/GamePlayerMessageC2S' + GamePlayerMessageS2C: + oneOf: + - $ref: '#/components/schemas/GamePlayerMessageS2CPrepare' + - $ref: '#/components/schemas/GamePlayerMessageS2CStart' + - $ref: '#/components/schemas/GamePlayerMessageS2CExecResult' + GamePlayerMessageS2CPrepare: + type: object + properties: + type: + type: string + const: "player:s2c:prepare" + data: + $ref: '#/components/schemas/GamePlayerMessageS2CPreparePayload' + required: + - type + - data + GamePlayerMessageS2CPreparePayload: + type: object + properties: + problem: + $ref: '#/components/schemas/Problem' + required: + - problem + GamePlayerMessageS2CStart: + type: object + properties: + type: + type: string + const: "player:s2c:start" + data: + $ref: '#/components/schemas/GamePlayerMessageS2CStartPayload' + required: + - type + - data + GamePlayerMessageS2CStartPayload: + type: object + properties: + start_at: + type: integer + example: 946684800 + required: + - start_at + GamePlayerMessageS2CExecResult: + type: object + properties: + type: + type: string + const: "player:s2c:execresult" + data: + $ref: '#/components/schemas/GamePlayerMessageS2CExecResultPayload' + required: + - type + - data + GamePlayerMessageS2CExecResultPayload: + type: object + properties: + status: + type: string + example: "success" + enum: + - success + - failure + - timeout + - internal_error + - compile_error + - wrong_answer + score: + type: integer + nullable: true + example: 100 + required: + - status + - score + GamePlayerMessageC2S: + oneOf: + - $ref: '#/components/schemas/GamePlayerMessageC2SEntry' + - $ref: '#/components/schemas/GamePlayerMessageC2SReady' + - $ref: '#/components/schemas/GamePlayerMessageC2SCode' + - $ref: '#/components/schemas/GamePlayerMessageC2SSubmit' + GamePlayerMessageC2SEntry: + type: object + properties: + type: + type: string + const: "player:c2s:entry" + required: + - type + GamePlayerMessageC2SReady: + type: object + properties: + type: + type: string + const: "player:c2s:ready" + required: + - type + GamePlayerMessageC2SCode: + type: object + properties: + type: + type: string + const: "player:c2s:code" + data: + $ref: '#/components/schemas/GamePlayerMessageC2SCodePayload' + required: + - type + - data + GamePlayerMessageC2SCodePayload: + type: object + properties: + code: + type: string + example: "print('Hello, world!')" + required: + - code + GamePlayerMessageC2SSubmit: + type: object + properties: + type: + type: string + const: "player:c2s:submit" + data: + $ref: '#/components/schemas/GamePlayerMessageC2SSubmitPayload' + required: + - type + - data + GamePlayerMessageC2SSubmitPayload: + type: object + properties: + code: + type: string + example: "print('Hello, world!')" + required: + - code + GameWatcherMessage: + oneOf: + - $ref: '#/components/schemas/GameWatcherMessageS2C' + # - $ref: '#/components/schemas/GameWatcherMessageC2S' + GameWatcherMessageS2C: + oneOf: + - $ref: '#/components/schemas/GameWatcherMessageS2CStart' + - $ref: '#/components/schemas/GameWatcherMessageS2CCode' + - $ref: '#/components/schemas/GameWatcherMessageS2CSubmit' + - $ref: '#/components/schemas/GameWatcherMessageS2CExecResult' + - $ref: '#/components/schemas/GameWatcherMessageS2CSubmitResult' + GameWatcherMessageS2CStart: + type: object + properties: + type: + type: string + const: "watcher:s2c:start" + data: + $ref: '#/components/schemas/GameWatcherMessageS2CStartPayload' + required: + - type + - data + GameWatcherMessageS2CStartPayload: + type: object + properties: + start_at: + type: integer + example: 946684800 + required: + - start_at + GameWatcherMessageS2CCode: + type: object + properties: + type: + type: string + const: "watcher:s2c:code" + data: + $ref: '#/components/schemas/GameWatcherMessageS2CCodePayload' + required: + - type + - data + GameWatcherMessageS2CCodePayload: + type: object + properties: + player_id: + type: integer + example: 1 + code: + type: string + example: "print('Hello, world!')" + required: + - player_id + - code + GameWatcherMessageS2CSubmit: + type: object + properties: + type: + type: string + const: "watcher:s2c:submit" + data: + $ref: '#/components/schemas/GameWatcherMessageS2CSubmitPayload' + required: + - type + - data + GameWatcherMessageS2CSubmitPayload: + type: object + properties: + player_id: + type: integer + example: 1 + preliminary_score: + type: integer + example: 100 + required: + - player_id + - preliminary_score + GameWatcherMessageS2CExecResult: + type: object + properties: + type: + type: string + const: "watcher:s2c:execresult" + data: + $ref: '#/components/schemas/GameWatcherMessageS2CExecResultPayload' + required: + - type + - data + GameWatcherMessageS2CExecResultPayload: + type: object + properties: + player_id: + type: integer + example: 1 + testcase_id: + type: integer + nullable: true + example: 1 + status: + type: string + example: "success" + enum: + - success + - wrong_answer + - timeout + - runtime_error + - internal_error + - compile_error + stdout: + type: string + example: "Hello, world!" + stderr: + type: string + example: "" + required: + - player_id + - testcase_id + - status + - stdout + - stderr + GameWatcherMessageS2CSubmitResult: + type: object + properties: + type: + type: string + const: "watcher:s2c:submitresult" + data: + $ref: '#/components/schemas/GameWatcherMessageS2CSubmitResultPayload' + required: + - type + - data + GameWatcherMessageS2CSubmitResultPayload: + type: object + properties: + player_id: + type: integer + example: 1 + status: + type: string + example: "success" + enum: + - success + - wrong_answer + - timeout + - runtime_error + - internal_error + - compile_error + required: + - player_id + - status + # GameWatcherMessageC2S: + # oneOf: -- cgit v1.2.3-70-g09d2