Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Openapi Cli Laravel Package

spatie/laravel-openapi-cli

Generate Laravel Artisan commands from an OpenAPI spec. Each API endpoint becomes its own command with typed options for params and request bodies, plus auth, base URL, caching, redirects, and output formatting—ideal for building API CLIs with Laravel Zero.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:

    composer require spatie/laravel-openapi-cli
    

    Publish the config (if needed):

    php artisan vendor:publish --provider="Spatie\OpenApiCli\OpenApiCliServiceProvider"
    
  2. Register an API spec in a service provider:

    use Spatie\OpenApiCli\Facades\OpenApiCli;
    
    OpenApiCli::register('https://api.example.com/openapi.yaml', 'example-api')
        ->baseUrl('https://api.example.com');
    
  3. Run the command generator:

    php artisan openapi:generate
    

    This creates Artisan commands for each endpoint in your OpenAPI spec (e.g., example-api:get-users).

  4. Use the generated command:

    php artisan example-api:get-users --limit=10
    

First Use Case: Quick API Testing

For a GET /users endpoint with query params limit and offset, the package generates:

php artisan example-api:get-users --limit=5 --offset=10

No manual argument parsing or HTTP client setup required.


Implementation Patterns

Core Workflow

  1. Register APIs: Use OpenApiCli::register() in a service provider (e.g., AppServiceProvider@boot) to map OpenAPI specs to CLI namespaces. Configure auth, base URLs, and caching per API.

  2. Generate Commands: Run php artisan openapi:generate to create commands. Regenerate after spec updates:

    php artisan openapi:generate --force
    
  3. Customize Commands: Extend generated commands by publishing stubs:

    php artisan vendor:publish --tag="openapi-cli.stubs"
    

    Override app/Commands/OpenApiCli/ to add pre/post hooks (e.g., logging, input validation).

  4. Integrate with Laravel Zero: Register APIs in AppServiceProvider and use commands directly in a Laravel Zero app:

    $this->command('example-api:get-users', function () {
        return $this->call('example-api:get-users', ['--limit' => 10]);
    });
    

Advanced Patterns

  • Dynamic API Registration: Load specs from environment variables or config:

    OpenApiCli::register(config('services.api.spec'), config('services.api.namespace'));
    
  • Multi-Tenant APIs: Use a factory to register tenant-specific APIs:

    OpenApiCli::register(
        "https://api.tenant-{tenant_id}.com/openapi.yaml",
        "tenant-{tenant_id}"
    )->baseUrl("https://api.tenant-{tenant_id}.com");
    
  • Reusable Auth Logic: Centralize auth in a trait or service:

    OpenApiCli::register('...')
        ->auth(fn () => $this->getAuthToken());
    
  • Command Chaining: Chain commands for workflows (e.g., fetch data then process it):

    php artisan example-api:get-users --limit=10 | php artisan process-users
    

Integration Tips

  • Laravel HTTP Client: The package uses Laravel’s HTTP client under the hood. Customize it via config:

    'http' => [
        'timeout' => 30,
        'headers' => [
            'Accept' => 'application/json',
        ],
    ],
    
  • Event Listeners: Listen to OpenApiCli.Generated to log or validate generated commands:

    event(new OpenApiCliGenerated($commands));
    
  • Testing: Mock the facade in tests:

    OpenApiCli::shouldReceive('register')->once();
    

Gotchas and Tips

Common Pitfalls

  1. Spec Parsing Errors:

    • Issue: Invalid OpenAPI specs (e.g., missing paths or malformed schemas) cause silent failures.
    • Fix: Validate specs with Swagger Editor before generating commands. Use --verbose flag:
      php artisan openapi:generate --verbose
      
  2. Parameter Name Collisions:

    • Issue: Path params (e.g., /users/{id}) and query params with the same name (e.g., ?id=1) may conflict.
    • Fix: Use -- for query params explicitly:
      php artisan example-api:get-user --id=123 --query-id=456
      
  3. Caching Quirks:

    • Issue: Cached specs may not reflect recent API changes.
    • Fix: Clear cache after spec updates:
      php artisan cache:clear
      
      Or disable caching during development:
      ->cache(ttl: 0)
      
  4. Auth Token Expiry:

    • Issue: Static tokens (e.g., hardcoded API keys) fail on expiry.
    • Fix: Use the retryOn hook to refresh tokens:
      ->retryOn(function ($response) {
          return $response->status() === 401;
      }, maxRetries: 3)
      
  5. Command Naming Conflicts:

    • Issue: Generated command names may clash with existing Artisan commands.
    • Fix: Use a unique namespace (e.g., api-v2:) or override the getCommandName() method in stubs.

Debugging Tips

  • Inspect Generated Commands: Check app/Commands/OpenApiCli/ for auto-generated files. Override them to debug logic.

  • HTTP Request Logging: Enable Laravel’s HTTP client logging:

    'http' => [
        'debug' => env('APP_DEBUG', false),
    ],
    
  • Spec Diffing: Compare specs before/after updates using diff:

    curl -s https://api.example.com/openapi.yaml > old.yaml
    php artisan openapi:generate
    curl -s https://api.example.com/openapi.yaml > new.yaml
    diff old.yaml new.yaml
    

Extension Points

  1. Custom Command Classes: Publish stubs and extend Spatie\OpenApiCli\Commands\OpenApiCommand to add:

    • Pre-flight validation (e.g., check user permissions).
    • Post-response processing (e.g., format JSON output).
  2. Dynamic Spec Loading: Override Spatie\OpenApiCli\OpenApiCli::resolveSpec() to load specs from databases or S3:

    public static function resolveSpec(string $spec): string
    {
        return Storage::disk('s3')->get("openapi/{$spec}.yaml");
    }
    
  3. Output Formatters: Extend the Spatie\OpenApiCli\Commands\OpenApiCommand to support custom output (e.g., CSV, Markdown):

    ->outputFormatter(function ($response) {
        return response()->json($response->json());
    });
    
  4. Operation ID Overrides: Use operationId in the OpenAPI spec to control command names. For custom IDs:

    paths:
      /users:
        get:
          operationId: custom-get-users-list
    

Pro Tips

  • Laravel Zero + OpenAPI: Combine with Laravel Zero to build standalone CLI tools:

    // In a Laravel Zero app
    OpenApiCli::register('https://api.example.com/openapi.yaml', 'api')
        ->banner('My CLI Tool')
        ->useOperationIds();
    
  • Interactive Mode: Use --interactive to prompt for missing parameters:

    php artisan example-api:post-users --interactive
    
  • Rate Limit Handling: Leverage the onError hook to handle rate limits gracefully:

    ->onError(function ($response, $command) {
        if ($response->status() === 429) {
            $command->warn('Rate limited. Retry after ' . $response->header('Retry-After') . 's.');
            return true; // Retry automatically
        }
        return false;
    })
    
  • Environment-Specific Configs: Use different specs/configs per environment:

    if (app()->environment('staging')) {
        OpenApiCli::register('https://staging.api.example.com/openapi.yaml', 'staging-api');
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai