{"id":30108064,"url":"https://github.com/oaswrap/spec","last_synced_at":"2025-08-10T02:05:00.304Z","repository":{"id":307158355,"uuid":"1028167777","full_name":"oaswrap/spec","owner":"oaswrap","description":"A lightweight, framework-agnostic OpenAPI 3.x specification builder for Go.","archived":false,"fork":false,"pushed_at":"2025-08-07T12:13:01.000Z","size":357,"stargazers_count":63,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-07T14:17:00.389Z","etag":null,"topics":["go","golang","oas","openapi","openapi-3","openapi-generator","swagger"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/oaswrap/spec","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oaswrap.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-29T06:10:55.000Z","updated_at":"2025-08-06T18:22:19.000Z","dependencies_parsed_at":"2025-08-07T14:12:04.915Z","dependency_job_id":"b8fa4b3a-3eea-4bd2-a00c-11a36e08ff5e","html_url":"https://github.com/oaswrap/spec","commit_stats":null,"previous_names":["faizlabs/openapi-wrapper","oaswrap/spec"],"tags_count":48,"template":false,"template_full_name":null,"purl":"pkg:github/oaswrap/spec","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oaswrap%2Fspec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oaswrap%2Fspec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oaswrap%2Fspec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oaswrap%2Fspec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oaswrap","download_url":"https://codeload.github.com/oaswrap/spec/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oaswrap%2Fspec/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269643725,"owners_count":24452425,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-09T02:00:10.424Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","oas","openapi","openapi-3","openapi-generator","swagger"],"created_at":"2025-08-10T02:02:42.653Z","updated_at":"2025-08-10T02:05:00.261Z","avatar_url":"https://github.com/oaswrap.png","language":"Go","readme":"# oaswrap/spec\n\n[![CI](https://github.com/oaswrap/spec/actions/workflows/ci.yml/badge.svg)](https://github.com/oaswrap/spec/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/oaswrap/spec/graph/badge.svg?token=RIEIM9BAIW)](https://codecov.io/gh/oaswrap/spec)\n[![Go Reference](https://pkg.go.dev/badge/github.com/oaswrap/spec.svg)](https://pkg.go.dev/github.com/oaswrap/spec)\n[![Go Report Card](https://goreportcard.com/badge/github.com/oaswrap/spec)](https://goreportcard.com/report/github.com/oaswrap/spec)\n[![Go Version](https://img.shields.io/github/go-mod/go-version/oaswrap/spec)](https://github.com/oaswrap/spec/blob/main/go.mod)\n[![License](https://img.shields.io/github/license/oaswrap/spec)](LICENSE)\n\nA lightweight, framework-agnostic OpenAPI 3.x specification builder for Go that gives you complete control over your API documentation without vendor lock-in.\n\n## Why oaswrap/spec?\n\n- **🎯 Framework Agnostic** — Works with any Go web framework or as a standalone tool\n- **⚡ Zero Dependencies** — Powered by [`swaggest/openapi-go`](https://github.com/swaggest/openapi-go) with minimal overhead\n- **🔧 Programmatic Control** — Build specs in pure Go code with full type safety\n- **🚀 Adapter Ecosystem** — Seamless integration with popular frameworks via dedicated adapters\n- **📝 CI/CD Ready** — Generate specs at build time for documentation pipelines\n\n## Installation\n\n```bash\ngo get github.com/oaswrap/spec\n```\n\n## Quick Start\n\n### Basic Usage (Standalone)\n\nPerfect for generating OpenAPI specs in CI/CD, build scripts, or documentation tools:\n\n```go\npackage main\n\nimport (\n\t\"log\"\n\n\t\"github.com/oaswrap/spec\"\n\t\"github.com/oaswrap/spec/option\"\n)\n\nfunc main() {\n\t// Create a new OpenAPI router\n\tr := spec.NewRouter(\n\t\toption.WithTitle(\"My API\"),\n\t\toption.WithVersion(\"1.0.0\"),\n\t\toption.WithServer(\"https://api.example.com\"),\n\t)\n\n\t// Add routes\n\tv1 := r.Group(\"/api/v1\")\n\t\n\tv1.Post(\"/login\",\n\t\toption.Summary(\"User login\"),\n\t\toption.Request(new(LoginRequest)),\n\t\toption.Response(200, new(LoginResponse)),\n\t)\n\n\tv1.Get(\"/users/{id}\",\n\t\toption.Summary(\"Get user by ID\"),\n\t\toption.Request(new(GetUserRequest)),\n\t\toption.Response(200, new(User)),\n\t)\n\n\t// Generate OpenAPI spec\n\tif err := r.WriteSchemaTo(\"openapi.yaml\"); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tlog.Println(\"✅ OpenAPI spec generated at openapi.yaml\")\n}\n\ntype LoginRequest struct {\n\tUsername string `json:\"username\" required:\"true\"`\n\tPassword string `json:\"password\" required:\"true\"`\n}\n\ntype LoginResponse struct {\n\tToken string `json:\"token\"`\n}\n\ntype GetUserRequest struct {\n\tID string `path:\"id\" required:\"true\"`\n}\n\ntype User struct {\n\tID   string `json:\"id\"`\n\tName string `json:\"name\"`\n}\n```\n\n📖 **[View the generated spec](https://rest.wiki/?https://raw.githubusercontent.com/oaswrap/spec/main/examples/basic/openapi.yaml)** on Rest.Wiki\n\n### Framework Integration\n\nFor seamless HTTP server integration, use one of our framework adapters:\n\n| Framework | Package |\n|-----------|---------|\n| **Chi** | [`chiopenapi`](/adapter/chiopenapi) |\n| **Echo** | [`echoopenapi`](/adapter/echoopenapi) |\n| **Gin** | [`ginopenapi`](/adapter/ginopenapi) |\n| **Fiber** | [`fiberopenapi`](/adapter/fiberopenapi) |\n| **HTTP** | [`httpopenapi`](/adapter/httpopenapi) |\n| **Mux** | [`muxopenapi`](/adapter/muxopenapi) |\n\nEach adapter provides:\n- ✅ Automatic spec generation from your routes\n- 📚 Built-in Swagger UI documentation at `/docs`\n- 📄 YAML spec endpoints at `/docs/openapi.yaml`\n- 🔧 Inline OpenAPI options with route definitions\n\nVisit the individual adapter repositories for framework-specific examples and detailed integration guides.\n\n## When to Use What?\n\n### ✅ Use `spec` standalone when you:\n- Generate OpenAPI files at **build time**\n- Integrate with **CI/CD pipelines**\n- Build **custom documentation tools**\n- Need **static spec generation**\n- Want **framework independence**\n\n### ✅ Use framework adapters when you:\n- Want **automatic spec generation** from routes\n- Need **built-in documentation UI**\n- Prefer **inline OpenAPI configuration**\n- Want **live spec endpoints**\n\n## Configuration Options\n\nThe `option` package provides comprehensive OpenAPI configuration:\n\n### Basic Information\n```go\noption.WithOpenAPIVersion(\"3.0.3\") // Default: \"3.0.3\"\noption.WithTitle(\"My API\")\noption.WithDescription(\"API description\")\noption.WithVersion(\"1.2.3\")\noption.WithContact(openapi.Contact{\n\tName:  \"Support Team\",\n\tURL:   \"https://support.example.com\",\n\tEmail: \"support@example.com\",\n})\noption.WithLicense(openapi.License{\n\tName: \"MIT License\",\n\tURL:  \"https://opensource.org/licenses/MIT\",\n})\noption.WithExternalDocs(\"https://docs.example.com\", \"API Documentation\")\noption.WithTags(\n\topenapi.Tag{\n\t\tName:        \"User Management\",\n\t\tDescription: \"Operations related to user management\",\n\t},\n\topenapi.Tag{\n\t\tName:        \"Authentication\", \n\t\tDescription: \"Authentication related operations\",\n\t},\n)\n```\n\n### Servers\n```go\noption.WithServer(\"https://api.example.com\")\noption.WithServer(\"https://api-example.com/{version}\",\n\toption.ServerDescription(\"Production Server\"),\n\toption.ServerVariables(map[string]openapi.ServerVariable{\n\t\t\"version\": {\n\t\t\tDefault:     \"v1\",\n\t\t\tEnum:        []string{\"v1\", \"v2\"},\n\t\t\tDescription: \"API version\",\n\t\t},\n\t}),\n)\n```\n\n### Security Schemes\n```go\n// Bearer token\noption.WithSecurity(\"bearerAuth\", option.SecurityHTTPBearer(\"Bearer\"))\n\n// API Key\noption.WithSecurity(\"apiKey\", option.SecurityAPIKey(\"X-API-Key\", \"header\"))\n\n// OAuth2\noption.WithSecurity(\"oauth2\", option.SecurityOAuth2(\n\topenapi.OAuthFlows{\n\t\tImplicit: \u0026openapi.OAuthFlowsImplicit{\n\t\t\tAuthorizationURL: \"https://auth.example.com/authorize\",\n\t\t\tScopes: map[string]string{\n\t\t\t\t\"read\":  \"Read access\",\n\t\t\t\t\"write\": \"Write access\",\n\t\t\t},\n\t\t},\n\t},\n))\n```\n\n### Route Documentation\n```go\noption.OperationID(\"getUserByID\")           // Unique operation ID\noption.Summary(\"Short description\")         // Brief summary\noption.Description(\"Detailed description\") // Full description\noption.Tags(\"User Management\", \"Authentication\") // Group by tags\noption.Request(new(RequestModel))          // Request body model\noption.Response(200, new(ResponseModel),   // Response model\n\toption.ContentDescription(\"Successful response\"),\n\toption.ContentType(\"application/json\"),\n\toption.ContentDefault(true),\n)\noption.Security(\"bearerAuth\")              // Apply security scheme\noption.Deprecated()                        // Mark as deprecated\noption.Hidden()                            // Hide from spec\n```\n\n### Parameter Definition\nDefine parameters using struct tags in your request models:\n\n```go\ntype GetUserRequest struct {\n\tID     string `path:\"id\" required:\"true\" description:\"User identifier\"`\n\tLimit  int    `query:\"limit\" description:\"Maximum number of results\"`\n\tAPIKey string `header:\"X-API-Key\" description:\"API authentication key\"`\n}\n```\n\n### Group-Level Configuration\nApply settings to all routes within a group:\n\n```go\n// Apply to all routes in the group\nadminGroup := r.Group(\"/admin\",\n\toption.GroupTags(\"Administration\"),\n\toption.GroupSecurity(\"bearerAuth\"),\n\toption.GroupDeprecated(),\n)\n\n// Hide internal routes from documentation\ninternalGroup := r.Group(\"/internal\",\n\toption.GroupHidden(),\n)\n```\n\n## Advanced Features\n\n### Rich Schema Documentation\n```go\ntype CreateUserRequest struct {\n\tName     string   `json:\"name\" required:\"true\" minLength:\"2\" maxLength:\"50\"`\n\tEmail    string   `json:\"email\" required:\"true\" format:\"email\"`\n\tAge      int      `json:\"age\" minimum:\"18\" maximum:\"120\"`\n\tTags     []string `json:\"tags\" maxItems:\"10\"`\n}\n```\n\nFor comprehensive struct tag documentation, see [swaggest/openapi-go](https://github.com/swaggest/openapi-go?tab=readme-ov-file#features) and [swaggest/jsonschema-go](https://github.com/swaggest/jsonschema-go?tab=readme-ov-file#field-tags).\n\n### Generic Response Types\n```go\ntype APIResponse[T any] struct {\n\tSuccess   bool   `json:\"success\"`\n\tData      T      `json:\"data,omitempty\"`\n\tError     string `json:\"error,omitempty\"`\n\tTimestamp string `json:\"timestamp\"`\n}\n\n// Usage\noption.Response(200, new(APIResponse[User]))\noption.Response(200, new(APIResponse[[]Product]))\n```\n\n## Examples\n\nExplore complete working examples in the [`examples/`](examples/) directory:\n\n- **[Basic](examples/basic/)** — Standalone spec generation\n- **[Petstore](examples/petstore/)** — Full Petstore API with routes and models\n\n## API Reference\n\nComplete documentation at [pkg.go.dev/github.com/oaswrap/spec](https://pkg.go.dev/github.com/oaswrap/spec).\n\nKey packages:\n- [`spec`](https://pkg.go.dev/github.com/oaswrap/spec) — Core router and spec builder\n- [`option`](https://pkg.go.dev/github.com/oaswrap/spec/option) — Configuration options\n\n## FAQ\n\n**Q: Can I use this with my existing API?**  \nA: Absolutely! Use the standalone version to document existing APIs, or gradually migrate to framework adapters.\n\n**Q: How does this compare to swag/swaggo?**  \nA: While swag uses code comments, oaswrap uses pure Go code for type safety and better IDE support. Both have their merits - swag is annotation-based while oaswrap is code-first.\n\n**Q: How does this compare to Huma?**  \nA: Both are excellent choices with different philosophies:\n- **Huma** is a complete HTTP framework with built-in OpenAPI generation, validation, and middleware\n- **oaswrap/spec** is a lightweight, framework-agnostic documentation builder that works with your existing setup\n- Use **Huma** if you're building a new API and want an all-in-one solution with automatic validation\n- Use **oaswrap** if you have existing code, prefer framework flexibility, or need standalone spec generation\n\n**Q: Can I customize the generated documentation UI?**  \nA: Framework adapters provide built-in UIs, but you can serve the spec with any OpenAPI-compatible tool like Swagger UI, Redoc, or Stoplight.\n\n**Q: Is this production ready?**  \nA: The library is in active development. While core functionality is solid, consider it beta software. Thorough testing is recommended before production use.\n\n**Q: How do I handle authentication in the generated docs?**  \nA: Define security schemes using `option.WithSecurity()` and apply them to routes with `option.Security()`. The generated docs will include authentication UI.\n\n## Roadmap\n\n- [ ] Redoc UI support  \n- [ ] Stoplight Elements integration\n\n## Contributing\n\nWe welcome contributions! Here's how you can help:\n\n1. **🐛 Report bugs** — Open an issue with reproduction steps\n2. **💡 Suggest features** — Share your ideas for improvements\n3. **📝 Improve docs** — Help make our documentation clearer\n4. **🔧 Submit PRs** — Fix bugs or add features\n\nPlease check existing issues and discussions before starting work on new features.\n\n## License\n\n[MIT License](LICENSE) — Created with ❤️ by [Ahmad Faiz](https://github.com/afkdevs).","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foaswrap%2Fspec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foaswrap%2Fspec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foaswrap%2Fspec/lists"}