zolteam/ogen

Maintainers

Details

gitlab.com/zolteam/ogen

Source

Issues

Installs: 1 206

Dependents: 2

Suggesters: 0

Security: 0

Stars: 0

Forks: 0

7.0.4 2024-04-29 12:46 UTC

README

Ogen stands for OpenAPI Generator and is a tool that generates a Symfony bundle from an OpenAPI specification YAML file. The bundle is a server stub implementing the specified API: it automatically handles all the routing as well as the (de)serialization of the DTOs and their validation. You then have to plug the domain behaviour by implementing interfaces defined by the bundle.

Usage

To use Ogen, you first need to install the latest version of this vendor in your project:

make composer-bash
composer require --dev zolteam/ogen:^1.0
exit

Then, add a target in your Makefile:

ogen:
	rm -rf symfony/openapi/invoicing/bundle/*
	wget -O symfony/openapi/invoicing/openapi.yaml https://stoplight.io/api/v1/projects/bfav-zol/zol-skeleton/nodes/zol-skeleton.yaml
	@$(RUNNER_DOCKER_EXEC) 'vendor/bin/ogen InvoicingOpenApiServer Zol\\Invoicing\\OpenApiServer zol/invoicing-openapi-server /var/www/html/openapi/invoicing/openapi.yaml /var/www/html/openapi/invoicing/bundle'
	make cc
  • Replace all symfony/openapi/invoicing/bundle by the path of the folder where you want the bundle code to be generated.
  • Replace all symfony/openapi/invoicing/openapi.yaml by the path where you want a copy of the OpenApi specification YAML file.
  • Replace https://stoplight.io/api/v1/projects/bfav-zol/zol-skeleton/nodes/zol-skeleton.yaml by the URL to your OpenAPI specification YAML file (in this example we are using stoplight.io as an editor for our specification).
  • Replace InvoicingOpenApiServer by the name you want to give to your bundle.
  • Replace Zol\\Invoicing\\OpenApiServer by the namespace you want the classes of your bundle to live in.
  • Replace zol/invoicing-openapi-server by the name you want for the bundle's composer package.

Then, run the target:

make ogen

From now on, you can overwrite the bundle anytime you update the OpenAPI specification by replaying the previous command. You should never modify any file in the bundle as they will be overwritten each time you regenerate the bundle.

The bundle is now generated and needs to be configured. First add the bundle directory as a repository in the composer.json of your project:

"repositories": [
    {
        "type": "path",
        "url": "openapi/invoicing/bundle"
    }
]

Then you can require the bundle:

make composer-bash
composer require zol/invoicing-openapi-server:dev-main
composer update
exit

Next, add the bundle in the symfony/config/bundles.php file:

<?php

return [
    Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
    Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
    Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
    Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
    Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
    \Zol\Invoicing\OpenApiServer\InvoicingOpenApiServerBundle::class => ['all' => true], // <-- Here
];

Then, add the bundle routes in your symfony/config/routes.yaml file choosing any prefix:

parazol:
  resource: '@InvoicingOpenApiServerBundle/config/routes.yaml'
  prefix: 'api'

Now you have to implement all interfaces you find in your bundle, that is all src/Api/<TagName>/<TagName>Handler.php and all src/Format/<FormatName>Definition.php. Once implemented, you have to declare them as services and tag them appropriately in your services.yaml file. Here is an example:

<?php

// symfony/src/Zol/Invoicing/Presentation/Client/ClientHandler.php

namespace App\Zol\Invoicing\Presentation\Client;

use Zol\Invoicing\OpenApiServer\Api\Client\GetClients200ApplicationJsonResponse;

class ClientHandler implements \Zol\Invoicing\OpenApiServer\Api\Client\ClientHandler
{
    // ...
}

<?php

// symfony/src/Zol/Invoicing/Presentation/UuidDefinition.php

namespace App\Zol\Invoicing\Presentation;

class UuidDefinition implements \Zol\Invoicing\OpenApiServer\Format\UuidDefinition
{
    public function validate(mixed $value): array
    {
        // ...
    }
}

# symfony/config/services.yaml

### Handlers ###

App\Zol\Invoicing\Presentation\Client\ClientHandler:
    tags:
        - { name: "invoicing_open_api_server.handler", controller: "client" }

### Format Definitions ###

App\Zol\Invoicing\Presentation\UuidDefinition:
    tags:
        - { name: "invoicing_open_api_server.format_definition", format: "uuid" }

That's it, you can now test calling your endpoints !

Troubleshooting

My endpoints are all listed under the DefaultHandler

If you tag your operation then it will be listed under the Handler

My endpoint does not appear nor in the routes nor in the handlers generated

Make sure you declared at least one response with a non-empty content in the endpoint specification. You can always specify a 400 response for example, even if you never intend to return it in your implementation.

My handlers' method names are meaningless

The operation name is used to generate them so make them clear and simple like e.g. "get-client".