diff --git a/cmd/arduino-app-cli/brick/list.go b/cmd/arduino-app-cli/brick/list.go index 04fff7e3..9e5e6389 100644 --- a/cmd/arduino-app-cli/brick/list.go +++ b/cmd/arduino-app-cli/brick/list.go @@ -21,7 +21,6 @@ import ( "github.com/arduino/arduino-app-cli/cmd/arduino-app-cli/internal/servicelocator" "github.com/arduino/arduino-app-cli/cmd/feedback" - "github.com/arduino/arduino-app-cli/internal/orchestrator/bricks" "github.com/arduino/arduino-app-cli/internal/tablestyle" ) @@ -42,10 +41,6 @@ func bricksListHandler() { feedback.PrintResult(brickListResult{Bricks: res.Bricks}) } -type brickListResult struct { - Bricks []bricks.BrickListItem `json:"bricks"` -} - func (r brickListResult) String() string { t := table.NewWriter() t.SetStyle(tablestyle.CustomCleanStyle) diff --git a/internal/api/handlers/app_bricks.go b/internal/api/handlers/app_bricks.go new file mode 100644 index 00000000..fddb0106 --- /dev/null +++ b/internal/api/handlers/app_bricks.go @@ -0,0 +1,77 @@ +package handlers + +import ( + "fmt" + "log/slog" + "net/http" + + "github.com/arduino/arduino-app-cli/internal/api/models" + "github.com/arduino/arduino-app-cli/internal/orchestrator/app" + "github.com/arduino/arduino-app-cli/internal/orchestrator/bricks" + "github.com/arduino/arduino-app-cli/internal/render" +) + +func HandleAppBrickInstancesList( + brickService *bricks.Service, + idProvider *app.IDProvider, +) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + appId, err := idProvider.IDFromBase64(r.PathValue("appID")) + if err != nil { + render.EncodeResponse(w, http.StatusPreconditionFailed, models.ErrorResponse{Details: "invalid app id"}) + return + } + appPath := appId.ToPath() + + app, err := app.Load(appPath) + if err != nil { + slog.Error("Unable to parse the app.yaml", slog.String("error", err.Error()), slog.String("path", appId.String())) + render.EncodeResponse(w, http.StatusInternalServerError, models.ErrorResponse{Details: "unable to find the app"}) + return + } + + res, err := brickService.AppBrickInstancesList(&app) + if err != nil { + slog.Error("Unable to parse the app.yaml", slog.String("error", err.Error())) + details := fmt.Sprintf("unable to find brick list for app %q", appId) + render.EncodeResponse(w, http.StatusInternalServerError, models.ErrorResponse{Details: details}) + return + } + render.EncodeResponse(w, http.StatusOK, res) + } +} + +func HandleAppBrickInstanceDetails( + brickService *bricks.Service, + idProvider *app.IDProvider, +) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + appId, err := idProvider.IDFromBase64(r.PathValue("appID")) + if err != nil { + render.EncodeResponse(w, http.StatusPreconditionFailed, models.ErrorResponse{Details: "invalid app id"}) + return + } + appPath := appId.ToPath() + + app, err := app.Load(appPath) + if err != nil { + slog.Error("Unable to parse the app.yaml", slog.String("error", err.Error()), slog.String("path", appId.String())) + render.EncodeResponse(w, http.StatusInternalServerError, models.ErrorResponse{Details: "unable to find the app"}) + return + } + + brickID := r.PathValue("brickID") + if brickID == "" { + render.EncodeResponse(w, http.StatusBadRequest, models.ErrorResponse{Details: "brickID must be set"}) + return + } + + res, err := brickService.AppBrickInstanceDetails(&app, brickID) + if err != nil { + slog.Error("Unable to parse the app.yaml", slog.String("error", err.Error())) + render.EncodeResponse(w, http.StatusInternalServerError, models.ErrorResponse{Details: "unable to obtain brick details"}) + return + } + render.EncodeResponse(w, http.StatusOK, res) + } +} diff --git a/internal/api/handlers/bricks.go b/internal/api/handlers/bricks.go index f3d22c6d..7e61b758 100644 --- a/internal/api/handlers/bricks.go +++ b/internal/api/handlers/bricks.go @@ -32,80 +32,45 @@ import ( func HandleBrickList(brickService *bricks.Service) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - res, err := brickService.List() + bricks, err := brickService.List() if err != nil { slog.Error("Unable to parse the app.yaml", slog.String("error", err.Error())) render.EncodeResponse(w, http.StatusInternalServerError, models.ErrorResponse{Details: "unable to retrieve brick list"}) return } - render.EncodeResponse(w, http.StatusOK, res) + render.EncodeResponse(w, http.StatusOK, buildListBricksResponse(bricks)) } } -func HandleAppBrickInstancesList( - brickService *bricks.Service, - idProvider *app.IDProvider, -) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - appId, err := idProvider.IDFromBase64(r.PathValue("appID")) - if err != nil { - render.EncodeResponse(w, http.StatusPreconditionFailed, models.ErrorResponse{Details: "invalid app id"}) - return - } - appPath := appId.ToPath() - - app, err := app.Load(appPath) - if err != nil { - slog.Error("Unable to parse the app.yaml", slog.String("error", err.Error()), slog.String("path", appId.String())) - render.EncodeResponse(w, http.StatusInternalServerError, models.ErrorResponse{Details: "unable to find the app"}) - return - } - - res, err := brickService.AppBrickInstancesList(&app) - if err != nil { - slog.Error("Unable to parse the app.yaml", slog.String("error", err.Error())) - details := fmt.Sprintf("unable to find brick list for app %q", appId) - render.EncodeResponse(w, http.StatusInternalServerError, models.ErrorResponse{Details: details}) - return - } - render.EncodeResponse(w, http.StatusOK, res) - } +type BrickListResponse struct { + Bricks []BrickItem `json:"bricks"` } -func HandleAppBrickInstanceDetails( - brickService *bricks.Service, - idProvider *app.IDProvider, -) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - appId, err := idProvider.IDFromBase64(r.PathValue("appID")) - if err != nil { - render.EncodeResponse(w, http.StatusPreconditionFailed, models.ErrorResponse{Details: "invalid app id"}) - return - } - appPath := appId.ToPath() - - app, err := app.Load(appPath) - if err != nil { - slog.Error("Unable to parse the app.yaml", slog.String("error", err.Error()), slog.String("path", appId.String())) - render.EncodeResponse(w, http.StatusInternalServerError, models.ErrorResponse{Details: "unable to find the app"}) - return - } - - brickID := r.PathValue("brickID") - if brickID == "" { - render.EncodeResponse(w, http.StatusBadRequest, models.ErrorResponse{Details: "brickID must be set"}) - return - } +type BrickItem struct { + ID string `json:"id"` + Name string `json:"name"` + Author string `json:"author"` + Description string `json:"description"` + Category string `json:"category"` + Status string `json:"status"` + RequireModel bool `json:"require_model"` +} - res, err := brickService.AppBrickInstanceDetails(&app, brickID) - if err != nil { - slog.Error("Unable to parse the app.yaml", slog.String("error", err.Error())) - render.EncodeResponse(w, http.StatusInternalServerError, models.ErrorResponse{Details: "unable to obtain brick details"}) - return - } - render.EncodeResponse(w, http.StatusOK, res) +func buildListBricksResponse(bricks []bricks.Brick) BrickListResponse { + items := make([]BrickItem, 0, len(bricks)) + for _, b := range bricks { + items = append(items, BrickItem{ + ID: b.ID, + Name: b.Name, + Author: b.Author, + Description: b.Description, + Category: b.Category, + Status: b.Status, + RequireModel: b.RequireModel, + }) } + return BrickListResponse{Bricks: items} } func HandleBrickCreate( diff --git a/internal/orchestrator/bricks/bricks.go b/internal/orchestrator/bricks/bricks.go index 3248d129..b2cf6f08 100644 --- a/internal/orchestrator/bricks/bricks.go +++ b/internal/orchestrator/bricks/bricks.go @@ -54,10 +54,10 @@ func NewService( } } -func (s *Service) List() (BrickListResult, error) { - res := BrickListResult{Bricks: make([]BrickListItem, len(s.bricksIndex.Bricks))} +func (s *Service) List() ([]Brick, error) { + bricks := make([]Brick, len(s.bricksIndex.Bricks)) for i, brick := range s.bricksIndex.Bricks { - res.Bricks[i] = BrickListItem{ + bricks[i] = Brick{ ID: brick.ID, Name: brick.Name, Author: "Arduino", // TODO: for now we only support our bricks @@ -67,7 +67,7 @@ func (s *Service) List() (BrickListResult, error) { RequireModel: brick.RequireModel, } } - return res, nil + return bricks, nil } func (s *Service) AppBrickInstancesList(a *app.ArduinoApp) (AppBrickInstancesResult, error) { diff --git a/internal/orchestrator/bricks/types.go b/internal/orchestrator/bricks/types.go index e4b1b747..d1fca5d0 100644 --- a/internal/orchestrator/bricks/types.go +++ b/internal/orchestrator/bricks/types.go @@ -15,18 +15,14 @@ package bricks -type BrickListResult struct { - Bricks []BrickListItem `json:"bricks"` -} - -type BrickListItem struct { - ID string `json:"id"` - Name string `json:"name"` - Author string `json:"author"` - Description string `json:"description"` - Category string `json:"category"` - Status string `json:"status"` - RequireModel bool `json:"require_model"` +type Brick struct { + ID string + Name string + Author string + Description string + Category string + Status string + RequireModel bool } type AppBrickInstancesResult struct {