Skip to content

Commit

Permalink
feat: add additional queries and update migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
SomethingSexy committed Sep 23, 2024
1 parent 1419eb9 commit 8fe11b3
Show file tree
Hide file tree
Showing 20 changed files with 325 additions and 25 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,9 @@ atlas migrate apply \
Using the free version of Atlas, we need to manually add extensions.

Right now we are adding them to the root migration (probably should make this a separate first migration).

Need to run the following after manually adding extensions.

```shell
atlas migrate hash
```
78 changes: 73 additions & 5 deletions internal/chronicle/adapter/http/game/game_server.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package game

import (
"log"
"net/http"

corePort "github.com/SomethingSexy/chronicle/internal/chronicle/core/port"
Expand Down Expand Up @@ -36,8 +35,9 @@ func (h GameHttpServer) Routes() chi.Router {
// Either at this level or a higher level to apply
// relationships to root routes.
r.Post("/{gameId}/worlds", h.CreateWorld)
// TODO: Eh this probably belongs within a /words/{worldId} path
r.Post("/{gameId}/locations", h.CreateLocation)
r.Get("/{gameId}/worlds/{worldId}", h.GetWorld)
r.Post("/{gameId}/worlds/{worldId}/locations", h.CreateLocation)
r.Get("/{gameId}/worlds/{worldId}/locations", h.GetLocations)

return r
}
Expand Down Expand Up @@ -74,6 +74,7 @@ func (h GameHttpServer) ListGames(w http.ResponseWriter, r *http.Request) {
worlds[x] = &WorldRequest{
ID: world.WorldId.String(),
WorldId: world.WorldId.String(),
GameId: world.GameId.String(),
Name: world.Name,
}
}
Expand Down Expand Up @@ -123,7 +124,6 @@ func (h GameHttpServer) GetGame(w http.ResponseWriter, r *http.Request) {

func (h GameHttpServer) CreateWorld(w http.ResponseWriter, r *http.Request) {
data := &WorldRequest{}
log.Println(r.Body)
if err := render.Bind(r, data); err != nil {
render.Render(w, r, common.ErrInvalidRequest(err))
return
Expand All @@ -139,9 +139,37 @@ func (h GameHttpServer) CreateWorld(w http.ResponseWriter, r *http.Request) {
render.Status(r, http.StatusCreated)
}

func (h GameHttpServer) GetWorld(w http.ResponseWriter, r *http.Request) {
gameId := chi.URLParam(r, "gameId")
worldId := chi.URLParam(r, "worldId")

world, err := h.queries.GetWorld.Handle(r.Context(), corePort.GetWorldQuery{
// TODO: BAD check for error
GameId: uuid.MustParse(gameId),
WorldId: uuid.MustParse(worldId),
})
if err != nil {
render.Render(w, r, common.ErrInvalidRequest(err))
return
}

response := &WorldRequest{
ID: world.WorldId.String(),
WorldId: world.WorldId.String(),
GameId: world.GameId.String(),
Name: world.Name,
}

w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", jsonapi.MediaType)
if err := jsonapi.MarshalPayload(w, response); err != nil {
render.Render(w, r, common.ErrInvalidRequest(err))
return
}
}

func (h GameHttpServer) CreateLocation(w http.ResponseWriter, r *http.Request) {
data := &LocationRequest{}
log.Println(r.Body)
if err := render.Bind(r, data); err != nil {
render.Render(w, r, common.ErrInvalidRequest(err))
return
Expand All @@ -156,3 +184,43 @@ func (h GameHttpServer) CreateLocation(w http.ResponseWriter, r *http.Request) {

render.Status(r, http.StatusCreated)
}

func (h GameHttpServer) GetLocations(w http.ResponseWriter, r *http.Request) {
gameId := chi.URLParam(r, "gameId")
worldId := chi.URLParam(r, "worldId")

locations, err := h.queries.ListLocations.Handle(r.Context(), corePort.LocationsQuery{
// TODO: BAD check for error
GameId: uuid.MustParse(gameId),
WorldId: uuid.MustParse(worldId),
})
if err != nil {
render.Render(w, r, common.ErrInvalidRequest(err))
return
}

responses := make([]*LocationRequest, len(locations))

for i, location := range locations {
paths := make([]string, len(location.Path))
for x, path := range location.Path {
paths[x] = path.String()
}

responses[i] = &LocationRequest{
ID: location.LocationId.String(),
LocationId: location.LocationId.String(),
WorldId: location.WorldId.String(),
Name: location.Name,
Type: location.Type,
Path: paths,
}
}

w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", jsonapi.MediaType)
if err := jsonapi.MarshalPayload(w, responses); err != nil {
render.Render(w, r, common.ErrInvalidRequest(err))
return
}
}
2 changes: 1 addition & 1 deletion internal/chronicle/adapter/http/game/location_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

type LocationRequest struct {
ID string `jsonapi:"primary,location"`
ID string `jsonapi:"primary,locations"`
LocationId string `jsonapi:"attr,locationId"`
WorldId string `jsonapi:"attr,worldId"`
Name string `jsonapi:"attr,name"`
Expand Down
9 changes: 5 additions & 4 deletions internal/chronicle/adapter/http/game/world_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import (
)

type WorldRequest struct {
ID string `jsonapi:"primary,worlds"`
WorldId string `jsonapi:"attr,worldId"`
GameId string `jsonapi:"attr,gameId"`
Name string `jsonapi:"attr,name"`
ID string `jsonapi:"primary,worlds"`
WorldId string `jsonapi:"attr,worldId"`
GameId string `jsonapi:"attr,gameId"`
Name string `jsonapi:"attr,name"`
Locations []*LocationRequest `jsonapi:"relation,locations"`
}

func (a *WorldRequest) Bind(r *http.Request) error {
Expand Down
53 changes: 53 additions & 0 deletions internal/chronicle/adapter/persistence/postgres/query/game.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package query

import (
"context"
"strings"

"github.com/SomethingSexy/chronicle/internal/chronicle/adapter/persistence/postgres/sqlc/repository"
"github.com/SomethingSexy/chronicle/internal/chronicle/core/domain"
Expand Down Expand Up @@ -89,6 +90,7 @@ func (g GameQuery) GetGameWorlds(ctx context.Context, gameId uuid.UUID) ([]domai
for i, world := range response {
worlds[i] = domain.World{
WorldId: world.WorldID,
GameId: gameId,
Name: world.Name,
}
}
Expand Down Expand Up @@ -119,6 +121,19 @@ func (g GameQuery) CreateWorld(ctx context.Context, world domain.World) (domain.
}, nil
}

func (g GameQuery) GetWorld(ctx context.Context, gameId uuid.UUID, worldId uuid.UUID) (domain.World, error) {
world, err := g.Queries.GetWorldFromUuid(ctx, worldId)
if err != nil {
return domain.World{}, err
}

return domain.World{
WorldId: world.WorldID,
GameId: gameId,
Name: world.Name,
}, nil
}

func (g GameQuery) CreateLocation(ctx context.Context, location domain.Location) (domain.Location, error) {
world, err := g.Queries.GetWorldFromUuid(ctx, location.WorldId)
if err != nil {
Expand Down Expand Up @@ -148,3 +163,41 @@ func (g GameQuery) CreateLocation(ctx context.Context, location domain.Location)

return location, nil
}

func (g GameQuery) ListLocations(ctx context.Context, gameId uuid.UUID, worldId uuid.UUID) ([]domain.Location, error) {
response, err := g.Queries.GetWorldLocations(ctx, repository.GetWorldLocationsParams{
GameID: gameId,
WorldID: worldId,
})
if err != nil {
return []domain.Location{}, err
}

locations := make([]domain.Location, len(response))

for i, location := range response {
var paths []uuid.UUID
// Split might return a string with a single element here
if location.Path.String != "" {
rawPaths := strings.Split(location.Path.String, ".")
for _, path := range rawPaths {
// This error should never but ya know...
parsed, err := uuid.Parse(path)
if err != nil {
return []domain.Location{}, err
}
paths = append(paths, parsed)
}
}

locations[i] = domain.Location{
LocationId: location.LocationID,
WorldId: location.WorldID_2,
Name: location.Name,
Type: location.Type,
Path: paths,
}
}

return locations, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,18 @@ CREATE INDEX "world_game_id" ON "public"."world" ("game_id");
CREATE TABLE "public"."location" (
"id" bigserial NOT NULL,
"location_id" uuid NOT NULL,
"game_id" bigserial NOT NULL,
"world_id" bigserial NOT NULL,
"type" text NOT NULL,
"name" text NOT NULL,
"path" public.ltree NULL,
PRIMARY KEY ("id"),
CONSTRAINT "location_location_id_key" UNIQUE ("location_id"),
CONSTRAINT "location_game_id_fkey" FOREIGN KEY ("game_id") REFERENCES "public"."game" ("id") ON UPDATE NO ACTION ON DELETE NO ACTION,
CONSTRAINT "location_world_id_fkey" FOREIGN KEY ("world_id") REFERENCES "public"."world" ("id") ON UPDATE NO ACTION ON DELETE NO ACTION
);
-- Create index "location_game_id" to table: "location"
CREATE INDEX "location_game_id" ON "public"."location" ("game_id");
-- Create index "location_path_idx" to table: "location"
CREATE INDEX "location_path_idx" ON "public"."location" USING gist ("path");
-- Create index "location_world_id" to table: "location"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
h1:e7Whf5lPTyJ5gZaclj0NLm1BA25BpU/S/uuWiNUeGFs=
20240820200446_initial.sql h1:FINnqTjzKlGS/n7twb3x1BGaGGqC/f/ztU7N/RNOQcU=
h1:PmA+4B4HY9WeN+NxUCd14XupO1EHfzKekMUpCcc+OtA=
20240922180859_initial.sql h1:tDi7JzkIFGrhaZgallRrrYgCFXWJo8ickqK/Xn35gCY=
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,10 @@ ON CONFLICT (location_id) DO UPDATE SET
type = EXCLUDED.type,
path = EXCLUDED.path
RETURNING *;

-- name: GetWorldLocations :many
SELECT * FROM location
JOIN world ON location.world_id = world.id
JOIN game ON location.game_id = game.id
WHERE game.game_id = $1 and
world.world_id = $2;

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@ create index world_game_id on world(game_id);
CREATE TABLE location (
id BIGSERIAL PRIMARY KEY,
location_id uuid UNIQUE NOT NULL,
-- Adding game_id here for now, incase we want locations independent of world?
game_id BIGSERIAL NOT NULL REFERENCES game(id),
world_id BIGSERIAL NOT NULL REFERENCES world(id),
type text NOT NULL,
name text NOT NULL,
path ltree
);

create index location_game_id on location(game_id);
create index location_world_id on location(world_id);
create index location_path_idx on location using gist (path);
6 changes: 4 additions & 2 deletions internal/chronicle/core/application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ func NewApplication(persistence port.ChronicleQueries) port.ChronicleApplication
}

queries := port.GameQueries{
ListGames: query.NewListGamesHandler(persistence),
GetGame: query.NewGetGameHandler(persistence),
ListGames: query.NewListGamesHandler(persistence),
GetGame: query.NewGetGameHandler(persistence),
ListLocations: query.NewListLocationsHandler(persistence),
GetWorld: query.NewGetWorldHandler(persistence),
}

return port.ChronicleApplication{
Expand Down
Loading

0 comments on commit 8fe11b3

Please sign in to comment.