diff --git a/.cursor/rules/tests.mdc b/.cursor/rules/tests.mdc new file mode 100644 index 0000000..95c3383 --- /dev/null +++ b/.cursor/rules/tests.mdc @@ -0,0 +1,38 @@ +--- +description: +globs: +alwaysApply: false +--- +Write tests using TDD with the hydronica.trial package following this pattern. +The most important thing is to keep things as simple and understandable as possible. + +``` +func TestFunction(t *testing.T) { + // basic function that takes the table's input and returns the output value and an error. + // All errors cases should be handled as an error response + // if no errors return nil in the second value + // Keep the input and output values as simple as possible, preferable primitive types or the exact values of the function being tested + // do not create inline structs, define the struct in the test function first, if a simple struct is needed + fn := func(i string) (RawJSON, error) { + var v RawJSON + err := json.Unmarshal([]byte(i), &v) + return v, err + } + // Tables (test cases) should be clear and as simple as possible to provide logical coverage. + cases := trial.Cases[string, RawJSON]{ + "test_case": { + Input:{}, + Expected:{}, + } + } + + trial.New(fn, cases).SubTest(t) +} +``` + +When dealing time using the following helper functions +- TimeHour(s string) - uses format "2006-01-02T15" +- TimeDay(s string) - uses format "2006-01-02" +- Time(layout string, value) +- Times(layout string, values ...string) +- TimeP(layout string, s string) returns a *time.Time diff --git a/README.md b/README.md index 7920da8..1f65c85 100644 --- a/README.md +++ b/README.md @@ -1,153 +1,633 @@ # GoOpenAPI -A Go Lang SDK to help create OpenApi 3.0.3 Spec -[OpenAPI spec](https://swagger.io/specification/) +A Go SDK for building OpenAPI 3.0.3 specifications programmatically. Generate complete OpenAPI documentation from your Go code with type-safe schema generation and comprehensive security support. [](https://codecov.io/gh/hydronica/go-openapi) +## Features -## OpenAPI Document Breakdown - +- **Complete OpenAPI 3.0.3 Support**: Generate valid OpenAPI specifications +- **Type-Safe Schema Generation**: Automatic schema creation from Go structs, maps, and JSON +- **Comprehensive Security**: Support for API Key, Bearer, Basic, OAuth2, and OpenID Connect +- **Parameter Management**: Path, query, header, and cookie parameters with examples +- **Request/Response Bodies**: Multiple content types and examples +- **Route Management**: Fluent API for building routes and operations +- **Schema Compilation**: Automatic schema consolidation and reference generation +## Installation -## Getting Started +```bash +go get github.com/hydronica/go-openapi +``` + +## Quick Start + +### Basic Usage + +```go +package main -``` go import ( - _ "embed" - + "fmt" "github.com/hydronica/go-openapi" ) -// go:embed base.json -var base string func main() { + // Create a new OpenAPI document + doc := openapi.New("My API", "1.0.0", "A sample API") - // create doc from base template - doc, err := openapi.NewFromJson(base) - if err != nil { - log.Fatal(err) - } - - // create doc from scratch - doc = openapi.New("title", "v1.0.0", "all about this API") - - doc.AddRoute( - openapi.NewRoute("/path/v1", "get"). - AddResponse( - openapi.Resp{Code: 200, Desc:"valid response"}.WithJSONString('{"status":"ok"}' - ). - AddRequest( - openapi.Req{MType: "application/json", Desc:"pull data"}. - WithParams(myStruct) - ) - ) - - // print generated json document - fmt.Println(string(doc.JSON())) + // Add a route + route := doc.GetRoute("/users/{id}", "GET") + route.AddResponse(openapi.Response{ + Status: 200, + Desc: "User retrieved successfully", + }.WithExample(map[string]any{ + "id": 123, + "name": "John Doe", + "email": "john@example.com", + })) + + // Generate JSON + fmt.Println(doc.JSON()) } ``` -### Adding Schema +### From Existing JSON -#### JSONExample - - Easiest to implement - - go-openapi converts to object - - hard to read unique hash16 name of object based on keys - - No way to add descriptions to fields +```go +//go:embed openapi.json +var baseSpec string -``` go - openapi.NewRoute("path/v1/test","post"). - AddRequest(openapi.RequestBody{}.WithJSONString(`{"name":"bob","age":99,"country":"United States"}`) +doc, err := openapi.NewFromJson(baseSpec) +if err != nil { + log.Fatal(err) +} ``` -``` json -{ - "title": "fd4b3d4f5cce2e6d", - "type": "object", - "properties": { - "age": { - "type": "number" - }, - "country": { - "type": "string" +## Schema Generation + +### 1. Go Structs (Recommended) + +Use Go structs with `json` and `desc` tags for the cleanest schema generation: + +```go +type User struct { + ID int `json:"id" desc:"Unique user identifier"` + Name string `json:"name" desc:"User's full name"` + Email string `json:"email" desc:"User's email address"` + Active bool `json:"active" desc:"Whether the user is active"` + Created time.Time `json:"created" desc:"Account creation timestamp"` +} + +route.AddRequest(openapi.RequestBody{}.WithExample(User{})) +``` + +**Benefits:** +- Clear, readable schema names (`User` instead of hash) +- Field descriptions from `desc` tags +- Type-safe and refactor-friendly + +### 2. JSON Strings + +Convert JSON strings directly to schemas: + +```go +route.AddRequest(openapi.RequestBody{}.WithJSONString(`{ + "name": "John Doe", + "age": 30, + "email": "john@example.com" +}`)) +``` + +**Benefits:** +- Quick prototyping +- Easy for simple schemas + +**Limitations:** +- Auto-generated hash names +- No field descriptions + +### 3. Example Maps + +Use `map[string]Example` for detailed field descriptions: + +```go +route.AddRequest(openapi.RequestBody{}.WithExample(map[string]openapi.Example{ + "name": {Value: "John Doe", Desc: "User's full name"}, + "age": {Value: 30, Desc: "User's age in years"}, + "email": {Value: "john@example.com", Desc: "User's email address"}, +})) +``` + +**Benefits:** +- Field-level descriptions +- Flexible value types + +**Limitations:** +- Auto-generated hash names +- More verbose syntax + +## Route Management + +### Creating Routes + +```go +// Get or create a route +route := doc.GetRoute("/users/{id}", "GET") + +// Add tags for grouping +route.Tags("users", "management") + +// Add summary +route.Summary = "Get user by ID" +``` + +### Path Parameters + +Path parameters are automatically detected from the path: + +```go +route := doc.GetRoute("/users/{id}/posts/{postId}", "GET") +// Automatically creates path parameters for 'id' and 'postId' + +// Add examples for path parameters +route.PathParam("id", 123, "User ID") +route.PathParam("postId", "abc-123", "Post ID") +``` + +### Query Parameters + +```go +// Single parameter +route.QueryParam("limit", 10, "Maximum number of results") +route.QueryParam("offset", 0, "Number of results to skip") + +// Multiple parameters from struct +type QueryParams struct { + Limit int `json:"limit" desc:"Maximum results"` + Offset int `json:"offset" desc:"Results to skip"` + Search string `json:"search" desc:"Search term"` +} +route.QueryParams(QueryParams{Limit: 10, Offset: 0, Search: "example"}) + +// Multiple parameters from map +route.QueryParams(map[string]any{ + "limit": 10, + "offset": 0, + "search": "example", +}) +``` + +### Header Parameters + +```go +route.HeaderParam("X-API-Version", "v1", "API version") +route.HeaderParam("X-Request-ID", "abc-123", "Request identifier") +``` + +### Cookie Parameters + +```go +route.CookieParam("session", "abc123", "Session identifier") +``` + +### Multiple Parameter Examples + +```go +// Multiple examples for a single parameter +route.QueryParam("status", []string{"active", "inactive", "pending"}, "User status") + +// Using Example struct for custom names +route.QueryParam("priority", []openapi.Example{ + {Summary: "low", Value: 1}, + {Summary: "medium", Value: 5}, + {Summary: "high", Value: 10}, +}, "Priority level") +``` + +## Request and Response Bodies + +### Request Bodies + +```go +// From struct +type CreateUserRequest struct { + Name string `json:"name" desc:"User's name"` + Email string `json:"email" desc:"User's email"` +} + +route.AddRequest(openapi.RequestBody{ + Desc: "User creation data", + Required: true, +}.WithExample(CreateUserRequest{})) + +// Multiple examples +route.AddRequest(openapi.RequestBody{}. + WithNamedExample("admin", CreateUserRequest{Name: "Admin", Email: "admin@example.com"}). + WithNamedExample("user", CreateUserRequest{Name: "User", Email: "user@example.com"})) +``` + +### Response Bodies + +```go +// Success response +route.AddResponse(openapi.Response{ + Status: 200, + Desc: "User created successfully", +}.WithExample(User{})) + +// Error response +route.AddResponse(openapi.Response{ + Status: 400, + Desc: "Invalid request", +}.WithJSONString(`{"error": "validation failed", "details": "name is required"}`)) + +// Multiple status codes +route.AddResponse(openapi.Response{Status: 200, Desc: "Success"}.WithExample(User{})) +route.AddResponse(openapi.Response{Status: 404, Desc: "Not found"}.WithJSONString(`{"error": "user not found"}`)) +route.AddResponse(openapi.Response{Status: 500, Desc: "Server error"}.WithJSONString(`{"error": "internal server error"}`)) +``` + +## Security + +### API Key Authentication + +```go +// Header-based API key +doc.AddAPIKeyAuth("YourUniqueNameApiKeyAuth", "X-API-Key", openapi.APIKeyInHeader, "API key for authentication") + +// Query parameter API key +doc.AddAPIKeyAuth("ApiKeyQuery", "api_key", openapi.APIKeyInQuery, "API key as query parameter") + +// Cookie-based API key +doc.AddAPIKeyAuth("ApiKeyCookie", "auth_token", openapi.APIKeyInCookie, "API key in cookie") +``` + +### Bearer Token Authentication + +```go +doc.AddBearerAuth("BearerAuth", openapi.BearerFormatJWT, "Bearer token authentication") +``` + +### Basic Authentication + +```go +doc.AddBasicAuth("BasicAuth", "HTTP Basic authentication") +``` + +### OAuth2 Authentication + +```go +flows := &openapi.Flows{ + AuthorizationCode: &openapi.Flow{ + AuthorizationURL: "https://example.com/oauth/authorize", + TokenURL: "https://example.com/oauth/token", + Scopes: map[string]string{ + "read": "Read access", + "write": "Write access", + "admin": "Admin access", + }, }, - "name": { - "type": "string" - } - } } +doc.AddOAuth2Auth("OAuth2", flows, "OAuth2 authentication") ``` -#### map[string]openapi.Example - - hard to read unique hash16 name of object based on keys - - Ability to add Description to fields +### OpenID Connect +```go +doc.AddOpenIDConnectAuth("OpenIDConnect", "https://example.com/.well-known/openid_configuration", "OpenID Connect authentication") +``` + +### Security Requirements + +#### Global Security Requirements + +```go +// Single security requirement for all endpoints +doc.AddSecurityRequirement("ApiKeyAuth", []string{}) + +// OAuth2 with scopes for all endpoints +doc.AddSecurityRequirement("OAuth2", []string{"read", "write"}) + +// Multiple security schemes (AND logic) for all endpoints +doc.AddMultipleSecurityRequirement(map[string][]string{ + "ApiKeyAuth": {}, + "OAuth2": {"read"}, +}) +``` + +#### Route-Specific Security Requirements + +```go +// Add security to individual routes +route := doc.GetRoute("/admin/users", "POST") + +// Single security requirement for this route only +route.AddSecurity("OAuth2Auth", "admin", "write") + +// Multiple security schemes for this route (AND logic) +route.AddMultipleSecurity(map[string][]string{ + "BearerAuth": {}, + "ApiKeyAuth": {}, +}) + +// Different routes can have different security requirements +publicRoute := doc.GetRoute("/public", "GET") +// No security requirements needed for public route + +protectedRoute := doc.GetRoute("/protected", "GET") +protectedRoute.AddSecurity("BearerAuth") + +adminRoute := doc.GetRoute("/admin", "DELETE") +adminRoute.AddSecurity("OAuth2Auth", "admin") + +// Clear security from a route if needed +route.ClearSecurity() +``` + +### Available Constants + +The library provides constants for common security values: + +```go +// Security scheme types +openapi.SecurityTypeAPIKey // "apiKey" +openapi.SecurityTypeHTTP // "http" +openapi.SecurityTypeOAuth2 // "oauth2" +openapi.SecurityTypeOpenID // "openIdConnect" + +// HTTP authentication schemes +openapi.HTTPSchemeBearer // "bearer" +openapi.HTTPSchemeBasic // "basic" + +// API key locations +openapi.APIKeyInQuery // "query" +openapi.APIKeyInHeader // "header" +openapi.APIKeyInCookie // "cookie" -``` go -openapi.NewRoute("path/v1/test","post"). - AddRequest(RequestBody{}.WithExample(map[string]Example{ - "age": {Value: 12, Desc: "age in earth years"}, - "country": {Value: "USA", Desc: "3 character ISO Code"}, - "name": {Value: "bob", Desc: "individual name"}, - }) +// Common bearer token formats +openapi.BearerFormatJWT // "JWT" ``` -``` json -{ - "title": "fd4b3d4f5cce2e6d", - "type": "object", - "properties": { - "age": { - "type": "integer", - "description": "age in earth years" +## Advanced Features + +### Tags + +```go +doc.AddTags( + openapi.Tag{ + Name: "users", + Desc: "User management operations", }, - "country": { - "type": "string", - "description": "3 character ISO Code" + openapi.Tag{ + Name: "posts", + Desc: "Post management operations", + }, +) +``` + +### Servers + +```go +doc.Servers = []openapi.Server{ + { + URL: "https://api.example.com/v1", + Desc: "Production server", + }, + { + URL: "https://staging-api.example.com/v1", + Desc: "Staging server", }, - "name": { - "type": "string", - "description": "individual name" - } - } } ``` -#### struct - - description pulled from the `desc` struct tag - - clear title based on the struct name - - +### Path Conversion + +Convert Go-style paths to OpenAPI format: + +```go +// Convert ":id" to "{id}" +path := openapi.CleanPath("/users/:id/posts/:postId") +// Result: "/users/{id}/posts/{postId}" +``` + +### Custom Time Formatting + +```go +type Event struct { + Name string `json:"name"` + Date openapi.Time `json:"date"` +} -``` go -type myStruct struct { - Name string `json:"name" desc:"individual name"` - Age int `json:"age" desc:"age in earth years"` - Country string `json:"country" desc:"3 character ISO Code"` +event := Event{ + Name: "Meeting", + Date: openapi.Time{Time: time.Now(), Format: "2006-01-02"}, } +``` + +### Schema Compilation +Compile the document to consolidate schemas and validate: -openapi.NewRoute("path/v1/test","post"). - AddRequest(RequestBody{}.WithExample(myStruct{}) +```go +if err := doc.Compile(); err != nil { + log.Printf("Validation errors: %v", err) +} ``` -``` json -{ - "title": "openapi.myStruct", - "type": "object", - "properties": { - "age": { - "type": "integer", - "description": "age in earth years" - }, - "country": { - "type": "string", - "description": "3 character ISO Code" - }, - "name": { - "type": "string", - "description": "individual name" +### Custom Schema Names + +```go +// Set custom name for JSON schema +jsonData := openapi.JSONString(`{"name": "value"}`).SetName("CustomSchema") +route.AddRequest(openapi.RequestBody{}.WithExample(jsonData)) +``` + +## Complete Example + +```go +package main + +import ( + "fmt" + "time" + "github.com/hydronica/go-openapi" +) + +type User struct { + ID int `json:"id" desc:"Unique user identifier"` + Name string `json:"name" desc:"User's full name"` + Email string `json:"email" desc:"User's email address"` + Active bool `json:"active" desc:"Whether the user is active"` + Created time.Time `json:"created" desc:"Account creation timestamp"` +} + +type CreateUserRequest struct { + Name string `json:"name" desc:"User's name"` + Email string `json:"email" desc:"User's email"` +} + +type ErrorResponse struct { + Error string `json:"error" desc:"Error message"` + Details string `json:"details" desc:"Error details"` +} + +func main() { + // Create document + doc := openapi.New("User API", "1.0.0", "A simple user management API") + + // Add security schemes + doc.AddBearerAuth("BearerAuth", openapi.BearerFormatJWT, "Bearer token authentication") + + // Add OAuth2 for admin endpoints + flows := &openapi.Flows{ + AuthorizationCode: &openapi.Flow{ + AuthorizationURL: "https://example.com/oauth/authorize", + TokenURL: "https://example.com/oauth/token", + Scopes: map[string]string{ + "read": "Read access to user data", + "write": "Write access to user data", + "admin": "Administrative access", + }, + }, + } + doc.AddOAuth2Auth("OAuth2Auth", flows, "OAuth2 authentication for admin operations") + + // Add tags + doc.AddTags(openapi.Tag{ + Name: "users", + Desc: "User management operations", + }) + + // GET /users + listRoute := doc.GetRoute("/users", "GET") + listRoute.Tags("users") + listRoute.Summary = "List users" + listRoute.QueryParam("limit", 10, "Maximum number of users to return") + listRoute.QueryParam("offset", 0, "Number of users to skip") + listRoute.AddResponse(openapi.Response{ + Status: 200, + Desc: "List of users", + }.WithExample([]User{{ID: 1, Name: "John Doe", Email: "john@example.com", Active: true}})) + + // POST /users + createRoute := doc.GetRoute("/users", "POST") + createRoute.Tags("users") + createRoute.Summary = "Create user" + createRoute.AddRequest(openapi.RequestBody{ + Desc: "User creation data", + Required: true, + }.WithExample(CreateUserRequest{Name: "Jane Doe", Email: "jane@example.com"})) + createRoute.AddResponse(openapi.Response{ + Status: 201, + Desc: "User created successfully", + }.WithExample(User{ID: 2, Name: "Jane Doe", Email: "jane@example.com", Active: true})) + createRoute.AddResponse(openapi.Response{ + Status: 400, + Desc: "Invalid request", + }.WithExample(ErrorResponse{Error: "validation failed", Details: "name is required"})) + + // GET /users/{id} - requires bearer auth + getRoute := doc.GetRoute("/users/{id}", "GET") + getRoute.Tags("users") + getRoute.Summary = "Get user by ID" + getRoute.PathParam("id", 123, "User ID") + getRoute.AddSecurity("BearerAuth") // Route-specific security + getRoute.AddResponse(openapi.Response{ + Status: 200, + Desc: "User details", + }.WithExample(User{ID: 1, Name: "John Doe", Email: "john@example.com", Active: true})) + getRoute.AddResponse(openapi.Response{ + Status: 404, + Desc: "User not found", + }.WithExample(ErrorResponse{Error: "not found", Details: "user with id 123 not found"})) + + // DELETE /users/{id} - requires admin OAuth2 scope + deleteRoute := doc.GetRoute("/users/{id}", "DELETE") + deleteRoute.Tags("users") + deleteRoute.Summary = "Delete user" + deleteRoute.PathParam("id", 123, "User ID") + deleteRoute.AddSecurity("OAuth2Auth", "admin") // Admin-only endpoint + deleteRoute.AddResponse(openapi.Response{ + Status: 204, + Desc: "User deleted successfully", + }) + deleteRoute.AddResponse(openapi.Response{ + Status: 403, + Desc: "Insufficient permissions", + }.WithExample(ErrorResponse{Error: "forbidden", Details: "admin scope required"})) + + // GET /public/info - no security required + publicRoute := doc.GetRoute("/public/info", "GET") + publicRoute.Tags("public") + publicRoute.Summary = "Get public information" + publicRoute.AddResponse(openapi.Response{ + Status: 200, + Desc: "Public information", + }.WithJSONString(`{"version": "1.0.0", "status": "operational"}`)) + // No security requirements for public endpoints + + // Compile and validate + if err := doc.Compile(); err != nil { + fmt.Printf("Validation errors: %v\n", err) } - } + + // Output JSON + fmt.Println(doc.JSON()) } -``` \ No newline at end of file +``` + +## API Reference + +### Core Types + +- `OpenAPI`: Main document structure +- `Route`: Individual API endpoint +- `RequestBody`: Request body definition +- `Response`: Response definition +- `Param`: Parameter definition +- `Schema`: Data type definition +- `Example`: Example value with description + +### Methods + +#### Document Methods +- `New(title, version, description)`: Create new document +- `NewFromJson(spec)`: Create from existing JSON +- `GetRoute(path, method)`: Get or create route +- `JSON()`: Generate JSON output +- `Compile()`: Validate and consolidate schemas + +#### Global Security Methods +- `AddAPIKeyAuth(name, keyName, location, description)`: Add API key authentication +- `AddBearerAuth(name, bearerFormat, description)`: Add bearer token authentication +- `AddBasicAuth(name, description)`: Add basic authentication +- `AddOAuth2Auth(name, flows, description)`: Add OAuth2 authentication +- `AddOpenIDConnectAuth(name, url, description)`: Add OpenID Connect authentication +- `AddSecurityRequirement(schemeName, scopes...)`: Add global security requirement +- `AddMultipleSecurityRequirement(schemes)`: Add multiple global security schemes + +#### Route Methods +- `AddResponse(response)`: Add response to route +- `AddRequest(request)`: Add request body to route +- `AddSecurity(schemeName, scopes...)`: Add security requirement to specific route +- `AddMultipleSecurity(schemes)`: Add multiple security schemes to specific route +- `ClearSecurity()`: Remove all security requirements from route +- `PathParam(name, value, desc)`: Add path parameter +- `QueryParam(name, value, desc)`: Add query parameter +- `HeaderParam(name, value, desc)`: Add header parameter +- `CookieParam(name, value, desc)`: Add cookie parameter +- `Tags(tags...)`: Add tags to route + +#### Request/Response Methods +- `WithExample(value)`: Add example to request/response +- `WithJSONString(json)`: Add JSON string example +- `WithNamedExample(name, value)`: Add named example + +## Contributing + +Contributions are welcome! Please feel free to submit a Pull Request. + +## License + +This project is licensed under the MIT License - see the LICENSE file for details. \ No newline at end of file diff --git a/build.go b/build.go index 75360ec..8ea30c3 100644 --- a/build.go +++ b/build.go @@ -14,6 +14,8 @@ import ( "time" ) +// NewFromJson creates a new OpenAPI object from an existing json string +// This allows the user to create a spec with a base structure and then add to it. func NewFromJson(spec string) (api *OpenAPI, err error) { api = &OpenAPI{ Paths: make(Router), @@ -238,11 +240,11 @@ func (o *OpenAPI) Compile() error { o.Components.Schemas = make(map[string]Schema) } var errs error - for _, r := range o.Paths { - if r.Requests != nil { - for k, c := range r.Requests.Content { + for _, path := range o.Paths { + if path.Requests != nil { + for k, c := range path.Requests.Content { if k == "invalid/json" { - errs = errors.Join(errs, fmt.Errorf("invalid json %v request at %v: %q", r.method, r.path, c.Examples["invalid"].Value)) + errs = errors.Join(errs, fmt.Errorf("invalid json %v request at %v: %q", path.method, path.path, c.Examples["invalid"].Value)) continue } if c.Schema.Type != Object { @@ -252,13 +254,13 @@ func (o *OpenAPI) Compile() error { o.Components.Schemas[c.Schema.Title] = c.Schema } c.Schema = Schema{Ref: "#/components/schemas/" + c.Schema.Title} - r.Requests.Content[k] = c + path.Requests.Content[k] = c } } - for _, resp := range r.Responses { + for _, resp := range path.Responses { for k, c := range resp.Content { if k == "invalid/json" { - errs = errors.Join(errs, fmt.Errorf("invalid json %v response at %v: %q", r.method, r.path, c.Examples["invalid"].Value)) + errs = errors.Join(errs, fmt.Errorf("invalid json %v response at %v: %q", path.method, path.path, c.Examples["invalid"].Value)) continue } if c.Schema.Type != Object { @@ -272,7 +274,7 @@ func (o *OpenAPI) Compile() error { } } - for _, p := range r.Params { + for _, p := range path.Params { if strings.Contains(p.Desc, "err:") { errs = errors.Join(errs, fmt.Errorf("%v param %v| %v", p.In, p.Name, p.Desc)) } diff --git a/cmd/gherkin/main.go b/cmd/gherkin/main.go index 512eb64..498a362 100644 --- a/cmd/gherkin/main.go +++ b/cmd/gherkin/main.go @@ -147,7 +147,7 @@ func main() { // generate the output swagger doc f, err := os.Create(c.Out) if err != nil { - log.Fatalf("issue with writing %q: %w", c.Out, err) + log.Fatalf("issue with writing %q: %+v", c.Out, err) } f.Write([]byte(doc.JSON())) } diff --git a/docs/chart.drawio.svg b/docs/chart.drawio.svg index 080ed69..4dc4b43 100644 --- a/docs/chart.drawio.svg +++ b/docs/chart.drawio.svg @@ -1,11 +1,11 @@ - + - + - + OpenAPI @@ -19,20 +19,20 @@ - + OpenAPI... - - - - - + + + + + - + Route @@ -40,16 +40,16 @@ - + Route - + - + @@ -72,16 +72,16 @@ - + Tags: []string... - + - + path|method @@ -89,63 +89,20 @@ - + path|method - - - - - + + + + + - - - - Media - - - - - - Media - - - - - - - - - - - Response - - - Desc: string - - Status Code - - - - - - - - Response... - - - - - - - - - - + Code @@ -153,35 +110,16 @@ - + Code - - - + - - - - MIMEType - - - - - - MIMEType - - - - - - - - + Info @@ -189,7 +127,7 @@ - + Info @@ -197,7 +135,7 @@ - + @@ -235,18 +173,20 @@ - + Title: string... - - - + + + + + - + Paths: Router @@ -254,18 +194,18 @@ - + Paths: Router - - - + + + - + Tags: []Tag @@ -273,18 +213,18 @@ - + Tags: []Tag - - - + + + - + Servers:[]Server @@ -292,16 +232,16 @@ - + Servers:[]Server - + - + Params: @@ -312,16 +252,16 @@ - + Params: []Param - + - + RequestBody @@ -329,18 +269,18 @@ - + RequestBody - - - + + + - + Responses @@ -348,16 +288,16 @@ - + Responses - + - + ExternalDocs: @@ -365,117 +305,185 @@ - + ExternalDocs: - - - + - + - Content + Example - - Content + + Example - + - + - Schema - - - - + Tag - - Schema + + Tag - - + + + + + + Name: string + + Desc: string + + + + + + + + + Name: string... + + + + + + + + + + + ExternalDocs: + + + + + + ExternalDocs: + + + + + + + + - Request Body + Server - - Request Body + + Server - - + + - - + + + URL: string + Desc: string + - - - - Required: bool - - + - - Desc: string... + + URL: string... + + + + + + + + + + + ExternalDocs: + + + + + + ExternalDocs: - + + + - + + + + Components + + + + + + Components + + + + + + + + - Content + Component - - Content + + Component - - - + + + - + Schema @@ -483,236 +491,280 @@ - + Schema - - - + + + - + - - Examples + + id - - Examples + + id - - + + - - - - Title: string - - - - - Desc: string - - Type: string - - - - + @schema - - Title: string... + + @schema + + + + + + + + + + + Security + + + + + + Security - - - + + + - + - Items + Media - - Items + + Media - - - + - + - Properties + Response + + + Desc: string + + Status Code + + - - Properties + + Response... - - - + + + - + - Name + MIMEType - - Name + + MIMEType - + + + - + - Param + Content - - Param + + Content + - - + + + + Schema + + + + + + + + + + Schema + + + + + + + + + + + Request Body + + + + + + Request Body + + + + + + + + - - Name: string - - - - + Desc: string - In: string + Required: bool - - - - - - Name: string... + + Desc: string... - - - + - + - Schema + Content - - Schema + + Content - - - + + + - + - Examples + Schema - - Examples + + Schema - + + + - + - Example + Examples - - Example + + Examples - + + + + Title: string + + + - Summary: string - - Desc: String - - Value: any + Desc: string + + Type: string + @@ -720,231 +772,253 @@ - - Summary: string... + + Title: string... - - - + + + - + - - Name + + Items - - Name + + Items - + + + - + - Tag + Properties - - Tag + + Properties + + + - - - - - - Name: string - - Desc: string - - - + + + + Name - - Name: string... + + Name - + - - - - ExternalDocs: + + + + Param - - ExternalDocs: + + Param - - - - - Server + + + + + + Name: string + + + + + Desc: string + + + + + In: string + + + + + + - - Server + + Name: string... + + + - - - - - - URL: string - - Desc: string - - - + + + + Schema - - URL: string... + + Schema - + + + - - - - ExternalDocs: + + + + Examples - - ExternalDocs: + + Examples - - - - - - - Components + + + + + + Summary: string + + Desc: String + + Value: any + + + - - Components + + Summary: string... - + + + - + - - Component + + Name - - Component + + Name - - - + - - - - Schema + + + + Global + + Security - - Schema + + Global... - - - + + + - - - - id + + + + JWT - - id + + JWT + - + -
@@ -72,16 +72,16 @@
@@ -235,18 +173,20 @@
- + + + URL: string + Desc: string + -
- - Required: bool - -
- - Name: string - -
- + Desc: string
- In: string + Required: bool - -
-
+ + Name: string + +
+ + Desc: string + +
+ + In: string + + +
+ +