Skip to content
Sean Reeise edited this page Jun 1, 2023 · 4 revisions

Codegen Related Information

How clients are generated using paths

As example, paths that start with /teams/{team-id} have links to another client primaryChannel with paths /teams/{team-id}/primaryChannel?

client
    .team("team-id")
    .primaryChannel("primary-channel-id")
    .get_primary_channel()

Explanation

You could certainly try to store these different api methods under one client since their paths start with the same resource (teams) but your going to run into several issues and quickly. Those issues were the reason for several design decisions about codegen and the library itself. Its important to understand these reasons to understand how codegen parses and writes the api impls:

  1. The OpenApi config that Microsoft provides has a habit of giving the same method names to requests despite being totally different paths/APIs. A simple example is all of the $count paths

I searched all usages of $count in the already generated teams directory and found 10+ usages such as:

"/teams/sharedWithTeams/$count"
"/teams/{team-id}/primaryChannel/tabs/$count"
"/teams/{team-id}/allChannels/$count"
"/teams/{team-id}/schedule/timesOff/$count"

In the OpenApi config Microsoft has decided the method name for all of these 10+ requests, which are distinct on their own, should be count. So, if you havn't figure it out already, having 10+ methods under the same impl will not compile. For methods like count this is mainly due to how the OpenApi configs are designed to be implemented by object oriented programming languages and therefore the amount of times we see count is not necessarily reflective of poor OpenAPI configurations. We will get to that later however.

  1. The client is much easier to use and find the APIs you want when they are divided logically by their paths.
  2. The OpenApi configs are heavily designed to aid in building API clients based on object oriented programming languages. Rust is not so adept at building object oriented design unless you decide your going to use some odd techniques and possibly anti-Rust patterns. The API clients themselves are using the operation id and tags which is provided by OpenApi configs and provides a class hierarchy based on inheritance and polymorphism as well as the method name. For instance:

Trimmed down part of a request in the OpenApi config:

{
  "/sets": {
    "description": "Provides operations to manage the sets property of the microsoft.graph.termStore.store entity.",
    "get": {
      "tags": [
        "sites.store"
      ],
      "operationId": "sites.termStore.ListSets"
    }
  }
}
  1. Even if we could come up with a decent algorithm to get the correct hierarchy from the operation id, the OpenApi configs are unfortunately all over the place when it comes to consistency with the naming and ids (sites, termStores), used.
    • They may have 2 or 3 operation id's which is suppose to be under the same sites.termStore hierarchy as some random operation id that doesn't have any relation to any other class or operation id.
    • They may totally botch the naming of the operation id to the point where its not even discernible what it was meant to be just by reading it.
  2. Lastly, there are whole sets of operation ids where some random grouping of characters is tacked onto the end of the operation id. Examples:

These are two requests that are under the same reports API:

operation_id: "reports.getTeamsUserActivityUserDetail-7554",
operation_id: "reports.getTeamsUserActivityUserDetail-fba7"

I have yet to figure out what those characters on the end are referencing. If anyone finds out I would love to know. Even if we remove those characters at the end including the dash we are still left with the same method name.