GithubHelp home page GithubHelp logo

crescat-io / saloon-sdk-generator Goto Github PK

View Code? Open in Web Editor NEW
105.0 105.0 17.0 93.97 MB

Generate Saloon SDKs from Postman Collections and OpenAPI Specifications.

License: MIT License

PHP 100.00%
generator laravel php saloon sdk

saloon-sdk-generator's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

saloon-sdk-generator's Issues

OpenAPI $ref not resolved

Issue

When the OpenAPI schema contains referenced parameters, they are not resolved and not included in the generated SDK.

Here is a test that fails to reproduce this (based on https://github.com/crescat-io/saloon-sdk-generator/blob/master/tests/Samples/spotify.yml) :

test('Resolved references in parameters', function () {
    $specFile = sample_path('spotify.yml');
    $parser = OpenApiParser::build($specFile);
    $spec = $parser->parse();

    expect($spec->endpoints)->not()->toBeNull()
        ->and($spec->endpoints[0]->pathParameters)->toHaveCount(1)
        ->and($spec->endpoints[0]->queryParameters)->toHaveCount(1);
});

For reference, here is the expected SDK (based on the source schema):
CleanShot 2024-03-17 at 00 58 35

Resolution & discussion

At the first attempt, I tried:
https://github.com/crescat-io/saloon-sdk-generator/blob/master/src/Parsers/OpenApiParser.php

    public static function build($content): self
    {
        return new self(
            Str::endsWith($content, '.json')
-              ? Reader::readFromJsonFile(fileName: realpath($content), resolveReferences: ReferenceContext::RESOLVE_MODE_INLINE)
-              : Reader::readFromYamlFile(fileName: realpath($content), resolveReferences: ReferenceContext::RESOLVE_MODE_INLINE)
+              ? Reader::readFromJsonFile(fileName: realpath($content), resolveReferences: ReferenceContext::RESOLVE_MODE_ALL)
+              : Reader::readFromYamlFile(fileName: realpath($content), resolveReferences: ReferenceContext::RESOLVE_MODE_ALL)
        );
    }

This amply slows down generation.
On my machine, the SmokeTest test takes about 12 seconds before the change and times out after (60 seconds)

I also found this commit bd9d325 which changes the resolution mode from RESOLVE_MODE_ALL to RESOLVE_MODE_INLINE without explaining why but surely on purpose.

My second thought was to resolve references in the mapPrams method by overriding context at that time to change its mode:

if(is_a($parameter->schema, Reference::class)) {
    $context = $parameter->schema->getContext();
    $context->mode = 'ReferenceContext::RESOLVE_MODE_ALL';

    $parameter->schema = $parameter->schema->resolve($context);
}

But according to the OpenAPI specification, references can be used at various locations, for example responses.
I know responses are not yet parsed, but I think it should be taken in account for the future.


As I think there are choices to make, I preferred to submit an issue first. I'll submit a PR when this discussion converges to a solution.

[Feature Request] HAR File support

HAR files is for lack of a better term a JSON dump of HTTP Requests that you can generate via the DevTools and various proxy tools, useful when there is no official api documentation and you have to reverse engineer an API by doing the good old "clicking around in the user interface to trigger all possible api endpoints manually".

Docs and specs

Getting an error when running composer global require

I am on PHP 8.3.1, when I run

composer global require crescat-io/saloon-sdk-generator
  Problem 1
    - illuminate/session[v10.0.0, ..., v10.39.0] require symfony/finder ^6.2 -> found symfony/finder[v6.2.0, ..., v6.4.0] but the package is fixed to v5.4.27 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
    - illuminate/http[v9.52.0, ..., v9.52.16] require illuminate/collections ^9.0 -> found illuminate/collections[v9.0.0, ..., v9.52.16] but the package is fixed to v10.39.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
    - crescat-io/saloon-sdk-generator v1.10.0 requires saloonphp/laravel-plugin ^3.0 -> satisfiable by saloonphp/laravel-plugin[v3.0.0, v3.1.0, v3.2.0].
    - saloonphp/laravel-plugin[v3.1.0, ..., v3.2.0] require illuminate/http ^10.0 -> satisfiable by illuminate/http[v10.0.0, ..., v10.39.0].
    - saloonphp/laravel-plugin v3.0.0 requires illuminate/http ^9.52 || ^10.0 -> satisfiable by illuminate/http[v9.52.0, ..., v9.52.16, v10.0.0, ..., v10.39.0].
    - illuminate/http[v10.0.0, ..., v10.39.0] require illuminate/session ^10.0 -> satisfiable by illuminate/session[v10.0.0, ..., v10.39.0].
    - Root composer.json requires crescat-io/saloon-sdk-generator ^1.10 -> satisfiable by crescat-io/saloon-sdk-generator[v1.10.0].

Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.
You can also try re-running composer require with an explicit version constraint, e.g. "composer require crescat-io/saloon-sdk-generator:*" to figure out if any version is installable, or "composer require crescat-io/saloon-sdk-generator:^2.1" if you know which you need.

can you advice please

[Feature Request] Ability to "name" resources based on path segments instead of tags/names in OpenAPI Spec

Problem

image

Possible solution

Should be a flag or config option that will generate Resource names based on path segments (/api/projects/10/comments/2 where --segment=4,2 would first try the 4th segment in the path, and fallback to the 2nd if it cant be found.)

Alternative solutions

Regex

Specify a regex capture group to specify the resource and class names

$uri = 'posts/25/comments/>postNewComment';
$pattern = '{(?<resourceName>\w+)/\d+/(?requestName)}';

Might be stupid and brittle though...

Prompt user for each request

Annoying, but possibly useful, maybe use laravel prompts to build a "table" interface with arrow navigation and inputs.... dunno, might be decent.

Use AI

Requires API Key for an AI service, might generate garbage, might potentially be a fallback solution when everything else fails..

Incorrectly generated description

Given this API: https://developers.checkmango.com/operation/operation-createexperiment

The generated request class CreateExperiment has a bad comment:

/**
 * createExperiment
 */
class CreateExperiment extends Request
{
	protected Method $method = Method::POST;


	public function resolveEndpoint(): string
	{
		return "/api/teams/{$this->team}/experiments";
	}


	/**
-	 * @param int $team The ID of the team to list experiments in.
+	 * @param int $team The ID of the team to create the experiment in.
	 */
	public function __construct(
		protected int $team,
	) {
	}
}

Incorrectly generated method signature

Given this endpoint https://developers.checkmango.com/group/endpoint-ingestion, the generated request class is incorrect:

<?php

namespace Checkmango\Requests\Ingestion;

use Saloon\Enums\Method;
use Saloon\Http\Request;

/**
 * ingestData
 *
 * This endpoint handles all ingestion of data into the system, including enrolments, impressions and
 * conversions.
 *
 * > warn
 * > Participants may only be enrolled into a running experiment.
 */
class IngestData extends Request
{
    protected Method $method = Method::POST;

    public function resolveEndpoint(): string
    {
        return "/api/teams/{$this->teamId}/ingest";
    }

    /**
     * @param  int  $team The ID of the team.
     */
    public function __construct(
        protected int $teamId,
        protected int $team,
    ) {
    }
}

Note that the __construct generates with both teamId and team, but only teamId is referenced in the API?

Optional Query Parameters

Hey @HelgeSverre. I'm chipping away my SDK ๐Ÿ˜„ and came across another one to discuss.

All query parameters are added as class properties but query parameters don't appear to ever have nullable set so they're always required.

https://github.com/Space48/bigcommerce-api-php/blob/main/generated/Space48/Bigcommerce/Requests/Customers/CustomersGet.php#L60

I took a look at the OpenAPIParser and the mapParams method. It seems like in the underlying library defaults to nullable being false if there is a type vendor/cebe/php-openapi/src/spec/Schema.php:L130 despite your true default here if it's not set:

nullable: $parameter->schema?->nullable ?? true,

I wonder about whether we add a mapping for the required property of parameter to your own parameter class. This would allow us to maintain the distinction between required and nullable. Based on the spec, it seems that `required should default to false, unless explicitly defined in the spec, or if is a path parameter. We can then use that to determine whether query parameters are optional/required.

In terms of the Request classes, they would then have required and optional/nullable arguments, and then the defaultQuery method could also be updated to wrapped in array_filter to remove null query fields.

Let me know what you think!

[Help/debugging] POST headers & body not being generated

๐Ÿ‘‹ Heyo! Finally got around to working on more of my banking sdk. Thought I'd make an issue for investigation instead of going on socials just for better visibility/tracking.

I'm using the OpenAPI specification files from the bank's API, for example this one. On that page you'll see a download button for the OpenAPI file that I'm using with the generator.

The generator generates all the requests, connectors, etc. correctly. The issues I'm having are that some headers and POST bodies are not being populated in the requests. I'm going to assume this is due to the OpenAPI spec file being quirky and having more complex specs maybe?

Let's take the Post Category request for example. The generated CreateCategory request class is bare:

Screenshot 2023-09-18 at 22 16 23

Meanwhile, the Swagger editor seems to pick the header & body up correctly:

Screenshot 2023-09-18 at 22 17 29

All requests in this api also require an intermediaryId header value, but this is not picked up in any of the generation.


Command-wise, what I'm running is:

sdkgenerator generate:sdk ~/Downloads/CIBForIntermediaries.json --type=openapi --namespace=InvestecSdkPhp

Any ideas? Is the OpenAPI spec file being weird, or am I doing something wrong?

Reserved Word Protection

Hi @HelgeSverre! Thanks for this project. I'm just trying it out and I ran into an error when a Request class is created with a reserved word. Here, you will see an endpoint /void which then errors when trying to create a class Void.

Initially I replaced the RequestGenerator with a version that would catch the exception that's thrown and then try again with a suffix, e.g. VoidRequest.

However, that then has a problem where the same logic is required in the ResourceGenerator.

So then I was wondering if a check for reserved words might be better done somewhere centrally, like in the NameHelper here.

The challenge then is knowing how to adjust the class name with an appropriate suffix.

If you have advice on a route you would prefer, I'd be happy to work on a PR when I have a moment.

Argument #2 ($schema) must be of type cebe\openapi\spec\Schema

I tried to give the new DTO feature a spin and ran into an issue:

In DtoGenerator.php line 35:

  Crescat\SaloonSdkGenerator\Generators\DtoGenerator::generateDtoClass(): Argument #2 ($schema) must be of type cebe\openapi\spec\Schema, cebe\openap
  i\spec\Reference given, called in phar:///app/vendor/crescat-io/saloon-sdk-generator/builds/sdkgenerator/src/Generators/DtoGenerator.php on line 28


Script sdkgenerator generate:sdk merged.json --type=openapi --name="SaloonConnector" --output=src --namespace=ShipStream\\FedEx --force handling the generate-sdk event returned with error code 1

Let me know if you'd like to take a look at the repo but basically all it does is merge multiple OpenAPI specs into merged.json, apply some sanitization to the spec (e.g. adding tags) then run the sdkgenerator. It worked on version 1.10.0 but does not work on 1.2.0.

Side note: When using "composer require" the default version installed is 1.10, not 1.2 since 1.10 is "newer".. Took me a while to figure out why I wasn't seeing any DTO generated.. :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.