{"id":13861364,"url":"https://github.com/wapmorgan/OpenApiGenerator","last_synced_at":"2025-07-14T09:31:41.253Z","repository":{"id":62546563,"uuid":"235849181","full_name":"wapmorgan/OpenApiGenerator","owner":"wapmorgan","description":"OpenApi configuration generator directly from PHP code (PhpDoc and php type hints). Can be used with a large monolithic backend","archived":false,"fork":false,"pushed_at":"2024-10-21T16:27:23.000Z","size":230,"stargazers_count":19,"open_issues_count":1,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-18T16:57:36.936Z","etag":null,"topics":["api","api-docs-generator","api-documentation","openapi","scraper","swagger"],"latest_commit_sha":null,"homepage":"https://wapmorgan.github.io/OpenApiGenerator/","language":"PHP","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/wapmorgan.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}},"created_at":"2020-01-23T17:33:52.000Z","updated_at":"2024-10-21T16:08:47.000Z","dependencies_parsed_at":"2024-04-19T23:27:37.802Z","dependency_job_id":"6c0b5226-5b1a-4533-b225-38719e7173ab","html_url":"https://github.com/wapmorgan/OpenApiGenerator","commit_stats":{"total_commits":119,"total_committers":1,"mean_commits":119.0,"dds":0.0,"last_synced_commit":"9d504265f3d3cf09593ae099491aa6cd9cc7a334"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wapmorgan%2FOpenApiGenerator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wapmorgan%2FOpenApiGenerator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wapmorgan%2FOpenApiGenerator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wapmorgan%2FOpenApiGenerator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wapmorgan","download_url":"https://codeload.github.com/wapmorgan/OpenApiGenerator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225968812,"owners_count":17553142,"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","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","api-docs-generator","api-documentation","openapi","scraper","swagger"],"created_at":"2024-08-05T06:01:19.548Z","updated_at":"2024-11-22T21:30:32.976Z","avatar_url":"https://github.com/wapmorgan.png","language":"PHP","funding_links":[],"categories":["PHP"],"sub_categories":[],"readme":"# What is it?\nIt is OpenApi configuration generator that works with origin source code + phpdoc.\n\n[![Latest Stable Version](https://poser.pugx.org/wapmorgan/openapi-generator/v/stable)](https://packagist.org/packages/wapmorgan/openapi-generator)\n[![Latest Unstable Version](https://poser.pugx.org/wapmorgan/openapi-generator/v/unstable)](https://packagist.org/packages/wapmorgan/openapi-generator)\n[![License](https://poser.pugx.org/wapmorgan/openapi-generator/license)](https://packagist.org/packages/wapmorgan/openapi-generator)\n\nMain purpose of this library is to automatize generation of OpenApi-specification for existing **JSON-API** with a lot of methods. Idea by [@maxonrock](https://github.com/maxonrock).\n\n1. [Open Api generator](#openapigenerator)\n   - [Laravel Example](#laravel-example)\n   - [How it works](#how-it-works)\n   - [How to use](#how-to-use)\n   - [Integrations](#integrations)\n2. [Extending](#extending)\n   - [New scraper](#new-scraper)\n   - [Settings](#settings)\n   - [Limitations](#limitations)\n   - [ToDo](#todo)\n\n# OpenApiGenerator\n**What it does?**\n\nIt generates [OpenApi 3.0 specification files](https://swagger.io/docs/specification/about/) for your REST JSON-based API\nwritten in PHP from source code directly. You **do not need** to write OpenApi-specification manually.\n\n## Laravel Example\n\n1. Routes:\n\n   ```php\n   Route::get('/selector/lists', [\\App\\Http\\Controllers\\SelectorController::class, 'lists']);\n   Route::post('/selector/select', [\\App\\Http\\Controllers\\SelectorController::class, 'select']);\n   Route::get('/selector/goTo', [\\App\\Http\\Controllers\\SelectorController::class, 'goTo']);\n   Route::get('/geo/detect', [\\App\\Http\\Controllers\\GeoController::class, 'detect']);\n   Route::get('/geo/select', [\\App\\Http\\Controllers\\GeoController::class, 'select']);\n   ```\n\n2. One controller:\n\n   ```php\n   /**\n   * Returns lists of filters\n   * @param Request $request\n   * @return ListsResponse\n   */\n   public function lists(Request $request) {\n     return new ListsResponse([\n         //            'persons' =\u003e range(1, 15),\n         'persons' =\u003e array_keys(Menu::$personsList),\n         'tastes' =\u003e Menu::$tastes,\n         'meat' =\u003e Menu::$meat,\n         'pizzas' =\u003e Menu::$pizzas,\n     ]);\n   }\n   \n   /**\n   * Makes a selection of pizzas according to criteria\n   * @param \\App\\Http\\Requests\\SelectPizzas $request\n   * @return PizzaListItem[]\n   */\n   public function select(\\App\\Http\\Requests\\SelectPizzas $request) {\n     $validated = $request-\u003evalidated();\n   \n     return (new Selector())-\u003eselect(\n         $validated['city'], $validated['persons'],\n         $validated['tastes'] ?? null, $validated['meat'] ?? null,\n         $validated['vegetarian'] ?? false, $validated['maxPrice'] ?? null);\n   }\n   ```\n   \n3. One request and two responses:\n\n   ```php\n   class SelectPizzas extends FormRequest {\n        public function rules()\n        { \n            // ...\n            return array_merge([\n               'city' =\u003e ['required', 'string'],\n               'persons' =\u003e ['required', Rule::in(array_keys(Menu::$personsList))],\n               'vegetarian' =\u003e ['boolean'],\n               'maxPrice' =\u003e ['numeric'],\n               'pizzas' =\u003e ['array', Rule::in(array_keys(Menu::$pizzas))],\n            ], $tastes, $meat);\n        } \n   }\n\n   class ListsResponse extends BaseResponse {\n        /** @var string[] */\n        public $persons;\n        /** @var string[] */\n        public $tastes;\n        /** @var string[] */\n        public $meat;\n        /** @var string[] */\n        public $pizzas;\n   }\n   \n   class PizzaListItem extends BaseResponse {\n        public string $pizzeria;\n        public string $id;\n        public int $sizeId;\n        public string $name;\n        public float $size;\n        public array $tastes;\n        public array $meat;\n        public float $price;\n        public float $pizzaArea;\n        public float $pizzaCmPrice;\n        public string $thumbnail;\n        public array $ingredients;\n        public int $dough;\n   }\n   ```\n\n4. **Result of generation from code**: two endpoints with description and arguments for `select`.\n\n   ```\n   ┌─────────┬─────────────────┬──────────────────────────┐\n   │ get     │ /selector/lists │ Returns lists of filters │\n   ├─────────┼─────────────────┼──────────────────────────┤\n   │ Result (4)                                           │\n   │ persons │ array of string │                          │\n   │ tastes  │ array of string │                          │\n   │ meat    │ array of string │                          │\n   │ pizzas  │ array of string │                          │\n   └─────────┴─────────────────┴──────────────────────────┘\n   ┌──────────────────┬──────────────────┬───────────────────────────────────────────────────┐\n   │ post             │ /selector/select │ Makes a selection of pizzas according to criteria │\n   ├──────────────────┼──────────────────┼───────────────────────────────────────────────────┤\n   │ Parameters (15)                                                                         │\n   │ string           │ city             │                                                   │\n   │ string           │ persons          │                                                   │\n   │ boolean          │ vegetarian       │                                                   │\n   │ number           │ maxPrice         │                                                   │\n   │ array            │ pizzas           │                                                   │\n   │ boolean          │ tastes.cheese    │                                                   │\n   │ boolean          │ tastes.sausage   │                                                   │\n   │ boolean          │ tastes.spicy     │                                                   │\n   │ boolean          │ tastes.mushroom  │                                                   │\n   │ boolean          │ tastes.exotic    │                                                   │\n   │ boolean          │ meat.chicken     │                                                   │\n   │ boolean          │ meat.pork        │                                                   │\n   │ boolean          │ meat.beef        │                                                   │\n   │ boolean          │ meat.fish        │                                                   │\n   │ boolean          │ meat.sauce_meat  │                                                   │\n   ├──────────────────┼──────────────────┼───────────────────────────────────────────────────┤\n   │ Result (14)                                                                             │\n   │                  │ array of         │                                                   │\n   │ [*].pizzeria     │ string           │                                                   │\n   │ [*].id           │ string           │                                                   │\n   │ [*].sizeId       │ integer          │                                                   │\n   │ [*].name         │ string           │                                                   │\n   │ [*].size         │ integer          │                                                   │\n   │ [*].tastes       │ array of         │                                                   │\n   │ [*].meat         │ array of         │                                                   │\n   │ [*].price        │ integer          │                                                   │\n   │ [*].pizzaArea    │ integer          │                                                   │\n   │ [*].pizzaCmPrice │ integer          │                                                   │\n   │ [*].thumbnail    │ string           │                                                   │\n   │ [*].ingredients  │ array of         │                                                   │\n   │ [*].dough        │ integer          │                                                   │\n   └──────────────────┴──────────────────┴───────────────────────────────────────────────────┘\n   ```\n\n## How it works\n\n1. **Scraper** collects info about API (tags, security schemes and servers, all endpoints) and contains settings for Generator. Scraper is framework-dependent.\n2. **Generator** fulfills openapi-specification with endpoints information by analyzing source code:\n    - summary and description of actions\n    - parameters and result of actions\n   Generator is common. It just receives information from Scraper and analyzes code by Scraper rules.\n\nMore detailed process description is in [How it works document](docs/how_it_works.md).\n\n## How to use\nInvoke console script to generate openapi for your project (with help of integrations): \n\nFor example, for yii2-project:\n1. Run parser on project to analyze files and retrieve info about endpoints\n   ```shell\n   ./vendor/bin/openapi-generator scrape --scraper yii2 ./\n   # And more deeper scan\n   ./vendor/bin/openapi-generator generate --scraper yii2 --inspect ./\n   ```\n2. Generate specification(s) into yaml-files in `api_docs` folder by **specification_name.yml**\n   ```shell\n   ./vendor/bin/openapi-generator generate --scraper yii2 ./ ./api_docs/\n   # Or with your own scraper (child of one of basic scrapers)\n   ./vendor/bin/openapi-generator generate --scraper components/api/OpenApiScraper.php ./ ./api_docs/\n   ```\n3. Deploy swagger with specification (e.g. _api_docs/main.yml_ on port 8091)\n   ```shell\n    docker run -p 8091:8080 --rm -e URL=./apis/main.yaml -v $(pwd):/usr/share/nginx/html/apis/ swaggerapi/swagger-ui:v4.15.2\n   ```\n\nMore detailed description is in [How to use document](docs/how_to_use.md).\n\n## Integrations\nThere's few integrations: Yii2, Laravel, Slim. Details is in [Integrations document](docs/integrations.md).\nYou can write your own integration for framework or your project.\n\n# Extending\n## New scraper\n\nYou use (or extend) a predefined _scraper_ (see Integrations) or create your own _scraper_ from scratch (extend `DefaultScraper`), which should return a result with list of your API endpoints. Also, your scraper should provide tags, security schemes and so on.\n\nScraper should return list of **specifications** (for example, list of api versions) with:\n- _meta_ - version/description/externalDocs - of specification.\n- _servers_ - list of servers (base urls).\n- _tags_ - list of tags with description and other properties (categories for endpoints).\n- _securitySchemes_ - list of security schemes (authorization types).\n- _endpoints_ - list of API endpoints (separate callbacks).\n\nDetailed information about Scraper result: [in another document](docs/scraper_result.md).\n\n## Settings\nDefaultGenerator provides list of settings to tune generator.\n\n| Parameter                                  | type | default | description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |\n|--------------------------------------------|------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n|  CHANGE_GET_TO_POST_FOR_COMPLEX_PARAMETERS | bool | false   |                                                                                                                                         if callback has arguments with  `object` ,  `array` ,  `stdclass` ,  `mixed`  type or class-typed, method of argument will be changed to  `POST`  and these arguments will be placed as  `body`  data in json-format                                                                                                                                        |\n| TREAT_COMPLEX_ARGUMENTS_AS_BODY            | bool | false   | move complex arguments to request body                                                                                                                                                                                                                                                                                                                                                                                                                                                              |\n| PARSE_PARAMETERS_FROM_ENDPOINT             | bool | false   | if callback `id` has macroses (`users/{id}`), these arguments will be parsed as normal callback arguments                                                                                                                                                                                                                                                                                                                                                                                           |\n| PARSE_PARAMETERS_FORMAT_FORMAT_DESCRIPTION | bool | false   | if php-doc for callback argument in first word after argument variable has one of predefined sub-types (`@param string $arg SUBTYPE Full parameter description `), this will change sub-type in resulting specification. For example, for `string` format there are subtypes: `date`, `date-time`, `password`, `byte`, `binary`, for `integer` there are: `float`, `double`, `int32`, `int64`. Also, you can defined custom format with `DefaultGenerator::setCustomFormat($format, $formatConfig)` |\n\nUsage:\n```php\n$generator-\u003echangeSetting(DefaultGenerator::CHANGE_GET_TO_POST_FOR_COMPLEX_PARAMETERS, true);\n```\n\nBy default, they all are disabled.\n\n## Limitations\n- Only query parameters supported (`url?param1=...\u0026param2=...`) or body json parameters (`{data: 123`).\n- Only one response type supported - HTTP 200 response.\n- No support for parameters' / fields' / properties' `format`, `example` and other validators.\n\n## ToDo\n- [x] Support for few operations on one endpoint (GET/POST/PUT/DELETE/...).\n- [x] Support for body parameters (when parameters are complex objects) - partially.\n- [ ] Support for few responses (with different HTTP codes).\n- [ ] Extracting class types into separate components (into openapi components).\n- [ ] Support for other request/response types besides JSON\n- [x] Add `@paramFormat` for specifying parameter format - partially.\n- [ ] Support for dynamic action arguments in dynamic model\n- [ ] Switch 3.0/3.1 (https://www.openapis.org/blog/2021/02/16/migrating-from-openapi-3-0-to-3-1-0)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwapmorgan%2FOpenApiGenerator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwapmorgan%2FOpenApiGenerator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwapmorgan%2FOpenApiGenerator/lists"}