generated from alexstojda/go-react-app
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(api-clients): Create api client for pinball map API to fetch loc…
…ations
- Loading branch information
1 parent
41bb0bc
commit 49c14d7
Showing
11 changed files
with
474 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
inpackage: true | ||
keeptree: true | ||
dir: "{{.InterfaceDir}}" | ||
with-expecter: false | ||
packages: | ||
pinman/internal/utils: | ||
interfaces: | ||
# select the interfaces you want mocked | ||
HttpDoer: {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,16 +36,16 @@ build: build-backend build-frontend | |
|
||
build-backend: | ||
@mkdir -p ./build | ||
@go build -v -o ./build/pinman ./cmd/pinman/ | ||
@go build -v -o ./build/pinman main.go | ||
|
||
build-frontend: | ||
@cd $(FRONTEND_DIR) && yarn build | ||
|
||
run: clean generate build-frontend | ||
@SPA_PATH=./web/app/build go run cmd/pinman/main.go | ||
@SPA_PATH=./web/app/build go run main.go | ||
|
||
run-backend: | ||
@go run cmd/pinman/main.go | ||
@go run main.go | ||
|
||
run-database: | ||
@docker compose up -d postgres | ||
|
@@ -57,6 +57,8 @@ test: test-backend test-frontend | |
|
||
test-setup: | ||
@go install -mod=mod github.com/onsi/ginkgo/v2/ginkgo | ||
@go install -mod=mod github.com/vektra/mockery/[email protected] | ||
@mockery | ||
|
||
test-frontend: | ||
@cd $(FRONTEND_DIR) && yarn test | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
package pinballmap | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"net/url" | ||
"pinman/internal/utils" | ||
) | ||
|
||
type Client struct { | ||
apiHost string | ||
apiScheme string | ||
client utils.HttpDoer | ||
} | ||
|
||
type ClientInterface interface { | ||
GetLocations(nameFilter string) ([]Location, error) | ||
GetLocation(id int) (*Location, error) | ||
} | ||
|
||
func NewClient() *Client { | ||
return &Client{ | ||
apiScheme: "https", | ||
apiHost: "pinballmap.com", | ||
client: http.DefaultClient, | ||
} | ||
} | ||
|
||
func NewClientWithHttpClient(client utils.HttpDoer) *Client { | ||
return &Client{ | ||
apiScheme: "https", | ||
apiHost: "pinballmap.com", | ||
client: client, | ||
} | ||
} | ||
|
||
func (c *Client) NewUrl(path string, params url.Values) *url.URL { | ||
urrl := &url.URL{ | ||
Scheme: c.apiScheme, | ||
Host: c.apiHost, | ||
Path: path, | ||
} | ||
|
||
if params != nil { | ||
urrl.RawQuery = params.Encode() | ||
} | ||
|
||
return urrl | ||
} | ||
|
||
type Location struct { | ||
ID int `json:"id"` | ||
Name string `json:"name"` | ||
Street string `json:"street"` | ||
City string `json:"city"` | ||
State string `json:"state"` | ||
Country string `json:"country"` | ||
NumMachines int `json:"num_machines"` | ||
} | ||
|
||
type LocationResponse struct { | ||
Locations []Location `json:"locations"` | ||
} | ||
|
||
type ErrorResponse struct { | ||
Errors string `json:"errors"` | ||
} | ||
|
||
// GetLocations retrieves all locations from the Pinball Map API matching the given name filter. | ||
// https://pinballmap.com/api/v1/docs/1.0/locations/index.html | ||
func (c *Client) GetLocations(nameFilter string) ([]Location, error) { | ||
params := url.Values{} | ||
params.Add("by_location_name", nameFilter) | ||
params.Add("no_details", "true") | ||
|
||
req, err := http.NewRequest("GET", c.NewUrl("/api/v1/locations.json", params).String(), nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
req.Header.Set("Accept", "application/json") | ||
|
||
resp, err := c.client.Do(req) | ||
if err != nil { | ||
return nil, fmt.Errorf("doing request: %w", err) | ||
} | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
errResp := ErrorResponse{} | ||
err := json.NewDecoder(resp.Body).Decode(&errResp) | ||
if err != nil { | ||
return nil, fmt.Errorf("decoding error response: %w", err) | ||
} | ||
|
||
return nil, fmt.Errorf("unexpected response: %s", errResp.Errors) | ||
} | ||
|
||
//goland:noinspection GoUnhandledErrorResult | ||
defer resp.Body.Close() | ||
|
||
var locations LocationResponse | ||
if err := json.NewDecoder(resp.Body).Decode(&locations); err != nil { | ||
return nil, fmt.Errorf("retrieving locations: %w", err) | ||
} | ||
|
||
return locations.Locations, nil | ||
} | ||
|
||
func (c *Client) GetLocation(id int) (*Location, error) { | ||
req, err := http.NewRequest("GET", c.NewUrl(fmt.Sprintf("/api/v1/locations/%d.json", id), nil).String(), nil) | ||
if err != nil { | ||
return nil, fmt.Errorf("creating request: %w", err) | ||
} | ||
|
||
req.Header.Set("Accept", "application/json") | ||
|
||
resp, err := c.client.Do(req) | ||
if err != nil { | ||
return nil, fmt.Errorf("doing request: %w", err) | ||
} | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
errResp := ErrorResponse{} | ||
err := json.NewDecoder(resp.Body).Decode(&errResp) | ||
if err != nil { | ||
return nil, fmt.Errorf("decoding error response: %w", err) | ||
} | ||
|
||
return nil, fmt.Errorf("unexpected response: %s", errResp.Errors) | ||
} | ||
|
||
//goland:noinspection GoUnhandledErrorResult | ||
defer resp.Body.Close() | ||
|
||
var location Location | ||
if err := json.NewDecoder(resp.Body).Decode(&location); err != nil { | ||
return nil, fmt.Errorf("decoding response: %w", err) | ||
} | ||
|
||
return &location, nil | ||
} |
Oops, something went wrong.