Skip to content

Commit

Permalink
Merge pull request #116 from DoclerLabs/add-include-tags-and-exclude-…
Browse files Browse the repository at this point in the history
…tags

add include and exclude tags
  • Loading branch information
vsouz4 authored Aug 22, 2024
2 parents 5033df3 + 345d8d0 commit bdb0b95
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [10.9.0] - 2024.08.16
### Added
- `INCLUDE_TAGS` and `EXCLUDE_TAGS` to whitelist/blacklist client generation based on operation tags

## [10.8.1] - 2024.06.04
### Fixed
- Enums for path parameters
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ API client generator is a console application capable of auto-generating a [PSR1
- It is base client independent, you are free to choose any [existing PSR-18 compliant client](https://packagist.org/providers/psr/http-client-implementation). Just choose the one which you already use, so generated client would not cause any conflicts with your dependencies. Although not recommended, you can also use or build your own PSR-18 implementation, as the generated client depends on PSR interfaces only.
- Applies code style rules to generated code, you can specify your own.
- Generates README and composer.json files with possibility to use your own template.
- Supports `allOf` OpenAPI parameter.
- Supports `allOf`, `oneOf`, `anyOf` OpenAPI parameters.
- Supports nullable optional scheme property.

## Example
Expand Down Expand Up @@ -68,8 +68,8 @@ OPENAPI={path-to-specification}/openapi.yaml NAMESPACE=Group\SomeApiClient PACKA
## Configuration
The following environment variables are available:

| Variable | Required | Default | Enum | Example |
|------------|---------|------------------|---------|---------------------------|
| Variable | Required | Default | Enum | Example | Description |
|------------|---------|------------------|---------|---------------------------|----------------------------|
| `NAMESPACE` | yes | | | Group\\SomeApiClient |
| `PACKAGE` | yes | | | group/some-api-client |
| `OPENAPI ` | yes | | | /api/openapi.yaml |
Expand All @@ -81,6 +81,8 @@ The following environment variables are available:
| `README_MD_TEMPLATE_DIR` | no | {path-to-repository}/template/README.md.twig | | /path/README.md.twig |
| `HTTP_MESSAGE` | no | guzzle | guzzle, nyholm | nyholm |
| `CONTAINER` | no | pimple | pimple | pimple |
| `INCLUDE_TAGS` | no | | | tag1,tag2,tag3 | tag whitelist to select generated operations |
| `EXCLUDE_TAGS` | no | | | tag1,tag2,tag3 | tag blacklist to select generated operations |

## Running tests

Expand Down
25 changes: 25 additions & 0 deletions src/Generator/ClientGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

namespace DoclerLabs\ApiClientGenerator\Generator;

use DoclerLabs\ApiClientGenerator\Ast\Builder\CodeBuilder;
use DoclerLabs\ApiClientGenerator\Ast\Builder\MethodBuilder;
use DoclerLabs\ApiClientGenerator\Ast\Builder\ParameterBuilder;
use DoclerLabs\ApiClientGenerator\Ast\ParameterNode;
use DoclerLabs\ApiClientGenerator\Ast\PhpVersion;
use DoclerLabs\ApiClientGenerator\Entity\Field;
use DoclerLabs\ApiClientGenerator\Entity\Operation;
use DoclerLabs\ApiClientGenerator\Entity\Response;
Expand All @@ -33,6 +35,16 @@

class ClientGenerator extends GeneratorAbstract
{
public function __construct(
string $baseNamespace,
CodeBuilder $builder,
PhpVersion $phpVersion,
private array $includeTags,
private array $excludeTags
) {
parent::__construct($baseNamespace, $builder, $phpVersion);
}

public function generate(Specification $specification, PhpFileCollection $fileRegistry): void
{
$classBuilder = $this->builder
Expand All @@ -42,6 +54,19 @@ public function generate(Specification $specification, PhpFileCollection $fileRe
->addStmt($this->generateSendRequestMethod());

foreach ($specification->getOperations() as $operation) {
if (
(
!empty($this->includeTags)
&& empty(array_intersect($operation->tags, $this->includeTags))
)
|| (
!empty($this->excludeTags)
&& !empty(array_intersect($operation->tags, $this->excludeTags))
)
) {
continue;
}

$classBuilder->addStmt($this->generateAction($operation));
}

Expand Down
8 changes: 7 additions & 1 deletion src/Input/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ class Configuration

public const STATIC_PHP_FILE_DIRECTORY = __DIR__ . '/../Output/Copy';

/**
* @param string[] $includeTags
* @param string[] $excludeTags
*/
public function __construct(
public readonly string $specificationFilePath,
public readonly string $baseNamespace,
Expand All @@ -39,7 +43,9 @@ public function __construct(
public readonly string $composerJsonTemplateDir,
public readonly string $readmeMdTemplateDir,
public readonly string $httpMessage,
public readonly string $container
public readonly string $container,
public readonly array $includeTags,
public readonly array $excludeTags
) {
Assert::notEmpty($specificationFilePath, 'Specification file path is not provided.');
Assert::notEmpty($baseNamespace, 'Namespace for generated code is not provided.');
Expand Down
6 changes: 5 additions & 1 deletion src/ServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ public function register(Container $pimple): void
getenv('README_MD_TEMPLATE_DIR') ?: Configuration::DEFAULT_TEMPLATE_DIRECTORY,
getenv('HTTP_MESSAGE') ?: Configuration::DEFAULT_HTTP_MESSAGE,
getenv('CONTAINER') ?: Configuration::DEFAULT_CONTAINER,
array_filter(explode(',', (string)getenv('INCLUDE_TAGS'))),
array_filter(explode(',', (string)getenv('EXCLUDE_TAGS')))
);

$pimple[GenerateCommand::class] = static fn (Container $container) => new GenerateCommand(
Expand Down Expand Up @@ -204,7 +206,9 @@ public function register(Container $pimple): void
$pimple[ClientGenerator::class] = static fn (Container $container) => new ClientGenerator(
$container[Configuration::class]->baseNamespace,
$container[CodeBuilder::class],
$container[PhpVersion::class]
$container[PhpVersion::class],
$container[Configuration::class]->includeTags,
$container[Configuration::class]->excludeTags
);

$pimple[SchemaGenerator::class] = static fn (Container $container) => new SchemaGenerator(
Expand Down
24 changes: 23 additions & 1 deletion test/suite/functional/ConfigurationBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ class ConfigurationBuilder

private string $container;

private array $includeTags;

private array $excludeTags;

private function __construct()
{
$this->specificationFilePath = '/dir/path/openapi.yaml';
Expand All @@ -46,6 +50,8 @@ private function __construct()
$this->readmeMdTemplateDir = Configuration::DEFAULT_TEMPLATE_DIRECTORY;
$this->httpMessage = Configuration::DEFAULT_HTTP_MESSAGE;
$this->container = Configuration::DEFAULT_CONTAINER;
$this->includeTags = [];
$this->excludeTags = [];
}

public static function fake(): self
Expand Down Expand Up @@ -130,6 +136,20 @@ public function withContainer(string $container): self
return $this;
}

public function withIncludeTags(array $includeTags): self
{
$this->includeTags = $includeTags;

return $this;
}

public function withExcludeTags(array $excludeTags): self
{
$this->excludeTags = $excludeTags;

return $this;
}

public function build(): Configuration
{
return new Configuration(
Expand All @@ -144,7 +164,9 @@ public function build(): Configuration
$this->composerJsonTemplateDir,
$this->readmeMdTemplateDir,
$this->httpMessage,
$this->container
$this->container,
$this->includeTags,
$this->excludeTags
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);

/*
* This file was generated by docler-labs/api-client-generator.
*
* Do not edit it manually.
*/

namespace Test;

use Psr\Container\ContainerInterface;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\ResponseInterface;
use Test\Request\AddPetRequest;
use Test\Request\CountPetsRequest;
use Test\Request\FindPetsRequest;
use Test\Request\Mapper\RequestMapperInterface;
use Test\Request\RequestInterface;
use Test\Response\ResponseHandler;
use Test\Schema\Mapper\PetCollectionMapper;
use Test\Schema\Mapper\PetMapper;
use Test\Schema\Pet;
use Test\Schema\PetCollection;

class SwaggerPetstoreClient
{
public function __construct(private readonly ClientInterface $client, private readonly ContainerInterface $container)
{
}

public function sendRequest(RequestInterface $request): ResponseInterface
{
return $this->client->sendRequest($this->container->get(RequestMapperInterface::class)->map($request));
}

public function findPets(FindPetsRequest $request): PetCollection
{
$response = $this->handleResponse($this->sendRequest($request));

return $this->container->get(PetCollectionMapper::class)->toSchema($response);
}

public function addPet(AddPetRequest $request): Pet
{
$response = $this->handleResponse($this->sendRequest($request));

return $this->container->get(PetMapper::class)->toSchema($response);
}

public function countPets(CountPetsRequest $request): void
{
$this->handleResponse($this->sendRequest($request));
}

protected function handleResponse(ResponseInterface $response)
{
return $this->container->get(ResponseHandler::class)->handle($response);
}
}
10 changes: 9 additions & 1 deletion test/suite/functional/Generator/Client/petstore.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ paths:
/pets:
get:
operationId: find-pets
tags:
- tag1
parameters:
- name: tags
in: query
Expand Down Expand Up @@ -43,6 +45,8 @@ paths:
$ref: '#/components/schemas/Error'
post:
operationId: addPet
tags:
- tag1
requestBody:
description: Pet to add to the store
required: true
Expand All @@ -66,7 +70,7 @@ paths:
head:
operationId: countPets
tags:
- Pet
- tag2
responses:
200:
description: Count pets
Expand All @@ -78,6 +82,8 @@ paths:
/pets/{id}:
get:
operationId: findPetById
tags:
- tag3
parameters:
- name: id
in: path
Expand All @@ -102,6 +108,8 @@ paths:
/pets/{id}/pet-food/{food_id}:
delete:
description: no operation id provided
tags:
- tag4
parameters:
- name: id
in: path
Expand Down
12 changes: 12 additions & 0 deletions test/suite/functional/Generator/ClientGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ public function exampleProvider(): array
self::BASE_NAMESPACE . '\\MultipleResponsesClient',
ConfigurationBuilder::fake()->withPhpVersion(PhpVersion::VERSION_PHP81)->build(),
],
'Basic schema with php 8.1 and include tags' => [
'/Client/petstore.yaml',
'/Client/SwaggerPetstoreClientWithTags.php',
self::BASE_NAMESPACE . '\\SwaggerPetstoreClient',
ConfigurationBuilder::fake()->withPhpVersion(PhpVersion::VERSION_PHP81)->withIncludeTags(['tag1', 'tag2'])->build(),
],
'Basic schema with php 8.1 and exclude tags' => [
'/Client/petstore.yaml',
'/Client/SwaggerPetstoreClientWithTags.php',
self::BASE_NAMESPACE . '\\SwaggerPetstoreClient',
ConfigurationBuilder::fake()->withPhpVersion(PhpVersion::VERSION_PHP81)->withExcludeTags(['tag3', 'tag4'])->build(),
],
];
}

Expand Down
12 changes: 10 additions & 2 deletions test/suite/unit/Input/ConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ public function testValidConfiguration(
string $composerJsonTemplateDir,
string $readmeMdTemplateDir,
string $httpMessage,
string $container
string $container,
array $includeTags,
array $excludeTags
): void {
$sut = new Configuration(
$openapiFilePath,
Expand All @@ -41,7 +43,9 @@ public function testValidConfiguration(
$composerJsonTemplateDir,
$readmeMdTemplateDir,
$httpMessage,
$container
$container,
$includeTags,
$excludeTags
);

self::assertEquals($openapiFilePath, $sut->specificationFilePath);
Expand All @@ -56,6 +60,8 @@ public function testValidConfiguration(
self::assertEquals($readmeMdTemplateDir, $sut->readmeMdTemplateDir);
self::assertEquals($httpMessage, $sut->httpMessage);
self::assertEquals($container, $sut->container);
self::assertEquals($includeTags, $sut->includeTags);
self::assertEquals($excludeTags, $sut->excludeTags);
}

public function validConfigurationOptions(): array
Expand All @@ -74,6 +80,8 @@ public function validConfigurationOptions(): array
__DIR__,
Configuration::DEFAULT_HTTP_MESSAGE,
Configuration::DEFAULT_CONTAINER,
['tag1', 'tag2'],
['tag3', 'tag4'],
],
];
}
Expand Down

0 comments on commit bdb0b95

Please sign in to comment.