...
This commit is contained in:
236
aiprompts/instructions/instructions_openapi_generation.md
Normal file
236
aiprompts/instructions/instructions_openapi_generation.md
Normal file
@@ -0,0 +1,236 @@
|
||||
# OpenAPI Generation Instructions
|
||||
|
||||
## Overview
|
||||
|
||||
The OpenAPI package in `pkg/openapi` provides functionality to generate server code from OpenAPI specifications. This document explains how to use this package to generate and host multiple APIs under a single server with Swagger UI integration.
|
||||
|
||||
## Implementation Status
|
||||
|
||||
We have successfully implemented:
|
||||
|
||||
1. A proper test in `pkg/openapi/examples` that generates code from OpenAPI specifications
|
||||
2. Code generation for two example APIs:
|
||||
- `petstoreapi` (from `petstore.yaml`)
|
||||
- `actionsapi` (from `actions.yaml`)
|
||||
3. A webserver that hosts multiple generated APIs
|
||||
4. Swagger UI integration for API documentation
|
||||
5. A home page with links to the APIs and their documentation
|
||||
|
||||
All APIs are hosted under `$serverurl:$port/api` with a clean navigation structure.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
pkg/openapi/
|
||||
├── examples/
|
||||
│ ├── actions.yaml # OpenAPI spec for Actions API
|
||||
│ ├── actionsapi/ # Generated code for Actions API
|
||||
│ ├── main.go # Main server implementation
|
||||
│ ├── petstore.yaml # OpenAPI spec for Petstore API
|
||||
│ ├── petstoreapi/ # Generated code for Petstore API
|
||||
│ ├── README.md # Documentation for examples
|
||||
│ ├── run_test.sh # Script to run tests and server
|
||||
│ └── test/ # Tests for OpenAPI generation
|
||||
├── generator.go # Server code generator
|
||||
├── parser.go # OpenAPI spec parser
|
||||
├── example.go # Example usage
|
||||
└── templates/ # Code generation templates
|
||||
└── server.tmpl # Server template
|
||||
```
|
||||
|
||||
## How to Use
|
||||
|
||||
### Running the Example
|
||||
|
||||
To run the example implementation:
|
||||
|
||||
1. Navigate to the examples directory:
|
||||
```bash
|
||||
cd pkg/openapi/examples
|
||||
```
|
||||
|
||||
2. Run the test script:
|
||||
```bash
|
||||
./run_test.sh
|
||||
```
|
||||
|
||||
3. Access the APIs:
|
||||
- API Home: http://localhost:9091/api
|
||||
- Petstore API: http://localhost:9091/api/petstore
|
||||
- Petstore API Documentation: http://localhost:9091/api/swagger/petstore
|
||||
- Actions API: http://localhost:9091/api/actions
|
||||
- Actions API Documentation: http://localhost:9091/api/swagger/actions
|
||||
|
||||
### Generating Code from Your Own OpenAPI Spec
|
||||
|
||||
To generate code from your own OpenAPI specification:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/openapi"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Parse the OpenAPI specification
|
||||
spec, err := openapi.ParseFromFile("your-api.yaml")
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to parse OpenAPI specification: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Create a server generator
|
||||
generator := openapi.NewServerGenerator(spec)
|
||||
|
||||
// Generate server code
|
||||
serverCode := generator.GenerateServerCode()
|
||||
|
||||
// Write the server code to a file
|
||||
outputPath := "generated-server.go"
|
||||
err = os.WriteFile(outputPath, []byte(serverCode), 0644)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to write server code: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("Generated server code in %s\n", outputPath)
|
||||
}
|
||||
```
|
||||
|
||||
### Hosting Multiple APIs
|
||||
|
||||
To host multiple APIs under a single server:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/freeflowuniverse/heroagent/pkg/openapi"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Create the main server
|
||||
app := fiber.New()
|
||||
|
||||
// Setup API routes
|
||||
app.Get("/api", func(c *fiber.Ctx) error {
|
||||
return c.SendString("API Home Page")
|
||||
})
|
||||
|
||||
// Mount the first API
|
||||
spec1, _ := openapi.ParseFromFile("api1.yaml")
|
||||
generator1 := openapi.NewServerGenerator(spec1)
|
||||
apiServer1 := generator1.GenerateServer()
|
||||
app.Mount("/api/api1", apiServer1)
|
||||
|
||||
// Mount the second API
|
||||
spec2, _ := openapi.ParseFromFile("api2.yaml")
|
||||
generator2 := openapi.NewServerGenerator(spec2)
|
||||
apiServer2 := generator2.GenerateServer()
|
||||
app.Mount("/api/api2", apiServer2)
|
||||
|
||||
// Start the server
|
||||
app.Listen(":8080")
|
||||
}
|
||||
```
|
||||
|
||||
### Adding Swagger UI
|
||||
|
||||
To add Swagger UI for API documentation:
|
||||
|
||||
```go
|
||||
// Serve OpenAPI specs
|
||||
app.Static("/api/api1/openapi.yaml", "api1.yaml")
|
||||
app.Static("/api/api2/openapi.yaml", "api2.yaml")
|
||||
|
||||
// API1 Swagger UI
|
||||
app.Get("/api/swagger/api1", func(c *fiber.Ctx) error {
|
||||
return c.SendString(`
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>API1 - Swagger UI</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui.css" />
|
||||
<style>
|
||||
html { box-sizing: border-box; overflow: -moz-scrollbars-vertical; overflow-y: scroll; }
|
||||
*, *:before, *:after { box-sizing: inherit; }
|
||||
body { margin: 0; background: #fafafa; }
|
||||
.swagger-ui .topbar { display: none; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="swagger-ui"></div>
|
||||
<script src="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui-bundle.js"></script>
|
||||
<script src="https://unpkg.com/swagger-ui-dist@5.9.0/swagger-ui-standalone-preset.js"></script>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
const ui = SwaggerUIBundle({
|
||||
url: "/api/api1/openapi.yaml",
|
||||
dom_id: '#swagger-ui',
|
||||
deepLinking: true,
|
||||
presets: [
|
||||
SwaggerUIBundle.presets.apis,
|
||||
SwaggerUIStandalonePreset
|
||||
],
|
||||
layout: "StandaloneLayout"
|
||||
});
|
||||
window.ui = ui;
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
})
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
### OpenAPI Parsing
|
||||
|
||||
The package can parse OpenAPI 3.0 and 3.1 specifications from files or byte slices.
|
||||
|
||||
### Code Generation
|
||||
|
||||
The package generates Fiber server code with mock implementations based on examples in the OpenAPI spec.
|
||||
|
||||
### Mock Implementations
|
||||
|
||||
Mock implementations are created using examples from the OpenAPI spec, making it easy to test APIs without writing any code.
|
||||
|
||||
### Multiple API Hosting
|
||||
|
||||
The package supports hosting multiple APIs under a single server, with each API mounted at a different path.
|
||||
|
||||
### Swagger UI Integration
|
||||
|
||||
The package includes Swagger UI integration for API documentation, making it easy to explore and test APIs.
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Organize Your Code**: Keep your OpenAPI specs, generated code, and server implementation in separate directories.
|
||||
|
||||
2. **Use Examples**: Include examples in your OpenAPI spec to generate better mock implementations.
|
||||
|
||||
3. **Test Your APIs**: Write tests to verify that your APIs work as expected.
|
||||
|
||||
4. **Document Your APIs**: Use Swagger UI to document your APIs and make them easier to use.
|
||||
|
||||
5. **Use Version Control**: Keep your OpenAPI specs and generated code in version control to track changes.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **Parse Error**: If you get a parse error, check that your OpenAPI spec is valid. You can use tools like [Swagger Editor](https://editor.swagger.io/) to validate your spec.
|
||||
|
||||
- **Generation Error**: If code generation fails, check that your OpenAPI spec includes all required fields and that examples are properly formatted.
|
||||
|
||||
- **Server Error**: If the server fails to start, check that the port is not already in use and that all required dependencies are installed.
|
||||
|
||||
Reference in New Issue
Block a user