{"id":32692519,"url":"https://github.com/greyorange-labs/rebar3_openapi","last_synced_at":"2026-05-13T20:34:04.539Z","repository":{"id":321420807,"uuid":"1085747354","full_name":"greyorange-labs/rebar3_openapi","owner":"greyorange-labs","description":"Rebar3 plugin for bidirectional OpenAPI and Erlang/Cowboy code generation","archived":false,"fork":false,"pushed_at":"2025-10-29T14:22:26.000Z","size":53,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-29T16:05:40.850Z","etag":null,"topics":["api","code-generation","cowboy","erlang","openapi","rebar3","rebar3-plugin"],"latest_commit_sha":null,"homepage":null,"language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/greyorange-labs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-29T13:10:55.000Z","updated_at":"2025-10-29T14:22:30.000Z","dependencies_parsed_at":"2025-10-29T16:05:42.751Z","dependency_job_id":"81af478a-d620-4687-9c71-5c8f96a433e9","html_url":"https://github.com/greyorange-labs/rebar3_openapi","commit_stats":null,"previous_names":["greyorange-labs/rebar3_openapi"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/greyorange-labs/rebar3_openapi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greyorange-labs%2Frebar3_openapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greyorange-labs%2Frebar3_openapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greyorange-labs%2Frebar3_openapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greyorange-labs%2Frebar3_openapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/greyorange-labs","download_url":"https://codeload.github.com/greyorange-labs/rebar3_openapi/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/greyorange-labs%2Frebar3_openapi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32999465,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-13T13:14:54.681Z","status":"ssl_error","status_checked_at":"2026-05-13T13:14:51.610Z","response_time":115,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["api","code-generation","cowboy","erlang","openapi","rebar3","rebar3-plugin"],"created_at":"2025-11-01T16:01:21.552Z","updated_at":"2026-05-13T20:34:04.521Z","avatar_url":"https://github.com/greyorange-labs.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rebar3_openapi\n\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Erlang](https://img.shields.io/badge/Erlang-OTP%2024%2B-red.svg)](https://www.erlang.org/)\n\nA rebar3 plugin for bidirectional code generation between OpenAPI specifications and Erlang/Cowboy REST handlers.\n\n## Features\n\n- 🔄 **Bidirectional Generation**: OpenAPI ↔ Erlang code\n- 🔌 **Seamless Integration**: Works with existing Cowboy projects via trails() compatibility\n- ✅ **Validation**: Validate code against OpenAPI specs\n- 🎯 **Hybrid Pattern**: Leverages openapi-generator with custom transformations\n- 📝 **CI Ready**: Validate code against OpenAPI specs in CI pipelines\n- 🐳 **Docker Support**: Falls back to Docker if openapi-generator CLI not available\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Requirements](#requirements)\n- [Commands](#commands)\n- [Configuration](#configuration)\n- [Architecture](#architecture)\n- [Integration](#integration)\n- [Status](#status)\n- [Documentation](#documentation)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Installation\n\nAdd to your project's `rebar.config`:\n\n```erlang\n{plugins, [\n    {rebar3_openapi, {git, \"https://github.com/your-org/rebar3_openapi.git\", {branch, \"main\"}}}\n]}.\n```\n\n### Optional Configuration\n\n```erlang\n{openapi, [\n    {specs_dir, \"specs\"},\n    {manifest_file, \".openapi_manifest.json\"},\n    {server_url, \"http://localhost:8080\"},\n    {validation_on_generate, true}\n]}.\n```\n\n## Quick Start\n\n### Generate Handler from OpenAPI Spec\n\n```bash\nrebar3 openapi generate \\\n    --spec /path/to/specs/my_api.yml \\\n    --handler /path/to/src/my_api_handler.erl \\\n    --logic-module my_api_logic_handler\n```\n\nThis creates three files in the same directory as your handler:\n- `my_api_router.erl` - Router with trails() compatibility\n- `my_api_handler.erl` - REST handler with cowboy_rest callbacks\n- `my_api_logic_handler.erl` - Logic handler skeleton (implement your business logic here)\n\n### Extract OpenAPI from Existing Handler\n\n```bash\nrebar3 openapi extract \\\n    --handler /path/to/src/my_api_handler.erl \\\n    --output specs/my_api.yml\n```\n\n### Validate Code Against Spec\n\n```bash\nrebar3 openapi validate \\\n    --handler /path/to/src/my_api_handler.erl \\\n    --spec /path/to/specs/my_api.yml\n```\n\n**See [EXAMPLES.md](EXAMPLES.md) for detailed usage examples.**\n\n## Requirements\n\n### Mandatory\n- **Erlang/OTP 24+**\n- **Rebar3 3.20+**\n- **Dependencies** (automatically installed):\n  - `yamerl` - YAML parsing\n  - `jsx` - JSON handling\n\n### Optional\n- **openapi-generator CLI** - For code generation (Docker fallback available)\n  ```bash\n  # Using npm\n  npm install -g @openapitools/openapi-generator-cli\n\n  # Or using Homebrew (macOS)\n  brew install openapi-generator\n\n  # Or use Docker (no installation needed)\n  docker pull openapitools/openapi-generator-cli\n  ```\n\n## Commands\n\n### Generate\n\nGenerate Erlang handlers from OpenAPI specification.\n\n```bash\nrebar3 openapi generate --spec SPEC_PATH --handler HANDLER_PATH [OPTIONS]\n```\n\n**Required Options:**\n- `--spec, -s` - Full path to OpenAPI spec file (YAML or JSON)\n- `--handler, -h` - Full path to handler file (e.g., `/path/to/src/my_handler.erl`)\n\n**Optional Options:**\n- `--logic-module, -l` - Logic handler module name (default: `\u003chandler\u003e_logic_handler`)\n- `--package-name, -p` - Package name for openapi-generator (default: handler name)\n- `--update, -u` - Update existing handler (preserves business logic)\n- `--dry-run, -d` - Preview changes without creating files\n- `--force, -f` - Force overwrite existing files\n\n**Example:**\n```bash\nrebar3 openapi generate \\\n    --spec /Users/me/project/specs/my_api.yml \\\n    --handler /Users/me/project/apps/my_app/src/my_api_handler.erl \\\n    --dry-run\n```\n\n### Extract\n\nExtract OpenAPI specification from Erlang handlers.\n\n```bash\nrebar3 openapi extract --handler HANDLER_PATH --output OUTPUT [OPTIONS]\n```\n\n**Required Options:**\n- `--handler, -h` - Full path to handler file (required)\n- `--output, -o` - Output file path (required)\n\n**Optional Options:**\n- `--format, -f` - Output format: `yaml` or `json` (auto-detected from file extension)\n\n**Example:**\n```bash\nrebar3 openapi extract \\\n    --handler /Users/me/project/apps/my_app/src/my_handler.erl \\\n    --output specs/my_api.yml\n```\n\n### Validate\n\nValidate handler implementation against OpenAPI spec.\n\n```bash\nrebar3 openapi validate --handler HANDLER --spec SPEC [OPTIONS]\n```\n\n**Options:**\n- `--handler, -h` - Handler module name (required unless --all)\n- `--spec, -s` - OpenAPI spec file (required unless --all)\n- `--app, -a` - Application name\n- `--strict` - Strict mode (fail on any differences, for CI)\n- `--all` - Validate all handlers tracked in manifest\n\n**Example:**\n```bash\n# Single handler\nrebar3 openapi validate \\\n    --handler my_handler \\\n    --spec specs/my_api.yml\n\n# CI mode (all handlers, strict)\nrebar3 openapi validate --all --strict\n```\n\n## Configuration\n\n### Project Configuration\n\nAdd to your `rebar.config`:\n\n```erlang\n{openapi, [\n    %% Directory for OpenAPI specs\n    {specs_dir, \"specs\"},\n\n    %% Manifest file to track generated handlers\n    {manifest_file, \".openapi_manifest.json\"},\n\n    %% Default server URL for generated specs\n    {server_url, \"http://localhost:8080\"},\n\n    %% Validate specs on generation\n    {validation_on_generate, true}\n]}.\n```\n\n### Manifest File\n\nThe plugin creates `.openapi_manifest.json` to track generated handlers:\n\n```json\n{\n  \"version\": \"1.0\",\n  \"handlers\": {\n    \"my_api_handler\": {\n      \"spec_file\": \"specs/my_api.yml\",\n      \"router_module\": \"my_api_router\",\n      \"logic_module\": \"my_api_logic_handler\",\n      \"output_dir\": \"apps/my_app/src\",\n      \"spec_version\": \"1.0.0\",\n      \"last_generated\": \"2025-10-29T12:34:56Z\"\n    }\n  }\n}\n```\n\nThis enables:\n- Batch validation (`rebar3 openapi validate --all`)\n- Tracking which specs generated which handlers\n- CI/CD integration\n\n## Architecture\n\n### Hybrid Pattern\n\nThe plugin implements a **Hybrid Pattern** that combines the power of openapi-generator with compatibility for existing Cowboy infrastructure:\n\n```\nOpenAPI Spec\n     ↓\nopenapi-generator (initial generation)\n     ↓\nTransformation to Hybrid Pattern\n     ↓\n┌─────────────┬──────────────┬─────────────────┐\n│   Router    │   Handler    │  Logic Handler  │\n│  (trails)   │ (cowboy_rest)│ (your business) │\n└─────────────┴──────────────┴─────────────────┘\n```\n\n**Three Generated Modules:**\n\n1. **Router Module** (`\u003chandler\u003e_router.erl`)\n   - Implements `trails_handler` behavior\n   - Provides `trails/0` for cowboy_routes_manager\n   - Maps paths to operations\n\n2. **Handler Module** (`\u003chandler\u003e.erl`)\n   - Implements `cowboy_rest` behavior\n   - Handles HTTP callbacks\n   - Delegates to logic handler\n\n3. **Logic Handler** (`\u003clogic_module\u003e.erl`)\n   - Contains business logic callbacks\n   - Separated from routing concerns\n   - Easy to test and maintain\n\n### Why This Works\n\n- ✅ **No changes to existing infrastructure** - Works with current cowboy_routes_manager\n- ✅ **Gradual migration** - Convert handlers one at a time\n- ✅ **Future-proof** - Easy to migrate to full openapi-generator pattern later\n- ✅ **Clear separation** - Router → Handler → Logic provides clean architecture\n\n### Core Modules\n\nThe plugin consists of 10 Erlang modules:\n\n- `rebar3_openapi.erl` - Main plugin entry point\n- `rebar3_openapi_parser.erl` - OpenAPI YAML/JSON parser\n- `rebar3_openapi_generator.erl` - openapi-generator CLI wrapper\n- `rebar3_openapi_transformer.erl` - Code transformation engine\n- `rebar3_openapi_extractor.erl` - Code to OpenAPI extraction\n- `rebar3_openapi_validator.erl` - Validation logic\n- `rebar3_openapi_prv_generate.erl` - Generate command provider\n- `rebar3_openapi_prv_extract.erl` - Extract command provider\n- `rebar3_openapi_prv_validate.erl` - Validate command provider\n- `rebar3_openapi_utils.erl` - Common utilities\n\n## Integration\n\n### With Cowboy Application\n\nIn your application startup code:\n\n```erlang\n%% src/my_app_app.erl\n\nstart(_StartType, _StartArgs) -\u003e\n    %% Compile routes using trails\n    Trails = trails:trails([\n        my_api_router,     % Your generated router\n        other_handler      % Other handlers\n    ]),\n\n    trails:store(Trails),\n    Dispatch = trails:single_host_compile(Trails),\n\n    %% Start Cowboy\n    {ok, _} = cowboy:start_clear(http_listener,\n        [{port, 8080}],\n        #{env =\u003e #{dispatch =\u003e Dispatch}}\n    ),\n\n    my_app_sup:start_link().\n```\n\n### CI/CD Integration\n\nAdd to your CI pipeline:\n\n```yaml\n# .github/workflows/ci.yml\nname: CI\n\non: [push, pull_request]\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - uses: erlef/setup-beam@v1\n        with:\n          otp-version: '26'\n          rebar3-version: '3.22'\n\n      - name: Compile\n        run: rebar3 compile\n\n      - name: Validate OpenAPI\n        run: rebar3 openapi validate --all --strict\n```\n\nThis ensures your code always matches your OpenAPI specs.\n\n## Status\n\n### ✅ Core Implementation Complete\n\n**Phases 1-3 Implemented:**\n- ✅ OpenAPI parsing (YAML/JSON)\n- ✅ Code generation from OpenAPI specs\n- ✅ Hybrid pattern transformation (trails() compatible)\n- ✅ OpenAPI extraction from handlers\n- ✅ Validation and comparison\n- ✅ Manifest tracking\n- ✅ CI-ready strict mode\n- ✅ Docker fallback for openapi-generator\n\n### 🚧 Partial Implementation\n\nThese features work at a basic level but could be enhanced:\n\n- **--update mode** - Basic structure exists, needs full AST parsing for intelligent merging\n- **Advanced extraction** - Currently uses simplified pattern matching, full AST parsing would improve accuracy\n- **Schema extraction from priv/** - Helper functions exist, not fully wired up\n\n### 📋 Future Enhancements\n\nPlanned for future releases:\n- Full AST parsing for robust code modification\n- Advanced schema extraction from Jesse files\n- Request/response validation using Jesse\n- Template customization support\n- Plugin architecture for custom transformations\n- Comprehensive test suite\n- Publishing to hex.pm\n\n## Documentation\n\n- **[EXAMPLES.md](EXAMPLES.md)** - Detailed usage examples and workflows\n- **[CONTRIBUTING.md](CONTRIBUTING.md)** - Development guide and contribution guidelines\n- **[examples/simple_api.yml](examples/simple_api.yml)** - Example OpenAPI specification\n- **[Implementation Plan](../rebar3_openapi_implementation_plan.md)** - Original design and architecture decisions\n\n## Contributing\n\nContributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for:\n- Development setup\n- Project structure\n- Code style guidelines\n- How to submit pull requests\n\n## Known Limitations\n\n1. **Update Mode**: Currently logs what it would do but doesn't perform full AST-based updates. Manual merge may be required when using `--update`.\n\n2. **Extraction Accuracy**: Extraction from existing handlers is simplified and may not capture all nuances of complex handlers.\n\n3. **Schema Conversion**: Jesse to OpenAPI schema conversion covers common cases but may not handle all edge cases.\n\n4. **Operation Routing**: The generated handler uses simplified operation routing. Complex routing logic may need customization.\n\n## Troubleshooting\n\n### openapi-generator not found\n\n```\nError: openapi-generator not found\n```\n\n**Solution**: Install openapi-generator or ensure Docker is available:\n```bash\nnpm install -g @openapitools/openapi-generator-cli\n# or\ndocker pull openapitools/openapi-generator-cli\n```\n\n### Handler not found during extraction\n\n```\nError: Handler module not found: my_handler\n```\n\n**Solution**: Use `--app` to specify the application:\n```bash\nrebar3 openapi extract \\\n    --handler my_handler \\\n    --app my_app \\\n    --output spec.yml\n```\n\n### Spec validation failed\n\n```\nError: Invalid YAML in spec.yml\n```\n\n**Solution**: Validate your OpenAPI spec:\n- [Swagger Editor](https://editor.swagger.io/)\n- [OpenAPI Validator](https://apitools.dev/swagger-parser/online/)\n\n## License\n\nApache 2.0\n\n## Credits\n\nBuilt with ❤️ for the Butler Core team\n\nBased on the [Hybrid Pattern design](../rebar3_openapi_implementation_plan.md) that leverages openapi-generator while maintaining compatibility with existing Cowboy infrastructure.\n\n## Support\n\nFor issues and questions:\n- File an issue on GitHub\n- Check [EXAMPLES.md](EXAMPLES.md) for usage patterns\n- Review [CONTRIBUTING.md](CONTRIBUTING.md) for development details\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgreyorange-labs%2Frebar3_openapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgreyorange-labs%2Frebar3_openapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgreyorange-labs%2Frebar3_openapi/lists"}