laravel-12/app/Console/Commands/GenerateSwagger.php

253 lines
10 KiB
PHP

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Symfony\Component\Yaml\Yaml;
class GenerateSwagger extends Command
{
protected $signature = 'swagger:generate';
protected $description = 'Generate OpenAPI specification for the API';
public function handle(): int
{
$this->info('Generating OpenAPI specification...');
$outputDir = public_path('docs');
if (!File::exists($outputDir)) {
File::makeDirectory($outputDir, 0755, true);
}
$spec = $this->generateSpec();
$yaml = Yaml::dump($spec, 4, 2);
File::put($outputDir . '/openapi.yaml', $yaml);
$this->info('OpenAPI specification saved to public/docs/openapi.yaml');
return Command::SUCCESS;
}
protected function generateSpec(): array
{
$appUrl = config('app.url', 'http://localhost');
return [
'openapi' => '3.0.0',
'info' => [
'title' => config('app.name', 'Laravel API'),
'description' => 'API Documentation',
'version' => '1.0.0',
],
'servers' => [
['url' => $appUrl, 'description' => 'Local server'],
],
'paths' => $this->generatePaths(),
'components' => [
'securitySchemes' => [
'bearerAuth' => [
'type' => 'http',
'scheme' => 'bearer',
'bearerFormat' => 'JWT',
],
],
'schemas' => $this->generateSchemas(),
],
];
}
protected function generatePaths(): array
{
return [
'/api/register' => [
'post' => [
'tags' => ['Auth'],
'summary' => 'Register a new user',
'requestBody' => [
'required' => true,
'content' => [
'application/json' => [
'schema' => [
'type' => 'object',
'required' => ['name', 'email', 'password', 'password_confirmation'],
'properties' => [
'name' => ['type' => 'string', 'example' => 'John Doe'],
'email' => ['type' => 'string', 'format' => 'email', 'example' => 'john@example.com'],
'password' => ['type' => 'string', 'format' => 'password', 'example' => 'password123'],
'password_confirmation' => ['type' => 'string', 'format' => 'password', 'example' => 'password123'],
],
],
],
],
],
'responses' => [
'201' => ['description' => 'User registered successfully'],
'422' => ['description' => 'Validation error'],
],
],
],
'/api/login' => [
'post' => [
'tags' => ['Auth'],
'summary' => 'Login user',
'requestBody' => [
'required' => true,
'content' => [
'application/json' => [
'schema' => [
'type' => 'object',
'required' => ['email', 'password'],
'properties' => [
'email' => ['type' => 'string', 'format' => 'email', 'example' => 'john@example.com'],
'password' => ['type' => 'string', 'format' => 'password', 'example' => 'password123'],
],
],
],
],
],
'responses' => [
'200' => ['description' => 'Login successful'],
'401' => ['description' => 'Invalid credentials'],
],
],
],
'/api/logout' => [
'post' => [
'tags' => ['Auth'],
'summary' => 'Logout user',
'security' => [['bearerAuth' => []]],
'responses' => [
'200' => ['description' => 'Logged out successfully'],
],
],
],
'/api/user' => [
'get' => [
'tags' => ['Auth'],
'summary' => 'Get authenticated user',
'security' => [['bearerAuth' => []]],
'responses' => [
'200' => ['description' => 'User data'],
],
],
],
'/api/posts' => [
'get' => [
'tags' => ['Posts'],
'summary' => 'Get all posts',
'security' => [['bearerAuth' => []]],
'responses' => [
'200' => ['description' => 'List of posts'],
],
],
'post' => [
'tags' => ['Posts'],
'summary' => 'Create a new post',
'security' => [['bearerAuth' => []]],
'requestBody' => [
'required' => true,
'content' => [
'application/json' => [
'schema' => [
'type' => 'object',
'required' => ['title', 'content'],
'properties' => [
'title' => ['type' => 'string', 'example' => 'My Post Title'],
'content' => ['type' => 'string', 'example' => 'Post content here...'],
],
],
],
],
],
'responses' => [
'201' => ['description' => 'Post created successfully'],
'422' => ['description' => 'Validation error'],
],
],
],
'/api/posts/{id}' => [
'get' => [
'tags' => ['Posts'],
'summary' => 'Get a post',
'security' => [['bearerAuth' => []]],
'parameters' => [
['name' => 'id', 'in' => 'path', 'required' => true, 'schema' => ['type' => 'integer']],
],
'responses' => [
'200' => ['description' => 'Post data'],
'404' => ['description' => 'Post not found'],
],
],
'put' => [
'tags' => ['Posts'],
'summary' => 'Update a post',
'security' => [['bearerAuth' => []]],
'parameters' => [
['name' => 'id', 'in' => 'path', 'required' => true, 'schema' => ['type' => 'integer']],
],
'requestBody' => [
'required' => true,
'content' => [
'application/json' => [
'schema' => [
'type' => 'object',
'properties' => [
'title' => ['type' => 'string', 'example' => 'Updated Title'],
'content' => ['type' => 'string', 'example' => 'Updated content...'],
],
],
],
],
],
'responses' => [
'200' => ['description' => 'Post updated successfully'],
'404' => ['description' => 'Post not found'],
'422' => ['description' => 'Validation error'],
],
],
'delete' => [
'tags' => ['Posts'],
'summary' => 'Delete a post',
'security' => [['bearerAuth' => []]],
'parameters' => [
['name' => 'id', 'in' => 'path', 'required' => true, 'schema' => ['type' => 'integer']],
],
'responses' => [
'200' => ['description' => 'Post deleted successfully'],
'404' => ['description' => 'Post not found'],
],
],
],
];
}
protected function generateSchemas(): array
{
return [
'User' => [
'type' => 'object',
'properties' => [
'id' => ['type' => 'integer'],
'name' => ['type' => 'string'],
'email' => ['type' => 'string', 'format' => 'email'],
'role' => ['type' => 'string'],
'created_at' => ['type' => 'string', 'format' => 'date-time'],
],
],
'Post' => [
'type' => 'object',
'properties' => [
'id' => ['type' => 'integer'],
'title' => ['type' => 'string'],
'content' => ['type' => 'string'],
'user_id' => ['type' => 'integer'],
'user' => ['$ref' => '#/components/schemas/User'],
'created_at' => ['type' => 'string', 'format' => 'date-time'],
'updated_at' => ['type' => 'string', 'format' => 'date-time'],
],
],
];
}
}