Add M0 server skeleton with SQLite store, SSE events, worktrees, and tailscale service
This commit is contained in:
@@ -0,0 +1,688 @@
|
||||
//go:build go1.22
|
||||
|
||||
// Package api provides primitives to interact with the openapi HTTP API.
|
||||
//
|
||||
// Code generated by github.com/oapi-codegen/oapi-codegen/v2 version v2.8.0 DO NOT EDIT.
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/flate"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/oapi-codegen/runtime"
|
||||
)
|
||||
|
||||
// Defines values for TaskStatus.
|
||||
const (
|
||||
Active TaskStatus = "active"
|
||||
Completed TaskStatus = "completed"
|
||||
)
|
||||
|
||||
// Valid indicates whether the value is a known member of the TaskStatus enum.
|
||||
func (e TaskStatus) Valid() bool {
|
||||
switch e {
|
||||
case Active:
|
||||
return true
|
||||
case Completed:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Error defines model for Error.
|
||||
type Error struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// Event defines model for Event.
|
||||
type Event struct {
|
||||
Actor string `json:"actor"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Kind string `json:"kind"`
|
||||
Payload map[string]interface{} `json:"payload"`
|
||||
ProjectId *string `json:"project_id,omitempty"`
|
||||
Seq int64 `json:"seq"`
|
||||
TaskId *string `json:"task_id,omitempty"`
|
||||
}
|
||||
|
||||
// Project defines model for Project.
|
||||
type Project struct {
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
CreatedBy string `json:"created_by"`
|
||||
DefaultBranch string `json:"default_branch"`
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Remote string `json:"remote"`
|
||||
RepoPath string `json:"repo_path"`
|
||||
}
|
||||
|
||||
// ProjectCreate defines model for ProjectCreate.
|
||||
type ProjectCreate struct {
|
||||
Name string `json:"name"`
|
||||
RepoPath string `json:"repo_path"`
|
||||
}
|
||||
|
||||
// Status defines model for Status.
|
||||
type Status struct {
|
||||
ActiveTasks int `json:"active_tasks"`
|
||||
DbBytes int64 `json:"db_bytes"`
|
||||
LastEventSeq int64 `json:"last_event_seq"`
|
||||
Projects int `json:"projects"`
|
||||
SseClients int `json:"sse_clients"`
|
||||
StartedAt time.Time `json:"started_at"`
|
||||
}
|
||||
|
||||
// Task defines model for Task.
|
||||
type Task struct {
|
||||
BaseRef string `json:"base_ref"`
|
||||
Branch string `json:"branch"`
|
||||
CompletedAt *time.Time `json:"completed_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
CreatedBy string `json:"created_by"`
|
||||
Id string `json:"id"`
|
||||
ProjectId string `json:"project_id"`
|
||||
Status TaskStatus `json:"status"`
|
||||
Title string `json:"title"`
|
||||
WorktreePath string `json:"worktree_path"`
|
||||
}
|
||||
|
||||
// TaskStatus defines model for Task.Status.
|
||||
type TaskStatus string
|
||||
|
||||
// TaskCreate defines model for TaskCreate.
|
||||
type TaskCreate struct {
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
// User defines model for User.
|
||||
type User struct {
|
||||
DisplayName string `json:"display_name"`
|
||||
GitEmail string `json:"git_email"`
|
||||
GitName string `json:"git_name"`
|
||||
Login string `json:"login"`
|
||||
}
|
||||
|
||||
// UserUpdate defines model for UserUpdate.
|
||||
type UserUpdate struct {
|
||||
GitEmail string `json:"git_email"`
|
||||
GitName string `json:"git_name"`
|
||||
}
|
||||
|
||||
// StreamEventsParams defines parameters for StreamEvents.
|
||||
type StreamEventsParams struct {
|
||||
After *int64 `form:"after,omitempty" json:"after,omitempty"`
|
||||
LastEventID *int64 `json:"Last-Event-ID,omitempty"`
|
||||
}
|
||||
|
||||
// UpdateMeJSONRequestBody defines body for UpdateMe for application/json ContentType.
|
||||
type UpdateMeJSONRequestBody = UserUpdate
|
||||
|
||||
// CreateProjectJSONRequestBody defines body for CreateProject for application/json ContentType.
|
||||
type CreateProjectJSONRequestBody = ProjectCreate
|
||||
|
||||
// CreateTaskJSONRequestBody defines body for CreateTask for application/json ContentType.
|
||||
type CreateTaskJSONRequestBody = TaskCreate
|
||||
|
||||
// ServerInterface represents all server handlers.
|
||||
type ServerInterface interface {
|
||||
|
||||
// (GET /api/admin/status)
|
||||
GetStatus(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
// (GET /api/events)
|
||||
StreamEvents(w http.ResponseWriter, r *http.Request, params StreamEventsParams)
|
||||
|
||||
// (GET /api/me)
|
||||
GetMe(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
// (PUT /api/me)
|
||||
UpdateMe(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
// (GET /api/projects)
|
||||
ListProjects(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
// (POST /api/projects)
|
||||
CreateProject(w http.ResponseWriter, r *http.Request)
|
||||
|
||||
// (GET /api/projects/{projectId})
|
||||
GetProject(w http.ResponseWriter, r *http.Request, projectId string)
|
||||
|
||||
// (GET /api/projects/{projectId}/tasks)
|
||||
ListTasks(w http.ResponseWriter, r *http.Request, projectId string)
|
||||
|
||||
// (POST /api/projects/{projectId}/tasks)
|
||||
CreateTask(w http.ResponseWriter, r *http.Request, projectId string)
|
||||
|
||||
// (GET /api/tasks/{taskId})
|
||||
GetTask(w http.ResponseWriter, r *http.Request, taskId string)
|
||||
|
||||
// (POST /api/tasks/{taskId}/complete)
|
||||
CompleteTask(w http.ResponseWriter, r *http.Request, taskId string)
|
||||
}
|
||||
|
||||
// ServerInterfaceWrapper converts contexts to parameters.
|
||||
type ServerInterfaceWrapper struct {
|
||||
Handler ServerInterface
|
||||
HandlerMiddlewares []MiddlewareFunc
|
||||
ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
|
||||
}
|
||||
|
||||
type MiddlewareFunc func(http.Handler) http.Handler
|
||||
|
||||
// GetStatus operation middleware
|
||||
func (siw *ServerInterfaceWrapper) GetStatus(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.GetStatus(w, r)
|
||||
}))
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// StreamEvents operation middleware
|
||||
func (siw *ServerInterfaceWrapper) StreamEvents(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var err error
|
||||
_ = err
|
||||
|
||||
// Parameter object where we will unmarshal all parameters from the context
|
||||
var params StreamEventsParams
|
||||
|
||||
// ------------- Optional query parameter "after" -------------
|
||||
|
||||
err = runtime.BindQueryParameterWithOptions("form", true, false, "after", r.URL.Query(), ¶ms.After, runtime.BindQueryParameterOptions{Type: "integer", Format: "int64"})
|
||||
if err != nil {
|
||||
var requiredError *runtime.RequiredParameterError
|
||||
if errors.As(err, &requiredError) {
|
||||
siw.ErrorHandlerFunc(w, r, &RequiredParamError{ParamName: "after"})
|
||||
} else {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "after", Err: err})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
headers := r.Header
|
||||
|
||||
// ------------- Optional header parameter "Last-Event-ID" -------------
|
||||
if valueList, found := headers[http.CanonicalHeaderKey("Last-Event-ID")]; found {
|
||||
var LastEventID int64
|
||||
n := len(valueList)
|
||||
if n != 1 {
|
||||
siw.ErrorHandlerFunc(w, r, &TooManyValuesForParamError{ParamName: "Last-Event-ID", Count: n})
|
||||
return
|
||||
}
|
||||
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "Last-Event-ID", valueList[0], &LastEventID, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationHeader, Explode: false, Required: false, Type: "integer", Format: "int64"})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "Last-Event-ID", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
params.LastEventID = &LastEventID
|
||||
|
||||
}
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.StreamEvents(w, r, params)
|
||||
}))
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// GetMe operation middleware
|
||||
func (siw *ServerInterfaceWrapper) GetMe(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.GetMe(w, r)
|
||||
}))
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// UpdateMe operation middleware
|
||||
func (siw *ServerInterfaceWrapper) UpdateMe(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.UpdateMe(w, r)
|
||||
}))
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// ListProjects operation middleware
|
||||
func (siw *ServerInterfaceWrapper) ListProjects(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.ListProjects(w, r)
|
||||
}))
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// CreateProject operation middleware
|
||||
func (siw *ServerInterfaceWrapper) CreateProject(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.CreateProject(w, r)
|
||||
}))
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// GetProject operation middleware
|
||||
func (siw *ServerInterfaceWrapper) GetProject(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var err error
|
||||
_ = err
|
||||
|
||||
// ------------- Path parameter "projectId" -------------
|
||||
var projectId string
|
||||
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "projectId", r.PathValue("projectId"), &projectId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "", ValueIsUnescaped: true})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectId", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.GetProject(w, r, projectId)
|
||||
}))
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// ListTasks operation middleware
|
||||
func (siw *ServerInterfaceWrapper) ListTasks(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var err error
|
||||
_ = err
|
||||
|
||||
// ------------- Path parameter "projectId" -------------
|
||||
var projectId string
|
||||
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "projectId", r.PathValue("projectId"), &projectId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "", ValueIsUnescaped: true})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectId", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.ListTasks(w, r, projectId)
|
||||
}))
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// CreateTask operation middleware
|
||||
func (siw *ServerInterfaceWrapper) CreateTask(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var err error
|
||||
_ = err
|
||||
|
||||
// ------------- Path parameter "projectId" -------------
|
||||
var projectId string
|
||||
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "projectId", r.PathValue("projectId"), &projectId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "", ValueIsUnescaped: true})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "projectId", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.CreateTask(w, r, projectId)
|
||||
}))
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// GetTask operation middleware
|
||||
func (siw *ServerInterfaceWrapper) GetTask(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var err error
|
||||
_ = err
|
||||
|
||||
// ------------- Path parameter "taskId" -------------
|
||||
var taskId string
|
||||
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "taskId", r.PathValue("taskId"), &taskId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "", ValueIsUnescaped: true})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "taskId", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.GetTask(w, r, taskId)
|
||||
}))
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
// CompleteTask operation middleware
|
||||
func (siw *ServerInterfaceWrapper) CompleteTask(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
var err error
|
||||
_ = err
|
||||
|
||||
// ------------- Path parameter "taskId" -------------
|
||||
var taskId string
|
||||
|
||||
err = runtime.BindStyledParameterWithOptions("simple", "taskId", r.PathValue("taskId"), &taskId, runtime.BindStyledParameterOptions{ParamLocation: runtime.ParamLocationPath, Explode: false, Required: true, Type: "string", Format: "", ValueIsUnescaped: true})
|
||||
if err != nil {
|
||||
siw.ErrorHandlerFunc(w, r, &InvalidParamFormatError{ParamName: "taskId", Err: err})
|
||||
return
|
||||
}
|
||||
|
||||
handler := http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
siw.Handler.CompleteTask(w, r, taskId)
|
||||
}))
|
||||
|
||||
for _, middleware := range siw.HandlerMiddlewares {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
type UnescapedCookieParamError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *UnescapedCookieParamError) Error() string {
|
||||
return fmt.Sprintf("error unescaping cookie parameter '%s'", e.ParamName)
|
||||
}
|
||||
|
||||
func (e *UnescapedCookieParamError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type UnmarshalingParamError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *UnmarshalingParamError) Error() string {
|
||||
return fmt.Sprintf("Error unmarshaling parameter %s as JSON: %s", e.ParamName, e.Err.Error())
|
||||
}
|
||||
|
||||
func (e *UnmarshalingParamError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type RequiredParamError struct {
|
||||
ParamName string
|
||||
}
|
||||
|
||||
func (e *RequiredParamError) Error() string {
|
||||
return fmt.Sprintf("Query argument %s is required, but not found", e.ParamName)
|
||||
}
|
||||
|
||||
type RequiredHeaderError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *RequiredHeaderError) Error() string {
|
||||
return fmt.Sprintf("Header parameter %s is required, but not found", e.ParamName)
|
||||
}
|
||||
|
||||
func (e *RequiredHeaderError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type InvalidParamFormatError struct {
|
||||
ParamName string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *InvalidParamFormatError) Error() string {
|
||||
return fmt.Sprintf("Invalid format for parameter %s: %s", e.ParamName, e.Err.Error())
|
||||
}
|
||||
|
||||
func (e *InvalidParamFormatError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
type TooManyValuesForParamError struct {
|
||||
ParamName string
|
||||
Count int
|
||||
}
|
||||
|
||||
func (e *TooManyValuesForParamError) Error() string {
|
||||
return fmt.Sprintf("Expected one value for %s, got %d", e.ParamName, e.Count)
|
||||
}
|
||||
|
||||
// Handler creates http.Handler with routing matching OpenAPI spec.
|
||||
func Handler(si ServerInterface) http.Handler {
|
||||
return HandlerWithOptions(si, StdHTTPServerOptions{})
|
||||
}
|
||||
|
||||
// ServeMux is an abstraction of [http.ServeMux].
|
||||
type ServeMux interface {
|
||||
HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
|
||||
http.Handler
|
||||
}
|
||||
|
||||
type StdHTTPServerOptions struct {
|
||||
BaseURL string
|
||||
BaseRouter ServeMux
|
||||
Middlewares []MiddlewareFunc
|
||||
ErrorHandlerFunc func(w http.ResponseWriter, r *http.Request, err error)
|
||||
}
|
||||
|
||||
// HandlerFromMux creates http.Handler with routing matching OpenAPI spec based on the provided mux.
|
||||
func HandlerFromMux(si ServerInterface, m ServeMux) http.Handler {
|
||||
return HandlerWithOptions(si, StdHTTPServerOptions{
|
||||
BaseRouter: m,
|
||||
})
|
||||
}
|
||||
|
||||
func HandlerFromMuxWithBaseURL(si ServerInterface, m ServeMux, baseURL string) http.Handler {
|
||||
return HandlerWithOptions(si, StdHTTPServerOptions{
|
||||
BaseURL: baseURL,
|
||||
BaseRouter: m,
|
||||
})
|
||||
}
|
||||
|
||||
// HandlerWithOptions creates http.Handler with additional options
|
||||
func HandlerWithOptions(si ServerInterface, options StdHTTPServerOptions) http.Handler {
|
||||
m := options.BaseRouter
|
||||
|
||||
if m == nil {
|
||||
m = http.NewServeMux()
|
||||
}
|
||||
if options.ErrorHandlerFunc == nil {
|
||||
options.ErrorHandlerFunc = func(w http.ResponseWriter, r *http.Request, err error) {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
wrapper := ServerInterfaceWrapper{
|
||||
Handler: si,
|
||||
HandlerMiddlewares: options.Middlewares,
|
||||
ErrorHandlerFunc: options.ErrorHandlerFunc,
|
||||
}
|
||||
|
||||
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/me", wrapper.GetMe)
|
||||
m.HandleFunc(http.MethodPut+" "+options.BaseURL+"/api/me", wrapper.UpdateMe)
|
||||
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/projects", wrapper.ListProjects)
|
||||
m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/projects", wrapper.CreateProject)
|
||||
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/projects/{projectId}", wrapper.GetProject)
|
||||
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/projects/{projectId}/tasks", wrapper.ListTasks)
|
||||
m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/projects/{projectId}/tasks", wrapper.CreateTask)
|
||||
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/tasks/{taskId}", wrapper.GetTask)
|
||||
m.HandleFunc(http.MethodPost+" "+options.BaseURL+"/api/tasks/{taskId}/complete", wrapper.CompleteTask)
|
||||
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/events", wrapper.StreamEvents)
|
||||
m.HandleFunc(http.MethodGet+" "+options.BaseURL+"/api/admin/status", wrapper.GetStatus)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// Base64 encoded, compressed with deflate, json marshaled OpenAPI spec.
|
||||
// Stored as a slice of fixed-width chunks rather than one concatenated
|
||||
// const string: with thousands of chunks the chained `+` fold is several
|
||||
// times slower for the Go compiler than parsing a slice literal.
|
||||
var swaggerSpec = []string{
|
||||
"zFhbb+M2E/0rBL8PSAsottsNCtR96iUoUmzbRZN92gYCLY1tbiRSGY69NQL994KkrjblS2p3+xRZJIdn",
|
||||
"Ds8ZDfPCE50XWoEiw6cvHMEUWhlwP24RNdqHRCsCRfZRFEUmE0FSq/FHo5V9Z5Il5MI+/R9hzqf8f+M2",
|
||||
"6tiPmrGPVpZlxFMwCcrCBuFTv82I24Fqbm/zAnUBSNJjysEYsQD7SJsC+JQbQqkWbjnC80oipHz6oZn4",
|
||||
"GNUT9ewjJMTLiN+uq2z6sUVCfsutyBFPEARBGgu3aq4xt088FQTXJHPg0e6aJ6nSYLBCbDItumMtsgK1",
|
||||
"fYxleKmB5x4Aqeibm3ZzqQgWgHYmCfMUjrLFkw1ZgY0qBlqIvcxDTL7zeHe5fA1j9ZrZJph8CnOxyiie",
|
||||
"oVDJMjhlgDYlcggOIOSahoYKHReClocplJYot0d32Q7gZrtepsdS/KObtUv0ntyOTmAHewjHPQlamaBr",
|
||||
"5BpiKzjT2aqjxXQWzzbkZx8h3UwYisFaND5e75VxBhAYA3GSybrKBSaQwNPkum2jNkAn4Z1kOkCjPnN9",
|
||||
"kKEDeBDmaZf+mTAQu7Ib0MAeq9gKncFrLXpGWw949lAlbNQIapXbE/Bs8k5mHRbbhSQpCxvmk8YnQoBT",
|
||||
"XN9BWYduWN+OGLVn1eA/rRRYBQzVgaG8tlD7aaHg7w0EvrepNEUmNvFgmVlIiiEXMhscHVya6YVUhyH7",
|
||||
"aVEfSid0F8NQYu+LNMjaq9FvYTwSjF0m1Vx3DozPNmiXrQGN74cmo8loYrfXBShRSD7lb0aT0Rv3Xaal",
|
||||
"wz0WhRyLNJdq3DphAc6VNj/XoN2lfMp/Brqvtdbr7r6eTM7W21U7BJq7e8A1IFuCyGjJhErZyrZltt2z",
|
||||
"k10erjx2MwiFuDagiPmpI3YrkqX/cWWYTJk0TJJhBp6/Y6kgYV/QEpjr9Jgw7Jf7338b+Z+GiTkBsrfC",
|
||||
"0LV7c333E/tCo1vhx55XgBtWCBQ5EOCXTCAwBKs/SNkM5hqBZXINNaI/rUL7zN8Tgsj9lu7sqmCGTz+8",
|
||||
"cKt8vgSRAtbdw5T3IPGow/7BT2AZVTEd9Daky+fEUI8HpULwF/lzuzYuzb5Wts2y2/O7c/FLe1rwZhtS",
|
||||
"8q9wSRW7ChgA+7AElogsk2rBVgbcXcV+oVYBkL7QVDifV2DoB51uzgqxqmVlvwYRrqD8TOSsHKK0Jifi",
|
||||
"N37jULwGYHshrM++28MFFfBWGnrX9k//KFdJkJtDSdfXm7IxiUAUmxAP32cZqxOoBaJNIAn/Aa8jX0Ym",
|
||||
"/TvDUUr56tybD4lFwaeaqDNoZfxSPd2l5b7K0eX7Qg45kHc/55sTcg5/O6qesirzDQt8+6ijPXX5cR+d",
|
||||
"4+ZKN2jGh+rqcnknusvPETbsMH1lmMsgspIDQ2wu0fzH+G+LRD8N71zfw9gkrgzztwrXQtX3CjZHnbs5",
|
||||
"bcrVPx2q6aOdrsRHdnRepvZ0Lin/cuHxGhmuOpbIk0vOqWKpHeWkN36xfw6UpuYsLlSX9tHSoeTcjvCZ",
|
||||
"v64c9ckb1zd6d3+7yMZDPvwDcr3u+7Axn3Vi5TL20I4jJBpTN+rvBgztdVAFrFil9TkF0Pyz5HVSsLO/",
|
||||
"PcUdZfl3AAAA//8=",
|
||||
}
|
||||
|
||||
// decodeSpec returns the embedded OpenAPI spec as raw JSON bytes,
|
||||
// after base64-decoding and flate-decompressing the embedded blob.
|
||||
func decodeSpec() ([]byte, error) {
|
||||
encoded := strings.Join(swaggerSpec, "")
|
||||
compressed, err := base64.StdEncoding.DecodeString(encoded)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error base64 decoding spec: %w", err)
|
||||
}
|
||||
zr := flate.NewReader(bytes.NewReader(compressed))
|
||||
var buf bytes.Buffer
|
||||
if _, err := buf.ReadFrom(zr); err != nil {
|
||||
return nil, fmt.Errorf("read flate: %w", err)
|
||||
}
|
||||
if err := zr.Close(); err != nil {
|
||||
return nil, fmt.Errorf("close flate reader: %w", err)
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
var rawSpec = decodeSpecCached()
|
||||
|
||||
// a naive cache of the decoded OpenAPI spec
|
||||
func decodeSpecCached() func() ([]byte, error) {
|
||||
data, err := decodeSpec()
|
||||
return func() ([]byte, error) {
|
||||
return data, err
|
||||
}
|
||||
}
|
||||
|
||||
// Constructs a synthetic filesystem for resolving external references when loading openapi specifications.
|
||||
func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) {
|
||||
res := make(map[string]func() ([]byte, error))
|
||||
if len(pathToFile) > 0 {
|
||||
res[pathToFile] = rawSpec
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// GetSpec returns the OpenAPI specification corresponding to the generated
|
||||
// code in this file. External references in the spec are resolved through
|
||||
// PathToRawSpec; externally-referenced files must be embedded in their
|
||||
// corresponding Go packages (via the import-mapping feature). URL-based
|
||||
// external refs are not supported.
|
||||
func GetSpec() (swagger *openapi3.T, err error) {
|
||||
resolvePath := PathToRawSpec("")
|
||||
|
||||
loader := openapi3.NewLoader()
|
||||
loader.IsExternalRefsAllowed = true
|
||||
loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) {
|
||||
pathToFile := url.String()
|
||||
pathToFile = path.Clean(pathToFile)
|
||||
getSpec, ok := resolvePath[pathToFile]
|
||||
if !ok {
|
||||
err1 := fmt.Errorf("path not found: %s", pathToFile)
|
||||
return nil, err1
|
||||
}
|
||||
return getSpec()
|
||||
}
|
||||
var specData []byte
|
||||
specData, err = rawSpec()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
swagger, err = loader.LoadFromData(specData)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetSpecJSON returns the raw JSON bytes of the embedded OpenAPI
|
||||
// specification: decompressed but not unmarshaled. External references
|
||||
// are not resolved here; the bytes are the spec exactly as embedded by
|
||||
// codegen. The result is cached at package init time, so repeated calls
|
||||
// are cheap.
|
||||
func GetSpecJSON() ([]byte, error) {
|
||||
return rawSpec()
|
||||
}
|
||||
|
||||
// GetSwagger returns the OpenAPI specification corresponding to the
|
||||
// generated code in this file.
|
||||
//
|
||||
// Deprecated: GetSwagger predates kin-openapi renaming openapi3.Swagger
|
||||
// to openapi3.T. Use [GetSpec] instead. This wrapper is retained for
|
||||
// backwards compatibility.
|
||||
func GetSwagger() (*openapi3.T, error) {
|
||||
return GetSpec()
|
||||
}
|
||||
Reference in New Issue
Block a user