Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
234 lines
8.8 KiB
Go
234 lines
8.8 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"time"
|
|
|
|
tuttigenerated "github.com/tutti-os/tutti/services/tuttid/api/generated"
|
|
"github.com/tutti-os/tutti/services/tuttid/apierrors"
|
|
workspaceservice "github.com/tutti-os/tutti/services/tuttid/service/workspace"
|
|
tuttitypes "github.com/tutti-os/tutti/services/tuttid/types"
|
|
)
|
|
|
|
func registerWorkspaceAppUploadRoutes(mux *http.ServeMux, wrapper *tuttigenerated.ServerInterfaceWrapper) {
|
|
mux.HandleFunc("/v1/workspaces/{workspaceID}/apps/{appID}/uploads", func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
tuttitypes.WriteMethodNotAllowed(w)
|
|
return
|
|
}
|
|
wrapper.PrepareWorkspaceAppUpload(w, r)
|
|
})
|
|
|
|
mux.HandleFunc("/v1/workspaces/{workspaceID}/apps/{appID}/uploads/{uploadID}/content", func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPut {
|
|
tuttitypes.WriteMethodNotAllowed(w)
|
|
return
|
|
}
|
|
wrapper.PutWorkspaceAppUploadContent(w, r)
|
|
})
|
|
|
|
mux.HandleFunc("/v1/workspaces/{workspaceID}/apps/{appID}/uploads/{uploadID}", func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodDelete {
|
|
tuttitypes.WriteMethodNotAllowed(w)
|
|
return
|
|
}
|
|
wrapper.CancelWorkspaceAppUpload(w, r)
|
|
})
|
|
|
|
mux.HandleFunc("/v1/workspaces/{workspaceID}/apps/{appID}/uploads/{uploadID}/complete", func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
tuttitypes.WriteMethodNotAllowed(w)
|
|
return
|
|
}
|
|
wrapper.CompleteWorkspaceAppUpload(w, r)
|
|
})
|
|
}
|
|
|
|
func (api DaemonAPI) PrepareWorkspaceAppUpload(
|
|
ctx context.Context,
|
|
request tuttigenerated.PrepareWorkspaceAppUploadRequestObject,
|
|
) (tuttigenerated.PrepareWorkspaceAppUploadResponseObject, error) {
|
|
if api.AppCenterService == nil {
|
|
return tuttigenerated.PrepareWorkspaceAppUpload503JSONResponse{
|
|
ServiceUnavailableErrorJSONResponse: workspaceAppServiceUnavailableError(),
|
|
}, nil
|
|
}
|
|
workspaceID, appID, errResponse := validateWorkspaceAppPath(request.WorkspaceID, request.AppID)
|
|
if errResponse != nil {
|
|
return tuttigenerated.PrepareWorkspaceAppUpload400JSONResponse{InvalidRequestErrorJSONResponse: *errResponse}, nil
|
|
}
|
|
if request.Body == nil {
|
|
return tuttigenerated.PrepareWorkspaceAppUpload400JSONResponse{
|
|
InvalidRequestErrorJSONResponse: invalidRequestError(
|
|
apierrors.EmptyBody(apierrors.WithDeveloperMessage("empty body")),
|
|
),
|
|
}, nil
|
|
}
|
|
|
|
session, err := api.AppCenterService.PrepareWorkspaceAppUpload(ctx, workspaceID, appID, workspaceservice.PrepareWorkspaceAppUploadInput{
|
|
MimeType: request.Body.MimeType,
|
|
Name: request.Body.Name,
|
|
Purpose: string(request.Body.Purpose),
|
|
SizeBytes: request.Body.SizeBytes,
|
|
})
|
|
if err != nil {
|
|
return writePrepareWorkspaceAppUploadError(err), nil
|
|
}
|
|
|
|
return tuttigenerated.PrepareWorkspaceAppUpload201JSONResponse{
|
|
ExpiresAt: session.ExpiresAt,
|
|
UploadId: session.UploadID,
|
|
}, nil
|
|
}
|
|
|
|
func (api DaemonAPI) PutWorkspaceAppUploadContent(
|
|
ctx context.Context,
|
|
request tuttigenerated.PutWorkspaceAppUploadContentRequestObject,
|
|
) (tuttigenerated.PutWorkspaceAppUploadContentResponseObject, error) {
|
|
if api.AppCenterService == nil {
|
|
return tuttigenerated.PutWorkspaceAppUploadContent503JSONResponse{
|
|
ServiceUnavailableErrorJSONResponse: workspaceAppServiceUnavailableError(),
|
|
}, nil
|
|
}
|
|
workspaceID, appID, errResponse := validateWorkspaceAppPath(request.WorkspaceID, request.AppID)
|
|
if errResponse != nil {
|
|
return tuttigenerated.PutWorkspaceAppUploadContent400JSONResponse{InvalidRequestErrorJSONResponse: *errResponse}, nil
|
|
}
|
|
|
|
if err := api.AppCenterService.PutWorkspaceAppUploadContent(ctx, workspaceID, appID, request.UploadID, workspaceservice.PutWorkspaceAppUploadContentInput{
|
|
Body: request.Body,
|
|
}); err != nil {
|
|
return writePutWorkspaceAppUploadContentError(err), nil
|
|
}
|
|
|
|
return tuttigenerated.PutWorkspaceAppUploadContent204Response{}, nil
|
|
}
|
|
|
|
func (api DaemonAPI) CompleteWorkspaceAppUpload(
|
|
ctx context.Context,
|
|
request tuttigenerated.CompleteWorkspaceAppUploadRequestObject,
|
|
) (tuttigenerated.CompleteWorkspaceAppUploadResponseObject, error) {
|
|
if api.AppCenterService == nil {
|
|
return tuttigenerated.CompleteWorkspaceAppUpload503JSONResponse{
|
|
ServiceUnavailableErrorJSONResponse: workspaceAppServiceUnavailableError(),
|
|
}, nil
|
|
}
|
|
workspaceID, appID, errResponse := validateWorkspaceAppPath(request.WorkspaceID, request.AppID)
|
|
if errResponse != nil {
|
|
return tuttigenerated.CompleteWorkspaceAppUpload400JSONResponse{InvalidRequestErrorJSONResponse: *errResponse}, nil
|
|
}
|
|
|
|
file, err := api.AppCenterService.CompleteWorkspaceAppUpload(ctx, workspaceID, appID, request.UploadID, time.Now().UTC())
|
|
if err != nil {
|
|
return writeCompleteWorkspaceAppUploadError(err), nil
|
|
}
|
|
|
|
return tuttigenerated.CompleteWorkspaceAppUpload200JSONResponse{
|
|
File: generatedWorkspaceAppUploadedFile(file),
|
|
}, nil
|
|
}
|
|
|
|
func (api DaemonAPI) CancelWorkspaceAppUpload(
|
|
ctx context.Context,
|
|
request tuttigenerated.CancelWorkspaceAppUploadRequestObject,
|
|
) (tuttigenerated.CancelWorkspaceAppUploadResponseObject, error) {
|
|
if api.AppCenterService == nil {
|
|
return tuttigenerated.CancelWorkspaceAppUpload503JSONResponse{
|
|
ServiceUnavailableErrorJSONResponse: workspaceAppServiceUnavailableError(),
|
|
}, nil
|
|
}
|
|
workspaceID, appID, errResponse := validateWorkspaceAppPath(request.WorkspaceID, request.AppID)
|
|
if errResponse != nil {
|
|
return tuttigenerated.CancelWorkspaceAppUpload400JSONResponse{InvalidRequestErrorJSONResponse: *errResponse}, nil
|
|
}
|
|
|
|
if err := api.AppCenterService.CancelWorkspaceAppUpload(ctx, workspaceID, appID, request.UploadID); err != nil {
|
|
return writeCancelWorkspaceAppUploadError(err), nil
|
|
}
|
|
|
|
return tuttigenerated.CancelWorkspaceAppUpload204Response{}, nil
|
|
}
|
|
|
|
func generatedWorkspaceAppUploadedFile(file workspaceservice.WorkspaceAppUploadedFile) tuttigenerated.WorkspaceAppUploadedFile {
|
|
return tuttigenerated.WorkspaceAppUploadedFile{
|
|
MimeType: file.MimeType,
|
|
Name: file.Name,
|
|
Path: file.Path,
|
|
Sha256: file.SHA256,
|
|
SizeBytes: file.SizeBytes,
|
|
}
|
|
}
|
|
|
|
func writeCancelWorkspaceAppUploadError(err error) tuttigenerated.CancelWorkspaceAppUploadResponseObject {
|
|
protocolErr := apierrors.Classify(err)
|
|
switch protocolErr.Code {
|
|
case tuttigenerated.WorkspaceNotFound, tuttigenerated.WorkspaceAppNotFound:
|
|
return tuttigenerated.CancelWorkspaceAppUpload404JSONResponse{
|
|
WorkspaceAppNotFoundErrorJSONResponse: workspaceAppNotFoundError(protocolErr),
|
|
}
|
|
case tuttigenerated.InvalidRequest:
|
|
return tuttigenerated.CancelWorkspaceAppUpload400JSONResponse{
|
|
InvalidRequestErrorJSONResponse: invalidRequestError(protocolErr),
|
|
}
|
|
default:
|
|
return tuttigenerated.CancelWorkspaceAppUpload502JSONResponse{
|
|
WorkspaceOperationErrorJSONResponse: workspaceOperationError(protocolErr),
|
|
}
|
|
}
|
|
}
|
|
|
|
func writePrepareWorkspaceAppUploadError(err error) tuttigenerated.PrepareWorkspaceAppUploadResponseObject {
|
|
protocolErr := apierrors.Classify(err)
|
|
switch protocolErr.Code {
|
|
case tuttigenerated.WorkspaceNotFound, tuttigenerated.WorkspaceAppNotFound:
|
|
return tuttigenerated.PrepareWorkspaceAppUpload404JSONResponse{
|
|
WorkspaceAppNotFoundErrorJSONResponse: workspaceAppNotFoundError(protocolErr),
|
|
}
|
|
case tuttigenerated.InvalidRequest:
|
|
return tuttigenerated.PrepareWorkspaceAppUpload400JSONResponse{
|
|
InvalidRequestErrorJSONResponse: invalidRequestError(protocolErr),
|
|
}
|
|
default:
|
|
return tuttigenerated.PrepareWorkspaceAppUpload502JSONResponse{
|
|
WorkspaceOperationErrorJSONResponse: workspaceOperationError(protocolErr),
|
|
}
|
|
}
|
|
}
|
|
|
|
func writePutWorkspaceAppUploadContentError(err error) tuttigenerated.PutWorkspaceAppUploadContentResponseObject {
|
|
protocolErr := apierrors.Classify(err)
|
|
switch protocolErr.Code {
|
|
case tuttigenerated.WorkspaceNotFound, tuttigenerated.WorkspaceAppNotFound:
|
|
return tuttigenerated.PutWorkspaceAppUploadContent404JSONResponse{
|
|
WorkspaceAppNotFoundErrorJSONResponse: workspaceAppNotFoundError(protocolErr),
|
|
}
|
|
case tuttigenerated.InvalidRequest:
|
|
return tuttigenerated.PutWorkspaceAppUploadContent400JSONResponse{
|
|
InvalidRequestErrorJSONResponse: invalidRequestError(protocolErr),
|
|
}
|
|
default:
|
|
return tuttigenerated.PutWorkspaceAppUploadContent502JSONResponse{
|
|
WorkspaceOperationErrorJSONResponse: workspaceOperationError(protocolErr),
|
|
}
|
|
}
|
|
}
|
|
|
|
func writeCompleteWorkspaceAppUploadError(err error) tuttigenerated.CompleteWorkspaceAppUploadResponseObject {
|
|
protocolErr := apierrors.Classify(err)
|
|
switch protocolErr.Code {
|
|
case tuttigenerated.WorkspaceNotFound, tuttigenerated.WorkspaceAppNotFound:
|
|
return tuttigenerated.CompleteWorkspaceAppUpload404JSONResponse{
|
|
WorkspaceAppNotFoundErrorJSONResponse: workspaceAppNotFoundError(protocolErr),
|
|
}
|
|
case tuttigenerated.InvalidRequest:
|
|
return tuttigenerated.CompleteWorkspaceAppUpload400JSONResponse{
|
|
InvalidRequestErrorJSONResponse: invalidRequestError(protocolErr),
|
|
}
|
|
default:
|
|
return tuttigenerated.CompleteWorkspaceAppUpload502JSONResponse{
|
|
WorkspaceOperationErrorJSONResponse: workspaceOperationError(protocolErr),
|
|
}
|
|
}
|
|
}
|