Git Product home page Git Product logo

microsoft / kiota Goto Github PK

View Code? Open in Web Editor NEW
2.3K 40.0 155.0 25.03 MB

OpenAPI based HTTP Client code generator

Home Page: https://aka.ms/kiota/docs

License: MIT License

C# 95.14% Dockerfile 0.05% Ruby 0.14% Swift 0.36% CSS 0.06% JavaScript 0.13% Java 0.84% TypeScript 2.12% PowerShell 0.95% Go 0.15% PHP 0.02% Python 0.03% Kotlin 0.03%
openapi csharp typescript java dotnet golang ruby php http api

kiota's Introduction

Project

Dotnet CodeQL Coverage Sonarcloud Status

Kiota is a command line tool for generating an API client to call any OpenAPI described API you are interested in. The goal is to eliminate the need to take a dependency on a different API SDK for every API that you need to call. Kiota API clients provide a strongly typed experience with all the features you expect from a high quality API SDK, but without having to learn a new library for every HTTP API.

This library builds on top of the Microsoft.OpenAPI.NET library to ensure comprehensive support for APIs that use OpenAPI descriptions. One of the goals of the project is to provide the best code generator support possible for OpenAPI and JSON Schema features. The conceptual documentation describes how kiota works and the high level concepts, this readme documents how to get started with Kiota.

Getting started

Generating SDKs

  1. Install required tools and dependencies. (refer to the Supported Languages table under the Required tools & dependencies column)
  2. Get Kiota using one of the available options.
  3. Generate your API client, checkout the Parameters reference for the different options.
  4. Start calling your API using your fluent API Client.

Supported languages

The following table provides an overview of the languages supported by Kiota and the progress in the implementation of the different components.

Language Generation Abstractions Serialization Authentication HTTP Required tools & dependencies
CSharp FORM, JSON, MULTIPART, TEXT Anonymous, API Key, Azure link
Go FORM, JSON, MULTIPART, TEXT Anonymous, API Key, Azure link
Java FORM, JSON, MULTIPART, TEXT Anonymous, API Key, Azure link
PHP JSON, ❌ FORM, ❌ MULTIPART, TEXT Anonymous, ✔️ PHP League link
Python FORM, JSON, MULTIPART, TEXT Anonymous, Azure link
Ruby ❌ FORM, JSON, ❌ MULTIPART, ❌ TEXT Anonymous, ✔️ OAuth2
CLI (see CSharp) + (see CSharp) (see CSharp) (see CSharp) link
Swift ❌ FORM, ❌ JSON, ❌ FORM, ❌ TEXT Anonymous, ❌ Azure
TypeScript/JavaScript FORM, JSON, MULTIPART, TEXT Anonymous, API Key, Azure, SPFx link

Legend: ✔ -> in preview, ❌ -> not started, ▶ -> in progress.

Parameters reference

Parameters are documented here.

Debugging

Make sure you install the pre-requisites first. If you are using Visual Studio Code as your IDE, the launch.json file already contains the configuration to run Kiota. By default this configuration will use the openApiDocs/v1.0/Mail.yml under the PowerShell repository as the OpenAPI to generate an SDK for. By default this configuration will output the generated files in a graphdotnetv4|graphjavav4|graphtypescriptv4 folder located in the parent folder this repository is cloned in.

Selecting the language you want to generate an API client for in the Visual Studio Debug tab and hitting F5 will automatically build, start, and attach the debugging process to Kiota.

Samples

You can find samples of clients generated with Kiota in the Kiota samples repository.

An example of an application that is calling multiple API can be found in the KiotaApp repo

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.

When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.

kiota's People

Contributors

abfarah avatar andreatp avatar andrueastman avatar baywet avatar calebkiage avatar carolkigoonya avatar chausner avatar collinalpert avatar crobibero avatar darrelmiller avatar dependabot[bot] avatar github-actions[bot] avatar hossain2024 avatar iozcelik avatar isvargasmsft avatar jasonjoh avatar jobala avatar koros avatar maisarissi avatar ndiritu avatar nikithauc avatar osose-e avatar papegaaij avatar purekrome avatar ramsessanchez avatar rkodev avatar samwelkanda avatar sebastienlevert avatar silaskenneth avatar zengin avatar

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  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

kiota's Issues

Ability to execute the requests on the wire

  • implementation for dotnet auth provider + http core
  • implementation for java auth provider + http core
  • implementation for typescript auth provider + http core
  • abstraction for authentication provider for dotnet
  • abstraction for authentication provider for java
  • abstraction for authentication provider for typescript
    AB#8498

Add additional properties on the using statements

