fern-api / fern

Input OpenAPI. Output SDKs and Docs.
https://buildwithfern.com
Apache License 2.0
2.68k stars 150 forks source link

[Feature] Object Oriented SDKs #2544

Open dsinghvi opened 10 months ago

dsinghvi commented 10 months ago

Problem description

Often times, API resources are interconnected and it is natural to propagate these relationships directly into the SDK. See the snippet below, which uses the Github API as an example

const user = client.user.get("user-id..."); 
const repositories = user.get_repos(); 

In the example above, you can call get_repos directly on the user response. In comparison, today, with Fern, the user would instead have to call client.repositories.filter(user_id = user.id).

Why would it be useful?

This is more intuitive for developers and reduces boilerplate.

Describe the solution (optional)

The solution here is to introduce a new primitive into fern, called "methods". Every type defined in the API can have methods, which make calls to API endpoints. For the users example above, this is what the Fern Definition would look like:

imports: 
  repos: repos.yml

types: 
  User: 
    methods: # <---------------  new methods key
      get_repos: # <------------  name of method
        endpoint: repos.list # <--- the endpoint to proxy to 
        parameters: 
          user_id: $.id  # <-------- any parameters to pass in from the type itself
    properties: 
      id: 
        type: string
        docs: The ID of the user. 

For users coming from OpenAPI, we would support a x-fern-methods extension directly on the schema.

components: 
  schemas: 
    User: 
      x-fern-methods: 
        get_repos: 
           path: /users
           method: POST
           parameters: 
             user_id: $.id
      properties: 
        id:
          type: string 
xgp commented 2 months ago

Adding the idea that you may want a method to return another object.

For example, an Organization has a Role that has Members

api.organizations(orgId).roles("play-tuba").addMember(userId);

Where

I'm not sure the specification suggested could allow generation of such hierarchies.

xgp commented 1 month ago

See the *Resource classes that can be accessed via PhaseTwo client as an example https://github.com/p2-inc/phasetwo-java/tree/main/src/main/java/io/phasetwo/client