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

Integration Engine Laravel Package

carlosgude/integration-engine

IntegrationEngine standardizes external API integrations in Symfony: each endpoint is a predictable Action with a Request and Response DTO + Mapper. Includes scaffolding commands to generate integrations and actions, keeping HTTP/mapping logic consistent and maintainable.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require carlosgude/integration-engine
    

    Ensure your project uses PHP 8.2+ and Symfony 7.0+.

  2. Generate a Basic Integration:

    php bin/console make:integration MyApi GetEmployee
    

    Follow the interactive prompts to define the base URL, HTTP method, and path.

  3. Configure the Integration: Add the integration to config/packages/integration_engine.yaml:

    integration_engine:
        integrations:
            my_api:
                base_url: 'https://api.example.com'
                config_path: '%kernel.project_dir%/src/Infrastructure/Integrations/MyApi/MyApi.yaml'
    
  4. First Use Case: Call the integration facade in a service:

    use App\Infrastructure\Integrations\MyApi\MyApiIntegration;
    
    $employee = $myApiIntegration->getEmployee(123);
    

Where to Look First

  • Demo Repository: integrationEngine-use-example for a real-world Symfony integration.
  • Generated Structure: Check src/Infrastructure/Integrations/{Name}/ for the predictable layout.
  • Configuration: Review config/packages/integration_engine.yaml for integration settings.

Implementation Patterns

Core Workflow

  1. Facade Pattern: Always expose integrations via facades (e.g., MyApiIntegration) to abstract the IntegrationRegistry. Never call the registry directly from controllers or services.

  2. Action-Driven Design: Each endpoint is a stateless action with:

    • A Request class (e.g., GetEmployeeAction) handling HTTP logic.
    • A Response DTO (e.g., GetEmployeeResponse) for typed data.
    • A Mapper (e.g., GetEmployeeMapper) to transform raw API responses.
  3. Anti-Corruption Layer (ACL): Use a Gateway (e.g., MyApiGateway) to map integration DTOs to domain objects. This isolates your domain from API changes.

    final class MyApiGateway {
        public function __construct(private MyApiIntegration $integration) {}
    
        public function find(int $id): Employee {
            $dto = $this->integration->getEmployee($id)->employee;
            return new Employee(id: $dto->id, name: $dto->name);
        }
    }
    
  4. Batch Requests: Use sendMany() for parallel requests (e.g., fetching multiple employees):

    $employees = $this->integration->getManyEmployees([1, 2, 3]);
    

    Handle failures via BatchResultCollection:

    if ($results->hasFailures()) {
        throw array_values($results->errors())[0];
    }
    

Integration Tips

  • Reuse DTOs: Shared data types (e.g., Employee) go in Dto/ at the integration root.
  • Path Resolution:
    • Use {placeholder} in YAML paths for dynamic segments (e.g., /employees/{id}).
    • For query strings, implement PathResolvableContextInterface or declare required params in YAML (e.g., /employees?status={status}).
  • Authorization:
    • Static: Define in YAML (e.g., authorization: { type: bearer, token: '%env(TOKEN)%' }).
    • Dynamic (OAuth2): Reference a token-fetching action (e.g., authorization: { type: dynamic, action: FetchToken }).

Testing Patterns

  • Unit Test Actions: Mock the ClientAdapterInterface to test request/response logic.
  • Integration Test: Use IntegrationEngineTestCase to test full API interactions.
  • Gateway Tests: Verify domain object mappings in isolation.

Gotchas and Tips

Pitfalls

  1. Direct Registry Calls:

    • Avoid: Injecting IntegrationRegistry directly into controllers/services.
    • Do: Use facades (e.g., MyApiIntegration) to encapsulate logic.
  2. Cache Scope:

    • The default cache.app is process-local under PHP-FPM. For shared token caching (e.g., OAuth2), configure a distributed cache (e.g., Redis):
      cache_service: cache.redis
      
  3. GraphQL Limitations:

    • The built-in GraphQLClientAdapter does not support batch requests (sendMany). For concurrency, implement a custom BatchClientInterface.
  4. Path Resolution Errors:

    • Missing required path params (e.g., {id}) throw PathResolutionException. Validate context data before sending requests.
  5. Dynamic Auth Retries:

    • If a cached token fails with HTTP 401, the engine retries once with a fresh token. Avoid tight loops in token-dependent actions.

Debugging Tips

  • Log Requests/Responses: Enable debug mode in config/packages/integration_engine.yaml:

    debug: true
    

    Logs appear in Symfony’s profiler or var/log/dev.log.

  • Inspect Raw Responses: Override the mapper’s map() method to dump raw data:

    public function map(array $data): GetEmployeeResponse {
        \Log::debug('Raw API response:', $data);
        return new GetEmployeeResponse(...);
    }
    
  • Validate YAML: Use php bin/console debug:integration-engine:validate to check for syntax errors in {Name}.yaml.

Extension Points

  1. Custom Clients: Implement ClientAdapterInterface for unsupported protocols (e.g., SOAP):

    final class SoapClientAdapter implements ClientAdapterInterface {
        public static function getClientType(): string { return 'soap'; }
        public function send(AbstractAction $action, ...): array { ... }
    }
    

    Tag the service in services.yaml:

    tags:
        - { name: integration_engine.client_adapter }
    
  2. Custom Contexts: Extend DefaultActionContext for complex path/query logic:

    final class FilterContext implements PathResolvableContextInterface {
        public function resolvePath(string $path): ?string {
            return $path . '?' . http_build_query($this->filters);
        }
    }
    
  3. Response Validation: Use PHP 8.2’s read-only properties and constructed properties to enforce DTO immutability:

    final readonly class GetEmployeeResponse {
        public function __construct(
            public int $id,
            public string $name,
        ) {}
    }
    
  4. Error Handling: Catch IntegrationEngineException for API failures:

    try {
        $response = $integration->getEmployee(123);
    } catch (IntegrationEngineException $e) {
        // Handle rate limits, timeouts, etc.
    }
    

Configuration Quirks

  • Base URL: Must include the scheme (e.g., https://api.example.com), not just the path.
  • Client Overrides: Setting client_service in config replaces the default rest/graphql clients.
  • TTL for Dynamic Auth: Defaults to 1 hour (3600 seconds). Adjust for short-lived tokens:
    authorization:
        type: dynamic
        ttl: 900  # 15 minutes
    

Performance Tips

  • Batch Requests: Use sendMany() for bulk operations (e.g., fetching 100+ records).
  • Cache Tokens: For OAuth2, set a shorter TTL (e.g., 5 minutes) to avoid stale tokens.
  • Avoid Redundant Mappers: Reuse mappers across similar actions to reduce boilerplate.

Common Anti-Patterns

  • Mixing HTTP Logic in Domain Services: Keep request/response handling in actions or gateways.
  • Tight Coupling to API DTOs: Always use the Gateway to map to domain objects.
  • Hardcoding URLs: Use the base_url config and YAML paths for maintainability.
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi