mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2025-12-14 17:30:35 +00:00
322 lines
9.0 KiB
Markdown
322 lines
9.0 KiB
Markdown
# OpenAPI Generator for ResolveSpec
|
|
|
|
This package provides automatic OpenAPI 3.0 specification generation for ResolveSpec, RestheadSpec, and FuncSpec API frameworks.
|
|
|
|
## Features
|
|
|
|
- **Automatic Schema Generation**: Generates OpenAPI schemas from Go struct models
|
|
- **Multiple Framework Support**: Works with RestheadSpec, ResolveSpec, and FuncSpec
|
|
- **Dynamic Endpoint Discovery**: Automatically discovers all registered models and generates paths
|
|
- **Query Parameter Access**: Access spec via `?openapi` on any endpoint or via `/openapi`
|
|
- **Comprehensive Documentation**: Includes all request/response schemas, parameters, and security schemes
|
|
|
|
## Quick Start
|
|
|
|
### RestheadSpec Example
|
|
|
|
```go
|
|
import (
|
|
"github.com/bitechdev/ResolveSpec/pkg/openapi"
|
|
"github.com/bitechdev/ResolveSpec/pkg/restheadspec"
|
|
"github.com/gorilla/mux"
|
|
)
|
|
|
|
func main() {
|
|
// 1. Create handler
|
|
handler := restheadspec.NewHandlerWithGORM(db)
|
|
|
|
// 2. Register models
|
|
handler.registry.RegisterModel("public.users", User{})
|
|
handler.registry.RegisterModel("public.products", Product{})
|
|
|
|
// 3. Configure OpenAPI generator
|
|
handler.SetOpenAPIGenerator(func() (string, error) {
|
|
generator := openapi.NewGenerator(openapi.GeneratorConfig{
|
|
Title: "My API",
|
|
Description: "API documentation",
|
|
Version: "1.0.0",
|
|
BaseURL: "http://localhost:8080",
|
|
Registry: handler.registry.(*modelregistry.DefaultModelRegistry),
|
|
IncludeRestheadSpec: true,
|
|
IncludeResolveSpec: false,
|
|
IncludeFuncSpec: false,
|
|
})
|
|
return generator.GenerateJSON()
|
|
})
|
|
|
|
// 4. Setup routes (automatically includes /openapi endpoint)
|
|
router := mux.NewRouter()
|
|
restheadspec.SetupMuxRoutes(router, handler, nil)
|
|
|
|
// Start server
|
|
http.ListenAndServe(":8080", router)
|
|
}
|
|
```
|
|
|
|
### ResolveSpec Example
|
|
|
|
```go
|
|
func main() {
|
|
// 1. Create handler
|
|
handler := resolvespec.NewHandlerWithGORM(db)
|
|
|
|
// 2. Register models
|
|
handler.RegisterModel("public", "users", User{})
|
|
handler.RegisterModel("public", "products", Product{})
|
|
|
|
// 3. Configure OpenAPI generator
|
|
handler.SetOpenAPIGenerator(func() (string, error) {
|
|
generator := openapi.NewGenerator(openapi.GeneratorConfig{
|
|
Title: "My API",
|
|
Version: "1.0.0",
|
|
Registry: handler.registry.(*modelregistry.DefaultModelRegistry),
|
|
IncludeResolveSpec: true,
|
|
})
|
|
return generator.GenerateJSON()
|
|
})
|
|
|
|
// 4. Setup routes
|
|
router := mux.NewRouter()
|
|
resolvespec.SetupMuxRoutes(router, handler, nil)
|
|
|
|
http.ListenAndServe(":8080", router)
|
|
}
|
|
```
|
|
|
|
## Accessing the OpenAPI Specification
|
|
|
|
Once configured, the OpenAPI spec is available in two ways:
|
|
|
|
### 1. Global `/openapi` Endpoint
|
|
|
|
```bash
|
|
curl http://localhost:8080/openapi
|
|
```
|
|
|
|
Returns the complete OpenAPI specification for all registered models.
|
|
|
|
### 2. Query Parameter on Any Endpoint
|
|
|
|
```bash
|
|
# RestheadSpec
|
|
curl http://localhost:8080/public/users?openapi
|
|
|
|
# ResolveSpec
|
|
curl http://localhost:8080/resolve/public/users?openapi
|
|
```
|
|
|
|
Returns the same OpenAPI specification as `/openapi`.
|
|
|
|
## Generated Endpoints
|
|
|
|
### RestheadSpec
|
|
|
|
For each registered model (e.g., `public.users`), the following paths are generated:
|
|
|
|
- `GET /public/users` - List records with header-based filtering
|
|
- `POST /public/users` - Create a new record
|
|
- `GET /public/users/{id}` - Get a single record
|
|
- `PUT /public/users/{id}` - Update a record
|
|
- `PATCH /public/users/{id}` - Partially update a record
|
|
- `DELETE /public/users/{id}` - Delete a record
|
|
- `GET /public/users/metadata` - Get table metadata
|
|
- `OPTIONS /public/users` - CORS preflight
|
|
|
|
### ResolveSpec
|
|
|
|
For each registered model (e.g., `public.users`), the following paths are generated:
|
|
|
|
- `POST /resolve/public/users` - Execute operations (read, create, meta)
|
|
- `POST /resolve/public/users/{id}` - Execute operations (update, delete)
|
|
- `GET /resolve/public/users` - Get metadata
|
|
- `OPTIONS /resolve/public/users` - CORS preflight
|
|
|
|
## Schema Generation
|
|
|
|
The generator automatically extracts information from your Go struct tags:
|
|
|
|
```go
|
|
type User struct {
|
|
ID int `json:"id" gorm:"primaryKey" description:"User ID"`
|
|
Name string `json:"name" gorm:"not null" description:"User's full name"`
|
|
Email string `json:"email" gorm:"unique" description:"Email address"`
|
|
CreatedAt time.Time `json:"created_at" description:"Creation timestamp"`
|
|
Roles []string `json:"roles" description:"User roles"`
|
|
}
|
|
```
|
|
|
|
This generates an OpenAPI schema with:
|
|
- Property names from `json` tags
|
|
- Required fields from `gorm:"not null"` and non-pointer types
|
|
- Descriptions from `description` tags
|
|
- Proper type mappings (int → integer, time.Time → string with format: date-time, etc.)
|
|
|
|
## RestheadSpec Headers
|
|
|
|
The generator documents all RestheadSpec HTTP headers:
|
|
|
|
- `X-Filters` - JSON array of filter conditions
|
|
- `X-Columns` - Comma-separated columns to select
|
|
- `X-Sort` - JSON array of sort specifications
|
|
- `X-Limit` - Maximum records to return
|
|
- `X-Offset` - Records to skip
|
|
- `X-Preload` - Relations to eager load
|
|
- `X-Expand` - Relations to expand (LEFT JOIN)
|
|
- `X-Distinct` - Enable DISTINCT queries
|
|
- `X-Response-Format` - Response format (detail, simple, syncfusion)
|
|
- `X-Clean-JSON` - Remove null/empty fields
|
|
- `X-Custom-SQL-Where` - Custom WHERE clause (AND)
|
|
- `X-Custom-SQL-Or` - Custom WHERE clause (OR)
|
|
|
|
## ResolveSpec Request Body
|
|
|
|
The generator documents the ResolveSpec request body structure:
|
|
|
|
```json
|
|
{
|
|
"operation": "read",
|
|
"data": {},
|
|
"id": 123,
|
|
"options": {
|
|
"limit": 10,
|
|
"offset": 0,
|
|
"filters": [
|
|
{"column": "status", "operator": "eq", "value": "active"}
|
|
],
|
|
"sort": [
|
|
{"column": "created_at", "direction": "desc"}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
## Security Schemes
|
|
|
|
The generator automatically includes common security schemes:
|
|
|
|
- **BearerAuth**: JWT Bearer token authentication
|
|
- **SessionToken**: Session token in Authorization header
|
|
- **CookieAuth**: Cookie-based session authentication
|
|
- **HeaderAuth**: Header-based user authentication (X-User-ID)
|
|
|
|
## FuncSpec Custom Endpoints
|
|
|
|
For FuncSpec, you can manually register custom SQL endpoints:
|
|
|
|
```go
|
|
funcSpecEndpoints := map[string]openapi.FuncSpecEndpoint{
|
|
"/api/reports/sales": {
|
|
Path: "/api/reports/sales",
|
|
Method: "GET",
|
|
Summary: "Get sales report",
|
|
Description: "Returns sales data for specified date range",
|
|
SQLQuery: "SELECT * FROM sales WHERE date BETWEEN [start_date] AND [end_date]",
|
|
Parameters: []string{"start_date", "end_date"},
|
|
},
|
|
}
|
|
|
|
generator := openapi.NewGenerator(openapi.GeneratorConfig{
|
|
// ... other config
|
|
IncludeFuncSpec: true,
|
|
FuncSpecEndpoints: funcSpecEndpoints,
|
|
})
|
|
```
|
|
|
|
## Combining Multiple Frameworks
|
|
|
|
You can generate a unified OpenAPI spec that includes multiple frameworks:
|
|
|
|
```go
|
|
generator := openapi.NewGenerator(openapi.GeneratorConfig{
|
|
Title: "Unified API",
|
|
Version: "1.0.0",
|
|
Registry: sharedRegistry,
|
|
IncludeRestheadSpec: true,
|
|
IncludeResolveSpec: true,
|
|
IncludeFuncSpec: true,
|
|
FuncSpecEndpoints: funcSpecEndpoints,
|
|
})
|
|
```
|
|
|
|
This will generate a complete spec with all endpoints from all frameworks.
|
|
|
|
## Advanced Customization
|
|
|
|
You can customize the generated spec further:
|
|
|
|
```go
|
|
handler.SetOpenAPIGenerator(func() (string, error) {
|
|
generator := openapi.NewGenerator(config)
|
|
|
|
// Generate initial spec
|
|
spec, err := generator.Generate()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// Add contact information
|
|
spec.Info.Contact = &openapi.Contact{
|
|
Name: "API Support",
|
|
Email: "support@example.com",
|
|
URL: "https://example.com/support",
|
|
}
|
|
|
|
// Add additional servers
|
|
spec.Servers = append(spec.Servers, openapi.Server{
|
|
URL: "https://staging.example.com",
|
|
Description: "Staging Server",
|
|
})
|
|
|
|
// Convert back to JSON
|
|
data, _ := json.MarshalIndent(spec, "", " ")
|
|
return string(data), nil
|
|
})
|
|
```
|
|
|
|
## Using with Swagger UI
|
|
|
|
You can serve the generated OpenAPI spec with Swagger UI:
|
|
|
|
1. Get the spec from `/openapi`
|
|
2. Load it in Swagger UI at `https://petstore.swagger.io/`
|
|
3. Or self-host Swagger UI and point it to your `/openapi` endpoint
|
|
|
|
Example with self-hosted Swagger UI:
|
|
|
|
```go
|
|
// Serve Swagger UI static files
|
|
router.PathPrefix("/swagger/").Handler(
|
|
http.StripPrefix("/swagger/", http.FileServer(http.Dir("./swagger-ui"))),
|
|
)
|
|
|
|
// Configure Swagger UI to use /openapi
|
|
```
|
|
|
|
## Testing
|
|
|
|
You can test the OpenAPI endpoint:
|
|
|
|
```bash
|
|
# Get the full spec
|
|
curl http://localhost:8080/openapi | jq
|
|
|
|
# Validate with openapi-generator
|
|
openapi-generator validate -i http://localhost:8080/openapi
|
|
|
|
# Generate client SDKs
|
|
openapi-generator generate -i http://localhost:8080/openapi -g typescript-fetch -o ./client
|
|
```
|
|
|
|
## Complete Example
|
|
|
|
See `example.go` in this package for complete, runnable examples including:
|
|
- Basic RestheadSpec setup
|
|
- Basic ResolveSpec setup
|
|
- Combining both frameworks
|
|
- Adding FuncSpec endpoints
|
|
- Advanced customization
|
|
|
|
## License
|
|
|
|
Part of the ResolveSpec project.
|