diff --git a/pkg/openapi/example.go b/pkg/openapi/example.go index 11e880c..15022f0 100644 --- a/pkg/openapi/example.go +++ b/pkg/openapi/example.go @@ -1,11 +1,12 @@ package openapi import ( - "github.com/bitechdev/ResolveSpec/pkg/modelregistry" - "github.com/bitechdev/ResolveSpec/pkg/restheadspec" - "github.com/bitechdev/ResolveSpec/pkg/resolvespec" "github.com/gorilla/mux" "gorm.io/gorm" + + "github.com/bitechdev/ResolveSpec/pkg/modelregistry" + "github.com/bitechdev/ResolveSpec/pkg/resolvespec" + "github.com/bitechdev/ResolveSpec/pkg/restheadspec" ) // ExampleRestheadSpec shows how to configure OpenAPI generation for RestheadSpec @@ -25,11 +26,11 @@ func ExampleRestheadSpec(db *gorm.DB) { // 3. Configure OpenAPI generator handler.SetOpenAPIGenerator(func() (string, error) { generator := NewGenerator(GeneratorConfig{ - Title: "My API", - Description: "API documentation for my application", - Version: "1.0.0", - BaseURL: "http://localhost:8080", - Registry: registry, + Title: "My API", + Description: "API documentation for my application", + Version: "1.0.0", + BaseURL: "http://localhost:8080", + Registry: registry, IncludeRestheadSpec: true, IncludeResolveSpec: false, IncludeFuncSpec: false, @@ -66,11 +67,11 @@ func ExampleResolveSpec(db *gorm.DB) { // 3. Configure OpenAPI generator handler.SetOpenAPIGenerator(func() (string, error) { generator := NewGenerator(GeneratorConfig{ - Title: "My API", - Description: "API documentation for my application", - Version: "1.0.0", - BaseURL: "http://localhost:8080", - Registry: registry, + Title: "My API", + Description: "API documentation for my application", + Version: "1.0.0", + BaseURL: "http://localhost:8080", + Registry: registry, IncludeRestheadSpec: false, IncludeResolveSpec: true, IncludeFuncSpec: false, @@ -110,11 +111,11 @@ func ExampleBothSpecs(db *gorm.DB) { // Configure OpenAPI generator for both generatorFunc := func() (string, error) { generator := NewGenerator(GeneratorConfig{ - Title: "My Unified API", - Description: "Complete API documentation with both RestheadSpec and ResolveSpec endpoints", - Version: "1.0.0", - BaseURL: "http://localhost:8080", - Registry: sharedRegistry, + Title: "My Unified API", + Description: "Complete API documentation with both RestheadSpec and ResolveSpec endpoints", + Version: "1.0.0", + BaseURL: "http://localhost:8080", + Registry: sharedRegistry, IncludeRestheadSpec: true, IncludeResolveSpec: true, IncludeFuncSpec: false, @@ -165,11 +166,11 @@ func ExampleWithFuncSpec() { } generator := NewGenerator(GeneratorConfig{ - Title: "My API with Custom Queries", - Description: "API with FuncSpec custom SQL endpoints", - Version: "1.0.0", - BaseURL: "http://localhost:8080", - Registry: modelregistry.NewModelRegistry(), + Title: "My API with Custom Queries", + Description: "API with FuncSpec custom SQL endpoints", + Version: "1.0.0", + BaseURL: "http://localhost:8080", + Registry: modelregistry.NewModelRegistry(), IncludeRestheadSpec: false, IncludeResolveSpec: false, IncludeFuncSpec: true, @@ -197,11 +198,11 @@ func ExampleCustomization() { // Advanced configuration - create generator function generatorFunc := func() (string, error) { generator := NewGenerator(GeneratorConfig{ - Title: "My Advanced API", - Description: "Comprehensive API documentation with custom configuration", - Version: "2.1.0", - BaseURL: "https://api.myapp.com", - Registry: registry, + Title: "My Advanced API", + Description: "Comprehensive API documentation with custom configuration", + Version: "2.1.0", + BaseURL: "https://api.myapp.com", + Registry: registry, IncludeRestheadSpec: true, IncludeResolveSpec: true, IncludeFuncSpec: false, diff --git a/pkg/openapi/generator.go b/pkg/openapi/generator.go index d4a47df..61593c3 100644 --- a/pkg/openapi/generator.go +++ b/pkg/openapi/generator.go @@ -20,9 +20,9 @@ type OpenAPISpec struct { } type Info struct { - Title string `json:"title"` - Description string `json:"description,omitempty"` - Version string `json:"version"` + Title string `json:"title"` + Description string `json:"description,omitempty"` + Version string `json:"version"` Contact *Contact `json:"contact,omitempty"` } @@ -47,22 +47,22 @@ type PathItem struct { } type Operation struct { - Summary string `json:"summary,omitempty"` - Description string `json:"description,omitempty"` - OperationID string `json:"operationId,omitempty"` - Tags []string `json:"tags,omitempty"` - Parameters []Parameter `json:"parameters,omitempty"` - RequestBody *RequestBody `json:"requestBody,omitempty"` - Responses map[string]Response `json:"responses"` + Summary string `json:"summary,omitempty"` + Description string `json:"description,omitempty"` + OperationID string `json:"operationId,omitempty"` + Tags []string `json:"tags,omitempty"` + Parameters []Parameter `json:"parameters,omitempty"` + RequestBody *RequestBody `json:"requestBody,omitempty"` + Responses map[string]Response `json:"responses"` Security []map[string][]string `json:"security,omitempty"` } type Parameter struct { - Name string `json:"name"` - In string `json:"in"` // "query", "header", "path", "cookie" - Description string `json:"description,omitempty"` - Required bool `json:"required,omitempty"` - Schema *Schema `json:"schema,omitempty"` + Name string `json:"name"` + In string `json:"in"` // "query", "header", "path", "cookie" + Description string `json:"description,omitempty"` + Required bool `json:"required,omitempty"` + Schema *Schema `json:"schema,omitempty"` Example interface{} `json:"example,omitempty"` } @@ -103,21 +103,21 @@ type Schema struct { } type SecurityScheme struct { - Type string `json:"type"` // "apiKey", "http", "oauth2", "openIdConnect" - Description string `json:"description,omitempty"` - Name string `json:"name,omitempty"` // For apiKey - In string `json:"in,omitempty"` // For apiKey: "query", "header", "cookie" - Scheme string `json:"scheme,omitempty"` // For http: "basic", "bearer" + Type string `json:"type"` // "apiKey", "http", "oauth2", "openIdConnect" + Description string `json:"description,omitempty"` + Name string `json:"name,omitempty"` // For apiKey + In string `json:"in,omitempty"` // For apiKey: "query", "header", "cookie" + Scheme string `json:"scheme,omitempty"` // For http: "basic", "bearer" BearerFormat string `json:"bearerFormat,omitempty"` // For http bearer } // GeneratorConfig holds configuration for OpenAPI spec generation type GeneratorConfig struct { - Title string - Description string - Version string - BaseURL string - Registry *modelregistry.DefaultModelRegistry + Title string + Description string + Version string + BaseURL string + Registry *modelregistry.DefaultModelRegistry IncludeRestheadSpec bool IncludeResolveSpec bool IncludeFuncSpec bool @@ -234,8 +234,8 @@ func (g *Generator) addCommonSchemas(spec *OpenAPISpec) { spec.Components.Schemas["Response"] = Schema{ Type: "object", Properties: map[string]*Schema{ - "success": {Type: "boolean", Description: "Indicates if the operation was successful"}, - "data": {Description: "The response data"}, + "success": {Type: "boolean", Description: "Indicates if the operation was successful"}, + "data": {Description: "The response data"}, "metadata": {Ref: "#/components/schemas/Metadata"}, "error": {Ref: "#/components/schemas/APIError"}, }, diff --git a/pkg/resolvespec/handler.go b/pkg/resolvespec/handler.go index 52fff72..d410851 100644 --- a/pkg/resolvespec/handler.go +++ b/pkg/resolvespec/handler.go @@ -22,12 +22,12 @@ type FallbackHandler func(w common.ResponseWriter, r common.Request, params map[ // Handler handles API requests using database and model abstractions type Handler struct { - db common.Database - registry common.ModelRegistry - nestedProcessor *common.NestedCUDProcessor - hooks *HookRegistry - fallbackHandler FallbackHandler - openAPIGenerator func() (string, error) + db common.Database + registry common.ModelRegistry + nestedProcessor *common.NestedCUDProcessor + hooks *HookRegistry + fallbackHandler FallbackHandler + openAPIGenerator func() (string, error) } // NewHandler creates a new API handler with database and registry abstractions @@ -1464,7 +1464,10 @@ func (h *Handler) HandleOpenAPI(w common.ResponseWriter, r common.Request) { w.SetHeader("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - w.Write([]byte(spec)) + _, err = w.Write([]byte(spec)) + if err != nil { + logger.Error("Error sending OpenAPI spec response: %v", err) + } } // SetOpenAPIGenerator sets the OpenAPI generator function diff --git a/pkg/restheadspec/handler.go b/pkg/restheadspec/handler.go index a579dbb..df239fb 100644 --- a/pkg/restheadspec/handler.go +++ b/pkg/restheadspec/handler.go @@ -24,12 +24,12 @@ type FallbackHandler func(w common.ResponseWriter, r common.Request, params map[ // Handler handles API requests using database and model abstractions // This handler reads filters, columns, and options from HTTP headers type Handler struct { - db common.Database - registry common.ModelRegistry - hooks *HookRegistry - nestedProcessor *common.NestedCUDProcessor - fallbackHandler FallbackHandler - openAPIGenerator func() (string, error) + db common.Database + registry common.ModelRegistry + hooks *HookRegistry + nestedProcessor *common.NestedCUDProcessor + fallbackHandler FallbackHandler + openAPIGenerator func() (string, error) } // NewHandler creates a new API handler with database and registry abstractions @@ -2413,7 +2413,10 @@ func (h *Handler) HandleOpenAPI(w common.ResponseWriter, r common.Request) { w.SetHeader("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - w.Write([]byte(spec)) + _, err = w.Write([]byte(spec)) + if err != nil { + logger.Error("Error sending OpenAPI spec response: %v", err) + } } // SetOpenAPIGenerator sets the OpenAPI generator function