PHPackages                             timatic/saloon-sdk-generator - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. timatic/saloon-sdk-generator

ActiveProject[Utility &amp; Helpers](/categories/utility)

timatic/saloon-sdk-generator
============================

Simplified SDK Scaffolding for Saloon

0911PHP

Since Nov 17Pushed 4w agoCompare

[ Source](https://github.com/Timatic/saloon-sdk-generator)[ Packagist](https://packagist.org/packages/timatic/saloon-sdk-generator)[ RSS](/packages/timatic-saloon-sdk-generator/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependenciesVersions (9)Used By (1)

[![](.github/header.png)](.github/header.png)

Saloon SDK Generator - Simplified SDK Scaffolding 🚀
===================================================

[](#saloon-sdk-generator---simplified-sdk-scaffolding-)

[![Latest Version on Packagist](https://camo.githubusercontent.com/5b024ad2056cd6f371edd19daadcfe4a5af41c8ea41d21fcfc711c00a774375c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f637265736361742d696f2f73616c6f6f6e2d73646b2d67656e657261746f722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/crescat-io/saloon-sdk-generator)[![Total Downloads](https://camo.githubusercontent.com/c0291ebeb621330c3477572d9eba051d70612883760ed8a296ca73d59dc3953b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f637265736361742d696f2f73616c6f6f6e2d73646b2d67656e657261746f722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/crescat-io/saloon-sdk-generator)

Introducing the Saloon SDK Generator – your tool for quickly creating the basic structure of PHP SDKs using the powerful [Saloon](https://docs.saloon.dev/) package.

Please note: This tool helps you set up the foundation for your SDK, but it might not create a complete, ready-to-use solution. 🛠️

Whether you're using Postman Collection JSON files (v2.1) or OpenAPI specifications, the Saloon SDK Generator simplifies the process of generating PHP SDKs. It provides you with a starting point to build the initial framework for your API interactions.

Keep in mind that the generated code might not be perfect for every situation. Think of it as a speedy way to scaffold your SDK structure. While you might need to customize it for specific cases, the Saloon SDK Generator saves you time by eliminating the need to create boilerplate code from scratch.

Your journey to crafting a tailored SDK starts here – with the Saloon SDK Generator. 🌟

Fork Enhancements
-----------------

[](#fork-enhancements)

This is an enhanced fork of the original [Crescat Saloon SDK Generator](https://github.com/crescat-io/saloon-sdk-generator) with significant additional features focused on production-ready SDK generation, comprehensive testing, and advanced customization capabilities.

### Comprehensive Test Generation

[](#comprehensive-test-generation)

The fork automatically generates **Pest PHP tests** for all your API endpoints, providing a complete test suite out of the box:

- **Automatic test generation** for all request types (GET, POST, PUT, DELETE)
- **Specialized test patterns** for different endpoint types:
    - Collection endpoints (lists/searches)
    - Singular resource endpoints (get by ID)
    - Mutation endpoints (create/update)
    - Delete endpoints
- **Factory generation** for Spatie Laravel Data objects to create realistic test data
- **DTO assertions** with support for nested objects and complex structures
- **Mock response fixtures** for repeatable, isolated tests

**Example generated test:**

```
test('can create user', function () {
    $connector = new MySDKConnector();

    $mockClient = new MockClient([
        CreateUserRequest::class => MockResponse::make([
            'id' => 123,
            'name' => 'John Doe',
            'email' => 'john@example.com'
        ], 201),
    ]);

    $connector->withMockClient($mockClient);

    $request = new CreateUserRequest(
        name: 'John Doe',
        email: 'john@example.com'
    );

    $response = $connector->send($request);
    $dto = $response->dto();

    expect($dto)->toBeInstanceOf(UserDto::class)
        ->and($dto->id)->toBe(123)
        ->and($dto->name)->toBe('John Doe')
        ->and($dto->email)->toBe('john@example.com');
});
```

### Enhanced DTO Support

[](#enhanced-dto-support)

Rich Data Transfer Object generation with modern PHP features:

- **Spatie Laravel Data integration** - Generated DTOs extend `Spatie\LaravelData\Data` for automatic validation, transformation, and serialization
- **Nested DTO support** - Automatically handles complex object hierarchies with recursive generation
- **Response hydration methods** - Each request includes a `createDtoFromResponse()` method for easy response parsing
- **Union type support** - Handles OpenAPI `anyOf`, `oneOf`, and `allOf` schemas
- **DateTime detection** - Automatically generates `Carbon` types for OpenAPI `date-time` format fields

**Example generated DTO:**

```
class UserDto extends Data
{
    public function __construct(
        public int $id,
        public string $name,
        public ?Carbon $created_at,
        public AddressDto $address,
    ) {}
}
```

**Response hydration:**

```
public function createDtoFromResponse(Response $response): UserDto
{
    return UserDto::from($response->json());
}
```

### Extensive Customization Hooks

[](#extensive-customization-hooks)

The fork provides a powerful hook system allowing you to customize every aspect of code generation:

- Request Generator Hooks
- Resource Generator Hooks
- DTO Generator Hooks
- Test Generator Hooks

**Example: Customizing request class names**

```
class MyRequestGenerator extends RequestGenerator
{
    protected function getRequestClassName(Endpoint $endpoint): string
    {
        // Remove version prefixes from endpoint names
        $name = preg_replace('/^v\d+/', '', $endpoint->name);
        return $name . 'Request';
    }
}

$generator = new CodeGenerator(
    config: $config,
    requestGenerator: new MyRequestGenerator($config)
);
```

### Configuration Enhancements

[](#configuration-enhancements)

Additional configuration options for fine-tuned control:

- **`requestClassSuffix`** - Customize the suffix for request classes (default: 'Request')
- **OpenAPI as default** - No need to specify `--type=openapi` when generating from OpenAPI specs
- **Test path customization** - Configure where test files are generated
- **Factory namespace configuration** - Control factory class namespaces

### Summary

[](#summary)

These enhancements make the SDK Generator suitable for production use with:

- Complete test coverage out of the box
- Type-safe DTOs with validation and transformation
- Full customization through hooks
- Modern PHP 8.2+ features
- Spatie Laravel Data integration

All features are backward-compatible with the original package and can be adopted incrementally.

Installation
------------

[](#installation)

> **Note:** This is an enhanced fork with additional features. See the [Fork Enhancements](#fork-enhancements) section above for details on what's been added beyond the original package.

You can install this package using Composer:

```
composer global timatic/saloon-sdk-generator
```

Usage
-----

[](#usage)

### First run: generate with `--foundation`

[](#first-run-generate-with---foundation)

When you run the generator for the first time, use `--foundation` to generate the static support files (config, service provider, test setup). These can be changed manually afterward.

Recommended first-time setup:

1. Create your project directory, e.g. `mkdir my-sdk && cd my-sdk && git init`
2. Initialize Composer: `composer init` — the generator depends on the PSR-4 autoload namespace
3. Run the generator with `--foundation`

```
sdkgenerator generate:sdk API_SPEC_FILE.{json|yaml|yml} \
    --foundation \
    --connector-name=MyApiConnector \
    --base-url=https://api.example.com \
    --output=./my-sdk \
    --force
```

The root namespace is read from the `autoload.psr-4` section of the `composer.json` in the output directory — that is why `composer init` is required first.

What `--foundation` does:

- Generates a Laravel config file with the base URL as `env()` fallback value
- Generates a service provider that registers the connector
- Generates a test setup with Orchestra Testbench and config injection
- Updates the SDK's `composer.json` (autoload mappings, scripts, Laravel auto-discovery) and runs `composer require` for the SDK dependencies
- If `vendor/bin/pint` is available in the output directory, code is automatically formatted after generation

### Re-runs: without `--foundation`

[](#re-runs-without---foundation)

On subsequent runs, the generator automatically reads the connector name and base URL from the existing config file in the output directory. You don't need to repeat `--connector-name` and `--base-url`:

```
sdkgenerator generate:sdk API_SPEC_FILE.{json|yaml|yml} \
    --output=./my-sdk \
    --force
```

You can still pass `--connector-name` or `--base-url` to override the values read from the config file. Without `--foundation`, the output directory must already contain a generated SDK (a `config/*.php` file); otherwise the command fails and asks you to use `--foundation`.

### Command reference

[](#command-reference)

```
sdkgenerator generate:sdk API_SPEC_FILE.{json|yaml|yml}
     --type={postman|openapi}
    [--output=OUTPUT_PATH]
    [--connector-name=CONNECTOR_NAME]
    [--skip-tests]
    [--skip-factories]
    [--foundation]
    [--base-url=BASE_URL]
    [--dry-run]
    [--force]
    [--exclude-put-requests]
```

OptionDescription`API_SPEC_FILE`Path or URL to the API specification file (JSON or YAML format)`--type`Type of API specification: `postman` or `openapi` (default: `openapi`)`--output` / `-o`Output directory for the generated SDK (default: `./output`)`--connector-name`Name of the Connector class (e.g. `MyApiConnector`). The config key is derived from this. Required with `--foundation`, auto-detected on re-runs from existing config`--skip-tests`Skip generating Pest test suites`--skip-factories`Skip generating Faker factories for DTOs`--foundation`Generate Laravel foundation files (config, service provider, test setup) and set up composer`--base-url`Base URL for the API. Used in config as `env()` fallback. Auto-detected on re-runs from existing config`--dry-run`Show what would be generated without writing files`--force`Force overwriting existing files`--exclude-put-requests`Exclude PUT requests from the generated SDKConverting Swagger v1 or v2 definitions to the OpenAPI 3.0 format
-----------------------------------------------------------------

[](#converting-swagger-v1-or-v2-definitions-to-the-openapi-30-format)

For convenience, we've included a command that allows you to convert Swagger v1 or v2 definitions to the OpenAPI 3.0 The command will send your api definition file to the [Swagger Converter API](https://converter.swagger.io/) and save the output in the specified path.

if no output file is specified, the output location will be the original filepath with the `.converted.json` extension.

To use it, run the following command:

```
sdkgenerator convert old.json [output.json]

## e.g.
sdkgenerator convert tests/Samples/tripletex.json tests/Samples/tripletex.converted.json
```

Only OpenAPI is supported for now.

Using the Code Generator and Parser Programmatically
----------------------------------------------------

[](#using-the-code-generator-and-parser-programmatically)

1. **Configure Your Generator:**

Configure the `CodeGenerator` with the desired settings:

```
$generator = new CodeGenerator(
   namespace: "App\Sdk",
   resourceNamespaceSuffix: 'Resource',
   requestNamespaceSuffix: 'Requests',
   dtoNamespaceSuffix: 'Dto',
   connectorName: 'MySDK', // Replace with your desired SDK name
   outputFolder: './Generated', // Replace with your desired output folder
   ignoredQueryParams: ['after', 'order_by', 'per_page'] // Ignore params used for pagination
);
```

2. **Parse and Generate:**

Parse your API specification file and generate the SDK classes:

```
$inputPath = 'path/to/api_spec_file.json'; // Replace with your API specification file path
$type = 'postman'; // Replace with your API specification type

$result = $generator->run(Factory::parse($type, $inputPath));
```

3. **Use Generated Results:**

You can access the generated classes and perform actions with them:

```
// Generated Connector Class
echo "Generated Connector Class: " . Utils::formatNamespaceAndClass($result->connectorClass) . "\n";

// Generated Base Resource Class
echo "Generated Base Resource Class: " . Utils::formatNamespaceAndClass($result->resourceBaseClass) . "\n";

// Generated Resource Classes
foreach ($result->resourceClasses as $resourceClass) {
   echo "Generated Resource Class: " . Utils::formatNamespaceAndClass($resourceClass) . "\n";
}

// Generated Request Classes
foreach ($result->requestClasses as $requestClass) {
   echo "Generated Request Class: " . Utils::formatNamespaceAndClass($requestClass) . "\n";
}
```

---

How It Works
------------

[](#how-it-works)

The Saloon SDK Generator automates the creation of PHP SDKs by following these steps:

### 1. Parsing API Specifications

[](#1-parsing-api-specifications)

The parser reads and understands different API specification formats, including Postman Collection JSON (v2.1), OpenAPI specifications, and custom formats. When executed, it:

- Takes an input file.
- Converts the contents into an internal format called `ApiSpecification`.
- This format provides a comprehensive view of the API, which the SDK generator uses.

### 2. Auto-generating SDK Components

[](#2-auto-generating-sdk-components)

This component automatically generates essential SDK components based on parsed specifications:

- Request classes
- Resource classes
- Data Transfer Objects (DTOs)
- Connectors
- Foundational resource class

### 3. Configurable Generators

[](#3-configurable-generators)

The Saloon SDK Generator is modular, allowing you to replace default generators with custom ones to tailor the SDK generation to your needs. The following generators can be customized:

- `BaseResourceGenerator`
- `ConnectorGenerator`
- `DtoGenerator`
- `RequestGenerator`
- `ResourceGenerator`

Core Data Structures
--------------------

[](#core-data-structures)

These foundational structures form the basis of the generated SDK output:

### 1. ApiSpecification

[](#1-apispecification)

- Represents the entire API specification.
- Contains metadata like name, description, base URL, and endpoints catalog.

### 2. Config

[](#2-config)

- Central repository for SDK generator configurations.
- Defines namespaces, component suffixes, and other parameters.
- Customizable for specific requirements.

### 3. Endpoint

[](#3-endpoint)

- Describes individual API endpoints.
- Includes method types, path segments, and related parameters.

### 4. GeneratedCode

[](#4-generatedcode)

- Captures the complete generated SDK code.
- Encompasses PHP files for request classes, resource classes, DTOs, connectors, and foundational resource class.

### 5. Parameter

[](#5-parameter)

- Describes parameters associated with API endpoints.
- Includes attributes like type, name, and nullability.

Building a Custom Parser
------------------------

[](#building-a-custom-parser)

If you're working with an API specification format that isn't natively supported by the Saloon SDK Generator, you can build a custom parser to integrate it. Here's how you can do it:

1. **Create Your Custom Parser:**

Start by creating a custom parser class that implements the `Crescat\SaloonSdkGenerator\Contracts\Parser` interface.

There are two ways to initialize a Parser. The first one is through the constructor, which will receive the filePath specified when running `sdkgenerator generate:sdk {FILE_PATH}`.

Example:

```
