Skip to content

Commit 8e6acf0

Browse files
committed
🚧 automatic documentation
1 parent 54e31d5 commit 8e6acf0

File tree

16 files changed

+1215
-11
lines changed

16 files changed

+1215
-11
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,11 @@ TODO
9797
## Roadmap for the end of bêta (Estimated delivery October 2023)
9898

9999
- Automatic documentation with extension possible
100-
- Refactor actions listing to --> Get resource informations (fields exposed / actions / etc ? regroupe all those possibilities)
101-
- Alias for includes / aggregates
100+
- Add tests for all commands !!!!
102101

103102
## Roadmap
104103

105104
- Metrics support
106105
- Refactor the response class
107106
- Plain text search using Laravel Scout
107+
- Alias for includes / aggregates

config/rest.php

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,47 @@
2727
],
2828

2929
/*
30-
|--------------------------------------------------------------------------
31-
| Rest Authorizations
32-
|--------------------------------------------------------------------------
33-
|
34-
| This is the feature that automatically binds to policies to validate incoming requests.
35-
| Laravel Rest Api will validate each models searched / mutated / deleted to avoid leaks in your API.
36-
|
37-
*/
30+
|--------------------------------------------------------------------------
31+
| Rest Authorizations
32+
|--------------------------------------------------------------------------
33+
|
34+
| This is the feature that automatically binds to policies to validate incoming requests.
35+
| Laravel Rest Api will validate each models searched / mutated / deleted to avoid leaks in your API.
36+
|
37+
*/
3838

3939
'authorizations' => [
4040
'enabled' => true
4141
],
42+
43+
/*
44+
|--------------------------------------------------------------------------
45+
| Rest Documentation
46+
|--------------------------------------------------------------------------
47+
|
48+
| This is the feature that generates automatically your API documentation for you.
49+
| Laravel Rest Api will validate each models searched / mutated / deleted to avoid leaks in your API.
50+
| This feature is based on OpenApi, for more detail see: https://swagger.io/specification/
51+
|
52+
*/
53+
54+
'documentation' => [
55+
'info' => [
56+
'title' => config('app.name'),
57+
'summary' => 'This is my projet\'s documentation',
58+
'description' => 'Find out all about my projet\'s API',
59+
'termsOfService' => null, // (Optional) Url to terms of services
60+
'contact' => [
61+
'name' => 'My Company',
62+
'email' => '[email protected]',
63+
'url' => 'https://company.com'
64+
],
65+
'license' => [
66+
'url' => null,
67+
'name' => 'Apache 2.0',
68+
'identifier' => 'Apache-2.0'
69+
],
70+
'version' => '1.0.0'
71+
]
72+
],
4273
];
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?php
2+
3+
namespace Lomkit\Rest\Console\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use Illuminate\Console\GeneratorCommand;
7+
use Illuminate\Contracts\Console\PromptsForMissingInput;
8+
use Illuminate\Database\Migrations\MigrationCreator;
9+
use Illuminate\Support\Composer;
10+
use Illuminate\Support\Str;
11+
use Lomkit\Rest\Console\ResolvesStubPath;
12+
use Lomkit\Rest\Documentation\Schemas\Contact;
13+
use Lomkit\Rest\Documentation\Schemas\Info;
14+
use Lomkit\Rest\Documentation\Schemas\License;
15+
use Lomkit\Rest\Documentation\Schemas\OpenAPI;
16+
use RuntimeException;
17+
18+
class DocumentationCommand extends GeneratorCommand implements PromptsForMissingInput
19+
{
20+
/**
21+
* The console command signature.
22+
*
23+
* @var string
24+
*/
25+
protected $signature = 'rest:documentation
26+
{--path= : The location where the documentation file should be created}';
27+
28+
/**
29+
* The console command description.
30+
*
31+
* @var string
32+
*/
33+
protected $description = 'Generate the documentation';
34+
35+
public function handle()
36+
{
37+
$openApi = $this->generateOpenApiSchema();
38+
39+
$path = $this->getPath('open-api');
40+
41+
$this->makeDirectory($path);
42+
43+
$this->files->put(
44+
$path,
45+
json_encode($openApi->jsonSerialize())
46+
);
47+
}
48+
49+
/**
50+
* Get the documentation path.
51+
*
52+
* @param string $name
53+
* @return string
54+
*/
55+
protected function getPath($name)
56+
{
57+
return storage_path('app/documentation/'.$name.'.json');
58+
}
59+
60+
61+
62+
protected function generateOpenApiSchema(): OpenAPI
63+
{
64+
return (new OpenAPI)
65+
->withInfo(
66+
$this->generateInfoSchema()
67+
)
68+
->withPaths([])
69+
->withSecurity([])
70+
->withServers([]);
71+
}
72+
73+
protected function generateInfoSchema(): Info
74+
{
75+
return (new Info)
76+
->withTitle(config('rest.documentation.info.title'))
77+
->withSummary(config('rest.documentation.info.summary'))
78+
->withDescription(config('rest.documentation.info.description'))
79+
->withTermsOfService(config('rest.documentation.info.termsOfService'))
80+
->withContact(
81+
$this->generateContactSchema()
82+
)
83+
->withLicense(
84+
$this->generateLicense()
85+
)
86+
->withVersion(config('rest.documentation.info.version'));
87+
}
88+
89+
protected function generateContactSchema(): Contact
90+
{
91+
return (new Contact)
92+
->withName(config('rest.documentation.info.contact.name'))
93+
->withEmail(config('rest.documentation.info.contact.email'))
94+
->withUrl(config('rest.documentation.info.contact.url'));
95+
}
96+
97+
protected function generateLicense(): License
98+
{
99+
return (new License)
100+
->withUrl(config('rest.documentation.info.license.url'))
101+
->withName(config('rest.documentation.info.license.name'))
102+
->withIdentifier(config('rest.documentation.info.license.identifier'));
103+
}
104+
105+
protected function getStub()
106+
{
107+
throw new RuntimeException('Should not be here');
108+
}
109+
}

