Initialize project with basic structure, including Docker configuration, backend and frontend setup, environment configuration, and essential files for development.
This commit is contained in:
735
openapi/openapi.yaml
Normal file
735
openapi/openapi.yaml
Normal file
@@ -0,0 +1,735 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: Mixmaker API
|
||||
version: 0.1.0
|
||||
description: API for Overwatch community scrims.
|
||||
servers:
|
||||
- url: /
|
||||
security:
|
||||
- cookieAuth: []
|
||||
tags:
|
||||
- name: Auth
|
||||
- name: Players
|
||||
- name: Events
|
||||
- name: Teams
|
||||
- name: Series
|
||||
- name: Tournaments
|
||||
paths:
|
||||
/healthz:
|
||||
get:
|
||||
security: []
|
||||
operationId: health
|
||||
responses:
|
||||
"200":
|
||||
description: Healthy
|
||||
/readyz:
|
||||
get:
|
||||
security: []
|
||||
operationId: ready
|
||||
responses:
|
||||
"200":
|
||||
description: Ready
|
||||
"503":
|
||||
description: Not ready
|
||||
/api/auth/discord:
|
||||
get:
|
||||
security: []
|
||||
tags: [Auth]
|
||||
operationId: startDiscordLogin
|
||||
responses:
|
||||
"302":
|
||||
description: Redirect to Discord
|
||||
/api/auth/discord/callback:
|
||||
get:
|
||||
security: []
|
||||
tags: [Auth]
|
||||
operationId: finishDiscordLogin
|
||||
parameters:
|
||||
- name: code
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- name: state
|
||||
in: query
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"302":
|
||||
description: Session created
|
||||
/api/auth/me:
|
||||
get:
|
||||
tags: [Auth]
|
||||
operationId: getCurrentAccount
|
||||
responses:
|
||||
"200":
|
||||
description: Current account
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Session"
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
/api/auth/logout:
|
||||
post:
|
||||
tags: [Auth]
|
||||
operationId: logout
|
||||
responses:
|
||||
"204":
|
||||
description: Logged out
|
||||
/api/me/player:
|
||||
patch:
|
||||
tags: [Players]
|
||||
operationId: updateMyPlayer
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/PlayerUpdate"
|
||||
responses:
|
||||
"200":
|
||||
description: Updated profile
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Player"
|
||||
"422":
|
||||
$ref: "#/components/responses/ValidationError"
|
||||
/api/players:
|
||||
get:
|
||||
tags: [Players]
|
||||
operationId: listPlayers
|
||||
responses:
|
||||
"200":
|
||||
description: Players
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Player"
|
||||
/api/events:
|
||||
get:
|
||||
tags: [Events]
|
||||
operationId: listEvents
|
||||
parameters:
|
||||
- name: from
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
responses:
|
||||
"200":
|
||||
description: Events
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Event"
|
||||
post:
|
||||
tags: [Events]
|
||||
operationId: createEvent
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/EventInput"
|
||||
responses:
|
||||
"201":
|
||||
description: Event created
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Event"
|
||||
"403":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
/api/events/{eventId}:
|
||||
get:
|
||||
tags: [Events]
|
||||
operationId: getEvent
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/EventId"
|
||||
responses:
|
||||
"200":
|
||||
description: Event details
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Event"
|
||||
"404":
|
||||
$ref: "#/components/responses/NotFound"
|
||||
put:
|
||||
tags: [Events]
|
||||
operationId: updateEvent
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/EventId"
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/EventInput"
|
||||
responses:
|
||||
"200":
|
||||
description: Event updated
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Event"
|
||||
/api/events/{eventId}/rsvps:
|
||||
get:
|
||||
tags: [Events]
|
||||
operationId: listRegistrations
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/EventId"
|
||||
responses:
|
||||
"200":
|
||||
description: Registrations
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/EventRegistration"
|
||||
/api/events/{eventId}/rsvps/{playerId}:
|
||||
put:
|
||||
tags: [Events]
|
||||
operationId: adminSetRegistration
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/EventId"
|
||||
- $ref: "#/components/parameters/PlayerId"
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/RegistrationInput"
|
||||
responses:
|
||||
"200":
|
||||
description: Registration updated by admin
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/EventRegistration"
|
||||
"403":
|
||||
$ref: "#/components/responses/Forbidden"
|
||||
/api/events/{eventId}/balance:
|
||||
post:
|
||||
tags: [Teams]
|
||||
operationId: generateBalanceCandidates
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/EventId"
|
||||
requestBody:
|
||||
required: false
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
seed:
|
||||
type: integer
|
||||
format: int64
|
||||
responses:
|
||||
"200":
|
||||
description: Three best candidates
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/BalanceCandidate"
|
||||
/api/teams/{teamId}/captain:
|
||||
put:
|
||||
tags: [Teams]
|
||||
operationId: assignCaptain
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/TeamId"
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [playerId]
|
||||
properties:
|
||||
playerId:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
"200":
|
||||
description: Captain assigned
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Team"
|
||||
"422":
|
||||
$ref: "#/components/responses/ValidationError"
|
||||
/api/coin-toss:
|
||||
post:
|
||||
tags: [Series]
|
||||
operationId: tossCoin
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [teamAId, teamBId, seed, eventId, actingTeamId]
|
||||
properties:
|
||||
teamAId: { type: string }
|
||||
teamBId: { type: string }
|
||||
seed: { type: string }
|
||||
eventId: { type: string }
|
||||
actingTeamId: { type: string }
|
||||
responses:
|
||||
"200":
|
||||
description: Coin toss result
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
/api/drafts/{seriesId}/map-bans:
|
||||
post:
|
||||
tags: [Series]
|
||||
operationId: banMap
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/SeriesId"
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [teamId, map, eventId, version]
|
||||
properties:
|
||||
teamId: { type: string }
|
||||
map: { type: string }
|
||||
eventId: { type: string }
|
||||
version:
|
||||
type: integer
|
||||
responses:
|
||||
"200":
|
||||
description: Updated series
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Series"
|
||||
"409":
|
||||
$ref: "#/components/responses/Conflict"
|
||||
/api/drafts/{seriesId}/hero-bans:
|
||||
post:
|
||||
tags: [Series]
|
||||
operationId: banHero
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/SeriesId"
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [teamId, hero, eventId, version]
|
||||
properties:
|
||||
teamId: { type: string }
|
||||
hero: { type: string }
|
||||
eventId: { type: string }
|
||||
version:
|
||||
type: integer
|
||||
responses:
|
||||
"200":
|
||||
description: Updated series
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Series"
|
||||
"409":
|
||||
$ref: "#/components/responses/Conflict"
|
||||
/api/series/{seriesId}/results:
|
||||
post:
|
||||
tags: [Series]
|
||||
operationId: recordMapResult
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/SeriesId"
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/MapResultInput"
|
||||
responses:
|
||||
"200":
|
||||
description: Result recorded
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Series"
|
||||
/api/events/stream:
|
||||
get:
|
||||
tags: [Series]
|
||||
operationId: subscribeSeries
|
||||
parameters:
|
||||
- name: topic
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: Server-sent event stream
|
||||
content:
|
||||
text/event-stream:
|
||||
schema:
|
||||
type: string
|
||||
/api/tournaments/{tournamentId}:
|
||||
get:
|
||||
tags: [Tournaments]
|
||||
operationId: getTournament
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/TournamentId"
|
||||
responses:
|
||||
"200":
|
||||
description: Tournament bracket
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Tournament"
|
||||
components:
|
||||
securitySchemes:
|
||||
cookieAuth:
|
||||
type: apiKey
|
||||
in: cookie
|
||||
name: mixmaker_session
|
||||
parameters:
|
||||
EventId:
|
||||
name: eventId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
PlayerId:
|
||||
name: playerId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
TeamId:
|
||||
name: teamId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
SeriesId:
|
||||
name: seriesId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
TournamentId:
|
||||
name: tournamentId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
Unauthorized:
|
||||
description: Authentication required
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Problem"
|
||||
Forbidden:
|
||||
description: Insufficient permission
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Problem"
|
||||
NotFound:
|
||||
description: Resource not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Problem"
|
||||
Conflict:
|
||||
description: State version conflict
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Problem"
|
||||
ValidationError:
|
||||
description: Invalid command
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Problem"
|
||||
schemas:
|
||||
Session:
|
||||
type: object
|
||||
required: [account, player]
|
||||
properties:
|
||||
account:
|
||||
$ref: "#/components/schemas/Account"
|
||||
player:
|
||||
$ref: "#/components/schemas/Player"
|
||||
Account:
|
||||
type: object
|
||||
required: [id, discordId, username, role, createdAt]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
discordId:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
avatarUrl:
|
||||
type: [string, "null"]
|
||||
format: uri
|
||||
role:
|
||||
type: string
|
||||
enum: [player, admin]
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
Ratings:
|
||||
type: object
|
||||
required: [tank, damage, support]
|
||||
properties:
|
||||
tank:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 40
|
||||
description: Bronze 5 = 1, Champion 1 = 40
|
||||
damage:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 40
|
||||
description: Bronze 5 = 1, Champion 1 = 40
|
||||
support:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 40
|
||||
description: Bronze 5 = 1, Champion 1 = 40
|
||||
Player:
|
||||
type: object
|
||||
required: [id, accountId, displayName, ratings, preferredRoles, preferredPlayerIds, updatedAt]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
accountId:
|
||||
type: string
|
||||
format: uuid
|
||||
displayName:
|
||||
type: string
|
||||
ratings:
|
||||
$ref: "#/components/schemas/Ratings"
|
||||
preferredRoles:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum: [Tank, Damage, Support]
|
||||
preferredPlayerIds:
|
||||
type: array
|
||||
maxItems: 3
|
||||
items:
|
||||
type: string
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
updatedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
PlayerUpdate:
|
||||
type: object
|
||||
required: [ratings]
|
||||
properties:
|
||||
displayName:
|
||||
type: string
|
||||
ratings:
|
||||
$ref: "#/components/schemas/Ratings"
|
||||
preferredRoles:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
enum: [Tank, Damage, Support]
|
||||
preferredPlayerIds:
|
||||
type: array
|
||||
maxItems: 3
|
||||
items:
|
||||
type: string
|
||||
EventInput:
|
||||
type: object
|
||||
required: [name, startsAt, endsAt, registrationDeadline]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
minLength: 1
|
||||
description:
|
||||
type: string
|
||||
startsAt:
|
||||
type: string
|
||||
format: date-time
|
||||
endsAt:
|
||||
type: string
|
||||
format: date-time
|
||||
registrationDeadline:
|
||||
type: string
|
||||
format: date-time
|
||||
Event:
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/EventInput"
|
||||
- type: object
|
||||
required: [id, createdBy, createdAt, updatedAt]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
createdBy:
|
||||
type: string
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
updatedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
RegistrationInput:
|
||||
type: object
|
||||
required: [status]
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
enum: [Going, Maybe, NotGoing]
|
||||
EventRegistration:
|
||||
type: object
|
||||
required: [eventId, playerId, status, actorAccountId, source, updatedAt]
|
||||
properties:
|
||||
eventId:
|
||||
type: string
|
||||
format: uuid
|
||||
playerId:
|
||||
type: string
|
||||
format: uuid
|
||||
status:
|
||||
type: string
|
||||
enum: [Going, Maybe, NotGoing]
|
||||
actorAccountId:
|
||||
type: string
|
||||
format: uuid
|
||||
source:
|
||||
type: string
|
||||
enum: [player, admin]
|
||||
updatedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
TeamSlot:
|
||||
type: object
|
||||
required: [playerId, role, rating]
|
||||
properties:
|
||||
playerId:
|
||||
type: string
|
||||
role:
|
||||
type: string
|
||||
enum: [Tank, Damage, Support]
|
||||
rating:
|
||||
type: integer
|
||||
Team:
|
||||
type: object
|
||||
required: [id, eventId, name, captainPlayerId, slots]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
eventId:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
captainPlayerId:
|
||||
type: string
|
||||
slots:
|
||||
type: array
|
||||
minItems: 5
|
||||
maxItems: 5
|
||||
items:
|
||||
$ref: "#/components/schemas/TeamSlot"
|
||||
BalanceCandidate:
|
||||
type: object
|
||||
required: [score, teams, reserve]
|
||||
properties:
|
||||
score:
|
||||
type: integer
|
||||
teams:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Team"
|
||||
reserve:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
MapResultInput:
|
||||
type: object
|
||||
required: [mapName, outcome, expectedVersion]
|
||||
properties:
|
||||
mapName:
|
||||
type: string
|
||||
outcome:
|
||||
type: string
|
||||
enum: [TeamAWin, TeamBWin, Draw]
|
||||
expectedVersion:
|
||||
type: integer
|
||||
Series:
|
||||
type: object
|
||||
required: [id, tournamentId, teamAId, teamBId, winnerTeamId, bestOf, results, version]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
tournamentId:
|
||||
type: string
|
||||
teamAId:
|
||||
type: string
|
||||
teamBId:
|
||||
type: string
|
||||
winnerTeamId:
|
||||
type: string
|
||||
bestOf:
|
||||
type: integer
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
version:
|
||||
type: integer
|
||||
Tournament:
|
||||
type: object
|
||||
required: [id, eventId, name, winnerTeamId, teamIds, rounds]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
eventId:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
winnerTeamId:
|
||||
type: string
|
||||
teamIds:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
rounds:
|
||||
type: array
|
||||
items:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Series"
|
||||
Problem:
|
||||
type: object
|
||||
required: [error]
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
Reference in New Issue
Block a user