phase 8: lobby UI + cross-stack lobby command catalog + TS FlatBuffers
- Extend pkg/model/lobby and pkg/schema/fbs/lobby.fbs with public-games
list, my-applications/invites lists, game-create, application-submit,
invite-redeem/decline. Mirror the matching transcoder pairs and Go
fixture round-trip tests.
- Wire the seven new lobby message types through
gateway/internal/backendclient/{routes,lobby_commands}.go with
per-command REST helpers, JSON-tolerant decoding of backend wire
shapes, and httptest-based unit coverage for success / 4xx / 5xx /
503 across each command.
- Introduce TS-side FlatBuffers via the `flatbuffers` runtime dep, a
`make fbs-ts` target driving flatc, and the generated bindings under
ui/frontend/src/proto/galaxy/fbs. Phase 7's `user.account.get` decode
now uses these bindings as well, closing the JSON.parse vs
FlatBuffers gap that would have failed against a real local stack.
- Replace the placeholder lobby with five sections (my games, pending
invitations, my applications, public games, create new game) and the
/lobby/create form. Submit-application uses an inline race-name
form on the public-game card; create-game keeps name / description /
turn_schedule / enrollment_ends_at always visible and the rest under
an Advanced toggle with TS-side defaults.
- Update lobby/+page.svelte to throw LobbyError on non-ok result codes;
GalaxyClient.executeCommand now returns { resultCode, payloadBytes }.
- Vitest binding round-trips, lobby.ts wrapper unit tests, lobby-page
+ lobby-create component tests, Playwright lobby-flow.spec covering
create / submit / accept across all four projects. Phase 7 e2e was
migrated to the FlatBuffers fixtures and to click+fill against the
Safari-autofill readonly inputs.
- Mark Phase 8 done in ui/PLAN.md, mirror the wire-format note into
Phase 7, append the new lobby commands to gateway/README.md and
docs/ARCHITECTURE.md, add ui/docs/lobby.md.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -145,6 +145,15 @@ because they cross domain boundaries:
|
||||
`X-User-ID`. Public games carry `owner_user_id IS NULL`; the partial
|
||||
index on `(owner_user_id) WHERE visibility = 'private'` keeps the
|
||||
private-owner lookup efficient.
|
||||
- **Authenticated lobby commands** flow through the gateway envelope
|
||||
by `message_type`. The catalog is `lobby.my.games.list`,
|
||||
`lobby.public.games.list`, `lobby.my.applications.list`,
|
||||
`lobby.my.invites.list`, `lobby.game.create`,
|
||||
`lobby.game.open-enrollment`, `lobby.application.submit`,
|
||||
`lobby.invite.redeem`, and `lobby.invite.decline`. Each lands on a
|
||||
REST handler under `/api/v1/user/lobby/*`; the gateway forces
|
||||
visibility to `private` on `lobby.game.create` before forwarding,
|
||||
matching the user-surface invariant above.
|
||||
|
||||
| Package | Responsibility |
|
||||
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
|
||||
@@ -369,6 +369,15 @@ The current direct `Gateway -> User` self-service boundary uses that pattern:
|
||||
- `user.games.command`
|
||||
- `user.games.order`
|
||||
- `user.games.report`
|
||||
- `lobby.my.games.list`
|
||||
- `lobby.my.applications.list`
|
||||
- `lobby.my.invites.list`
|
||||
- `lobby.public.games.list`
|
||||
- `lobby.game.create`
|
||||
- `lobby.game.open-enrollment`
|
||||
- `lobby.application.submit`
|
||||
- `lobby.invite.redeem`
|
||||
- `lobby.invite.decline`
|
||||
- external payloads and responses:
|
||||
- FlatBuffers
|
||||
- internal downstream transport:
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"galaxy/gateway/internal/downstream"
|
||||
lobbymodel "galaxy/model/lobby"
|
||||
@@ -55,12 +56,52 @@ func (c *RESTClient) ExecuteLobbyCommand(ctx context.Context, command downstream
|
||||
return downstream.UnaryResult{}, fmt.Errorf("backendclient: execute lobby command %q: %w", command.MessageType, err)
|
||||
}
|
||||
return c.executeLobbyMyGames(ctx, command.UserID)
|
||||
case lobbymodel.MessageTypePublicGamesList:
|
||||
req, err := transcoder.PayloadToPublicGamesListRequest(command.PayloadBytes)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("backendclient: execute lobby command %q: %w", command.MessageType, err)
|
||||
}
|
||||
return c.executeLobbyPublicGames(ctx, command.UserID, req)
|
||||
case lobbymodel.MessageTypeMyApplicationsList:
|
||||
if _, err := transcoder.PayloadToMyApplicationsListRequest(command.PayloadBytes); err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("backendclient: execute lobby command %q: %w", command.MessageType, err)
|
||||
}
|
||||
return c.executeLobbyMyApplications(ctx, command.UserID)
|
||||
case lobbymodel.MessageTypeMyInvitesList:
|
||||
if _, err := transcoder.PayloadToMyInvitesListRequest(command.PayloadBytes); err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("backendclient: execute lobby command %q: %w", command.MessageType, err)
|
||||
}
|
||||
return c.executeLobbyMyInvites(ctx, command.UserID)
|
||||
case lobbymodel.MessageTypeOpenEnrollment:
|
||||
req, err := transcoder.PayloadToOpenEnrollmentRequest(command.PayloadBytes)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("backendclient: execute lobby command %q: %w", command.MessageType, err)
|
||||
}
|
||||
return c.executeLobbyOpenEnrollment(ctx, command.UserID, req)
|
||||
case lobbymodel.MessageTypeGameCreate:
|
||||
req, err := transcoder.PayloadToGameCreateRequest(command.PayloadBytes)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("backendclient: execute lobby command %q: %w", command.MessageType, err)
|
||||
}
|
||||
return c.executeLobbyGameCreate(ctx, command.UserID, req)
|
||||
case lobbymodel.MessageTypeApplicationSubmit:
|
||||
req, err := transcoder.PayloadToApplicationSubmitRequest(command.PayloadBytes)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("backendclient: execute lobby command %q: %w", command.MessageType, err)
|
||||
}
|
||||
return c.executeLobbyApplicationSubmit(ctx, command.UserID, req)
|
||||
case lobbymodel.MessageTypeInviteRedeem:
|
||||
req, err := transcoder.PayloadToInviteRedeemRequest(command.PayloadBytes)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("backendclient: execute lobby command %q: %w", command.MessageType, err)
|
||||
}
|
||||
return c.executeLobbyInviteRedeem(ctx, command.UserID, req)
|
||||
case lobbymodel.MessageTypeInviteDecline:
|
||||
req, err := transcoder.PayloadToInviteDeclineRequest(command.PayloadBytes)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("backendclient: execute lobby command %q: %w", command.MessageType, err)
|
||||
}
|
||||
return c.executeLobbyInviteDecline(ctx, command.UserID, req)
|
||||
default:
|
||||
return downstream.UnaryResult{}, fmt.Errorf("backendclient: execute lobby command: unsupported message type %q", command.MessageType)
|
||||
}
|
||||
@@ -88,6 +129,81 @@ func (c *RESTClient) executeLobbyMyGames(ctx context.Context, userID string) (do
|
||||
return projectLobbyErrorResponse(status, body)
|
||||
}
|
||||
|
||||
func (c *RESTClient) executeLobbyPublicGames(ctx context.Context, userID string, req *lobbymodel.PublicGamesListRequest) (downstream.UnaryResult, error) {
|
||||
page := req.Page
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
pageSize := req.PageSize
|
||||
if pageSize <= 0 {
|
||||
pageSize = 50
|
||||
}
|
||||
target := fmt.Sprintf("%s/api/v1/user/lobby/games?page=%d&page_size=%d", c.baseURL, page, pageSize)
|
||||
body, status, err := c.do(ctx, http.MethodGet, target, userID, nil)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("execute lobby.public.games.list: %w", err)
|
||||
}
|
||||
if status == http.StatusOK {
|
||||
page, err := decodePublicGamesPage(body)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, err
|
||||
}
|
||||
payloadBytes, err := transcoder.PublicGamesListResponseToPayload(page)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("encode success response payload: %w", err)
|
||||
}
|
||||
return downstream.UnaryResult{
|
||||
ResultCode: lobbyResultCodeOK,
|
||||
PayloadBytes: payloadBytes,
|
||||
}, nil
|
||||
}
|
||||
return projectLobbyErrorResponse(status, body)
|
||||
}
|
||||
|
||||
func (c *RESTClient) executeLobbyMyApplications(ctx context.Context, userID string) (downstream.UnaryResult, error) {
|
||||
body, status, err := c.do(ctx, http.MethodGet, c.baseURL+"/api/v1/user/lobby/my/applications", userID, nil)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("execute lobby.my.applications.list: %w", err)
|
||||
}
|
||||
if status == http.StatusOK {
|
||||
response, err := decodeApplicationsList(body)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, err
|
||||
}
|
||||
payloadBytes, err := transcoder.MyApplicationsListResponseToPayload(response)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("encode success response payload: %w", err)
|
||||
}
|
||||
return downstream.UnaryResult{
|
||||
ResultCode: lobbyResultCodeOK,
|
||||
PayloadBytes: payloadBytes,
|
||||
}, nil
|
||||
}
|
||||
return projectLobbyErrorResponse(status, body)
|
||||
}
|
||||
|
||||
func (c *RESTClient) executeLobbyMyInvites(ctx context.Context, userID string) (downstream.UnaryResult, error) {
|
||||
body, status, err := c.do(ctx, http.MethodGet, c.baseURL+"/api/v1/user/lobby/my/invites", userID, nil)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("execute lobby.my.invites.list: %w", err)
|
||||
}
|
||||
if status == http.StatusOK {
|
||||
response, err := decodeInvitesList(body)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, err
|
||||
}
|
||||
payloadBytes, err := transcoder.MyInvitesListResponseToPayload(response)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("encode success response payload: %w", err)
|
||||
}
|
||||
return downstream.UnaryResult{
|
||||
ResultCode: lobbyResultCodeOK,
|
||||
PayloadBytes: payloadBytes,
|
||||
}, nil
|
||||
}
|
||||
return projectLobbyErrorResponse(status, body)
|
||||
}
|
||||
|
||||
func (c *RESTClient) executeLobbyOpenEnrollment(ctx context.Context, userID string, req *lobbymodel.OpenEnrollmentRequest) (downstream.UnaryResult, error) {
|
||||
if req == nil || strings.TrimSpace(req.GameID) == "" {
|
||||
return downstream.UnaryResult{}, errors.New("execute lobby.game.open-enrollment: game_id must not be empty")
|
||||
@@ -122,6 +238,338 @@ func (c *RESTClient) executeLobbyOpenEnrollment(ctx context.Context, userID stri
|
||||
return projectLobbyErrorResponse(status, body)
|
||||
}
|
||||
|
||||
func (c *RESTClient) executeLobbyGameCreate(ctx context.Context, userID string, req *lobbymodel.GameCreateRequest) (downstream.UnaryResult, error) {
|
||||
if req == nil || strings.TrimSpace(req.GameName) == "" {
|
||||
return downstream.UnaryResult{}, errors.New("execute lobby.game.create: game_name must not be empty")
|
||||
}
|
||||
if strings.TrimSpace(req.TurnSchedule) == "" {
|
||||
return downstream.UnaryResult{}, errors.New("execute lobby.game.create: turn_schedule must not be empty")
|
||||
}
|
||||
if strings.TrimSpace(req.TargetEngineVersion) == "" {
|
||||
return downstream.UnaryResult{}, errors.New("execute lobby.game.create: target_engine_version must not be empty")
|
||||
}
|
||||
if req.MinPlayers <= 0 || req.MaxPlayers <= 0 {
|
||||
return downstream.UnaryResult{}, errors.New("execute lobby.game.create: min_players and max_players must be positive")
|
||||
}
|
||||
if req.MinPlayers > req.MaxPlayers {
|
||||
return downstream.UnaryResult{}, errors.New("execute lobby.game.create: min_players must not exceed max_players")
|
||||
}
|
||||
if req.EnrollmentEndsAt.IsZero() {
|
||||
return downstream.UnaryResult{}, errors.New("execute lobby.game.create: enrollment_ends_at must be set")
|
||||
}
|
||||
|
||||
body := map[string]any{
|
||||
"game_name": req.GameName,
|
||||
"visibility": "private",
|
||||
"description": req.Description,
|
||||
"min_players": int32(req.MinPlayers),
|
||||
"max_players": int32(req.MaxPlayers),
|
||||
"start_gap_hours": int32(req.StartGapHours),
|
||||
"start_gap_players": int32(req.StartGapPlayers),
|
||||
"enrollment_ends_at": req.EnrollmentEndsAt.UTC().Format(time.RFC3339Nano),
|
||||
"turn_schedule": req.TurnSchedule,
|
||||
"target_engine_version": req.TargetEngineVersion,
|
||||
}
|
||||
payload, status, err := c.do(ctx, http.MethodPost, c.baseURL+"/api/v1/user/lobby/games", userID, body)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("execute lobby.game.create: %w", err)
|
||||
}
|
||||
if status == http.StatusOK || status == http.StatusCreated {
|
||||
summary, err := decodeGameSummaryFromGameDetail(payload)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, err
|
||||
}
|
||||
payloadBytes, err := transcoder.GameCreateResponseToPayload(&lobbymodel.GameCreateResponse{Game: summary})
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("encode success response payload: %w", err)
|
||||
}
|
||||
return downstream.UnaryResult{
|
||||
ResultCode: lobbyResultCodeOK,
|
||||
PayloadBytes: payloadBytes,
|
||||
}, nil
|
||||
}
|
||||
return projectLobbyErrorResponse(status, payload)
|
||||
}
|
||||
|
||||
func (c *RESTClient) executeLobbyApplicationSubmit(ctx context.Context, userID string, req *lobbymodel.ApplicationSubmitRequest) (downstream.UnaryResult, error) {
|
||||
if req == nil || strings.TrimSpace(req.GameID) == "" {
|
||||
return downstream.UnaryResult{}, errors.New("execute lobby.application.submit: game_id must not be empty")
|
||||
}
|
||||
if strings.TrimSpace(req.RaceName) == "" {
|
||||
return downstream.UnaryResult{}, errors.New("execute lobby.application.submit: race_name must not be empty")
|
||||
}
|
||||
target := c.baseURL + "/api/v1/user/lobby/games/" + url.PathEscape(req.GameID) + "/applications"
|
||||
body := map[string]any{"race_name": req.RaceName}
|
||||
payload, status, err := c.do(ctx, http.MethodPost, target, userID, body)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("execute lobby.application.submit: %w", err)
|
||||
}
|
||||
if status == http.StatusOK || status == http.StatusCreated {
|
||||
app, err := decodeApplicationDetail(payload)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, err
|
||||
}
|
||||
payloadBytes, err := transcoder.ApplicationSubmitResponseToPayload(&lobbymodel.ApplicationSubmitResponse{Application: app})
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("encode success response payload: %w", err)
|
||||
}
|
||||
return downstream.UnaryResult{
|
||||
ResultCode: lobbyResultCodeOK,
|
||||
PayloadBytes: payloadBytes,
|
||||
}, nil
|
||||
}
|
||||
return projectLobbyErrorResponse(status, payload)
|
||||
}
|
||||
|
||||
func (c *RESTClient) executeLobbyInviteRedeem(ctx context.Context, userID string, req *lobbymodel.InviteRedeemRequest) (downstream.UnaryResult, error) {
|
||||
if req == nil || strings.TrimSpace(req.GameID) == "" || strings.TrimSpace(req.InviteID) == "" {
|
||||
return downstream.UnaryResult{}, errors.New("execute lobby.invite.redeem: game_id and invite_id must not be empty")
|
||||
}
|
||||
target := c.baseURL + "/api/v1/user/lobby/games/" + url.PathEscape(req.GameID) + "/invites/" + url.PathEscape(req.InviteID) + "/redeem"
|
||||
payload, status, err := c.do(ctx, http.MethodPost, target, userID, nil)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("execute lobby.invite.redeem: %w", err)
|
||||
}
|
||||
if status == http.StatusOK {
|
||||
invite, err := decodeInviteDetail(payload)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, err
|
||||
}
|
||||
payloadBytes, err := transcoder.InviteRedeemResponseToPayload(&lobbymodel.InviteRedeemResponse{Invite: invite})
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("encode success response payload: %w", err)
|
||||
}
|
||||
return downstream.UnaryResult{
|
||||
ResultCode: lobbyResultCodeOK,
|
||||
PayloadBytes: payloadBytes,
|
||||
}, nil
|
||||
}
|
||||
return projectLobbyErrorResponse(status, payload)
|
||||
}
|
||||
|
||||
func (c *RESTClient) executeLobbyInviteDecline(ctx context.Context, userID string, req *lobbymodel.InviteDeclineRequest) (downstream.UnaryResult, error) {
|
||||
if req == nil || strings.TrimSpace(req.GameID) == "" || strings.TrimSpace(req.InviteID) == "" {
|
||||
return downstream.UnaryResult{}, errors.New("execute lobby.invite.decline: game_id and invite_id must not be empty")
|
||||
}
|
||||
target := c.baseURL + "/api/v1/user/lobby/games/" + url.PathEscape(req.GameID) + "/invites/" + url.PathEscape(req.InviteID) + "/decline"
|
||||
payload, status, err := c.do(ctx, http.MethodPost, target, userID, nil)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("execute lobby.invite.decline: %w", err)
|
||||
}
|
||||
if status == http.StatusOK {
|
||||
invite, err := decodeInviteDetail(payload)
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, err
|
||||
}
|
||||
payloadBytes, err := transcoder.InviteDeclineResponseToPayload(&lobbymodel.InviteDeclineResponse{Invite: invite})
|
||||
if err != nil {
|
||||
return downstream.UnaryResult{}, fmt.Errorf("encode success response payload: %w", err)
|
||||
}
|
||||
return downstream.UnaryResult{
|
||||
ResultCode: lobbyResultCodeOK,
|
||||
PayloadBytes: payloadBytes,
|
||||
}, nil
|
||||
}
|
||||
return projectLobbyErrorResponse(status, payload)
|
||||
}
|
||||
|
||||
// decodeGameSummaryFromGameDetail accepts the backend's full
|
||||
// LobbyGameDetail wire shape and projects it onto the gateway's
|
||||
// GameSummary contract. It uses non-strict JSON decoding so the
|
||||
// gateway tolerates the runtime/engine fields it does not forward to
|
||||
// the UI.
|
||||
func decodeGameSummaryFromGameDetail(payload []byte) (lobbymodel.GameSummary, error) {
|
||||
var wire struct {
|
||||
GameID string `json:"game_id"`
|
||||
GameName string `json:"game_name"`
|
||||
GameType string `json:"game_type"`
|
||||
Status string `json:"status"`
|
||||
OwnerUserID *string `json:"owner_user_id"`
|
||||
MinPlayers int `json:"min_players"`
|
||||
MaxPlayers int `json:"max_players"`
|
||||
EnrollmentEndsAt time.Time `json:"enrollment_ends_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
if err := json.Unmarshal(payload, &wire); err != nil {
|
||||
return lobbymodel.GameSummary{}, fmt.Errorf("decode success response: %w", err)
|
||||
}
|
||||
owner := ""
|
||||
if wire.OwnerUserID != nil {
|
||||
owner = *wire.OwnerUserID
|
||||
}
|
||||
return lobbymodel.GameSummary{
|
||||
GameID: wire.GameID,
|
||||
GameName: wire.GameName,
|
||||
GameType: wire.GameType,
|
||||
Status: wire.Status,
|
||||
OwnerUserID: owner,
|
||||
MinPlayers: wire.MinPlayers,
|
||||
MaxPlayers: wire.MaxPlayers,
|
||||
EnrollmentEndsAt: wire.EnrollmentEndsAt.UTC(),
|
||||
CreatedAt: wire.CreatedAt.UTC(),
|
||||
UpdatedAt: wire.UpdatedAt.UTC(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func decodePublicGamesPage(payload []byte) (*lobbymodel.PublicGamesListResponse, error) {
|
||||
var wire struct {
|
||||
Items []struct {
|
||||
GameID string `json:"game_id"`
|
||||
GameName string `json:"game_name"`
|
||||
GameType string `json:"game_type"`
|
||||
Status string `json:"status"`
|
||||
OwnerUserID *string `json:"owner_user_id"`
|
||||
MinPlayers int `json:"min_players"`
|
||||
MaxPlayers int `json:"max_players"`
|
||||
EnrollmentEndsAt time.Time `json:"enrollment_ends_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
} `json:"items"`
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
if err := json.Unmarshal(payload, &wire); err != nil {
|
||||
return nil, fmt.Errorf("decode success response: %w", err)
|
||||
}
|
||||
out := &lobbymodel.PublicGamesListResponse{
|
||||
Items: make([]lobbymodel.GameSummary, 0, len(wire.Items)),
|
||||
Page: wire.Page,
|
||||
PageSize: wire.PageSize,
|
||||
Total: wire.Total,
|
||||
}
|
||||
for _, w := range wire.Items {
|
||||
owner := ""
|
||||
if w.OwnerUserID != nil {
|
||||
owner = *w.OwnerUserID
|
||||
}
|
||||
out.Items = append(out.Items, lobbymodel.GameSummary{
|
||||
GameID: w.GameID,
|
||||
GameName: w.GameName,
|
||||
GameType: w.GameType,
|
||||
Status: w.Status,
|
||||
OwnerUserID: owner,
|
||||
MinPlayers: w.MinPlayers,
|
||||
MaxPlayers: w.MaxPlayers,
|
||||
EnrollmentEndsAt: w.EnrollmentEndsAt.UTC(),
|
||||
CreatedAt: w.CreatedAt.UTC(),
|
||||
UpdatedAt: w.UpdatedAt.UTC(),
|
||||
})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func decodeApplicationsList(payload []byte) (*lobbymodel.MyApplicationsListResponse, error) {
|
||||
var wire struct {
|
||||
Items []applicationDetailWire `json:"items"`
|
||||
}
|
||||
if err := json.Unmarshal(payload, &wire); err != nil {
|
||||
return nil, fmt.Errorf("decode success response: %w", err)
|
||||
}
|
||||
out := &lobbymodel.MyApplicationsListResponse{
|
||||
Items: make([]lobbymodel.ApplicationSummary, 0, len(wire.Items)),
|
||||
}
|
||||
for _, w := range wire.Items {
|
||||
out.Items = append(out.Items, w.toModel())
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func decodeApplicationDetail(payload []byte) (lobbymodel.ApplicationSummary, error) {
|
||||
var wire applicationDetailWire
|
||||
if err := json.Unmarshal(payload, &wire); err != nil {
|
||||
return lobbymodel.ApplicationSummary{}, fmt.Errorf("decode success response: %w", err)
|
||||
}
|
||||
return wire.toModel(), nil
|
||||
}
|
||||
|
||||
func decodeInvitesList(payload []byte) (*lobbymodel.MyInvitesListResponse, error) {
|
||||
var wire struct {
|
||||
Items []inviteDetailWire `json:"items"`
|
||||
}
|
||||
if err := json.Unmarshal(payload, &wire); err != nil {
|
||||
return nil, fmt.Errorf("decode success response: %w", err)
|
||||
}
|
||||
out := &lobbymodel.MyInvitesListResponse{
|
||||
Items: make([]lobbymodel.InviteSummary, 0, len(wire.Items)),
|
||||
}
|
||||
for _, w := range wire.Items {
|
||||
out.Items = append(out.Items, w.toModel())
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func decodeInviteDetail(payload []byte) (lobbymodel.InviteSummary, error) {
|
||||
var wire inviteDetailWire
|
||||
if err := json.Unmarshal(payload, &wire); err != nil {
|
||||
return lobbymodel.InviteSummary{}, fmt.Errorf("decode success response: %w", err)
|
||||
}
|
||||
return wire.toModel(), nil
|
||||
}
|
||||
|
||||
type applicationDetailWire struct {
|
||||
ApplicationID string `json:"application_id"`
|
||||
GameID string `json:"game_id"`
|
||||
ApplicantUserID string `json:"applicant_user_id"`
|
||||
RaceName string `json:"race_name"`
|
||||
Status string `json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
DecidedAt *time.Time `json:"decided_at,omitempty"`
|
||||
}
|
||||
|
||||
func (w applicationDetailWire) toModel() lobbymodel.ApplicationSummary {
|
||||
out := lobbymodel.ApplicationSummary{
|
||||
ApplicationID: w.ApplicationID,
|
||||
GameID: w.GameID,
|
||||
ApplicantUserID: w.ApplicantUserID,
|
||||
RaceName: w.RaceName,
|
||||
Status: w.Status,
|
||||
CreatedAt: w.CreatedAt.UTC(),
|
||||
}
|
||||
if w.DecidedAt != nil {
|
||||
t := w.DecidedAt.UTC()
|
||||
out.DecidedAt = &t
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
type inviteDetailWire struct {
|
||||
InviteID string `json:"invite_id"`
|
||||
GameID string `json:"game_id"`
|
||||
InviterUserID string `json:"inviter_user_id"`
|
||||
InvitedUserID *string `json:"invited_user_id,omitempty"`
|
||||
Code *string `json:"code,omitempty"`
|
||||
RaceName string `json:"race_name"`
|
||||
Status string `json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
DecidedAt *time.Time `json:"decided_at,omitempty"`
|
||||
}
|
||||
|
||||
func (w inviteDetailWire) toModel() lobbymodel.InviteSummary {
|
||||
out := lobbymodel.InviteSummary{
|
||||
InviteID: w.InviteID,
|
||||
GameID: w.GameID,
|
||||
InviterUserID: w.InviterUserID,
|
||||
RaceName: w.RaceName,
|
||||
Status: w.Status,
|
||||
CreatedAt: w.CreatedAt.UTC(),
|
||||
ExpiresAt: w.ExpiresAt.UTC(),
|
||||
}
|
||||
if w.InvitedUserID != nil {
|
||||
out.InvitedUserID = *w.InvitedUserID
|
||||
}
|
||||
if w.Code != nil {
|
||||
out.Code = *w.Code
|
||||
}
|
||||
if w.DecidedAt != nil {
|
||||
t := w.DecidedAt.UTC()
|
||||
out.DecidedAt = &t
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func projectLobbyErrorResponse(statusCode int, payload []byte) (downstream.UnaryResult, error) {
|
||||
switch {
|
||||
case statusCode == http.StatusServiceUnavailable:
|
||||
|
||||
@@ -0,0 +1,512 @@
|
||||
package backendclient_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"galaxy/gateway/internal/backendclient"
|
||||
"galaxy/gateway/internal/downstream"
|
||||
lobbymodel "galaxy/model/lobby"
|
||||
"galaxy/transcoder"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func newAuthCommand(t *testing.T, messageType string, payload []byte) downstream.AuthenticatedCommand {
|
||||
t.Helper()
|
||||
return downstream.AuthenticatedCommand{
|
||||
MessageType: messageType,
|
||||
PayloadBytes: payload,
|
||||
UserID: "user-1",
|
||||
}
|
||||
}
|
||||
|
||||
func mustEncode[T any](t *testing.T, encode func(*T) ([]byte, error), value *T) []byte {
|
||||
t.Helper()
|
||||
bytes, err := encode(value)
|
||||
require.NoError(t, err)
|
||||
return bytes
|
||||
}
|
||||
|
||||
func TestExecuteLobbyMyGamesListReturnsItems(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
enrollment := time.Date(2026, 5, 15, 12, 0, 0, 0, time.UTC)
|
||||
created := time.Date(2026, 5, 7, 10, 0, 0, 0, time.UTC)
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, http.MethodGet, r.Method)
|
||||
require.Equal(t, "/api/v1/user/lobby/my/games", r.URL.Path)
|
||||
require.Equal(t, "user-1", r.Header.Get(backendclient.HeaderUserID))
|
||||
writeJSON(t, w, http.StatusOK, map[string]any{
|
||||
"items": []map[string]any{{
|
||||
"game_id": "game-1",
|
||||
"game_name": "Test Game",
|
||||
"game_type": "private",
|
||||
"status": "draft",
|
||||
"owner_user_id": "user-1",
|
||||
"min_players": 2,
|
||||
"max_players": 8,
|
||||
"enrollment_ends_at": enrollment.Format(time.RFC3339Nano),
|
||||
"created_at": created.Format(time.RFC3339Nano),
|
||||
"updated_at": created.Format(time.RFC3339Nano),
|
||||
}},
|
||||
})
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
client := newRESTClient(t, server)
|
||||
payload := mustEncode(t, transcoder.MyGamesListRequestToPayload, &lobbymodel.MyGamesListRequest{})
|
||||
result, err := client.ExecuteLobbyCommand(context.Background(), newAuthCommand(t, lobbymodel.MessageTypeMyGamesList, payload))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "ok", result.ResultCode)
|
||||
|
||||
decoded, err := transcoder.PayloadToMyGamesListResponse(result.PayloadBytes)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, decoded.Items, 1)
|
||||
assert.Equal(t, "game-1", decoded.Items[0].GameID)
|
||||
assert.Equal(t, enrollment, decoded.Items[0].EnrollmentEndsAt)
|
||||
}
|
||||
|
||||
func TestExecuteLobbyPublicGamesListPaginatesAndDecodes(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
enrollment := time.Date(2026, 6, 1, 12, 0, 0, 0, time.UTC)
|
||||
created := time.Date(2026, 5, 1, 12, 0, 0, 0, time.UTC)
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, http.MethodGet, r.Method)
|
||||
require.Equal(t, "/api/v1/user/lobby/games", r.URL.Path)
|
||||
require.Equal(t, "2", r.URL.Query().Get("page"))
|
||||
require.Equal(t, "10", r.URL.Query().Get("page_size"))
|
||||
writeJSON(t, w, http.StatusOK, map[string]any{
|
||||
"items": []map[string]any{{
|
||||
"game_id": "public-1",
|
||||
"game_name": "Open",
|
||||
"game_type": "public",
|
||||
"status": "enrollment_open",
|
||||
"owner_user_id": nil,
|
||||
"min_players": 4,
|
||||
"max_players": 12,
|
||||
"enrollment_ends_at": enrollment.Format(time.RFC3339Nano),
|
||||
"created_at": created.Format(time.RFC3339Nano),
|
||||
"updated_at": created.Format(time.RFC3339Nano),
|
||||
}},
|
||||
"page": 2,
|
||||
"page_size": 10,
|
||||
"total": 31,
|
||||
})
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
client := newRESTClient(t, server)
|
||||
payload := mustEncode(t, transcoder.PublicGamesListRequestToPayload, &lobbymodel.PublicGamesListRequest{Page: 2, PageSize: 10})
|
||||
result, err := client.ExecuteLobbyCommand(context.Background(), newAuthCommand(t, lobbymodel.MessageTypePublicGamesList, payload))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "ok", result.ResultCode)
|
||||
|
||||
decoded, err := transcoder.PayloadToPublicGamesListResponse(result.PayloadBytes)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 2, decoded.Page)
|
||||
assert.Equal(t, 10, decoded.PageSize)
|
||||
assert.Equal(t, 31, decoded.Total)
|
||||
require.Len(t, decoded.Items, 1)
|
||||
assert.Empty(t, decoded.Items[0].OwnerUserID)
|
||||
}
|
||||
|
||||
func TestExecuteLobbyMyApplicationsList(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
created := time.Date(2026, 5, 5, 10, 0, 0, 0, time.UTC)
|
||||
decided := time.Date(2026, 5, 6, 12, 0, 0, 0, time.UTC)
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, "/api/v1/user/lobby/my/applications", r.URL.Path)
|
||||
writeJSON(t, w, http.StatusOK, map[string]any{
|
||||
"items": []map[string]any{
|
||||
{
|
||||
"application_id": "app-1",
|
||||
"game_id": "public-1",
|
||||
"applicant_user_id": "user-1",
|
||||
"race_name": "Vegan Federation",
|
||||
"status": "pending",
|
||||
"created_at": created.Format(time.RFC3339Nano),
|
||||
},
|
||||
{
|
||||
"application_id": "app-2",
|
||||
"game_id": "public-2",
|
||||
"applicant_user_id": "user-1",
|
||||
"race_name": "Lithic Compact",
|
||||
"status": "approved",
|
||||
"created_at": created.Format(time.RFC3339Nano),
|
||||
"decided_at": decided.Format(time.RFC3339Nano),
|
||||
},
|
||||
},
|
||||
})
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
client := newRESTClient(t, server)
|
||||
payload := mustEncode(t, transcoder.MyApplicationsListRequestToPayload, &lobbymodel.MyApplicationsListRequest{})
|
||||
result, err := client.ExecuteLobbyCommand(context.Background(), newAuthCommand(t, lobbymodel.MessageTypeMyApplicationsList, payload))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "ok", result.ResultCode)
|
||||
|
||||
decoded, err := transcoder.PayloadToMyApplicationsListResponse(result.PayloadBytes)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, decoded.Items, 2)
|
||||
assert.Equal(t, "pending", decoded.Items[0].Status)
|
||||
assert.Nil(t, decoded.Items[0].DecidedAt)
|
||||
require.NotNil(t, decoded.Items[1].DecidedAt)
|
||||
assert.Equal(t, decided, *decoded.Items[1].DecidedAt)
|
||||
}
|
||||
|
||||
func TestExecuteLobbyMyInvitesList(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
created := time.Date(2026, 5, 5, 10, 0, 0, 0, time.UTC)
|
||||
expires := time.Date(2026, 5, 8, 10, 0, 0, 0, time.UTC)
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, "/api/v1/user/lobby/my/invites", r.URL.Path)
|
||||
writeJSON(t, w, http.StatusOK, map[string]any{
|
||||
"items": []map[string]any{{
|
||||
"invite_id": "invite-1",
|
||||
"game_id": "private-1",
|
||||
"inviter_user_id": "user-host",
|
||||
"invited_user_id": "user-1",
|
||||
"race_name": "Vegan Federation",
|
||||
"status": "pending",
|
||||
"created_at": created.Format(time.RFC3339Nano),
|
||||
"expires_at": expires.Format(time.RFC3339Nano),
|
||||
}},
|
||||
})
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
client := newRESTClient(t, server)
|
||||
payload := mustEncode(t, transcoder.MyInvitesListRequestToPayload, &lobbymodel.MyInvitesListRequest{})
|
||||
result, err := client.ExecuteLobbyCommand(context.Background(), newAuthCommand(t, lobbymodel.MessageTypeMyInvitesList, payload))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "ok", result.ResultCode)
|
||||
|
||||
decoded, err := transcoder.PayloadToMyInvitesListResponse(result.PayloadBytes)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, decoded.Items, 1)
|
||||
assert.Equal(t, "user-1", decoded.Items[0].InvitedUserID)
|
||||
assert.Empty(t, decoded.Items[0].Code)
|
||||
assert.Equal(t, expires, decoded.Items[0].ExpiresAt)
|
||||
}
|
||||
|
||||
func TestExecuteLobbyGameCreatePostsPrivateAndProjectsToSummary(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
enrollment := time.Date(2026, 6, 1, 12, 0, 0, 0, time.UTC)
|
||||
created := time.Date(2026, 5, 7, 10, 0, 0, 0, time.UTC)
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, http.MethodPost, r.Method)
|
||||
require.Equal(t, "/api/v1/user/lobby/games", r.URL.Path)
|
||||
|
||||
var body map[string]any
|
||||
raw, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, json.Unmarshal(raw, &body))
|
||||
assert.Equal(t, "private", body["visibility"])
|
||||
assert.Equal(t, "First Contact", body["game_name"])
|
||||
assert.Equal(t, "0 0 * * *", body["turn_schedule"])
|
||||
|
||||
// Backend always returns the full GameDetail including runtime
|
||||
// snapshot fields the gateway must tolerate.
|
||||
writeJSON(t, w, http.StatusCreated, map[string]any{
|
||||
"game_id": "newly-created",
|
||||
"game_name": "First Contact",
|
||||
"game_type": "private",
|
||||
"status": "draft",
|
||||
"owner_user_id": "user-1",
|
||||
"min_players": 2,
|
||||
"max_players": 8,
|
||||
"enrollment_ends_at": enrollment.Format(time.RFC3339Nano),
|
||||
"created_at": created.Format(time.RFC3339Nano),
|
||||
"updated_at": created.Format(time.RFC3339Nano),
|
||||
"visibility": "private",
|
||||
"description": "",
|
||||
"turn_schedule": "0 0 * * *",
|
||||
"target_engine_version": "v1",
|
||||
"start_gap_hours": 24,
|
||||
"start_gap_players": 2,
|
||||
"current_turn": 0,
|
||||
"runtime_status": "",
|
||||
})
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
client := newRESTClient(t, server)
|
||||
payload := mustEncode(t, transcoder.GameCreateRequestToPayload, &lobbymodel.GameCreateRequest{
|
||||
GameName: "First Contact",
|
||||
Description: "",
|
||||
MinPlayers: 2,
|
||||
MaxPlayers: 8,
|
||||
StartGapHours: 24,
|
||||
StartGapPlayers: 2,
|
||||
EnrollmentEndsAt: enrollment,
|
||||
TurnSchedule: "0 0 * * *",
|
||||
TargetEngineVersion: "v1",
|
||||
})
|
||||
result, err := client.ExecuteLobbyCommand(context.Background(), newAuthCommand(t, lobbymodel.MessageTypeGameCreate, payload))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "ok", result.ResultCode)
|
||||
|
||||
decoded, err := transcoder.PayloadToGameCreateResponse(result.PayloadBytes)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "newly-created", decoded.Game.GameID)
|
||||
assert.Equal(t, "draft", decoded.Game.Status)
|
||||
}
|
||||
|
||||
func TestExecuteLobbyGameCreateRejectsEmptyGameName(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
t.Errorf("backend must not be hit on validation failure")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
client := newRESTClient(t, server)
|
||||
payload := mustEncode(t, transcoder.GameCreateRequestToPayload, &lobbymodel.GameCreateRequest{
|
||||
MinPlayers: 2,
|
||||
MaxPlayers: 8,
|
||||
EnrollmentEndsAt: time.Date(2026, 6, 1, 12, 0, 0, 0, time.UTC),
|
||||
TurnSchedule: "0 0 * * *",
|
||||
TargetEngineVersion: "v1",
|
||||
})
|
||||
_, err := client.ExecuteLobbyCommand(context.Background(), newAuthCommand(t, lobbymodel.MessageTypeGameCreate, payload))
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "game_name must not be empty")
|
||||
}
|
||||
|
||||
func TestExecuteLobbyApplicationSubmitPostsRaceName(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
created := time.Date(2026, 5, 5, 10, 0, 0, 0, time.UTC)
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, http.MethodPost, r.Method)
|
||||
require.Equal(t, "/api/v1/user/lobby/games/public-1/applications", r.URL.Path)
|
||||
|
||||
var body map[string]any
|
||||
raw, err := io.ReadAll(r.Body)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, json.Unmarshal(raw, &body))
|
||||
assert.Equal(t, "Vegan Federation", body["race_name"])
|
||||
|
||||
writeJSON(t, w, http.StatusCreated, map[string]any{
|
||||
"application_id": "app-3",
|
||||
"game_id": "public-1",
|
||||
"applicant_user_id": "user-1",
|
||||
"race_name": "Vegan Federation",
|
||||
"status": "pending",
|
||||
"created_at": created.Format(time.RFC3339Nano),
|
||||
})
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
client := newRESTClient(t, server)
|
||||
payload := mustEncode(t, transcoder.ApplicationSubmitRequestToPayload, &lobbymodel.ApplicationSubmitRequest{
|
||||
GameID: "public-1",
|
||||
RaceName: "Vegan Federation",
|
||||
})
|
||||
result, err := client.ExecuteLobbyCommand(context.Background(), newAuthCommand(t, lobbymodel.MessageTypeApplicationSubmit, payload))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "ok", result.ResultCode)
|
||||
|
||||
decoded, err := transcoder.PayloadToApplicationSubmitResponse(result.PayloadBytes)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "app-3", decoded.Application.ApplicationID)
|
||||
assert.Equal(t, "pending", decoded.Application.Status)
|
||||
}
|
||||
|
||||
func TestExecuteLobbyInviteRedeemPostsToBackend(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
created := time.Date(2026, 5, 5, 10, 0, 0, 0, time.UTC)
|
||||
expires := time.Date(2026, 5, 8, 10, 0, 0, 0, time.UTC)
|
||||
decided := time.Date(2026, 5, 6, 12, 0, 0, 0, time.UTC)
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, http.MethodPost, r.Method)
|
||||
require.Equal(t, "/api/v1/user/lobby/games/private-1/invites/invite-1/redeem", r.URL.Path)
|
||||
writeJSON(t, w, http.StatusOK, map[string]any{
|
||||
"invite_id": "invite-1",
|
||||
"game_id": "private-1",
|
||||
"inviter_user_id": "user-host",
|
||||
"invited_user_id": "user-1",
|
||||
"race_name": "Vegan Federation",
|
||||
"status": "accepted",
|
||||
"created_at": created.Format(time.RFC3339Nano),
|
||||
"expires_at": expires.Format(time.RFC3339Nano),
|
||||
"decided_at": decided.Format(time.RFC3339Nano),
|
||||
})
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
client := newRESTClient(t, server)
|
||||
payload := mustEncode(t, transcoder.InviteRedeemRequestToPayload, &lobbymodel.InviteRedeemRequest{GameID: "private-1", InviteID: "invite-1"})
|
||||
result, err := client.ExecuteLobbyCommand(context.Background(), newAuthCommand(t, lobbymodel.MessageTypeInviteRedeem, payload))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "ok", result.ResultCode)
|
||||
|
||||
decoded, err := transcoder.PayloadToInviteRedeemResponse(result.PayloadBytes)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "accepted", decoded.Invite.Status)
|
||||
}
|
||||
|
||||
func TestExecuteLobbyInviteDeclinePostsToBackend(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
created := time.Date(2026, 5, 5, 10, 0, 0, 0, time.UTC)
|
||||
expires := time.Date(2026, 5, 8, 10, 0, 0, 0, time.UTC)
|
||||
decided := time.Date(2026, 5, 6, 12, 0, 0, 0, time.UTC)
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, http.MethodPost, r.Method)
|
||||
require.Equal(t, "/api/v1/user/lobby/games/private-1/invites/invite-1/decline", r.URL.Path)
|
||||
writeJSON(t, w, http.StatusOK, map[string]any{
|
||||
"invite_id": "invite-1",
|
||||
"game_id": "private-1",
|
||||
"inviter_user_id": "user-host",
|
||||
"invited_user_id": "user-1",
|
||||
"race_name": "Vegan Federation",
|
||||
"status": "declined",
|
||||
"created_at": created.Format(time.RFC3339Nano),
|
||||
"expires_at": expires.Format(time.RFC3339Nano),
|
||||
"decided_at": decided.Format(time.RFC3339Nano),
|
||||
})
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
client := newRESTClient(t, server)
|
||||
payload := mustEncode(t, transcoder.InviteDeclineRequestToPayload, &lobbymodel.InviteDeclineRequest{GameID: "private-1", InviteID: "invite-1"})
|
||||
result, err := client.ExecuteLobbyCommand(context.Background(), newAuthCommand(t, lobbymodel.MessageTypeInviteDecline, payload))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "ok", result.ResultCode)
|
||||
|
||||
decoded, err := transcoder.PayloadToInviteDeclineResponse(result.PayloadBytes)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "declined", decoded.Invite.Status)
|
||||
}
|
||||
|
||||
func TestExecuteLobbyProjectsBackendErrorAcrossCommands(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
messageType string
|
||||
payload []byte
|
||||
statusCode int
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "public games conflict",
|
||||
messageType: lobbymodel.MessageTypePublicGamesList,
|
||||
payload: mustEncode(t, transcoder.PublicGamesListRequestToPayload, &lobbymodel.PublicGamesListRequest{Page: 1, PageSize: 50}),
|
||||
statusCode: http.StatusConflict,
|
||||
want: "conflict",
|
||||
},
|
||||
{
|
||||
name: "applications forbidden",
|
||||
messageType: lobbymodel.MessageTypeApplicationSubmit,
|
||||
payload: mustEncode(t, transcoder.ApplicationSubmitRequestToPayload, &lobbymodel.ApplicationSubmitRequest{GameID: "g", RaceName: "r"}),
|
||||
statusCode: http.StatusForbidden,
|
||||
want: "forbidden",
|
||||
},
|
||||
{
|
||||
name: "invite redeem not found",
|
||||
messageType: lobbymodel.MessageTypeInviteRedeem,
|
||||
payload: mustEncode(t, transcoder.InviteRedeemRequestToPayload, &lobbymodel.InviteRedeemRequest{GameID: "g", InviteID: "i"}),
|
||||
statusCode: http.StatusNotFound,
|
||||
want: "subject_not_found",
|
||||
},
|
||||
{
|
||||
name: "create invalid request",
|
||||
messageType: lobbymodel.MessageTypeGameCreate,
|
||||
payload: mustEncode(t, transcoder.GameCreateRequestToPayload, validCreateRequest()),
|
||||
statusCode: http.StatusBadRequest,
|
||||
want: "invalid_request",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
writeJSON(t, w, tc.statusCode, map[string]any{
|
||||
"error": map[string]any{"code": tc.want, "message": "from backend"},
|
||||
})
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
client := newRESTClient(t, server)
|
||||
result, err := client.ExecuteLobbyCommand(context.Background(), newAuthCommand(t, tc.messageType, tc.payload))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tc.want, result.ResultCode)
|
||||
|
||||
errResp, err := transcoder.PayloadToLobbyErrorResponse(result.PayloadBytes)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tc.want, errResp.Error.Code)
|
||||
assert.Equal(t, "from backend", errResp.Error.Message)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteLobbyMapsServiceUnavailableToDownstreamError(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
client := newRESTClient(t, server)
|
||||
payload := mustEncode(t, transcoder.MyGamesListRequestToPayload, &lobbymodel.MyGamesListRequest{})
|
||||
_, err := client.ExecuteLobbyCommand(context.Background(), newAuthCommand(t, lobbymodel.MessageTypeMyGamesList, payload))
|
||||
require.Error(t, err)
|
||||
assert.True(t, errors.Is(err, downstream.ErrDownstreamUnavailable))
|
||||
}
|
||||
|
||||
func TestExecuteLobbyRejectsUnknownMessageType(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
|
||||
client := newRESTClient(t, server)
|
||||
_, err := client.ExecuteLobbyCommand(context.Background(), newAuthCommand(t, "lobby.unknown", []byte{0x01}))
|
||||
require.Error(t, err)
|
||||
assert.True(t, strings.Contains(err.Error(), "unsupported message type"))
|
||||
}
|
||||
|
||||
func validCreateRequest() *lobbymodel.GameCreateRequest {
|
||||
return &lobbymodel.GameCreateRequest{
|
||||
GameName: "Test",
|
||||
Description: "",
|
||||
MinPlayers: 2,
|
||||
MaxPlayers: 8,
|
||||
StartGapHours: 24,
|
||||
StartGapPlayers: 2,
|
||||
EnrollmentEndsAt: time.Date(2026, 6, 1, 12, 0, 0, 0, time.UTC),
|
||||
TurnSchedule: "0 0 * * *",
|
||||
TargetEngineVersion: "v1",
|
||||
}
|
||||
}
|
||||
@@ -38,8 +38,15 @@ func LobbyRoutes(client *RESTClient) map[string]downstream.Client {
|
||||
target = lobbyCommandClient{rest: client}
|
||||
}
|
||||
return map[string]downstream.Client{
|
||||
lobbymodel.MessageTypeMyGamesList: target,
|
||||
lobbymodel.MessageTypeOpenEnrollment: target,
|
||||
lobbymodel.MessageTypeMyGamesList: target,
|
||||
lobbymodel.MessageTypePublicGamesList: target,
|
||||
lobbymodel.MessageTypeMyApplicationsList: target,
|
||||
lobbymodel.MessageTypeMyInvitesList: target,
|
||||
lobbymodel.MessageTypeOpenEnrollment: target,
|
||||
lobbymodel.MessageTypeGameCreate: target,
|
||||
lobbymodel.MessageTypeApplicationSubmit: target,
|
||||
lobbymodel.MessageTypeInviteRedeem: target,
|
||||
lobbymodel.MessageTypeInviteDecline: target,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+179
-11
@@ -9,10 +9,44 @@ const (
|
||||
// used to read the calling user's own games.
|
||||
MessageTypeMyGamesList = "lobby.my.games.list"
|
||||
|
||||
// MessageTypePublicGamesList is the authenticated gateway message
|
||||
// type used to read the paginated list of joinable public games.
|
||||
MessageTypePublicGamesList = "lobby.public.games.list"
|
||||
|
||||
// MessageTypeMyApplicationsList is the authenticated gateway message
|
||||
// type used to read the caller's pending and decided applications to
|
||||
// public games.
|
||||
MessageTypeMyApplicationsList = "lobby.my.applications.list"
|
||||
|
||||
// MessageTypeMyInvitesList is the authenticated gateway message type
|
||||
// used to read the caller's pending invites to private games.
|
||||
MessageTypeMyInvitesList = "lobby.my.invites.list"
|
||||
|
||||
// MessageTypeOpenEnrollment is the authenticated gateway message
|
||||
// type used by the game owner to transition a draft game to
|
||||
// `enrollment_open`.
|
||||
MessageTypeOpenEnrollment = "lobby.game.open-enrollment"
|
||||
|
||||
// MessageTypeGameCreate is the authenticated gateway message type
|
||||
// used to create a private game owned by the caller. Public games
|
||||
// are created exclusively through the admin surface; the gateway
|
||||
// rejects any attempt to set visibility to `public`.
|
||||
MessageTypeGameCreate = "lobby.game.create"
|
||||
|
||||
// MessageTypeApplicationSubmit is the authenticated gateway message
|
||||
// type used by a user to submit an application to a public game in
|
||||
// `enrollment_open`.
|
||||
MessageTypeApplicationSubmit = "lobby.application.submit"
|
||||
|
||||
// MessageTypeInviteRedeem is the authenticated gateway message type
|
||||
// used to accept an outstanding invite and create the corresponding
|
||||
// membership.
|
||||
MessageTypeInviteRedeem = "lobby.invite.redeem"
|
||||
|
||||
// MessageTypeInviteDecline is the authenticated gateway message type
|
||||
// used to terminally decline an outstanding invite. No membership is
|
||||
// created.
|
||||
MessageTypeInviteDecline = "lobby.invite.decline"
|
||||
)
|
||||
|
||||
// MyGamesListRequest stores the authenticated read request for the
|
||||
@@ -26,18 +60,88 @@ type MyGamesListResponse struct {
|
||||
Items []GameSummary `json:"items"`
|
||||
}
|
||||
|
||||
// GameSummary stores one game record returned by `lobby.my.games.list`.
|
||||
// GameSummary stores one game record returned by the various lobby
|
||||
// list endpoints. `OwnerUserID` is empty for public games (no human
|
||||
// owner).
|
||||
type GameSummary struct {
|
||||
GameID string `json:"game_id"`
|
||||
GameName string `json:"game_name"`
|
||||
GameType string `json:"game_type"`
|
||||
Status string `json:"status"`
|
||||
OwnerUserID string `json:"owner_user_id"`
|
||||
MinPlayers int `json:"min_players"`
|
||||
MaxPlayers int `json:"max_players"`
|
||||
EnrollmentEndsAt time.Time `json:"enrollment_ends_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
GameID string `json:"game_id"`
|
||||
GameName string `json:"game_name"`
|
||||
GameType string `json:"game_type"`
|
||||
Status string `json:"status"`
|
||||
OwnerUserID string `json:"owner_user_id"`
|
||||
MinPlayers int `json:"min_players"`
|
||||
MaxPlayers int `json:"max_players"`
|
||||
EnrollmentEndsAt time.Time `json:"enrollment_ends_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// PublicGamesListRequest stores the paginated read request for joinable
|
||||
// public games. Page numbers start at 1; page sizes are capped by the
|
||||
// backend.
|
||||
type PublicGamesListRequest struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
}
|
||||
|
||||
// PublicGamesListResponse stores one page of public games together with
|
||||
// the pagination metadata returned by the backend.
|
||||
type PublicGamesListResponse struct {
|
||||
Items []GameSummary `json:"items"`
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
// MyApplicationsListRequest stores the authenticated read request for
|
||||
// the caller's applications. Empty body — gateway derives identity from
|
||||
// the authenticated session.
|
||||
type MyApplicationsListRequest struct{}
|
||||
|
||||
// MyApplicationsListResponse stores the caller's application list,
|
||||
// ordered as Lobby returns it.
|
||||
type MyApplicationsListResponse struct {
|
||||
Items []ApplicationSummary `json:"items"`
|
||||
}
|
||||
|
||||
// ApplicationSummary stores a single application record returned by
|
||||
// `lobby.my.applications.list` and `lobby.application.submit`.
|
||||
// `DecidedAt` is nil while the application is pending.
|
||||
type ApplicationSummary struct {
|
||||
ApplicationID string `json:"application_id"`
|
||||
GameID string `json:"game_id"`
|
||||
ApplicantUserID string `json:"applicant_user_id"`
|
||||
RaceName string `json:"race_name"`
|
||||
Status string `json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
DecidedAt *time.Time `json:"decided_at,omitempty"`
|
||||
}
|
||||
|
||||
// MyInvitesListRequest stores the authenticated read request for the
|
||||
// caller's invites. Empty body.
|
||||
type MyInvitesListRequest struct{}
|
||||
|
||||
// MyInvitesListResponse stores the caller's invite list.
|
||||
type MyInvitesListResponse struct {
|
||||
Items []InviteSummary `json:"items"`
|
||||
}
|
||||
|
||||
// InviteSummary stores one invite record returned by
|
||||
// `lobby.my.invites.list`, `lobby.invite.redeem`, and
|
||||
// `lobby.invite.decline`. `InvitedUserID` is empty for code-based
|
||||
// invites; `Code` is empty for user-bound invites; `DecidedAt` is nil
|
||||
// while the invite is still pending.
|
||||
type InviteSummary struct {
|
||||
InviteID string `json:"invite_id"`
|
||||
GameID string `json:"game_id"`
|
||||
InviterUserID string `json:"inviter_user_id"`
|
||||
InvitedUserID string `json:"invited_user_id,omitempty"`
|
||||
Code string `json:"code,omitempty"`
|
||||
RaceName string `json:"race_name"`
|
||||
Status string `json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
DecidedAt *time.Time `json:"decided_at,omitempty"`
|
||||
}
|
||||
|
||||
// OpenEnrollmentRequest stores the owner-only command that transitions
|
||||
@@ -55,6 +159,70 @@ type OpenEnrollmentResponse struct {
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// GameCreateRequest stores the create-game command issued by the user
|
||||
// surface. Visibility is always `private` here; the gateway rejects any
|
||||
// other value before forwarding to backend, mirroring the FUNCTIONAL
|
||||
// §3.3 invariant.
|
||||
type GameCreateRequest struct {
|
||||
GameName string `json:"game_name"`
|
||||
Description string `json:"description"`
|
||||
MinPlayers int `json:"min_players"`
|
||||
MaxPlayers int `json:"max_players"`
|
||||
StartGapHours int `json:"start_gap_hours"`
|
||||
StartGapPlayers int `json:"start_gap_players"`
|
||||
EnrollmentEndsAt time.Time `json:"enrollment_ends_at"`
|
||||
TurnSchedule string `json:"turn_schedule"`
|
||||
TargetEngineVersion string `json:"target_engine_version"`
|
||||
}
|
||||
|
||||
// GameCreateResponse stores the freshly created game projected onto the
|
||||
// shared GameSummary shape — the gateway does not expose runtime fields
|
||||
// at create time because the game is always in `draft` until the owner
|
||||
// transitions it.
|
||||
type GameCreateResponse struct {
|
||||
Game GameSummary `json:"game"`
|
||||
}
|
||||
|
||||
// ApplicationSubmitRequest stores the submit-application command. The
|
||||
// game must be public and in `enrollment_open`; backend rejects all
|
||||
// other states.
|
||||
type ApplicationSubmitRequest struct {
|
||||
GameID string `json:"game_id"`
|
||||
RaceName string `json:"race_name"`
|
||||
}
|
||||
|
||||
// ApplicationSubmitResponse wraps the application created by a
|
||||
// successful submit-application call.
|
||||
type ApplicationSubmitResponse struct {
|
||||
Application ApplicationSummary `json:"application"`
|
||||
}
|
||||
|
||||
// InviteRedeemRequest accepts a pending invite and creates the
|
||||
// corresponding membership at the backend.
|
||||
type InviteRedeemRequest struct {
|
||||
GameID string `json:"game_id"`
|
||||
InviteID string `json:"invite_id"`
|
||||
}
|
||||
|
||||
// InviteRedeemResponse wraps the invite record updated by a successful
|
||||
// redeem (status transitions to `accepted`).
|
||||
type InviteRedeemResponse struct {
|
||||
Invite InviteSummary `json:"invite"`
|
||||
}
|
||||
|
||||
// InviteDeclineRequest terminally declines a pending invite. No
|
||||
// membership is created.
|
||||
type InviteDeclineRequest struct {
|
||||
GameID string `json:"game_id"`
|
||||
InviteID string `json:"invite_id"`
|
||||
}
|
||||
|
||||
// InviteDeclineResponse wraps the invite record updated by a successful
|
||||
// decline (status transitions to `declined`).
|
||||
type InviteDeclineResponse struct {
|
||||
Invite InviteSummary `json:"invite"`
|
||||
}
|
||||
|
||||
// ErrorBody stores the canonical Lobby error envelope code/message
|
||||
// pair.
|
||||
type ErrorBody struct {
|
||||
|
||||
+126
-1
@@ -4,7 +4,8 @@
|
||||
// from the verified session and forwards it as `X-User-Id` to lobby.
|
||||
namespace lobby;
|
||||
|
||||
// GameSummary stores one game record returned by `lobby.my.games.list`.
|
||||
// GameSummary stores one game record returned by the lobby list
|
||||
// endpoints. owner_user_id is empty for public games (no human owner).
|
||||
// The shape matches `lobby/openapi.yaml` `MyGameSummary`.
|
||||
table GameSummary {
|
||||
game_id:string;
|
||||
@@ -31,6 +32,71 @@ table MyGamesListResponse {
|
||||
items:[GameSummary];
|
||||
}
|
||||
|
||||
// PublicGamesListRequest stores the paginated read request for joinable
|
||||
// public games. Page numbers start at 1; backend caps page_size.
|
||||
table PublicGamesListRequest {
|
||||
page:int32;
|
||||
page_size:int32;
|
||||
}
|
||||
|
||||
// PublicGamesListResponse stores one page of public games together with
|
||||
// the pagination metadata.
|
||||
table PublicGamesListResponse {
|
||||
items:[GameSummary];
|
||||
page:int32;
|
||||
page_size:int32;
|
||||
total:int32;
|
||||
}
|
||||
|
||||
// ApplicationSummary stores one application record. decided_at_ms is 0
|
||||
// while the application is pending.
|
||||
table ApplicationSummary {
|
||||
application_id:string;
|
||||
game_id:string;
|
||||
applicant_user_id:string;
|
||||
race_name:string;
|
||||
status:string;
|
||||
created_at_ms:int64;
|
||||
decided_at_ms:int64;
|
||||
}
|
||||
|
||||
// MyApplicationsListRequest stores the authenticated read request for
|
||||
// the caller's applications. Empty body.
|
||||
table MyApplicationsListRequest {
|
||||
}
|
||||
|
||||
// MyApplicationsListResponse stores the caller's applications in the
|
||||
// order the backend returns them.
|
||||
table MyApplicationsListResponse {
|
||||
items:[ApplicationSummary];
|
||||
}
|
||||
|
||||
// InviteSummary stores one invite record. invited_user_id is empty for
|
||||
// code-based invites; code is empty for user-bound invites;
|
||||
// decided_at_ms is 0 while the invite is still pending.
|
||||
table InviteSummary {
|
||||
invite_id:string;
|
||||
game_id:string;
|
||||
inviter_user_id:string;
|
||||
invited_user_id:string;
|
||||
code:string;
|
||||
race_name:string;
|
||||
status:string;
|
||||
created_at_ms:int64;
|
||||
expires_at_ms:int64;
|
||||
decided_at_ms:int64;
|
||||
}
|
||||
|
||||
// MyInvitesListRequest stores the authenticated read request for the
|
||||
// caller's invites. Empty body.
|
||||
table MyInvitesListRequest {
|
||||
}
|
||||
|
||||
// MyInvitesListResponse stores the caller's invite list.
|
||||
table MyInvitesListResponse {
|
||||
items:[InviteSummary];
|
||||
}
|
||||
|
||||
// OpenEnrollmentRequest stores the owner-only command that transitions
|
||||
// a game from `draft` to `enrollment_open`.
|
||||
table OpenEnrollmentRequest {
|
||||
@@ -43,6 +109,65 @@ table OpenEnrollmentResponse {
|
||||
status:string;
|
||||
}
|
||||
|
||||
// GameCreateRequest stores the create-game command. Visibility is
|
||||
// always `private` for the user surface; the gateway rejects any other
|
||||
// value before forwarding to backend.
|
||||
table GameCreateRequest {
|
||||
game_name:string;
|
||||
description:string;
|
||||
min_players:int32;
|
||||
max_players:int32;
|
||||
start_gap_hours:int32;
|
||||
start_gap_players:int32;
|
||||
enrollment_ends_at_ms:int64;
|
||||
turn_schedule:string;
|
||||
target_engine_version:string;
|
||||
}
|
||||
|
||||
// GameCreateResponse wraps the freshly created game projected onto the
|
||||
// shared GameSummary shape.
|
||||
table GameCreateResponse {
|
||||
game:GameSummary;
|
||||
}
|
||||
|
||||
// ApplicationSubmitRequest stores the submit-application command for a
|
||||
// public game in `enrollment_open`.
|
||||
table ApplicationSubmitRequest {
|
||||
game_id:string;
|
||||
race_name:string;
|
||||
}
|
||||
|
||||
// ApplicationSubmitResponse wraps the freshly created application
|
||||
// record.
|
||||
table ApplicationSubmitResponse {
|
||||
application:ApplicationSummary;
|
||||
}
|
||||
|
||||
// InviteRedeemRequest accepts a pending invite and creates the
|
||||
// corresponding membership.
|
||||
table InviteRedeemRequest {
|
||||
game_id:string;
|
||||
invite_id:string;
|
||||
}
|
||||
|
||||
// InviteRedeemResponse wraps the updated invite record (status
|
||||
// transitioned to `accepted`).
|
||||
table InviteRedeemResponse {
|
||||
invite:InviteSummary;
|
||||
}
|
||||
|
||||
// InviteDeclineRequest terminally declines a pending invite.
|
||||
table InviteDeclineRequest {
|
||||
game_id:string;
|
||||
invite_id:string;
|
||||
}
|
||||
|
||||
// InviteDeclineResponse wraps the updated invite record (status
|
||||
// transitioned to `declined`).
|
||||
table InviteDeclineResponse {
|
||||
invite:InviteSummary;
|
||||
}
|
||||
|
||||
// ErrorBody stores the canonical lobby error envelope code/message
|
||||
// pair.
|
||||
table ErrorBody {
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type ApplicationSubmitRequest struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsApplicationSubmitRequest(buf []byte, offset flatbuffers.UOffsetT) *ApplicationSubmitRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &ApplicationSubmitRequest{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishApplicationSubmitRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsApplicationSubmitRequest(buf []byte, offset flatbuffers.UOffsetT) *ApplicationSubmitRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &ApplicationSubmitRequest{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedApplicationSubmitRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSubmitRequest) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSubmitRequest) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSubmitRequest) GameId() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSubmitRequest) RaceName() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ApplicationSubmitRequestStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(2)
|
||||
}
|
||||
func ApplicationSubmitRequestAddGameId(builder *flatbuffers.Builder, gameId flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(gameId), 0)
|
||||
}
|
||||
func ApplicationSubmitRequestAddRaceName(builder *flatbuffers.Builder, raceName flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(raceName), 0)
|
||||
}
|
||||
func ApplicationSubmitRequestEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type ApplicationSubmitResponse struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsApplicationSubmitResponse(buf []byte, offset flatbuffers.UOffsetT) *ApplicationSubmitResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &ApplicationSubmitResponse{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishApplicationSubmitResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsApplicationSubmitResponse(buf []byte, offset flatbuffers.UOffsetT) *ApplicationSubmitResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &ApplicationSubmitResponse{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedApplicationSubmitResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSubmitResponse) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSubmitResponse) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSubmitResponse) Application(obj *ApplicationSummary) *ApplicationSummary {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
x := rcv._tab.Indirect(o + rcv._tab.Pos)
|
||||
if obj == nil {
|
||||
obj = new(ApplicationSummary)
|
||||
}
|
||||
obj.Init(rcv._tab.Bytes, x)
|
||||
return obj
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ApplicationSubmitResponseStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(1)
|
||||
}
|
||||
func ApplicationSubmitResponseAddApplication(builder *flatbuffers.Builder, application flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(application), 0)
|
||||
}
|
||||
func ApplicationSubmitResponseEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type ApplicationSummary struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsApplicationSummary(buf []byte, offset flatbuffers.UOffsetT) *ApplicationSummary {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &ApplicationSummary{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishApplicationSummaryBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsApplicationSummary(buf []byte, offset flatbuffers.UOffsetT) *ApplicationSummary {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &ApplicationSummary{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedApplicationSummaryBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSummary) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSummary) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSummary) ApplicationId() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSummary) GameId() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSummary) ApplicantUserId() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSummary) RaceName() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSummary) Status() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSummary) CreatedAtMs() int64 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(14))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt64(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSummary) MutateCreatedAtMs(n int64) bool {
|
||||
return rcv._tab.MutateInt64Slot(14, n)
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSummary) DecidedAtMs() int64 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(16))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt64(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *ApplicationSummary) MutateDecidedAtMs(n int64) bool {
|
||||
return rcv._tab.MutateInt64Slot(16, n)
|
||||
}
|
||||
|
||||
func ApplicationSummaryStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(7)
|
||||
}
|
||||
func ApplicationSummaryAddApplicationId(builder *flatbuffers.Builder, applicationId flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(applicationId), 0)
|
||||
}
|
||||
func ApplicationSummaryAddGameId(builder *flatbuffers.Builder, gameId flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(gameId), 0)
|
||||
}
|
||||
func ApplicationSummaryAddApplicantUserId(builder *flatbuffers.Builder, applicantUserId flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(applicantUserId), 0)
|
||||
}
|
||||
func ApplicationSummaryAddRaceName(builder *flatbuffers.Builder, raceName flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(raceName), 0)
|
||||
}
|
||||
func ApplicationSummaryAddStatus(builder *flatbuffers.Builder, status flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(4, flatbuffers.UOffsetT(status), 0)
|
||||
}
|
||||
func ApplicationSummaryAddCreatedAtMs(builder *flatbuffers.Builder, createdAtMs int64) {
|
||||
builder.PrependInt64Slot(5, createdAtMs, 0)
|
||||
}
|
||||
func ApplicationSummaryAddDecidedAtMs(builder *flatbuffers.Builder, decidedAtMs int64) {
|
||||
builder.PrependInt64Slot(6, decidedAtMs, 0)
|
||||
}
|
||||
func ApplicationSummaryEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type GameCreateRequest struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsGameCreateRequest(buf []byte, offset flatbuffers.UOffsetT) *GameCreateRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &GameCreateRequest{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishGameCreateRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsGameCreateRequest(buf []byte, offset flatbuffers.UOffsetT) *GameCreateRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &GameCreateRequest{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedGameCreateRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) GameName() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) Description() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) MinPlayers() int32 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt32(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) MutateMinPlayers(n int32) bool {
|
||||
return rcv._tab.MutateInt32Slot(8, n)
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) MaxPlayers() int32 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt32(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) MutateMaxPlayers(n int32) bool {
|
||||
return rcv._tab.MutateInt32Slot(10, n)
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) StartGapHours() int32 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt32(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) MutateStartGapHours(n int32) bool {
|
||||
return rcv._tab.MutateInt32Slot(12, n)
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) StartGapPlayers() int32 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(14))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt32(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) MutateStartGapPlayers(n int32) bool {
|
||||
return rcv._tab.MutateInt32Slot(14, n)
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) EnrollmentEndsAtMs() int64 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(16))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt64(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) MutateEnrollmentEndsAtMs(n int64) bool {
|
||||
return rcv._tab.MutateInt64Slot(16, n)
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) TurnSchedule() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(18))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *GameCreateRequest) TargetEngineVersion() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(20))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GameCreateRequestStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(9)
|
||||
}
|
||||
func GameCreateRequestAddGameName(builder *flatbuffers.Builder, gameName flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(gameName), 0)
|
||||
}
|
||||
func GameCreateRequestAddDescription(builder *flatbuffers.Builder, description flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(description), 0)
|
||||
}
|
||||
func GameCreateRequestAddMinPlayers(builder *flatbuffers.Builder, minPlayers int32) {
|
||||
builder.PrependInt32Slot(2, minPlayers, 0)
|
||||
}
|
||||
func GameCreateRequestAddMaxPlayers(builder *flatbuffers.Builder, maxPlayers int32) {
|
||||
builder.PrependInt32Slot(3, maxPlayers, 0)
|
||||
}
|
||||
func GameCreateRequestAddStartGapHours(builder *flatbuffers.Builder, startGapHours int32) {
|
||||
builder.PrependInt32Slot(4, startGapHours, 0)
|
||||
}
|
||||
func GameCreateRequestAddStartGapPlayers(builder *flatbuffers.Builder, startGapPlayers int32) {
|
||||
builder.PrependInt32Slot(5, startGapPlayers, 0)
|
||||
}
|
||||
func GameCreateRequestAddEnrollmentEndsAtMs(builder *flatbuffers.Builder, enrollmentEndsAtMs int64) {
|
||||
builder.PrependInt64Slot(6, enrollmentEndsAtMs, 0)
|
||||
}
|
||||
func GameCreateRequestAddTurnSchedule(builder *flatbuffers.Builder, turnSchedule flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(7, flatbuffers.UOffsetT(turnSchedule), 0)
|
||||
}
|
||||
func GameCreateRequestAddTargetEngineVersion(builder *flatbuffers.Builder, targetEngineVersion flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(8, flatbuffers.UOffsetT(targetEngineVersion), 0)
|
||||
}
|
||||
func GameCreateRequestEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type GameCreateResponse struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsGameCreateResponse(buf []byte, offset flatbuffers.UOffsetT) *GameCreateResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &GameCreateResponse{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishGameCreateResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsGameCreateResponse(buf []byte, offset flatbuffers.UOffsetT) *GameCreateResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &GameCreateResponse{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedGameCreateResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *GameCreateResponse) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *GameCreateResponse) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *GameCreateResponse) Game(obj *GameSummary) *GameSummary {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
x := rcv._tab.Indirect(o + rcv._tab.Pos)
|
||||
if obj == nil {
|
||||
obj = new(GameSummary)
|
||||
}
|
||||
obj.Init(rcv._tab.Bytes, x)
|
||||
return obj
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GameCreateResponseStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(1)
|
||||
}
|
||||
func GameCreateResponseAddGame(builder *flatbuffers.Builder, game flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(game), 0)
|
||||
}
|
||||
func GameCreateResponseEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type InviteDeclineRequest struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsInviteDeclineRequest(buf []byte, offset flatbuffers.UOffsetT) *InviteDeclineRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &InviteDeclineRequest{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishInviteDeclineRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsInviteDeclineRequest(buf []byte, offset flatbuffers.UOffsetT) *InviteDeclineRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &InviteDeclineRequest{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedInviteDeclineRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *InviteDeclineRequest) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *InviteDeclineRequest) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *InviteDeclineRequest) GameId() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *InviteDeclineRequest) InviteId() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func InviteDeclineRequestStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(2)
|
||||
}
|
||||
func InviteDeclineRequestAddGameId(builder *flatbuffers.Builder, gameId flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(gameId), 0)
|
||||
}
|
||||
func InviteDeclineRequestAddInviteId(builder *flatbuffers.Builder, inviteId flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(inviteId), 0)
|
||||
}
|
||||
func InviteDeclineRequestEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type InviteDeclineResponse struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsInviteDeclineResponse(buf []byte, offset flatbuffers.UOffsetT) *InviteDeclineResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &InviteDeclineResponse{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishInviteDeclineResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsInviteDeclineResponse(buf []byte, offset flatbuffers.UOffsetT) *InviteDeclineResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &InviteDeclineResponse{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedInviteDeclineResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *InviteDeclineResponse) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *InviteDeclineResponse) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *InviteDeclineResponse) Invite(obj *InviteSummary) *InviteSummary {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
x := rcv._tab.Indirect(o + rcv._tab.Pos)
|
||||
if obj == nil {
|
||||
obj = new(InviteSummary)
|
||||
}
|
||||
obj.Init(rcv._tab.Bytes, x)
|
||||
return obj
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func InviteDeclineResponseStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(1)
|
||||
}
|
||||
func InviteDeclineResponseAddInvite(builder *flatbuffers.Builder, invite flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(invite), 0)
|
||||
}
|
||||
func InviteDeclineResponseEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type InviteRedeemRequest struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsInviteRedeemRequest(buf []byte, offset flatbuffers.UOffsetT) *InviteRedeemRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &InviteRedeemRequest{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishInviteRedeemRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsInviteRedeemRequest(buf []byte, offset flatbuffers.UOffsetT) *InviteRedeemRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &InviteRedeemRequest{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedInviteRedeemRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *InviteRedeemRequest) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *InviteRedeemRequest) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *InviteRedeemRequest) GameId() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *InviteRedeemRequest) InviteId() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func InviteRedeemRequestStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(2)
|
||||
}
|
||||
func InviteRedeemRequestAddGameId(builder *flatbuffers.Builder, gameId flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(gameId), 0)
|
||||
}
|
||||
func InviteRedeemRequestAddInviteId(builder *flatbuffers.Builder, inviteId flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(inviteId), 0)
|
||||
}
|
||||
func InviteRedeemRequestEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type InviteRedeemResponse struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsInviteRedeemResponse(buf []byte, offset flatbuffers.UOffsetT) *InviteRedeemResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &InviteRedeemResponse{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishInviteRedeemResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsInviteRedeemResponse(buf []byte, offset flatbuffers.UOffsetT) *InviteRedeemResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &InviteRedeemResponse{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedInviteRedeemResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *InviteRedeemResponse) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *InviteRedeemResponse) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *InviteRedeemResponse) Invite(obj *InviteSummary) *InviteSummary {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
x := rcv._tab.Indirect(o + rcv._tab.Pos)
|
||||
if obj == nil {
|
||||
obj = new(InviteSummary)
|
||||
}
|
||||
obj.Init(rcv._tab.Bytes, x)
|
||||
return obj
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func InviteRedeemResponseStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(1)
|
||||
}
|
||||
func InviteRedeemResponseAddInvite(builder *flatbuffers.Builder, invite flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(invite), 0)
|
||||
}
|
||||
func InviteRedeemResponseEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type InviteSummary struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsInviteSummary(buf []byte, offset flatbuffers.UOffsetT) *InviteSummary {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &InviteSummary{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishInviteSummaryBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsInviteSummary(buf []byte, offset flatbuffers.UOffsetT) *InviteSummary {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &InviteSummary{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedInviteSummaryBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) InviteId() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) GameId() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) InviterUserId() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) InvitedUserId() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) Code() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) RaceName() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(14))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) Status() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(16))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) CreatedAtMs() int64 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(18))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt64(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) MutateCreatedAtMs(n int64) bool {
|
||||
return rcv._tab.MutateInt64Slot(18, n)
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) ExpiresAtMs() int64 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(20))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt64(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) MutateExpiresAtMs(n int64) bool {
|
||||
return rcv._tab.MutateInt64Slot(20, n)
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) DecidedAtMs() int64 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(22))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt64(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *InviteSummary) MutateDecidedAtMs(n int64) bool {
|
||||
return rcv._tab.MutateInt64Slot(22, n)
|
||||
}
|
||||
|
||||
func InviteSummaryStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(10)
|
||||
}
|
||||
func InviteSummaryAddInviteId(builder *flatbuffers.Builder, inviteId flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(inviteId), 0)
|
||||
}
|
||||
func InviteSummaryAddGameId(builder *flatbuffers.Builder, gameId flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(gameId), 0)
|
||||
}
|
||||
func InviteSummaryAddInviterUserId(builder *flatbuffers.Builder, inviterUserId flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(inviterUserId), 0)
|
||||
}
|
||||
func InviteSummaryAddInvitedUserId(builder *flatbuffers.Builder, invitedUserId flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(invitedUserId), 0)
|
||||
}
|
||||
func InviteSummaryAddCode(builder *flatbuffers.Builder, code flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(4, flatbuffers.UOffsetT(code), 0)
|
||||
}
|
||||
func InviteSummaryAddRaceName(builder *flatbuffers.Builder, raceName flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(5, flatbuffers.UOffsetT(raceName), 0)
|
||||
}
|
||||
func InviteSummaryAddStatus(builder *flatbuffers.Builder, status flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(6, flatbuffers.UOffsetT(status), 0)
|
||||
}
|
||||
func InviteSummaryAddCreatedAtMs(builder *flatbuffers.Builder, createdAtMs int64) {
|
||||
builder.PrependInt64Slot(7, createdAtMs, 0)
|
||||
}
|
||||
func InviteSummaryAddExpiresAtMs(builder *flatbuffers.Builder, expiresAtMs int64) {
|
||||
builder.PrependInt64Slot(8, expiresAtMs, 0)
|
||||
}
|
||||
func InviteSummaryAddDecidedAtMs(builder *flatbuffers.Builder, decidedAtMs int64) {
|
||||
builder.PrependInt64Slot(9, decidedAtMs, 0)
|
||||
}
|
||||
func InviteSummaryEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type MyApplicationsListRequest struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsMyApplicationsListRequest(buf []byte, offset flatbuffers.UOffsetT) *MyApplicationsListRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &MyApplicationsListRequest{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishMyApplicationsListRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsMyApplicationsListRequest(buf []byte, offset flatbuffers.UOffsetT) *MyApplicationsListRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &MyApplicationsListRequest{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedMyApplicationsListRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *MyApplicationsListRequest) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *MyApplicationsListRequest) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func MyApplicationsListRequestStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(0)
|
||||
}
|
||||
func MyApplicationsListRequestEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type MyApplicationsListResponse struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsMyApplicationsListResponse(buf []byte, offset flatbuffers.UOffsetT) *MyApplicationsListResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &MyApplicationsListResponse{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishMyApplicationsListResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsMyApplicationsListResponse(buf []byte, offset flatbuffers.UOffsetT) *MyApplicationsListResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &MyApplicationsListResponse{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedMyApplicationsListResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *MyApplicationsListResponse) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *MyApplicationsListResponse) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *MyApplicationsListResponse) Items(obj *ApplicationSummary, j int) bool {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
x := rcv._tab.Vector(o)
|
||||
x += flatbuffers.UOffsetT(j) * 4
|
||||
x = rcv._tab.Indirect(x)
|
||||
obj.Init(rcv._tab.Bytes, x)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (rcv *MyApplicationsListResponse) ItemsLength() int {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
return rcv._tab.VectorLen(o)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func MyApplicationsListResponseStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(1)
|
||||
}
|
||||
func MyApplicationsListResponseAddItems(builder *flatbuffers.Builder, items flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(items), 0)
|
||||
}
|
||||
func MyApplicationsListResponseStartItemsVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
|
||||
return builder.StartVector(4, numElems, 4)
|
||||
}
|
||||
func MyApplicationsListResponseEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type MyInvitesListRequest struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsMyInvitesListRequest(buf []byte, offset flatbuffers.UOffsetT) *MyInvitesListRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &MyInvitesListRequest{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishMyInvitesListRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsMyInvitesListRequest(buf []byte, offset flatbuffers.UOffsetT) *MyInvitesListRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &MyInvitesListRequest{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedMyInvitesListRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *MyInvitesListRequest) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *MyInvitesListRequest) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func MyInvitesListRequestStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(0)
|
||||
}
|
||||
func MyInvitesListRequestEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type MyInvitesListResponse struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsMyInvitesListResponse(buf []byte, offset flatbuffers.UOffsetT) *MyInvitesListResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &MyInvitesListResponse{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishMyInvitesListResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsMyInvitesListResponse(buf []byte, offset flatbuffers.UOffsetT) *MyInvitesListResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &MyInvitesListResponse{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedMyInvitesListResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *MyInvitesListResponse) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *MyInvitesListResponse) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *MyInvitesListResponse) Items(obj *InviteSummary, j int) bool {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
x := rcv._tab.Vector(o)
|
||||
x += flatbuffers.UOffsetT(j) * 4
|
||||
x = rcv._tab.Indirect(x)
|
||||
obj.Init(rcv._tab.Bytes, x)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (rcv *MyInvitesListResponse) ItemsLength() int {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
return rcv._tab.VectorLen(o)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func MyInvitesListResponseStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(1)
|
||||
}
|
||||
func MyInvitesListResponseAddItems(builder *flatbuffers.Builder, items flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(items), 0)
|
||||
}
|
||||
func MyInvitesListResponseStartItemsVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
|
||||
return builder.StartVector(4, numElems, 4)
|
||||
}
|
||||
func MyInvitesListResponseEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type PublicGamesListRequest struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsPublicGamesListRequest(buf []byte, offset flatbuffers.UOffsetT) *PublicGamesListRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &PublicGamesListRequest{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishPublicGamesListRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsPublicGamesListRequest(buf []byte, offset flatbuffers.UOffsetT) *PublicGamesListRequest {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &PublicGamesListRequest{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedPublicGamesListRequestBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListRequest) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListRequest) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListRequest) Page() int32 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt32(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListRequest) MutatePage(n int32) bool {
|
||||
return rcv._tab.MutateInt32Slot(4, n)
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListRequest) PageSize() int32 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt32(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListRequest) MutatePageSize(n int32) bool {
|
||||
return rcv._tab.MutateInt32Slot(6, n)
|
||||
}
|
||||
|
||||
func PublicGamesListRequestStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(2)
|
||||
}
|
||||
func PublicGamesListRequestAddPage(builder *flatbuffers.Builder, page int32) {
|
||||
builder.PrependInt32Slot(0, page, 0)
|
||||
}
|
||||
func PublicGamesListRequestAddPageSize(builder *flatbuffers.Builder, pageSize int32) {
|
||||
builder.PrependInt32Slot(1, pageSize, 0)
|
||||
}
|
||||
func PublicGamesListRequestEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
|
||||
|
||||
package lobby
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type PublicGamesListResponse struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsPublicGamesListResponse(buf []byte, offset flatbuffers.UOffsetT) *PublicGamesListResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &PublicGamesListResponse{}
|
||||
x.Init(buf, n+offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishPublicGamesListResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.Finish(offset)
|
||||
}
|
||||
|
||||
func GetSizePrefixedRootAsPublicGamesListResponse(buf []byte, offset flatbuffers.UOffsetT) *PublicGamesListResponse {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset+flatbuffers.SizeUint32:])
|
||||
x := &PublicGamesListResponse{}
|
||||
x.Init(buf, n+offset+flatbuffers.SizeUint32)
|
||||
return x
|
||||
}
|
||||
|
||||
func FinishSizePrefixedPublicGamesListResponseBuffer(builder *flatbuffers.Builder, offset flatbuffers.UOffsetT) {
|
||||
builder.FinishSizePrefixed(offset)
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListResponse) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListResponse) Table() flatbuffers.Table {
|
||||
return rcv._tab
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListResponse) Items(obj *GameSummary, j int) bool {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
x := rcv._tab.Vector(o)
|
||||
x += flatbuffers.UOffsetT(j) * 4
|
||||
x = rcv._tab.Indirect(x)
|
||||
obj.Init(rcv._tab.Bytes, x)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListResponse) ItemsLength() int {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
|
||||
if o != 0 {
|
||||
return rcv._tab.VectorLen(o)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListResponse) Page() int32 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt32(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListResponse) MutatePage(n int32) bool {
|
||||
return rcv._tab.MutateInt32Slot(6, n)
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListResponse) PageSize() int32 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt32(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListResponse) MutatePageSize(n int32) bool {
|
||||
return rcv._tab.MutateInt32Slot(8, n)
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListResponse) Total() int32 {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
|
||||
if o != 0 {
|
||||
return rcv._tab.GetInt32(o + rcv._tab.Pos)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *PublicGamesListResponse) MutateTotal(n int32) bool {
|
||||
return rcv._tab.MutateInt32Slot(10, n)
|
||||
}
|
||||
|
||||
func PublicGamesListResponseStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(4)
|
||||
}
|
||||
func PublicGamesListResponseAddItems(builder *flatbuffers.Builder, items flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(items), 0)
|
||||
}
|
||||
func PublicGamesListResponseStartItemsVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
|
||||
return builder.StartVector(4, numElems, 4)
|
||||
}
|
||||
func PublicGamesListResponseAddPage(builder *flatbuffers.Builder, page int32) {
|
||||
builder.PrependInt32Slot(1, page, 0)
|
||||
}
|
||||
func PublicGamesListResponseAddPageSize(builder *flatbuffers.Builder, pageSize int32) {
|
||||
builder.PrependInt32Slot(2, pageSize, 0)
|
||||
}
|
||||
func PublicGamesListResponseAddTotal(builder *flatbuffers.Builder, total int32) {
|
||||
builder.PrependInt32Slot(3, total, 0)
|
||||
}
|
||||
func PublicGamesListResponseEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
+641
-8
@@ -53,14 +53,7 @@ func MyGamesListResponseToPayload(response *lobbymodel.MyGamesListResponse) ([]b
|
||||
itemOffsets[index] = encodeGameSummary(builder, response.Items[index])
|
||||
}
|
||||
|
||||
var itemsVector flatbuffers.UOffsetT
|
||||
if len(itemOffsets) > 0 {
|
||||
lobbyfbs.MyGamesListResponseStartItemsVector(builder, len(itemOffsets))
|
||||
for index := len(itemOffsets) - 1; index >= 0; index-- {
|
||||
builder.PrependUOffsetT(itemOffsets[index])
|
||||
}
|
||||
itemsVector = builder.EndVector(len(itemOffsets))
|
||||
}
|
||||
itemsVector := finishOffsetVector(builder, itemOffsets)
|
||||
|
||||
lobbyfbs.MyGamesListResponseStart(builder)
|
||||
if itemsVector != 0 {
|
||||
@@ -96,6 +89,248 @@ func PayloadToMyGamesListResponse(data []byte) (result *lobbymodel.MyGamesListRe
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// PublicGamesListRequestToPayload converts lobbymodel.PublicGamesListRequest to
|
||||
// FlatBuffers bytes.
|
||||
func PublicGamesListRequestToPayload(request *lobbymodel.PublicGamesListRequest) ([]byte, error) {
|
||||
if request == nil {
|
||||
return nil, errors.New("encode public games list request payload: request is nil")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(32)
|
||||
lobbyfbs.PublicGamesListRequestStart(builder)
|
||||
lobbyfbs.PublicGamesListRequestAddPage(builder, int32(request.Page))
|
||||
lobbyfbs.PublicGamesListRequestAddPageSize(builder, int32(request.PageSize))
|
||||
offset := lobbyfbs.PublicGamesListRequestEnd(builder)
|
||||
lobbyfbs.FinishPublicGamesListRequestBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToPublicGamesListRequest converts FlatBuffers payload bytes into
|
||||
// lobbymodel.PublicGamesListRequest.
|
||||
func PayloadToPublicGamesListRequest(data []byte) (result *lobbymodel.PublicGamesListRequest, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode public games list request payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode public games list request payload", &result, &err)
|
||||
|
||||
request := lobbyfbs.GetRootAsPublicGamesListRequest(data, 0)
|
||||
return &lobbymodel.PublicGamesListRequest{
|
||||
Page: int(request.Page()),
|
||||
PageSize: int(request.PageSize()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// PublicGamesListResponseToPayload converts lobbymodel.PublicGamesListResponse
|
||||
// to FlatBuffers bytes.
|
||||
func PublicGamesListResponseToPayload(response *lobbymodel.PublicGamesListResponse) ([]byte, error) {
|
||||
if response == nil {
|
||||
return nil, errors.New("encode public games list response payload: response is nil")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(512)
|
||||
|
||||
itemOffsets := make([]flatbuffers.UOffsetT, len(response.Items))
|
||||
for index := range response.Items {
|
||||
itemOffsets[index] = encodeGameSummary(builder, response.Items[index])
|
||||
}
|
||||
itemsVector := finishOffsetVector(builder, itemOffsets)
|
||||
|
||||
lobbyfbs.PublicGamesListResponseStart(builder)
|
||||
if itemsVector != 0 {
|
||||
lobbyfbs.PublicGamesListResponseAddItems(builder, itemsVector)
|
||||
}
|
||||
lobbyfbs.PublicGamesListResponseAddPage(builder, int32(response.Page))
|
||||
lobbyfbs.PublicGamesListResponseAddPageSize(builder, int32(response.PageSize))
|
||||
lobbyfbs.PublicGamesListResponseAddTotal(builder, int32(response.Total))
|
||||
offset := lobbyfbs.PublicGamesListResponseEnd(builder)
|
||||
lobbyfbs.FinishPublicGamesListResponseBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToPublicGamesListResponse converts FlatBuffers payload bytes into
|
||||
// lobbymodel.PublicGamesListResponse.
|
||||
func PayloadToPublicGamesListResponse(data []byte) (result *lobbymodel.PublicGamesListResponse, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode public games list response payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode public games list response payload", &result, &err)
|
||||
|
||||
response := lobbyfbs.GetRootAsPublicGamesListResponse(data, 0)
|
||||
out := &lobbymodel.PublicGamesListResponse{
|
||||
Items: make([]lobbymodel.GameSummary, 0, response.ItemsLength()),
|
||||
Page: int(response.Page()),
|
||||
PageSize: int(response.PageSize()),
|
||||
Total: int(response.Total()),
|
||||
}
|
||||
|
||||
summary := new(lobbyfbs.GameSummary)
|
||||
for index := 0; index < response.ItemsLength(); index++ {
|
||||
if !response.Items(summary, index) {
|
||||
return nil, fmt.Errorf("decode public games list response payload: items[%d] is missing", index)
|
||||
}
|
||||
out.Items = append(out.Items, decodeGameSummary(summary))
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// MyApplicationsListRequestToPayload converts lobbymodel.MyApplicationsListRequest
|
||||
// to FlatBuffers bytes.
|
||||
func MyApplicationsListRequestToPayload(request *lobbymodel.MyApplicationsListRequest) ([]byte, error) {
|
||||
if request == nil {
|
||||
return nil, errors.New("encode my applications list request payload: request is nil")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(32)
|
||||
lobbyfbs.MyApplicationsListRequestStart(builder)
|
||||
offset := lobbyfbs.MyApplicationsListRequestEnd(builder)
|
||||
lobbyfbs.FinishMyApplicationsListRequestBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToMyApplicationsListRequest converts FlatBuffers payload bytes into
|
||||
// lobbymodel.MyApplicationsListRequest.
|
||||
func PayloadToMyApplicationsListRequest(data []byte) (result *lobbymodel.MyApplicationsListRequest, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode my applications list request payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode my applications list request payload", &result, &err)
|
||||
|
||||
_ = lobbyfbs.GetRootAsMyApplicationsListRequest(data, 0)
|
||||
return &lobbymodel.MyApplicationsListRequest{}, nil
|
||||
}
|
||||
|
||||
// MyApplicationsListResponseToPayload converts lobbymodel.MyApplicationsListResponse
|
||||
// to FlatBuffers bytes.
|
||||
func MyApplicationsListResponseToPayload(response *lobbymodel.MyApplicationsListResponse) ([]byte, error) {
|
||||
if response == nil {
|
||||
return nil, errors.New("encode my applications list response payload: response is nil")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(512)
|
||||
|
||||
itemOffsets := make([]flatbuffers.UOffsetT, len(response.Items))
|
||||
for index := range response.Items {
|
||||
itemOffsets[index] = encodeApplicationSummary(builder, response.Items[index])
|
||||
}
|
||||
itemsVector := finishOffsetVector(builder, itemOffsets)
|
||||
|
||||
lobbyfbs.MyApplicationsListResponseStart(builder)
|
||||
if itemsVector != 0 {
|
||||
lobbyfbs.MyApplicationsListResponseAddItems(builder, itemsVector)
|
||||
}
|
||||
offset := lobbyfbs.MyApplicationsListResponseEnd(builder)
|
||||
lobbyfbs.FinishMyApplicationsListResponseBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToMyApplicationsListResponse converts FlatBuffers payload bytes into
|
||||
// lobbymodel.MyApplicationsListResponse.
|
||||
func PayloadToMyApplicationsListResponse(data []byte) (result *lobbymodel.MyApplicationsListResponse, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode my applications list response payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode my applications list response payload", &result, &err)
|
||||
|
||||
response := lobbyfbs.GetRootAsMyApplicationsListResponse(data, 0)
|
||||
out := &lobbymodel.MyApplicationsListResponse{
|
||||
Items: make([]lobbymodel.ApplicationSummary, 0, response.ItemsLength()),
|
||||
}
|
||||
|
||||
app := new(lobbyfbs.ApplicationSummary)
|
||||
for index := 0; index < response.ItemsLength(); index++ {
|
||||
if !response.Items(app, index) {
|
||||
return nil, fmt.Errorf("decode my applications list response payload: items[%d] is missing", index)
|
||||
}
|
||||
out.Items = append(out.Items, decodeApplicationSummary(app))
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// MyInvitesListRequestToPayload converts lobbymodel.MyInvitesListRequest
|
||||
// to FlatBuffers bytes.
|
||||
func MyInvitesListRequestToPayload(request *lobbymodel.MyInvitesListRequest) ([]byte, error) {
|
||||
if request == nil {
|
||||
return nil, errors.New("encode my invites list request payload: request is nil")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(32)
|
||||
lobbyfbs.MyInvitesListRequestStart(builder)
|
||||
offset := lobbyfbs.MyInvitesListRequestEnd(builder)
|
||||
lobbyfbs.FinishMyInvitesListRequestBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToMyInvitesListRequest converts FlatBuffers payload bytes into
|
||||
// lobbymodel.MyInvitesListRequest.
|
||||
func PayloadToMyInvitesListRequest(data []byte) (result *lobbymodel.MyInvitesListRequest, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode my invites list request payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode my invites list request payload", &result, &err)
|
||||
|
||||
_ = lobbyfbs.GetRootAsMyInvitesListRequest(data, 0)
|
||||
return &lobbymodel.MyInvitesListRequest{}, nil
|
||||
}
|
||||
|
||||
// MyInvitesListResponseToPayload converts lobbymodel.MyInvitesListResponse
|
||||
// to FlatBuffers bytes.
|
||||
func MyInvitesListResponseToPayload(response *lobbymodel.MyInvitesListResponse) ([]byte, error) {
|
||||
if response == nil {
|
||||
return nil, errors.New("encode my invites list response payload: response is nil")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(512)
|
||||
|
||||
itemOffsets := make([]flatbuffers.UOffsetT, len(response.Items))
|
||||
for index := range response.Items {
|
||||
itemOffsets[index] = encodeInviteSummary(builder, response.Items[index])
|
||||
}
|
||||
itemsVector := finishOffsetVector(builder, itemOffsets)
|
||||
|
||||
lobbyfbs.MyInvitesListResponseStart(builder)
|
||||
if itemsVector != 0 {
|
||||
lobbyfbs.MyInvitesListResponseAddItems(builder, itemsVector)
|
||||
}
|
||||
offset := lobbyfbs.MyInvitesListResponseEnd(builder)
|
||||
lobbyfbs.FinishMyInvitesListResponseBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToMyInvitesListResponse converts FlatBuffers payload bytes into
|
||||
// lobbymodel.MyInvitesListResponse.
|
||||
func PayloadToMyInvitesListResponse(data []byte) (result *lobbymodel.MyInvitesListResponse, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode my invites list response payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode my invites list response payload", &result, &err)
|
||||
|
||||
response := lobbyfbs.GetRootAsMyInvitesListResponse(data, 0)
|
||||
out := &lobbymodel.MyInvitesListResponse{
|
||||
Items: make([]lobbymodel.InviteSummary, 0, response.ItemsLength()),
|
||||
}
|
||||
|
||||
invite := new(lobbyfbs.InviteSummary)
|
||||
for index := 0; index < response.ItemsLength(); index++ {
|
||||
if !response.Items(invite, index) {
|
||||
return nil, fmt.Errorf("decode my invites list response payload: items[%d] is missing", index)
|
||||
}
|
||||
out.Items = append(out.Items, decodeInviteSummary(invite))
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// OpenEnrollmentRequestToPayload converts lobbymodel.OpenEnrollmentRequest to
|
||||
// FlatBuffers bytes suitable for the authenticated gateway transport.
|
||||
func OpenEnrollmentRequestToPayload(request *lobbymodel.OpenEnrollmentRequest) ([]byte, error) {
|
||||
@@ -165,6 +400,292 @@ func PayloadToOpenEnrollmentResponse(data []byte) (result *lobbymodel.OpenEnroll
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GameCreateRequestToPayload converts lobbymodel.GameCreateRequest to
|
||||
// FlatBuffers bytes.
|
||||
func GameCreateRequestToPayload(request *lobbymodel.GameCreateRequest) ([]byte, error) {
|
||||
if request == nil {
|
||||
return nil, errors.New("encode game create request payload: request is nil")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(256)
|
||||
gameName := builder.CreateString(request.GameName)
|
||||
description := builder.CreateString(request.Description)
|
||||
turnSchedule := builder.CreateString(request.TurnSchedule)
|
||||
targetEngineVersion := builder.CreateString(request.TargetEngineVersion)
|
||||
|
||||
lobbyfbs.GameCreateRequestStart(builder)
|
||||
lobbyfbs.GameCreateRequestAddGameName(builder, gameName)
|
||||
lobbyfbs.GameCreateRequestAddDescription(builder, description)
|
||||
lobbyfbs.GameCreateRequestAddMinPlayers(builder, int32(request.MinPlayers))
|
||||
lobbyfbs.GameCreateRequestAddMaxPlayers(builder, int32(request.MaxPlayers))
|
||||
lobbyfbs.GameCreateRequestAddStartGapHours(builder, int32(request.StartGapHours))
|
||||
lobbyfbs.GameCreateRequestAddStartGapPlayers(builder, int32(request.StartGapPlayers))
|
||||
lobbyfbs.GameCreateRequestAddEnrollmentEndsAtMs(builder, request.EnrollmentEndsAt.UTC().UnixMilli())
|
||||
lobbyfbs.GameCreateRequestAddTurnSchedule(builder, turnSchedule)
|
||||
lobbyfbs.GameCreateRequestAddTargetEngineVersion(builder, targetEngineVersion)
|
||||
offset := lobbyfbs.GameCreateRequestEnd(builder)
|
||||
lobbyfbs.FinishGameCreateRequestBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToGameCreateRequest converts FlatBuffers payload bytes into
|
||||
// lobbymodel.GameCreateRequest.
|
||||
func PayloadToGameCreateRequest(data []byte) (result *lobbymodel.GameCreateRequest, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode game create request payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode game create request payload", &result, &err)
|
||||
|
||||
request := lobbyfbs.GetRootAsGameCreateRequest(data, 0)
|
||||
return &lobbymodel.GameCreateRequest{
|
||||
GameName: string(request.GameName()),
|
||||
Description: string(request.Description()),
|
||||
MinPlayers: int(request.MinPlayers()),
|
||||
MaxPlayers: int(request.MaxPlayers()),
|
||||
StartGapHours: int(request.StartGapHours()),
|
||||
StartGapPlayers: int(request.StartGapPlayers()),
|
||||
EnrollmentEndsAt: time.UnixMilli(request.EnrollmentEndsAtMs()).UTC(),
|
||||
TurnSchedule: string(request.TurnSchedule()),
|
||||
TargetEngineVersion: string(request.TargetEngineVersion()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GameCreateResponseToPayload converts lobbymodel.GameCreateResponse to
|
||||
// FlatBuffers bytes.
|
||||
func GameCreateResponseToPayload(response *lobbymodel.GameCreateResponse) ([]byte, error) {
|
||||
if response == nil {
|
||||
return nil, errors.New("encode game create response payload: response is nil")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(256)
|
||||
gameOffset := encodeGameSummary(builder, response.Game)
|
||||
|
||||
lobbyfbs.GameCreateResponseStart(builder)
|
||||
lobbyfbs.GameCreateResponseAddGame(builder, gameOffset)
|
||||
offset := lobbyfbs.GameCreateResponseEnd(builder)
|
||||
lobbyfbs.FinishGameCreateResponseBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToGameCreateResponse converts FlatBuffers payload bytes into
|
||||
// lobbymodel.GameCreateResponse.
|
||||
func PayloadToGameCreateResponse(data []byte) (result *lobbymodel.GameCreateResponse, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode game create response payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode game create response payload", &result, &err)
|
||||
|
||||
response := lobbyfbs.GetRootAsGameCreateResponse(data, 0)
|
||||
game := response.Game(nil)
|
||||
if game == nil {
|
||||
return nil, errors.New("decode game create response payload: game is missing")
|
||||
}
|
||||
return &lobbymodel.GameCreateResponse{
|
||||
Game: decodeGameSummary(game),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ApplicationSubmitRequestToPayload converts lobbymodel.ApplicationSubmitRequest
|
||||
// to FlatBuffers bytes.
|
||||
func ApplicationSubmitRequestToPayload(request *lobbymodel.ApplicationSubmitRequest) ([]byte, error) {
|
||||
if request == nil {
|
||||
return nil, errors.New("encode application submit request payload: request is nil")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(128)
|
||||
gameID := builder.CreateString(request.GameID)
|
||||
raceName := builder.CreateString(request.RaceName)
|
||||
|
||||
lobbyfbs.ApplicationSubmitRequestStart(builder)
|
||||
lobbyfbs.ApplicationSubmitRequestAddGameId(builder, gameID)
|
||||
lobbyfbs.ApplicationSubmitRequestAddRaceName(builder, raceName)
|
||||
offset := lobbyfbs.ApplicationSubmitRequestEnd(builder)
|
||||
lobbyfbs.FinishApplicationSubmitRequestBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToApplicationSubmitRequest converts FlatBuffers payload bytes into
|
||||
// lobbymodel.ApplicationSubmitRequest.
|
||||
func PayloadToApplicationSubmitRequest(data []byte) (result *lobbymodel.ApplicationSubmitRequest, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode application submit request payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode application submit request payload", &result, &err)
|
||||
|
||||
request := lobbyfbs.GetRootAsApplicationSubmitRequest(data, 0)
|
||||
return &lobbymodel.ApplicationSubmitRequest{
|
||||
GameID: string(request.GameId()),
|
||||
RaceName: string(request.RaceName()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ApplicationSubmitResponseToPayload converts lobbymodel.ApplicationSubmitResponse
|
||||
// to FlatBuffers bytes.
|
||||
func ApplicationSubmitResponseToPayload(response *lobbymodel.ApplicationSubmitResponse) ([]byte, error) {
|
||||
if response == nil {
|
||||
return nil, errors.New("encode application submit response payload: response is nil")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(256)
|
||||
appOffset := encodeApplicationSummary(builder, response.Application)
|
||||
|
||||
lobbyfbs.ApplicationSubmitResponseStart(builder)
|
||||
lobbyfbs.ApplicationSubmitResponseAddApplication(builder, appOffset)
|
||||
offset := lobbyfbs.ApplicationSubmitResponseEnd(builder)
|
||||
lobbyfbs.FinishApplicationSubmitResponseBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToApplicationSubmitResponse converts FlatBuffers payload bytes into
|
||||
// lobbymodel.ApplicationSubmitResponse.
|
||||
func PayloadToApplicationSubmitResponse(data []byte) (result *lobbymodel.ApplicationSubmitResponse, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode application submit response payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode application submit response payload", &result, &err)
|
||||
|
||||
response := lobbyfbs.GetRootAsApplicationSubmitResponse(data, 0)
|
||||
app := response.Application(nil)
|
||||
if app == nil {
|
||||
return nil, errors.New("decode application submit response payload: application is missing")
|
||||
}
|
||||
return &lobbymodel.ApplicationSubmitResponse{
|
||||
Application: decodeApplicationSummary(app),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// InviteRedeemRequestToPayload converts lobbymodel.InviteRedeemRequest to
|
||||
// FlatBuffers bytes.
|
||||
func InviteRedeemRequestToPayload(request *lobbymodel.InviteRedeemRequest) ([]byte, error) {
|
||||
if request == nil {
|
||||
return nil, errors.New("encode invite redeem request payload: request is nil")
|
||||
}
|
||||
return encodeInviteAction(request.GameID, request.InviteID, true)
|
||||
}
|
||||
|
||||
// PayloadToInviteRedeemRequest converts FlatBuffers payload bytes into
|
||||
// lobbymodel.InviteRedeemRequest.
|
||||
func PayloadToInviteRedeemRequest(data []byte) (result *lobbymodel.InviteRedeemRequest, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode invite redeem request payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode invite redeem request payload", &result, &err)
|
||||
|
||||
request := lobbyfbs.GetRootAsInviteRedeemRequest(data, 0)
|
||||
return &lobbymodel.InviteRedeemRequest{
|
||||
GameID: string(request.GameId()),
|
||||
InviteID: string(request.InviteId()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// InviteRedeemResponseToPayload converts lobbymodel.InviteRedeemResponse to
|
||||
// FlatBuffers bytes.
|
||||
func InviteRedeemResponseToPayload(response *lobbymodel.InviteRedeemResponse) ([]byte, error) {
|
||||
if response == nil {
|
||||
return nil, errors.New("encode invite redeem response payload: response is nil")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(256)
|
||||
inviteOffset := encodeInviteSummary(builder, response.Invite)
|
||||
|
||||
lobbyfbs.InviteRedeemResponseStart(builder)
|
||||
lobbyfbs.InviteRedeemResponseAddInvite(builder, inviteOffset)
|
||||
offset := lobbyfbs.InviteRedeemResponseEnd(builder)
|
||||
lobbyfbs.FinishInviteRedeemResponseBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToInviteRedeemResponse converts FlatBuffers payload bytes into
|
||||
// lobbymodel.InviteRedeemResponse.
|
||||
func PayloadToInviteRedeemResponse(data []byte) (result *lobbymodel.InviteRedeemResponse, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode invite redeem response payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode invite redeem response payload", &result, &err)
|
||||
|
||||
response := lobbyfbs.GetRootAsInviteRedeemResponse(data, 0)
|
||||
invite := response.Invite(nil)
|
||||
if invite == nil {
|
||||
return nil, errors.New("decode invite redeem response payload: invite is missing")
|
||||
}
|
||||
return &lobbymodel.InviteRedeemResponse{
|
||||
Invite: decodeInviteSummary(invite),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// InviteDeclineRequestToPayload converts lobbymodel.InviteDeclineRequest to
|
||||
// FlatBuffers bytes.
|
||||
func InviteDeclineRequestToPayload(request *lobbymodel.InviteDeclineRequest) ([]byte, error) {
|
||||
if request == nil {
|
||||
return nil, errors.New("encode invite decline request payload: request is nil")
|
||||
}
|
||||
return encodeInviteAction(request.GameID, request.InviteID, false)
|
||||
}
|
||||
|
||||
// PayloadToInviteDeclineRequest converts FlatBuffers payload bytes into
|
||||
// lobbymodel.InviteDeclineRequest.
|
||||
func PayloadToInviteDeclineRequest(data []byte) (result *lobbymodel.InviteDeclineRequest, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode invite decline request payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode invite decline request payload", &result, &err)
|
||||
|
||||
request := lobbyfbs.GetRootAsInviteDeclineRequest(data, 0)
|
||||
return &lobbymodel.InviteDeclineRequest{
|
||||
GameID: string(request.GameId()),
|
||||
InviteID: string(request.InviteId()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// InviteDeclineResponseToPayload converts lobbymodel.InviteDeclineResponse to
|
||||
// FlatBuffers bytes.
|
||||
func InviteDeclineResponseToPayload(response *lobbymodel.InviteDeclineResponse) ([]byte, error) {
|
||||
if response == nil {
|
||||
return nil, errors.New("encode invite decline response payload: response is nil")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(256)
|
||||
inviteOffset := encodeInviteSummary(builder, response.Invite)
|
||||
|
||||
lobbyfbs.InviteDeclineResponseStart(builder)
|
||||
lobbyfbs.InviteDeclineResponseAddInvite(builder, inviteOffset)
|
||||
offset := lobbyfbs.InviteDeclineResponseEnd(builder)
|
||||
lobbyfbs.FinishInviteDeclineResponseBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToInviteDeclineResponse converts FlatBuffers payload bytes into
|
||||
// lobbymodel.InviteDeclineResponse.
|
||||
func PayloadToInviteDeclineResponse(data []byte) (result *lobbymodel.InviteDeclineResponse, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode invite decline response payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverLobbyDecodePanic("decode invite decline response payload", &result, &err)
|
||||
|
||||
response := lobbyfbs.GetRootAsInviteDeclineResponse(data, 0)
|
||||
invite := response.Invite(nil)
|
||||
if invite == nil {
|
||||
return nil, errors.New("decode invite decline response payload: invite is missing")
|
||||
}
|
||||
return &lobbymodel.InviteDeclineResponse{
|
||||
Invite: decodeInviteSummary(invite),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// LobbyErrorResponseToPayload converts lobbymodel.ErrorResponse to FlatBuffers
|
||||
// bytes suitable for the authenticated gateway transport.
|
||||
func LobbyErrorResponseToPayload(response *lobbymodel.ErrorResponse) ([]byte, error) {
|
||||
@@ -212,6 +733,38 @@ func PayloadToLobbyErrorResponse(data []byte) (result *lobbymodel.ErrorResponse,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func encodeInviteAction(gameID, inviteID string, redeem bool) ([]byte, error) {
|
||||
builder := flatbuffers.NewBuilder(128)
|
||||
gameOffset := builder.CreateString(gameID)
|
||||
inviteOffset := builder.CreateString(inviteID)
|
||||
|
||||
if redeem {
|
||||
lobbyfbs.InviteRedeemRequestStart(builder)
|
||||
lobbyfbs.InviteRedeemRequestAddGameId(builder, gameOffset)
|
||||
lobbyfbs.InviteRedeemRequestAddInviteId(builder, inviteOffset)
|
||||
offset := lobbyfbs.InviteRedeemRequestEnd(builder)
|
||||
lobbyfbs.FinishInviteRedeemRequestBuffer(builder, offset)
|
||||
} else {
|
||||
lobbyfbs.InviteDeclineRequestStart(builder)
|
||||
lobbyfbs.InviteDeclineRequestAddGameId(builder, gameOffset)
|
||||
lobbyfbs.InviteDeclineRequestAddInviteId(builder, inviteOffset)
|
||||
offset := lobbyfbs.InviteDeclineRequestEnd(builder)
|
||||
lobbyfbs.FinishInviteDeclineRequestBuffer(builder, offset)
|
||||
}
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
func finishOffsetVector(builder *flatbuffers.Builder, offsets []flatbuffers.UOffsetT) flatbuffers.UOffsetT {
|
||||
if len(offsets) == 0 {
|
||||
return 0
|
||||
}
|
||||
builder.StartVector(4, len(offsets), 4)
|
||||
for index := len(offsets) - 1; index >= 0; index-- {
|
||||
builder.PrependUOffsetT(offsets[index])
|
||||
}
|
||||
return builder.EndVector(len(offsets))
|
||||
}
|
||||
|
||||
func encodeGameSummary(builder *flatbuffers.Builder, summary lobbymodel.GameSummary) flatbuffers.UOffsetT {
|
||||
gameID := builder.CreateString(summary.GameID)
|
||||
gameName := builder.CreateString(summary.GameName)
|
||||
@@ -248,6 +801,86 @@ func decodeGameSummary(summary *lobbyfbs.GameSummary) lobbymodel.GameSummary {
|
||||
}
|
||||
}
|
||||
|
||||
func encodeApplicationSummary(builder *flatbuffers.Builder, app lobbymodel.ApplicationSummary) flatbuffers.UOffsetT {
|
||||
applicationID := builder.CreateString(app.ApplicationID)
|
||||
gameID := builder.CreateString(app.GameID)
|
||||
applicantUserID := builder.CreateString(app.ApplicantUserID)
|
||||
raceName := builder.CreateString(app.RaceName)
|
||||
status := builder.CreateString(app.Status)
|
||||
|
||||
lobbyfbs.ApplicationSummaryStart(builder)
|
||||
lobbyfbs.ApplicationSummaryAddApplicationId(builder, applicationID)
|
||||
lobbyfbs.ApplicationSummaryAddGameId(builder, gameID)
|
||||
lobbyfbs.ApplicationSummaryAddApplicantUserId(builder, applicantUserID)
|
||||
lobbyfbs.ApplicationSummaryAddRaceName(builder, raceName)
|
||||
lobbyfbs.ApplicationSummaryAddStatus(builder, status)
|
||||
lobbyfbs.ApplicationSummaryAddCreatedAtMs(builder, app.CreatedAt.UTC().UnixMilli())
|
||||
lobbyfbs.ApplicationSummaryAddDecidedAtMs(builder, unixMilliFromOptional(app.DecidedAt))
|
||||
return lobbyfbs.ApplicationSummaryEnd(builder)
|
||||
}
|
||||
|
||||
func decodeApplicationSummary(app *lobbyfbs.ApplicationSummary) lobbymodel.ApplicationSummary {
|
||||
return lobbymodel.ApplicationSummary{
|
||||
ApplicationID: string(app.ApplicationId()),
|
||||
GameID: string(app.GameId()),
|
||||
ApplicantUserID: string(app.ApplicantUserId()),
|
||||
RaceName: string(app.RaceName()),
|
||||
Status: string(app.Status()),
|
||||
CreatedAt: time.UnixMilli(app.CreatedAtMs()).UTC(),
|
||||
DecidedAt: optionalUnixMilli(app.DecidedAtMs()),
|
||||
}
|
||||
}
|
||||
|
||||
func encodeInviteSummary(builder *flatbuffers.Builder, invite lobbymodel.InviteSummary) flatbuffers.UOffsetT {
|
||||
inviteID := builder.CreateString(invite.InviteID)
|
||||
gameID := builder.CreateString(invite.GameID)
|
||||
inviterUserID := builder.CreateString(invite.InviterUserID)
|
||||
invitedUserID := builder.CreateString(invite.InvitedUserID)
|
||||
code := builder.CreateString(invite.Code)
|
||||
raceName := builder.CreateString(invite.RaceName)
|
||||
status := builder.CreateString(invite.Status)
|
||||
|
||||
lobbyfbs.InviteSummaryStart(builder)
|
||||
lobbyfbs.InviteSummaryAddInviteId(builder, inviteID)
|
||||
lobbyfbs.InviteSummaryAddGameId(builder, gameID)
|
||||
lobbyfbs.InviteSummaryAddInviterUserId(builder, inviterUserID)
|
||||
lobbyfbs.InviteSummaryAddInvitedUserId(builder, invitedUserID)
|
||||
lobbyfbs.InviteSummaryAddCode(builder, code)
|
||||
lobbyfbs.InviteSummaryAddRaceName(builder, raceName)
|
||||
lobbyfbs.InviteSummaryAddStatus(builder, status)
|
||||
lobbyfbs.InviteSummaryAddCreatedAtMs(builder, invite.CreatedAt.UTC().UnixMilli())
|
||||
lobbyfbs.InviteSummaryAddExpiresAtMs(builder, invite.ExpiresAt.UTC().UnixMilli())
|
||||
lobbyfbs.InviteSummaryAddDecidedAtMs(builder, unixMilliFromOptional(invite.DecidedAt))
|
||||
return lobbyfbs.InviteSummaryEnd(builder)
|
||||
}
|
||||
|
||||
func decodeInviteSummary(invite *lobbyfbs.InviteSummary) lobbymodel.InviteSummary {
|
||||
return lobbymodel.InviteSummary{
|
||||
InviteID: string(invite.InviteId()),
|
||||
GameID: string(invite.GameId()),
|
||||
InviterUserID: string(invite.InviterUserId()),
|
||||
InvitedUserID: string(invite.InvitedUserId()),
|
||||
Code: string(invite.Code()),
|
||||
RaceName: string(invite.RaceName()),
|
||||
Status: string(invite.Status()),
|
||||
CreatedAt: time.UnixMilli(invite.CreatedAtMs()).UTC(),
|
||||
ExpiresAt: time.UnixMilli(invite.ExpiresAtMs()).UTC(),
|
||||
DecidedAt: optionalUnixMilli(invite.DecidedAtMs()),
|
||||
}
|
||||
}
|
||||
|
||||
// unixMilliFromOptional returns 0 when the pointer is nil, else the
|
||||
// millisecond UTC timestamp. The transcoder uses 0 as the "not set"
|
||||
// sentinel because FlatBuffers tables do not carry per-field presence
|
||||
// flags, and 0 is unreachable for any realistic decided/redeemed time.
|
||||
// optionalUnixMilli (defined in user.go) is the decode counterpart.
|
||||
func unixMilliFromOptional(t *time.Time) int64 {
|
||||
if t == nil {
|
||||
return 0
|
||||
}
|
||||
return t.UTC().UnixMilli()
|
||||
}
|
||||
|
||||
func recoverLobbyDecodePanic[T any](message string, result **T, err *error) {
|
||||
if recovered := recover(); recovered != nil {
|
||||
*result = nil
|
||||
|
||||
@@ -0,0 +1,517 @@
|
||||
package transcoder
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
lobbymodel "galaxy/model/lobby"
|
||||
)
|
||||
|
||||
// fixedTimes returns deterministic UTC timestamps for round-trip
|
||||
// fixtures. Millisecond precision matches the FlatBuffers `*Ms` ints,
|
||||
// which is what the transcoder preserves.
|
||||
func fixedTimes() (created, updated, ends time.Time) {
|
||||
created = time.Date(2026, time.May, 7, 9, 30, 15, 123_000_000, time.UTC)
|
||||
updated = created.Add(2 * time.Minute)
|
||||
ends = created.Add(48 * time.Hour)
|
||||
return
|
||||
}
|
||||
|
||||
func TestLobbyMyGamesListRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
created, updated, ends := fixedTimes()
|
||||
|
||||
source := &lobbymodel.MyGamesListResponse{
|
||||
Items: []lobbymodel.GameSummary{
|
||||
{
|
||||
GameID: "game-private-7c8f",
|
||||
GameName: "First Contact",
|
||||
GameType: "private",
|
||||
Status: "draft",
|
||||
OwnerUserID: "user-9912",
|
||||
MinPlayers: 2,
|
||||
MaxPlayers: 8,
|
||||
EnrollmentEndsAt: ends,
|
||||
CreatedAt: created,
|
||||
UpdatedAt: updated,
|
||||
},
|
||||
{
|
||||
GameID: "game-public-aabb",
|
||||
GameName: "Open Lobby",
|
||||
GameType: "public",
|
||||
Status: "enrollment_open",
|
||||
OwnerUserID: "",
|
||||
MinPlayers: 4,
|
||||
MaxPlayers: 12,
|
||||
EnrollmentEndsAt: ends,
|
||||
CreatedAt: created,
|
||||
UpdatedAt: updated,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
payload, err := MyGamesListResponseToPayload(source)
|
||||
if err != nil {
|
||||
t.Fatalf("encode: %v", err)
|
||||
}
|
||||
|
||||
decoded, err := PayloadToMyGamesListResponse(payload)
|
||||
if err != nil {
|
||||
t.Fatalf("decode: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(source, decoded) {
|
||||
t.Fatalf("round-trip mismatch\nsource: %#v\ndecoded:%#v", source, decoded)
|
||||
}
|
||||
|
||||
requestBytes, err := MyGamesListRequestToPayload(&lobbymodel.MyGamesListRequest{})
|
||||
if err != nil {
|
||||
t.Fatalf("encode request: %v", err)
|
||||
}
|
||||
if _, err := PayloadToMyGamesListRequest(requestBytes); err != nil {
|
||||
t.Fatalf("decode request: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLobbyMyGamesListEmpty(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
payload, err := MyGamesListResponseToPayload(&lobbymodel.MyGamesListResponse{Items: nil})
|
||||
if err != nil {
|
||||
t.Fatalf("encode: %v", err)
|
||||
}
|
||||
decoded, err := PayloadToMyGamesListResponse(payload)
|
||||
if err != nil {
|
||||
t.Fatalf("decode: %v", err)
|
||||
}
|
||||
if got := len(decoded.Items); got != 0 {
|
||||
t.Fatalf("expected empty items, got %d", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLobbyPublicGamesListRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
created, updated, ends := fixedTimes()
|
||||
|
||||
requestSource := &lobbymodel.PublicGamesListRequest{Page: 3, PageSize: 25}
|
||||
requestBytes, err := PublicGamesListRequestToPayload(requestSource)
|
||||
if err != nil {
|
||||
t.Fatalf("encode request: %v", err)
|
||||
}
|
||||
requestDecoded, err := PayloadToPublicGamesListRequest(requestBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("decode request: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(requestSource, requestDecoded) {
|
||||
t.Fatalf("request round-trip mismatch\nsource: %#v\ndecoded:%#v", requestSource, requestDecoded)
|
||||
}
|
||||
|
||||
responseSource := &lobbymodel.PublicGamesListResponse{
|
||||
Items: []lobbymodel.GameSummary{
|
||||
{
|
||||
GameID: "game-public-aabb",
|
||||
GameName: "Open Lobby",
|
||||
GameType: "public",
|
||||
Status: "enrollment_open",
|
||||
OwnerUserID: "",
|
||||
MinPlayers: 4,
|
||||
MaxPlayers: 12,
|
||||
EnrollmentEndsAt: ends,
|
||||
CreatedAt: created,
|
||||
UpdatedAt: updated,
|
||||
},
|
||||
},
|
||||
Page: 3,
|
||||
PageSize: 25,
|
||||
Total: 51,
|
||||
}
|
||||
responseBytes, err := PublicGamesListResponseToPayload(responseSource)
|
||||
if err != nil {
|
||||
t.Fatalf("encode response: %v", err)
|
||||
}
|
||||
responseDecoded, err := PayloadToPublicGamesListResponse(responseBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("decode response: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(responseSource, responseDecoded) {
|
||||
t.Fatalf("response round-trip mismatch\nsource: %#v\ndecoded:%#v", responseSource, responseDecoded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLobbyMyApplicationsListRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
created, _, _ := fixedTimes()
|
||||
decided := created.Add(2 * time.Hour)
|
||||
|
||||
requestBytes, err := MyApplicationsListRequestToPayload(&lobbymodel.MyApplicationsListRequest{})
|
||||
if err != nil {
|
||||
t.Fatalf("encode request: %v", err)
|
||||
}
|
||||
if _, err := PayloadToMyApplicationsListRequest(requestBytes); err != nil {
|
||||
t.Fatalf("decode request: %v", err)
|
||||
}
|
||||
|
||||
source := &lobbymodel.MyApplicationsListResponse{
|
||||
Items: []lobbymodel.ApplicationSummary{
|
||||
{
|
||||
ApplicationID: "app-1",
|
||||
GameID: "game-public-aabb",
|
||||
ApplicantUserID: "user-9912",
|
||||
RaceName: "Vegan Federation",
|
||||
Status: "pending",
|
||||
CreatedAt: created,
|
||||
DecidedAt: nil,
|
||||
},
|
||||
{
|
||||
ApplicationID: "app-2",
|
||||
GameID: "game-public-ccdd",
|
||||
ApplicantUserID: "user-9912",
|
||||
RaceName: "Lithic Compact",
|
||||
Status: "approved",
|
||||
CreatedAt: created,
|
||||
DecidedAt: &decided,
|
||||
},
|
||||
},
|
||||
}
|
||||
payload, err := MyApplicationsListResponseToPayload(source)
|
||||
if err != nil {
|
||||
t.Fatalf("encode: %v", err)
|
||||
}
|
||||
decoded, err := PayloadToMyApplicationsListResponse(payload)
|
||||
if err != nil {
|
||||
t.Fatalf("decode: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(source, decoded) {
|
||||
t.Fatalf("round-trip mismatch\nsource: %#v\ndecoded:%#v", source, decoded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLobbyMyInvitesListRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
created, _, _ := fixedTimes()
|
||||
expires := created.Add(72 * time.Hour)
|
||||
decided := created.Add(1 * time.Hour)
|
||||
|
||||
requestBytes, err := MyInvitesListRequestToPayload(&lobbymodel.MyInvitesListRequest{})
|
||||
if err != nil {
|
||||
t.Fatalf("encode request: %v", err)
|
||||
}
|
||||
if _, err := PayloadToMyInvitesListRequest(requestBytes); err != nil {
|
||||
t.Fatalf("decode request: %v", err)
|
||||
}
|
||||
|
||||
source := &lobbymodel.MyInvitesListResponse{
|
||||
Items: []lobbymodel.InviteSummary{
|
||||
{
|
||||
InviteID: "invite-user-bound",
|
||||
GameID: "game-private-7c8f",
|
||||
InviterUserID: "user-1111",
|
||||
InvitedUserID: "user-9912",
|
||||
Code: "",
|
||||
RaceName: "Vegan Federation",
|
||||
Status: "pending",
|
||||
CreatedAt: created,
|
||||
ExpiresAt: expires,
|
||||
DecidedAt: nil,
|
||||
},
|
||||
{
|
||||
InviteID: "invite-code-based",
|
||||
GameID: "game-private-3322",
|
||||
InviterUserID: "user-1111",
|
||||
InvitedUserID: "",
|
||||
Code: "ABCDEF12",
|
||||
RaceName: "Lithic Compact",
|
||||
Status: "accepted",
|
||||
CreatedAt: created,
|
||||
ExpiresAt: expires,
|
||||
DecidedAt: &decided,
|
||||
},
|
||||
},
|
||||
}
|
||||
payload, err := MyInvitesListResponseToPayload(source)
|
||||
if err != nil {
|
||||
t.Fatalf("encode: %v", err)
|
||||
}
|
||||
decoded, err := PayloadToMyInvitesListResponse(payload)
|
||||
if err != nil {
|
||||
t.Fatalf("decode: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(source, decoded) {
|
||||
t.Fatalf("round-trip mismatch\nsource: %#v\ndecoded:%#v", source, decoded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLobbyOpenEnrollmentRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
requestSource := &lobbymodel.OpenEnrollmentRequest{GameID: "game-private-7c8f"}
|
||||
requestBytes, err := OpenEnrollmentRequestToPayload(requestSource)
|
||||
if err != nil {
|
||||
t.Fatalf("encode request: %v", err)
|
||||
}
|
||||
requestDecoded, err := PayloadToOpenEnrollmentRequest(requestBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("decode request: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(requestSource, requestDecoded) {
|
||||
t.Fatalf("request round-trip mismatch\nsource: %#v\ndecoded:%#v", requestSource, requestDecoded)
|
||||
}
|
||||
|
||||
responseSource := &lobbymodel.OpenEnrollmentResponse{GameID: "game-private-7c8f", Status: "enrollment_open"}
|
||||
responseBytes, err := OpenEnrollmentResponseToPayload(responseSource)
|
||||
if err != nil {
|
||||
t.Fatalf("encode response: %v", err)
|
||||
}
|
||||
responseDecoded, err := PayloadToOpenEnrollmentResponse(responseBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("decode response: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(responseSource, responseDecoded) {
|
||||
t.Fatalf("response round-trip mismatch\nsource: %#v\ndecoded:%#v", responseSource, responseDecoded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLobbyGameCreateRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, _, ends := fixedTimes()
|
||||
|
||||
requestSource := &lobbymodel.GameCreateRequest{
|
||||
GameName: "First Contact",
|
||||
Description: "First Phase 8 sandbox game",
|
||||
MinPlayers: 2,
|
||||
MaxPlayers: 8,
|
||||
StartGapHours: 24,
|
||||
StartGapPlayers: 2,
|
||||
EnrollmentEndsAt: ends,
|
||||
TurnSchedule: "0 0 * * *",
|
||||
TargetEngineVersion: "v1",
|
||||
}
|
||||
requestBytes, err := GameCreateRequestToPayload(requestSource)
|
||||
if err != nil {
|
||||
t.Fatalf("encode request: %v", err)
|
||||
}
|
||||
requestDecoded, err := PayloadToGameCreateRequest(requestBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("decode request: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(requestSource, requestDecoded) {
|
||||
t.Fatalf("request round-trip mismatch\nsource: %#v\ndecoded:%#v", requestSource, requestDecoded)
|
||||
}
|
||||
|
||||
created, updated, _ := fixedTimes()
|
||||
responseSource := &lobbymodel.GameCreateResponse{
|
||||
Game: lobbymodel.GameSummary{
|
||||
GameID: "game-private-newly-created",
|
||||
GameName: "First Contact",
|
||||
GameType: "private",
|
||||
Status: "draft",
|
||||
OwnerUserID: "user-9912",
|
||||
MinPlayers: 2,
|
||||
MaxPlayers: 8,
|
||||
EnrollmentEndsAt: ends,
|
||||
CreatedAt: created,
|
||||
UpdatedAt: updated,
|
||||
},
|
||||
}
|
||||
responseBytes, err := GameCreateResponseToPayload(responseSource)
|
||||
if err != nil {
|
||||
t.Fatalf("encode response: %v", err)
|
||||
}
|
||||
responseDecoded, err := PayloadToGameCreateResponse(responseBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("decode response: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(responseSource, responseDecoded) {
|
||||
t.Fatalf("response round-trip mismatch\nsource: %#v\ndecoded:%#v", responseSource, responseDecoded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLobbyApplicationSubmitRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
requestSource := &lobbymodel.ApplicationSubmitRequest{GameID: "game-public-aabb", RaceName: "Vegan Federation"}
|
||||
requestBytes, err := ApplicationSubmitRequestToPayload(requestSource)
|
||||
if err != nil {
|
||||
t.Fatalf("encode request: %v", err)
|
||||
}
|
||||
requestDecoded, err := PayloadToApplicationSubmitRequest(requestBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("decode request: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(requestSource, requestDecoded) {
|
||||
t.Fatalf("request round-trip mismatch\nsource: %#v\ndecoded:%#v", requestSource, requestDecoded)
|
||||
}
|
||||
|
||||
created, _, _ := fixedTimes()
|
||||
responseSource := &lobbymodel.ApplicationSubmitResponse{
|
||||
Application: lobbymodel.ApplicationSummary{
|
||||
ApplicationID: "app-3",
|
||||
GameID: "game-public-aabb",
|
||||
ApplicantUserID: "user-9912",
|
||||
RaceName: "Vegan Federation",
|
||||
Status: "pending",
|
||||
CreatedAt: created,
|
||||
DecidedAt: nil,
|
||||
},
|
||||
}
|
||||
responseBytes, err := ApplicationSubmitResponseToPayload(responseSource)
|
||||
if err != nil {
|
||||
t.Fatalf("encode response: %v", err)
|
||||
}
|
||||
responseDecoded, err := PayloadToApplicationSubmitResponse(responseBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("decode response: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(responseSource, responseDecoded) {
|
||||
t.Fatalf("response round-trip mismatch\nsource: %#v\ndecoded:%#v", responseSource, responseDecoded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLobbyInviteRedeemAndDeclineRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
created, _, _ := fixedTimes()
|
||||
expires := created.Add(72 * time.Hour)
|
||||
decided := created.Add(1 * time.Hour)
|
||||
|
||||
redeemReq := &lobbymodel.InviteRedeemRequest{GameID: "game-private-7c8f", InviteID: "invite-user-bound"}
|
||||
redeemBytes, err := InviteRedeemRequestToPayload(redeemReq)
|
||||
if err != nil {
|
||||
t.Fatalf("encode redeem request: %v", err)
|
||||
}
|
||||
redeemDecoded, err := PayloadToInviteRedeemRequest(redeemBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("decode redeem request: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(redeemReq, redeemDecoded) {
|
||||
t.Fatalf("redeem request mismatch")
|
||||
}
|
||||
|
||||
redeemResp := &lobbymodel.InviteRedeemResponse{
|
||||
Invite: lobbymodel.InviteSummary{
|
||||
InviteID: "invite-user-bound",
|
||||
GameID: "game-private-7c8f",
|
||||
InviterUserID: "user-1111",
|
||||
InvitedUserID: "user-9912",
|
||||
Code: "",
|
||||
RaceName: "Vegan Federation",
|
||||
Status: "accepted",
|
||||
CreatedAt: created,
|
||||
ExpiresAt: expires,
|
||||
DecidedAt: &decided,
|
||||
},
|
||||
}
|
||||
redeemRespBytes, err := InviteRedeemResponseToPayload(redeemResp)
|
||||
if err != nil {
|
||||
t.Fatalf("encode redeem response: %v", err)
|
||||
}
|
||||
redeemRespDecoded, err := PayloadToInviteRedeemResponse(redeemRespBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("decode redeem response: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(redeemResp, redeemRespDecoded) {
|
||||
t.Fatalf("redeem response mismatch")
|
||||
}
|
||||
|
||||
declineReq := &lobbymodel.InviteDeclineRequest{GameID: "game-private-7c8f", InviteID: "invite-user-bound"}
|
||||
declineBytes, err := InviteDeclineRequestToPayload(declineReq)
|
||||
if err != nil {
|
||||
t.Fatalf("encode decline request: %v", err)
|
||||
}
|
||||
declineDecoded, err := PayloadToInviteDeclineRequest(declineBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("decode decline request: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(declineReq, declineDecoded) {
|
||||
t.Fatalf("decline request mismatch")
|
||||
}
|
||||
|
||||
declineResp := &lobbymodel.InviteDeclineResponse{
|
||||
Invite: lobbymodel.InviteSummary{
|
||||
InviteID: "invite-user-bound",
|
||||
GameID: "game-private-7c8f",
|
||||
InviterUserID: "user-1111",
|
||||
InvitedUserID: "user-9912",
|
||||
Code: "",
|
||||
RaceName: "Vegan Federation",
|
||||
Status: "declined",
|
||||
CreatedAt: created,
|
||||
ExpiresAt: expires,
|
||||
DecidedAt: &decided,
|
||||
},
|
||||
}
|
||||
declineRespBytes, err := InviteDeclineResponseToPayload(declineResp)
|
||||
if err != nil {
|
||||
t.Fatalf("encode decline response: %v", err)
|
||||
}
|
||||
declineRespDecoded, err := PayloadToInviteDeclineResponse(declineRespBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("decode decline response: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(declineResp, declineRespDecoded) {
|
||||
t.Fatalf("decline response mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLobbyErrorResponseRoundTrip(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
source := &lobbymodel.ErrorResponse{
|
||||
Error: lobbymodel.ErrorBody{
|
||||
Code: "conflict",
|
||||
Message: "request conflicts with current state",
|
||||
},
|
||||
}
|
||||
payload, err := LobbyErrorResponseToPayload(source)
|
||||
if err != nil {
|
||||
t.Fatalf("encode: %v", err)
|
||||
}
|
||||
decoded, err := PayloadToLobbyErrorResponse(payload)
|
||||
if err != nil {
|
||||
t.Fatalf("decode: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(source, decoded) {
|
||||
t.Fatalf("round-trip mismatch\nsource: %#v\ndecoded:%#v", source, decoded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLobbyDecodersRecoverFromCorruption(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
garbage := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}
|
||||
|
||||
if _, err := PayloadToMyGamesListResponse(garbage); err == nil {
|
||||
t.Fatal("expected error decoding corrupt my games payload")
|
||||
}
|
||||
if _, err := PayloadToPublicGamesListResponse(garbage); err == nil {
|
||||
t.Fatal("expected error decoding corrupt public games payload")
|
||||
}
|
||||
if _, err := PayloadToApplicationSubmitResponse(garbage); err == nil {
|
||||
t.Fatal("expected error decoding corrupt application submit response")
|
||||
}
|
||||
if _, err := PayloadToInviteRedeemResponse(garbage); err == nil {
|
||||
t.Fatal("expected error decoding corrupt invite redeem response")
|
||||
}
|
||||
if _, err := PayloadToLobbyErrorResponse(garbage); err == nil {
|
||||
t.Fatal("expected error decoding corrupt error payload")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLobbyDecodersRejectEmptyPayload(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if _, err := PayloadToMyGamesListRequest(nil); err == nil {
|
||||
t.Fatal("expected error decoding nil request")
|
||||
}
|
||||
if _, err := PayloadToPublicGamesListResponse(nil); err == nil {
|
||||
t.Fatal("expected error decoding nil response")
|
||||
}
|
||||
if _, err := PayloadToInviteDeclineRequest(nil); err == nil {
|
||||
t.Fatal("expected error decoding nil decline request")
|
||||
}
|
||||
}
|
||||
+9
-1
@@ -1,15 +1,18 @@
|
||||
.PHONY: help web wasm ts-protos gomobile desktop-mac desktop-win desktop-linux ios android all
|
||||
.PHONY: help web wasm ts-protos fbs-ts gomobile desktop-mac desktop-win desktop-linux ios android all
|
||||
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
WASM_OUT := frontend/static/core.wasm
|
||||
WASM_EXEC := frontend/static/wasm_exec.js
|
||||
TINYGO_ROOT := $(shell tinygo env TINYGOROOT 2>/dev/null)
|
||||
FBS_OUT := frontend/src/proto/galaxy/fbs
|
||||
FBS_INPUTS := ../pkg/schema/fbs/lobby.fbs ../pkg/schema/fbs/user.fbs
|
||||
|
||||
help:
|
||||
@echo "ui targets:"
|
||||
@echo " wasm TinyGo build of ui/core to core.wasm + wasm_exec.js shim (Phase 5)"
|
||||
@echo " ts-protos Connect-ES + Protobuf-ES generation from gateway/proto (Phase 5)"
|
||||
@echo " fbs-ts FlatBuffers TS generation from pkg/schema/fbs/*.fbs (Phase 8)"
|
||||
@echo " web Vite production build (Phase 5+)"
|
||||
@echo " gomobile gomobile bind for iOS .framework + Android .aar (Phase 32+)"
|
||||
@echo " desktop-mac Wails build for darwin/{arm64,amd64} (Phase 31)"
|
||||
@@ -30,6 +33,11 @@ ts-protos:
|
||||
@test -x frontend/node_modules/.bin/protoc-gen-es || { echo "protoc-gen-es not installed; run 'pnpm install' inside ui/frontend"; exit 1; }
|
||||
buf generate ../gateway --template buf.gen.yaml --include-imports
|
||||
|
||||
fbs-ts:
|
||||
@command -v flatc >/dev/null || { echo "flatc not found; install via 'brew install flatbuffers' (macOS) or 'apt-get install -y flatbuffers-compiler' (Linux)"; exit 1; }
|
||||
mkdir -p $(FBS_OUT)
|
||||
flatc --ts --gen-object-api -o $(FBS_OUT) $(FBS_INPUTS)
|
||||
|
||||
web gomobile desktop-mac desktop-win desktop-linux ios android all:
|
||||
@echo "TODO: implement '$@' (placeholder, see ui/PLAN.md)"
|
||||
@exit 1
|
||||
|
||||
+154
-25
@@ -720,7 +720,12 @@ Artifacts (delivered):
|
||||
- `ui/frontend/src/routes/lobby/+page.svelte` (+ `+page.ts`) —
|
||||
placeholder lobby that issues the first authenticated
|
||||
`user.account.get` through `GalaxyClient` and surfaces the decoded
|
||||
display name.
|
||||
display name. The placeholder used `JSON.parse(TextDecoder)` to
|
||||
read the response payload; that worked with the mocked Playwright
|
||||
setup but did not match the gateway's FlatBuffers wire format. Phase
|
||||
8 introduces the TS-side FlatBuffers integration and rewrites this
|
||||
page to decode `AccountResponse` via the generated bindings, so the
|
||||
greeting now also works against a real local stack.
|
||||
- `ui/frontend/src/routes/+layout.svelte` — boot-time session init,
|
||||
route guard (anonymous → `/login`, authenticated on `/login` →
|
||||
`/lobby`), browser-not-supported blocker, and the revocation
|
||||
@@ -784,41 +789,165 @@ Targeted tests (delivered):
|
||||
chromium-mobile-pixel-5: fresh login, returning user, revocation
|
||||
within one second, browser-not-supported blocker.
|
||||
|
||||
## Phase 8. Lobby UI
|
||||
## ~~Phase 8. Lobby UI~~
|
||||
|
||||
Status: pending.
|
||||
Status: done.
|
||||
|
||||
Goal: replace the placeholder lobby with a working list of games
|
||||
allowing the user to view membership, accept invitations, join public
|
||||
games, and create new games.
|
||||
allowing the user to view membership, see and act on invitations and
|
||||
applications, submit applications to public games, and create new
|
||||
private games. The phase also introduces the TS-side FlatBuffers
|
||||
codec the rest of the client relies on for authenticated payloads.
|
||||
|
||||
Artifacts:
|
||||
Decisions taken with the project owner before implementation:
|
||||
|
||||
- `ui/frontend/src/routes/lobby/+page.svelte` landing page sections:
|
||||
my games (`docs/FUNCTIONAL.md` §4.5), public games (§4.2), pending
|
||||
invitations (§4.3), action to create a new game (§3.3)
|
||||
- `ui/frontend/src/api/lobby.ts` typed wrappers over the relevant
|
||||
authenticated RPCs
|
||||
- `ui/frontend/src/routes/lobby/create/+page.svelte` create-game form
|
||||
matching backend contract
|
||||
- routing wiring: clicking a game card navigates to
|
||||
`/games/:gameId/map` (placeholder until Phase 10)
|
||||
1. **Cross-stack catalog extension.** Phase 8 expands the lobby
|
||||
command catalog beyond `lobby.my.games.list` and
|
||||
`lobby.game.open-enrollment` (the only routes shipped before this
|
||||
phase). Seven new authenticated message types now flow through
|
||||
`gateway/internal/backendclient/lobby_commands.go`:
|
||||
`lobby.public.games.list`, `lobby.my.applications.list`,
|
||||
`lobby.my.invites.list`, `lobby.game.create`,
|
||||
`lobby.application.submit`, `lobby.invite.redeem`,
|
||||
`lobby.invite.decline`. Each carries its FlatBuffers schema in
|
||||
`pkg/schema/fbs/lobby.fbs`, its Go request/response struct in
|
||||
`pkg/model/lobby/lobby.go`, and its transcoder pair in
|
||||
`pkg/transcoder/lobby.go`.
|
||||
2. **My applications projection.** FUNCTIONAL.md §4.5 lists three
|
||||
"my" projections (games, applications, invites). The original
|
||||
plan text omitted applications; the lobby now renders a fourth
|
||||
"my applications" section so the user sees the pending status of
|
||||
any application they submit.
|
||||
3. **Submit-application UX.** Per FUNCTIONAL.md §4.2, joining a
|
||||
public game means submitting an application that lands in the
|
||||
`pending` state until the owner approves. The button label is
|
||||
`Submit application`, the inline race-name form lives on the
|
||||
public-game card itself (no overlay/modal infrastructure yet —
|
||||
that lands later when the in-game shell does), and a successful
|
||||
submit refreshes the applications section so the user sees the
|
||||
pending entry immediately.
|
||||
4. **TS-side FlatBuffers integration.** The placeholder lobby in
|
||||
Phase 7 used `JSON.parse(TextDecoder)` to read the
|
||||
`user.account.get` payload; that was a mismatch with the gateway's
|
||||
FlatBuffers transcoder and only worked under mocked tests. Phase 8
|
||||
adds a `flatbuffers` runtime dep to `ui/frontend/package.json`, a
|
||||
`fbs-ts` Make target in `ui/Makefile` that drives `flatc --ts`,
|
||||
and checks the generated bindings into
|
||||
`ui/frontend/src/proto/galaxy/fbs/{lobby,user}/`. Phase 7's
|
||||
`user.account.get` decode is rewritten to use those bindings as
|
||||
part of this phase, fixing the wire-format gap.
|
||||
5. **Create-game form scope.** The form keeps `game_name`,
|
||||
`description`, `turn_schedule` (5-field cron), and
|
||||
`enrollment_ends_at` always visible; the rest (`min_players`,
|
||||
`max_players`, `start_gap_hours`, `start_gap_players`,
|
||||
`target_engine_version`) sit behind a `<details>` "Advanced"
|
||||
toggle with TS-side defaults (2 / 8 / 24 / 2 / `v1`). The gateway
|
||||
forces visibility to `private` regardless of input — public games
|
||||
come exclusively through the admin surface per FUNCTIONAL.md §3.3.
|
||||
|
||||
Artifacts (delivered):
|
||||
|
||||
- `ui/frontend/src/routes/lobby/+page.svelte` — full lobby landing
|
||||
page. Header preserves the Phase 7 device-session-id and greeting
|
||||
affordances; below it five sections render in a single mobile-first
|
||||
column: a top-level "create new game" action (§3.3), `my games`
|
||||
cards routing to `/games/:id/map` (placeholder until Phase 10,
|
||||
§4.5), `pending invitations` cards with Accept / Decline (§4.3),
|
||||
`my applications` cards with localised pending / approved /
|
||||
rejected status (§4.5), and `public games` cards with an inline
|
||||
race-name form behind a `Submit application` button (§4.2).
|
||||
Convention follows the Phase 7 login page — single `max-width:
|
||||
32rem` cap, no `@media` queries.
|
||||
- `ui/frontend/src/routes/lobby/create/+page.svelte` (+ `+page.ts`
|
||||
with `ssr = false; prerender = false;`) — create-game form with
|
||||
always-visible name / description / turn-schedule / enrollment-end,
|
||||
Advanced fields under `<details>` for the rest, and TS-side
|
||||
defaults for the advanced inputs.
|
||||
- `ui/frontend/src/api/lobby.ts` — typed wrappers around
|
||||
`GalaxyClient.executeCommand` for all eight lobby commands plus a
|
||||
`LobbyError` class that surfaces canonical lobby error codes
|
||||
(`invalid_request`, `subject_not_found`, `forbidden`, `conflict`,
|
||||
`internal_error`).
|
||||
- `ui/frontend/src/api/galaxy-client.ts` — `executeCommand` now
|
||||
returns `{ resultCode, payloadBytes }`; `lobby.ts` uses the
|
||||
result-code branch to throw `LobbyError`.
|
||||
- `pkg/model/lobby/lobby.go` — seven new message-type constants and
|
||||
matching request/response structs.
|
||||
- `pkg/schema/fbs/lobby.fbs` — `PublicGamesListRequest`,
|
||||
`PublicGamesListResponse`, `ApplicationSummary`,
|
||||
`MyApplicationsListRequest`, `MyApplicationsListResponse`,
|
||||
`InviteSummary`, `MyInvitesListRequest`, `MyInvitesListResponse`,
|
||||
`GameCreateRequest`, `GameCreateResponse`,
|
||||
`ApplicationSubmitRequest`, `ApplicationSubmitResponse`,
|
||||
`InviteRedeemRequest`, `InviteRedeemResponse`,
|
||||
`InviteDeclineRequest`, `InviteDeclineResponse` tables. Reused
|
||||
`GameSummary` for `GameCreateResponse.game` and `MyGamesListResponse`.
|
||||
- `pkg/transcoder/lobby.go` — encode/decode pairs for all new types
|
||||
plus shared helpers `encodeApplicationSummary`,
|
||||
`decodeApplicationSummary`, `encodeInviteSummary`,
|
||||
`decodeInviteSummary`, `unixMilliFromOptional`. Reuses
|
||||
`encodeGameSummary` / `decodeGameSummary` from before.
|
||||
- `gateway/internal/backendclient/lobby_commands.go` — switch cases
|
||||
for the seven new message types and the per-command REST helpers
|
||||
(`executeLobbyPublicGames`, `executeLobbyMyApplications`,
|
||||
`executeLobbyMyInvites`, `executeLobbyGameCreate`,
|
||||
`executeLobbyApplicationSubmit`, `executeLobbyInviteRedeem`,
|
||||
`executeLobbyInviteDecline`); the JSON wire types from backend's
|
||||
user-lobby handlers are mirrored locally for non-strict decoding.
|
||||
- `gateway/internal/backendclient/routes.go` — the new message types
|
||||
are wired into `LobbyRoutes`.
|
||||
- `ui/frontend/src/proto/galaxy/fbs/{lobby,user}/...` — generated TS
|
||||
FlatBuffers bindings (regenerated from `pkg/schema/fbs/*.fbs` via
|
||||
the `fbs-ts` Make target, checked into the repo like the Connect
|
||||
bindings).
|
||||
- `ui/Makefile` — new `fbs-ts` target.
|
||||
- `ui/frontend/package.json` — `flatbuffers` runtime dep.
|
||||
- `ui/frontend/src/lib/i18n/locales/{en,ru}.ts` — full `lobby.*`
|
||||
catalogue covering sections, empty states, application form,
|
||||
create form, status badges, and lobby error code translations.
|
||||
- Topic doc `ui/docs/lobby.md`.
|
||||
- Vitest: `tests/lobby-fbs.test.ts` (binding round-trips),
|
||||
`tests/lobby-api.test.ts` (wrapper unit tests over a stub client),
|
||||
`tests/lobby-page.test.ts`, `tests/lobby-create.test.ts`.
|
||||
- Playwright: `tests/e2e/lobby-flow.spec.ts` (3 cases × 4 projects)
|
||||
with `tests/e2e/fixtures/lobby-fbs.ts` building forged FlatBuffers
|
||||
payloads through the same generated bindings the production code
|
||||
uses. The Phase 7 spec was migrated to the same fixture so
|
||||
`user.account.get` is now FlatBuffers end-to-end.
|
||||
- Phase 7 e2e specs were updated to `click → fill` the readonly
|
||||
inputs (the readonly attribute is the documented Safari
|
||||
autofill-suppression workaround; `fill` checks editability before
|
||||
Playwright's own focus call, so a deliberate click is required).
|
||||
- `pkg/transcoder/lobby_test.go` — round-trip and corruption-recover
|
||||
cases for every new pair.
|
||||
- `gateway/internal/backendclient/lobby_commands_test.go` — per-RPC
|
||||
success / 4xx / 5xx / 503 cases against an `httptest.Server`.
|
||||
|
||||
Dependencies: Phase 7.
|
||||
|
||||
Acceptance criteria:
|
||||
Acceptance criteria (met):
|
||||
|
||||
- the user can list, create, join a game, and accept an invitation
|
||||
end-to-end against a local stack;
|
||||
- mobile viewport renders without horizontal scroll;
|
||||
- empty states are explicit (`no games yet`, `no public games`).
|
||||
- the user can list, create, submit-application, and accept an
|
||||
invitation end-to-end against a local stack — the gateway routes
|
||||
every required envelope, and the FlatBuffers wire path is the same
|
||||
in production and in mocked tests;
|
||||
- mobile viewport renders without horizontal scroll on
|
||||
`chromium-mobile-iphone-13` and `chromium-mobile-pixel-5`;
|
||||
- empty states are explicit (`no games yet`, `no invitations`,
|
||||
`no applications`, `no public games`).
|
||||
|
||||
Targeted tests:
|
||||
Targeted tests (delivered):
|
||||
|
||||
- Vitest component tests for each section with mocked API responses;
|
||||
- Playwright e2e: complete a create-game flow and confirm the new game
|
||||
appears in `my games`;
|
||||
- mobile-viewport Playwright run for the same flow.
|
||||
- Vitest binding round-trips for every lobby request/response;
|
||||
- Vitest API wrapper coverage for every wrapper plus the LobbyError
|
||||
surfacing path;
|
||||
- Vitest component tests for the lobby page (every section, empty
|
||||
states, race-name validation, Accept / Decline) and the create-game
|
||||
form (validation, submission, cancel);
|
||||
- Playwright e2e (3 flows × 4 projects): full create-game flow to
|
||||
My Games, submit-application to My Applications pending, accept
|
||||
invitation removes card and adds the game to My Games. Phase 7
|
||||
auth flow now also runs over the FlatBuffers wire.
|
||||
|
||||
## Phase 9. Map Renderer with Fixture Data
|
||||
|
||||
|
||||
+14
-10
@@ -75,8 +75,8 @@ ui/
|
||||
├── src/lib/ env config, session store, revocation watcher
|
||||
├── src/platform/core/ Core interface + WasmCore adapter
|
||||
├── src/platform/store/ KeyStore/Cache interfaces + web adapter
|
||||
├── src/proto/ generated Protobuf-ES + Connect descriptors
|
||||
├── src/routes/ SvelteKit routes (/, /login, /lobby)
|
||||
├── src/proto/ generated Protobuf-ES + Connect descriptors + FlatBuffers TS bindings
|
||||
├── src/routes/ SvelteKit routes (/, /login, /lobby, /lobby/create)
|
||||
└── static/ core.wasm + wasm_exec.js (committed artefacts)
|
||||
```
|
||||
|
||||
@@ -84,6 +84,8 @@ Linked topic docs:
|
||||
|
||||
- [`docs/auth-flow.md`](docs/auth-flow.md) — email-code login,
|
||||
session store state machine, revocation watcher.
|
||||
- [`docs/lobby.md`](docs/lobby.md) — lobby UI sections, application
|
||||
/ invite lifecycle, create-game form defaults.
|
||||
- [`docs/i18n.md`](docs/i18n.md) — translation primitive, native-name
|
||||
language picker, recipe for adding a new locale.
|
||||
- [`docs/storage.md`](docs/storage.md) — web KeyStore/Cache,
|
||||
@@ -117,14 +119,16 @@ named targets are placeholders until the named phase lands; running
|
||||
`make` with no arguments prints the current placeholder map.
|
||||
|
||||
```text
|
||||
make web Vite production build Phase 5+
|
||||
make wasm TinyGo → core.wasm Phase 5
|
||||
make gomobile gomobile bind → ios + android Phase 32+
|
||||
make desktop-mac Wails build for darwin Phase 31
|
||||
make desktop-win Wails build for windows Phase 31
|
||||
make desktop-linux Wails build for linux Phase 31
|
||||
make ios Capacitor + xcodebuild Phase 32+
|
||||
make android Capacitor + gradle Phase 32+
|
||||
make web Vite production build Phase 5+
|
||||
make wasm TinyGo → core.wasm Phase 5
|
||||
make ts-protos Connect-ES + Protobuf-ES gen Phase 5
|
||||
make fbs-ts FlatBuffers TS bindings via flatc Phase 8
|
||||
make gomobile gomobile bind → ios + android Phase 32+
|
||||
make desktop-mac Wails build for darwin Phase 31
|
||||
make desktop-win Wails build for windows Phase 31
|
||||
make desktop-linux Wails build for linux Phase 31
|
||||
make ios Capacitor + xcodebuild Phase 32+
|
||||
make android Capacitor + gradle Phase 32+
|
||||
make all every target above
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
# Lobby UI
|
||||
|
||||
The lobby is the first authenticated view; the user lands here after
|
||||
the email-code login completes (see
|
||||
[`docs/auth-flow.md`](auth-flow.md)). Phase 8 introduced the live
|
||||
lobby with five sections, the create-game form, and the TS-side
|
||||
FlatBuffers integration the rest of the client builds on. This doc
|
||||
captures the sections, the application / invite lifecycle the user
|
||||
sees, and the defaults baked into the create-game form.
|
||||
|
||||
## Sections
|
||||
|
||||
The lobby renders one column of sections, top to bottom, with the
|
||||
common content max-width capped at `32rem` (same convention as the
|
||||
login page). Cards inside each section take the full available
|
||||
width.
|
||||
|
||||
| Section | Empty state | Source | Action |
|
||||
| -------------------- | --------------------- | -------------------------- | --------------------------------------------------------- |
|
||||
| `create new game` | (always visible) | — | Navigates to `/lobby/create` |
|
||||
| `my games` | `no games yet` | `lobby.my.games.list` | Click → `/games/:id/map` (placeholder until Phase 10) |
|
||||
| `pending invitations`| `no invitations` | `lobby.my.invites.list` | Accept (`lobby.invite.redeem`) / Decline (`lobby.invite.decline`) |
|
||||
| `my applications` | `no applications` | `lobby.my.applications.list` | Status badge (`pending` / `approved` / `rejected`) |
|
||||
| `public games` | `no public games` | `lobby.public.games.list` | Submit application via inline race-name form (`lobby.application.submit`) |
|
||||
|
||||
The header preserves the device-session-id `<code>` block from the
|
||||
Phase 7 placeholder (kept as a debug affordance) plus a greeting if
|
||||
the gateway returns a `display_name` for the caller.
|
||||
|
||||
## Application lifecycle
|
||||
|
||||
`Submit application` on a public-game card toggles an inline race-name
|
||||
form on the same card (no overlay/modal infrastructure yet — the
|
||||
in-game shell that introduces overlays lands later). On submit:
|
||||
|
||||
1. The page calls `submitApplication(client, gameId, raceName)` from
|
||||
`src/api/lobby.ts`.
|
||||
2. The wrapper builds an `ApplicationSubmitRequest` FlatBuffers
|
||||
payload, posts it through `GalaxyClient.executeCommand`, decodes
|
||||
the `ApplicationSubmitResponse`, and returns an
|
||||
`ApplicationSummary` plain object.
|
||||
3. The lobby page prepends the new application to the
|
||||
`my applications` list and collapses the inline form. The page
|
||||
does not refresh the public-games list — backend semantics are
|
||||
that the public game still exists and is still in
|
||||
`enrollment_open`.
|
||||
4. Status starts as `pending`. When the owner approves, backend
|
||||
creates a membership and the next refresh of `lobby.my.games.list`
|
||||
surfaces the game in `my games`. When the owner rejects, the
|
||||
application stays terminal in `my applications` with status
|
||||
`rejected`.
|
||||
|
||||
## Invite lifecycle
|
||||
|
||||
A pending invite arrives in `pending invitations` either when the
|
||||
inviter targets the user by id (`invited_user_id` is set) or when the
|
||||
user redeems a code-based invite from somewhere outside the lobby.
|
||||
The user can accept (`lobby.invite.redeem`) or decline
|
||||
(`lobby.invite.decline`):
|
||||
|
||||
- **Accept** — the invite card disappears, the page refreshes
|
||||
`my games`, and the freshly-joined game appears there.
|
||||
- **Decline** — the invite card disappears. No membership is
|
||||
created.
|
||||
|
||||
## Create-game form
|
||||
|
||||
The form posts `lobby.game.create` through the gateway with
|
||||
`visibility="private"` hard-coded; the user surface never produces a
|
||||
public game (FUNCTIONAL.md §3.3). Fields:
|
||||
|
||||
| Field | Visibility | Default | Notes |
|
||||
| --------------------- | ---------------- | ------- | ------------------------------------------------------ |
|
||||
| `game_name` | always | `""` | Non-empty client-side check |
|
||||
| `description` | always | `""` | |
|
||||
| `turn_schedule` | always | `0 0 * * *` | Plain text input, hint says "five-field cron" |
|
||||
| `enrollment_ends_at` | always | `""` | `<input type="datetime-local">`, RFC 3339 on submit |
|
||||
| `min_players` | Advanced toggle | `2` | `<details>` block |
|
||||
| `max_players` | Advanced toggle | `8` | |
|
||||
| `start_gap_hours` | Advanced toggle | `24` | |
|
||||
| `start_gap_players` | Advanced toggle | `2` | |
|
||||
| `target_engine_version` | Advanced toggle | `v1` | Falls back to `v1` if blank |
|
||||
|
||||
On success the page navigates back to `/lobby` and the new game shows
|
||||
up in `my games` once the lobby's onMount has had a chance to refresh
|
||||
the list.
|
||||
|
||||
## Errors
|
||||
|
||||
Lobby errors raised by the gateway carry a canonical code
|
||||
(`invalid_request`, `subject_not_found`, `forbidden`, `conflict`,
|
||||
`internal_error`). The `LobbyError` thrown by `lobby.ts` exposes the
|
||||
code; the page maps it to the matching `lobby.error.<code>` i18n key
|
||||
and falls back to the gateway-supplied message via
|
||||
`lobby.error.unknown` for any unknown code.
|
||||
|
||||
## Why FlatBuffers on the TS side
|
||||
|
||||
The gateway encodes lobby payloads through `pkg/transcoder/lobby.go`
|
||||
into FlatBuffers bytes; the browser must decode them with the same
|
||||
schema. Phase 8 ships:
|
||||
|
||||
- `flatbuffers` runtime dependency in `ui/frontend/package.json`;
|
||||
- `make -C ui fbs-ts` driving `flatc --ts` to regenerate the bindings
|
||||
from `pkg/schema/fbs/*.fbs` into `ui/frontend/src/proto/galaxy/fbs/`;
|
||||
- a Vitest round-trip suite (`tests/lobby-fbs.test.ts`) that catches
|
||||
binding drift in CI.
|
||||
|
||||
Phase 7's `user.account.get` decode previously used
|
||||
`JSON.parse(TextDecoder)`; that path was rewritten in Phase 8 to use
|
||||
the same generated `AccountResponse` table, so the lobby greeting now
|
||||
works against a real local stack as well as the mocked Playwright
|
||||
fixtures.
|
||||
@@ -12,6 +12,7 @@
|
||||
"test:e2e": "playwright test"
|
||||
},
|
||||
"dependencies": {
|
||||
"flatbuffers": "^25.9.23",
|
||||
"idb": "^8.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -46,6 +46,11 @@ export interface GalaxyClientOptions {
|
||||
|
||||
const PROTOCOL_VERSION = "v1";
|
||||
|
||||
export interface ExecuteCommandResult {
|
||||
resultCode: string;
|
||||
payloadBytes: Uint8Array;
|
||||
}
|
||||
|
||||
export class GalaxyClient {
|
||||
private readonly core: Core;
|
||||
private readonly edge: EdgeGatewayClient;
|
||||
@@ -72,7 +77,7 @@ export class GalaxyClient {
|
||||
messageType: string,
|
||||
payload: Uint8Array,
|
||||
traceId = "",
|
||||
): Promise<Uint8Array> {
|
||||
): Promise<ExecuteCommandResult> {
|
||||
const requestId = this.requestIdFactory();
|
||||
const timestampMs = this.clock();
|
||||
const payloadHash = await this.sha256(payload);
|
||||
@@ -103,7 +108,10 @@ export class GalaxyClient {
|
||||
);
|
||||
|
||||
this.verifyResponse(response, requestId);
|
||||
return response.payloadBytes;
|
||||
return {
|
||||
resultCode: response.resultCode,
|
||||
payloadBytes: response.payloadBytes,
|
||||
};
|
||||
}
|
||||
|
||||
private verifyResponse(
|
||||
|
||||
@@ -0,0 +1,361 @@
|
||||
// Typed wrappers around `GalaxyClient.executeCommand` for the Phase 8
|
||||
// lobby command catalog. Each wrapper builds a FlatBuffers request
|
||||
// payload via the generated TS bindings, calls `executeCommand`, then
|
||||
// decodes the FlatBuffers response payload. Errors carrying a non-`ok`
|
||||
// `result_code` are surfaced as a thrown `LobbyError` so callers can
|
||||
// branch on canonical lobby error codes (`invalid_request`,
|
||||
// `subject_not_found`, `forbidden`, `conflict`, `internal_error`).
|
||||
|
||||
import { Builder, ByteBuffer } from "flatbuffers";
|
||||
|
||||
import type { GalaxyClient } from "./galaxy-client";
|
||||
import {
|
||||
ApplicationSubmitRequest,
|
||||
ApplicationSubmitResponse,
|
||||
ApplicationSummary as FbsApplicationSummary,
|
||||
ErrorResponse as FbsErrorResponse,
|
||||
GameCreateRequest,
|
||||
GameCreateResponse,
|
||||
GameSummary as FbsGameSummary,
|
||||
InviteDeclineRequest,
|
||||
InviteDeclineResponse,
|
||||
InviteRedeemRequest,
|
||||
InviteRedeemResponse,
|
||||
InviteSummary as FbsInviteSummary,
|
||||
MyApplicationsListRequest,
|
||||
MyApplicationsListResponse,
|
||||
MyGamesListRequest,
|
||||
MyGamesListResponse,
|
||||
MyInvitesListRequest,
|
||||
MyInvitesListResponse,
|
||||
PublicGamesListRequest,
|
||||
PublicGamesListResponse,
|
||||
} from "../proto/galaxy/fbs/lobby";
|
||||
|
||||
export class LobbyError extends Error {
|
||||
readonly code: string;
|
||||
readonly resultCode: string;
|
||||
|
||||
constructor(resultCode: string, code: string, message: string) {
|
||||
super(message);
|
||||
this.name = "LobbyError";
|
||||
this.resultCode = resultCode;
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
|
||||
export interface GameSummary {
|
||||
gameId: string;
|
||||
gameName: string;
|
||||
gameType: string;
|
||||
status: string;
|
||||
ownerUserId: string;
|
||||
minPlayers: number;
|
||||
maxPlayers: number;
|
||||
enrollmentEndsAt: Date;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
export interface PublicGamesPage {
|
||||
items: GameSummary[];
|
||||
page: number;
|
||||
pageSize: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface ApplicationSummary {
|
||||
applicationId: string;
|
||||
gameId: string;
|
||||
applicantUserId: string;
|
||||
raceName: string;
|
||||
status: string;
|
||||
createdAt: Date;
|
||||
decidedAt: Date | null;
|
||||
}
|
||||
|
||||
export interface InviteSummary {
|
||||
inviteId: string;
|
||||
gameId: string;
|
||||
inviterUserId: string;
|
||||
invitedUserId: string;
|
||||
code: string;
|
||||
raceName: string;
|
||||
status: string;
|
||||
createdAt: Date;
|
||||
expiresAt: Date;
|
||||
decidedAt: Date | null;
|
||||
}
|
||||
|
||||
export interface CreateGameInput {
|
||||
gameName: string;
|
||||
description: string;
|
||||
minPlayers: number;
|
||||
maxPlayers: number;
|
||||
startGapHours: number;
|
||||
startGapPlayers: number;
|
||||
enrollmentEndsAt: Date;
|
||||
turnSchedule: string;
|
||||
targetEngineVersion: string;
|
||||
}
|
||||
|
||||
const RESULT_CODE_OK = "ok";
|
||||
|
||||
export async function listMyGames(client: GalaxyClient): Promise<GameSummary[]> {
|
||||
const builder = new Builder(32);
|
||||
MyGamesListRequest.startMyGamesListRequest(builder);
|
||||
builder.finish(MyGamesListRequest.endMyGamesListRequest(builder));
|
||||
const payload = await execute(client, "lobby.my.games.list", builder.asUint8Array());
|
||||
const response = MyGamesListResponse.getRootAsMyGamesListResponse(new ByteBuffer(payload));
|
||||
const out: GameSummary[] = [];
|
||||
for (let i = 0; i < response.itemsLength(); i++) {
|
||||
const item = response.items(i);
|
||||
if (item) {
|
||||
out.push(decodeGameSummary(item));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export async function listPublicGames(
|
||||
client: GalaxyClient,
|
||||
options: { page?: number; pageSize?: number } = {},
|
||||
): Promise<PublicGamesPage> {
|
||||
const page = options.page ?? 1;
|
||||
const pageSize = options.pageSize ?? 50;
|
||||
const builder = new Builder(32);
|
||||
PublicGamesListRequest.startPublicGamesListRequest(builder);
|
||||
PublicGamesListRequest.addPage(builder, page);
|
||||
PublicGamesListRequest.addPageSize(builder, pageSize);
|
||||
builder.finish(PublicGamesListRequest.endPublicGamesListRequest(builder));
|
||||
const payload = await execute(client, "lobby.public.games.list", builder.asUint8Array());
|
||||
const response = PublicGamesListResponse.getRootAsPublicGamesListResponse(
|
||||
new ByteBuffer(payload),
|
||||
);
|
||||
const out: GameSummary[] = [];
|
||||
for (let i = 0; i < response.itemsLength(); i++) {
|
||||
const item = response.items(i);
|
||||
if (item) {
|
||||
out.push(decodeGameSummary(item));
|
||||
}
|
||||
}
|
||||
return {
|
||||
items: out,
|
||||
page: response.page(),
|
||||
pageSize: response.pageSize(),
|
||||
total: response.total(),
|
||||
};
|
||||
}
|
||||
|
||||
export async function listMyApplications(
|
||||
client: GalaxyClient,
|
||||
): Promise<ApplicationSummary[]> {
|
||||
const builder = new Builder(32);
|
||||
MyApplicationsListRequest.startMyApplicationsListRequest(builder);
|
||||
builder.finish(MyApplicationsListRequest.endMyApplicationsListRequest(builder));
|
||||
const payload = await execute(client, "lobby.my.applications.list", builder.asUint8Array());
|
||||
const response = MyApplicationsListResponse.getRootAsMyApplicationsListResponse(
|
||||
new ByteBuffer(payload),
|
||||
);
|
||||
const out: ApplicationSummary[] = [];
|
||||
for (let i = 0; i < response.itemsLength(); i++) {
|
||||
const item = response.items(i);
|
||||
if (item) {
|
||||
out.push(decodeApplicationSummary(item));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export async function listMyInvites(client: GalaxyClient): Promise<InviteSummary[]> {
|
||||
const builder = new Builder(32);
|
||||
MyInvitesListRequest.startMyInvitesListRequest(builder);
|
||||
builder.finish(MyInvitesListRequest.endMyInvitesListRequest(builder));
|
||||
const payload = await execute(client, "lobby.my.invites.list", builder.asUint8Array());
|
||||
const response = MyInvitesListResponse.getRootAsMyInvitesListResponse(new ByteBuffer(payload));
|
||||
const out: InviteSummary[] = [];
|
||||
for (let i = 0; i < response.itemsLength(); i++) {
|
||||
const item = response.items(i);
|
||||
if (item) {
|
||||
out.push(decodeInviteSummary(item));
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export async function createGame(
|
||||
client: GalaxyClient,
|
||||
input: CreateGameInput,
|
||||
): Promise<GameSummary> {
|
||||
const builder = new Builder(256);
|
||||
const gameNameOff = builder.createString(input.gameName);
|
||||
const descriptionOff = builder.createString(input.description);
|
||||
const turnScheduleOff = builder.createString(input.turnSchedule);
|
||||
const targetEngineVersionOff = builder.createString(input.targetEngineVersion);
|
||||
GameCreateRequest.startGameCreateRequest(builder);
|
||||
GameCreateRequest.addGameName(builder, gameNameOff);
|
||||
GameCreateRequest.addDescription(builder, descriptionOff);
|
||||
GameCreateRequest.addMinPlayers(builder, input.minPlayers);
|
||||
GameCreateRequest.addMaxPlayers(builder, input.maxPlayers);
|
||||
GameCreateRequest.addStartGapHours(builder, input.startGapHours);
|
||||
GameCreateRequest.addStartGapPlayers(builder, input.startGapPlayers);
|
||||
GameCreateRequest.addEnrollmentEndsAtMs(builder, BigInt(input.enrollmentEndsAt.getTime()));
|
||||
GameCreateRequest.addTurnSchedule(builder, turnScheduleOff);
|
||||
GameCreateRequest.addTargetEngineVersion(builder, targetEngineVersionOff);
|
||||
builder.finish(GameCreateRequest.endGameCreateRequest(builder));
|
||||
const payload = await execute(client, "lobby.game.create", builder.asUint8Array());
|
||||
const response = GameCreateResponse.getRootAsGameCreateResponse(new ByteBuffer(payload));
|
||||
const game = response.game();
|
||||
if (game === null) {
|
||||
throw new LobbyError("internal_error", "internal_error", "game missing in response");
|
||||
}
|
||||
return decodeGameSummary(game);
|
||||
}
|
||||
|
||||
export async function submitApplication(
|
||||
client: GalaxyClient,
|
||||
gameId: string,
|
||||
raceName: string,
|
||||
): Promise<ApplicationSummary> {
|
||||
const builder = new Builder(128);
|
||||
const gameIdOff = builder.createString(gameId);
|
||||
const raceNameOff = builder.createString(raceName);
|
||||
ApplicationSubmitRequest.startApplicationSubmitRequest(builder);
|
||||
ApplicationSubmitRequest.addGameId(builder, gameIdOff);
|
||||
ApplicationSubmitRequest.addRaceName(builder, raceNameOff);
|
||||
builder.finish(ApplicationSubmitRequest.endApplicationSubmitRequest(builder));
|
||||
const payload = await execute(client, "lobby.application.submit", builder.asUint8Array());
|
||||
const response = ApplicationSubmitResponse.getRootAsApplicationSubmitResponse(
|
||||
new ByteBuffer(payload),
|
||||
);
|
||||
const application = response.application();
|
||||
if (application === null) {
|
||||
throw new LobbyError("internal_error", "internal_error", "application missing in response");
|
||||
}
|
||||
return decodeApplicationSummary(application);
|
||||
}
|
||||
|
||||
export async function redeemInvite(
|
||||
client: GalaxyClient,
|
||||
gameId: string,
|
||||
inviteId: string,
|
||||
): Promise<InviteSummary> {
|
||||
const builder = new Builder(128);
|
||||
const gameIdOff = builder.createString(gameId);
|
||||
const inviteIdOff = builder.createString(inviteId);
|
||||
InviteRedeemRequest.startInviteRedeemRequest(builder);
|
||||
InviteRedeemRequest.addGameId(builder, gameIdOff);
|
||||
InviteRedeemRequest.addInviteId(builder, inviteIdOff);
|
||||
builder.finish(InviteRedeemRequest.endInviteRedeemRequest(builder));
|
||||
const payload = await execute(client, "lobby.invite.redeem", builder.asUint8Array());
|
||||
const response = InviteRedeemResponse.getRootAsInviteRedeemResponse(new ByteBuffer(payload));
|
||||
const invite = response.invite();
|
||||
if (invite === null) {
|
||||
throw new LobbyError("internal_error", "internal_error", "invite missing in response");
|
||||
}
|
||||
return decodeInviteSummary(invite);
|
||||
}
|
||||
|
||||
export async function declineInvite(
|
||||
client: GalaxyClient,
|
||||
gameId: string,
|
||||
inviteId: string,
|
||||
): Promise<InviteSummary> {
|
||||
const builder = new Builder(128);
|
||||
const gameIdOff = builder.createString(gameId);
|
||||
const inviteIdOff = builder.createString(inviteId);
|
||||
InviteDeclineRequest.startInviteDeclineRequest(builder);
|
||||
InviteDeclineRequest.addGameId(builder, gameIdOff);
|
||||
InviteDeclineRequest.addInviteId(builder, inviteIdOff);
|
||||
builder.finish(InviteDeclineRequest.endInviteDeclineRequest(builder));
|
||||
const payload = await execute(client, "lobby.invite.decline", builder.asUint8Array());
|
||||
const response = InviteDeclineResponse.getRootAsInviteDeclineResponse(
|
||||
new ByteBuffer(payload),
|
||||
);
|
||||
const invite = response.invite();
|
||||
if (invite === null) {
|
||||
throw new LobbyError("internal_error", "internal_error", "invite missing in response");
|
||||
}
|
||||
return decodeInviteSummary(invite);
|
||||
}
|
||||
|
||||
async function execute(
|
||||
client: GalaxyClient,
|
||||
messageType: string,
|
||||
payloadBytes: Uint8Array,
|
||||
): Promise<Uint8Array> {
|
||||
const result = await client.executeCommand(messageType, payloadBytes);
|
||||
if (result.resultCode !== RESULT_CODE_OK) {
|
||||
throw decodeLobbyError(result.resultCode, result.payloadBytes);
|
||||
}
|
||||
return result.payloadBytes;
|
||||
}
|
||||
|
||||
function decodeLobbyError(resultCode: string, payload: Uint8Array): LobbyError {
|
||||
let code = resultCode;
|
||||
let message = resultCode;
|
||||
try {
|
||||
const errorResponse = FbsErrorResponse.getRootAsErrorResponse(new ByteBuffer(payload));
|
||||
const body = errorResponse.error();
|
||||
if (body) {
|
||||
code = body.code() ?? resultCode;
|
||||
message = body.message() ?? resultCode;
|
||||
}
|
||||
} catch (_err) {
|
||||
// fall through to use raw resultCode as both code and message
|
||||
}
|
||||
return new LobbyError(resultCode, code, message);
|
||||
}
|
||||
|
||||
function decodeGameSummary(summary: FbsGameSummary): GameSummary {
|
||||
return {
|
||||
gameId: summary.gameId() ?? "",
|
||||
gameName: summary.gameName() ?? "",
|
||||
gameType: summary.gameType() ?? "",
|
||||
status: summary.status() ?? "",
|
||||
ownerUserId: summary.ownerUserId() ?? "",
|
||||
minPlayers: summary.minPlayers(),
|
||||
maxPlayers: summary.maxPlayers(),
|
||||
enrollmentEndsAt: dateFromMs(summary.enrollmentEndsAtMs()),
|
||||
createdAt: dateFromMs(summary.createdAtMs()),
|
||||
updatedAt: dateFromMs(summary.updatedAtMs()),
|
||||
};
|
||||
}
|
||||
|
||||
function decodeApplicationSummary(app: FbsApplicationSummary): ApplicationSummary {
|
||||
return {
|
||||
applicationId: app.applicationId() ?? "",
|
||||
gameId: app.gameId() ?? "",
|
||||
applicantUserId: app.applicantUserId() ?? "",
|
||||
raceName: app.raceName() ?? "",
|
||||
status: app.status() ?? "",
|
||||
createdAt: dateFromMs(app.createdAtMs()),
|
||||
decidedAt: optionalDateFromMs(app.decidedAtMs()),
|
||||
};
|
||||
}
|
||||
|
||||
function decodeInviteSummary(invite: FbsInviteSummary): InviteSummary {
|
||||
return {
|
||||
inviteId: invite.inviteId() ?? "",
|
||||
gameId: invite.gameId() ?? "",
|
||||
inviterUserId: invite.inviterUserId() ?? "",
|
||||
invitedUserId: invite.invitedUserId() ?? "",
|
||||
code: invite.code() ?? "",
|
||||
raceName: invite.raceName() ?? "",
|
||||
status: invite.status() ?? "",
|
||||
createdAt: dateFromMs(invite.createdAtMs()),
|
||||
expiresAt: dateFromMs(invite.expiresAtMs()),
|
||||
decidedAt: optionalDateFromMs(invite.decidedAtMs()),
|
||||
};
|
||||
}
|
||||
|
||||
function dateFromMs(ms: bigint): Date {
|
||||
return new Date(Number(ms));
|
||||
}
|
||||
|
||||
function optionalDateFromMs(ms: bigint): Date | null {
|
||||
if (ms === 0n) {
|
||||
return null;
|
||||
}
|
||||
return new Date(Number(ms));
|
||||
}
|
||||
@@ -35,6 +35,53 @@ const en = {
|
||||
"lobby.greeting": "hello, {name}!",
|
||||
"lobby.account_loading": "loading account…",
|
||||
"lobby.logout": "logout",
|
||||
"lobby.section.my_games": "my games",
|
||||
"lobby.section.invitations": "pending invitations",
|
||||
"lobby.section.applications": "my applications",
|
||||
"lobby.section.public_games": "public games",
|
||||
"lobby.section.create": "create a game",
|
||||
"lobby.create_button": "create new game",
|
||||
"lobby.my_games.empty": "no games yet",
|
||||
"lobby.invitations.empty": "no invitations",
|
||||
"lobby.applications.empty": "no applications",
|
||||
"lobby.public_games.empty": "no public games",
|
||||
"lobby.invitation.accept": "accept",
|
||||
"lobby.invitation.decline": "decline",
|
||||
"lobby.application.submit": "submit application",
|
||||
"lobby.application.submit_for": "join {name}",
|
||||
"lobby.application.race_name_label": "race name",
|
||||
"lobby.application.race_name_required": "race name must not be empty",
|
||||
"lobby.application.cancel": "cancel",
|
||||
"lobby.application.submitted": "application submitted, awaiting approval",
|
||||
"lobby.application.status.pending": "pending",
|
||||
"lobby.application.status.approved": "approved",
|
||||
"lobby.application.status.rejected": "rejected",
|
||||
"lobby.application.status.unknown": "{status}",
|
||||
"lobby.list_loading": "loading…",
|
||||
"lobby.create.title": "create new game",
|
||||
"lobby.create.game_name_label": "game name",
|
||||
"lobby.create.description_label": "description",
|
||||
"lobby.create.turn_schedule_label": "turn schedule",
|
||||
"lobby.create.turn_schedule_hint": "five-field cron, e.g. 0 0 * * *",
|
||||
"lobby.create.enrollment_ends_at_label": "enrollment ends at",
|
||||
"lobby.create.advanced": "advanced",
|
||||
"lobby.create.min_players_label": "min players",
|
||||
"lobby.create.max_players_label": "max players",
|
||||
"lobby.create.start_gap_hours_label": "start gap (hours)",
|
||||
"lobby.create.start_gap_players_label": "start gap (players)",
|
||||
"lobby.create.target_engine_version_label": "target engine version",
|
||||
"lobby.create.submit": "create",
|
||||
"lobby.create.submitting": "creating…",
|
||||
"lobby.create.cancel": "cancel",
|
||||
"lobby.create.game_name_required": "game name must not be empty",
|
||||
"lobby.create.turn_schedule_required": "turn schedule must not be empty",
|
||||
"lobby.create.enrollment_ends_at_required": "enrollment end time must be set",
|
||||
"lobby.error.invalid_request": "request is invalid",
|
||||
"lobby.error.subject_not_found": "not found",
|
||||
"lobby.error.forbidden": "operation is forbidden",
|
||||
"lobby.error.conflict": "request conflicts with current state",
|
||||
"lobby.error.internal_error": "internal server error",
|
||||
"lobby.error.unknown": "{message}",
|
||||
} as const;
|
||||
|
||||
export default en;
|
||||
|
||||
@@ -36,6 +36,53 @@ const ru: Record<keyof typeof en, string> = {
|
||||
"lobby.greeting": "здравствуйте, {name}!",
|
||||
"lobby.account_loading": "загрузка профиля…",
|
||||
"lobby.logout": "выйти",
|
||||
"lobby.section.my_games": "мои игры",
|
||||
"lobby.section.invitations": "ожидающие приглашения",
|
||||
"lobby.section.applications": "мои заявки",
|
||||
"lobby.section.public_games": "публичные игры",
|
||||
"lobby.section.create": "создать игру",
|
||||
"lobby.create_button": "создать новую игру",
|
||||
"lobby.my_games.empty": "пока нет игр",
|
||||
"lobby.invitations.empty": "приглашений нет",
|
||||
"lobby.applications.empty": "заявок нет",
|
||||
"lobby.public_games.empty": "публичных игр нет",
|
||||
"lobby.invitation.accept": "принять",
|
||||
"lobby.invitation.decline": "отклонить",
|
||||
"lobby.application.submit": "подать заявку",
|
||||
"lobby.application.submit_for": "подать заявку в {name}",
|
||||
"lobby.application.race_name_label": "название расы",
|
||||
"lobby.application.race_name_required": "название расы не должно быть пустым",
|
||||
"lobby.application.cancel": "отмена",
|
||||
"lobby.application.submitted": "заявка отправлена, ожидает одобрения",
|
||||
"lobby.application.status.pending": "ожидает",
|
||||
"lobby.application.status.approved": "одобрена",
|
||||
"lobby.application.status.rejected": "отклонена",
|
||||
"lobby.application.status.unknown": "{status}",
|
||||
"lobby.list_loading": "загрузка…",
|
||||
"lobby.create.title": "создание новой игры",
|
||||
"lobby.create.game_name_label": "название игры",
|
||||
"lobby.create.description_label": "описание",
|
||||
"lobby.create.turn_schedule_label": "расписание ходов",
|
||||
"lobby.create.turn_schedule_hint": "cron из пяти полей, например 0 0 * * *",
|
||||
"lobby.create.enrollment_ends_at_label": "окончание набора",
|
||||
"lobby.create.advanced": "дополнительно",
|
||||
"lobby.create.min_players_label": "мин. игроков",
|
||||
"lobby.create.max_players_label": "макс. игроков",
|
||||
"lobby.create.start_gap_hours_label": "интервал старта (часы)",
|
||||
"lobby.create.start_gap_players_label": "интервал старта (игроки)",
|
||||
"lobby.create.target_engine_version_label": "версия движка",
|
||||
"lobby.create.submit": "создать",
|
||||
"lobby.create.submitting": "создаём…",
|
||||
"lobby.create.cancel": "отмена",
|
||||
"lobby.create.game_name_required": "название игры не должно быть пустым",
|
||||
"lobby.create.turn_schedule_required": "расписание ходов не должно быть пустым",
|
||||
"lobby.create.enrollment_ends_at_required": "время окончания набора обязательно",
|
||||
"lobby.error.invalid_request": "запрос некорректен",
|
||||
"lobby.error.subject_not_found": "объект не найден",
|
||||
"lobby.error.forbidden": "операция запрещена",
|
||||
"lobby.error.conflict": "запрос конфликтует с текущим состоянием",
|
||||
"lobby.error.internal_error": "внутренняя ошибка сервера",
|
||||
"lobby.error.unknown": "{message}",
|
||||
};
|
||||
|
||||
export default ru;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
export { ApplicationSubmitRequest, ApplicationSubmitRequestT } from './lobby/application-submit-request.js';
|
||||
export { ApplicationSubmitResponse, ApplicationSubmitResponseT } from './lobby/application-submit-response.js';
|
||||
export { ApplicationSummary, ApplicationSummaryT } from './lobby/application-summary.js';
|
||||
export { ErrorBody, ErrorBodyT } from './lobby/error-body.js';
|
||||
export { ErrorResponse, ErrorResponseT } from './lobby/error-response.js';
|
||||
export { GameCreateRequest, GameCreateRequestT } from './lobby/game-create-request.js';
|
||||
export { GameCreateResponse, GameCreateResponseT } from './lobby/game-create-response.js';
|
||||
export { GameSummary, GameSummaryT } from './lobby/game-summary.js';
|
||||
export { InviteDeclineRequest, InviteDeclineRequestT } from './lobby/invite-decline-request.js';
|
||||
export { InviteDeclineResponse, InviteDeclineResponseT } from './lobby/invite-decline-response.js';
|
||||
export { InviteRedeemRequest, InviteRedeemRequestT } from './lobby/invite-redeem-request.js';
|
||||
export { InviteRedeemResponse, InviteRedeemResponseT } from './lobby/invite-redeem-response.js';
|
||||
export { InviteSummary, InviteSummaryT } from './lobby/invite-summary.js';
|
||||
export { MyApplicationsListRequest, MyApplicationsListRequestT } from './lobby/my-applications-list-request.js';
|
||||
export { MyApplicationsListResponse, MyApplicationsListResponseT } from './lobby/my-applications-list-response.js';
|
||||
export { MyGamesListRequest, MyGamesListRequestT } from './lobby/my-games-list-request.js';
|
||||
export { MyGamesListResponse, MyGamesListResponseT } from './lobby/my-games-list-response.js';
|
||||
export { MyInvitesListRequest, MyInvitesListRequestT } from './lobby/my-invites-list-request.js';
|
||||
export { MyInvitesListResponse, MyInvitesListResponseT } from './lobby/my-invites-list-response.js';
|
||||
export { OpenEnrollmentRequest, OpenEnrollmentRequestT } from './lobby/open-enrollment-request.js';
|
||||
export { OpenEnrollmentResponse, OpenEnrollmentResponseT } from './lobby/open-enrollment-response.js';
|
||||
export { PublicGamesListRequest, PublicGamesListRequestT } from './lobby/public-games-list-request.js';
|
||||
export { PublicGamesListResponse, PublicGamesListResponseT } from './lobby/public-games-list-response.js';
|
||||
@@ -0,0 +1,95 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class ApplicationSubmitRequest implements flatbuffers.IUnpackableObject<ApplicationSubmitRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):ApplicationSubmitRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsApplicationSubmitRequest(bb:flatbuffers.ByteBuffer, obj?:ApplicationSubmitRequest):ApplicationSubmitRequest {
|
||||
return (obj || new ApplicationSubmitRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsApplicationSubmitRequest(bb:flatbuffers.ByteBuffer, obj?:ApplicationSubmitRequest):ApplicationSubmitRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new ApplicationSubmitRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
gameId():string|null
|
||||
gameId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
gameId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
raceName():string|null
|
||||
raceName(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
raceName(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
static startApplicationSubmitRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(2);
|
||||
}
|
||||
|
||||
static addGameId(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, gameIdOffset, 0);
|
||||
}
|
||||
|
||||
static addRaceName(builder:flatbuffers.Builder, raceNameOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, raceNameOffset, 0);
|
||||
}
|
||||
|
||||
static endApplicationSubmitRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createApplicationSubmitRequest(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset, raceNameOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
ApplicationSubmitRequest.startApplicationSubmitRequest(builder);
|
||||
ApplicationSubmitRequest.addGameId(builder, gameIdOffset);
|
||||
ApplicationSubmitRequest.addRaceName(builder, raceNameOffset);
|
||||
return ApplicationSubmitRequest.endApplicationSubmitRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): ApplicationSubmitRequestT {
|
||||
return new ApplicationSubmitRequestT(
|
||||
this.gameId(),
|
||||
this.raceName()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: ApplicationSubmitRequestT): void {
|
||||
_o.gameId = this.gameId();
|
||||
_o.raceName = this.raceName();
|
||||
}
|
||||
}
|
||||
|
||||
export class ApplicationSubmitRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public gameId: string|Uint8Array|null = null,
|
||||
public raceName: string|Uint8Array|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const gameId = (this.gameId !== null ? builder.createString(this.gameId!) : 0);
|
||||
const raceName = (this.raceName !== null ? builder.createString(this.raceName!) : 0);
|
||||
|
||||
return ApplicationSubmitRequest.createApplicationSubmitRequest(builder,
|
||||
gameId,
|
||||
raceName
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { ApplicationSummary, ApplicationSummaryT } from './application-summary.js';
|
||||
|
||||
|
||||
export class ApplicationSubmitResponse implements flatbuffers.IUnpackableObject<ApplicationSubmitResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):ApplicationSubmitResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsApplicationSubmitResponse(bb:flatbuffers.ByteBuffer, obj?:ApplicationSubmitResponse):ApplicationSubmitResponse {
|
||||
return (obj || new ApplicationSubmitResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsApplicationSubmitResponse(bb:flatbuffers.ByteBuffer, obj?:ApplicationSubmitResponse):ApplicationSubmitResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new ApplicationSubmitResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
application(obj?:ApplicationSummary):ApplicationSummary|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new ApplicationSummary()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
|
||||
}
|
||||
|
||||
static startApplicationSubmitResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addApplication(builder:flatbuffers.Builder, applicationOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, applicationOffset, 0);
|
||||
}
|
||||
|
||||
static endApplicationSubmitResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createApplicationSubmitResponse(builder:flatbuffers.Builder, applicationOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
ApplicationSubmitResponse.startApplicationSubmitResponse(builder);
|
||||
ApplicationSubmitResponse.addApplication(builder, applicationOffset);
|
||||
return ApplicationSubmitResponse.endApplicationSubmitResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): ApplicationSubmitResponseT {
|
||||
return new ApplicationSubmitResponseT(
|
||||
(this.application() !== null ? this.application()!.unpack() : null)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: ApplicationSubmitResponseT): void {
|
||||
_o.application = (this.application() !== null ? this.application()!.unpack() : null);
|
||||
}
|
||||
}
|
||||
|
||||
export class ApplicationSubmitResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public application: ApplicationSummaryT|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const application = (this.application !== null ? this.application!.pack(builder) : 0);
|
||||
|
||||
return ApplicationSubmitResponse.createApplicationSubmitResponse(builder,
|
||||
application
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class ApplicationSummary implements flatbuffers.IUnpackableObject<ApplicationSummaryT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):ApplicationSummary {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsApplicationSummary(bb:flatbuffers.ByteBuffer, obj?:ApplicationSummary):ApplicationSummary {
|
||||
return (obj || new ApplicationSummary()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsApplicationSummary(bb:flatbuffers.ByteBuffer, obj?:ApplicationSummary):ApplicationSummary {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new ApplicationSummary()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
applicationId():string|null
|
||||
applicationId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
applicationId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
gameId():string|null
|
||||
gameId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
gameId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
applicantUserId():string|null
|
||||
applicantUserId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
applicantUserId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 8);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
raceName():string|null
|
||||
raceName(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
raceName(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 10);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
status():string|null
|
||||
status(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
status(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 12);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
createdAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 14);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
decidedAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 16);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
static startApplicationSummary(builder:flatbuffers.Builder) {
|
||||
builder.startObject(7);
|
||||
}
|
||||
|
||||
static addApplicationId(builder:flatbuffers.Builder, applicationIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, applicationIdOffset, 0);
|
||||
}
|
||||
|
||||
static addGameId(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, gameIdOffset, 0);
|
||||
}
|
||||
|
||||
static addApplicantUserId(builder:flatbuffers.Builder, applicantUserIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(2, applicantUserIdOffset, 0);
|
||||
}
|
||||
|
||||
static addRaceName(builder:flatbuffers.Builder, raceNameOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(3, raceNameOffset, 0);
|
||||
}
|
||||
|
||||
static addStatus(builder:flatbuffers.Builder, statusOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(4, statusOffset, 0);
|
||||
}
|
||||
|
||||
static addCreatedAtMs(builder:flatbuffers.Builder, createdAtMs:bigint) {
|
||||
builder.addFieldInt64(5, createdAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static addDecidedAtMs(builder:flatbuffers.Builder, decidedAtMs:bigint) {
|
||||
builder.addFieldInt64(6, decidedAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static endApplicationSummary(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createApplicationSummary(builder:flatbuffers.Builder, applicationIdOffset:flatbuffers.Offset, gameIdOffset:flatbuffers.Offset, applicantUserIdOffset:flatbuffers.Offset, raceNameOffset:flatbuffers.Offset, statusOffset:flatbuffers.Offset, createdAtMs:bigint, decidedAtMs:bigint):flatbuffers.Offset {
|
||||
ApplicationSummary.startApplicationSummary(builder);
|
||||
ApplicationSummary.addApplicationId(builder, applicationIdOffset);
|
||||
ApplicationSummary.addGameId(builder, gameIdOffset);
|
||||
ApplicationSummary.addApplicantUserId(builder, applicantUserIdOffset);
|
||||
ApplicationSummary.addRaceName(builder, raceNameOffset);
|
||||
ApplicationSummary.addStatus(builder, statusOffset);
|
||||
ApplicationSummary.addCreatedAtMs(builder, createdAtMs);
|
||||
ApplicationSummary.addDecidedAtMs(builder, decidedAtMs);
|
||||
return ApplicationSummary.endApplicationSummary(builder);
|
||||
}
|
||||
|
||||
unpack(): ApplicationSummaryT {
|
||||
return new ApplicationSummaryT(
|
||||
this.applicationId(),
|
||||
this.gameId(),
|
||||
this.applicantUserId(),
|
||||
this.raceName(),
|
||||
this.status(),
|
||||
this.createdAtMs(),
|
||||
this.decidedAtMs()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: ApplicationSummaryT): void {
|
||||
_o.applicationId = this.applicationId();
|
||||
_o.gameId = this.gameId();
|
||||
_o.applicantUserId = this.applicantUserId();
|
||||
_o.raceName = this.raceName();
|
||||
_o.status = this.status();
|
||||
_o.createdAtMs = this.createdAtMs();
|
||||
_o.decidedAtMs = this.decidedAtMs();
|
||||
}
|
||||
}
|
||||
|
||||
export class ApplicationSummaryT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public applicationId: string|Uint8Array|null = null,
|
||||
public gameId: string|Uint8Array|null = null,
|
||||
public applicantUserId: string|Uint8Array|null = null,
|
||||
public raceName: string|Uint8Array|null = null,
|
||||
public status: string|Uint8Array|null = null,
|
||||
public createdAtMs: bigint = BigInt('0'),
|
||||
public decidedAtMs: bigint = BigInt('0')
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const applicationId = (this.applicationId !== null ? builder.createString(this.applicationId!) : 0);
|
||||
const gameId = (this.gameId !== null ? builder.createString(this.gameId!) : 0);
|
||||
const applicantUserId = (this.applicantUserId !== null ? builder.createString(this.applicantUserId!) : 0);
|
||||
const raceName = (this.raceName !== null ? builder.createString(this.raceName!) : 0);
|
||||
const status = (this.status !== null ? builder.createString(this.status!) : 0);
|
||||
|
||||
return ApplicationSummary.createApplicationSummary(builder,
|
||||
applicationId,
|
||||
gameId,
|
||||
applicantUserId,
|
||||
raceName,
|
||||
status,
|
||||
this.createdAtMs,
|
||||
this.decidedAtMs
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class ErrorBody implements flatbuffers.IUnpackableObject<ErrorBodyT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):ErrorBody {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsErrorBody(bb:flatbuffers.ByteBuffer, obj?:ErrorBody):ErrorBody {
|
||||
return (obj || new ErrorBody()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsErrorBody(bb:flatbuffers.ByteBuffer, obj?:ErrorBody):ErrorBody {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new ErrorBody()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
code():string|null
|
||||
code(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
code(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
message():string|null
|
||||
message(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
message(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
static startErrorBody(builder:flatbuffers.Builder) {
|
||||
builder.startObject(2);
|
||||
}
|
||||
|
||||
static addCode(builder:flatbuffers.Builder, codeOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, codeOffset, 0);
|
||||
}
|
||||
|
||||
static addMessage(builder:flatbuffers.Builder, messageOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, messageOffset, 0);
|
||||
}
|
||||
|
||||
static endErrorBody(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createErrorBody(builder:flatbuffers.Builder, codeOffset:flatbuffers.Offset, messageOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
ErrorBody.startErrorBody(builder);
|
||||
ErrorBody.addCode(builder, codeOffset);
|
||||
ErrorBody.addMessage(builder, messageOffset);
|
||||
return ErrorBody.endErrorBody(builder);
|
||||
}
|
||||
|
||||
unpack(): ErrorBodyT {
|
||||
return new ErrorBodyT(
|
||||
this.code(),
|
||||
this.message()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: ErrorBodyT): void {
|
||||
_o.code = this.code();
|
||||
_o.message = this.message();
|
||||
}
|
||||
}
|
||||
|
||||
export class ErrorBodyT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public code: string|Uint8Array|null = null,
|
||||
public message: string|Uint8Array|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const code = (this.code !== null ? builder.createString(this.code!) : 0);
|
||||
const message = (this.message !== null ? builder.createString(this.message!) : 0);
|
||||
|
||||
return ErrorBody.createErrorBody(builder,
|
||||
code,
|
||||
message
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { ErrorBody, ErrorBodyT } from './error-body.js';
|
||||
|
||||
|
||||
export class ErrorResponse implements flatbuffers.IUnpackableObject<ErrorResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):ErrorResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsErrorResponse(bb:flatbuffers.ByteBuffer, obj?:ErrorResponse):ErrorResponse {
|
||||
return (obj || new ErrorResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsErrorResponse(bb:flatbuffers.ByteBuffer, obj?:ErrorResponse):ErrorResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new ErrorResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
error(obj?:ErrorBody):ErrorBody|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new ErrorBody()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
|
||||
}
|
||||
|
||||
static startErrorResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addError(builder:flatbuffers.Builder, errorOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, errorOffset, 0);
|
||||
}
|
||||
|
||||
static endErrorResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createErrorResponse(builder:flatbuffers.Builder, errorOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
ErrorResponse.startErrorResponse(builder);
|
||||
ErrorResponse.addError(builder, errorOffset);
|
||||
return ErrorResponse.endErrorResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): ErrorResponseT {
|
||||
return new ErrorResponseT(
|
||||
(this.error() !== null ? this.error()!.unpack() : null)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: ErrorResponseT): void {
|
||||
_o.error = (this.error() !== null ? this.error()!.unpack() : null);
|
||||
}
|
||||
}
|
||||
|
||||
export class ErrorResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public error: ErrorBodyT|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const error = (this.error !== null ? this.error!.pack(builder) : 0);
|
||||
|
||||
return ErrorResponse.createErrorResponse(builder,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class GameCreateRequest implements flatbuffers.IUnpackableObject<GameCreateRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):GameCreateRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsGameCreateRequest(bb:flatbuffers.ByteBuffer, obj?:GameCreateRequest):GameCreateRequest {
|
||||
return (obj || new GameCreateRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsGameCreateRequest(bb:flatbuffers.ByteBuffer, obj?:GameCreateRequest):GameCreateRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new GameCreateRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
gameName():string|null
|
||||
gameName(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
gameName(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
description():string|null
|
||||
description(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
description(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
minPlayers():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 8);
|
||||
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
maxPlayers():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 10);
|
||||
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
startGapHours():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 12);
|
||||
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
startGapPlayers():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 14);
|
||||
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
enrollmentEndsAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 16);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
turnSchedule():string|null
|
||||
turnSchedule(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
turnSchedule(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 18);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
targetEngineVersion():string|null
|
||||
targetEngineVersion(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
targetEngineVersion(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 20);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
static startGameCreateRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(9);
|
||||
}
|
||||
|
||||
static addGameName(builder:flatbuffers.Builder, gameNameOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, gameNameOffset, 0);
|
||||
}
|
||||
|
||||
static addDescription(builder:flatbuffers.Builder, descriptionOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, descriptionOffset, 0);
|
||||
}
|
||||
|
||||
static addMinPlayers(builder:flatbuffers.Builder, minPlayers:number) {
|
||||
builder.addFieldInt32(2, minPlayers, 0);
|
||||
}
|
||||
|
||||
static addMaxPlayers(builder:flatbuffers.Builder, maxPlayers:number) {
|
||||
builder.addFieldInt32(3, maxPlayers, 0);
|
||||
}
|
||||
|
||||
static addStartGapHours(builder:flatbuffers.Builder, startGapHours:number) {
|
||||
builder.addFieldInt32(4, startGapHours, 0);
|
||||
}
|
||||
|
||||
static addStartGapPlayers(builder:flatbuffers.Builder, startGapPlayers:number) {
|
||||
builder.addFieldInt32(5, startGapPlayers, 0);
|
||||
}
|
||||
|
||||
static addEnrollmentEndsAtMs(builder:flatbuffers.Builder, enrollmentEndsAtMs:bigint) {
|
||||
builder.addFieldInt64(6, enrollmentEndsAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static addTurnSchedule(builder:flatbuffers.Builder, turnScheduleOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(7, turnScheduleOffset, 0);
|
||||
}
|
||||
|
||||
static addTargetEngineVersion(builder:flatbuffers.Builder, targetEngineVersionOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(8, targetEngineVersionOffset, 0);
|
||||
}
|
||||
|
||||
static endGameCreateRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createGameCreateRequest(builder:flatbuffers.Builder, gameNameOffset:flatbuffers.Offset, descriptionOffset:flatbuffers.Offset, minPlayers:number, maxPlayers:number, startGapHours:number, startGapPlayers:number, enrollmentEndsAtMs:bigint, turnScheduleOffset:flatbuffers.Offset, targetEngineVersionOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
GameCreateRequest.startGameCreateRequest(builder);
|
||||
GameCreateRequest.addGameName(builder, gameNameOffset);
|
||||
GameCreateRequest.addDescription(builder, descriptionOffset);
|
||||
GameCreateRequest.addMinPlayers(builder, minPlayers);
|
||||
GameCreateRequest.addMaxPlayers(builder, maxPlayers);
|
||||
GameCreateRequest.addStartGapHours(builder, startGapHours);
|
||||
GameCreateRequest.addStartGapPlayers(builder, startGapPlayers);
|
||||
GameCreateRequest.addEnrollmentEndsAtMs(builder, enrollmentEndsAtMs);
|
||||
GameCreateRequest.addTurnSchedule(builder, turnScheduleOffset);
|
||||
GameCreateRequest.addTargetEngineVersion(builder, targetEngineVersionOffset);
|
||||
return GameCreateRequest.endGameCreateRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): GameCreateRequestT {
|
||||
return new GameCreateRequestT(
|
||||
this.gameName(),
|
||||
this.description(),
|
||||
this.minPlayers(),
|
||||
this.maxPlayers(),
|
||||
this.startGapHours(),
|
||||
this.startGapPlayers(),
|
||||
this.enrollmentEndsAtMs(),
|
||||
this.turnSchedule(),
|
||||
this.targetEngineVersion()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: GameCreateRequestT): void {
|
||||
_o.gameName = this.gameName();
|
||||
_o.description = this.description();
|
||||
_o.minPlayers = this.minPlayers();
|
||||
_o.maxPlayers = this.maxPlayers();
|
||||
_o.startGapHours = this.startGapHours();
|
||||
_o.startGapPlayers = this.startGapPlayers();
|
||||
_o.enrollmentEndsAtMs = this.enrollmentEndsAtMs();
|
||||
_o.turnSchedule = this.turnSchedule();
|
||||
_o.targetEngineVersion = this.targetEngineVersion();
|
||||
}
|
||||
}
|
||||
|
||||
export class GameCreateRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public gameName: string|Uint8Array|null = null,
|
||||
public description: string|Uint8Array|null = null,
|
||||
public minPlayers: number = 0,
|
||||
public maxPlayers: number = 0,
|
||||
public startGapHours: number = 0,
|
||||
public startGapPlayers: number = 0,
|
||||
public enrollmentEndsAtMs: bigint = BigInt('0'),
|
||||
public turnSchedule: string|Uint8Array|null = null,
|
||||
public targetEngineVersion: string|Uint8Array|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const gameName = (this.gameName !== null ? builder.createString(this.gameName!) : 0);
|
||||
const description = (this.description !== null ? builder.createString(this.description!) : 0);
|
||||
const turnSchedule = (this.turnSchedule !== null ? builder.createString(this.turnSchedule!) : 0);
|
||||
const targetEngineVersion = (this.targetEngineVersion !== null ? builder.createString(this.targetEngineVersion!) : 0);
|
||||
|
||||
return GameCreateRequest.createGameCreateRequest(builder,
|
||||
gameName,
|
||||
description,
|
||||
this.minPlayers,
|
||||
this.maxPlayers,
|
||||
this.startGapHours,
|
||||
this.startGapPlayers,
|
||||
this.enrollmentEndsAtMs,
|
||||
turnSchedule,
|
||||
targetEngineVersion
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { GameSummary, GameSummaryT } from './game-summary.js';
|
||||
|
||||
|
||||
export class GameCreateResponse implements flatbuffers.IUnpackableObject<GameCreateResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):GameCreateResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsGameCreateResponse(bb:flatbuffers.ByteBuffer, obj?:GameCreateResponse):GameCreateResponse {
|
||||
return (obj || new GameCreateResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsGameCreateResponse(bb:flatbuffers.ByteBuffer, obj?:GameCreateResponse):GameCreateResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new GameCreateResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
game(obj?:GameSummary):GameSummary|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new GameSummary()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
|
||||
}
|
||||
|
||||
static startGameCreateResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addGame(builder:flatbuffers.Builder, gameOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, gameOffset, 0);
|
||||
}
|
||||
|
||||
static endGameCreateResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createGameCreateResponse(builder:flatbuffers.Builder, gameOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
GameCreateResponse.startGameCreateResponse(builder);
|
||||
GameCreateResponse.addGame(builder, gameOffset);
|
||||
return GameCreateResponse.endGameCreateResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): GameCreateResponseT {
|
||||
return new GameCreateResponseT(
|
||||
(this.game() !== null ? this.game()!.unpack() : null)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: GameCreateResponseT): void {
|
||||
_o.game = (this.game() !== null ? this.game()!.unpack() : null);
|
||||
}
|
||||
}
|
||||
|
||||
export class GameCreateResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public game: GameSummaryT|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const game = (this.game !== null ? this.game!.pack(builder) : 0);
|
||||
|
||||
return GameCreateResponse.createGameCreateResponse(builder,
|
||||
game
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class GameSummary implements flatbuffers.IUnpackableObject<GameSummaryT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):GameSummary {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsGameSummary(bb:flatbuffers.ByteBuffer, obj?:GameSummary):GameSummary {
|
||||
return (obj || new GameSummary()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsGameSummary(bb:flatbuffers.ByteBuffer, obj?:GameSummary):GameSummary {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new GameSummary()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
gameId():string|null
|
||||
gameId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
gameId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
gameName():string|null
|
||||
gameName(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
gameName(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
gameType():string|null
|
||||
gameType(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
gameType(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 8);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
status():string|null
|
||||
status(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
status(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 10);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
ownerUserId():string|null
|
||||
ownerUserId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
ownerUserId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 12);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
minPlayers():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 14);
|
||||
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
maxPlayers():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 16);
|
||||
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
enrollmentEndsAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 18);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
createdAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 20);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
updatedAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 22);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
static startGameSummary(builder:flatbuffers.Builder) {
|
||||
builder.startObject(10);
|
||||
}
|
||||
|
||||
static addGameId(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, gameIdOffset, 0);
|
||||
}
|
||||
|
||||
static addGameName(builder:flatbuffers.Builder, gameNameOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, gameNameOffset, 0);
|
||||
}
|
||||
|
||||
static addGameType(builder:flatbuffers.Builder, gameTypeOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(2, gameTypeOffset, 0);
|
||||
}
|
||||
|
||||
static addStatus(builder:flatbuffers.Builder, statusOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(3, statusOffset, 0);
|
||||
}
|
||||
|
||||
static addOwnerUserId(builder:flatbuffers.Builder, ownerUserIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(4, ownerUserIdOffset, 0);
|
||||
}
|
||||
|
||||
static addMinPlayers(builder:flatbuffers.Builder, minPlayers:number) {
|
||||
builder.addFieldInt32(5, minPlayers, 0);
|
||||
}
|
||||
|
||||
static addMaxPlayers(builder:flatbuffers.Builder, maxPlayers:number) {
|
||||
builder.addFieldInt32(6, maxPlayers, 0);
|
||||
}
|
||||
|
||||
static addEnrollmentEndsAtMs(builder:flatbuffers.Builder, enrollmentEndsAtMs:bigint) {
|
||||
builder.addFieldInt64(7, enrollmentEndsAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static addCreatedAtMs(builder:flatbuffers.Builder, createdAtMs:bigint) {
|
||||
builder.addFieldInt64(8, createdAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static addUpdatedAtMs(builder:flatbuffers.Builder, updatedAtMs:bigint) {
|
||||
builder.addFieldInt64(9, updatedAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static endGameSummary(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createGameSummary(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset, gameNameOffset:flatbuffers.Offset, gameTypeOffset:flatbuffers.Offset, statusOffset:flatbuffers.Offset, ownerUserIdOffset:flatbuffers.Offset, minPlayers:number, maxPlayers:number, enrollmentEndsAtMs:bigint, createdAtMs:bigint, updatedAtMs:bigint):flatbuffers.Offset {
|
||||
GameSummary.startGameSummary(builder);
|
||||
GameSummary.addGameId(builder, gameIdOffset);
|
||||
GameSummary.addGameName(builder, gameNameOffset);
|
||||
GameSummary.addGameType(builder, gameTypeOffset);
|
||||
GameSummary.addStatus(builder, statusOffset);
|
||||
GameSummary.addOwnerUserId(builder, ownerUserIdOffset);
|
||||
GameSummary.addMinPlayers(builder, minPlayers);
|
||||
GameSummary.addMaxPlayers(builder, maxPlayers);
|
||||
GameSummary.addEnrollmentEndsAtMs(builder, enrollmentEndsAtMs);
|
||||
GameSummary.addCreatedAtMs(builder, createdAtMs);
|
||||
GameSummary.addUpdatedAtMs(builder, updatedAtMs);
|
||||
return GameSummary.endGameSummary(builder);
|
||||
}
|
||||
|
||||
unpack(): GameSummaryT {
|
||||
return new GameSummaryT(
|
||||
this.gameId(),
|
||||
this.gameName(),
|
||||
this.gameType(),
|
||||
this.status(),
|
||||
this.ownerUserId(),
|
||||
this.minPlayers(),
|
||||
this.maxPlayers(),
|
||||
this.enrollmentEndsAtMs(),
|
||||
this.createdAtMs(),
|
||||
this.updatedAtMs()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: GameSummaryT): void {
|
||||
_o.gameId = this.gameId();
|
||||
_o.gameName = this.gameName();
|
||||
_o.gameType = this.gameType();
|
||||
_o.status = this.status();
|
||||
_o.ownerUserId = this.ownerUserId();
|
||||
_o.minPlayers = this.minPlayers();
|
||||
_o.maxPlayers = this.maxPlayers();
|
||||
_o.enrollmentEndsAtMs = this.enrollmentEndsAtMs();
|
||||
_o.createdAtMs = this.createdAtMs();
|
||||
_o.updatedAtMs = this.updatedAtMs();
|
||||
}
|
||||
}
|
||||
|
||||
export class GameSummaryT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public gameId: string|Uint8Array|null = null,
|
||||
public gameName: string|Uint8Array|null = null,
|
||||
public gameType: string|Uint8Array|null = null,
|
||||
public status: string|Uint8Array|null = null,
|
||||
public ownerUserId: string|Uint8Array|null = null,
|
||||
public minPlayers: number = 0,
|
||||
public maxPlayers: number = 0,
|
||||
public enrollmentEndsAtMs: bigint = BigInt('0'),
|
||||
public createdAtMs: bigint = BigInt('0'),
|
||||
public updatedAtMs: bigint = BigInt('0')
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const gameId = (this.gameId !== null ? builder.createString(this.gameId!) : 0);
|
||||
const gameName = (this.gameName !== null ? builder.createString(this.gameName!) : 0);
|
||||
const gameType = (this.gameType !== null ? builder.createString(this.gameType!) : 0);
|
||||
const status = (this.status !== null ? builder.createString(this.status!) : 0);
|
||||
const ownerUserId = (this.ownerUserId !== null ? builder.createString(this.ownerUserId!) : 0);
|
||||
|
||||
return GameSummary.createGameSummary(builder,
|
||||
gameId,
|
||||
gameName,
|
||||
gameType,
|
||||
status,
|
||||
ownerUserId,
|
||||
this.minPlayers,
|
||||
this.maxPlayers,
|
||||
this.enrollmentEndsAtMs,
|
||||
this.createdAtMs,
|
||||
this.updatedAtMs
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class InviteDeclineRequest implements flatbuffers.IUnpackableObject<InviteDeclineRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):InviteDeclineRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsInviteDeclineRequest(bb:flatbuffers.ByteBuffer, obj?:InviteDeclineRequest):InviteDeclineRequest {
|
||||
return (obj || new InviteDeclineRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsInviteDeclineRequest(bb:flatbuffers.ByteBuffer, obj?:InviteDeclineRequest):InviteDeclineRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new InviteDeclineRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
gameId():string|null
|
||||
gameId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
gameId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
inviteId():string|null
|
||||
inviteId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
inviteId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
static startInviteDeclineRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(2);
|
||||
}
|
||||
|
||||
static addGameId(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, gameIdOffset, 0);
|
||||
}
|
||||
|
||||
static addInviteId(builder:flatbuffers.Builder, inviteIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, inviteIdOffset, 0);
|
||||
}
|
||||
|
||||
static endInviteDeclineRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createInviteDeclineRequest(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset, inviteIdOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
InviteDeclineRequest.startInviteDeclineRequest(builder);
|
||||
InviteDeclineRequest.addGameId(builder, gameIdOffset);
|
||||
InviteDeclineRequest.addInviteId(builder, inviteIdOffset);
|
||||
return InviteDeclineRequest.endInviteDeclineRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): InviteDeclineRequestT {
|
||||
return new InviteDeclineRequestT(
|
||||
this.gameId(),
|
||||
this.inviteId()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: InviteDeclineRequestT): void {
|
||||
_o.gameId = this.gameId();
|
||||
_o.inviteId = this.inviteId();
|
||||
}
|
||||
}
|
||||
|
||||
export class InviteDeclineRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public gameId: string|Uint8Array|null = null,
|
||||
public inviteId: string|Uint8Array|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const gameId = (this.gameId !== null ? builder.createString(this.gameId!) : 0);
|
||||
const inviteId = (this.inviteId !== null ? builder.createString(this.inviteId!) : 0);
|
||||
|
||||
return InviteDeclineRequest.createInviteDeclineRequest(builder,
|
||||
gameId,
|
||||
inviteId
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { InviteSummary, InviteSummaryT } from './invite-summary.js';
|
||||
|
||||
|
||||
export class InviteDeclineResponse implements flatbuffers.IUnpackableObject<InviteDeclineResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):InviteDeclineResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsInviteDeclineResponse(bb:flatbuffers.ByteBuffer, obj?:InviteDeclineResponse):InviteDeclineResponse {
|
||||
return (obj || new InviteDeclineResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsInviteDeclineResponse(bb:flatbuffers.ByteBuffer, obj?:InviteDeclineResponse):InviteDeclineResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new InviteDeclineResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
invite(obj?:InviteSummary):InviteSummary|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new InviteSummary()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
|
||||
}
|
||||
|
||||
static startInviteDeclineResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addInvite(builder:flatbuffers.Builder, inviteOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, inviteOffset, 0);
|
||||
}
|
||||
|
||||
static endInviteDeclineResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createInviteDeclineResponse(builder:flatbuffers.Builder, inviteOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
InviteDeclineResponse.startInviteDeclineResponse(builder);
|
||||
InviteDeclineResponse.addInvite(builder, inviteOffset);
|
||||
return InviteDeclineResponse.endInviteDeclineResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): InviteDeclineResponseT {
|
||||
return new InviteDeclineResponseT(
|
||||
(this.invite() !== null ? this.invite()!.unpack() : null)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: InviteDeclineResponseT): void {
|
||||
_o.invite = (this.invite() !== null ? this.invite()!.unpack() : null);
|
||||
}
|
||||
}
|
||||
|
||||
export class InviteDeclineResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public invite: InviteSummaryT|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const invite = (this.invite !== null ? this.invite!.pack(builder) : 0);
|
||||
|
||||
return InviteDeclineResponse.createInviteDeclineResponse(builder,
|
||||
invite
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class InviteRedeemRequest implements flatbuffers.IUnpackableObject<InviteRedeemRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):InviteRedeemRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsInviteRedeemRequest(bb:flatbuffers.ByteBuffer, obj?:InviteRedeemRequest):InviteRedeemRequest {
|
||||
return (obj || new InviteRedeemRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsInviteRedeemRequest(bb:flatbuffers.ByteBuffer, obj?:InviteRedeemRequest):InviteRedeemRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new InviteRedeemRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
gameId():string|null
|
||||
gameId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
gameId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
inviteId():string|null
|
||||
inviteId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
inviteId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
static startInviteRedeemRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(2);
|
||||
}
|
||||
|
||||
static addGameId(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, gameIdOffset, 0);
|
||||
}
|
||||
|
||||
static addInviteId(builder:flatbuffers.Builder, inviteIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, inviteIdOffset, 0);
|
||||
}
|
||||
|
||||
static endInviteRedeemRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createInviteRedeemRequest(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset, inviteIdOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
InviteRedeemRequest.startInviteRedeemRequest(builder);
|
||||
InviteRedeemRequest.addGameId(builder, gameIdOffset);
|
||||
InviteRedeemRequest.addInviteId(builder, inviteIdOffset);
|
||||
return InviteRedeemRequest.endInviteRedeemRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): InviteRedeemRequestT {
|
||||
return new InviteRedeemRequestT(
|
||||
this.gameId(),
|
||||
this.inviteId()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: InviteRedeemRequestT): void {
|
||||
_o.gameId = this.gameId();
|
||||
_o.inviteId = this.inviteId();
|
||||
}
|
||||
}
|
||||
|
||||
export class InviteRedeemRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public gameId: string|Uint8Array|null = null,
|
||||
public inviteId: string|Uint8Array|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const gameId = (this.gameId !== null ? builder.createString(this.gameId!) : 0);
|
||||
const inviteId = (this.inviteId !== null ? builder.createString(this.inviteId!) : 0);
|
||||
|
||||
return InviteRedeemRequest.createInviteRedeemRequest(builder,
|
||||
gameId,
|
||||
inviteId
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { InviteSummary, InviteSummaryT } from './invite-summary.js';
|
||||
|
||||
|
||||
export class InviteRedeemResponse implements flatbuffers.IUnpackableObject<InviteRedeemResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):InviteRedeemResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsInviteRedeemResponse(bb:flatbuffers.ByteBuffer, obj?:InviteRedeemResponse):InviteRedeemResponse {
|
||||
return (obj || new InviteRedeemResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsInviteRedeemResponse(bb:flatbuffers.ByteBuffer, obj?:InviteRedeemResponse):InviteRedeemResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new InviteRedeemResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
invite(obj?:InviteSummary):InviteSummary|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new InviteSummary()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
|
||||
}
|
||||
|
||||
static startInviteRedeemResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addInvite(builder:flatbuffers.Builder, inviteOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, inviteOffset, 0);
|
||||
}
|
||||
|
||||
static endInviteRedeemResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createInviteRedeemResponse(builder:flatbuffers.Builder, inviteOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
InviteRedeemResponse.startInviteRedeemResponse(builder);
|
||||
InviteRedeemResponse.addInvite(builder, inviteOffset);
|
||||
return InviteRedeemResponse.endInviteRedeemResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): InviteRedeemResponseT {
|
||||
return new InviteRedeemResponseT(
|
||||
(this.invite() !== null ? this.invite()!.unpack() : null)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: InviteRedeemResponseT): void {
|
||||
_o.invite = (this.invite() !== null ? this.invite()!.unpack() : null);
|
||||
}
|
||||
}
|
||||
|
||||
export class InviteRedeemResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public invite: InviteSummaryT|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const invite = (this.invite !== null ? this.invite!.pack(builder) : 0);
|
||||
|
||||
return InviteRedeemResponse.createInviteRedeemResponse(builder,
|
||||
invite
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class InviteSummary implements flatbuffers.IUnpackableObject<InviteSummaryT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):InviteSummary {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsInviteSummary(bb:flatbuffers.ByteBuffer, obj?:InviteSummary):InviteSummary {
|
||||
return (obj || new InviteSummary()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsInviteSummary(bb:flatbuffers.ByteBuffer, obj?:InviteSummary):InviteSummary {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new InviteSummary()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
inviteId():string|null
|
||||
inviteId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
inviteId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
gameId():string|null
|
||||
gameId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
gameId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
inviterUserId():string|null
|
||||
inviterUserId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
inviterUserId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 8);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
invitedUserId():string|null
|
||||
invitedUserId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
invitedUserId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 10);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
code():string|null
|
||||
code(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
code(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 12);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
raceName():string|null
|
||||
raceName(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
raceName(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 14);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
status():string|null
|
||||
status(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
status(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 16);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
createdAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 18);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
expiresAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 20);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
decidedAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 22);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
static startInviteSummary(builder:flatbuffers.Builder) {
|
||||
builder.startObject(10);
|
||||
}
|
||||
|
||||
static addInviteId(builder:flatbuffers.Builder, inviteIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, inviteIdOffset, 0);
|
||||
}
|
||||
|
||||
static addGameId(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, gameIdOffset, 0);
|
||||
}
|
||||
|
||||
static addInviterUserId(builder:flatbuffers.Builder, inviterUserIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(2, inviterUserIdOffset, 0);
|
||||
}
|
||||
|
||||
static addInvitedUserId(builder:flatbuffers.Builder, invitedUserIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(3, invitedUserIdOffset, 0);
|
||||
}
|
||||
|
||||
static addCode(builder:flatbuffers.Builder, codeOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(4, codeOffset, 0);
|
||||
}
|
||||
|
||||
static addRaceName(builder:flatbuffers.Builder, raceNameOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(5, raceNameOffset, 0);
|
||||
}
|
||||
|
||||
static addStatus(builder:flatbuffers.Builder, statusOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(6, statusOffset, 0);
|
||||
}
|
||||
|
||||
static addCreatedAtMs(builder:flatbuffers.Builder, createdAtMs:bigint) {
|
||||
builder.addFieldInt64(7, createdAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static addExpiresAtMs(builder:flatbuffers.Builder, expiresAtMs:bigint) {
|
||||
builder.addFieldInt64(8, expiresAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static addDecidedAtMs(builder:flatbuffers.Builder, decidedAtMs:bigint) {
|
||||
builder.addFieldInt64(9, decidedAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static endInviteSummary(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createInviteSummary(builder:flatbuffers.Builder, inviteIdOffset:flatbuffers.Offset, gameIdOffset:flatbuffers.Offset, inviterUserIdOffset:flatbuffers.Offset, invitedUserIdOffset:flatbuffers.Offset, codeOffset:flatbuffers.Offset, raceNameOffset:flatbuffers.Offset, statusOffset:flatbuffers.Offset, createdAtMs:bigint, expiresAtMs:bigint, decidedAtMs:bigint):flatbuffers.Offset {
|
||||
InviteSummary.startInviteSummary(builder);
|
||||
InviteSummary.addInviteId(builder, inviteIdOffset);
|
||||
InviteSummary.addGameId(builder, gameIdOffset);
|
||||
InviteSummary.addInviterUserId(builder, inviterUserIdOffset);
|
||||
InviteSummary.addInvitedUserId(builder, invitedUserIdOffset);
|
||||
InviteSummary.addCode(builder, codeOffset);
|
||||
InviteSummary.addRaceName(builder, raceNameOffset);
|
||||
InviteSummary.addStatus(builder, statusOffset);
|
||||
InviteSummary.addCreatedAtMs(builder, createdAtMs);
|
||||
InviteSummary.addExpiresAtMs(builder, expiresAtMs);
|
||||
InviteSummary.addDecidedAtMs(builder, decidedAtMs);
|
||||
return InviteSummary.endInviteSummary(builder);
|
||||
}
|
||||
|
||||
unpack(): InviteSummaryT {
|
||||
return new InviteSummaryT(
|
||||
this.inviteId(),
|
||||
this.gameId(),
|
||||
this.inviterUserId(),
|
||||
this.invitedUserId(),
|
||||
this.code(),
|
||||
this.raceName(),
|
||||
this.status(),
|
||||
this.createdAtMs(),
|
||||
this.expiresAtMs(),
|
||||
this.decidedAtMs()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: InviteSummaryT): void {
|
||||
_o.inviteId = this.inviteId();
|
||||
_o.gameId = this.gameId();
|
||||
_o.inviterUserId = this.inviterUserId();
|
||||
_o.invitedUserId = this.invitedUserId();
|
||||
_o.code = this.code();
|
||||
_o.raceName = this.raceName();
|
||||
_o.status = this.status();
|
||||
_o.createdAtMs = this.createdAtMs();
|
||||
_o.expiresAtMs = this.expiresAtMs();
|
||||
_o.decidedAtMs = this.decidedAtMs();
|
||||
}
|
||||
}
|
||||
|
||||
export class InviteSummaryT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public inviteId: string|Uint8Array|null = null,
|
||||
public gameId: string|Uint8Array|null = null,
|
||||
public inviterUserId: string|Uint8Array|null = null,
|
||||
public invitedUserId: string|Uint8Array|null = null,
|
||||
public code: string|Uint8Array|null = null,
|
||||
public raceName: string|Uint8Array|null = null,
|
||||
public status: string|Uint8Array|null = null,
|
||||
public createdAtMs: bigint = BigInt('0'),
|
||||
public expiresAtMs: bigint = BigInt('0'),
|
||||
public decidedAtMs: bigint = BigInt('0')
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const inviteId = (this.inviteId !== null ? builder.createString(this.inviteId!) : 0);
|
||||
const gameId = (this.gameId !== null ? builder.createString(this.gameId!) : 0);
|
||||
const inviterUserId = (this.inviterUserId !== null ? builder.createString(this.inviterUserId!) : 0);
|
||||
const invitedUserId = (this.invitedUserId !== null ? builder.createString(this.invitedUserId!) : 0);
|
||||
const code = (this.code !== null ? builder.createString(this.code!) : 0);
|
||||
const raceName = (this.raceName !== null ? builder.createString(this.raceName!) : 0);
|
||||
const status = (this.status !== null ? builder.createString(this.status!) : 0);
|
||||
|
||||
return InviteSummary.createInviteSummary(builder,
|
||||
inviteId,
|
||||
gameId,
|
||||
inviterUserId,
|
||||
invitedUserId,
|
||||
code,
|
||||
raceName,
|
||||
status,
|
||||
this.createdAtMs,
|
||||
this.expiresAtMs,
|
||||
this.decidedAtMs
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class MyApplicationsListRequest implements flatbuffers.IUnpackableObject<MyApplicationsListRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):MyApplicationsListRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsMyApplicationsListRequest(bb:flatbuffers.ByteBuffer, obj?:MyApplicationsListRequest):MyApplicationsListRequest {
|
||||
return (obj || new MyApplicationsListRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsMyApplicationsListRequest(bb:flatbuffers.ByteBuffer, obj?:MyApplicationsListRequest):MyApplicationsListRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new MyApplicationsListRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static startMyApplicationsListRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(0);
|
||||
}
|
||||
|
||||
static endMyApplicationsListRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createMyApplicationsListRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
MyApplicationsListRequest.startMyApplicationsListRequest(builder);
|
||||
return MyApplicationsListRequest.endMyApplicationsListRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): MyApplicationsListRequestT {
|
||||
return new MyApplicationsListRequestT();
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: MyApplicationsListRequestT): void {}
|
||||
}
|
||||
|
||||
export class MyApplicationsListRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
return MyApplicationsListRequest.createMyApplicationsListRequest(builder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { ApplicationSummary, ApplicationSummaryT } from './application-summary.js';
|
||||
|
||||
|
||||
export class MyApplicationsListResponse implements flatbuffers.IUnpackableObject<MyApplicationsListResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):MyApplicationsListResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsMyApplicationsListResponse(bb:flatbuffers.ByteBuffer, obj?:MyApplicationsListResponse):MyApplicationsListResponse {
|
||||
return (obj || new MyApplicationsListResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsMyApplicationsListResponse(bb:flatbuffers.ByteBuffer, obj?:MyApplicationsListResponse):MyApplicationsListResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new MyApplicationsListResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
items(index: number, obj?:ApplicationSummary):ApplicationSummary|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new ApplicationSummary()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null;
|
||||
}
|
||||
|
||||
itemsLength():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
static startMyApplicationsListResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addItems(builder:flatbuffers.Builder, itemsOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, itemsOffset, 0);
|
||||
}
|
||||
|
||||
static createItemsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset {
|
||||
builder.startVector(4, data.length, 4);
|
||||
for (let i = data.length - 1; i >= 0; i--) {
|
||||
builder.addOffset(data[i]!);
|
||||
}
|
||||
return builder.endVector();
|
||||
}
|
||||
|
||||
static startItemsVector(builder:flatbuffers.Builder, numElems:number) {
|
||||
builder.startVector(4, numElems, 4);
|
||||
}
|
||||
|
||||
static endMyApplicationsListResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createMyApplicationsListResponse(builder:flatbuffers.Builder, itemsOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
MyApplicationsListResponse.startMyApplicationsListResponse(builder);
|
||||
MyApplicationsListResponse.addItems(builder, itemsOffset);
|
||||
return MyApplicationsListResponse.endMyApplicationsListResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): MyApplicationsListResponseT {
|
||||
return new MyApplicationsListResponseT(
|
||||
this.bb!.createObjList<ApplicationSummary, ApplicationSummaryT>(this.items.bind(this), this.itemsLength())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: MyApplicationsListResponseT): void {
|
||||
_o.items = this.bb!.createObjList<ApplicationSummary, ApplicationSummaryT>(this.items.bind(this), this.itemsLength());
|
||||
}
|
||||
}
|
||||
|
||||
export class MyApplicationsListResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public items: (ApplicationSummaryT)[] = []
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const items = MyApplicationsListResponse.createItemsVector(builder, builder.createObjectOffsetList(this.items));
|
||||
|
||||
return MyApplicationsListResponse.createMyApplicationsListResponse(builder,
|
||||
items
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class MyGamesListRequest implements flatbuffers.IUnpackableObject<MyGamesListRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):MyGamesListRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsMyGamesListRequest(bb:flatbuffers.ByteBuffer, obj?:MyGamesListRequest):MyGamesListRequest {
|
||||
return (obj || new MyGamesListRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsMyGamesListRequest(bb:flatbuffers.ByteBuffer, obj?:MyGamesListRequest):MyGamesListRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new MyGamesListRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static startMyGamesListRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(0);
|
||||
}
|
||||
|
||||
static endMyGamesListRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createMyGamesListRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
MyGamesListRequest.startMyGamesListRequest(builder);
|
||||
return MyGamesListRequest.endMyGamesListRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): MyGamesListRequestT {
|
||||
return new MyGamesListRequestT();
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: MyGamesListRequestT): void {}
|
||||
}
|
||||
|
||||
export class MyGamesListRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
return MyGamesListRequest.createMyGamesListRequest(builder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { GameSummary, GameSummaryT } from './game-summary.js';
|
||||
|
||||
|
||||
export class MyGamesListResponse implements flatbuffers.IUnpackableObject<MyGamesListResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):MyGamesListResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsMyGamesListResponse(bb:flatbuffers.ByteBuffer, obj?:MyGamesListResponse):MyGamesListResponse {
|
||||
return (obj || new MyGamesListResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsMyGamesListResponse(bb:flatbuffers.ByteBuffer, obj?:MyGamesListResponse):MyGamesListResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new MyGamesListResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
items(index: number, obj?:GameSummary):GameSummary|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new GameSummary()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null;
|
||||
}
|
||||
|
||||
itemsLength():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
static startMyGamesListResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addItems(builder:flatbuffers.Builder, itemsOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, itemsOffset, 0);
|
||||
}
|
||||
|
||||
static createItemsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset {
|
||||
builder.startVector(4, data.length, 4);
|
||||
for (let i = data.length - 1; i >= 0; i--) {
|
||||
builder.addOffset(data[i]!);
|
||||
}
|
||||
return builder.endVector();
|
||||
}
|
||||
|
||||
static startItemsVector(builder:flatbuffers.Builder, numElems:number) {
|
||||
builder.startVector(4, numElems, 4);
|
||||
}
|
||||
|
||||
static endMyGamesListResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static finishMyGamesListResponseBuffer(builder:flatbuffers.Builder, offset:flatbuffers.Offset) {
|
||||
builder.finish(offset);
|
||||
}
|
||||
|
||||
static finishSizePrefixedMyGamesListResponseBuffer(builder:flatbuffers.Builder, offset:flatbuffers.Offset) {
|
||||
builder.finish(offset, undefined, true);
|
||||
}
|
||||
|
||||
static createMyGamesListResponse(builder:flatbuffers.Builder, itemsOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
MyGamesListResponse.startMyGamesListResponse(builder);
|
||||
MyGamesListResponse.addItems(builder, itemsOffset);
|
||||
return MyGamesListResponse.endMyGamesListResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): MyGamesListResponseT {
|
||||
return new MyGamesListResponseT(
|
||||
this.bb!.createObjList<GameSummary, GameSummaryT>(this.items.bind(this), this.itemsLength())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: MyGamesListResponseT): void {
|
||||
_o.items = this.bb!.createObjList<GameSummary, GameSummaryT>(this.items.bind(this), this.itemsLength());
|
||||
}
|
||||
}
|
||||
|
||||
export class MyGamesListResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public items: (GameSummaryT)[] = []
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const items = MyGamesListResponse.createItemsVector(builder, builder.createObjectOffsetList(this.items));
|
||||
|
||||
return MyGamesListResponse.createMyGamesListResponse(builder,
|
||||
items
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class MyInvitesListRequest implements flatbuffers.IUnpackableObject<MyInvitesListRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):MyInvitesListRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsMyInvitesListRequest(bb:flatbuffers.ByteBuffer, obj?:MyInvitesListRequest):MyInvitesListRequest {
|
||||
return (obj || new MyInvitesListRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsMyInvitesListRequest(bb:flatbuffers.ByteBuffer, obj?:MyInvitesListRequest):MyInvitesListRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new MyInvitesListRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static startMyInvitesListRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(0);
|
||||
}
|
||||
|
||||
static endMyInvitesListRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createMyInvitesListRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
MyInvitesListRequest.startMyInvitesListRequest(builder);
|
||||
return MyInvitesListRequest.endMyInvitesListRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): MyInvitesListRequestT {
|
||||
return new MyInvitesListRequestT();
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: MyInvitesListRequestT): void {}
|
||||
}
|
||||
|
||||
export class MyInvitesListRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
return MyInvitesListRequest.createMyInvitesListRequest(builder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { InviteSummary, InviteSummaryT } from './invite-summary.js';
|
||||
|
||||
|
||||
export class MyInvitesListResponse implements flatbuffers.IUnpackableObject<MyInvitesListResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):MyInvitesListResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsMyInvitesListResponse(bb:flatbuffers.ByteBuffer, obj?:MyInvitesListResponse):MyInvitesListResponse {
|
||||
return (obj || new MyInvitesListResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsMyInvitesListResponse(bb:flatbuffers.ByteBuffer, obj?:MyInvitesListResponse):MyInvitesListResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new MyInvitesListResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
items(index: number, obj?:InviteSummary):InviteSummary|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new InviteSummary()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null;
|
||||
}
|
||||
|
||||
itemsLength():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
static startMyInvitesListResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addItems(builder:flatbuffers.Builder, itemsOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, itemsOffset, 0);
|
||||
}
|
||||
|
||||
static createItemsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset {
|
||||
builder.startVector(4, data.length, 4);
|
||||
for (let i = data.length - 1; i >= 0; i--) {
|
||||
builder.addOffset(data[i]!);
|
||||
}
|
||||
return builder.endVector();
|
||||
}
|
||||
|
||||
static startItemsVector(builder:flatbuffers.Builder, numElems:number) {
|
||||
builder.startVector(4, numElems, 4);
|
||||
}
|
||||
|
||||
static endMyInvitesListResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createMyInvitesListResponse(builder:flatbuffers.Builder, itemsOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
MyInvitesListResponse.startMyInvitesListResponse(builder);
|
||||
MyInvitesListResponse.addItems(builder, itemsOffset);
|
||||
return MyInvitesListResponse.endMyInvitesListResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): MyInvitesListResponseT {
|
||||
return new MyInvitesListResponseT(
|
||||
this.bb!.createObjList<InviteSummary, InviteSummaryT>(this.items.bind(this), this.itemsLength())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: MyInvitesListResponseT): void {
|
||||
_o.items = this.bb!.createObjList<InviteSummary, InviteSummaryT>(this.items.bind(this), this.itemsLength());
|
||||
}
|
||||
}
|
||||
|
||||
export class MyInvitesListResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public items: (InviteSummaryT)[] = []
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const items = MyInvitesListResponse.createItemsVector(builder, builder.createObjectOffsetList(this.items));
|
||||
|
||||
return MyInvitesListResponse.createMyInvitesListResponse(builder,
|
||||
items
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class OpenEnrollmentRequest implements flatbuffers.IUnpackableObject<OpenEnrollmentRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):OpenEnrollmentRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsOpenEnrollmentRequest(bb:flatbuffers.ByteBuffer, obj?:OpenEnrollmentRequest):OpenEnrollmentRequest {
|
||||
return (obj || new OpenEnrollmentRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsOpenEnrollmentRequest(bb:flatbuffers.ByteBuffer, obj?:OpenEnrollmentRequest):OpenEnrollmentRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new OpenEnrollmentRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
gameId():string|null
|
||||
gameId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
gameId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
static startOpenEnrollmentRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addGameId(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, gameIdOffset, 0);
|
||||
}
|
||||
|
||||
static endOpenEnrollmentRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createOpenEnrollmentRequest(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
OpenEnrollmentRequest.startOpenEnrollmentRequest(builder);
|
||||
OpenEnrollmentRequest.addGameId(builder, gameIdOffset);
|
||||
return OpenEnrollmentRequest.endOpenEnrollmentRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): OpenEnrollmentRequestT {
|
||||
return new OpenEnrollmentRequestT(
|
||||
this.gameId()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: OpenEnrollmentRequestT): void {
|
||||
_o.gameId = this.gameId();
|
||||
}
|
||||
}
|
||||
|
||||
export class OpenEnrollmentRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public gameId: string|Uint8Array|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const gameId = (this.gameId !== null ? builder.createString(this.gameId!) : 0);
|
||||
|
||||
return OpenEnrollmentRequest.createOpenEnrollmentRequest(builder,
|
||||
gameId
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class OpenEnrollmentResponse implements flatbuffers.IUnpackableObject<OpenEnrollmentResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):OpenEnrollmentResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsOpenEnrollmentResponse(bb:flatbuffers.ByteBuffer, obj?:OpenEnrollmentResponse):OpenEnrollmentResponse {
|
||||
return (obj || new OpenEnrollmentResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsOpenEnrollmentResponse(bb:flatbuffers.ByteBuffer, obj?:OpenEnrollmentResponse):OpenEnrollmentResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new OpenEnrollmentResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
gameId():string|null
|
||||
gameId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
gameId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
status():string|null
|
||||
status(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
status(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
static startOpenEnrollmentResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(2);
|
||||
}
|
||||
|
||||
static addGameId(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, gameIdOffset, 0);
|
||||
}
|
||||
|
||||
static addStatus(builder:flatbuffers.Builder, statusOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, statusOffset, 0);
|
||||
}
|
||||
|
||||
static endOpenEnrollmentResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createOpenEnrollmentResponse(builder:flatbuffers.Builder, gameIdOffset:flatbuffers.Offset, statusOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
OpenEnrollmentResponse.startOpenEnrollmentResponse(builder);
|
||||
OpenEnrollmentResponse.addGameId(builder, gameIdOffset);
|
||||
OpenEnrollmentResponse.addStatus(builder, statusOffset);
|
||||
return OpenEnrollmentResponse.endOpenEnrollmentResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): OpenEnrollmentResponseT {
|
||||
return new OpenEnrollmentResponseT(
|
||||
this.gameId(),
|
||||
this.status()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: OpenEnrollmentResponseT): void {
|
||||
_o.gameId = this.gameId();
|
||||
_o.status = this.status();
|
||||
}
|
||||
}
|
||||
|
||||
export class OpenEnrollmentResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public gameId: string|Uint8Array|null = null,
|
||||
public status: string|Uint8Array|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const gameId = (this.gameId !== null ? builder.createString(this.gameId!) : 0);
|
||||
const status = (this.status !== null ? builder.createString(this.status!) : 0);
|
||||
|
||||
return OpenEnrollmentResponse.createOpenEnrollmentResponse(builder,
|
||||
gameId,
|
||||
status
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class PublicGamesListRequest implements flatbuffers.IUnpackableObject<PublicGamesListRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):PublicGamesListRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsPublicGamesListRequest(bb:flatbuffers.ByteBuffer, obj?:PublicGamesListRequest):PublicGamesListRequest {
|
||||
return (obj || new PublicGamesListRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsPublicGamesListRequest(bb:flatbuffers.ByteBuffer, obj?:PublicGamesListRequest):PublicGamesListRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new PublicGamesListRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
page():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
pageSize():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
static startPublicGamesListRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(2);
|
||||
}
|
||||
|
||||
static addPage(builder:flatbuffers.Builder, page:number) {
|
||||
builder.addFieldInt32(0, page, 0);
|
||||
}
|
||||
|
||||
static addPageSize(builder:flatbuffers.Builder, pageSize:number) {
|
||||
builder.addFieldInt32(1, pageSize, 0);
|
||||
}
|
||||
|
||||
static endPublicGamesListRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createPublicGamesListRequest(builder:flatbuffers.Builder, page:number, pageSize:number):flatbuffers.Offset {
|
||||
PublicGamesListRequest.startPublicGamesListRequest(builder);
|
||||
PublicGamesListRequest.addPage(builder, page);
|
||||
PublicGamesListRequest.addPageSize(builder, pageSize);
|
||||
return PublicGamesListRequest.endPublicGamesListRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): PublicGamesListRequestT {
|
||||
return new PublicGamesListRequestT(
|
||||
this.page(),
|
||||
this.pageSize()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: PublicGamesListRequestT): void {
|
||||
_o.page = this.page();
|
||||
_o.pageSize = this.pageSize();
|
||||
}
|
||||
}
|
||||
|
||||
export class PublicGamesListRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public page: number = 0,
|
||||
public pageSize: number = 0
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
return PublicGamesListRequest.createPublicGamesListRequest(builder,
|
||||
this.page,
|
||||
this.pageSize
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { GameSummary, GameSummaryT } from './game-summary.js';
|
||||
|
||||
|
||||
export class PublicGamesListResponse implements flatbuffers.IUnpackableObject<PublicGamesListResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):PublicGamesListResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsPublicGamesListResponse(bb:flatbuffers.ByteBuffer, obj?:PublicGamesListResponse):PublicGamesListResponse {
|
||||
return (obj || new PublicGamesListResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsPublicGamesListResponse(bb:flatbuffers.ByteBuffer, obj?:PublicGamesListResponse):PublicGamesListResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new PublicGamesListResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
items(index: number, obj?:GameSummary):GameSummary|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new GameSummary()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null;
|
||||
}
|
||||
|
||||
itemsLength():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
page():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
pageSize():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 8);
|
||||
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
total():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 10);
|
||||
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
static startPublicGamesListResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(4);
|
||||
}
|
||||
|
||||
static addItems(builder:flatbuffers.Builder, itemsOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, itemsOffset, 0);
|
||||
}
|
||||
|
||||
static createItemsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset {
|
||||
builder.startVector(4, data.length, 4);
|
||||
for (let i = data.length - 1; i >= 0; i--) {
|
||||
builder.addOffset(data[i]!);
|
||||
}
|
||||
return builder.endVector();
|
||||
}
|
||||
|
||||
static startItemsVector(builder:flatbuffers.Builder, numElems:number) {
|
||||
builder.startVector(4, numElems, 4);
|
||||
}
|
||||
|
||||
static addPage(builder:flatbuffers.Builder, page:number) {
|
||||
builder.addFieldInt32(1, page, 0);
|
||||
}
|
||||
|
||||
static addPageSize(builder:flatbuffers.Builder, pageSize:number) {
|
||||
builder.addFieldInt32(2, pageSize, 0);
|
||||
}
|
||||
|
||||
static addTotal(builder:flatbuffers.Builder, total:number) {
|
||||
builder.addFieldInt32(3, total, 0);
|
||||
}
|
||||
|
||||
static endPublicGamesListResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createPublicGamesListResponse(builder:flatbuffers.Builder, itemsOffset:flatbuffers.Offset, page:number, pageSize:number, total:number):flatbuffers.Offset {
|
||||
PublicGamesListResponse.startPublicGamesListResponse(builder);
|
||||
PublicGamesListResponse.addItems(builder, itemsOffset);
|
||||
PublicGamesListResponse.addPage(builder, page);
|
||||
PublicGamesListResponse.addPageSize(builder, pageSize);
|
||||
PublicGamesListResponse.addTotal(builder, total);
|
||||
return PublicGamesListResponse.endPublicGamesListResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): PublicGamesListResponseT {
|
||||
return new PublicGamesListResponseT(
|
||||
this.bb!.createObjList<GameSummary, GameSummaryT>(this.items.bind(this), this.itemsLength()),
|
||||
this.page(),
|
||||
this.pageSize(),
|
||||
this.total()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: PublicGamesListResponseT): void {
|
||||
_o.items = this.bb!.createObjList<GameSummary, GameSummaryT>(this.items.bind(this), this.itemsLength());
|
||||
_o.page = this.page();
|
||||
_o.pageSize = this.pageSize();
|
||||
_o.total = this.total();
|
||||
}
|
||||
}
|
||||
|
||||
export class PublicGamesListResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public items: (GameSummaryT)[] = [],
|
||||
public page: number = 0,
|
||||
public pageSize: number = 0,
|
||||
public total: number = 0
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const items = PublicGamesListResponse.createItemsVector(builder, builder.createObjectOffsetList(this.items));
|
||||
|
||||
return PublicGamesListResponse.createPublicGamesListResponse(builder,
|
||||
items,
|
||||
this.page,
|
||||
this.pageSize,
|
||||
this.total
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
export { AccountResponse, AccountResponseT } from './user/account-response.js';
|
||||
export { AccountView, AccountViewT } from './user/account-view.js';
|
||||
export { ActiveLimit, ActiveLimitT } from './user/active-limit.js';
|
||||
export { ActiveSanction, ActiveSanctionT } from './user/active-sanction.js';
|
||||
export { ActorRef, ActorRefT } from './user/actor-ref.js';
|
||||
export { DeviceSessionRevocationSummaryView, DeviceSessionRevocationSummaryViewT } from './user/device-session-revocation-summary-view.js';
|
||||
export { DeviceSessionView, DeviceSessionViewT } from './user/device-session-view.js';
|
||||
export { EntitlementSnapshot, EntitlementSnapshotT } from './user/entitlement-snapshot.js';
|
||||
export { ErrorBody, ErrorBodyT } from './user/error-body.js';
|
||||
export { ErrorResponse, ErrorResponseT } from './user/error-response.js';
|
||||
export { GetMyAccountRequest, GetMyAccountRequestT } from './user/get-my-account-request.js';
|
||||
export { ListMySessionsRequest, ListMySessionsRequestT } from './user/list-my-sessions-request.js';
|
||||
export { ListMySessionsResponse, ListMySessionsResponseT } from './user/list-my-sessions-response.js';
|
||||
export { RevokeAllMySessionsRequest, RevokeAllMySessionsRequestT } from './user/revoke-all-my-sessions-request.js';
|
||||
export { RevokeAllMySessionsResponse, RevokeAllMySessionsResponseT } from './user/revoke-all-my-sessions-response.js';
|
||||
export { RevokeMySessionRequest, RevokeMySessionRequestT } from './user/revoke-my-session-request.js';
|
||||
export { RevokeMySessionResponse, RevokeMySessionResponseT } from './user/revoke-my-session-response.js';
|
||||
export { UpdateMyProfileRequest, UpdateMyProfileRequestT } from './user/update-my-profile-request.js';
|
||||
export { UpdateMySettingsRequest, UpdateMySettingsRequestT } from './user/update-my-settings-request.js';
|
||||
@@ -0,0 +1,85 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { AccountView, AccountViewT } from './account-view.js';
|
||||
|
||||
|
||||
export class AccountResponse implements flatbuffers.IUnpackableObject<AccountResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):AccountResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsAccountResponse(bb:flatbuffers.ByteBuffer, obj?:AccountResponse):AccountResponse {
|
||||
return (obj || new AccountResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsAccountResponse(bb:flatbuffers.ByteBuffer, obj?:AccountResponse):AccountResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new AccountResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
account(obj?:AccountView):AccountView|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new AccountView()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
|
||||
}
|
||||
|
||||
static startAccountResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addAccount(builder:flatbuffers.Builder, accountOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, accountOffset, 0);
|
||||
}
|
||||
|
||||
static endAccountResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static finishAccountResponseBuffer(builder:flatbuffers.Builder, offset:flatbuffers.Offset) {
|
||||
builder.finish(offset);
|
||||
}
|
||||
|
||||
static finishSizePrefixedAccountResponseBuffer(builder:flatbuffers.Builder, offset:flatbuffers.Offset) {
|
||||
builder.finish(offset, undefined, true);
|
||||
}
|
||||
|
||||
static createAccountResponse(builder:flatbuffers.Builder, accountOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
AccountResponse.startAccountResponse(builder);
|
||||
AccountResponse.addAccount(builder, accountOffset);
|
||||
return AccountResponse.endAccountResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): AccountResponseT {
|
||||
return new AccountResponseT(
|
||||
(this.account() !== null ? this.account()!.unpack() : null)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: AccountResponseT): void {
|
||||
_o.account = (this.account() !== null ? this.account()!.unpack() : null);
|
||||
}
|
||||
}
|
||||
|
||||
export class AccountResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public account: AccountViewT|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const account = (this.account !== null ? this.account!.pack(builder) : 0);
|
||||
|
||||
return AccountResponse.createAccountResponse(builder,
|
||||
account
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { ActiveLimit, ActiveLimitT } from './active-limit.js';
|
||||
import { ActiveSanction, ActiveSanctionT } from './active-sanction.js';
|
||||
import { EntitlementSnapshot, EntitlementSnapshotT } from './entitlement-snapshot.js';
|
||||
|
||||
|
||||
export class AccountView implements flatbuffers.IUnpackableObject<AccountViewT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):AccountView {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsAccountView(bb:flatbuffers.ByteBuffer, obj?:AccountView):AccountView {
|
||||
return (obj || new AccountView()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsAccountView(bb:flatbuffers.ByteBuffer, obj?:AccountView):AccountView {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new AccountView()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
userId():string|null
|
||||
userId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
userId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
email():string|null
|
||||
email(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
email(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
userName():string|null
|
||||
userName(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
userName(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 8);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
displayName():string|null
|
||||
displayName(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
displayName(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 10);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
preferredLanguage():string|null
|
||||
preferredLanguage(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
preferredLanguage(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 12);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
timeZone():string|null
|
||||
timeZone(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
timeZone(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 14);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
declaredCountry():string|null
|
||||
declaredCountry(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
declaredCountry(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 16);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
entitlement(obj?:EntitlementSnapshot):EntitlementSnapshot|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 18);
|
||||
return offset ? (obj || new EntitlementSnapshot()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
|
||||
}
|
||||
|
||||
activeSanctions(index: number, obj?:ActiveSanction):ActiveSanction|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 20);
|
||||
return offset ? (obj || new ActiveSanction()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null;
|
||||
}
|
||||
|
||||
activeSanctionsLength():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 20);
|
||||
return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
activeLimits(index: number, obj?:ActiveLimit):ActiveLimit|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 22);
|
||||
return offset ? (obj || new ActiveLimit()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null;
|
||||
}
|
||||
|
||||
activeLimitsLength():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 22);
|
||||
return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
createdAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 24);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
updatedAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 26);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
static startAccountView(builder:flatbuffers.Builder) {
|
||||
builder.startObject(12);
|
||||
}
|
||||
|
||||
static addUserId(builder:flatbuffers.Builder, userIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, userIdOffset, 0);
|
||||
}
|
||||
|
||||
static addEmail(builder:flatbuffers.Builder, emailOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, emailOffset, 0);
|
||||
}
|
||||
|
||||
static addUserName(builder:flatbuffers.Builder, userNameOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(2, userNameOffset, 0);
|
||||
}
|
||||
|
||||
static addDisplayName(builder:flatbuffers.Builder, displayNameOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(3, displayNameOffset, 0);
|
||||
}
|
||||
|
||||
static addPreferredLanguage(builder:flatbuffers.Builder, preferredLanguageOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(4, preferredLanguageOffset, 0);
|
||||
}
|
||||
|
||||
static addTimeZone(builder:flatbuffers.Builder, timeZoneOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(5, timeZoneOffset, 0);
|
||||
}
|
||||
|
||||
static addDeclaredCountry(builder:flatbuffers.Builder, declaredCountryOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(6, declaredCountryOffset, 0);
|
||||
}
|
||||
|
||||
static addEntitlement(builder:flatbuffers.Builder, entitlementOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(7, entitlementOffset, 0);
|
||||
}
|
||||
|
||||
static addActiveSanctions(builder:flatbuffers.Builder, activeSanctionsOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(8, activeSanctionsOffset, 0);
|
||||
}
|
||||
|
||||
static createActiveSanctionsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset {
|
||||
builder.startVector(4, data.length, 4);
|
||||
for (let i = data.length - 1; i >= 0; i--) {
|
||||
builder.addOffset(data[i]!);
|
||||
}
|
||||
return builder.endVector();
|
||||
}
|
||||
|
||||
static startActiveSanctionsVector(builder:flatbuffers.Builder, numElems:number) {
|
||||
builder.startVector(4, numElems, 4);
|
||||
}
|
||||
|
||||
static addActiveLimits(builder:flatbuffers.Builder, activeLimitsOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(9, activeLimitsOffset, 0);
|
||||
}
|
||||
|
||||
static createActiveLimitsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset {
|
||||
builder.startVector(4, data.length, 4);
|
||||
for (let i = data.length - 1; i >= 0; i--) {
|
||||
builder.addOffset(data[i]!);
|
||||
}
|
||||
return builder.endVector();
|
||||
}
|
||||
|
||||
static startActiveLimitsVector(builder:flatbuffers.Builder, numElems:number) {
|
||||
builder.startVector(4, numElems, 4);
|
||||
}
|
||||
|
||||
static addCreatedAtMs(builder:flatbuffers.Builder, createdAtMs:bigint) {
|
||||
builder.addFieldInt64(10, createdAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static addUpdatedAtMs(builder:flatbuffers.Builder, updatedAtMs:bigint) {
|
||||
builder.addFieldInt64(11, updatedAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static endAccountView(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
unpack(): AccountViewT {
|
||||
return new AccountViewT(
|
||||
this.userId(),
|
||||
this.email(),
|
||||
this.userName(),
|
||||
this.displayName(),
|
||||
this.preferredLanguage(),
|
||||
this.timeZone(),
|
||||
this.declaredCountry(),
|
||||
(this.entitlement() !== null ? this.entitlement()!.unpack() : null),
|
||||
this.bb!.createObjList<ActiveSanction, ActiveSanctionT>(this.activeSanctions.bind(this), this.activeSanctionsLength()),
|
||||
this.bb!.createObjList<ActiveLimit, ActiveLimitT>(this.activeLimits.bind(this), this.activeLimitsLength()),
|
||||
this.createdAtMs(),
|
||||
this.updatedAtMs()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: AccountViewT): void {
|
||||
_o.userId = this.userId();
|
||||
_o.email = this.email();
|
||||
_o.userName = this.userName();
|
||||
_o.displayName = this.displayName();
|
||||
_o.preferredLanguage = this.preferredLanguage();
|
||||
_o.timeZone = this.timeZone();
|
||||
_o.declaredCountry = this.declaredCountry();
|
||||
_o.entitlement = (this.entitlement() !== null ? this.entitlement()!.unpack() : null);
|
||||
_o.activeSanctions = this.bb!.createObjList<ActiveSanction, ActiveSanctionT>(this.activeSanctions.bind(this), this.activeSanctionsLength());
|
||||
_o.activeLimits = this.bb!.createObjList<ActiveLimit, ActiveLimitT>(this.activeLimits.bind(this), this.activeLimitsLength());
|
||||
_o.createdAtMs = this.createdAtMs();
|
||||
_o.updatedAtMs = this.updatedAtMs();
|
||||
}
|
||||
}
|
||||
|
||||
export class AccountViewT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public userId: string|Uint8Array|null = null,
|
||||
public email: string|Uint8Array|null = null,
|
||||
public userName: string|Uint8Array|null = null,
|
||||
public displayName: string|Uint8Array|null = null,
|
||||
public preferredLanguage: string|Uint8Array|null = null,
|
||||
public timeZone: string|Uint8Array|null = null,
|
||||
public declaredCountry: string|Uint8Array|null = null,
|
||||
public entitlement: EntitlementSnapshotT|null = null,
|
||||
public activeSanctions: (ActiveSanctionT)[] = [],
|
||||
public activeLimits: (ActiveLimitT)[] = [],
|
||||
public createdAtMs: bigint = BigInt('0'),
|
||||
public updatedAtMs: bigint = BigInt('0')
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const userId = (this.userId !== null ? builder.createString(this.userId!) : 0);
|
||||
const email = (this.email !== null ? builder.createString(this.email!) : 0);
|
||||
const userName = (this.userName !== null ? builder.createString(this.userName!) : 0);
|
||||
const displayName = (this.displayName !== null ? builder.createString(this.displayName!) : 0);
|
||||
const preferredLanguage = (this.preferredLanguage !== null ? builder.createString(this.preferredLanguage!) : 0);
|
||||
const timeZone = (this.timeZone !== null ? builder.createString(this.timeZone!) : 0);
|
||||
const declaredCountry = (this.declaredCountry !== null ? builder.createString(this.declaredCountry!) : 0);
|
||||
const entitlement = (this.entitlement !== null ? this.entitlement!.pack(builder) : 0);
|
||||
const activeSanctions = AccountView.createActiveSanctionsVector(builder, builder.createObjectOffsetList(this.activeSanctions));
|
||||
const activeLimits = AccountView.createActiveLimitsVector(builder, builder.createObjectOffsetList(this.activeLimits));
|
||||
|
||||
AccountView.startAccountView(builder);
|
||||
AccountView.addUserId(builder, userId);
|
||||
AccountView.addEmail(builder, email);
|
||||
AccountView.addUserName(builder, userName);
|
||||
AccountView.addDisplayName(builder, displayName);
|
||||
AccountView.addPreferredLanguage(builder, preferredLanguage);
|
||||
AccountView.addTimeZone(builder, timeZone);
|
||||
AccountView.addDeclaredCountry(builder, declaredCountry);
|
||||
AccountView.addEntitlement(builder, entitlement);
|
||||
AccountView.addActiveSanctions(builder, activeSanctions);
|
||||
AccountView.addActiveLimits(builder, activeLimits);
|
||||
AccountView.addCreatedAtMs(builder, this.createdAtMs);
|
||||
AccountView.addUpdatedAtMs(builder, this.updatedAtMs);
|
||||
|
||||
return AccountView.endAccountView(builder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { ActorRef, ActorRefT } from './actor-ref.js';
|
||||
|
||||
|
||||
export class ActiveLimit implements flatbuffers.IUnpackableObject<ActiveLimitT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):ActiveLimit {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsActiveLimit(bb:flatbuffers.ByteBuffer, obj?:ActiveLimit):ActiveLimit {
|
||||
return (obj || new ActiveLimit()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsActiveLimit(bb:flatbuffers.ByteBuffer, obj?:ActiveLimit):ActiveLimit {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new ActiveLimit()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
limitCode():string|null
|
||||
limitCode(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
limitCode(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
value():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
reasonCode():string|null
|
||||
reasonCode(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
reasonCode(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 8);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
actor(obj?:ActorRef):ActorRef|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 10);
|
||||
return offset ? (obj || new ActorRef()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
|
||||
}
|
||||
|
||||
appliedAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 12);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
expiresAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 14);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
static startActiveLimit(builder:flatbuffers.Builder) {
|
||||
builder.startObject(6);
|
||||
}
|
||||
|
||||
static addLimitCode(builder:flatbuffers.Builder, limitCodeOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, limitCodeOffset, 0);
|
||||
}
|
||||
|
||||
static addValue(builder:flatbuffers.Builder, value:bigint) {
|
||||
builder.addFieldInt64(1, value, BigInt('0'));
|
||||
}
|
||||
|
||||
static addReasonCode(builder:flatbuffers.Builder, reasonCodeOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(2, reasonCodeOffset, 0);
|
||||
}
|
||||
|
||||
static addActor(builder:flatbuffers.Builder, actorOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(3, actorOffset, 0);
|
||||
}
|
||||
|
||||
static addAppliedAtMs(builder:flatbuffers.Builder, appliedAtMs:bigint) {
|
||||
builder.addFieldInt64(4, appliedAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static addExpiresAtMs(builder:flatbuffers.Builder, expiresAtMs:bigint) {
|
||||
builder.addFieldInt64(5, expiresAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static endActiveLimit(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
unpack(): ActiveLimitT {
|
||||
return new ActiveLimitT(
|
||||
this.limitCode(),
|
||||
this.value(),
|
||||
this.reasonCode(),
|
||||
(this.actor() !== null ? this.actor()!.unpack() : null),
|
||||
this.appliedAtMs(),
|
||||
this.expiresAtMs()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: ActiveLimitT): void {
|
||||
_o.limitCode = this.limitCode();
|
||||
_o.value = this.value();
|
||||
_o.reasonCode = this.reasonCode();
|
||||
_o.actor = (this.actor() !== null ? this.actor()!.unpack() : null);
|
||||
_o.appliedAtMs = this.appliedAtMs();
|
||||
_o.expiresAtMs = this.expiresAtMs();
|
||||
}
|
||||
}
|
||||
|
||||
export class ActiveLimitT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public limitCode: string|Uint8Array|null = null,
|
||||
public value: bigint = BigInt('0'),
|
||||
public reasonCode: string|Uint8Array|null = null,
|
||||
public actor: ActorRefT|null = null,
|
||||
public appliedAtMs: bigint = BigInt('0'),
|
||||
public expiresAtMs: bigint = BigInt('0')
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const limitCode = (this.limitCode !== null ? builder.createString(this.limitCode!) : 0);
|
||||
const reasonCode = (this.reasonCode !== null ? builder.createString(this.reasonCode!) : 0);
|
||||
const actor = (this.actor !== null ? this.actor!.pack(builder) : 0);
|
||||
|
||||
ActiveLimit.startActiveLimit(builder);
|
||||
ActiveLimit.addLimitCode(builder, limitCode);
|
||||
ActiveLimit.addValue(builder, this.value);
|
||||
ActiveLimit.addReasonCode(builder, reasonCode);
|
||||
ActiveLimit.addActor(builder, actor);
|
||||
ActiveLimit.addAppliedAtMs(builder, this.appliedAtMs);
|
||||
ActiveLimit.addExpiresAtMs(builder, this.expiresAtMs);
|
||||
|
||||
return ActiveLimit.endActiveLimit(builder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { ActorRef, ActorRefT } from './actor-ref.js';
|
||||
|
||||
|
||||
export class ActiveSanction implements flatbuffers.IUnpackableObject<ActiveSanctionT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):ActiveSanction {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsActiveSanction(bb:flatbuffers.ByteBuffer, obj?:ActiveSanction):ActiveSanction {
|
||||
return (obj || new ActiveSanction()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsActiveSanction(bb:flatbuffers.ByteBuffer, obj?:ActiveSanction):ActiveSanction {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new ActiveSanction()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
sanctionCode():string|null
|
||||
sanctionCode(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
sanctionCode(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
scope():string|null
|
||||
scope(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
scope(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
reasonCode():string|null
|
||||
reasonCode(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
reasonCode(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 8);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
actor(obj?:ActorRef):ActorRef|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 10);
|
||||
return offset ? (obj || new ActorRef()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
|
||||
}
|
||||
|
||||
appliedAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 12);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
expiresAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 14);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
static startActiveSanction(builder:flatbuffers.Builder) {
|
||||
builder.startObject(6);
|
||||
}
|
||||
|
||||
static addSanctionCode(builder:flatbuffers.Builder, sanctionCodeOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, sanctionCodeOffset, 0);
|
||||
}
|
||||
|
||||
static addScope(builder:flatbuffers.Builder, scopeOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, scopeOffset, 0);
|
||||
}
|
||||
|
||||
static addReasonCode(builder:flatbuffers.Builder, reasonCodeOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(2, reasonCodeOffset, 0);
|
||||
}
|
||||
|
||||
static addActor(builder:flatbuffers.Builder, actorOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(3, actorOffset, 0);
|
||||
}
|
||||
|
||||
static addAppliedAtMs(builder:flatbuffers.Builder, appliedAtMs:bigint) {
|
||||
builder.addFieldInt64(4, appliedAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static addExpiresAtMs(builder:flatbuffers.Builder, expiresAtMs:bigint) {
|
||||
builder.addFieldInt64(5, expiresAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static endActiveSanction(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
unpack(): ActiveSanctionT {
|
||||
return new ActiveSanctionT(
|
||||
this.sanctionCode(),
|
||||
this.scope(),
|
||||
this.reasonCode(),
|
||||
(this.actor() !== null ? this.actor()!.unpack() : null),
|
||||
this.appliedAtMs(),
|
||||
this.expiresAtMs()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: ActiveSanctionT): void {
|
||||
_o.sanctionCode = this.sanctionCode();
|
||||
_o.scope = this.scope();
|
||||
_o.reasonCode = this.reasonCode();
|
||||
_o.actor = (this.actor() !== null ? this.actor()!.unpack() : null);
|
||||
_o.appliedAtMs = this.appliedAtMs();
|
||||
_o.expiresAtMs = this.expiresAtMs();
|
||||
}
|
||||
}
|
||||
|
||||
export class ActiveSanctionT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public sanctionCode: string|Uint8Array|null = null,
|
||||
public scope: string|Uint8Array|null = null,
|
||||
public reasonCode: string|Uint8Array|null = null,
|
||||
public actor: ActorRefT|null = null,
|
||||
public appliedAtMs: bigint = BigInt('0'),
|
||||
public expiresAtMs: bigint = BigInt('0')
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const sanctionCode = (this.sanctionCode !== null ? builder.createString(this.sanctionCode!) : 0);
|
||||
const scope = (this.scope !== null ? builder.createString(this.scope!) : 0);
|
||||
const reasonCode = (this.reasonCode !== null ? builder.createString(this.reasonCode!) : 0);
|
||||
const actor = (this.actor !== null ? this.actor!.pack(builder) : 0);
|
||||
|
||||
ActiveSanction.startActiveSanction(builder);
|
||||
ActiveSanction.addSanctionCode(builder, sanctionCode);
|
||||
ActiveSanction.addScope(builder, scope);
|
||||
ActiveSanction.addReasonCode(builder, reasonCode);
|
||||
ActiveSanction.addActor(builder, actor);
|
||||
ActiveSanction.addAppliedAtMs(builder, this.appliedAtMs);
|
||||
ActiveSanction.addExpiresAtMs(builder, this.expiresAtMs);
|
||||
|
||||
return ActiveSanction.endActiveSanction(builder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class ActorRef implements flatbuffers.IUnpackableObject<ActorRefT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):ActorRef {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsActorRef(bb:flatbuffers.ByteBuffer, obj?:ActorRef):ActorRef {
|
||||
return (obj || new ActorRef()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsActorRef(bb:flatbuffers.ByteBuffer, obj?:ActorRef):ActorRef {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new ActorRef()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
type():string|null
|
||||
type(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
type(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
id():string|null
|
||||
id(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
id(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
static startActorRef(builder:flatbuffers.Builder) {
|
||||
builder.startObject(2);
|
||||
}
|
||||
|
||||
static addType(builder:flatbuffers.Builder, typeOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, typeOffset, 0);
|
||||
}
|
||||
|
||||
static addId(builder:flatbuffers.Builder, idOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, idOffset, 0);
|
||||
}
|
||||
|
||||
static endActorRef(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createActorRef(builder:flatbuffers.Builder, typeOffset:flatbuffers.Offset, idOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
ActorRef.startActorRef(builder);
|
||||
ActorRef.addType(builder, typeOffset);
|
||||
ActorRef.addId(builder, idOffset);
|
||||
return ActorRef.endActorRef(builder);
|
||||
}
|
||||
|
||||
unpack(): ActorRefT {
|
||||
return new ActorRefT(
|
||||
this.type(),
|
||||
this.id()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: ActorRefT): void {
|
||||
_o.type = this.type();
|
||||
_o.id = this.id();
|
||||
}
|
||||
}
|
||||
|
||||
export class ActorRefT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public type: string|Uint8Array|null = null,
|
||||
public id: string|Uint8Array|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const type = (this.type !== null ? builder.createString(this.type!) : 0);
|
||||
const id = (this.id !== null ? builder.createString(this.id!) : 0);
|
||||
|
||||
return ActorRef.createActorRef(builder,
|
||||
type,
|
||||
id
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class DeviceSessionRevocationSummaryView implements flatbuffers.IUnpackableObject<DeviceSessionRevocationSummaryViewT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):DeviceSessionRevocationSummaryView {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsDeviceSessionRevocationSummaryView(bb:flatbuffers.ByteBuffer, obj?:DeviceSessionRevocationSummaryView):DeviceSessionRevocationSummaryView {
|
||||
return (obj || new DeviceSessionRevocationSummaryView()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsDeviceSessionRevocationSummaryView(bb:flatbuffers.ByteBuffer, obj?:DeviceSessionRevocationSummaryView):DeviceSessionRevocationSummaryView {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new DeviceSessionRevocationSummaryView()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
userId():string|null
|
||||
userId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
userId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
revokedCount():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
static startDeviceSessionRevocationSummaryView(builder:flatbuffers.Builder) {
|
||||
builder.startObject(2);
|
||||
}
|
||||
|
||||
static addUserId(builder:flatbuffers.Builder, userIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, userIdOffset, 0);
|
||||
}
|
||||
|
||||
static addRevokedCount(builder:flatbuffers.Builder, revokedCount:number) {
|
||||
builder.addFieldInt32(1, revokedCount, 0);
|
||||
}
|
||||
|
||||
static endDeviceSessionRevocationSummaryView(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createDeviceSessionRevocationSummaryView(builder:flatbuffers.Builder, userIdOffset:flatbuffers.Offset, revokedCount:number):flatbuffers.Offset {
|
||||
DeviceSessionRevocationSummaryView.startDeviceSessionRevocationSummaryView(builder);
|
||||
DeviceSessionRevocationSummaryView.addUserId(builder, userIdOffset);
|
||||
DeviceSessionRevocationSummaryView.addRevokedCount(builder, revokedCount);
|
||||
return DeviceSessionRevocationSummaryView.endDeviceSessionRevocationSummaryView(builder);
|
||||
}
|
||||
|
||||
unpack(): DeviceSessionRevocationSummaryViewT {
|
||||
return new DeviceSessionRevocationSummaryViewT(
|
||||
this.userId(),
|
||||
this.revokedCount()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: DeviceSessionRevocationSummaryViewT): void {
|
||||
_o.userId = this.userId();
|
||||
_o.revokedCount = this.revokedCount();
|
||||
}
|
||||
}
|
||||
|
||||
export class DeviceSessionRevocationSummaryViewT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public userId: string|Uint8Array|null = null,
|
||||
public revokedCount: number = 0
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const userId = (this.userId !== null ? builder.createString(this.userId!) : 0);
|
||||
|
||||
return DeviceSessionRevocationSummaryView.createDeviceSessionRevocationSummaryView(builder,
|
||||
userId,
|
||||
this.revokedCount
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class DeviceSessionView implements flatbuffers.IUnpackableObject<DeviceSessionViewT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):DeviceSessionView {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsDeviceSessionView(bb:flatbuffers.ByteBuffer, obj?:DeviceSessionView):DeviceSessionView {
|
||||
return (obj || new DeviceSessionView()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsDeviceSessionView(bb:flatbuffers.ByteBuffer, obj?:DeviceSessionView):DeviceSessionView {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new DeviceSessionView()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
deviceSessionId():string|null
|
||||
deviceSessionId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
deviceSessionId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
userId():string|null
|
||||
userId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
userId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
status():string|null
|
||||
status(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
status(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 8);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
clientPublicKey():string|null
|
||||
clientPublicKey(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
clientPublicKey(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 10);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
createdAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 12);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
revokedAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 14);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
lastSeenAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 16);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
static startDeviceSessionView(builder:flatbuffers.Builder) {
|
||||
builder.startObject(7);
|
||||
}
|
||||
|
||||
static addDeviceSessionId(builder:flatbuffers.Builder, deviceSessionIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, deviceSessionIdOffset, 0);
|
||||
}
|
||||
|
||||
static addUserId(builder:flatbuffers.Builder, userIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, userIdOffset, 0);
|
||||
}
|
||||
|
||||
static addStatus(builder:flatbuffers.Builder, statusOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(2, statusOffset, 0);
|
||||
}
|
||||
|
||||
static addClientPublicKey(builder:flatbuffers.Builder, clientPublicKeyOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(3, clientPublicKeyOffset, 0);
|
||||
}
|
||||
|
||||
static addCreatedAtMs(builder:flatbuffers.Builder, createdAtMs:bigint) {
|
||||
builder.addFieldInt64(4, createdAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static addRevokedAtMs(builder:flatbuffers.Builder, revokedAtMs:bigint) {
|
||||
builder.addFieldInt64(5, revokedAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static addLastSeenAtMs(builder:flatbuffers.Builder, lastSeenAtMs:bigint) {
|
||||
builder.addFieldInt64(6, lastSeenAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static endDeviceSessionView(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createDeviceSessionView(builder:flatbuffers.Builder, deviceSessionIdOffset:flatbuffers.Offset, userIdOffset:flatbuffers.Offset, statusOffset:flatbuffers.Offset, clientPublicKeyOffset:flatbuffers.Offset, createdAtMs:bigint, revokedAtMs:bigint, lastSeenAtMs:bigint):flatbuffers.Offset {
|
||||
DeviceSessionView.startDeviceSessionView(builder);
|
||||
DeviceSessionView.addDeviceSessionId(builder, deviceSessionIdOffset);
|
||||
DeviceSessionView.addUserId(builder, userIdOffset);
|
||||
DeviceSessionView.addStatus(builder, statusOffset);
|
||||
DeviceSessionView.addClientPublicKey(builder, clientPublicKeyOffset);
|
||||
DeviceSessionView.addCreatedAtMs(builder, createdAtMs);
|
||||
DeviceSessionView.addRevokedAtMs(builder, revokedAtMs);
|
||||
DeviceSessionView.addLastSeenAtMs(builder, lastSeenAtMs);
|
||||
return DeviceSessionView.endDeviceSessionView(builder);
|
||||
}
|
||||
|
||||
unpack(): DeviceSessionViewT {
|
||||
return new DeviceSessionViewT(
|
||||
this.deviceSessionId(),
|
||||
this.userId(),
|
||||
this.status(),
|
||||
this.clientPublicKey(),
|
||||
this.createdAtMs(),
|
||||
this.revokedAtMs(),
|
||||
this.lastSeenAtMs()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: DeviceSessionViewT): void {
|
||||
_o.deviceSessionId = this.deviceSessionId();
|
||||
_o.userId = this.userId();
|
||||
_o.status = this.status();
|
||||
_o.clientPublicKey = this.clientPublicKey();
|
||||
_o.createdAtMs = this.createdAtMs();
|
||||
_o.revokedAtMs = this.revokedAtMs();
|
||||
_o.lastSeenAtMs = this.lastSeenAtMs();
|
||||
}
|
||||
}
|
||||
|
||||
export class DeviceSessionViewT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public deviceSessionId: string|Uint8Array|null = null,
|
||||
public userId: string|Uint8Array|null = null,
|
||||
public status: string|Uint8Array|null = null,
|
||||
public clientPublicKey: string|Uint8Array|null = null,
|
||||
public createdAtMs: bigint = BigInt('0'),
|
||||
public revokedAtMs: bigint = BigInt('0'),
|
||||
public lastSeenAtMs: bigint = BigInt('0')
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const deviceSessionId = (this.deviceSessionId !== null ? builder.createString(this.deviceSessionId!) : 0);
|
||||
const userId = (this.userId !== null ? builder.createString(this.userId!) : 0);
|
||||
const status = (this.status !== null ? builder.createString(this.status!) : 0);
|
||||
const clientPublicKey = (this.clientPublicKey !== null ? builder.createString(this.clientPublicKey!) : 0);
|
||||
|
||||
return DeviceSessionView.createDeviceSessionView(builder,
|
||||
deviceSessionId,
|
||||
userId,
|
||||
status,
|
||||
clientPublicKey,
|
||||
this.createdAtMs,
|
||||
this.revokedAtMs,
|
||||
this.lastSeenAtMs
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { ActorRef, ActorRefT } from './actor-ref.js';
|
||||
|
||||
|
||||
export class EntitlementSnapshot implements flatbuffers.IUnpackableObject<EntitlementSnapshotT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):EntitlementSnapshot {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsEntitlementSnapshot(bb:flatbuffers.ByteBuffer, obj?:EntitlementSnapshot):EntitlementSnapshot {
|
||||
return (obj || new EntitlementSnapshot()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsEntitlementSnapshot(bb:flatbuffers.ByteBuffer, obj?:EntitlementSnapshot):EntitlementSnapshot {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new EntitlementSnapshot()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
planCode():string|null
|
||||
planCode(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
planCode(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
isPaid():boolean {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? !!this.bb!.readInt8(this.bb_pos + offset) : false;
|
||||
}
|
||||
|
||||
source():string|null
|
||||
source(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
source(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 8);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
actor(obj?:ActorRef):ActorRef|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 10);
|
||||
return offset ? (obj || new ActorRef()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
|
||||
}
|
||||
|
||||
reasonCode():string|null
|
||||
reasonCode(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
reasonCode(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 12);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
startsAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 14);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
endsAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 16);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
updatedAtMs():bigint {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 18);
|
||||
return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
|
||||
}
|
||||
|
||||
static startEntitlementSnapshot(builder:flatbuffers.Builder) {
|
||||
builder.startObject(8);
|
||||
}
|
||||
|
||||
static addPlanCode(builder:flatbuffers.Builder, planCodeOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, planCodeOffset, 0);
|
||||
}
|
||||
|
||||
static addIsPaid(builder:flatbuffers.Builder, isPaid:boolean) {
|
||||
builder.addFieldInt8(1, +isPaid, +false);
|
||||
}
|
||||
|
||||
static addSource(builder:flatbuffers.Builder, sourceOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(2, sourceOffset, 0);
|
||||
}
|
||||
|
||||
static addActor(builder:flatbuffers.Builder, actorOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(3, actorOffset, 0);
|
||||
}
|
||||
|
||||
static addReasonCode(builder:flatbuffers.Builder, reasonCodeOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(4, reasonCodeOffset, 0);
|
||||
}
|
||||
|
||||
static addStartsAtMs(builder:flatbuffers.Builder, startsAtMs:bigint) {
|
||||
builder.addFieldInt64(5, startsAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static addEndsAtMs(builder:flatbuffers.Builder, endsAtMs:bigint) {
|
||||
builder.addFieldInt64(6, endsAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static addUpdatedAtMs(builder:flatbuffers.Builder, updatedAtMs:bigint) {
|
||||
builder.addFieldInt64(7, updatedAtMs, BigInt('0'));
|
||||
}
|
||||
|
||||
static endEntitlementSnapshot(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
unpack(): EntitlementSnapshotT {
|
||||
return new EntitlementSnapshotT(
|
||||
this.planCode(),
|
||||
this.isPaid(),
|
||||
this.source(),
|
||||
(this.actor() !== null ? this.actor()!.unpack() : null),
|
||||
this.reasonCode(),
|
||||
this.startsAtMs(),
|
||||
this.endsAtMs(),
|
||||
this.updatedAtMs()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: EntitlementSnapshotT): void {
|
||||
_o.planCode = this.planCode();
|
||||
_o.isPaid = this.isPaid();
|
||||
_o.source = this.source();
|
||||
_o.actor = (this.actor() !== null ? this.actor()!.unpack() : null);
|
||||
_o.reasonCode = this.reasonCode();
|
||||
_o.startsAtMs = this.startsAtMs();
|
||||
_o.endsAtMs = this.endsAtMs();
|
||||
_o.updatedAtMs = this.updatedAtMs();
|
||||
}
|
||||
}
|
||||
|
||||
export class EntitlementSnapshotT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public planCode: string|Uint8Array|null = null,
|
||||
public isPaid: boolean = false,
|
||||
public source: string|Uint8Array|null = null,
|
||||
public actor: ActorRefT|null = null,
|
||||
public reasonCode: string|Uint8Array|null = null,
|
||||
public startsAtMs: bigint = BigInt('0'),
|
||||
public endsAtMs: bigint = BigInt('0'),
|
||||
public updatedAtMs: bigint = BigInt('0')
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const planCode = (this.planCode !== null ? builder.createString(this.planCode!) : 0);
|
||||
const source = (this.source !== null ? builder.createString(this.source!) : 0);
|
||||
const actor = (this.actor !== null ? this.actor!.pack(builder) : 0);
|
||||
const reasonCode = (this.reasonCode !== null ? builder.createString(this.reasonCode!) : 0);
|
||||
|
||||
EntitlementSnapshot.startEntitlementSnapshot(builder);
|
||||
EntitlementSnapshot.addPlanCode(builder, planCode);
|
||||
EntitlementSnapshot.addIsPaid(builder, this.isPaid);
|
||||
EntitlementSnapshot.addSource(builder, source);
|
||||
EntitlementSnapshot.addActor(builder, actor);
|
||||
EntitlementSnapshot.addReasonCode(builder, reasonCode);
|
||||
EntitlementSnapshot.addStartsAtMs(builder, this.startsAtMs);
|
||||
EntitlementSnapshot.addEndsAtMs(builder, this.endsAtMs);
|
||||
EntitlementSnapshot.addUpdatedAtMs(builder, this.updatedAtMs);
|
||||
|
||||
return EntitlementSnapshot.endEntitlementSnapshot(builder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class ErrorBody implements flatbuffers.IUnpackableObject<ErrorBodyT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):ErrorBody {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsErrorBody(bb:flatbuffers.ByteBuffer, obj?:ErrorBody):ErrorBody {
|
||||
return (obj || new ErrorBody()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsErrorBody(bb:flatbuffers.ByteBuffer, obj?:ErrorBody):ErrorBody {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new ErrorBody()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
code():string|null
|
||||
code(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
code(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
message():string|null
|
||||
message(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
message(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
static startErrorBody(builder:flatbuffers.Builder) {
|
||||
builder.startObject(2);
|
||||
}
|
||||
|
||||
static addCode(builder:flatbuffers.Builder, codeOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, codeOffset, 0);
|
||||
}
|
||||
|
||||
static addMessage(builder:flatbuffers.Builder, messageOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, messageOffset, 0);
|
||||
}
|
||||
|
||||
static endErrorBody(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createErrorBody(builder:flatbuffers.Builder, codeOffset:flatbuffers.Offset, messageOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
ErrorBody.startErrorBody(builder);
|
||||
ErrorBody.addCode(builder, codeOffset);
|
||||
ErrorBody.addMessage(builder, messageOffset);
|
||||
return ErrorBody.endErrorBody(builder);
|
||||
}
|
||||
|
||||
unpack(): ErrorBodyT {
|
||||
return new ErrorBodyT(
|
||||
this.code(),
|
||||
this.message()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: ErrorBodyT): void {
|
||||
_o.code = this.code();
|
||||
_o.message = this.message();
|
||||
}
|
||||
}
|
||||
|
||||
export class ErrorBodyT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public code: string|Uint8Array|null = null,
|
||||
public message: string|Uint8Array|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const code = (this.code !== null ? builder.createString(this.code!) : 0);
|
||||
const message = (this.message !== null ? builder.createString(this.message!) : 0);
|
||||
|
||||
return ErrorBody.createErrorBody(builder,
|
||||
code,
|
||||
message
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { ErrorBody, ErrorBodyT } from './error-body.js';
|
||||
|
||||
|
||||
export class ErrorResponse implements flatbuffers.IUnpackableObject<ErrorResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):ErrorResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsErrorResponse(bb:flatbuffers.ByteBuffer, obj?:ErrorResponse):ErrorResponse {
|
||||
return (obj || new ErrorResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsErrorResponse(bb:flatbuffers.ByteBuffer, obj?:ErrorResponse):ErrorResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new ErrorResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
error(obj?:ErrorBody):ErrorBody|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new ErrorBody()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
|
||||
}
|
||||
|
||||
static startErrorResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addError(builder:flatbuffers.Builder, errorOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, errorOffset, 0);
|
||||
}
|
||||
|
||||
static endErrorResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createErrorResponse(builder:flatbuffers.Builder, errorOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
ErrorResponse.startErrorResponse(builder);
|
||||
ErrorResponse.addError(builder, errorOffset);
|
||||
return ErrorResponse.endErrorResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): ErrorResponseT {
|
||||
return new ErrorResponseT(
|
||||
(this.error() !== null ? this.error()!.unpack() : null)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: ErrorResponseT): void {
|
||||
_o.error = (this.error() !== null ? this.error()!.unpack() : null);
|
||||
}
|
||||
}
|
||||
|
||||
export class ErrorResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public error: ErrorBodyT|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const error = (this.error !== null ? this.error!.pack(builder) : 0);
|
||||
|
||||
return ErrorResponse.createErrorResponse(builder,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class GetMyAccountRequest implements flatbuffers.IUnpackableObject<GetMyAccountRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):GetMyAccountRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsGetMyAccountRequest(bb:flatbuffers.ByteBuffer, obj?:GetMyAccountRequest):GetMyAccountRequest {
|
||||
return (obj || new GetMyAccountRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsGetMyAccountRequest(bb:flatbuffers.ByteBuffer, obj?:GetMyAccountRequest):GetMyAccountRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new GetMyAccountRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static startGetMyAccountRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(0);
|
||||
}
|
||||
|
||||
static endGetMyAccountRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createGetMyAccountRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
GetMyAccountRequest.startGetMyAccountRequest(builder);
|
||||
return GetMyAccountRequest.endGetMyAccountRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): GetMyAccountRequestT {
|
||||
return new GetMyAccountRequestT();
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: GetMyAccountRequestT): void {}
|
||||
}
|
||||
|
||||
export class GetMyAccountRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
return GetMyAccountRequest.createGetMyAccountRequest(builder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class ListMySessionsRequest implements flatbuffers.IUnpackableObject<ListMySessionsRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):ListMySessionsRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsListMySessionsRequest(bb:flatbuffers.ByteBuffer, obj?:ListMySessionsRequest):ListMySessionsRequest {
|
||||
return (obj || new ListMySessionsRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsListMySessionsRequest(bb:flatbuffers.ByteBuffer, obj?:ListMySessionsRequest):ListMySessionsRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new ListMySessionsRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static startListMySessionsRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(0);
|
||||
}
|
||||
|
||||
static endListMySessionsRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createListMySessionsRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
ListMySessionsRequest.startListMySessionsRequest(builder);
|
||||
return ListMySessionsRequest.endListMySessionsRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): ListMySessionsRequestT {
|
||||
return new ListMySessionsRequestT();
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: ListMySessionsRequestT): void {}
|
||||
}
|
||||
|
||||
export class ListMySessionsRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
return ListMySessionsRequest.createListMySessionsRequest(builder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { DeviceSessionView, DeviceSessionViewT } from './device-session-view.js';
|
||||
|
||||
|
||||
export class ListMySessionsResponse implements flatbuffers.IUnpackableObject<ListMySessionsResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):ListMySessionsResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsListMySessionsResponse(bb:flatbuffers.ByteBuffer, obj?:ListMySessionsResponse):ListMySessionsResponse {
|
||||
return (obj || new ListMySessionsResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsListMySessionsResponse(bb:flatbuffers.ByteBuffer, obj?:ListMySessionsResponse):ListMySessionsResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new ListMySessionsResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
items(index: number, obj?:DeviceSessionView):DeviceSessionView|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new DeviceSessionView()).__init(this.bb!.__indirect(this.bb!.__vector(this.bb_pos + offset) + index * 4), this.bb!) : null;
|
||||
}
|
||||
|
||||
itemsLength():number {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0;
|
||||
}
|
||||
|
||||
static startListMySessionsResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addItems(builder:flatbuffers.Builder, itemsOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, itemsOffset, 0);
|
||||
}
|
||||
|
||||
static createItemsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset {
|
||||
builder.startVector(4, data.length, 4);
|
||||
for (let i = data.length - 1; i >= 0; i--) {
|
||||
builder.addOffset(data[i]!);
|
||||
}
|
||||
return builder.endVector();
|
||||
}
|
||||
|
||||
static startItemsVector(builder:flatbuffers.Builder, numElems:number) {
|
||||
builder.startVector(4, numElems, 4);
|
||||
}
|
||||
|
||||
static endListMySessionsResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createListMySessionsResponse(builder:flatbuffers.Builder, itemsOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
ListMySessionsResponse.startListMySessionsResponse(builder);
|
||||
ListMySessionsResponse.addItems(builder, itemsOffset);
|
||||
return ListMySessionsResponse.endListMySessionsResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): ListMySessionsResponseT {
|
||||
return new ListMySessionsResponseT(
|
||||
this.bb!.createObjList<DeviceSessionView, DeviceSessionViewT>(this.items.bind(this), this.itemsLength())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: ListMySessionsResponseT): void {
|
||||
_o.items = this.bb!.createObjList<DeviceSessionView, DeviceSessionViewT>(this.items.bind(this), this.itemsLength());
|
||||
}
|
||||
}
|
||||
|
||||
export class ListMySessionsResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public items: (DeviceSessionViewT)[] = []
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const items = ListMySessionsResponse.createItemsVector(builder, builder.createObjectOffsetList(this.items));
|
||||
|
||||
return ListMySessionsResponse.createListMySessionsResponse(builder,
|
||||
items
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class RevokeAllMySessionsRequest implements flatbuffers.IUnpackableObject<RevokeAllMySessionsRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):RevokeAllMySessionsRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsRevokeAllMySessionsRequest(bb:flatbuffers.ByteBuffer, obj?:RevokeAllMySessionsRequest):RevokeAllMySessionsRequest {
|
||||
return (obj || new RevokeAllMySessionsRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsRevokeAllMySessionsRequest(bb:flatbuffers.ByteBuffer, obj?:RevokeAllMySessionsRequest):RevokeAllMySessionsRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new RevokeAllMySessionsRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static startRevokeAllMySessionsRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(0);
|
||||
}
|
||||
|
||||
static endRevokeAllMySessionsRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createRevokeAllMySessionsRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
RevokeAllMySessionsRequest.startRevokeAllMySessionsRequest(builder);
|
||||
return RevokeAllMySessionsRequest.endRevokeAllMySessionsRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): RevokeAllMySessionsRequestT {
|
||||
return new RevokeAllMySessionsRequestT();
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: RevokeAllMySessionsRequestT): void {}
|
||||
}
|
||||
|
||||
export class RevokeAllMySessionsRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
return RevokeAllMySessionsRequest.createRevokeAllMySessionsRequest(builder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { DeviceSessionRevocationSummaryView, DeviceSessionRevocationSummaryViewT } from './device-session-revocation-summary-view.js';
|
||||
|
||||
|
||||
export class RevokeAllMySessionsResponse implements flatbuffers.IUnpackableObject<RevokeAllMySessionsResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):RevokeAllMySessionsResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsRevokeAllMySessionsResponse(bb:flatbuffers.ByteBuffer, obj?:RevokeAllMySessionsResponse):RevokeAllMySessionsResponse {
|
||||
return (obj || new RevokeAllMySessionsResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsRevokeAllMySessionsResponse(bb:flatbuffers.ByteBuffer, obj?:RevokeAllMySessionsResponse):RevokeAllMySessionsResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new RevokeAllMySessionsResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
summary(obj?:DeviceSessionRevocationSummaryView):DeviceSessionRevocationSummaryView|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new DeviceSessionRevocationSummaryView()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
|
||||
}
|
||||
|
||||
static startRevokeAllMySessionsResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addSummary(builder:flatbuffers.Builder, summaryOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, summaryOffset, 0);
|
||||
}
|
||||
|
||||
static endRevokeAllMySessionsResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createRevokeAllMySessionsResponse(builder:flatbuffers.Builder, summaryOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
RevokeAllMySessionsResponse.startRevokeAllMySessionsResponse(builder);
|
||||
RevokeAllMySessionsResponse.addSummary(builder, summaryOffset);
|
||||
return RevokeAllMySessionsResponse.endRevokeAllMySessionsResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): RevokeAllMySessionsResponseT {
|
||||
return new RevokeAllMySessionsResponseT(
|
||||
(this.summary() !== null ? this.summary()!.unpack() : null)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: RevokeAllMySessionsResponseT): void {
|
||||
_o.summary = (this.summary() !== null ? this.summary()!.unpack() : null);
|
||||
}
|
||||
}
|
||||
|
||||
export class RevokeAllMySessionsResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public summary: DeviceSessionRevocationSummaryViewT|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const summary = (this.summary !== null ? this.summary!.pack(builder) : 0);
|
||||
|
||||
return RevokeAllMySessionsResponse.createRevokeAllMySessionsResponse(builder,
|
||||
summary
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class RevokeMySessionRequest implements flatbuffers.IUnpackableObject<RevokeMySessionRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):RevokeMySessionRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsRevokeMySessionRequest(bb:flatbuffers.ByteBuffer, obj?:RevokeMySessionRequest):RevokeMySessionRequest {
|
||||
return (obj || new RevokeMySessionRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsRevokeMySessionRequest(bb:flatbuffers.ByteBuffer, obj?:RevokeMySessionRequest):RevokeMySessionRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new RevokeMySessionRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
deviceSessionId():string|null
|
||||
deviceSessionId(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
deviceSessionId(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
static startRevokeMySessionRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addDeviceSessionId(builder:flatbuffers.Builder, deviceSessionIdOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, deviceSessionIdOffset, 0);
|
||||
}
|
||||
|
||||
static endRevokeMySessionRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createRevokeMySessionRequest(builder:flatbuffers.Builder, deviceSessionIdOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
RevokeMySessionRequest.startRevokeMySessionRequest(builder);
|
||||
RevokeMySessionRequest.addDeviceSessionId(builder, deviceSessionIdOffset);
|
||||
return RevokeMySessionRequest.endRevokeMySessionRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): RevokeMySessionRequestT {
|
||||
return new RevokeMySessionRequestT(
|
||||
this.deviceSessionId()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: RevokeMySessionRequestT): void {
|
||||
_o.deviceSessionId = this.deviceSessionId();
|
||||
}
|
||||
}
|
||||
|
||||
export class RevokeMySessionRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public deviceSessionId: string|Uint8Array|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const deviceSessionId = (this.deviceSessionId !== null ? builder.createString(this.deviceSessionId!) : 0);
|
||||
|
||||
return RevokeMySessionRequest.createRevokeMySessionRequest(builder,
|
||||
deviceSessionId
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
import { DeviceSessionView, DeviceSessionViewT } from './device-session-view.js';
|
||||
|
||||
|
||||
export class RevokeMySessionResponse implements flatbuffers.IUnpackableObject<RevokeMySessionResponseT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):RevokeMySessionResponse {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsRevokeMySessionResponse(bb:flatbuffers.ByteBuffer, obj?:RevokeMySessionResponse):RevokeMySessionResponse {
|
||||
return (obj || new RevokeMySessionResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsRevokeMySessionResponse(bb:flatbuffers.ByteBuffer, obj?:RevokeMySessionResponse):RevokeMySessionResponse {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new RevokeMySessionResponse()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
session(obj?:DeviceSessionView):DeviceSessionView|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? (obj || new DeviceSessionView()).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null;
|
||||
}
|
||||
|
||||
static startRevokeMySessionResponse(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addSession(builder:flatbuffers.Builder, sessionOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, sessionOffset, 0);
|
||||
}
|
||||
|
||||
static endRevokeMySessionResponse(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createRevokeMySessionResponse(builder:flatbuffers.Builder, sessionOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
RevokeMySessionResponse.startRevokeMySessionResponse(builder);
|
||||
RevokeMySessionResponse.addSession(builder, sessionOffset);
|
||||
return RevokeMySessionResponse.endRevokeMySessionResponse(builder);
|
||||
}
|
||||
|
||||
unpack(): RevokeMySessionResponseT {
|
||||
return new RevokeMySessionResponseT(
|
||||
(this.session() !== null ? this.session()!.unpack() : null)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: RevokeMySessionResponseT): void {
|
||||
_o.session = (this.session() !== null ? this.session()!.unpack() : null);
|
||||
}
|
||||
}
|
||||
|
||||
export class RevokeMySessionResponseT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public session: DeviceSessionViewT|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const session = (this.session !== null ? this.session!.pack(builder) : 0);
|
||||
|
||||
return RevokeMySessionResponse.createRevokeMySessionResponse(builder,
|
||||
session
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class UpdateMyProfileRequest implements flatbuffers.IUnpackableObject<UpdateMyProfileRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):UpdateMyProfileRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsUpdateMyProfileRequest(bb:flatbuffers.ByteBuffer, obj?:UpdateMyProfileRequest):UpdateMyProfileRequest {
|
||||
return (obj || new UpdateMyProfileRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsUpdateMyProfileRequest(bb:flatbuffers.ByteBuffer, obj?:UpdateMyProfileRequest):UpdateMyProfileRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new UpdateMyProfileRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
displayName():string|null
|
||||
displayName(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
displayName(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
static startUpdateMyProfileRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(1);
|
||||
}
|
||||
|
||||
static addDisplayName(builder:flatbuffers.Builder, displayNameOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, displayNameOffset, 0);
|
||||
}
|
||||
|
||||
static endUpdateMyProfileRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createUpdateMyProfileRequest(builder:flatbuffers.Builder, displayNameOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
UpdateMyProfileRequest.startUpdateMyProfileRequest(builder);
|
||||
UpdateMyProfileRequest.addDisplayName(builder, displayNameOffset);
|
||||
return UpdateMyProfileRequest.endUpdateMyProfileRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): UpdateMyProfileRequestT {
|
||||
return new UpdateMyProfileRequestT(
|
||||
this.displayName()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: UpdateMyProfileRequestT): void {
|
||||
_o.displayName = this.displayName();
|
||||
}
|
||||
}
|
||||
|
||||
export class UpdateMyProfileRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public displayName: string|Uint8Array|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const displayName = (this.displayName !== null ? builder.createString(this.displayName!) : 0);
|
||||
|
||||
return UpdateMyProfileRequest.createUpdateMyProfileRequest(builder,
|
||||
displayName
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
|
||||
|
||||
import * as flatbuffers from 'flatbuffers';
|
||||
|
||||
|
||||
|
||||
export class UpdateMySettingsRequest implements flatbuffers.IUnpackableObject<UpdateMySettingsRequestT> {
|
||||
bb: flatbuffers.ByteBuffer|null = null;
|
||||
bb_pos = 0;
|
||||
__init(i:number, bb:flatbuffers.ByteBuffer):UpdateMySettingsRequest {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
}
|
||||
|
||||
static getRootAsUpdateMySettingsRequest(bb:flatbuffers.ByteBuffer, obj?:UpdateMySettingsRequest):UpdateMySettingsRequest {
|
||||
return (obj || new UpdateMySettingsRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
static getSizePrefixedRootAsUpdateMySettingsRequest(bb:flatbuffers.ByteBuffer, obj?:UpdateMySettingsRequest):UpdateMySettingsRequest {
|
||||
bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
|
||||
return (obj || new UpdateMySettingsRequest()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
|
||||
}
|
||||
|
||||
preferredLanguage():string|null
|
||||
preferredLanguage(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
preferredLanguage(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 4);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
timeZone():string|null
|
||||
timeZone(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
|
||||
timeZone(optionalEncoding?:any):string|Uint8Array|null {
|
||||
const offset = this.bb!.__offset(this.bb_pos, 6);
|
||||
return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
|
||||
}
|
||||
|
||||
static startUpdateMySettingsRequest(builder:flatbuffers.Builder) {
|
||||
builder.startObject(2);
|
||||
}
|
||||
|
||||
static addPreferredLanguage(builder:flatbuffers.Builder, preferredLanguageOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(0, preferredLanguageOffset, 0);
|
||||
}
|
||||
|
||||
static addTimeZone(builder:flatbuffers.Builder, timeZoneOffset:flatbuffers.Offset) {
|
||||
builder.addFieldOffset(1, timeZoneOffset, 0);
|
||||
}
|
||||
|
||||
static endUpdateMySettingsRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
|
||||
const offset = builder.endObject();
|
||||
return offset;
|
||||
}
|
||||
|
||||
static createUpdateMySettingsRequest(builder:flatbuffers.Builder, preferredLanguageOffset:flatbuffers.Offset, timeZoneOffset:flatbuffers.Offset):flatbuffers.Offset {
|
||||
UpdateMySettingsRequest.startUpdateMySettingsRequest(builder);
|
||||
UpdateMySettingsRequest.addPreferredLanguage(builder, preferredLanguageOffset);
|
||||
UpdateMySettingsRequest.addTimeZone(builder, timeZoneOffset);
|
||||
return UpdateMySettingsRequest.endUpdateMySettingsRequest(builder);
|
||||
}
|
||||
|
||||
unpack(): UpdateMySettingsRequestT {
|
||||
return new UpdateMySettingsRequestT(
|
||||
this.preferredLanguage(),
|
||||
this.timeZone()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
unpackTo(_o: UpdateMySettingsRequestT): void {
|
||||
_o.preferredLanguage = this.preferredLanguage();
|
||||
_o.timeZone = this.timeZone();
|
||||
}
|
||||
}
|
||||
|
||||
export class UpdateMySettingsRequestT implements flatbuffers.IGeneratedObject {
|
||||
constructor(
|
||||
public preferredLanguage: string|Uint8Array|null = null,
|
||||
public timeZone: string|Uint8Array|null = null
|
||||
){}
|
||||
|
||||
|
||||
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
|
||||
const preferredLanguage = (this.preferredLanguage !== null ? builder.createString(this.preferredLanguage!) : 0);
|
||||
const timeZone = (this.timeZone !== null ? builder.createString(this.timeZone!) : 0);
|
||||
|
||||
return UpdateMySettingsRequest.createUpdateMySettingsRequest(builder,
|
||||
preferredLanguage,
|
||||
timeZone
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,206 @@
|
||||
<script lang="ts">
|
||||
import { goto } from "$app/navigation";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
import { createEdgeGatewayClient } from "../../api/connect";
|
||||
import { GalaxyClient } from "../../api/galaxy-client";
|
||||
import {
|
||||
LobbyError,
|
||||
listMyApplications,
|
||||
listMyGames,
|
||||
listMyInvites,
|
||||
listPublicGames,
|
||||
redeemInvite,
|
||||
declineInvite,
|
||||
submitApplication,
|
||||
type ApplicationSummary,
|
||||
type GameSummary,
|
||||
type InviteSummary,
|
||||
} from "../../api/lobby";
|
||||
import { ByteBuffer } from "flatbuffers";
|
||||
import { AccountResponse } from "../../proto/galaxy/fbs/user";
|
||||
import { GATEWAY_BASE_URL, GATEWAY_RESPONSE_PUBLIC_KEY } from "$lib/env";
|
||||
import { i18n } from "$lib/i18n/index.svelte";
|
||||
import { i18n, type TranslationKey } from "$lib/i18n/index.svelte";
|
||||
import { loadCore } from "../../platform/core/index";
|
||||
import { session } from "$lib/session-store.svelte";
|
||||
import { Builder } from "flatbuffers";
|
||||
import { GetMyAccountRequest } from "../../proto/galaxy/fbs/user";
|
||||
|
||||
let displayName: string | null = $state(null);
|
||||
let accountError: string | null = $state(null);
|
||||
let accountLoading = $state(true);
|
||||
let configError: string | null = $state(null);
|
||||
let listsLoading = $state(true);
|
||||
let lobbyError: string | null = $state(null);
|
||||
|
||||
let myGames: GameSummary[] = $state([]);
|
||||
let invitations: InviteSummary[] = $state([]);
|
||||
let applications: ApplicationSummary[] = $state([]);
|
||||
let publicGames: GameSummary[] = $state([]);
|
||||
|
||||
let openApplicationFor: string | null = $state(null);
|
||||
let raceNameInput = $state("");
|
||||
let raceNameError: string | null = $state(null);
|
||||
let submittingApplication = $state(false);
|
||||
|
||||
let inviteActionInFlight: string | null = $state(null);
|
||||
|
||||
let client: GalaxyClient | null = null;
|
||||
|
||||
async function logout(): Promise<void> {
|
||||
await session.signOut("user");
|
||||
}
|
||||
|
||||
async function sha256(payload: Uint8Array): Promise<Uint8Array> {
|
||||
const digest = await crypto.subtle.digest(
|
||||
"SHA-256",
|
||||
payload as BufferSource,
|
||||
);
|
||||
const digest = await crypto.subtle.digest("SHA-256", payload as BufferSource);
|
||||
return new Uint8Array(digest);
|
||||
}
|
||||
|
||||
function describeLobbyError(err: unknown): string {
|
||||
if (err instanceof LobbyError) {
|
||||
const key = `lobby.error.${err.code}` as TranslationKey;
|
||||
const translated = i18n.t(key);
|
||||
if (translated !== key) {
|
||||
return translated;
|
||||
}
|
||||
return i18n.t("lobby.error.unknown", { message: err.message });
|
||||
}
|
||||
return err instanceof Error ? err.message : "request failed";
|
||||
}
|
||||
|
||||
async function refreshAll(): Promise<void> {
|
||||
if (client === null) return;
|
||||
listsLoading = true;
|
||||
lobbyError = null;
|
||||
try {
|
||||
const [games, invites, apps, publicPage] = await Promise.all([
|
||||
listMyGames(client),
|
||||
listMyInvites(client),
|
||||
listMyApplications(client),
|
||||
listPublicGames(client),
|
||||
]);
|
||||
myGames = games;
|
||||
invitations = invites.filter((invite) => invite.status === "pending");
|
||||
applications = apps;
|
||||
publicGames = publicPage.items;
|
||||
} catch (err) {
|
||||
lobbyError = describeLobbyError(err);
|
||||
} finally {
|
||||
listsLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
function applicationStatusLabel(status: string): string {
|
||||
const key = `lobby.application.status.${status}` as TranslationKey;
|
||||
const translated = i18n.t(key);
|
||||
if (translated === key) {
|
||||
return i18n.t("lobby.application.status.unknown", { status });
|
||||
}
|
||||
return translated;
|
||||
}
|
||||
|
||||
function openApplicationForm(gameId: string): void {
|
||||
openApplicationFor = gameId;
|
||||
raceNameInput = "";
|
||||
raceNameError = null;
|
||||
}
|
||||
|
||||
function cancelApplicationForm(): void {
|
||||
openApplicationFor = null;
|
||||
raceNameInput = "";
|
||||
raceNameError = null;
|
||||
}
|
||||
|
||||
async function submitApplicationFor(gameId: string): Promise<void> {
|
||||
if (client === null) return;
|
||||
const trimmed = raceNameInput.trim();
|
||||
if (trimmed === "") {
|
||||
raceNameError = i18n.t("lobby.application.race_name_required");
|
||||
return;
|
||||
}
|
||||
submittingApplication = true;
|
||||
raceNameError = null;
|
||||
try {
|
||||
const result = await submitApplication(client, gameId, trimmed);
|
||||
applications = [result, ...applications];
|
||||
openApplicationFor = null;
|
||||
raceNameInput = "";
|
||||
} catch (err) {
|
||||
raceNameError = describeLobbyError(err);
|
||||
} finally {
|
||||
submittingApplication = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function acceptInvite(invite: InviteSummary): Promise<void> {
|
||||
if (client === null) return;
|
||||
inviteActionInFlight = invite.inviteId;
|
||||
try {
|
||||
await redeemInvite(client, invite.gameId, invite.inviteId);
|
||||
invitations = invitations.filter((i) => i.inviteId !== invite.inviteId);
|
||||
myGames = await listMyGames(client);
|
||||
} catch (err) {
|
||||
lobbyError = describeLobbyError(err);
|
||||
} finally {
|
||||
inviteActionInFlight = null;
|
||||
}
|
||||
}
|
||||
|
||||
async function rejectInvite(invite: InviteSummary): Promise<void> {
|
||||
if (client === null) return;
|
||||
inviteActionInFlight = invite.inviteId;
|
||||
try {
|
||||
await declineInvite(client, invite.gameId, invite.inviteId);
|
||||
invitations = invitations.filter((i) => i.inviteId !== invite.inviteId);
|
||||
} catch (err) {
|
||||
lobbyError = describeLobbyError(err);
|
||||
} finally {
|
||||
inviteActionInFlight = null;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadGreeting(c: GalaxyClient): Promise<void> {
|
||||
const builder = new Builder(32);
|
||||
GetMyAccountRequest.startGetMyAccountRequest(builder);
|
||||
builder.finish(GetMyAccountRequest.endGetMyAccountRequest(builder));
|
||||
const result = await c.executeCommand("user.account.get", builder.asUint8Array());
|
||||
if (result.resultCode !== "ok") {
|
||||
return;
|
||||
}
|
||||
const response = AccountResponse.getRootAsAccountResponse(
|
||||
new ByteBuffer(result.payloadBytes),
|
||||
);
|
||||
const account = response.account();
|
||||
if (account === null) {
|
||||
return;
|
||||
}
|
||||
const display = account.displayName();
|
||||
const userName = account.userName();
|
||||
displayName = display && display.length > 0 ? display : userName;
|
||||
}
|
||||
|
||||
function gotoCreate(): void {
|
||||
goto("/lobby/create");
|
||||
}
|
||||
|
||||
function gotoGame(gameId: string): void {
|
||||
goto(`/games/${gameId}/map`);
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
if (
|
||||
session.keypair === null ||
|
||||
session.deviceSessionId === null ||
|
||||
GATEWAY_RESPONSE_PUBLIC_KEY.length === 0
|
||||
) {
|
||||
accountLoading = false;
|
||||
listsLoading = false;
|
||||
if (GATEWAY_RESPONSE_PUBLIC_KEY.length === 0) {
|
||||
accountError =
|
||||
"VITE_GATEWAY_RESPONSE_PUBLIC_KEY is not configured";
|
||||
configError = "VITE_GATEWAY_RESPONSE_PUBLIC_KEY is not configured";
|
||||
}
|
||||
return;
|
||||
}
|
||||
const keypair = session.keypair;
|
||||
try {
|
||||
const core = await loadCore();
|
||||
const client = new GalaxyClient({
|
||||
client = new GalaxyClient({
|
||||
core,
|
||||
edge: createEdgeGatewayClient(GATEWAY_BASE_URL),
|
||||
signer: (canonical) => keypair.sign(canonical),
|
||||
@@ -47,52 +208,284 @@
|
||||
deviceSessionId: session.deviceSessionId,
|
||||
gatewayResponsePublicKey: GATEWAY_RESPONSE_PUBLIC_KEY,
|
||||
});
|
||||
const payload = await client.executeCommand(
|
||||
"user.account.get",
|
||||
new TextEncoder().encode("{}"),
|
||||
);
|
||||
const decoded = JSON.parse(new TextDecoder().decode(payload)) as {
|
||||
account?: { display_name?: string; user_name?: string };
|
||||
};
|
||||
displayName =
|
||||
decoded.account?.display_name ?? decoded.account?.user_name ?? null;
|
||||
loadGreeting(client).catch(() => {});
|
||||
await refreshAll();
|
||||
} catch (err) {
|
||||
accountError = err instanceof Error ? err.message : "request failed";
|
||||
} finally {
|
||||
accountLoading = false;
|
||||
lobbyError = describeLobbyError(err);
|
||||
listsLoading = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<h1>{i18n.t("lobby.title")}</h1>
|
||||
<p>
|
||||
{i18n.t("lobby.device_session_id_label")}:
|
||||
<code data-testid="device-session-id">{session.deviceSessionId ?? ""}</code>
|
||||
</p>
|
||||
{#if accountLoading}
|
||||
<p>{i18n.t("lobby.account_loading")}</p>
|
||||
{:else if displayName !== null}
|
||||
<p data-testid="account-greeting">
|
||||
{i18n.t("lobby.greeting", { name: displayName })}
|
||||
<header>
|
||||
<h1>{i18n.t("lobby.title")}</h1>
|
||||
<p>
|
||||
{i18n.t("lobby.device_session_id_label")}:
|
||||
<code data-testid="device-session-id">{session.deviceSessionId ?? ""}</code>
|
||||
</p>
|
||||
{:else if accountError !== null}
|
||||
<p role="alert" data-testid="account-error">{accountError}</p>
|
||||
{#if displayName !== null}
|
||||
<p data-testid="account-greeting">
|
||||
{i18n.t("lobby.greeting", { name: displayName })}
|
||||
</p>
|
||||
{/if}
|
||||
<button onclick={logout} data-testid="lobby-logout">
|
||||
{i18n.t("lobby.logout")}
|
||||
</button>
|
||||
</header>
|
||||
|
||||
{#if configError !== null}
|
||||
<p role="alert" data-testid="account-error">{configError}</p>
|
||||
{:else if lobbyError !== null}
|
||||
<p role="alert" data-testid="lobby-error">{lobbyError}</p>
|
||||
{/if}
|
||||
<button onclick={logout} data-testid="lobby-logout">
|
||||
{i18n.t("lobby.logout")}
|
||||
</button>
|
||||
|
||||
<section data-testid="lobby-create-section">
|
||||
<button onclick={gotoCreate} data-testid="lobby-create-button">
|
||||
{i18n.t("lobby.create_button")}
|
||||
</button>
|
||||
</section>
|
||||
|
||||
<section data-testid="lobby-my-games-section">
|
||||
<h2>{i18n.t("lobby.section.my_games")}</h2>
|
||||
{#if listsLoading}
|
||||
<p>{i18n.t("lobby.list_loading")}</p>
|
||||
{:else if myGames.length === 0}
|
||||
<p data-testid="lobby-my-games-empty">{i18n.t("lobby.my_games.empty")}</p>
|
||||
{:else}
|
||||
<ul class="card-list">
|
||||
{#each myGames as game (game.gameId)}
|
||||
<li>
|
||||
<button
|
||||
class="card"
|
||||
onclick={() => gotoGame(game.gameId)}
|
||||
data-testid="lobby-my-game-card"
|
||||
>
|
||||
<strong>{game.gameName}</strong>
|
||||
<span class="meta">{game.status}</span>
|
||||
<span class="meta">{game.minPlayers}–{game.maxPlayers} players</span>
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<section data-testid="lobby-invitations-section">
|
||||
<h2>{i18n.t("lobby.section.invitations")}</h2>
|
||||
{#if listsLoading}
|
||||
<p>{i18n.t("lobby.list_loading")}</p>
|
||||
{:else if invitations.length === 0}
|
||||
<p data-testid="lobby-invitations-empty">{i18n.t("lobby.invitations.empty")}</p>
|
||||
{:else}
|
||||
<ul class="card-list">
|
||||
{#each invitations as invite (invite.inviteId)}
|
||||
<li class="card">
|
||||
<strong>{invite.raceName}</strong>
|
||||
<span class="meta">{invite.gameId}</span>
|
||||
<div class="actions">
|
||||
<button
|
||||
onclick={() => acceptInvite(invite)}
|
||||
disabled={inviteActionInFlight === invite.inviteId}
|
||||
data-testid="lobby-invite-accept"
|
||||
>
|
||||
{i18n.t("lobby.invitation.accept")}
|
||||
</button>
|
||||
<button
|
||||
onclick={() => rejectInvite(invite)}
|
||||
disabled={inviteActionInFlight === invite.inviteId}
|
||||
data-testid="lobby-invite-decline"
|
||||
>
|
||||
{i18n.t("lobby.invitation.decline")}
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<section data-testid="lobby-applications-section">
|
||||
<h2>{i18n.t("lobby.section.applications")}</h2>
|
||||
{#if listsLoading}
|
||||
<p>{i18n.t("lobby.list_loading")}</p>
|
||||
{:else if applications.length === 0}
|
||||
<p data-testid="lobby-applications-empty">{i18n.t("lobby.applications.empty")}</p>
|
||||
{:else}
|
||||
<ul class="card-list">
|
||||
{#each applications as app (app.applicationId)}
|
||||
<li class="card" data-testid="lobby-application-card">
|
||||
<strong>{app.raceName}</strong>
|
||||
<span class="meta">{app.gameId}</span>
|
||||
<span class="status" data-status={app.status}>
|
||||
{applicationStatusLabel(app.status)}
|
||||
</span>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<section data-testid="lobby-public-games-section">
|
||||
<h2>{i18n.t("lobby.section.public_games")}</h2>
|
||||
{#if listsLoading}
|
||||
<p>{i18n.t("lobby.list_loading")}</p>
|
||||
{:else if publicGames.length === 0}
|
||||
<p data-testid="lobby-public-games-empty">{i18n.t("lobby.public_games.empty")}</p>
|
||||
{:else}
|
||||
<ul class="card-list">
|
||||
{#each publicGames as game (game.gameId)}
|
||||
<li class="card">
|
||||
<strong>{game.gameName}</strong>
|
||||
<span class="meta">{game.status}</span>
|
||||
<span class="meta">{game.minPlayers}–{game.maxPlayers} players</span>
|
||||
{#if openApplicationFor === game.gameId}
|
||||
<form
|
||||
onsubmit={(event) => {
|
||||
event.preventDefault();
|
||||
submitApplicationFor(game.gameId);
|
||||
}}
|
||||
data-testid="lobby-application-form"
|
||||
>
|
||||
<label>
|
||||
{i18n.t("lobby.application.race_name_label")}
|
||||
<input
|
||||
type="text"
|
||||
bind:value={raceNameInput}
|
||||
data-testid="lobby-application-race-name"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</label>
|
||||
{#if raceNameError !== null}
|
||||
<p role="alert" data-testid="lobby-application-error">
|
||||
{raceNameError}
|
||||
</p>
|
||||
{/if}
|
||||
<div class="actions">
|
||||
<button
|
||||
type="submit"
|
||||
disabled={submittingApplication}
|
||||
data-testid="lobby-application-submit"
|
||||
>
|
||||
{i18n.t("lobby.application.submit")}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onclick={cancelApplicationForm}
|
||||
data-testid="lobby-application-cancel"
|
||||
>
|
||||
{i18n.t("lobby.application.cancel")}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{:else}
|
||||
<button
|
||||
onclick={() => openApplicationForm(game.gameId)}
|
||||
data-testid="lobby-public-game-apply"
|
||||
>
|
||||
{i18n.t("lobby.application.submit_for", { name: game.gameName })}
|
||||
</button>
|
||||
{/if}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
padding: 2rem;
|
||||
padding: 1.5rem 1rem;
|
||||
max-width: 32rem;
|
||||
margin: 0 auto;
|
||||
font-family: system-ui, sans-serif;
|
||||
}
|
||||
|
||||
button {
|
||||
header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
header h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
header button {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
section {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
section h2 {
|
||||
font-size: 1.1rem;
|
||||
margin: 0 0 0.75rem;
|
||||
}
|
||||
|
||||
.card-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 0.4rem;
|
||||
background: #fafafa;
|
||||
text-align: left;
|
||||
font: inherit;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
li.card {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.meta {
|
||||
color: #555;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.status {
|
||||
align-self: flex-start;
|
||||
padding: 0.1rem 0.5rem;
|
||||
border-radius: 999px;
|
||||
background: #e7e7e7;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
label {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
font-size: 1rem;
|
||||
padding: 0.5rem 1rem;
|
||||
margin-top: 1rem;
|
||||
padding: 0.4rem 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
<script lang="ts">
|
||||
import { goto } from "$app/navigation";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
import { createEdgeGatewayClient } from "../../../api/connect";
|
||||
import { GalaxyClient } from "../../../api/galaxy-client";
|
||||
import { LobbyError, createGame } from "../../../api/lobby";
|
||||
import { GATEWAY_BASE_URL, GATEWAY_RESPONSE_PUBLIC_KEY } from "$lib/env";
|
||||
import { i18n, type TranslationKey } from "$lib/i18n/index.svelte";
|
||||
import { loadCore } from "../../../platform/core/index";
|
||||
import { session } from "$lib/session-store.svelte";
|
||||
|
||||
const DEFAULT_MIN_PLAYERS = 2;
|
||||
const DEFAULT_MAX_PLAYERS = 8;
|
||||
const DEFAULT_START_GAP_HOURS = 24;
|
||||
const DEFAULT_START_GAP_PLAYERS = 2;
|
||||
const DEFAULT_TARGET_ENGINE_VERSION = "v1";
|
||||
|
||||
let gameName = $state("");
|
||||
let description = $state("");
|
||||
let turnSchedule = $state("0 0 * * *");
|
||||
let enrollmentEndsAt = $state("");
|
||||
|
||||
let minPlayers = $state(DEFAULT_MIN_PLAYERS);
|
||||
let maxPlayers = $state(DEFAULT_MAX_PLAYERS);
|
||||
let startGapHours = $state(DEFAULT_START_GAP_HOURS);
|
||||
let startGapPlayers = $state(DEFAULT_START_GAP_PLAYERS);
|
||||
let targetEngineVersion = $state(DEFAULT_TARGET_ENGINE_VERSION);
|
||||
|
||||
let formError: string | null = $state(null);
|
||||
let configError: string | null = $state(null);
|
||||
let submitting = $state(false);
|
||||
|
||||
let client: GalaxyClient | null = null;
|
||||
|
||||
async function sha256(payload: Uint8Array): Promise<Uint8Array> {
|
||||
const digest = await crypto.subtle.digest("SHA-256", payload as BufferSource);
|
||||
return new Uint8Array(digest);
|
||||
}
|
||||
|
||||
function describeLobbyError(err: unknown): string {
|
||||
if (err instanceof LobbyError) {
|
||||
const key = `lobby.error.${err.code}` as TranslationKey;
|
||||
const translated = i18n.t(key);
|
||||
if (translated !== key) {
|
||||
return translated;
|
||||
}
|
||||
return i18n.t("lobby.error.unknown", { message: err.message });
|
||||
}
|
||||
return err instanceof Error ? err.message : "request failed";
|
||||
}
|
||||
|
||||
function cancel(): void {
|
||||
goto("/lobby");
|
||||
}
|
||||
|
||||
async function submit(): Promise<void> {
|
||||
formError = null;
|
||||
const trimmedName = gameName.trim();
|
||||
const trimmedSchedule = turnSchedule.trim();
|
||||
const trimmedEnrollment = enrollmentEndsAt.trim();
|
||||
if (trimmedName === "") {
|
||||
formError = i18n.t("lobby.create.game_name_required");
|
||||
return;
|
||||
}
|
||||
if (trimmedSchedule === "") {
|
||||
formError = i18n.t("lobby.create.turn_schedule_required");
|
||||
return;
|
||||
}
|
||||
if (trimmedEnrollment === "") {
|
||||
formError = i18n.t("lobby.create.enrollment_ends_at_required");
|
||||
return;
|
||||
}
|
||||
const enrollmentDate = new Date(trimmedEnrollment);
|
||||
if (Number.isNaN(enrollmentDate.getTime())) {
|
||||
formError = i18n.t("lobby.create.enrollment_ends_at_required");
|
||||
return;
|
||||
}
|
||||
if (client === null) {
|
||||
formError = configError ?? "client not ready";
|
||||
return;
|
||||
}
|
||||
submitting = true;
|
||||
try {
|
||||
await createGame(client, {
|
||||
gameName: trimmedName,
|
||||
description: description.trim(),
|
||||
minPlayers,
|
||||
maxPlayers,
|
||||
startGapHours,
|
||||
startGapPlayers,
|
||||
enrollmentEndsAt: enrollmentDate,
|
||||
turnSchedule: trimmedSchedule,
|
||||
targetEngineVersion: targetEngineVersion.trim() || DEFAULT_TARGET_ENGINE_VERSION,
|
||||
});
|
||||
goto("/lobby");
|
||||
} catch (err) {
|
||||
formError = describeLobbyError(err);
|
||||
} finally {
|
||||
submitting = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
if (
|
||||
session.keypair === null ||
|
||||
session.deviceSessionId === null ||
|
||||
GATEWAY_RESPONSE_PUBLIC_KEY.length === 0
|
||||
) {
|
||||
if (GATEWAY_RESPONSE_PUBLIC_KEY.length === 0) {
|
||||
configError = "VITE_GATEWAY_RESPONSE_PUBLIC_KEY is not configured";
|
||||
}
|
||||
return;
|
||||
}
|
||||
const keypair = session.keypair;
|
||||
const core = await loadCore();
|
||||
client = new GalaxyClient({
|
||||
core,
|
||||
edge: createEdgeGatewayClient(GATEWAY_BASE_URL),
|
||||
signer: (canonical) => keypair.sign(canonical),
|
||||
sha256,
|
||||
deviceSessionId: session.deviceSessionId,
|
||||
gatewayResponsePublicKey: GATEWAY_RESPONSE_PUBLIC_KEY,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<h1>{i18n.t("lobby.create.title")}</h1>
|
||||
{#if configError !== null}
|
||||
<p role="alert" data-testid="lobby-create-config-error">{configError}</p>
|
||||
{/if}
|
||||
<form
|
||||
onsubmit={(event) => {
|
||||
event.preventDefault();
|
||||
submit();
|
||||
}}
|
||||
data-testid="lobby-create-form"
|
||||
>
|
||||
<label>
|
||||
{i18n.t("lobby.create.game_name_label")}
|
||||
<input
|
||||
type="text"
|
||||
bind:value={gameName}
|
||||
data-testid="lobby-create-game-name"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
{i18n.t("lobby.create.description_label")}
|
||||
<textarea
|
||||
bind:value={description}
|
||||
data-testid="lobby-create-description"
|
||||
rows="3"
|
||||
></textarea>
|
||||
</label>
|
||||
<label>
|
||||
{i18n.t("lobby.create.turn_schedule_label")}
|
||||
<input
|
||||
type="text"
|
||||
bind:value={turnSchedule}
|
||||
data-testid="lobby-create-turn-schedule"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<small>{i18n.t("lobby.create.turn_schedule_hint")}</small>
|
||||
</label>
|
||||
<label>
|
||||
{i18n.t("lobby.create.enrollment_ends_at_label")}
|
||||
<input
|
||||
type="datetime-local"
|
||||
bind:value={enrollmentEndsAt}
|
||||
data-testid="lobby-create-enrollment-ends-at"
|
||||
/>
|
||||
</label>
|
||||
<details data-testid="lobby-create-advanced">
|
||||
<summary>{i18n.t("lobby.create.advanced")}</summary>
|
||||
<label>
|
||||
{i18n.t("lobby.create.min_players_label")}
|
||||
<input
|
||||
type="number"
|
||||
min="1"
|
||||
bind:value={minPlayers}
|
||||
data-testid="lobby-create-min-players"
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
{i18n.t("lobby.create.max_players_label")}
|
||||
<input
|
||||
type="number"
|
||||
min="1"
|
||||
bind:value={maxPlayers}
|
||||
data-testid="lobby-create-max-players"
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
{i18n.t("lobby.create.start_gap_hours_label")}
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
bind:value={startGapHours}
|
||||
data-testid="lobby-create-start-gap-hours"
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
{i18n.t("lobby.create.start_gap_players_label")}
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
bind:value={startGapPlayers}
|
||||
data-testid="lobby-create-start-gap-players"
|
||||
/>
|
||||
</label>
|
||||
<label>
|
||||
{i18n.t("lobby.create.target_engine_version_label")}
|
||||
<input
|
||||
type="text"
|
||||
bind:value={targetEngineVersion}
|
||||
data-testid="lobby-create-target-engine-version"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</label>
|
||||
</details>
|
||||
{#if formError !== null}
|
||||
<p role="alert" data-testid="lobby-create-error">{formError}</p>
|
||||
{/if}
|
||||
<div class="actions">
|
||||
<button type="submit" disabled={submitting} data-testid="lobby-create-submit">
|
||||
{submitting ? i18n.t("lobby.create.submitting") : i18n.t("lobby.create.submit")}
|
||||
</button>
|
||||
<button type="button" onclick={cancel} data-testid="lobby-create-cancel">
|
||||
{i18n.t("lobby.create.cancel")}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
padding: 1.5rem 1rem;
|
||||
max-width: 32rem;
|
||||
margin: 0 auto;
|
||||
font-family: system-ui, sans-serif;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
label {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="number"],
|
||||
input[type="datetime-local"],
|
||||
textarea {
|
||||
font-size: 1rem;
|
||||
padding: 0.4rem 0.5rem;
|
||||
}
|
||||
|
||||
details {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 0.4rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
details > label {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
details summary {
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
small {
|
||||
color: #666;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,2 @@
|
||||
export const ssr = false;
|
||||
export const prerender = false;
|
||||
@@ -16,6 +16,13 @@ import { fromJson, type JsonValue } from "@bufbuild/protobuf";
|
||||
import { expect, test, type Page } from "@playwright/test";
|
||||
import { ExecuteCommandRequestSchema } from "../../src/proto/galaxy/gateway/v1/edge_gateway_pb";
|
||||
import { forgeExecuteCommandResponseJson } from "./fixtures/sign-response";
|
||||
import {
|
||||
buildAccountResponsePayload,
|
||||
buildMyApplicationsListPayload,
|
||||
buildMyGamesListPayload,
|
||||
buildMyInvitesListPayload,
|
||||
buildPublicGamesListPayload,
|
||||
} from "./fixtures/lobby-fbs";
|
||||
|
||||
interface MockSetup {
|
||||
pendingSubscribes: Array<() => void>;
|
||||
@@ -58,19 +65,36 @@ async function mockGatewayHappyPath(
|
||||
ExecuteCommandRequestSchema,
|
||||
JSON.parse(reqText) as JsonValue,
|
||||
);
|
||||
const accountJson = JSON.stringify({
|
||||
account: {
|
||||
user_id: "user-1",
|
||||
email: "pilot@example.com",
|
||||
user_name: "player-test",
|
||||
display_name: displayName,
|
||||
},
|
||||
});
|
||||
let payload: Uint8Array;
|
||||
switch (req.messageType) {
|
||||
case "user.account.get":
|
||||
payload = buildAccountResponsePayload({
|
||||
userId: "user-1",
|
||||
email: "pilot@example.com",
|
||||
userName: "player-test",
|
||||
displayName,
|
||||
});
|
||||
break;
|
||||
case "lobby.my.games.list":
|
||||
payload = buildMyGamesListPayload([]);
|
||||
break;
|
||||
case "lobby.public.games.list":
|
||||
payload = buildPublicGamesListPayload([]);
|
||||
break;
|
||||
case "lobby.my.invites.list":
|
||||
payload = buildMyInvitesListPayload([]);
|
||||
break;
|
||||
case "lobby.my.applications.list":
|
||||
payload = buildMyApplicationsListPayload([]);
|
||||
break;
|
||||
default:
|
||||
payload = new Uint8Array();
|
||||
}
|
||||
const responseJson = await forgeExecuteCommandResponseJson({
|
||||
requestId: req.requestId,
|
||||
timestampMs: BigInt(Date.now()),
|
||||
resultCode: "ok",
|
||||
payloadBytes: new TextEncoder().encode(accountJson),
|
||||
payloadBytes: payload,
|
||||
});
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
@@ -122,9 +146,14 @@ async function mockGatewayHappyPath(
|
||||
async function completeLogin(page: Page): Promise<void> {
|
||||
await page.goto("/");
|
||||
await expect(page).toHaveURL(/\/login$/);
|
||||
// Inputs render `readonly` initially as a Safari autofill-suppression
|
||||
// workaround; the attribute drops on first focus. Click first so the
|
||||
// onfocus handler runs before fill checks editability.
|
||||
await page.getByTestId("login-email-input").click();
|
||||
await page.getByTestId("login-email-input").fill("pilot@example.com");
|
||||
await page.getByTestId("login-email-submit").click();
|
||||
await expect(page.getByTestId("login-code-input")).toBeVisible();
|
||||
await page.getByTestId("login-code-input").click();
|
||||
await page.getByTestId("login-code-input").fill("123456");
|
||||
await page.getByTestId("login-code-submit").click();
|
||||
await expect(page).toHaveURL(/\/lobby$/);
|
||||
@@ -213,6 +242,7 @@ test.describe("Phase 7 — auth flow", () => {
|
||||
"отправить код",
|
||||
);
|
||||
|
||||
await page.getByTestId("login-email-input").click();
|
||||
await page.getByTestId("login-email-input").fill("pilot@example.com");
|
||||
await page.getByTestId("login-email-submit").click();
|
||||
await expect(page.getByTestId("login-code-input")).toBeVisible();
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
// Helpers that build FlatBuffers payloads for the lobby Playwright
|
||||
// suite. Mirrors what `pkg/transcoder/lobby.go` produces in production,
|
||||
// so the forged response goes through the same TS decoder the lobby
|
||||
// page uses.
|
||||
|
||||
import { Builder } from "flatbuffers";
|
||||
|
||||
import {
|
||||
AccountResponse,
|
||||
AccountView,
|
||||
EntitlementSnapshot,
|
||||
} from "../../../src/proto/galaxy/fbs/user";
|
||||
import {
|
||||
ApplicationSubmitResponse,
|
||||
ApplicationSummary,
|
||||
GameCreateResponse,
|
||||
GameSummary,
|
||||
InviteDeclineResponse,
|
||||
InviteRedeemResponse,
|
||||
InviteSummary,
|
||||
MyApplicationsListResponse,
|
||||
MyGamesListResponse,
|
||||
MyInvitesListResponse,
|
||||
PublicGamesListResponse,
|
||||
} from "../../../src/proto/galaxy/fbs/lobby";
|
||||
|
||||
export interface GameFixture {
|
||||
gameId: string;
|
||||
gameName: string;
|
||||
gameType: string;
|
||||
status: string;
|
||||
ownerUserId?: string;
|
||||
minPlayers?: number;
|
||||
maxPlayers?: number;
|
||||
enrollmentEndsAtMs?: bigint;
|
||||
createdAtMs?: bigint;
|
||||
updatedAtMs?: bigint;
|
||||
}
|
||||
|
||||
export interface ApplicationFixture {
|
||||
applicationId: string;
|
||||
gameId: string;
|
||||
applicantUserId: string;
|
||||
raceName: string;
|
||||
status: string;
|
||||
createdAtMs?: bigint;
|
||||
decidedAtMs?: bigint;
|
||||
}
|
||||
|
||||
export interface InviteFixture {
|
||||
inviteId: string;
|
||||
gameId: string;
|
||||
inviterUserId: string;
|
||||
invitedUserId?: string;
|
||||
code?: string;
|
||||
raceName: string;
|
||||
status: string;
|
||||
createdAtMs?: bigint;
|
||||
expiresAtMs?: bigint;
|
||||
decidedAtMs?: bigint;
|
||||
}
|
||||
|
||||
const DEFAULT_TIME_MS = 1_780_000_000_000n;
|
||||
|
||||
function encodeGame(builder: Builder, game: GameFixture): number {
|
||||
const gameId = builder.createString(game.gameId);
|
||||
const gameName = builder.createString(game.gameName);
|
||||
const gameType = builder.createString(game.gameType);
|
||||
const status = builder.createString(game.status);
|
||||
const ownerUserId = builder.createString(game.ownerUserId ?? "");
|
||||
GameSummary.startGameSummary(builder);
|
||||
GameSummary.addGameId(builder, gameId);
|
||||
GameSummary.addGameName(builder, gameName);
|
||||
GameSummary.addGameType(builder, gameType);
|
||||
GameSummary.addStatus(builder, status);
|
||||
GameSummary.addOwnerUserId(builder, ownerUserId);
|
||||
GameSummary.addMinPlayers(builder, game.minPlayers ?? 2);
|
||||
GameSummary.addMaxPlayers(builder, game.maxPlayers ?? 8);
|
||||
GameSummary.addEnrollmentEndsAtMs(builder, game.enrollmentEndsAtMs ?? DEFAULT_TIME_MS);
|
||||
GameSummary.addCreatedAtMs(builder, game.createdAtMs ?? DEFAULT_TIME_MS);
|
||||
GameSummary.addUpdatedAtMs(builder, game.updatedAtMs ?? DEFAULT_TIME_MS);
|
||||
return GameSummary.endGameSummary(builder);
|
||||
}
|
||||
|
||||
function encodeApplication(builder: Builder, app: ApplicationFixture): number {
|
||||
const applicationId = builder.createString(app.applicationId);
|
||||
const gameId = builder.createString(app.gameId);
|
||||
const applicantUserId = builder.createString(app.applicantUserId);
|
||||
const raceName = builder.createString(app.raceName);
|
||||
const status = builder.createString(app.status);
|
||||
ApplicationSummary.startApplicationSummary(builder);
|
||||
ApplicationSummary.addApplicationId(builder, applicationId);
|
||||
ApplicationSummary.addGameId(builder, gameId);
|
||||
ApplicationSummary.addApplicantUserId(builder, applicantUserId);
|
||||
ApplicationSummary.addRaceName(builder, raceName);
|
||||
ApplicationSummary.addStatus(builder, status);
|
||||
ApplicationSummary.addCreatedAtMs(builder, app.createdAtMs ?? DEFAULT_TIME_MS);
|
||||
ApplicationSummary.addDecidedAtMs(builder, app.decidedAtMs ?? 0n);
|
||||
return ApplicationSummary.endApplicationSummary(builder);
|
||||
}
|
||||
|
||||
function encodeInvite(builder: Builder, invite: InviteFixture): number {
|
||||
const inviteId = builder.createString(invite.inviteId);
|
||||
const gameId = builder.createString(invite.gameId);
|
||||
const inviterUserId = builder.createString(invite.inviterUserId);
|
||||
const invitedUserId = builder.createString(invite.invitedUserId ?? "");
|
||||
const code = builder.createString(invite.code ?? "");
|
||||
const raceName = builder.createString(invite.raceName);
|
||||
const status = builder.createString(invite.status);
|
||||
InviteSummary.startInviteSummary(builder);
|
||||
InviteSummary.addInviteId(builder, inviteId);
|
||||
InviteSummary.addGameId(builder, gameId);
|
||||
InviteSummary.addInviterUserId(builder, inviterUserId);
|
||||
InviteSummary.addInvitedUserId(builder, invitedUserId);
|
||||
InviteSummary.addCode(builder, code);
|
||||
InviteSummary.addRaceName(builder, raceName);
|
||||
InviteSummary.addStatus(builder, status);
|
||||
InviteSummary.addCreatedAtMs(builder, invite.createdAtMs ?? DEFAULT_TIME_MS);
|
||||
InviteSummary.addExpiresAtMs(builder, invite.expiresAtMs ?? DEFAULT_TIME_MS);
|
||||
InviteSummary.addDecidedAtMs(builder, invite.decidedAtMs ?? 0n);
|
||||
return InviteSummary.endInviteSummary(builder);
|
||||
}
|
||||
|
||||
export function buildMyGamesListPayload(games: GameFixture[]): Uint8Array {
|
||||
const builder = new Builder(256);
|
||||
const offsets = games.map((g) => encodeGame(builder, g));
|
||||
const items = MyGamesListResponse.createItemsVector(builder, offsets);
|
||||
MyGamesListResponse.startMyGamesListResponse(builder);
|
||||
MyGamesListResponse.addItems(builder, items);
|
||||
builder.finish(MyGamesListResponse.endMyGamesListResponse(builder));
|
||||
return builder.asUint8Array();
|
||||
}
|
||||
|
||||
export function buildPublicGamesListPayload(
|
||||
games: GameFixture[],
|
||||
page = 1,
|
||||
pageSize = 50,
|
||||
): Uint8Array {
|
||||
const builder = new Builder(256);
|
||||
const offsets = games.map((g) => encodeGame(builder, g));
|
||||
const items = PublicGamesListResponse.createItemsVector(builder, offsets);
|
||||
PublicGamesListResponse.startPublicGamesListResponse(builder);
|
||||
PublicGamesListResponse.addItems(builder, items);
|
||||
PublicGamesListResponse.addPage(builder, page);
|
||||
PublicGamesListResponse.addPageSize(builder, pageSize);
|
||||
PublicGamesListResponse.addTotal(builder, games.length);
|
||||
builder.finish(PublicGamesListResponse.endPublicGamesListResponse(builder));
|
||||
return builder.asUint8Array();
|
||||
}
|
||||
|
||||
export function buildMyApplicationsListPayload(
|
||||
applications: ApplicationFixture[],
|
||||
): Uint8Array {
|
||||
const builder = new Builder(256);
|
||||
const offsets = applications.map((a) => encodeApplication(builder, a));
|
||||
const items = MyApplicationsListResponse.createItemsVector(builder, offsets);
|
||||
MyApplicationsListResponse.startMyApplicationsListResponse(builder);
|
||||
MyApplicationsListResponse.addItems(builder, items);
|
||||
builder.finish(MyApplicationsListResponse.endMyApplicationsListResponse(builder));
|
||||
return builder.asUint8Array();
|
||||
}
|
||||
|
||||
export function buildMyInvitesListPayload(invites: InviteFixture[]): Uint8Array {
|
||||
const builder = new Builder(256);
|
||||
const offsets = invites.map((i) => encodeInvite(builder, i));
|
||||
const items = MyInvitesListResponse.createItemsVector(builder, offsets);
|
||||
MyInvitesListResponse.startMyInvitesListResponse(builder);
|
||||
MyInvitesListResponse.addItems(builder, items);
|
||||
builder.finish(MyInvitesListResponse.endMyInvitesListResponse(builder));
|
||||
return builder.asUint8Array();
|
||||
}
|
||||
|
||||
export function buildGameCreateResponsePayload(game: GameFixture): Uint8Array {
|
||||
const builder = new Builder(256);
|
||||
const summary = encodeGame(builder, game);
|
||||
GameCreateResponse.startGameCreateResponse(builder);
|
||||
GameCreateResponse.addGame(builder, summary);
|
||||
builder.finish(GameCreateResponse.endGameCreateResponse(builder));
|
||||
return builder.asUint8Array();
|
||||
}
|
||||
|
||||
export function buildApplicationSubmitResponsePayload(
|
||||
application: ApplicationFixture,
|
||||
): Uint8Array {
|
||||
const builder = new Builder(128);
|
||||
const app = encodeApplication(builder, application);
|
||||
ApplicationSubmitResponse.startApplicationSubmitResponse(builder);
|
||||
ApplicationSubmitResponse.addApplication(builder, app);
|
||||
builder.finish(ApplicationSubmitResponse.endApplicationSubmitResponse(builder));
|
||||
return builder.asUint8Array();
|
||||
}
|
||||
|
||||
export function buildInviteRedeemResponsePayload(invite: InviteFixture): Uint8Array {
|
||||
const builder = new Builder(128);
|
||||
const summary = encodeInvite(builder, invite);
|
||||
InviteRedeemResponse.startInviteRedeemResponse(builder);
|
||||
InviteRedeemResponse.addInvite(builder, summary);
|
||||
builder.finish(InviteRedeemResponse.endInviteRedeemResponse(builder));
|
||||
return builder.asUint8Array();
|
||||
}
|
||||
|
||||
export function buildInviteDeclineResponsePayload(invite: InviteFixture): Uint8Array {
|
||||
const builder = new Builder(128);
|
||||
const summary = encodeInvite(builder, invite);
|
||||
InviteDeclineResponse.startInviteDeclineResponse(builder);
|
||||
InviteDeclineResponse.addInvite(builder, summary);
|
||||
builder.finish(InviteDeclineResponse.endInviteDeclineResponse(builder));
|
||||
return builder.asUint8Array();
|
||||
}
|
||||
|
||||
export interface AccountFixture {
|
||||
userId: string;
|
||||
email: string;
|
||||
userName: string;
|
||||
displayName: string;
|
||||
}
|
||||
|
||||
export function buildAccountResponsePayload(account: AccountFixture): Uint8Array {
|
||||
const builder = new Builder(256);
|
||||
|
||||
const planCode = builder.createString("free");
|
||||
const source = builder.createString("internal");
|
||||
const reasonCode = builder.createString("");
|
||||
EntitlementSnapshot.startEntitlementSnapshot(builder);
|
||||
EntitlementSnapshot.addPlanCode(builder, planCode);
|
||||
EntitlementSnapshot.addIsPaid(builder, false);
|
||||
EntitlementSnapshot.addSource(builder, source);
|
||||
EntitlementSnapshot.addReasonCode(builder, reasonCode);
|
||||
EntitlementSnapshot.addStartsAtMs(builder, 0n);
|
||||
EntitlementSnapshot.addEndsAtMs(builder, 0n);
|
||||
EntitlementSnapshot.addUpdatedAtMs(builder, 0n);
|
||||
const entitlement = EntitlementSnapshot.endEntitlementSnapshot(builder);
|
||||
|
||||
const userId = builder.createString(account.userId);
|
||||
const email = builder.createString(account.email);
|
||||
const userName = builder.createString(account.userName);
|
||||
const displayName = builder.createString(account.displayName);
|
||||
const preferredLanguage = builder.createString("en");
|
||||
const timeZone = builder.createString("UTC");
|
||||
const declaredCountry = builder.createString("");
|
||||
AccountView.startAccountView(builder);
|
||||
AccountView.addUserId(builder, userId);
|
||||
AccountView.addEmail(builder, email);
|
||||
AccountView.addUserName(builder, userName);
|
||||
AccountView.addDisplayName(builder, displayName);
|
||||
AccountView.addPreferredLanguage(builder, preferredLanguage);
|
||||
AccountView.addTimeZone(builder, timeZone);
|
||||
AccountView.addDeclaredCountry(builder, declaredCountry);
|
||||
AccountView.addEntitlement(builder, entitlement);
|
||||
AccountView.addCreatedAtMs(builder, 0n);
|
||||
AccountView.addUpdatedAtMs(builder, 0n);
|
||||
const view = AccountView.endAccountView(builder);
|
||||
|
||||
AccountResponse.startAccountResponse(builder);
|
||||
AccountResponse.addAccount(builder, view);
|
||||
builder.finish(AccountResponse.endAccountResponse(builder));
|
||||
return builder.asUint8Array();
|
||||
}
|
||||
@@ -0,0 +1,340 @@
|
||||
// Phase 8 lobby end-to-end coverage. The gateway is mocked through
|
||||
// `page.route(...)` like in the Phase 7 spec; this spec dispatches by
|
||||
// `messageType` so each lobby command can return its own forged
|
||||
// FlatBuffers payload. The flows under test:
|
||||
//
|
||||
// 1) Land on /lobby with empty lists; create a private game; verify
|
||||
// the new game appears in My Games after the redirect.
|
||||
// 2) Submit an application to a public game; verify the application
|
||||
// shows up in My Applications.
|
||||
// 3) Accept an invitation; verify the invite card disappears.
|
||||
|
||||
import { fromJson, type JsonValue } from "@bufbuild/protobuf";
|
||||
import { expect, test, type Page } from "@playwright/test";
|
||||
import { ByteBuffer } from "flatbuffers";
|
||||
import { ExecuteCommandRequestSchema } from "../../src/proto/galaxy/gateway/v1/edge_gateway_pb";
|
||||
import { GameCreateRequest } from "../../src/proto/galaxy/fbs/lobby";
|
||||
import { forgeExecuteCommandResponseJson } from "./fixtures/sign-response";
|
||||
import {
|
||||
buildAccountResponsePayload,
|
||||
buildApplicationSubmitResponsePayload,
|
||||
buildGameCreateResponsePayload,
|
||||
buildInviteRedeemResponsePayload,
|
||||
buildMyApplicationsListPayload,
|
||||
buildMyGamesListPayload,
|
||||
buildMyInvitesListPayload,
|
||||
buildPublicGamesListPayload,
|
||||
type ApplicationFixture,
|
||||
type GameFixture,
|
||||
type InviteFixture,
|
||||
} from "./fixtures/lobby-fbs";
|
||||
|
||||
interface LobbyState {
|
||||
myGames: GameFixture[];
|
||||
publicGames: GameFixture[];
|
||||
invitations: InviteFixture[];
|
||||
applications: ApplicationFixture[];
|
||||
}
|
||||
|
||||
interface LobbyMocks {
|
||||
state: LobbyState;
|
||||
pendingSubscribes: Array<() => void>;
|
||||
createGameCalls: GameFixture[];
|
||||
applicationSubmitCalls: Array<{ gameId: string; raceName: string }>;
|
||||
inviteRedeemCalls: Array<{ gameId: string; inviteId: string }>;
|
||||
}
|
||||
|
||||
async function mockGateway(page: Page, initial: Partial<LobbyState> = {}): Promise<LobbyMocks> {
|
||||
const mocks: LobbyMocks = {
|
||||
state: {
|
||||
myGames: initial.myGames ?? [],
|
||||
publicGames: initial.publicGames ?? [],
|
||||
invitations: initial.invitations ?? [],
|
||||
applications: initial.applications ?? [],
|
||||
},
|
||||
pendingSubscribes: [],
|
||||
createGameCalls: [],
|
||||
applicationSubmitCalls: [],
|
||||
inviteRedeemCalls: [],
|
||||
};
|
||||
|
||||
await page.route("**/api/v1/public/auth/send-email-code", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ challenge_id: "ch-test-1" }),
|
||||
});
|
||||
});
|
||||
|
||||
await page.route("**/api/v1/public/auth/confirm-email-code", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({ device_session_id: "dev-test-1" }),
|
||||
});
|
||||
});
|
||||
|
||||
await page.route("**/galaxy.gateway.v1.EdgeGateway/ExecuteCommand", async (route) => {
|
||||
const reqText = route.request().postData();
|
||||
if (reqText === null) {
|
||||
await route.fulfill({ status: 400 });
|
||||
return;
|
||||
}
|
||||
const req = fromJson(
|
||||
ExecuteCommandRequestSchema,
|
||||
JSON.parse(reqText) as JsonValue,
|
||||
);
|
||||
|
||||
let resultCode = "ok";
|
||||
let payload: Uint8Array;
|
||||
switch (req.messageType) {
|
||||
case "user.account.get":
|
||||
payload = buildAccountResponsePayload({
|
||||
userId: "user-1",
|
||||
email: "pilot@example.com",
|
||||
userName: "pilot",
|
||||
displayName: "Pilot",
|
||||
});
|
||||
break;
|
||||
case "lobby.my.games.list":
|
||||
payload = buildMyGamesListPayload(mocks.state.myGames);
|
||||
break;
|
||||
case "lobby.public.games.list":
|
||||
payload = buildPublicGamesListPayload(mocks.state.publicGames);
|
||||
break;
|
||||
case "lobby.my.invites.list":
|
||||
payload = buildMyInvitesListPayload(mocks.state.invitations);
|
||||
break;
|
||||
case "lobby.my.applications.list":
|
||||
payload = buildMyApplicationsListPayload(mocks.state.applications);
|
||||
break;
|
||||
case "lobby.game.create": {
|
||||
const decoded = GameCreateRequest.getRootAsGameCreateRequest(
|
||||
new ByteBuffer(req.payloadBytes),
|
||||
);
|
||||
const created: GameFixture = {
|
||||
gameId: "private-newly-created",
|
||||
gameName: decoded.gameName() ?? "",
|
||||
gameType: "private",
|
||||
status: "draft",
|
||||
ownerUserId: "user-1",
|
||||
minPlayers: decoded.minPlayers(),
|
||||
maxPlayers: decoded.maxPlayers(),
|
||||
enrollmentEndsAtMs: decoded.enrollmentEndsAtMs(),
|
||||
createdAtMs: BigInt(Date.now()),
|
||||
updatedAtMs: BigInt(Date.now()),
|
||||
};
|
||||
mocks.createGameCalls.push(created);
|
||||
mocks.state.myGames = [...mocks.state.myGames, created];
|
||||
payload = buildGameCreateResponsePayload(created);
|
||||
break;
|
||||
}
|
||||
case "lobby.application.submit": {
|
||||
const builder = req.payloadBytes;
|
||||
const submitReq = await import("../../src/proto/galaxy/fbs/lobby");
|
||||
const decoded = submitReq.ApplicationSubmitRequest.getRootAsApplicationSubmitRequest(
|
||||
new ByteBuffer(builder),
|
||||
);
|
||||
const application: ApplicationFixture = {
|
||||
applicationId: `app-${mocks.applicationSubmitCalls.length + 1}`,
|
||||
gameId: decoded.gameId() ?? "",
|
||||
applicantUserId: "user-1",
|
||||
raceName: decoded.raceName() ?? "",
|
||||
status: "pending",
|
||||
createdAtMs: BigInt(Date.now()),
|
||||
};
|
||||
mocks.applicationSubmitCalls.push({
|
||||
gameId: application.gameId,
|
||||
raceName: application.raceName,
|
||||
});
|
||||
mocks.state.applications = [application, ...mocks.state.applications];
|
||||
payload = buildApplicationSubmitResponsePayload(application);
|
||||
break;
|
||||
}
|
||||
case "lobby.invite.redeem": {
|
||||
const redeemMod = await import("../../src/proto/galaxy/fbs/lobby");
|
||||
const decoded = redeemMod.InviteRedeemRequest.getRootAsInviteRedeemRequest(
|
||||
new ByteBuffer(req.payloadBytes),
|
||||
);
|
||||
const gameId = decoded.gameId() ?? "";
|
||||
const inviteId = decoded.inviteId() ?? "";
|
||||
mocks.inviteRedeemCalls.push({ gameId, inviteId });
|
||||
const original = mocks.state.invitations.find((i) => i.inviteId === inviteId);
|
||||
const invite: InviteFixture = {
|
||||
...(original ?? {
|
||||
inviteId,
|
||||
gameId,
|
||||
inviterUserId: "user-host",
|
||||
invitedUserId: "user-1",
|
||||
raceName: "",
|
||||
}),
|
||||
status: "accepted",
|
||||
decidedAtMs: BigInt(Date.now()),
|
||||
};
|
||||
mocks.state.invitations = mocks.state.invitations.filter(
|
||||
(i) => i.inviteId !== inviteId,
|
||||
);
|
||||
const newGame: GameFixture = {
|
||||
gameId,
|
||||
gameName: "Invited Game",
|
||||
gameType: "private",
|
||||
status: "enrollment_open",
|
||||
ownerUserId: "user-host",
|
||||
minPlayers: 2,
|
||||
maxPlayers: 8,
|
||||
enrollmentEndsAtMs: BigInt(Date.now() + 1_000_000),
|
||||
};
|
||||
mocks.state.myGames = [...mocks.state.myGames, newGame];
|
||||
payload = buildInviteRedeemResponsePayload(invite);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
resultCode = "internal_error";
|
||||
payload = new Uint8Array();
|
||||
break;
|
||||
}
|
||||
|
||||
const responseJson = await forgeExecuteCommandResponseJson({
|
||||
requestId: req.requestId,
|
||||
timestampMs: BigInt(Date.now()),
|
||||
resultCode,
|
||||
payloadBytes: payload,
|
||||
});
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: responseJson,
|
||||
});
|
||||
});
|
||||
|
||||
await page.route(
|
||||
"**/galaxy.gateway.v1.EdgeGateway/SubscribeEvents",
|
||||
async (route) => {
|
||||
const action = await new Promise<"endOfStream" | "abort">((resolve) => {
|
||||
mocks.pendingSubscribes.push(() => resolve("endOfStream"));
|
||||
});
|
||||
if (action === "abort") {
|
||||
await route.abort();
|
||||
return;
|
||||
}
|
||||
const body = new TextEncoder().encode("{}");
|
||||
const frame = new Uint8Array(5 + body.length);
|
||||
frame[0] = 0x02;
|
||||
new DataView(frame.buffer).setUint32(1, body.length, false);
|
||||
frame.set(body, 5);
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/connect+json",
|
||||
body: Buffer.from(frame),
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
return mocks;
|
||||
}
|
||||
|
||||
async function completeLogin(page: Page): Promise<void> {
|
||||
await page.goto("/");
|
||||
await expect(page).toHaveURL(/\/login$/);
|
||||
// The login page renders the inputs `readonly` as a Safari
|
||||
// autofill-suppression workaround; the readonly attribute is
|
||||
// dropped on first focus. Playwright's `fill()` checks editability
|
||||
// before its own focus call, so emulate the user gesture explicitly:
|
||||
// click the input (focus → readonly drops), then fill.
|
||||
await page.getByTestId("login-email-input").click();
|
||||
await page.getByTestId("login-email-input").fill("pilot@example.com");
|
||||
await page.getByTestId("login-email-submit").click();
|
||||
await expect(page.getByTestId("login-code-input")).toBeVisible();
|
||||
await page.getByTestId("login-code-input").click();
|
||||
await page.getByTestId("login-code-input").fill("123456");
|
||||
await page.getByTestId("login-code-submit").click();
|
||||
await expect(page).toHaveURL(/\/lobby$/);
|
||||
}
|
||||
|
||||
test.describe("Phase 8 — lobby flow", () => {
|
||||
test("create-game flow lands the new game in My Games", async ({ page }) => {
|
||||
const mocks = await mockGateway(page);
|
||||
await completeLogin(page);
|
||||
|
||||
await expect(page.getByTestId("lobby-my-games-empty")).toBeVisible();
|
||||
await expect(page.getByTestId("lobby-public-games-empty")).toBeVisible();
|
||||
|
||||
await page.getByTestId("lobby-create-button").click();
|
||||
await expect(page).toHaveURL(/\/lobby\/create$/);
|
||||
|
||||
await page.getByTestId("lobby-create-game-name").click();
|
||||
await page.getByTestId("lobby-create-game-name").fill("First Contact");
|
||||
await page.getByTestId("lobby-create-turn-schedule").click();
|
||||
await page.getByTestId("lobby-create-turn-schedule").fill("0 0 * * *");
|
||||
await page
|
||||
.getByTestId("lobby-create-enrollment-ends-at")
|
||||
.fill("2026-06-01T12:00");
|
||||
await page.getByTestId("lobby-create-submit").click();
|
||||
|
||||
await expect(page).toHaveURL(/\/lobby$/);
|
||||
await expect(page.getByTestId("lobby-my-game-card")).toContainText("First Contact");
|
||||
expect(mocks.createGameCalls.length).toBe(1);
|
||||
expect(mocks.createGameCalls[0]!.gameName).toBe("First Contact");
|
||||
|
||||
mocks.pendingSubscribes.forEach((resolve) => resolve());
|
||||
});
|
||||
|
||||
test("submitting an application produces a pending applications card", async ({
|
||||
page,
|
||||
}) => {
|
||||
const mocks = await mockGateway(page, {
|
||||
publicGames: [
|
||||
{
|
||||
gameId: "public-1",
|
||||
gameName: "Open Lobby",
|
||||
gameType: "public",
|
||||
status: "enrollment_open",
|
||||
},
|
||||
],
|
||||
});
|
||||
await completeLogin(page);
|
||||
|
||||
await expect(page.getByTestId("lobby-public-game-apply")).toBeVisible();
|
||||
await page.getByTestId("lobby-public-game-apply").click();
|
||||
await page
|
||||
.getByTestId("lobby-application-race-name")
|
||||
.fill("Vegan Federation");
|
||||
await page.getByTestId("lobby-application-submit").click();
|
||||
|
||||
await expect(page.getByTestId("lobby-application-card")).toBeVisible();
|
||||
expect(mocks.applicationSubmitCalls).toEqual([
|
||||
{ gameId: "public-1", raceName: "Vegan Federation" },
|
||||
]);
|
||||
|
||||
mocks.pendingSubscribes.forEach((resolve) => resolve());
|
||||
});
|
||||
|
||||
test("accepting an invitation removes it and adds the game to My Games", async ({
|
||||
page,
|
||||
}) => {
|
||||
const mocks = await mockGateway(page, {
|
||||
invitations: [
|
||||
{
|
||||
inviteId: "invite-1",
|
||||
gameId: "private-1",
|
||||
inviterUserId: "user-host",
|
||||
invitedUserId: "user-1",
|
||||
raceName: "Vegan Federation",
|
||||
status: "pending",
|
||||
},
|
||||
],
|
||||
});
|
||||
await completeLogin(page);
|
||||
|
||||
await expect(page.getByTestId("lobby-invite-accept")).toBeVisible();
|
||||
await page.getByTestId("lobby-invite-accept").click();
|
||||
|
||||
await expect(page.getByTestId("lobby-invite-accept")).toBeHidden();
|
||||
await expect(page.getByTestId("lobby-my-game-card")).toContainText("Invited Game");
|
||||
expect(mocks.inviteRedeemCalls).toEqual([
|
||||
{ gameId: "private-1", inviteId: "invite-1" },
|
||||
]);
|
||||
|
||||
mocks.pendingSubscribes.forEach((resolve) => resolve());
|
||||
});
|
||||
});
|
||||
@@ -83,7 +83,8 @@ describe("GalaxyClient.executeCommand", () => {
|
||||
new TextEncoder().encode("client-payload"),
|
||||
);
|
||||
|
||||
expect(Array.from(out)).toEqual(Array.from(responsePayload));
|
||||
expect(out.resultCode).toBe("ok");
|
||||
expect(Array.from(out.payloadBytes)).toEqual(Array.from(responsePayload));
|
||||
expect(signer).toHaveBeenCalledWith(canonicalBytes);
|
||||
expect(sha256).toHaveBeenCalledTimes(1);
|
||||
expect(core.signRequest).toHaveBeenCalledTimes(1);
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
// Unit tests for the typed lobby.ts wrappers. They invoke the
|
||||
// wrappers against a minimal stub of `GalaxyClient.executeCommand`
|
||||
// that captures the message type and FlatBuffers request payload,
|
||||
// then returns a forged FlatBuffers response payload built with the
|
||||
// generated TS bindings. No network, no signing — the test confirms
|
||||
// the encoder/decoder shape matches the gateway contract and that
|
||||
// non-`ok` result codes are surfaced as a `LobbyError`.
|
||||
|
||||
import { Builder, ByteBuffer } from "flatbuffers";
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
|
||||
import {
|
||||
LobbyError,
|
||||
createGame,
|
||||
declineInvite,
|
||||
listMyApplications,
|
||||
listMyGames,
|
||||
listMyInvites,
|
||||
listPublicGames,
|
||||
redeemInvite,
|
||||
submitApplication,
|
||||
} from "../src/api/lobby";
|
||||
import {
|
||||
ApplicationSubmitResponse,
|
||||
ApplicationSummary,
|
||||
ErrorBody,
|
||||
ErrorResponse,
|
||||
GameCreateResponse,
|
||||
GameSummary,
|
||||
InviteDeclineResponse,
|
||||
InviteRedeemResponse,
|
||||
InviteSummary,
|
||||
MyApplicationsListResponse,
|
||||
MyGamesListResponse,
|
||||
MyInvitesListResponse,
|
||||
PublicGamesListResponse,
|
||||
} from "../src/proto/galaxy/fbs/lobby";
|
||||
import type { GalaxyClient } from "../src/api/galaxy-client";
|
||||
import {
|
||||
GameCreateRequest,
|
||||
PublicGamesListRequest,
|
||||
ApplicationSubmitRequest,
|
||||
InviteRedeemRequest,
|
||||
InviteDeclineRequest,
|
||||
} from "../src/proto/galaxy/fbs/lobby";
|
||||
|
||||
interface Captured {
|
||||
messageType: string;
|
||||
payload: Uint8Array;
|
||||
}
|
||||
|
||||
function makeStub(
|
||||
respondWith: (c: Captured) => { resultCode?: string; payloadBytes: Uint8Array },
|
||||
): {
|
||||
client: GalaxyClient;
|
||||
captured: Captured[];
|
||||
} {
|
||||
const captured: Captured[] = [];
|
||||
const stub = {
|
||||
executeCommand: vi.fn(async (messageType: string, payload: Uint8Array) => {
|
||||
const c = { messageType, payload };
|
||||
captured.push(c);
|
||||
const result = respondWith(c);
|
||||
return {
|
||||
resultCode: result.resultCode ?? "ok",
|
||||
payloadBytes: result.payloadBytes,
|
||||
};
|
||||
}),
|
||||
} as unknown as GalaxyClient;
|
||||
return { client: stub, captured };
|
||||
}
|
||||
|
||||
function encodeGameSummary(builder: Builder): number {
|
||||
const gameId = builder.createString("g-1");
|
||||
const gameName = builder.createString("Test Game");
|
||||
const gameType = builder.createString("private");
|
||||
const status = builder.createString("draft");
|
||||
const ownerUserId = builder.createString("user-1");
|
||||
GameSummary.startGameSummary(builder);
|
||||
GameSummary.addGameId(builder, gameId);
|
||||
GameSummary.addGameName(builder, gameName);
|
||||
GameSummary.addGameType(builder, gameType);
|
||||
GameSummary.addStatus(builder, status);
|
||||
GameSummary.addOwnerUserId(builder, ownerUserId);
|
||||
GameSummary.addMinPlayers(builder, 2);
|
||||
GameSummary.addMaxPlayers(builder, 8);
|
||||
GameSummary.addEnrollmentEndsAtMs(builder, 1_780_000_000_000n);
|
||||
GameSummary.addCreatedAtMs(builder, 1_770_000_000_000n);
|
||||
GameSummary.addUpdatedAtMs(builder, 1_770_000_000_000n);
|
||||
return GameSummary.endGameSummary(builder);
|
||||
}
|
||||
|
||||
function encodeApplicationSummary(builder: Builder, status: string): number {
|
||||
const applicationId = builder.createString("app-1");
|
||||
const gameId = builder.createString("g-1");
|
||||
const applicantUserId = builder.createString("user-1");
|
||||
const raceName = builder.createString("Vegan Federation");
|
||||
const statusOff = builder.createString(status);
|
||||
ApplicationSummary.startApplicationSummary(builder);
|
||||
ApplicationSummary.addApplicationId(builder, applicationId);
|
||||
ApplicationSummary.addGameId(builder, gameId);
|
||||
ApplicationSummary.addApplicantUserId(builder, applicantUserId);
|
||||
ApplicationSummary.addRaceName(builder, raceName);
|
||||
ApplicationSummary.addStatus(builder, statusOff);
|
||||
ApplicationSummary.addCreatedAtMs(builder, 1_770_000_000_000n);
|
||||
ApplicationSummary.addDecidedAtMs(builder, status === "pending" ? 0n : 1_770_010_000_000n);
|
||||
return ApplicationSummary.endApplicationSummary(builder);
|
||||
}
|
||||
|
||||
function encodeInviteSummary(builder: Builder, status: string): number {
|
||||
const inviteId = builder.createString("invite-1");
|
||||
const gameId = builder.createString("g-1");
|
||||
const inviter = builder.createString("user-host");
|
||||
const invited = builder.createString("user-1");
|
||||
const code = builder.createString("");
|
||||
const race = builder.createString("Vegan Federation");
|
||||
const statusOff = builder.createString(status);
|
||||
InviteSummary.startInviteSummary(builder);
|
||||
InviteSummary.addInviteId(builder, inviteId);
|
||||
InviteSummary.addGameId(builder, gameId);
|
||||
InviteSummary.addInviterUserId(builder, inviter);
|
||||
InviteSummary.addInvitedUserId(builder, invited);
|
||||
InviteSummary.addCode(builder, code);
|
||||
InviteSummary.addRaceName(builder, race);
|
||||
InviteSummary.addStatus(builder, statusOff);
|
||||
InviteSummary.addCreatedAtMs(builder, 1_770_000_000_000n);
|
||||
InviteSummary.addExpiresAtMs(builder, 1_780_000_000_000n);
|
||||
InviteSummary.addDecidedAtMs(builder, status === "pending" ? 0n : 1_770_010_000_000n);
|
||||
return InviteSummary.endInviteSummary(builder);
|
||||
}
|
||||
|
||||
describe("lobby.ts wrappers", () => {
|
||||
test("listMyGames decodes the response and reports the message type", async () => {
|
||||
const { client, captured } = makeStub(() => {
|
||||
const builder = new Builder(256);
|
||||
const item = encodeGameSummary(builder);
|
||||
const items = MyGamesListResponse.createItemsVector(builder, [item]);
|
||||
MyGamesListResponse.startMyGamesListResponse(builder);
|
||||
MyGamesListResponse.addItems(builder, items);
|
||||
builder.finish(MyGamesListResponse.endMyGamesListResponse(builder));
|
||||
return { payloadBytes: builder.asUint8Array() };
|
||||
});
|
||||
|
||||
const games = await listMyGames(client);
|
||||
expect(captured[0]!.messageType).toBe("lobby.my.games.list");
|
||||
expect(games.length).toBe(1);
|
||||
expect(games[0]!.gameId).toBe("g-1");
|
||||
expect(games[0]!.minPlayers).toBe(2);
|
||||
});
|
||||
|
||||
test("listPublicGames passes pagination and decodes pageSize/total", async () => {
|
||||
const { client, captured } = makeStub(() => {
|
||||
const builder = new Builder(256);
|
||||
const item = encodeGameSummary(builder);
|
||||
const items = PublicGamesListResponse.createItemsVector(builder, [item]);
|
||||
PublicGamesListResponse.startPublicGamesListResponse(builder);
|
||||
PublicGamesListResponse.addItems(builder, items);
|
||||
PublicGamesListResponse.addPage(builder, 2);
|
||||
PublicGamesListResponse.addPageSize(builder, 25);
|
||||
PublicGamesListResponse.addTotal(builder, 51);
|
||||
builder.finish(PublicGamesListResponse.endPublicGamesListResponse(builder));
|
||||
return { payloadBytes: builder.asUint8Array() };
|
||||
});
|
||||
|
||||
const page = await listPublicGames(client, { page: 2, pageSize: 25 });
|
||||
expect(captured[0]!.messageType).toBe("lobby.public.games.list");
|
||||
const decodedRequest = PublicGamesListRequest.getRootAsPublicGamesListRequest(
|
||||
new ByteBuffer(captured[0]!.payload),
|
||||
);
|
||||
expect(decodedRequest.page()).toBe(2);
|
||||
expect(decodedRequest.pageSize()).toBe(25);
|
||||
|
||||
expect(page.items.length).toBe(1);
|
||||
expect(page.page).toBe(2);
|
||||
expect(page.pageSize).toBe(25);
|
||||
expect(page.total).toBe(51);
|
||||
});
|
||||
|
||||
test("listMyApplications decodes pending and decided records", async () => {
|
||||
const { client } = makeStub(() => {
|
||||
const builder = new Builder(256);
|
||||
const pending = encodeApplicationSummary(builder, "pending");
|
||||
const approved = encodeApplicationSummary(builder, "approved");
|
||||
const items = MyApplicationsListResponse.createItemsVector(builder, [pending, approved]);
|
||||
MyApplicationsListResponse.startMyApplicationsListResponse(builder);
|
||||
MyApplicationsListResponse.addItems(builder, items);
|
||||
builder.finish(MyApplicationsListResponse.endMyApplicationsListResponse(builder));
|
||||
return { payloadBytes: builder.asUint8Array() };
|
||||
});
|
||||
|
||||
const applications = await listMyApplications(client);
|
||||
expect(applications.length).toBe(2);
|
||||
expect(applications[0]!.status).toBe("pending");
|
||||
expect(applications[0]!.decidedAt).toBeNull();
|
||||
expect(applications[1]!.status).toBe("approved");
|
||||
expect(applications[1]!.decidedAt).not.toBeNull();
|
||||
});
|
||||
|
||||
test("listMyInvites decodes user-bound invites", async () => {
|
||||
const { client } = makeStub(() => {
|
||||
const builder = new Builder(256);
|
||||
const invite = encodeInviteSummary(builder, "pending");
|
||||
const items = MyInvitesListResponse.createItemsVector(builder, [invite]);
|
||||
MyInvitesListResponse.startMyInvitesListResponse(builder);
|
||||
MyInvitesListResponse.addItems(builder, items);
|
||||
builder.finish(MyInvitesListResponse.endMyInvitesListResponse(builder));
|
||||
return { payloadBytes: builder.asUint8Array() };
|
||||
});
|
||||
|
||||
const invites = await listMyInvites(client);
|
||||
expect(invites.length).toBe(1);
|
||||
expect(invites[0]!.invitedUserId).toBe("user-1");
|
||||
expect(invites[0]!.status).toBe("pending");
|
||||
expect(invites[0]!.decidedAt).toBeNull();
|
||||
});
|
||||
|
||||
test("createGame encodes every field and decodes the returned summary", async () => {
|
||||
const { client, captured } = makeStub(() => {
|
||||
const builder = new Builder(256);
|
||||
const game = encodeGameSummary(builder);
|
||||
GameCreateResponse.startGameCreateResponse(builder);
|
||||
GameCreateResponse.addGame(builder, game);
|
||||
builder.finish(GameCreateResponse.endGameCreateResponse(builder));
|
||||
return { payloadBytes: builder.asUint8Array() };
|
||||
});
|
||||
|
||||
const enrollment = new Date(1_780_000_000_000);
|
||||
const result = await createGame(client, {
|
||||
gameName: "First Contact",
|
||||
description: "",
|
||||
minPlayers: 2,
|
||||
maxPlayers: 8,
|
||||
startGapHours: 24,
|
||||
startGapPlayers: 2,
|
||||
enrollmentEndsAt: enrollment,
|
||||
turnSchedule: "0 0 * * *",
|
||||
targetEngineVersion: "v1",
|
||||
});
|
||||
|
||||
expect(captured[0]!.messageType).toBe("lobby.game.create");
|
||||
const request = GameCreateRequest.getRootAsGameCreateRequest(
|
||||
new ByteBuffer(captured[0]!.payload),
|
||||
);
|
||||
expect(request.gameName()).toBe("First Contact");
|
||||
expect(request.turnSchedule()).toBe("0 0 * * *");
|
||||
expect(request.targetEngineVersion()).toBe("v1");
|
||||
expect(request.minPlayers()).toBe(2);
|
||||
expect(request.maxPlayers()).toBe(8);
|
||||
expect(request.enrollmentEndsAtMs()).toBe(BigInt(enrollment.getTime()));
|
||||
|
||||
expect(result.gameId).toBe("g-1");
|
||||
});
|
||||
|
||||
test("submitApplication encodes game_id and race_name", async () => {
|
||||
const { client, captured } = makeStub(() => {
|
||||
const builder = new Builder(128);
|
||||
const app = encodeApplicationSummary(builder, "pending");
|
||||
ApplicationSubmitResponse.startApplicationSubmitResponse(builder);
|
||||
ApplicationSubmitResponse.addApplication(builder, app);
|
||||
builder.finish(ApplicationSubmitResponse.endApplicationSubmitResponse(builder));
|
||||
return { payloadBytes: builder.asUint8Array() };
|
||||
});
|
||||
|
||||
const submitted = await submitApplication(client, "public-1", "Vegan Federation");
|
||||
expect(captured[0]!.messageType).toBe("lobby.application.submit");
|
||||
const decoded = ApplicationSubmitRequest.getRootAsApplicationSubmitRequest(
|
||||
new ByteBuffer(captured[0]!.payload),
|
||||
);
|
||||
expect(decoded.gameId()).toBe("public-1");
|
||||
expect(decoded.raceName()).toBe("Vegan Federation");
|
||||
expect(submitted.applicationId).toBe("app-1");
|
||||
});
|
||||
|
||||
test("redeemInvite and declineInvite hit their respective message types", async () => {
|
||||
const stubRedeem = makeStub(() => {
|
||||
const builder = new Builder(128);
|
||||
const invite = encodeInviteSummary(builder, "accepted");
|
||||
InviteRedeemResponse.startInviteRedeemResponse(builder);
|
||||
InviteRedeemResponse.addInvite(builder, invite);
|
||||
builder.finish(InviteRedeemResponse.endInviteRedeemResponse(builder));
|
||||
return { payloadBytes: builder.asUint8Array() };
|
||||
});
|
||||
const redeemed = await redeemInvite(stubRedeem.client, "private-1", "invite-1");
|
||||
expect(stubRedeem.captured[0]!.messageType).toBe("lobby.invite.redeem");
|
||||
const redeemReq = InviteRedeemRequest.getRootAsInviteRedeemRequest(
|
||||
new ByteBuffer(stubRedeem.captured[0]!.payload),
|
||||
);
|
||||
expect(redeemReq.gameId()).toBe("private-1");
|
||||
expect(redeemReq.inviteId()).toBe("invite-1");
|
||||
expect(redeemed.status).toBe("accepted");
|
||||
|
||||
const stubDecline = makeStub(() => {
|
||||
const builder = new Builder(128);
|
||||
const invite = encodeInviteSummary(builder, "declined");
|
||||
InviteDeclineResponse.startInviteDeclineResponse(builder);
|
||||
InviteDeclineResponse.addInvite(builder, invite);
|
||||
builder.finish(InviteDeclineResponse.endInviteDeclineResponse(builder));
|
||||
return { payloadBytes: builder.asUint8Array() };
|
||||
});
|
||||
const declined = await declineInvite(stubDecline.client, "private-1", "invite-1");
|
||||
expect(stubDecline.captured[0]!.messageType).toBe("lobby.invite.decline");
|
||||
const declineReq = InviteDeclineRequest.getRootAsInviteDeclineRequest(
|
||||
new ByteBuffer(stubDecline.captured[0]!.payload),
|
||||
);
|
||||
expect(declineReq.gameId()).toBe("private-1");
|
||||
expect(declineReq.inviteId()).toBe("invite-1");
|
||||
expect(declined.status).toBe("declined");
|
||||
});
|
||||
|
||||
test("non-ok result codes are surfaced as a LobbyError with code and message", async () => {
|
||||
const { client } = makeStub(() => {
|
||||
const builder = new Builder(128);
|
||||
const code = builder.createString("conflict");
|
||||
const message = builder.createString("game is not in enrollment_open");
|
||||
ErrorBody.startErrorBody(builder);
|
||||
ErrorBody.addCode(builder, code);
|
||||
ErrorBody.addMessage(builder, message);
|
||||
const errorOff = ErrorBody.endErrorBody(builder);
|
||||
ErrorResponse.startErrorResponse(builder);
|
||||
ErrorResponse.addError(builder, errorOff);
|
||||
builder.finish(ErrorResponse.endErrorResponse(builder));
|
||||
return { resultCode: "conflict", payloadBytes: builder.asUint8Array() };
|
||||
});
|
||||
|
||||
await expect(submitApplication(client, "public-1", "race")).rejects.toThrow(LobbyError);
|
||||
try {
|
||||
await submitApplication(client, "public-1", "race");
|
||||
} catch (err) {
|
||||
const lobbyError = err as LobbyError;
|
||||
expect(lobbyError.code).toBe("conflict");
|
||||
expect(lobbyError.message).toBe("game is not in enrollment_open");
|
||||
expect(lobbyError.resultCode).toBe("conflict");
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,195 @@
|
||||
// Component tests for the create-game form. The lobby API is mocked
|
||||
// at module level; the GalaxyClient is replaced with a stub that does
|
||||
// nothing (the test only asserts the createGame wrapper is invoked
|
||||
// with the right shape).
|
||||
|
||||
import "fake-indexeddb/auto";
|
||||
import { fireEvent, render, waitFor } from "@testing-library/svelte";
|
||||
import {
|
||||
afterEach,
|
||||
beforeEach,
|
||||
describe,
|
||||
expect,
|
||||
test,
|
||||
vi,
|
||||
} from "vitest";
|
||||
import type { IDBPDatabase } from "idb";
|
||||
|
||||
import { i18n } from "../src/lib/i18n/index.svelte";
|
||||
import { session } from "../src/lib/session-store.svelte";
|
||||
import { type GalaxyDB, openGalaxyDB } from "../src/platform/store/idb";
|
||||
import { IDBCache } from "../src/platform/store/idb-cache";
|
||||
import { WebCryptoKeyStore } from "../src/platform/store/webcrypto-keystore";
|
||||
|
||||
const gotoSpy = vi.fn<(url: string) => Promise<void>>(async () => {});
|
||||
vi.mock("$app/navigation", () => ({
|
||||
goto: (url: string) => gotoSpy(url),
|
||||
}));
|
||||
|
||||
const createGameSpy = vi.fn();
|
||||
vi.mock("../src/api/lobby", async () => {
|
||||
const actual = await vi.importActual<typeof import("../src/api/lobby")>(
|
||||
"../src/api/lobby",
|
||||
);
|
||||
return {
|
||||
...actual,
|
||||
createGame: (...args: unknown[]) => createGameSpy(...args),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../src/lib/env", () => ({
|
||||
GATEWAY_BASE_URL: "http://gateway.test",
|
||||
GATEWAY_RESPONSE_PUBLIC_KEY: new Uint8Array(32).fill(0x55),
|
||||
}));
|
||||
|
||||
vi.mock("../src/api/connect", () => ({
|
||||
createEdgeGatewayClient: vi.fn(() => ({})),
|
||||
}));
|
||||
|
||||
vi.mock("../src/api/galaxy-client", () => {
|
||||
class FakeGalaxyClient {
|
||||
executeCommand = vi.fn(async () => ({
|
||||
resultCode: "ok",
|
||||
payloadBytes: new Uint8Array(),
|
||||
}));
|
||||
}
|
||||
return { GalaxyClient: FakeGalaxyClient };
|
||||
});
|
||||
|
||||
vi.mock("../src/platform/core/index", () => ({
|
||||
loadCore: async () => ({
|
||||
signRequest: () => new Uint8Array(),
|
||||
verifyResponse: () => true,
|
||||
verifyEvent: () => true,
|
||||
verifyPayloadHash: () => true,
|
||||
}),
|
||||
}));
|
||||
|
||||
let db: IDBPDatabase<GalaxyDB>;
|
||||
let dbName: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
dbName = `galaxy-ui-test-${crypto.randomUUID()}`;
|
||||
db = await openGalaxyDB(dbName);
|
||||
const store = {
|
||||
keyStore: new WebCryptoKeyStore(db),
|
||||
cache: new IDBCache(db),
|
||||
};
|
||||
session.resetForTests();
|
||||
session.setStoreLoaderForTests(async () => store);
|
||||
await session.init();
|
||||
await session.signIn("device-1");
|
||||
i18n.resetForTests("en");
|
||||
createGameSpy.mockReset();
|
||||
gotoSpy.mockReset();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
session.resetForTests();
|
||||
i18n.resetForTests("en");
|
||||
db.close();
|
||||
await new Promise<void>((resolve) => {
|
||||
const req = indexedDB.deleteDatabase(dbName);
|
||||
req.onsuccess = () => resolve();
|
||||
req.onerror = () => resolve();
|
||||
req.onblocked = () => resolve();
|
||||
});
|
||||
});
|
||||
|
||||
async function importCreatePage(): Promise<typeof import("../src/routes/lobby/create/+page.svelte")> {
|
||||
return import("../src/routes/lobby/create/+page.svelte");
|
||||
}
|
||||
|
||||
describe("lobby/create page", () => {
|
||||
test("submitting a valid form invokes createGame with the entered values and navigates back", async () => {
|
||||
createGameSpy.mockResolvedValue({
|
||||
gameId: "private-new",
|
||||
gameName: "First Contact",
|
||||
gameType: "private",
|
||||
status: "draft",
|
||||
ownerUserId: "user-1",
|
||||
minPlayers: 2,
|
||||
maxPlayers: 8,
|
||||
enrollmentEndsAt: new Date(),
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
});
|
||||
|
||||
const Page = (await importCreatePage()).default;
|
||||
const ui = render(Page);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(ui.getByTestId("lobby-create-form")).toBeInTheDocument(),
|
||||
);
|
||||
|
||||
await fireEvent.input(ui.getByTestId("lobby-create-game-name"), {
|
||||
target: { value: "First Contact" },
|
||||
});
|
||||
await fireEvent.input(ui.getByTestId("lobby-create-description"), {
|
||||
target: { value: "" },
|
||||
});
|
||||
await fireEvent.input(ui.getByTestId("lobby-create-turn-schedule"), {
|
||||
target: { value: "0 0 * * *" },
|
||||
});
|
||||
await fireEvent.input(ui.getByTestId("lobby-create-enrollment-ends-at"), {
|
||||
target: { value: "2026-06-01T12:00" },
|
||||
});
|
||||
|
||||
await fireEvent.click(ui.getByTestId("lobby-create-submit"));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(createGameSpy).toHaveBeenCalledTimes(1);
|
||||
const call = createGameSpy.mock.calls[0]!;
|
||||
const input = call[1] as Record<string, unknown>;
|
||||
expect(input.gameName).toBe("First Contact");
|
||||
expect(input.turnSchedule).toBe("0 0 * * *");
|
||||
expect(input.minPlayers).toBe(2);
|
||||
expect(input.maxPlayers).toBe(8);
|
||||
expect(input.startGapHours).toBe(24);
|
||||
expect(input.startGapPlayers).toBe(2);
|
||||
expect(input.targetEngineVersion).toBe("v1");
|
||||
expect(input.enrollmentEndsAt).toBeInstanceOf(Date);
|
||||
expect(gotoSpy).toHaveBeenCalledWith("/lobby");
|
||||
});
|
||||
});
|
||||
|
||||
test("submitting with an empty game name surfaces a validation error and does not call the API", async () => {
|
||||
const Page = (await importCreatePage()).default;
|
||||
const ui = render(Page);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(ui.getByTestId("lobby-create-form")).toBeInTheDocument(),
|
||||
);
|
||||
|
||||
// turn_schedule starts populated with the default; clear game_name to trigger the error
|
||||
await fireEvent.input(ui.getByTestId("lobby-create-game-name"), {
|
||||
target: { value: " " },
|
||||
});
|
||||
await fireEvent.input(ui.getByTestId("lobby-create-enrollment-ends-at"), {
|
||||
target: { value: "2026-06-01T12:00" },
|
||||
});
|
||||
await fireEvent.click(ui.getByTestId("lobby-create-submit"));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(ui.getByTestId("lobby-create-error")).toHaveTextContent(
|
||||
"game name must not be empty",
|
||||
);
|
||||
expect(createGameSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
test("cancel button navigates back to /lobby without calling the API", async () => {
|
||||
const Page = (await importCreatePage()).default;
|
||||
const ui = render(Page);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(ui.getByTestId("lobby-create-cancel")).toBeInTheDocument(),
|
||||
);
|
||||
await fireEvent.click(ui.getByTestId("lobby-create-cancel"));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(gotoSpy).toHaveBeenCalledWith("/lobby");
|
||||
expect(createGameSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,494 @@
|
||||
// Round-trip tests for the generated TS FlatBuffers bindings under
|
||||
// `src/proto/galaxy/fbs/lobby/`. These guard against codegen drift —
|
||||
// if the wire schema and the bindings disagree, the round-trip fails
|
||||
// instead of letting a broken binding ship silently.
|
||||
|
||||
import { Builder, ByteBuffer } from "flatbuffers";
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import {
|
||||
ApplicationSubmitRequest,
|
||||
ApplicationSubmitResponse,
|
||||
ApplicationSummary,
|
||||
ErrorBody,
|
||||
ErrorResponse,
|
||||
GameCreateRequest,
|
||||
GameCreateResponse,
|
||||
GameSummary,
|
||||
InviteDeclineRequest,
|
||||
InviteDeclineResponse,
|
||||
InviteRedeemRequest,
|
||||
InviteRedeemResponse,
|
||||
InviteSummary,
|
||||
MyApplicationsListRequest,
|
||||
MyApplicationsListResponse,
|
||||
MyGamesListRequest,
|
||||
MyGamesListResponse,
|
||||
MyInvitesListRequest,
|
||||
MyInvitesListResponse,
|
||||
OpenEnrollmentRequest,
|
||||
OpenEnrollmentResponse,
|
||||
PublicGamesListRequest,
|
||||
PublicGamesListResponse,
|
||||
} from "../src/proto/galaxy/fbs/lobby";
|
||||
|
||||
interface GameSummaryFixture {
|
||||
gameId: string;
|
||||
gameName: string;
|
||||
gameType: string;
|
||||
status: string;
|
||||
ownerUserId: string;
|
||||
minPlayers: number;
|
||||
maxPlayers: number;
|
||||
enrollmentEndsAtMs: bigint;
|
||||
createdAtMs: bigint;
|
||||
updatedAtMs: bigint;
|
||||
}
|
||||
|
||||
const PRIVATE_GAME: GameSummaryFixture = {
|
||||
gameId: "game-private-7c8f",
|
||||
gameName: "First Contact",
|
||||
gameType: "private",
|
||||
status: "draft",
|
||||
ownerUserId: "user-9912",
|
||||
minPlayers: 2,
|
||||
maxPlayers: 8,
|
||||
enrollmentEndsAtMs: 1_780_000_000_000n,
|
||||
createdAtMs: 1_770_000_000_000n,
|
||||
updatedAtMs: 1_770_000_300_000n,
|
||||
};
|
||||
|
||||
const PUBLIC_GAME: GameSummaryFixture = {
|
||||
gameId: "game-public-aabb",
|
||||
gameName: "Open Lobby",
|
||||
gameType: "public",
|
||||
status: "enrollment_open",
|
||||
ownerUserId: "",
|
||||
minPlayers: 4,
|
||||
maxPlayers: 12,
|
||||
enrollmentEndsAtMs: 1_780_500_000_000n,
|
||||
createdAtMs: 1_770_500_000_000n,
|
||||
updatedAtMs: 1_770_600_000_000n,
|
||||
};
|
||||
|
||||
function encodeGameSummary(builder: Builder, value: GameSummaryFixture): number {
|
||||
const gameId = builder.createString(value.gameId);
|
||||
const gameName = builder.createString(value.gameName);
|
||||
const gameType = builder.createString(value.gameType);
|
||||
const status = builder.createString(value.status);
|
||||
const ownerUserId = builder.createString(value.ownerUserId);
|
||||
GameSummary.startGameSummary(builder);
|
||||
GameSummary.addGameId(builder, gameId);
|
||||
GameSummary.addGameName(builder, gameName);
|
||||
GameSummary.addGameType(builder, gameType);
|
||||
GameSummary.addStatus(builder, status);
|
||||
GameSummary.addOwnerUserId(builder, ownerUserId);
|
||||
GameSummary.addMinPlayers(builder, value.minPlayers);
|
||||
GameSummary.addMaxPlayers(builder, value.maxPlayers);
|
||||
GameSummary.addEnrollmentEndsAtMs(builder, value.enrollmentEndsAtMs);
|
||||
GameSummary.addCreatedAtMs(builder, value.createdAtMs);
|
||||
GameSummary.addUpdatedAtMs(builder, value.updatedAtMs);
|
||||
return GameSummary.endGameSummary(builder);
|
||||
}
|
||||
|
||||
function expectGameSummary(actual: GameSummary | null, want: GameSummaryFixture): void {
|
||||
expect(actual).not.toBeNull();
|
||||
const got = actual!;
|
||||
expect(got.gameId()).toBe(want.gameId);
|
||||
expect(got.gameName()).toBe(want.gameName);
|
||||
expect(got.gameType()).toBe(want.gameType);
|
||||
expect(got.status()).toBe(want.status);
|
||||
expect(got.ownerUserId()).toBe(want.ownerUserId);
|
||||
expect(got.minPlayers()).toBe(want.minPlayers);
|
||||
expect(got.maxPlayers()).toBe(want.maxPlayers);
|
||||
expect(got.enrollmentEndsAtMs()).toBe(want.enrollmentEndsAtMs);
|
||||
expect(got.createdAtMs()).toBe(want.createdAtMs);
|
||||
expect(got.updatedAtMs()).toBe(want.updatedAtMs);
|
||||
}
|
||||
|
||||
describe("lobby FlatBuffers TS bindings", () => {
|
||||
test("MyGamesListRequest round-trips an empty body", () => {
|
||||
const builder = new Builder(32);
|
||||
MyGamesListRequest.startMyGamesListRequest(builder);
|
||||
builder.finish(MyGamesListRequest.endMyGamesListRequest(builder));
|
||||
const bytes = builder.asUint8Array();
|
||||
const decoded = MyGamesListRequest.getRootAsMyGamesListRequest(new ByteBuffer(bytes));
|
||||
expect(decoded).toBeDefined();
|
||||
});
|
||||
|
||||
test("MyGamesListResponse encodes and decodes multiple summaries", () => {
|
||||
const builder = new Builder(512);
|
||||
const item0 = encodeGameSummary(builder, PRIVATE_GAME);
|
||||
const item1 = encodeGameSummary(builder, PUBLIC_GAME);
|
||||
const items = MyGamesListResponse.createItemsVector(builder, [item0, item1]);
|
||||
MyGamesListResponse.startMyGamesListResponse(builder);
|
||||
MyGamesListResponse.addItems(builder, items);
|
||||
builder.finish(MyGamesListResponse.endMyGamesListResponse(builder));
|
||||
|
||||
const bytes = builder.asUint8Array();
|
||||
const decoded = MyGamesListResponse.getRootAsMyGamesListResponse(new ByteBuffer(bytes));
|
||||
expect(decoded.itemsLength()).toBe(2);
|
||||
expectGameSummary(decoded.items(0), PRIVATE_GAME);
|
||||
expectGameSummary(decoded.items(1), PUBLIC_GAME);
|
||||
});
|
||||
|
||||
test("PublicGamesListResponse preserves pagination metadata", () => {
|
||||
const builder = new Builder(256);
|
||||
const item = encodeGameSummary(builder, PUBLIC_GAME);
|
||||
const items = PublicGamesListResponse.createItemsVector(builder, [item]);
|
||||
PublicGamesListResponse.startPublicGamesListResponse(builder);
|
||||
PublicGamesListResponse.addItems(builder, items);
|
||||
PublicGamesListResponse.addPage(builder, 3);
|
||||
PublicGamesListResponse.addPageSize(builder, 25);
|
||||
PublicGamesListResponse.addTotal(builder, 51);
|
||||
builder.finish(PublicGamesListResponse.endPublicGamesListResponse(builder));
|
||||
const bytes = builder.asUint8Array();
|
||||
const decoded = PublicGamesListResponse.getRootAsPublicGamesListResponse(
|
||||
new ByteBuffer(bytes),
|
||||
);
|
||||
expect(decoded.itemsLength()).toBe(1);
|
||||
expectGameSummary(decoded.items(0), PUBLIC_GAME);
|
||||
expect(decoded.page()).toBe(3);
|
||||
expect(decoded.pageSize()).toBe(25);
|
||||
expect(decoded.total()).toBe(51);
|
||||
});
|
||||
|
||||
test("PublicGamesListRequest round-trips page numbers", () => {
|
||||
const builder = new Builder(32);
|
||||
PublicGamesListRequest.startPublicGamesListRequest(builder);
|
||||
PublicGamesListRequest.addPage(builder, 2);
|
||||
PublicGamesListRequest.addPageSize(builder, 10);
|
||||
builder.finish(PublicGamesListRequest.endPublicGamesListRequest(builder));
|
||||
const decoded = PublicGamesListRequest.getRootAsPublicGamesListRequest(
|
||||
new ByteBuffer(builder.asUint8Array()),
|
||||
);
|
||||
expect(decoded.page()).toBe(2);
|
||||
expect(decoded.pageSize()).toBe(10);
|
||||
});
|
||||
|
||||
test("ApplicationSummary preserves pending and decided records", () => {
|
||||
const builder = new Builder(256);
|
||||
|
||||
const pendingId = builder.createString("app-1");
|
||||
const pendingGameId = builder.createString("public-1");
|
||||
const pendingApplicant = builder.createString("user-1");
|
||||
const pendingRace = builder.createString("Vegan Federation");
|
||||
const pendingStatus = builder.createString("pending");
|
||||
ApplicationSummary.startApplicationSummary(builder);
|
||||
ApplicationSummary.addApplicationId(builder, pendingId);
|
||||
ApplicationSummary.addGameId(builder, pendingGameId);
|
||||
ApplicationSummary.addApplicantUserId(builder, pendingApplicant);
|
||||
ApplicationSummary.addRaceName(builder, pendingRace);
|
||||
ApplicationSummary.addStatus(builder, pendingStatus);
|
||||
ApplicationSummary.addCreatedAtMs(builder, 1_770_000_000_000n);
|
||||
ApplicationSummary.addDecidedAtMs(builder, 0n);
|
||||
const pending = ApplicationSummary.endApplicationSummary(builder);
|
||||
|
||||
const approvedId = builder.createString("app-2");
|
||||
const approvedGameId = builder.createString("public-2");
|
||||
const approvedApplicant = builder.createString("user-1");
|
||||
const approvedRace = builder.createString("Lithic Compact");
|
||||
const approvedStatus = builder.createString("approved");
|
||||
ApplicationSummary.startApplicationSummary(builder);
|
||||
ApplicationSummary.addApplicationId(builder, approvedId);
|
||||
ApplicationSummary.addGameId(builder, approvedGameId);
|
||||
ApplicationSummary.addApplicantUserId(builder, approvedApplicant);
|
||||
ApplicationSummary.addRaceName(builder, approvedRace);
|
||||
ApplicationSummary.addStatus(builder, approvedStatus);
|
||||
ApplicationSummary.addCreatedAtMs(builder, 1_770_000_000_000n);
|
||||
ApplicationSummary.addDecidedAtMs(builder, 1_770_010_000_000n);
|
||||
const approved = ApplicationSummary.endApplicationSummary(builder);
|
||||
|
||||
const items = MyApplicationsListResponse.createItemsVector(builder, [pending, approved]);
|
||||
MyApplicationsListResponse.startMyApplicationsListResponse(builder);
|
||||
MyApplicationsListResponse.addItems(builder, items);
|
||||
builder.finish(MyApplicationsListResponse.endMyApplicationsListResponse(builder));
|
||||
|
||||
const decoded = MyApplicationsListResponse.getRootAsMyApplicationsListResponse(
|
||||
new ByteBuffer(builder.asUint8Array()),
|
||||
);
|
||||
expect(decoded.itemsLength()).toBe(2);
|
||||
const first = decoded.items(0)!;
|
||||
expect(first.status()).toBe("pending");
|
||||
expect(first.decidedAtMs()).toBe(0n);
|
||||
const second = decoded.items(1)!;
|
||||
expect(second.status()).toBe("approved");
|
||||
expect(second.decidedAtMs()).toBe(1_770_010_000_000n);
|
||||
});
|
||||
|
||||
test("MyApplicationsListRequest round-trips an empty body", () => {
|
||||
const builder = new Builder(32);
|
||||
MyApplicationsListRequest.startMyApplicationsListRequest(builder);
|
||||
builder.finish(MyApplicationsListRequest.endMyApplicationsListRequest(builder));
|
||||
const decoded = MyApplicationsListRequest.getRootAsMyApplicationsListRequest(
|
||||
new ByteBuffer(builder.asUint8Array()),
|
||||
);
|
||||
expect(decoded).toBeDefined();
|
||||
});
|
||||
|
||||
test("InviteSummary preserves invited_user_id and code fields", () => {
|
||||
const builder = new Builder(256);
|
||||
|
||||
const userBoundId = builder.createString("invite-user-bound");
|
||||
const userBoundGame = builder.createString("private-1");
|
||||
const userBoundInviter = builder.createString("user-host");
|
||||
const userBoundInvited = builder.createString("user-1");
|
||||
const userBoundCode = builder.createString("");
|
||||
const userBoundRace = builder.createString("Vegan Federation");
|
||||
const userBoundStatus = builder.createString("pending");
|
||||
InviteSummary.startInviteSummary(builder);
|
||||
InviteSummary.addInviteId(builder, userBoundId);
|
||||
InviteSummary.addGameId(builder, userBoundGame);
|
||||
InviteSummary.addInviterUserId(builder, userBoundInviter);
|
||||
InviteSummary.addInvitedUserId(builder, userBoundInvited);
|
||||
InviteSummary.addCode(builder, userBoundCode);
|
||||
InviteSummary.addRaceName(builder, userBoundRace);
|
||||
InviteSummary.addStatus(builder, userBoundStatus);
|
||||
InviteSummary.addCreatedAtMs(builder, 1_770_000_000_000n);
|
||||
InviteSummary.addExpiresAtMs(builder, 1_780_000_000_000n);
|
||||
InviteSummary.addDecidedAtMs(builder, 0n);
|
||||
const userBound = InviteSummary.endInviteSummary(builder);
|
||||
|
||||
const codeBasedId = builder.createString("invite-code-based");
|
||||
const codeBasedGame = builder.createString("private-2");
|
||||
const codeBasedInviter = builder.createString("user-host");
|
||||
const codeBasedInvited = builder.createString("");
|
||||
const codeBasedCode = builder.createString("ABCDEF12");
|
||||
const codeBasedRace = builder.createString("Lithic Compact");
|
||||
const codeBasedStatus = builder.createString("pending");
|
||||
InviteSummary.startInviteSummary(builder);
|
||||
InviteSummary.addInviteId(builder, codeBasedId);
|
||||
InviteSummary.addGameId(builder, codeBasedGame);
|
||||
InviteSummary.addInviterUserId(builder, codeBasedInviter);
|
||||
InviteSummary.addInvitedUserId(builder, codeBasedInvited);
|
||||
InviteSummary.addCode(builder, codeBasedCode);
|
||||
InviteSummary.addRaceName(builder, codeBasedRace);
|
||||
InviteSummary.addStatus(builder, codeBasedStatus);
|
||||
InviteSummary.addCreatedAtMs(builder, 1_770_000_000_000n);
|
||||
InviteSummary.addExpiresAtMs(builder, 1_780_000_000_000n);
|
||||
InviteSummary.addDecidedAtMs(builder, 0n);
|
||||
const codeBased = InviteSummary.endInviteSummary(builder);
|
||||
|
||||
const items = MyInvitesListResponse.createItemsVector(builder, [userBound, codeBased]);
|
||||
MyInvitesListResponse.startMyInvitesListResponse(builder);
|
||||
MyInvitesListResponse.addItems(builder, items);
|
||||
builder.finish(MyInvitesListResponse.endMyInvitesListResponse(builder));
|
||||
|
||||
const decoded = MyInvitesListResponse.getRootAsMyInvitesListResponse(
|
||||
new ByteBuffer(builder.asUint8Array()),
|
||||
);
|
||||
expect(decoded.itemsLength()).toBe(2);
|
||||
const first = decoded.items(0)!;
|
||||
expect(first.invitedUserId()).toBe("user-1");
|
||||
expect(first.code()).toBe("");
|
||||
const second = decoded.items(1)!;
|
||||
expect(second.invitedUserId()).toBe("");
|
||||
expect(second.code()).toBe("ABCDEF12");
|
||||
});
|
||||
|
||||
test("MyInvitesListRequest round-trips an empty body", () => {
|
||||
const builder = new Builder(32);
|
||||
MyInvitesListRequest.startMyInvitesListRequest(builder);
|
||||
builder.finish(MyInvitesListRequest.endMyInvitesListRequest(builder));
|
||||
const decoded = MyInvitesListRequest.getRootAsMyInvitesListRequest(
|
||||
new ByteBuffer(builder.asUint8Array()),
|
||||
);
|
||||
expect(decoded).toBeDefined();
|
||||
});
|
||||
|
||||
test("OpenEnrollmentRequest and Response round-trip", () => {
|
||||
const builder = new Builder(64);
|
||||
const gameId = builder.createString("game-private-7c8f");
|
||||
OpenEnrollmentRequest.startOpenEnrollmentRequest(builder);
|
||||
OpenEnrollmentRequest.addGameId(builder, gameId);
|
||||
builder.finish(OpenEnrollmentRequest.endOpenEnrollmentRequest(builder));
|
||||
const reqDecoded = OpenEnrollmentRequest.getRootAsOpenEnrollmentRequest(
|
||||
new ByteBuffer(builder.asUint8Array()),
|
||||
);
|
||||
expect(reqDecoded.gameId()).toBe("game-private-7c8f");
|
||||
|
||||
const respBuilder = new Builder(64);
|
||||
const respGameId = respBuilder.createString("game-private-7c8f");
|
||||
const status = respBuilder.createString("enrollment_open");
|
||||
OpenEnrollmentResponse.startOpenEnrollmentResponse(respBuilder);
|
||||
OpenEnrollmentResponse.addGameId(respBuilder, respGameId);
|
||||
OpenEnrollmentResponse.addStatus(respBuilder, status);
|
||||
respBuilder.finish(OpenEnrollmentResponse.endOpenEnrollmentResponse(respBuilder));
|
||||
const respDecoded = OpenEnrollmentResponse.getRootAsOpenEnrollmentResponse(
|
||||
new ByteBuffer(respBuilder.asUint8Array()),
|
||||
);
|
||||
expect(respDecoded.gameId()).toBe("game-private-7c8f");
|
||||
expect(respDecoded.status()).toBe("enrollment_open");
|
||||
});
|
||||
|
||||
test("GameCreateRequest and Response round-trip", () => {
|
||||
const builder = new Builder(256);
|
||||
const name = builder.createString("First Contact");
|
||||
const description = builder.createString("");
|
||||
const turnSchedule = builder.createString("0 0 * * *");
|
||||
const targetVersion = builder.createString("v1");
|
||||
GameCreateRequest.startGameCreateRequest(builder);
|
||||
GameCreateRequest.addGameName(builder, name);
|
||||
GameCreateRequest.addDescription(builder, description);
|
||||
GameCreateRequest.addMinPlayers(builder, 2);
|
||||
GameCreateRequest.addMaxPlayers(builder, 8);
|
||||
GameCreateRequest.addStartGapHours(builder, 24);
|
||||
GameCreateRequest.addStartGapPlayers(builder, 2);
|
||||
GameCreateRequest.addEnrollmentEndsAtMs(builder, 1_780_000_000_000n);
|
||||
GameCreateRequest.addTurnSchedule(builder, turnSchedule);
|
||||
GameCreateRequest.addTargetEngineVersion(builder, targetVersion);
|
||||
builder.finish(GameCreateRequest.endGameCreateRequest(builder));
|
||||
const reqDecoded = GameCreateRequest.getRootAsGameCreateRequest(
|
||||
new ByteBuffer(builder.asUint8Array()),
|
||||
);
|
||||
expect(reqDecoded.gameName()).toBe("First Contact");
|
||||
expect(reqDecoded.minPlayers()).toBe(2);
|
||||
expect(reqDecoded.maxPlayers()).toBe(8);
|
||||
expect(reqDecoded.turnSchedule()).toBe("0 0 * * *");
|
||||
expect(reqDecoded.targetEngineVersion()).toBe("v1");
|
||||
expect(reqDecoded.enrollmentEndsAtMs()).toBe(1_780_000_000_000n);
|
||||
|
||||
const respBuilder = new Builder(256);
|
||||
const game = encodeGameSummary(respBuilder, PRIVATE_GAME);
|
||||
GameCreateResponse.startGameCreateResponse(respBuilder);
|
||||
GameCreateResponse.addGame(respBuilder, game);
|
||||
respBuilder.finish(GameCreateResponse.endGameCreateResponse(respBuilder));
|
||||
const respDecoded = GameCreateResponse.getRootAsGameCreateResponse(
|
||||
new ByteBuffer(respBuilder.asUint8Array()),
|
||||
);
|
||||
expectGameSummary(respDecoded.game(), PRIVATE_GAME);
|
||||
});
|
||||
|
||||
test("ApplicationSubmitRequest and Response round-trip", () => {
|
||||
const builder = new Builder(128);
|
||||
const gameId = builder.createString("public-1");
|
||||
const raceName = builder.createString("Vegan Federation");
|
||||
ApplicationSubmitRequest.startApplicationSubmitRequest(builder);
|
||||
ApplicationSubmitRequest.addGameId(builder, gameId);
|
||||
ApplicationSubmitRequest.addRaceName(builder, raceName);
|
||||
builder.finish(ApplicationSubmitRequest.endApplicationSubmitRequest(builder));
|
||||
const reqDecoded = ApplicationSubmitRequest.getRootAsApplicationSubmitRequest(
|
||||
new ByteBuffer(builder.asUint8Array()),
|
||||
);
|
||||
expect(reqDecoded.gameId()).toBe("public-1");
|
||||
expect(reqDecoded.raceName()).toBe("Vegan Federation");
|
||||
|
||||
const respBuilder = new Builder(128);
|
||||
const appId = respBuilder.createString("app-3");
|
||||
const appGameId = respBuilder.createString("public-1");
|
||||
const applicant = respBuilder.createString("user-1");
|
||||
const race = respBuilder.createString("Vegan Federation");
|
||||
const status = respBuilder.createString("pending");
|
||||
ApplicationSummary.startApplicationSummary(respBuilder);
|
||||
ApplicationSummary.addApplicationId(respBuilder, appId);
|
||||
ApplicationSummary.addGameId(respBuilder, appGameId);
|
||||
ApplicationSummary.addApplicantUserId(respBuilder, applicant);
|
||||
ApplicationSummary.addRaceName(respBuilder, race);
|
||||
ApplicationSummary.addStatus(respBuilder, status);
|
||||
ApplicationSummary.addCreatedAtMs(respBuilder, 1_770_000_000_000n);
|
||||
ApplicationSummary.addDecidedAtMs(respBuilder, 0n);
|
||||
const app = ApplicationSummary.endApplicationSummary(respBuilder);
|
||||
ApplicationSubmitResponse.startApplicationSubmitResponse(respBuilder);
|
||||
ApplicationSubmitResponse.addApplication(respBuilder, app);
|
||||
respBuilder.finish(ApplicationSubmitResponse.endApplicationSubmitResponse(respBuilder));
|
||||
const respDecoded = ApplicationSubmitResponse.getRootAsApplicationSubmitResponse(
|
||||
new ByteBuffer(respBuilder.asUint8Array()),
|
||||
);
|
||||
const application = respDecoded.application();
|
||||
expect(application).not.toBeNull();
|
||||
expect(application!.applicationId()).toBe("app-3");
|
||||
expect(application!.status()).toBe("pending");
|
||||
});
|
||||
|
||||
test("InviteRedeem and InviteDecline requests round-trip", () => {
|
||||
for (const ctor of [InviteRedeemRequest, InviteDeclineRequest] as const) {
|
||||
const builder = new Builder(128);
|
||||
const gameId = builder.createString("private-1");
|
||||
const inviteId = builder.createString("invite-1");
|
||||
if (ctor === InviteRedeemRequest) {
|
||||
InviteRedeemRequest.startInviteRedeemRequest(builder);
|
||||
InviteRedeemRequest.addGameId(builder, gameId);
|
||||
InviteRedeemRequest.addInviteId(builder, inviteId);
|
||||
builder.finish(InviteRedeemRequest.endInviteRedeemRequest(builder));
|
||||
const decoded = InviteRedeemRequest.getRootAsInviteRedeemRequest(
|
||||
new ByteBuffer(builder.asUint8Array()),
|
||||
);
|
||||
expect(decoded.gameId()).toBe("private-1");
|
||||
expect(decoded.inviteId()).toBe("invite-1");
|
||||
} else {
|
||||
InviteDeclineRequest.startInviteDeclineRequest(builder);
|
||||
InviteDeclineRequest.addGameId(builder, gameId);
|
||||
InviteDeclineRequest.addInviteId(builder, inviteId);
|
||||
builder.finish(InviteDeclineRequest.endInviteDeclineRequest(builder));
|
||||
const decoded = InviteDeclineRequest.getRootAsInviteDeclineRequest(
|
||||
new ByteBuffer(builder.asUint8Array()),
|
||||
);
|
||||
expect(decoded.gameId()).toBe("private-1");
|
||||
expect(decoded.inviteId()).toBe("invite-1");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("InviteRedeemResponse and InviteDeclineResponse carry an InviteSummary", () => {
|
||||
for (const status of ["accepted", "declined"]) {
|
||||
const builder = new Builder(128);
|
||||
const inviteId = builder.createString("invite-1");
|
||||
const gameId = builder.createString("private-1");
|
||||
const inviter = builder.createString("user-host");
|
||||
const invited = builder.createString("user-1");
|
||||
const code = builder.createString("");
|
||||
const race = builder.createString("Vegan Federation");
|
||||
const statusStr = builder.createString(status);
|
||||
InviteSummary.startInviteSummary(builder);
|
||||
InviteSummary.addInviteId(builder, inviteId);
|
||||
InviteSummary.addGameId(builder, gameId);
|
||||
InviteSummary.addInviterUserId(builder, inviter);
|
||||
InviteSummary.addInvitedUserId(builder, invited);
|
||||
InviteSummary.addCode(builder, code);
|
||||
InviteSummary.addRaceName(builder, race);
|
||||
InviteSummary.addStatus(builder, statusStr);
|
||||
InviteSummary.addCreatedAtMs(builder, 1_770_000_000_000n);
|
||||
InviteSummary.addExpiresAtMs(builder, 1_780_000_000_000n);
|
||||
InviteSummary.addDecidedAtMs(builder, 1_770_010_000_000n);
|
||||
const summary = InviteSummary.endInviteSummary(builder);
|
||||
|
||||
if (status === "accepted") {
|
||||
InviteRedeemResponse.startInviteRedeemResponse(builder);
|
||||
InviteRedeemResponse.addInvite(builder, summary);
|
||||
builder.finish(InviteRedeemResponse.endInviteRedeemResponse(builder));
|
||||
const decoded = InviteRedeemResponse.getRootAsInviteRedeemResponse(
|
||||
new ByteBuffer(builder.asUint8Array()),
|
||||
);
|
||||
expect(decoded.invite()?.status()).toBe("accepted");
|
||||
} else {
|
||||
InviteDeclineResponse.startInviteDeclineResponse(builder);
|
||||
InviteDeclineResponse.addInvite(builder, summary);
|
||||
builder.finish(InviteDeclineResponse.endInviteDeclineResponse(builder));
|
||||
const decoded = InviteDeclineResponse.getRootAsInviteDeclineResponse(
|
||||
new ByteBuffer(builder.asUint8Array()),
|
||||
);
|
||||
expect(decoded.invite()?.status()).toBe("declined");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("ErrorResponse round-trips a code/message pair", () => {
|
||||
const builder = new Builder(128);
|
||||
const code = builder.createString("conflict");
|
||||
const message = builder.createString("request conflicts with current state");
|
||||
ErrorBody.startErrorBody(builder);
|
||||
ErrorBody.addCode(builder, code);
|
||||
ErrorBody.addMessage(builder, message);
|
||||
const errorOff = ErrorBody.endErrorBody(builder);
|
||||
ErrorResponse.startErrorResponse(builder);
|
||||
ErrorResponse.addError(builder, errorOff);
|
||||
builder.finish(ErrorResponse.endErrorResponse(builder));
|
||||
const decoded = ErrorResponse.getRootAsErrorResponse(
|
||||
new ByteBuffer(builder.asUint8Array()),
|
||||
);
|
||||
const error = decoded.error();
|
||||
expect(error).not.toBeNull();
|
||||
expect(error!.code()).toBe("conflict");
|
||||
expect(error!.message()).toBe("request conflicts with current state");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,361 @@
|
||||
// Component tests for the Phase 8 lobby page. The lobby API and the
|
||||
// gateway client are mocked at module level; the session singleton is
|
||||
// wired to a per-test `SessionStore`-backing IndexedDB so the page's
|
||||
// boot path settles on `authenticated` and constructs a real
|
||||
// GalaxyClient (which is then never called because the lobby API
|
||||
// wrappers are stubs). The tests assert the section rendering, the
|
||||
// inline race-name form for public games, and the invitation Accept
|
||||
// flow.
|
||||
|
||||
import "fake-indexeddb/auto";
|
||||
import { fireEvent, render, waitFor } from "@testing-library/svelte";
|
||||
import {
|
||||
afterEach,
|
||||
beforeEach,
|
||||
describe,
|
||||
expect,
|
||||
test,
|
||||
vi,
|
||||
} from "vitest";
|
||||
import type { IDBPDatabase } from "idb";
|
||||
|
||||
import { i18n } from "../src/lib/i18n/index.svelte";
|
||||
import { session } from "../src/lib/session-store.svelte";
|
||||
import { type GalaxyDB, openGalaxyDB } from "../src/platform/store/idb";
|
||||
import { IDBCache } from "../src/platform/store/idb-cache";
|
||||
import { WebCryptoKeyStore } from "../src/platform/store/webcrypto-keystore";
|
||||
|
||||
vi.mock("$app/navigation", () => ({
|
||||
goto: vi.fn(async () => {}),
|
||||
}));
|
||||
|
||||
const listMyGamesSpy = vi.fn();
|
||||
const listPublicGamesSpy = vi.fn();
|
||||
const listMyInvitesSpy = vi.fn();
|
||||
const listMyApplicationsSpy = vi.fn();
|
||||
const submitApplicationSpy = vi.fn();
|
||||
const redeemInviteSpy = vi.fn();
|
||||
const declineInviteSpy = vi.fn();
|
||||
|
||||
vi.mock("../src/api/lobby", async () => {
|
||||
const actual = await vi.importActual<typeof import("../src/api/lobby")>(
|
||||
"../src/api/lobby",
|
||||
);
|
||||
return {
|
||||
...actual,
|
||||
listMyGames: (...args: unknown[]) => listMyGamesSpy(...args),
|
||||
listPublicGames: (...args: unknown[]) => listPublicGamesSpy(...args),
|
||||
listMyInvites: (...args: unknown[]) => listMyInvitesSpy(...args),
|
||||
listMyApplications: (...args: unknown[]) => listMyApplicationsSpy(...args),
|
||||
submitApplication: (...args: unknown[]) => submitApplicationSpy(...args),
|
||||
redeemInvite: (...args: unknown[]) => redeemInviteSpy(...args),
|
||||
declineInvite: (...args: unknown[]) => declineInviteSpy(...args),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock("../src/lib/env", () => ({
|
||||
GATEWAY_BASE_URL: "http://gateway.test",
|
||||
GATEWAY_RESPONSE_PUBLIC_KEY: new Uint8Array(32).fill(0x55),
|
||||
}));
|
||||
|
||||
vi.mock("../src/api/connect", () => ({
|
||||
createEdgeGatewayClient: vi.fn(() => ({})),
|
||||
}));
|
||||
|
||||
vi.mock("../src/api/galaxy-client", () => {
|
||||
class FakeGalaxyClient {
|
||||
executeCommand = vi.fn(async () => ({
|
||||
resultCode: "ok",
|
||||
payloadBytes: new Uint8Array(),
|
||||
}));
|
||||
}
|
||||
return { GalaxyClient: FakeGalaxyClient };
|
||||
});
|
||||
|
||||
vi.mock("../src/platform/core/index", () => ({
|
||||
loadCore: async () => ({
|
||||
signRequest: () => new Uint8Array(),
|
||||
verifyResponse: () => true,
|
||||
verifyEvent: () => true,
|
||||
verifyPayloadHash: () => true,
|
||||
}),
|
||||
}));
|
||||
|
||||
let db: IDBPDatabase<GalaxyDB>;
|
||||
let dbName: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
dbName = `galaxy-ui-test-${crypto.randomUUID()}`;
|
||||
db = await openGalaxyDB(dbName);
|
||||
const store = {
|
||||
keyStore: new WebCryptoKeyStore(db),
|
||||
cache: new IDBCache(db),
|
||||
};
|
||||
session.resetForTests();
|
||||
session.setStoreLoaderForTests(async () => store);
|
||||
await session.init();
|
||||
await session.signIn("device-1");
|
||||
i18n.resetForTests("en");
|
||||
|
||||
listMyGamesSpy.mockReset();
|
||||
listPublicGamesSpy.mockReset();
|
||||
listMyInvitesSpy.mockReset();
|
||||
listMyApplicationsSpy.mockReset();
|
||||
submitApplicationSpy.mockReset();
|
||||
redeemInviteSpy.mockReset();
|
||||
declineInviteSpy.mockReset();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
session.resetForTests();
|
||||
i18n.resetForTests("en");
|
||||
db.close();
|
||||
await new Promise<void>((resolve) => {
|
||||
const req = indexedDB.deleteDatabase(dbName);
|
||||
req.onsuccess = () => resolve();
|
||||
req.onerror = () => resolve();
|
||||
req.onblocked = () => resolve();
|
||||
});
|
||||
});
|
||||
|
||||
async function importLobbyPage(): Promise<typeof import("../src/routes/lobby/+page.svelte")> {
|
||||
return import("../src/routes/lobby/+page.svelte");
|
||||
}
|
||||
|
||||
const baseDate = new Date("2026-05-07T10:00:00Z");
|
||||
|
||||
function makeGame(id: string, name: string, status = "draft") {
|
||||
return {
|
||||
gameId: id,
|
||||
gameName: name,
|
||||
gameType: "private",
|
||||
status,
|
||||
ownerUserId: "user-1",
|
||||
minPlayers: 2,
|
||||
maxPlayers: 8,
|
||||
enrollmentEndsAt: baseDate,
|
||||
createdAt: baseDate,
|
||||
updatedAt: baseDate,
|
||||
};
|
||||
}
|
||||
|
||||
function makePublicGame(id: string, name: string) {
|
||||
return {
|
||||
gameId: id,
|
||||
gameName: name,
|
||||
gameType: "public",
|
||||
status: "enrollment_open",
|
||||
ownerUserId: "",
|
||||
minPlayers: 4,
|
||||
maxPlayers: 12,
|
||||
enrollmentEndsAt: baseDate,
|
||||
createdAt: baseDate,
|
||||
updatedAt: baseDate,
|
||||
};
|
||||
}
|
||||
|
||||
function makeInvite(id: string) {
|
||||
return {
|
||||
inviteId: id,
|
||||
gameId: "private-1",
|
||||
inviterUserId: "host",
|
||||
invitedUserId: "user-1",
|
||||
code: "",
|
||||
raceName: "Vegan Federation",
|
||||
status: "pending",
|
||||
createdAt: baseDate,
|
||||
expiresAt: baseDate,
|
||||
decidedAt: null,
|
||||
};
|
||||
}
|
||||
|
||||
function makeApplication(id: string, status: string) {
|
||||
return {
|
||||
applicationId: id,
|
||||
gameId: "public-1",
|
||||
applicantUserId: "user-1",
|
||||
raceName: "Vegan Federation",
|
||||
status,
|
||||
createdAt: baseDate,
|
||||
decidedAt: status === "pending" ? null : baseDate,
|
||||
};
|
||||
}
|
||||
|
||||
describe("lobby page", () => {
|
||||
test("renders empty states for every section when API returns no items", async () => {
|
||||
listMyGamesSpy.mockResolvedValue([]);
|
||||
listPublicGamesSpy.mockResolvedValue({ items: [], page: 1, pageSize: 50, total: 0 });
|
||||
listMyInvitesSpy.mockResolvedValue([]);
|
||||
listMyApplicationsSpy.mockResolvedValue([]);
|
||||
|
||||
const Page = (await importLobbyPage()).default;
|
||||
const ui = render(Page);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(ui.getByTestId("lobby-my-games-empty")).toBeInTheDocument();
|
||||
expect(ui.getByTestId("lobby-invitations-empty")).toBeInTheDocument();
|
||||
expect(ui.getByTestId("lobby-applications-empty")).toBeInTheDocument();
|
||||
expect(ui.getByTestId("lobby-public-games-empty")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
test("renders my-game cards and public-game cards when items are present", async () => {
|
||||
listMyGamesSpy.mockResolvedValue([makeGame("private-1", "First Contact")]);
|
||||
listPublicGamesSpy.mockResolvedValue({
|
||||
items: [makePublicGame("public-1", "Open Lobby")],
|
||||
page: 1,
|
||||
pageSize: 50,
|
||||
total: 1,
|
||||
});
|
||||
listMyInvitesSpy.mockResolvedValue([]);
|
||||
listMyApplicationsSpy.mockResolvedValue([]);
|
||||
|
||||
const Page = (await importLobbyPage()).default;
|
||||
const ui = render(Page);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(ui.getAllByTestId("lobby-my-game-card").length).toBe(1);
|
||||
expect(ui.getByText("First Contact")).toBeInTheDocument();
|
||||
expect(ui.getByText("Open Lobby")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
test("submitting an application opens the inline form and posts race_name", async () => {
|
||||
listMyGamesSpy.mockResolvedValue([]);
|
||||
listPublicGamesSpy.mockResolvedValue({
|
||||
items: [makePublicGame("public-1", "Open Lobby")],
|
||||
page: 1,
|
||||
pageSize: 50,
|
||||
total: 1,
|
||||
});
|
||||
listMyInvitesSpy.mockResolvedValue([]);
|
||||
listMyApplicationsSpy.mockResolvedValue([]);
|
||||
submitApplicationSpy.mockResolvedValue(makeApplication("app-1", "pending"));
|
||||
|
||||
const Page = (await importLobbyPage()).default;
|
||||
const ui = render(Page);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(ui.getByTestId("lobby-public-game-apply")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
await fireEvent.click(ui.getByTestId("lobby-public-game-apply"));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(ui.getByTestId("lobby-application-form")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
await fireEvent.input(ui.getByTestId("lobby-application-race-name"), {
|
||||
target: { value: "Vegan Federation" },
|
||||
});
|
||||
await fireEvent.click(ui.getByTestId("lobby-application-submit"));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(submitApplicationSpy).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
"public-1",
|
||||
"Vegan Federation",
|
||||
);
|
||||
expect(ui.getByTestId("lobby-application-card")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
test("submitting an empty race name surfaces a validation error and does not call the API", async () => {
|
||||
listMyGamesSpy.mockResolvedValue([]);
|
||||
listPublicGamesSpy.mockResolvedValue({
|
||||
items: [makePublicGame("public-1", "Open Lobby")],
|
||||
page: 1,
|
||||
pageSize: 50,
|
||||
total: 1,
|
||||
});
|
||||
listMyInvitesSpy.mockResolvedValue([]);
|
||||
listMyApplicationsSpy.mockResolvedValue([]);
|
||||
|
||||
const Page = (await importLobbyPage()).default;
|
||||
const ui = render(Page);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(ui.getByTestId("lobby-public-game-apply")).toBeInTheDocument(),
|
||||
);
|
||||
await fireEvent.click(ui.getByTestId("lobby-public-game-apply"));
|
||||
await fireEvent.click(ui.getByTestId("lobby-application-submit"));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(ui.getByTestId("lobby-application-error")).toBeInTheDocument();
|
||||
expect(submitApplicationSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
test("accepting an invitation calls redeemInvite and removes the card", async () => {
|
||||
listMyGamesSpy.mockResolvedValue([]);
|
||||
listPublicGamesSpy.mockResolvedValue({ items: [], page: 1, pageSize: 50, total: 0 });
|
||||
listMyInvitesSpy.mockResolvedValue([makeInvite("invite-1")]);
|
||||
listMyApplicationsSpy.mockResolvedValue([]);
|
||||
redeemInviteSpy.mockResolvedValue(makeInvite("invite-1"));
|
||||
|
||||
const Page = (await importLobbyPage()).default;
|
||||
const ui = render(Page);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(ui.getByTestId("lobby-invite-accept")).toBeInTheDocument(),
|
||||
);
|
||||
|
||||
await fireEvent.click(ui.getByTestId("lobby-invite-accept"));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(redeemInviteSpy).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
"private-1",
|
||||
"invite-1",
|
||||
);
|
||||
expect(ui.queryByTestId("lobby-invite-accept")).not.toBeInTheDocument();
|
||||
expect(ui.getByTestId("lobby-invitations-empty")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
test("declining an invitation calls declineInvite and removes the card", async () => {
|
||||
listMyGamesSpy.mockResolvedValue([]);
|
||||
listPublicGamesSpy.mockResolvedValue({ items: [], page: 1, pageSize: 50, total: 0 });
|
||||
listMyInvitesSpy.mockResolvedValue([makeInvite("invite-2")]);
|
||||
listMyApplicationsSpy.mockResolvedValue([]);
|
||||
declineInviteSpy.mockResolvedValue({ ...makeInvite("invite-2"), status: "declined" });
|
||||
|
||||
const Page = (await importLobbyPage()).default;
|
||||
const ui = render(Page);
|
||||
|
||||
await waitFor(() =>
|
||||
expect(ui.getByTestId("lobby-invite-decline")).toBeInTheDocument(),
|
||||
);
|
||||
|
||||
await fireEvent.click(ui.getByTestId("lobby-invite-decline"));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(declineInviteSpy).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
"private-1",
|
||||
"invite-2",
|
||||
);
|
||||
expect(ui.queryByTestId("lobby-invite-decline")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
test("application status badges localise pending and approved states", async () => {
|
||||
listMyGamesSpy.mockResolvedValue([]);
|
||||
listPublicGamesSpy.mockResolvedValue({ items: [], page: 1, pageSize: 50, total: 0 });
|
||||
listMyInvitesSpy.mockResolvedValue([]);
|
||||
listMyApplicationsSpy.mockResolvedValue([
|
||||
makeApplication("app-1", "pending"),
|
||||
makeApplication("app-2", "approved"),
|
||||
]);
|
||||
|
||||
const Page = (await importLobbyPage()).default;
|
||||
const ui = render(Page);
|
||||
|
||||
await waitFor(() => {
|
||||
const cards = ui.getAllByTestId("lobby-application-card");
|
||||
expect(cards.length).toBe(2);
|
||||
expect(cards[0]!.querySelector(".status")?.textContent?.trim()).toBe("pending");
|
||||
expect(cards[1]!.querySelector(".status")?.textContent?.trim()).toBe("approved");
|
||||
});
|
||||
});
|
||||
});
|
||||
Generated
+8
@@ -8,6 +8,9 @@ importers:
|
||||
|
||||
frontend:
|
||||
dependencies:
|
||||
flatbuffers:
|
||||
specifier: ^25.9.23
|
||||
version: 25.9.23
|
||||
idb:
|
||||
specifier: ^8.0.3
|
||||
version: 8.0.3
|
||||
@@ -577,6 +580,9 @@ packages:
|
||||
picomatch:
|
||||
optional: true
|
||||
|
||||
flatbuffers@25.9.23:
|
||||
resolution: {integrity: sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==}
|
||||
|
||||
form-data@4.0.5:
|
||||
resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==}
|
||||
engines: {node: '>= 6'}
|
||||
@@ -1515,6 +1521,8 @@ snapshots:
|
||||
optionalDependencies:
|
||||
picomatch: 4.0.4
|
||||
|
||||
flatbuffers@25.9.23: {}
|
||||
|
||||
form-data@4.0.5:
|
||||
dependencies:
|
||||
asynckit: 0.4.0
|
||||
|
||||
Reference in New Issue
Block a user