src/Documentation/Schemas/Contact.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
namespace Lomkit\Rest\Documentation\Schemas;
4+
5+
class Contact extends Schema
6+
{
7+
/**
8+
* The identifying name of the contact person/organization.
9+
* @var string
10+
*/
11+
protected string $name;
12+
13+
/**
14+
* The URL pointing to the contact information.
15+
* @var string
16+
*/
17+
protected string $url;
18+
19+
/**
20+
* The email address of the contact person/organization.
21+
* @var string
22+
*/
23+
protected string $email;
24+
25+
public function withName(string $name): Contact
26+
{
27+
$this->name = $name;
28+
return $this;
29+
}
30+
31+
public function name(): string
32+
{
33+
return $this->name;
34+
}
35+
36+
public function withUrl(string $url): Contact
37+
{
38+
$this->url = $url;
39+
return $this;
40+
}
41+
42+
public function url(): string
43+
{
44+
return $this->url;
45+
}
46+
47+
public function withEmail(string $email): Contact
48+
{
49+
$this->email = $email;
50+
return $this;
51+
}
52+
53+
public function email(): string
54+
{
55+
return $this->email;
56+
}
57+
58+
public function jsonSerialize(): mixed
59+
{
60+
return [
61+
'name' => $this->name(),
62+
'url' => $this->url(),
63+
'email' => $this->email()
64+
];
65+
}
66+
}

src/Documentation/Schemas/Info.php

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
<?php
2+
3+
namespace Lomkit\Rest\Documentation\Schemas;
4+
5+
class Info extends Schema
6+
{
7+
/**
8+
* The title of the API.
9+
* @var string
10+
*/
11+
protected string $title;
12+
13+
/**
14+
* A short summary of the API.
15+
* @var string
16+
*/
17+
protected string $summary;
18+
19+
/**
20+
* A description of the API. CommonMark syntax MAY be used for rich text representation.
21+
* @var string
22+
*/
23+
protected string $description;
24+
25+
/**
26+
* A URL to the Terms of Service for the API.
27+
* @var string|null
28+
*/
29+
protected string|null $termsOfService;
30+
31+
/**
32+
* The contact information for the exposed API.
33+
* @var Contact
34+
*/
35+
protected Contact $contact;
36+
37+
/**
38+
* The license information for the exposed API.
39+
* @var License
40+
*/
41+
protected License $license;
42+
43+
/**
44+
* The version of the OpenAPI document
45+
* @var string
46+
*/
47+
protected string $version;
48+
49+
public function withTitle(string $title): Info
50+
{
51+
$this->title = $title;
52+
return $this;
53+
}
54+
55+
public function title(): string
56+
{
57+
return $this->title;
58+
}
59+
60+
public function withSummary(string $summary): Info
61+
{
62+
$this->summary = $summary;
63+
return $this;
64+
}
65+
66+
public function summary(): string
67+
{
68+
return $this->summary;
69+
}
70+
71+
public function withDescription(string $description): Info
72+
{
73+
$this->description = $description;
74+
return $this;
75+
}
76+
77+
public function description(): string
78+
{
79+
return $this->description;
80+
}
81+
82+
public function withTermsOfService(string|null $termsOfService): Info
83+
{
84+
$this->termsOfService = $termsOfService;
85+
return $this;
86+
}
87+
88+
public function termsOfService(): string|null
89+
{
90+
return $this->termsOfService;
91+
}
92+
93+
public function withContact(Contact $contact): Info
94+
{
95+
$this->contact = $contact;
96+
return $this;
97+
}
98+
99+
public function contact(): Contact
100+
{
101+
return $this->contact;
102+
}
103+
104+
public function withLicense(License $license): Info
105+
{
106+
$this->license = $license;
107+
return $this;
108+
}
109+
110+
public function license(): License
111+
{
112+
return $this->license;
113+
}
114+
115+
public function withVersion(string $version): Info
116+
{
117+
$this->version = $version;
118+
return $this;
119+
}
120+
121+
public function version(): string
122+
{
123+
return $this->version;
124+
}
125+
126+
public function jsonSerialize(): mixed
127+
{
128+
return array_merge(
129+
[
130+
'title' => $this->title(),
131+
'summary' => $this->summary(),
132+
'description' => $this->description(),
133+
'contact' => $this->contact()->jsonSerialize(),
134+
'license' => $this->license()->jsonSerialize(),
135+
'version' => $this->version()
136+
],
137+
!is_null($this->termsOfService()) ? ['termsOfService' => $this->termsOfService()] : []
138+
);
139+
}
140+
}

0 commit comments

Comments
 (0)