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'], ], ], ]; } }