diff --git a/specs/assets/core-diagram.png b/specs/assets/core-diagram.png new file mode 100644 index 0000000000..9c82ba3d6e Binary files /dev/null and b/specs/assets/core-diagram.png differ diff --git a/specs/cli/client-add.md b/specs/cli/client-add.md new file mode 100644 index 0000000000..32b0858e8c --- /dev/null +++ b/specs/cli/client-add.md @@ -0,0 +1,125 @@ +# kiota client add + +## Description + +`kiota client add` allows a developer to add a new API client to the `kiota-config.json` file. If no `kiota-config.json` file is found, a new `kiota-config.json` file would be created in thr current working directory. The command will add a new entry to the `clients` section of the `kiota-config.json` file. Once this is done, a local copy of the OpenAPI description is generated and kept in the `.kiota/descriptions` folder. + +When executing, a new API entry will be added and will use the `--client-name` parameter as the key for the map. When loading the OpenAPI description, it will store the location of the description in the `descriptionLocation` property. If `--include-path` or `--exclude-path` are provided, they will be stored in the `includePatterns` and `excludePatterns` properties respectively. + +Every time an API client is added, a copy of the OpenAPI description file will be stored in the `./.kiota/{client-name}` folder. The files will be named using the API client name. This will allow the CLI to detect changes in the description and avoid downloading the description again if it hasn't changed. + +At the same time, an [API Manifest](https://www.ietf.org/archive/id/draft-miller-api-manifest-01.html#section-2.5-3) file will be generated (if non existing) or edited (if already existing) to represent the surface of the API being used. This file will be named `apimanifest.json` and next to the `kiota-config.json`. This file will be used to generate the code files. + +Once the `kiota-config.json` file is generated and the OpenAPI description file is saved locally, the code generation will be executed and then the API Manifest would become available. + +## Parameters + +| Parameters | Required | Example | Description | +| -- | -- | -- | -- | +| `--config-location \| --cl` | No | ../../ | A location where to find or create the `kiota-config.json` file. When not specified it will find an ancestor `kiota-config.json` file and if not found, will use the defaults. Defaults to `./`. | +| `--client-name \| --cn` | Yes | graphDelegated | Name of the client. Unique within the parent API. If not provided, defaults to --class-name or its default. | +| `--openapi \| -d` | Yes | https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml | The location of the OpenAPI description in JSON or YAML format to use to generate the SDK. Accepts a URL or a local path. | +| `--search-key \| --sk` | No | github::microsoftgraph/msgraph-metadata/graph.microsoft.com/v1.0 | The search key used to locate the OpenAPI description. | +| `--include-path \| -i` | No | /me/chats#GET | A glob pattern to include paths from generation. Accepts multiple values. Defaults to no value which includes everything. | +| `--exclude-path \| -e` | No | \*\*/users/\*\* | A glob pattern to exclude paths from generation. Accepts multiple values. Defaults to no value which excludes nothing. | +| `--language \| -l` | Yes | csharp | The target language for the generated code files or for the information. | +| `--class-name \| -c` | No | GraphClient | The name of the client class. Defaults to `Client`. | +| `--namespace-name \| -n` | No | Contoso.GraphApp | The namespace of the client class. Defaults to `Microsoft.Graph`. | +| `--backing-store \| -b` | No | | Defaults to `false` | +| `--exclude-backward-compatible \| --ebc` | No | | Whether to exclude the code generated only for backward compatibility reasons or not. Defaults to `false`. | +| `--serializer \| -s` | No | `Contoso.Json.CustomSerializer` | One or more module names that implements ISerializationWriterFactory. Default are documented [here](https://learn.microsoft.com/openapi/kiota/using#--serializer--s). | +| `--deserializer \| --ds` | No | `Contoso.Json.CustomDeserializer` | One or more module names that implements IParseNodeFactory. Default are documented [here](https://learn.microsoft.com/en-us/openapi/kiota/using#--deserializer---ds). | +| `--structured-media-types \| -m` | No | `application/json` |Any valid media type which will match a request body type or a response type in the OpenAPI description. Default are documented [here](https://learn.microsoft.com/en-us/openapi/kiota/using#--structured-mime-types--m). | +| `--skip-generation \| --sg` | No | true | When specified, the generation would be skipped. Defaults to false. | +| `--output \| -o` | No | ./generated/graph/csharp | The output directory or file path for the generated code files. Defaults to `./output`. | + +> [!NOTE] +> It is not required to use the CLI to add new clients. It is possible to add a new client by adding a new entry in the `clients` section of the `kiota-config.json` file. See the [kiota-config.json schema](../schemas/kiota-config.json.md) for more information. + +## Using `kiota client add` + +```bash +kiota client add --client-name "graphDelegated" --openapi "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml" --include-path "**/users/**" --language csharp --class-name "GraphClient" --namespace-name "Contoso.GraphApp" --backing-store --exclude-backward-compatible --serializer "Contoso.Json.CustomSerializer" --deserializer "Contoso.Json.CustomDeserializer" -structured-mime-types "application/json" --output "./generated/graph/csharp" +``` + +_The resulting `kiota-config.json` file will look like this:_ + +```jsonc +{ + "version": "1.0.0", + "clients": { + "graphDelegated": { + "descriptionLocation": "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml", + "includePatterns": ["**/users/**"], + "excludePatterns": [], + "language": "csharp", + "outputPath": "./generated/graph/csharp", + "clientClassName": "GraphClient", + "clientNamespaceName": "Contoso.GraphApp", + "features": { + "structuredMediaTypes": [ + "application/json" + ], + "usesBackingStore": true, + "includeAdditionalData": true + } + } + } +} +``` + +_The resulting `apimanifest.json` file will look like this:_ + +```jsonc +{ + "apiDependencies": { + "graphDelegated": { + "x-ms-apiDescriptionHash": "9EDF8506CB74FE44...", + "apiDescriptionUrl": "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml", + "apiDeploymentBaseUrl": "https://graph.microsoft.com", + "apiDescriptionVersion": "v1.0", + "requests": [ + { + "method": "GET", + "uriTemplate": "/users" + }, + { + "method": "POST", + "uriTemplate": "/users" + }, + { + "method": "GET", + "uriTemplate": "/users/$count" + }, + { + "method": "GET", + "uriTemplate": "/users/{user-id}" + }, + { + "method": "PATCH", + "uriTemplate": "/users/{user-id}" + }, + { + "method": "DELETE", + "uriTemplate": "/users/{user-id}" + } + ] + } + } +} +``` + +## File structure +```bash +/ + └─.kiota + └─definitions + └─graphDelegated.yaml + └─generated + └─graph + └─csharp + └─... # Generated code files + └─GraphClient.cs + └─apimanifest.json + └─kiota-config.json +``` \ No newline at end of file diff --git a/specs/cli/client-edit.md b/specs/cli/client-edit.md new file mode 100644 index 0000000000..495ec082df --- /dev/null +++ b/specs/cli/client-edit.md @@ -0,0 +1,120 @@ +# kiota client edit + +## Description + +`kiota client update` allows a developer to edit an existing API client int the `kiota-config.json` file. If either the `kiota-config.json` file or if the `--client-name` client can't be found within the `kiota-config.json` file, the command should error out and let the developer know. + +When executing, the API entry defined by the `--client-name` parameter will be modified. All parameters should be supported and the only required one is `--client-name`. All others are optional as they would only modify the configuration of the API client. If the OpenAPI description location changed, a new hash of the description will be generated saved as part of the `descriptionHash` property. If `--include-path` or `--exclude-path` are provided, they will be stored in the `includePatterns` and `excludePatterns` properties respectively and would trigger an update to the [API Manifest](https://www.ietf.org/archive/id/draft-miller-api-manifest-01.html#section-2.5-3). + +Once the `kiota-config.json` file and the API Manifest are updated, the code generation will be executed based on the newly updated API client configuration. + +## Parameters + +| Parameters | Required | Example | Description | +| -- | -- | -- | -- | +| `--config-location \| --cl` | No | ../../ | A location where to find or create the `kiota-config.json` file. When not specified it will find an ancestor `kiota-config.json` file and if not found, will use the defaults. Defaults to `./`. | +| `--client-name \| --cn` | Yes | graphDelegated | Name of the client. Unique within the parent API. If not provided, defaults to --class-name or its default. | +| `--openapi \| -d` | No | https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml | The location of the OpenAPI description in JSON or YAML format to use to generate the SDK. Accepts a URL or a local path. | +| `--include-path \| -i` | No | /me/chats#GET | A glob pattern to include paths from generation. Accepts multiple values. Defaults to no value which includes everything. | +| `--exclude-path \| -e` | No | \*\*/users/\*\* | A glob pattern to exclude paths from generation. Accepts multiple values. Defaults to no value which excludes nothing. | +| `--language \| -l` | No | csharp | The target language for the generated code files or for the information. | +| `--class-name \| -c` | No | GraphClient | The name of the client class. Defaults to `Client`. | +| `--namespace-name \| -n` | No | Contoso.GraphApp | The namespace of the client class. Defaults to `Microsoft.Graph`. | +| `--backing-store \| -b` | No | | Defaults to `false` | +| `--exclude-backward-compatible \| --ebc` | No | | Whether to exclude the code generated only for backward compatibility reasons or not. Defaults to `false`. | +| `--serializer \| -s` | No | `Contoso.Json.CustomSerializer` | One or more module names that implements ISerializationWriterFactory. Default are documented [here](https://learn.microsoft.com/openapi/kiota/using#--serializer--s). | +| `--deserializer \| --ds` | No | `Contoso.Json.CustomDeserializer` | One or more module names that implements IParseNodeFactory. Default are documented [here](https://learn.microsoft.com/en-us/openapi/kiota/using#--deserializer---ds). | +| `--structured-media-types \| -m` | No | `application/json` |Any valid media type which will match a request body type or a response type in the OpenAPI description. Default are documented [here](https://learn.microsoft.com/en-us/openapi/kiota/using#--structured-mime-types--m). | +| `--skip-generation \| --sg` | No | true | When specified, the generation would be skipped. Defaults to false. | +| `--output \| -o` | No | ./generated/graph/csharp | The output directory or file path for the generated code files. Defaults to `./output`. | + +> [!NOTE] +> It is not required to use the CLI to edit clients. It is possible to edit a client by modifying its entry in the `clients` section of the `kiota-config.json` file. See the [kiota-config.json schema](../schemas/kiota-config.json.md) for more information. + +## Using `kiota client edit` + +```bash +kiota client edit --client-name "graphDelegated" --class-name "GraphServiceClient" --exclude-path "/users/$count" +``` + +_The resulting `kiota-config.json` file will look like this:_ + +```jsonc +{ + "version": "1.0.0", + "clients": { + "graphDelegated": { + "descriptionLocation": "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml", + "includePatterns": ["**/users/**"], + "excludePatterns": ["/users/$count"], + "language": "csharp", + "outputPath": "./generated/graph/csharp", + "clientClassName": "GraphServiceClient", + "clientNamespaceName": "Contoso.GraphApp", + "features": { + "structuredMediaTypes": [ + "application/json" + ], + "usesBackingStore": true, + "includeAdditionalData": true + } + } + } +} +``` + +_The resulting `apimanifest.json` file will look like this:_ + +```jsonc +{ + "publisher": { + "name": "Microsoft Graph", + "contactEmail": "graphsdkpub@microsoft.com" + }, + "apiDependencies": { + "graphDelegated": { + "x-ms-apiDescriptionHash": "9EDF8506CB74FE44...", + "apiDescriptionUrl": "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml", + "apiDeploymentBaseUrl": "https://graph.microsoft.com", + "apiDescriptionVersion": "v1.0", + "requests": [ + { + "method": "GET", + "uriTemplate": "/users" + }, + { + "method": "POST", + "uriTemplate": "/users" + }, + { + "method": "GET", + "uriTemplate": "/users/{user-id}" + }, + { + "method": "PATCH", + "uriTemplate": "/users/{user-id}" + }, + { + "method": "DELETE", + "uriTemplate": "/users/{user-id}" + } + ] + } + } +} +``` + +## File structure +```bash +/ + └─.kiota + └─definitions + └─graphDelegated.yaml + └─generated + └─graph + └─csharp + └─... # Generated code files + └─GraphClient.cs + └─apimanifest.json + └─kiota-config.json +``` \ No newline at end of file diff --git a/specs/cli/client-generate.md b/specs/cli/client-generate.md new file mode 100644 index 0000000000..c86b27cfdb --- /dev/null +++ b/specs/cli/client-generate.md @@ -0,0 +1,37 @@ +# kiota client generate + +## Description + +Now that we have a `kiota-config.json` file, all the parameters required to generate the code are stored in the file. The `kiota client generate` command will read the `kiota-config.json` file and generate the code for each of the available clients. + +It's also possible to specify for which API and client the code should be generated. This is useful when a project contains multiple clients. The `kiota client generate --client-name "MyClient"` command will read the `kiota-config.json` file and generate the code for the specified client. If it can't find the specified API or client, it will throw an error. + +In general cases, the `kiota client generate` command will generate the code for all the clients in the `kiota-config.json` file based on the cached OpenAPI description. If the `--refresh` parameter is provided, the command will refresh the cached OpenAPI description(s), update the different `descriptionHash` and then generate the code for the specified clients. + +## Parameters + +| Parameters | Required | Example | Description | +| -- | -- | -- | -- | +| `--config-location \| --cl` | No | ../../ | A location where to find or create the `kiota-config.json` file. When not specified it will find an ancestor `kiota-config.json` file and if not found, will use the defaults. Defaults to `./`. | +| `--client-name \| --cn` | No | graphDelegated | Name of the client. Unique within the parent API. | +| `--refresh \| -r` | No | true | Provided when refreshing the description(s) is required. | + +## Usage + +### Using `kiota client generate` for a single API client + +```bash +kiota client generate --client-name "graphDelegated" +``` + +### Using `kiota client generate` for all API clients + +```bash +kiota client generate +``` + +### Using `kiota client generate` for all API clients and refresh their descriptions + +```bash +kiota client generate +``` diff --git a/specs/cli/client-remove.md b/specs/cli/client-remove.md new file mode 100644 index 0000000000..2f3f3ba58d --- /dev/null +++ b/specs/cli/client-remove.md @@ -0,0 +1,46 @@ +# kiota client remove + +## Description + +`kiota client remove` allows a developer to remove an existing client from the `kiota-config.json` file. The command will remove the entry from the `clients` section of `kiota-config.json` file. The command has a single required parameters; the name of the client. + +The command also has one optional parameter, the ability to remove the generated client. If provided, kiota will delete the folder and its content specified at the `outputPath` from the client configuration. It will also remove the local version of the OpenAPI description file (specified by the `descriptionHash` property). The API Manifest is also updated to remove the dependency from the list of dependencies. + +| Parameters | Required | Example | Description | +| -- | -- | -- | -- | +| `--config-location \| --cl` | No | ../../ | A location where to find or create the `kiota-config.json` file. When not specified it will find an ancestor `kiota-config.json` file and if not found, will use the defaults. Defaults to `./`. | +| `--client-name \| --cn` | Yes | graphDelegated | Name of the client | +| `--clean-output \| --co` | No | | Cleans the generated client | + +#### Using kiota client remove + +```bash +kiota client remove --client-name "graphDelegated" --clean-output +``` + +The resulting `kiota-config.json` file will look like this: + +```jsonc +{ + "version": "1.0.0", + "clients": { } +} +``` + +_The resulting `apimanifest.json` file will look like this:_ + +```jsonc +{ + "apiDependencies": { } +} +``` + +## File structure +```bash +/ + └─.kiota + └─generated + └─graph + └─kiota-config.json + └─apimanifest.json +``` \ No newline at end of file diff --git a/specs/cli/config-init.md b/specs/cli/config-init.md new file mode 100644 index 0000000000..9f93a90ff3 --- /dev/null +++ b/specs/cli/config-init.md @@ -0,0 +1,37 @@ +# `kiota config init` + +## Description + +`kiota config init` creates a new kiota-config.json file with the provided parameters. If the file already exists, it should error out and report it to the user. As the file gets created, it should be adding a `version` property with the value of the `kiota-config.json` current schema version. + +When `kiota config init` is executed, a `kiota-config.json` file would be created in the current directory where the command is being executed. If the user wants to create the file in a different directory, they should use the `--config-file` global parameter. + +> [!NOTE] +> If a project only needs a single API, using `kiota config init` is not mandatory as generating code using the `kiota client generate` command could generate a `kiota-config.json` file with values coming from the `kiota client generate` command (if no `kiota-config.json` is present). See [kiota client generate](./client-generate.md) for more information. + +## Parameters + +| Parameters | Required | Example | Description | +| -- | -- | -- | -- | +| `--config-location \| --cl` | No | ../../ | A location where to find or create the `kiota-config.json` file. When not specified it will find an ancestor `kiota-config.json` file and if not found, will use the defaults. Defaults to `./`. | + +## Using `kiota config init` + +```bash +kiota config init +``` + +_The resulting `kiota-config.json` file will look like this:_ + +```jsonc +{ + "version": "1.0.0", +} +``` + +## File structure +```bash +/ + └─.kiota + └─kiota-config.json +``` \ No newline at end of file diff --git a/specs/cli/config-migrate.md b/specs/cli/config-migrate.md new file mode 100644 index 0000000000..e97fd50ce5 --- /dev/null +++ b/specs/cli/config-migrate.md @@ -0,0 +1,235 @@ +# `kiota config migrate` + +This command is valuable in cases where a code base was created with Kiota v1.0 and needs to be migrated to the latest version of Kiota. The `kiota config migrate` command will identify and locate the closest `kiota-config.json` file available. If a file can't be found, it would initialize a new `kiota-config.json` file. Then, it would identify all `kiota-lock.json` files that are within this folder structure and add each of them to the `kiota-config.json` file. Adding the clients to the `kiota-config.json` file would not trigger the generation as it only affects the `kiota-config.json` file. The `kiota client generate` command would need to be executed to generate the code for the clients. + +In the case where conflicting API client names would be migrated, the command will error out and invite the user to re-run the command providing more context for the `--client-name` parameter. + +## Parameters + +| Parameters | Required | Example | Description | +| -- | -- | -- | -- | +| `--config-location \| --cl` | No | ../../ | A location where to find or create the `kiota-config.json` file. When not specified it will find an ancestor `kiota-config.json` file and if not found, will use the defaults. Defaults to `./`. | +| `--lock-location \| --ll` | No | ./output/pythonClient/kiota-lock.json | Location of the `kiota-lock.json` file. If not specified, all `kiota-lock.json` files within in the current directory tree will be used. | +| `--client-name \| --cn` | No | graphDelegated | Used with `--lock-location`, it would allow to specify a name for the API client. Else, name is auto-generated as a concatenation of the `language` and `clientClassName`. | + +## Using `kiota config migrate` + +Assuming the following folder structure: +```bash +/ + └─generated + └─graph + └─csharp + └─... # Generated code files + └─GraphClient.cs + └─kiota-lock.json + └─python + └─... # Generated code files + └─graph_client.py + └─kiota-lock.json +``` + +```bash +kiota config migrate +``` + +_The resulting `kiota-config.json` file will look like this:_ + +```jsonc +{ + "version": "1.0.0", + "clients": { + "csharpGraphServiceClient": { + "descriptionLocation": "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml", + "includePatterns": ["**/users/**"], + "excludePatterns": [], + "language": "csharp", + "outputPath": "./generated/graph/csharp", + "clientClassName": "GraphServiceClient", + "clientNamespaceName": "Contoso.GraphApp", + "features": { + "structuredMediaTypes": [ + "application/json" + ], + "usesBackingStore": true, + "includeAdditionalData": true + } + }, + "pythonGraphServiceClient": { + "descriptionLocation": "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml", + "includePatterns": ["**/users/**"], + "excludePatterns": [], + "language": "python", + "outputPath": "./generated/graph/python", + "clientClassName": "GraphServiceClient", + "clientNamespaceName": "Contoso.GraphApp", + "features": { + "structuredMediaTypes": [ + "application/json" + ], + "usesBackingStore": true, + "includeAdditionalData": true + } + } + } +} +``` + +_The resulting `apimanifest.json` file will look like this:_ + +```jsonc +{ + "apiDependencies": { + "csharpGraphServiceClient": { + "x-ms-apiDescriptionHash": "9EDF8506CB74FE44...", + "apiDescriptionUrl": "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml", + "apiDeploymentBaseUrl": "https://graph.microsoft.com", + "apiDescriptionVersion": "v1.0", + "requests": [ + { + "method": "GET", + "uriTemplate": "/users" + }, + { + "method": "POST", + "uriTemplate": "/users" + }, + { + "method": "GET", + "uriTemplate": "/users/$count" + }, + { + "method": "GET", + "uriTemplate": "/users/{user-id}" + }, + { + "method": "PATCH", + "uriTemplate": "/users/{user-id}" + }, + { + "method": "DELETE", + "uriTemplate": "/users/{user-id}" + } + ] + }, + "pythonGraphServiceClient": { + "x-ms-apiDescriptionHash": "9EDF8506CB74FE44...", + "apiDescriptionUrl": "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml", + "apiDeploymentBaseUrl": "https://graph.microsoft.com", + "apiDescriptionVersion": "v1.0", + "requests": [ + { + "method": "GET", + "uriTemplate": "/users" + }, + { + "method": "POST", + "uriTemplate": "/users" + }, + { + "method": "GET", + "uriTemplate": "/users/$count" + }, + { + "method": "GET", + "uriTemplate": "/users/{user-id}" + }, + { + "method": "PATCH", + "uriTemplate": "/users/{user-id}" + }, + { + "method": "DELETE", + "uriTemplate": "/users/{user-id}" + } + ] + } + } +} +``` + +_The resulting file structure will look like this:_ + +```bash +/ + └─.kiota + └─definitions + └─csharpGraphServiceClient.yaml + └─pythonGraphServiceClient.yaml + └─generated + └─graph + └─csharp + └─... # Generated code files + └─GraphClient.cs + └─python + └─... # Generated code files + └─graph_client.py + └─apimanifest.json + └─kiota-config.json +``` + +## Using `kiota config migrate` for a specific `kiota-lock.json` file and a specific client name + +Assuming the following folder structure: +```bash +/ + └─generated + └─graph + └─csharp + └─... # Generated code files + └─GraphClient.cs + └─kiota-lock.json + └─python + └─... # Generated code files + └─graph_client.py + └─kiota-lock.json +``` + +```bash +kiota config migrate --lock-location ./generated/graph/csharp/kiota-lock.json --client-name graphDelegated +``` + +_The resulting `kiota-config.json` file will look like this:_ + +```jsonc +{ + "version": "1.0.0", + "clients": { + "graphDelegated": { + "descriptionLocation": "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml", + "includePatterns": ["**/users/**"], + "excludePatterns": [], + "language": "csharp", + "outputPath": "./generated/graph/csharp", + "clientClassName": "GraphServiceClient", + "clientNamespaceName": "Contoso.GraphApp", + "features": { + "structuredMediaTypes": [ + "application/json" + ], + "usesBackingStore": true, + "includeAdditionalData": true + } + } + } +} +``` + + +```bash +/ + └─.kiota + └─definitions + └─graphDelegated.yaml + └─generated + └─graph + └─csharp + └─... # Generated code files + └─GraphClient.cs + └─python + └─... # Generated code files + └─graph_client.py + └─kiota-lock.json + └─apimanifest.json + └─kiota-config.json +``` \ No newline at end of file diff --git a/specs/cli/info.md b/specs/cli/info.md new file mode 100644 index 0000000000..3db070dcb6 --- /dev/null +++ b/specs/cli/info.md @@ -0,0 +1,175 @@ +# `kiota info` + +## Description + +`kiota info` provides information about the available languages in Kiota and the dependencies that are used by the core libraries. This command is useful to get a sense of the maturity of languages in Kiota and to get language-specific information about their dependencies. + +## Parameters + +| Parameters | Required | Example | Description | +| -- | -- | -- | -- | +| `--language \| -l` | No | csharp | The language to get information about. | +| `--json` | No | | When specified, the output will be in JSON format. | +| `--ignore-dependencies` | No | | When specified, ignore the dependencies indicated in the `x-ms-kiota-info` extension (if any). | + + +## Using `kiota info` + +```bash +kiota info +``` + +```bash +Language Maturity Level +CLI Preview +CSharp Stable +Go Stable +Java Preview +PHP Stable +Python Stable +Ruby Experimental +Swift Experimental +TypeScript Experimental + +Hint: use the language argument to get the list of dependencies you need to add to your project. +Example: kiota info -l +``` + +## Using `kiota info -l ` + +```bash +kiota info -l csharp +``` + +```bash +The language CSharp is currently in Stable maturity level. +After generating code for this language, you need to install the following packages: +dotnet add package Microsoft.Kiota.Abstractions --version 1.6.1 +dotnet add package Microsoft.Kiota.Http.HttpClientLibrary --version 1.3.0 +dotnet add package Microsoft.Kiota.Serialization.Form --version 1.1.0 +dotnet add package Microsoft.Kiota.Serialization.Json --version 1.1.1 +dotnet add package Microsoft.Kiota.Authentication.Azure --version 1.1.0 +dotnet add package Microsoft.Kiota.Serialization.Text --version 1.1.0 +dotnet add package Microsoft.Kiota.Serialization.Multipart --version 1.1.0 +``` + +## Using `kiota info -l --json` + +```bash +kiota info -l csharp --json +``` + +```json +{ + "maturityLevel": "Stable", + "dependencyInstallCommand": "dotnet add package {0} --version {1}", + "dependencies": [ + { + "name": "Microsoft.Kiota.Abstractions", + "version": "1.6.1" + }, + { + "name": "Microsoft.Kiota.Http.HttpClientLibrary", + "version": "1.2.0" + }, + { + "name": "Microsoft.Kiota.Serialization.Form", + "version": "1.1.0" + }, + { + "name": "Microsoft.Kiota.Serialization.Json", + "version": "1.1.1" + }, + { + "name": "Microsoft.Kiota.Authentication.Azure", + "version": "1.1.0" + }, + { + "name": "Microsoft.Kiota.Serialization.Text", + "version": "1.1.0" + }, + { + "name": "Microsoft.Kiota.Serialization.Multipart", + "version": "1.1.0" + } + ], + "clientClassName": "", + "clientNamespaceName": "" +} +``` + +## Using `kiota info -l --openapi ` + +```bash +kiota info -l csharp --openapi https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml +``` + +_Assuming these extensions would be available in the OpenAPI description:_ + +```yaml +openapi: 3.0.3 +info: + title: OData Service for namespace microsoft.graph + description: This OData service is located at https://graph.microsoft.com/v1.0 + version: 1.0.1 +x-ms-kiota-info: + languagesInformation: + CSharp: + clientClassName: graphClient + clientNamespaceName: Microsoft.Graph + dependencyInstallCommand: dotnet add package {name} --version {version} + dependencies: + - name: Microsoft.Graph.Core + version: 3.0.0 + structuredMimeTypes: + - application/json +servers: + - url: https://graph.microsoft.com/v1.0 +``` + +```bash +The language CSharp is currently in Stable maturity level. +After generating code for this language, you need to install the following packages: +dotnet add package Microsoft.Graph.Core --version 3.0.0 +``` + +## Using `kiota info -l --openapi --ignore-dependencies` + +```bash +kiota info -l csharp --openapi https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml --ignore-dependencies +``` + +_Assuming these extensions would be available in the OpenAPI description:_ + +```yaml +openapi: 3.0.3 +info: + title: OData Service for namespace microsoft.graph + description: This OData service is located at https://graph.microsoft.com/v1.0 + version: 1.0.1 +x-ms-kiota-info: + languagesInformation: + CSharp: + clientClassName: graphClient + clientNamespaceName: Microsoft.Graph + dependencyInstallCommand: dotnet add package {name} --version {version} + dependencies: + - name: Microsoft.Graph.Core + version: 3.0.0 + structuredMimeTypes: + - application/json +servers: + - url: https://graph.microsoft.com/v1.0 +``` + +```bash +The language CSharp is currently in Stable maturity level. +After generating code for this language, you need to install the following packages: +dotnet add package Microsoft.Kiota.Abstractions --version 1.6.1 +dotnet add package Microsoft.Kiota.Http.HttpClientLibrary --version 1.3.0 +dotnet add package Microsoft.Kiota.Serialization.Form --version 1.1.0 +dotnet add package Microsoft.Kiota.Serialization.Json --version 1.1.1 +dotnet add package Microsoft.Kiota.Authentication.Azure --version 1.1.0 +dotnet add package Microsoft.Kiota.Serialization.Text --version 1.1.0 +dotnet add package Microsoft.Kiota.Serialization.Multipart --version 1.1.0 +``` \ No newline at end of file diff --git a/specs/index.md b/specs/index.md new file mode 100644 index 0000000000..e040b18428 --- /dev/null +++ b/specs/index.md @@ -0,0 +1,23 @@ +# Kiota Specification Repository + +This repository contains the specifications for the Kiota project. The goal of this repository is to provide a place to discuss and document the Kiota project. It will evolve over time as the project evolves. +config.md) + +## CLI + +* [kiota client add](./cli/client-add.md) +* [kiota client edit](./cli/client-edit.md) +* [kiota client remove](./cli/client-remove.md) +* [kiota client generate](./cli/client-generate.md) +* [kiota config init](./cli/config-init.md) +* [kiota config migrate](./cli/config-migrate.md) + +## Extension + +## Scenarios + +* [Kiota Config](./scenarios/kiota.config.md) + +## Schemas + +* [kiota-config.json](./schemas/kiota-config.json) \ No newline at end of file diff --git a/specs/scenarios/kiota-config.md b/specs/scenarios/kiota-config.md new file mode 100644 index 0000000000..8c713ba392 --- /dev/null +++ b/specs/scenarios/kiota-config.md @@ -0,0 +1,101 @@ +# Kiota Config + +Kiota generates client code for an API and stores parameters in a kiota-lock.json file. A project can contain multiple API clients, but they are independently managed. Kiota has no awareness that an app has a dependency on multiple APIs, even though that is a core use case. + +## Current Challenges + +- Client code generation is not reproducible if API description changes +- Kiota doesn't have an obvious solution for APIs that use multiple security schemes. +- Kiota doesn't have an obvious solution for projects utilizing multiple APIs. + +We have previously described Kiota's approach to managing API dependencies as consistent with the way people manage packages in a project. However, currently our tooling doesn't behave that way. We treat each dependency independently. + +## Proposal + +We should introduce a new Kiota.config file that holds the input parameters required to generate the API Client code. Currently kiota-lock.json is used to capture what the parameters were at the time of generation and can be used to regenerate based on the parameters in the file. This creates a mixture of purposes for the file. + +We did consider creating one kiota-config.json file as as a peer of the language project file, however, for someone who wants to generate multiple clients for an API in different languages, this would be a bit annoying. An alternative would be to allow the kiota-config.json file to move further up the folder structure and support generation in multiple languages from a single file. This is more consistent with what [TypeSpec](https://aka.ms/typespec) are doing and would be helpful for generating CLI and docs as well as a library. + +Here is an example of what the kiota-config.json file could look like. + +```jsonc +{ + "version": "1.0.0", + "clients": { + "graphDelegated": { + "descriptionLocation": "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml", + "includePatterns": ["**/users/**"], + "excludePatterns": [], + "language": "csharp", + "outputPath": "./generated/graph", + "clientClassName": "GraphClient", + "clientNamespaceName": "Contoso.GraphApp", + "features": { + "structuredMediaTypes": [ + "application/json" + ], + "usesBackingStore": true, + "includeAdditionalData": true + } + }, + "businessCentral": { + "descriptionLocation": "https://.../bcoas1.0.yaml", + "includePatterns": ["/companies#GET"], + "excludePatterns": [], + "language": "csharp", + "outputPath": "./generated/businessCentral" + } + } +} +``` + +Note that in this example we added suggestions for new parameters related to authentication. If we are to improve the generation experience so that we read the security schemes information from the OpenAPI, then we will need to have some place to configure what providers we will use for those schemes. + +The [API Manifest](https://www.ietf.org/archive/id/draft-miller-api-manifest-01.html) file can be used as a replacement for the kiota-lock.json file as a place to capture a snapshot of what information was used to perform code generation and what APIs that gives the application access to. + +## Commands + +* [kiota config init](../cli/init.md) +* [kiota client add](../cli/client-add.md) +* [kiota client edit](../cli/client-edit.md) +* [kiota client generate](../cli/client-generate.md) +* [kiota client remove](../cli/client-remove.md) + +## End-to-end experience + +### Migrate a project that uses Kiota v1.x + +```bash +kiota config migrate +``` + +### Get started to generate an API client + +```bash +kiota client init +kiota client add --client-name "graphDelegated" --openapi "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml" --language csharp --output "./csharpClient" +``` + +### Add a second API client + +```bash +kiota client add --clientName "graphPython" --openapi "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/openapi.yaml" --language python --outputPath ./pythonClient +``` + +### Edit an API client + +```bash +kiota client edit --client-name "graphDelegated" --class-name "GraphServiceClient" --exclude-path "/users/$count" +``` + +### Remove a language and delete the generated code + +```bash +kiota client delete --client=name "graphPython" --clean-output +``` + +### Generate code for all API clients + +```bash +kiota client generate +``` \ No newline at end of file diff --git a/specs/scenarios/self-serve.md b/specs/scenarios/self-serve.md new file mode 100644 index 0000000000..384770f66a --- /dev/null +++ b/specs/scenarios/self-serve.md @@ -0,0 +1,159 @@ +# Kiota Self-Serve + +Kiota enables developers to self-serve their own API client from an OpenAPI description. This is a proposal for how we can improve the experience to make it easier to use Kiota with specialized APIs that might have core dependencies that would provide a better experience for the developer. + +_This proposal is heavily influenced by scenarios that we have seen in the Microsoft Graph ecosystem. We are looking for feedback on whether this is a good approach for other APIs as well._ + +## Current Challenges + +One of the goals for Microsoft Graph is to shift from providing pre-packaged SDKs to invite developers to self-serve their own API client from the Microsoft Graph OpenAPI description. This brings a number of benefits to the developer: + +- The developer can choose the language that they want to use. +- The developer can choose the features and operations that they want to use, resulting in the smallest possible client. + +This is already possible today and provide "some" value to the developer. However, there are some challenges that we have seen in the ecosystem that we would like to address. + +- The developer loses core capabilities that are provided by our core libraries. For example, the developer would need to implement their own PageIterator to iterate over a collection of paged items, implement their own large file upload logic, their own batch management, etc. +- The developer loses the ability to use the same authentication provider that is used by the core libraries. For example, the developer would need to implement their own authentication provider to account for allowed hosts to be called. +- API producers might lose some telemetry if they use a custom mideleware to capture telemetry via the calls to the API. + +Without these key capabiltiies, Graph developers wouldn't be able to effectively use our self-serve approach. We have seen some developers try to use the self-serve approach and then give up and use the pre-packaged SDKs because they are easier to use. + +## Proposal + +This proposal will focus on how Kiota can be improved to support the scenarios described above. We will focus on the Microsoft Graph scenario, but we believe that this approach could be used for other APIs as well. Another internal document for this proposal will focus on how we can improve the Microsoft Graph ecosystem to support this approach. + +### Making dependencies discoverable + +The first step is to make the dependencies that are used by the core libraries discoverable. We can do this by adding a new parameter to the OpenAPI description that describes the dependencies that are used by the API. We already have [documented](https://github.com/microsoft/OpenAPI/blob/main/extensions/x-ms-kiota-info.md) how to represent language information on the `x-ms-kiota-info` OpenAPI extension and this scenario would leverage it. Here is an example of what this could look like: + +```yaml +openapi: 3.0.3 +info: + title: OData Service for namespace microsoft.graph + description: This OData service is located at https://graph.microsoft.com/v1.0 + version: 1.0.1 +x-ms-kiota-info: + languagesInformation: + CSharp: + clientClassName: graphClient + clientNamespaceName: Microsoft.Graph + dependencyInstallCommand: dotnet add package {name} --version {version} + dependencies: + - name: Microsoft.Graph.Core + version: 3.0.0 + structuredMimeTypes: + - application/json +servers: + - url: https://graph.microsoft.com/v1.0 +``` + +This would allow us to capture the dependencies that are used by the API and the information that is needed to install them. This would also allow to specify the versions of the dependencies that are used by the API producer. For instance, they could roll out their own authentication libraries, their own serialization libraries, etc. and specify the version that they want to use. This would make it easier for the developers to use the right set of functionality without relying on the API producer documentation. + +The metadata related to the `languageInformation` would be used by Kiota to generate the client code. It would be treated as default values but the developers could still override them with their preferred `clientClassName` and `clientNamespaceName`. The metadata related to the `dependencies` would be used by the developer to install the dependencies that are needed by the API. These would not be automatically installed by Kiota. When using `kiota info -l CSharp`, Kiota would use the `dependencies` metadata to generate the `dependencyInstallCommand` that the developer would need to run to install the dependencies. In cases where the API producer doesn't specify the `dependencies` metadata, Kiota would use the default dependencies that are used by the core libraries. It would also be possible to ignore the API Producer dependencies by using the `--ignore-dependencies` flag on the `kiota info -l ` command. + +### Defining a core pattern to easily extend the client + +The second step is to define a core pattern that would allow the developer to easily extend the client with the core capabilities that are provided by the core libraries. This would allow the developer to use the same authentication provider, the same telemetry provider, the same large file upload logic, etc. that are used by the core libraries. + +Today, using self-serve, you have to roll out a lot of the internals of the core libraries. This would be a minimal .NET app that would use Kiota to generate the client code. + +Assuming the following `kiota generate` command: + +```bash +kiota generate --openapi https://aka.ms/graph/v1.0/openapi.yaml --language CSharp --output ./generated/graph --client-name "TinyGraphClient" --namespace-name "Contoso.App" --include-path "/me#GET" +``` + +```csharp +using Azure.Identity; +using Contoso.App; +using Microsoft.Kiota.Authentication.Azure; +using Microsoft.Kiota.Http.HttpClientLibrary; + +// The auth provider will only authorize requests to +// the allowed hosts, in this case Microsoft Graph +var allowedHosts = new [] { "graph.microsoft.com" }; +var scopes = new [] { "User.Read" }; + +var options = new DeviceCodeCredentialOptions +{ + ClientId = "c723a528-361b-48a9-99dd-eb9396c00000", + DeviceCodeCallback = (code, cancellation) => + { + Console.WriteLine(code.Message); + return Task.FromResult(0); + }, +}; + +var credential = new DeviceCodeCredential(options); + +var authProvider = new AzureIdentityAuthenticationProvider(credential, allowedHosts, scopes: graphScopes); +var requestAdapter = new HttpClientRequestAdapter(authProvider); +var client = new TinyGraphClient(requestAdapter); + +var me = await client.Me.GetAsync(); +Console.WriteLine($"Hello {me.DisplayName}, your ID is {me.Id}"); +``` + +Compared to using the `Microsoft.Graph` prepackaged SDK, there is a lot of code that the developer has to write and also needs to understand the internals of Kiota to get the same functionality. This is a barrier for developers to use the self-serve approach. We want to make it easier for developers to use the self-serve approach by providing a core pattern that would allow them to easily extend the client with the core capabilities that are provided by the core libraries. + +```csharp +using Microsoft.Graph; +using Azure.Identity; +using Contoso.App; + +var scopes = new[] { "User.Read" }; +var clientId = "c723a528-361b-48a9-99dd-eb9396c00000"; + +var options = new DeviceCodeCredentialOptions +{ + ClientId = "c723a528-361b-48a9-99dd-eb9396c0ffba", + DeviceCodeCallback = (code, cancellation) => + { + Console.WriteLine(code.Message); + return Task.FromResult(0); + }, +}; + +var credential = new DeviceCodeCredential(options); +var client = new GraphServiceClient(credential, scopes); + +var me = await client.Me.GetAsync(); +Console.WriteLine($"Hello {me.DisplayName}, your ID is {me.Id}"); +``` + +The optimal experience would be to generate a client that would have all the necessary code to leverage the same capabilities the core and full libraries provide. This would allow the developer to use the same authentication provider, the same telemetry provider, the same large file upload logic, etc. that are used by the core libraries. This would also allow the API producer to capture the same telemetry that they would capture if the developer was using the pre-packaged SDKs. + +```csharp +using Azure.Identity; +using Contoso.App; + +var scopes = new [] { "User.Read" }; + +var options = new DeviceCodeCredentialOptions +{ + ClientId = "c723a528-361b-48a9-99dd-eb9396c0ffba", + DeviceCodeCallback = (code, cancellation) => + { + Console.WriteLine(code.Message); + return Task.FromResult(0); + }, +}; + +var credential = new DeviceCodeCredential(options); +var client = new TinyGraphClient(credential, scopes); + +var me = await client.Me.GetAsync(); +Console.WriteLine($"Hello {me.DisplayName}, your ID is {me.Id}"); +``` + +* Need an option to use a "core" base class for a generated client +* serializer settings and structured media types are associated to a "core" not a client. Should work with same media types with different serializers. +* We need a default core to simplify getting started for most users +* We need the structured mime type +* This will allow both serializers and backing store registry to be done with their singleton implementation +* Core would take on the ApiClientBuilder calls +* Core is not necessary for the generation. Cores shouldn't be required in the kiota.config. +* In every model file, inject a static property that has the key of the clientName. This would allow the backing store to know the instance it cares about. + +![](../assets/core-diagram.png) \ No newline at end of file diff --git a/specs/schemas/kiota-config.json b/specs/schemas/kiota-config.json new file mode 100644 index 0000000000..70389af1f6 --- /dev/null +++ b/specs/schemas/kiota-config.json @@ -0,0 +1,75 @@ +{ + "$schema": "", + "type": "object", + "properties": { + "version": { + "type": "string" + }, + "clients": { + "type": "object", + "patternProperties": { + ".*": { + "type": "object", + "properties": { + "descriptionLocation": { + "type": "string" + } + }, + "descriptionLocation": { + "type": "string" + }, + "includePatterns": { + "type": "array", + "items": { + "type": "string" + } + }, + "excludePatterns": { + "type": "array", + "items": { + "type": "string" + } + }, + "baseUrl": { + "type": "string" + }, + "language": { + "type": "string" + }, + "outputPath": { + "type": "string" + }, + "clientClassName": { + "type": "string" + }, + "clientNamespaceName": { + "type": "string" + }, + "features": { + "type": "object", + "properties": { + "structuredMediaTypes": { + "type": "array", + "items": { + "type": "string" + } + }, + "usesBackingStore": { + "type": "boolean" + }, + "includeAdditionalData": { + "type": "boolean" + } + } + } + } + }, + "disabledValidationRules": { + "type": "array", + "items": { + "type": "string" + } + } + } + } +}