Skip to content

Commit 45b8df1

Browse files
author
František Mazura
committed
init
1 parent 14a884b commit 45b8df1

22 files changed

+1308
-1
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/.idea/
2+
/node_modules/
3+
/vendor/
4+
composer.lock
5+
phpunit.xml
6+
.phpunit.result.cache
7+
/tmp/

Makefile

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!make
2+
3+
.PHONY: tests
4+
5+
COMPOSE_IMAGE = composer:2
6+
PHP_IMAGE=php:8
7+
8+
composer:
9+
docker pull $(COMPOSE_IMAGE)
10+
docker run --rm --interactive --tty --user $(id -u):$(id -g) -w /app --volume `pwd`:/app --volume `pwd`/tmp:/tmp $(COMPOSE_IMAGE) composer $(P)
11+
12+
composer_install:
13+
make composer P="install"
14+
15+
phpunit:
16+
docker pull $(PHP_IMAGE)
17+
docker run --rm -it --user $(id -u):$(id -g) -w /app --volume `pwd`:/app $(PHP_IMAGE) ./vendor/bin/phpunit $(P)
18+
19+
# run all php unit tests
20+
tests:
21+
make phpunit P=tests

README.md

Lines changed: 167 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,168 @@
11
# laravel-openapi-value-object
2-
Autogenerate openapi from value objects
2+
3+
This library extends [vyuldashev/laravel-openapi](https://github.com/vyuldashev/laravel-openapi). Main idea is do not
4+
create a scheme manually:
5+
6+
```php
7+
class UserCreateRequestBody extends RequestBodyFactory
8+
{
9+
public function build(): RequestBody
10+
{
11+
return RequestBody::create('UserCreate')
12+
->description('User data')
13+
->content(
14+
MediaType::json()->schema(UserSchema::ref())
15+
);
16+
}
17+
}
18+
```
19+
20+
The library get any PHP class and schema is autogenerated from class attributes. You should use PHP doc:
21+
22+
```php
23+
class CarRequest
24+
{
25+
/**
26+
* Car name <-- auto parsed title
27+
*
28+
* This is a car name description... <-- auto parsed description
29+
*
30+
* @var string
31+
*/
32+
protected string $name;
33+
34+
/**
35+
* Engine power in kW
36+
*
37+
* More is better
38+
*
39+
* @var int
40+
*/
41+
protected int $enginePower;
42+
43+
/**
44+
* Wheels of car
45+
*
46+
* It is necessary to move
47+
* @var WheelValueObject[]
48+
*/
49+
protected array $wheels;
50+
51+
/**
52+
* @return string
53+
*/
54+
public function getName(): string
55+
{
56+
return $this->name;
57+
}
58+
59+
/**
60+
* @param string $name
61+
* @return CarValueObject
62+
*/
63+
public function setName(string $name): CarValueObject
64+
{
65+
$this->name = $name;
66+
return $this;
67+
}
68+
69+
/**
70+
* @return int
71+
*/
72+
public function getEnginePower(): int
73+
{
74+
return $this->enginePower;
75+
}
76+
77+
/**
78+
* @param int $enginePower
79+
* @return CarValueObject
80+
*/
81+
public function setEnginePower(int $enginePower): CarValueObject
82+
{
83+
$this->enginePower = $enginePower;
84+
return $this;
85+
}
86+
87+
/**
88+
* @return WheelValueObject[]
89+
*/
90+
public function getWheels(): array
91+
{
92+
return $this->wheels;
93+
}
94+
95+
/**
96+
* @param WheelValueObject[] $wheels
97+
* @return CarValueObject
98+
*/
99+
public function setWheels(WheelValueObject ...$wheels): CarValueObject
100+
{
101+
$this->wheels = $wheels;
102+
return $this;
103+
}
104+
}
105+
```
106+
107+
Output is:
108+
109+
```php
110+
(...)
111+
'properties' =>
112+
[
113+
'name' =>
114+
[
115+
'title' => 'Car name',
116+
'description' => 'This is a car name description...',
117+
'type' => 'string',
118+
'nullable' => false,
119+
],
120+
'enginePower' =>
121+
[
122+
'title' => 'Engine power in kW',
123+
'description' => 'More is better',
124+
'type' => 'integer',
125+
'nullable' => false,
126+
],
127+
'wheels' =>
128+
[
129+
'title' => 'Wheels of car',
130+
'description' => 'It is necessary to move',
131+
'type' => 'array',
132+
'items' =>
133+
[
134+
'type' => 'object',
135+
'properties' =>
136+
[
137+
'size' =>
138+
[
139+
'type' => 'integer',
140+
'nullable' => true,
141+
],
142+
'tire' =>
143+
[
144+
'type' => 'object',
145+
'properties' =>
146+
[
147+
'winter' =>
148+
[
149+
'type' => 'boolean',
150+
'nullable' => false,
151+
],
152+
],
153+
],
154+
],
155+
],
156+
'nullable' => false,
157+
],
158+
]
159+
(...)
160+
```
161+
162+
# Usage
163+
164+
Check `examples/cartore/CarController.php` controller and `exmples/carstore/OpenApi` directory.
165+
166+
# TODO
167+
168+
Update `composer.json` after [pull request](https://github.com/vyuldashev/laravel-openapi/pull/37) is accepted.

composer.json

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"name": "og-soft/laravel-openapi-value-object",
3+
"description": "Generate OpenAPI Specification for Laravel Applications from value objects",
4+
"keywords": [
5+
"laravel",
6+
"openapi",
7+
"api",
8+
"documentation",
9+
"docs",
10+
"rest",
11+
"swagger"
12+
],
13+
"type": "library",
14+
"license": "MIT",
15+
"authors": [
16+
{
17+
"name": "Frantisek Mazura",
18+
"email": "[email protected]"
19+
}
20+
],
21+
"require": {
22+
"php": "^8.0",
23+
"cweagans/composer-patches": "^1.7",
24+
"doctrine/annotations": "^1.12",
25+
"vyuldashev/laravel-openapi": "dev-master"
26+
},
27+
"require-dev": {
28+
"orchestra/testbench": "^5.3|^6.0",
29+
"phpunit/phpunit": "^9.4"
30+
},
31+
"autoload": {
32+
"psr-4": {
33+
"OGSoft\\LaravelOpenApiValueObject\\": "src/"
34+
}
35+
},
36+
"autoload-dev": {
37+
"psr-4": {
38+
"OGSoft\\LaravelOpenApiValueObject\\Tests\\": "tests/",
39+
"Examples\\Carstore\\": "examples/carstore/"
40+
}
41+
},
42+
"config": {
43+
"sort-packages": true
44+
},
45+
"minimum-stability": "dev",
46+
"prefer-stable": true,
47+
"extra": {
48+
"patches": {
49+
"vyuldashev/laravel-openapi": {
50+
"Add PR": "https://github.com/vyuldashev/laravel-openapi/pull/37.patch"
51+
}
52+
}
53+
}
54+
}

config/openapi.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<?php
2+
3+
return [
4+
5+
'collections' => [
6+
7+
'default' => [
8+
9+
'info' => [
10+
'title' => config('app.name'),
11+
'description' => null,
12+
'version' => '1.0.0',
13+
],
14+
15+
'servers' => [
16+
[
17+
'url' => env('APP_URL'),
18+
],
19+
],
20+
21+
'tags' => [
22+
23+
// [
24+
// 'name' => 'user',
25+
// 'description' => 'Application users',
26+
// ],
27+
28+
],
29+
30+
'security' => [
31+
// GoldSpecDigital\ObjectOrientedOAS\Objects\SecurityRequirement::create()->securityScheme('JWT'),
32+
],
33+
34+
// Route for exposing specification.
35+
// Leave uri null to disable.
36+
'route' => [
37+
'uri' => '/openapi',
38+
'middleware' => [],
39+
],
40+
41+
// Register custom middlewares for different objects.
42+
'middlewares' => [
43+
'paths' => [
44+
//
45+
],
46+
],
47+
48+
],
49+
50+
],
51+
52+
// Directories to use for locating OpenAPI object definitions.
53+
'locations' => [
54+
'callbacks' => [
55+
app_path('OpenApi/Callbacks'),
56+
],
57+
58+
'request_bodies' => [
59+
app_path('OpenApi/RequestBodies'),
60+
],
61+
62+
'responses' => [
63+
app_path('OpenApi/Responses'),
64+
],
65+
66+
'schemas' => [
67+
app_path('OpenApi/Schemas'),
68+
],
69+
70+
'security_schemes' => [
71+
app_path('OpenApi/SecuritySchemes'),
72+
],
73+
],
74+
75+
];
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace Examples\Carstore;
4+
5+
use Examples\Carstore\OpenApi\Parameters\CarCreateParams;
6+
use Examples\Carstore\OpenApi\RequestBodies\CarValueObject;
7+
use Examples\Carstore\OpenApi\Responses\CarResponse;
8+
use OGSoft\LaravelOpenApiValueObject\ParameterFactory;
9+
use OGSoft\LaravelOpenApiValueObject\RequestBodyFactory;
10+
use OGSoft\LaravelOpenApiValueObject\ResponseFactory;
11+
use Vyuldashev\LaravelOpenApi\Attributes as OpenApi;
12+
13+
#[OpenApi\PathItem]
14+
class CarController
15+
{
16+
/**
17+
* Create car
18+
*/
19+
#[OpenApi\Operation('createCar')]
20+
// RequestBodyFactory are from repository, CarValueObject is defined by user
21+
#[OpenApi\RequestBody(RequestBodyFactory::class, CarValueObject::class)]
22+
// ParameterFactory are from repository, CarCreateParams is defined by user
23+
#[OpenApi\Parameters(ParameterFactory::class, CarCreateParams::class)]
24+
// ResponseFactory are from repository, CarResponse is defined by user
25+
#[OpenApi\Response(ResponseFactory::class, 200, null, CarResponse::class)]
26+
public function create()
27+
{
28+
}
29+
}

0 commit comments

Comments
 (0)