In languages like typescript or java we need additional properties:

  • import symbol (that'd be the class name in the case of TypeScript/java)
  • external import or not (to understand whether it's something we've generated or not)
  • some kind of namespace prefixing information for local imports

Add support for alternative allOf inheritance definition

We currently have implemented one case of inheritance definition which is when all types in the inheritance tree are defined in the all of collection.
In the OpenAPI semantics, there's another way of defining inheritance where the child type will be in the schema and allOf collection will contain the base type.
AB#8905

Model class with no name breaks common language refiner

       protected void MoveClassesWithNamespaceNamesUnderNamespace(CodeElement currentElement) {
            if(currentElement is CodeClass currentClass && 
                currentClass.Parent is CodeNamespace parentNamespace) {
                var childNamespaceWithClassName = parentNamespace.InnerChildElements
                                                                .OfType<CodeNamespace>()
                                                                .FirstOrDefault(x => x.Name
                                                                                    .EndsWith(currentClass.Name, StringComparison.InvariantCultureIgnoreCase));
                if(childNamespaceWithClassName != null) {
                    parentNamespace.InnerChildElements.Remove(currentClass);
                    childNamespaceWithClassName.AddClass(currentClass);
                }
            }
            CrawlTree(currentElement, MoveClassesWithNamespaceNamesUnderNamespace);
        }

CrawlTree will fail with elements that have a null name.

openapi: 3.0.0
info:
  title: "Todo API"
  version: "1.0.0"
paths:
  /todos: 
    get:
      operationId: todos_ListTodos
      parameters:
          - name: active
            in: query
            schema:
              type: boolean
          - name: keyword
            in: query
            schema:
              type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                title: collectionTodos
                type: object
                properties:
                  value:
                    items: 
                      $ref: "#/components/schemas/todo"

    post:
      operationId: todos_CreateTodo
      responses:
        '201':
          description: OK
  /todos/{todoId}:
    get:
      operationId: todos_GetTodo
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/todo"
    delete:
      operationId: todos_DeleteTodo
      responses:
        '200':
          description: OK
  /tag/{tagId}:
    get:
      operationId: todos_GetTag
      responses:
        '200':
          description: OK
components:
  schemas:
    entity:
      type: object
      properties:
        id: 
          type: string
    tag:
      type: object
      properties:
        id: 
          type: string
        displayName: 
          type: string
    todo:
      allOf:
        - $ref: "#/components/schemas/entity"
        - type: object
          properties:
            subject:
              type: string

AB#8849

Setup a samples repo as a submodule to make PR reviews easier

Darrel and I had further brainstorming on this and here is a recap.
We have multiple concerns here:

  • The launch.json configuration should be valid, the paths should resolve with minimal repos cloning/rework from people cloning this repo.
  • The parameters should be documented so people can configure other IDEs, use dotnet run, use a compiled version of kiota... #96
  • The unit tests coverage should be ramped up and test aspects, not just generate files #79
  • The PRs should provide a generation diff (more on that below)
  • We want to avoid overcrowding this repo with too many things

The solution we're suggesting is the following:

  • create a samples repo under the Microsoft Org, this repo will contain multiple projects (one for each language)
  • add this repo as a submodule to kiota's repository
  • update launch.json to point to this submodule's path

Someone PRing kiota to change the generation result should:

  1. run the generation on the sample repo
  2. create a PR in the generation repo
  3. update the submodule reference
  4. create the PR in Kiota, linking to that generation PR

This has the advantage of:

  • providing a generation diff for reviewers
  • not polluting the current repo
  • force us to start building proper unit tests
  • being simple for anyone who knows about submodules
  • not being blocking for anyone who doesn't know about submodule

Thoughts?

Originally posted by @baywet in #48 (comment)
AB#9017

add support for middleware pipeline for request execution

People need to be able to inject behavior on responses before things are returned to the caller to handle things like retry, redirect, etc...
Review the design guidance

We probably need to model:

  • ResponseInfo (abstract reflection of http response)
  • RequestMiddleware (interface for middlewares excuting before the request is sent)
  • ResponseMiddleware (interface for middlewares executing after the response is received)
  • A property bag to tag the request with options for the middleware
  • A way to register (and order?) middlewares
  • A way to set default options for requests
    AB#9081

add a better client configuration experience

The client root class needs a better configuration experience. We could either go the fluent way like current graph clients or leverage a auto registration approach (singleton/reflection that adds things automatically when importing the module/dependencies).

This configuration experience needs to account for:

  • middleware addition/reorganisation (see #120)
  • serialization/deserialization factories registration
  • core engine registration

Note: we might want to rework the authentication handler as a middleware as part of this work.
AB#9082

Entity called entity breaks the Java code gen

This code fails

       protected void FixReferencesToEntityType(CodeElement currentElement, CodeClass entityClass = null){
            if(entityClass == null)
                entityClass = currentElement.GetImmediateParentOfType<CodeNamespace>()
                            .GetRootNamespace()
                            .GetChildElementOfType<CodeClass>(x => x.Name.Equals("entity", StringComparison.InvariantCultureIgnoreCase));

with this OpenAPI

openapi: 3.0.0
info:
  title: "Todo API"
  version: "1.0.0"
paths:
  /todos: 
    get:
      operationId: todos_ListTodos
      parameters:
          - name: active
            in: query
            schema:
              type: boolean
          - name: keyword
            in: query
            schema:
              type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                title: collectionTodos
                type: object
                properties:
                  value:
                    items: 
                      $ref: "#/components/schemas/todo"

    post:
      operationId: todos_CreateTodo
      responses:
        '201':
          description: OK
  /todos/{todoId}:
    get:
      operationId: todos_GetTodo
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/todo"
    delete:
      operationId: todos_DeleteTodo
      responses:
        '200':
          description: OK
  /tag/{tagId}:
    get:
      operationId: todos_GetTag
      responses:
        '200':
          description: OK
components:
  schemas:
    entity:
      type: object
      properties:
        id: 
          type: string
    tag:
      type: object
      properties:
        id: 
          type: string
        displayName: 
          type: string
    todo:
      allOf:
        - $ref: "#/components/schemas/entity"
        - type: object
          properties:
            subject:
              type: string

AB#8848

Generate methods to get the generic request

We'll need the generic request for batching/parallelization of calls. We need to generate additional methods to be able to get that abstract object without executing the call.
Split the request executors in two halves, the second one calling the first one like this

@javax.annotation.Nullable
    public RequestInfo createGetRequest(@javax.annotation.Nonnull final java.util.function.Consumer<GetQueryParameters> q, @javax.annotation.Nonnull final java.util.function.Consumer<Map<String, String>> h) throws URISyntaxException {
        Objects.requireNonNull(q);
        Objects.requireNonNull(h);
        final RequestInfo requestInfo = new RequestInfo() {{
            uri = new URI(currentPath);
            httpMethod = HttpMethod.GET;
        }};
        final GetQueryParameters qParams = new GetQueryParameters();
        q.accept(qParams);
        qParams.AddQueryParameters(requestInfo.queryParameters);
        h.accept(requestInfo.headers);
        return requestInfo;
    }
    @javax.annotation.Nullable
    public java.util.concurrent.CompletableFuture<MessagesResponse> get(@javax.annotation.Nonnull final java.util.function.Consumer<GetQueryParameters> q, @javax.annotation.Nonnull final java.util.function.Consumer<Map<String, String>> h, @javax.annotation.Nonnull final ResponseHandler responseHandler) {
        Objects.requireNonNull(q);
        Objects.requireNonNull(h);
        Objects.requireNonNull(responseHandler);
        try {
            final RequestInfo requestInfo = this.createGetRequest(q, h);
            return this.httpCore.sendAsync(requestInfo, responseHandler);
        } catch (URISyntaxException ex) {
            return java.util.concurrent.CompletableFuture.failedFuture(ex);
        }
    }

Additionally we might want to add a "addRequestToBatch(batch)" mehtod on the request info to enable fluent style batch building.
AB#8503

Request builder generic type parameter with type restriction overload

I suggest that we generate an overload that uses type parameters with constraints instead of concrete types in our final request builder. This could serve the following purposes:

  1. If the CSDL references a base type, the generated derived type serialization instructions can be used instead of the base type serialization instructions. No derivedtypeconverter
  2. In the case that the generated library hasn't been updated and there is a new derived type, a customer can derive from the base type, add the missing properties, and add serialization instructions as a quick fix until the generated library can be updated.
  3. Some customers like to use our models as the model for their applications. They GET the object, change the object, and then PATCH the object. This results in the entire object being sent in the PATCH, instead of a PATCH object containing only the updated properties. This results in serialized properties being sent that are read-only and ignored, or even properties that cause errors in the service when the service doesn't gracefully ignore unexpected properties. We provide guidance for this scenario where we have them derive from the base type, and they can potentially enhance their model with something like a PropertyChanged event to provide instruction to the Serialize(writer) method. We should consider how we would instruct the user to propagate PropertyChanged down to the base.Serialize method so that they could control serialization from their custom derived type into our generated base types without having special instructions in the SerializationWriter. OR, we just tell them to new up an object with just their changes.

The Serialize method in the model is interesting.

MessageRequestBuilder

public class MessagesRequestBuilder<T> where T : Message {
    public MessageRequestBuilder this[string position] { get {
        return new MessageRequestBuilder { HttpCore = HttpCore, CurrentPath = CurrentPath + PathSegment  + "/" + position};
    } }
    public async Task<MessagesResponse<T>> GetAsync(Action<GetQueryParameters> q = default, Action<IDictionary<string, string>> h = default, IResponseHandler responseHandler = default) {
        var requestInfo = new RequestInfo {
            HttpMethod = HttpMethod.GET,
            URI = new Uri(CurrentPath),
        };
        if (q != null) {
            var qParams = new GetQueryParameters();
            q.Invoke(qParams);
            qParams.AddQueryParameters(requestInfo.QueryParameters);
        }
        h?.Invoke(requestInfo.Headers);
        return await HttpCore.SendAsync<MessagesResponse<T>>(requestInfo, responseHandler);
    }
    public async Task<T> PostAsync(Action<IDictionary<string, string>> h = default, IResponseHandler responseHandler = default) {
        var requestInfo = new RequestInfo {
            HttpMethod = HttpMethod.POST,
            URI = new Uri(CurrentPath),
        };
        h?.Invoke(requestInfo.Headers);
        return await HttpCore.SendAsync<T>(requestInfo, responseHandler);
    }
    // ....
    }
}

MessageResponse

public class MessagesResponse<T> where T : Message {
    public List<T> Value { get; set; }
    public string NextLink { get; set; }
}

AB#8908

Fix java relative imports

There's still a bug in Java for the import for the GraphClient. It needs to do relative calculation like typescript does

related #12

Generate RequestBuilders in a hierarchy of folder and namespaces

Using this approach we can remove the need to generate hashes on request builder class names to avoid name clashes.

namespace MicrosoftGraph.Users
  UsersRequestBuilder
  
namespace microsoftgraph.Users.Messages
  MessagesRequestBuilder

namespace microsoftgraph.Users.Messages.Item
  MessageRequestBuilder

namespace microsoftgraph.users.Messages.Item.attachments
  AttachmentsRequestBuilder

namespace microsoftgraph.Users.MailFolder.Item.Messages.Item
  MessageRequestBuilder

Make OperationId optional

Currently we depend on OperationId but it is not a required field in OpenAPI, so if we can avoid being dependent on it, that would be good.

private string GetNamespaceNameForModelByOperationId(string operationId) {
            if(string.IsNullOrEmpty(operationId)) throw new ArgumentNullException(nameof(operationId));
            var cleanOperationId = operationId.Split('_').First();
            return $"{this.config.ClientNamespaceName}.{cleanOperationId}";
        }

AB#8847

Release kiota image on mcr.microsoft.com and dotnet tool on nuget.org

Can we please have the docker image stored in the newer ghcr.io registry? means we don't need auth/PAT's.

Currently there are 2 GH Docker registries, one at docker.pkg.github.com and a new one at ghcr.io. The original registry always requires a PAT with the read:packages scope (even for public packages). The new ghcr.io registry has the option to create true public container packages.

If you publish an image to ghcr.io you can make it public with no auth required. See here for more information:
https://docs.github.com/en/packages/guides/configuring-access-control-and-visibility-for-container-images#configuring-visibility-of-container-images-for-an-organization
AB#9098

getting started documentation

This repository is lacking getting started information so people can try kiota and contribute. It should contain:

  • the list of tools that are required
  • the documentation for the different parameters
  • links to sample OpenAPI descriptions
  • links to the design documentation
    AB#8966

Question: can we accept "json" OpenApi input files?

The OpenApi files I try playing with are either the common sample PetStore swagger file (ref: https://petstore.swagger.io/ ) or a default dotnet new webapi template with swagger enabled.

Does Kiota accept .json openapi files?

very briefly checking the code, it feels like it's yaml only?

EDIT: i know that the swagger editor can save the json as yml ... but i'm just curious about just json without having to do the manual conversion?

EDIT 2: here's the sample json file i was using: https://petstore.swagger.io/v2/swagger.json
Same error occured when I saved it as yml (via https://editor.swagger.io/ ) and tried that :/

image

AB#9047

CSharp entrypoint + mapping needs update

there's still a bug in the CSHarp writer because of the recent change of not using namespaces as an entry point. The mapping needs to be updated like Java/Tyepescript, and the usings need to be tested

related #12

break writers down into a visitor pattern

our language writers are getting bigger and bigger, which makes things hard to maintain, scope, and test. We should break them in a visitor pattern. Each visitor would implement the "write" method of IWriter<T> where T : CodeElement. Visitors would be registered via a method somewhere for each language.
AB#8904

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.