Skip to main content
Rate this page

Use the OpenAPI Generator to Generate Typed Clients

REST is a common pattern to define APIs of services. Many SAP systems like SAP S/4HANA, SAP Concur and SAP Business Technology Platform provide their services through REST APIs. A common way to specify these services are OpenAPI specifications. With the SAP Cloud SDK, you can generate typed clients for those specifications.

Installation

Run the command below to install the OpenAPI generator globally:

npm install -g @sap-cloud-sdk/openapi-generator

Generate a Client Using the Command Line Interface

The SAP Cloud SDK generator is primarily intended to be used on the command line. You can generate an OpenAPI client by running:

openapi-generator --input <input> --outputDir <outputDirectory>

The <input> points to your specification file or a directory containing the specification(s) and <outputDirectory> to the target folder where the generated client(s) will be saved.

By default, the generated clients will each contain:

  • API files as .ts files - one for each "API" in the service. See details.
  • A schema directory, containing schema files (.ts), one for each schema defined in the service specification.
  • All of the above as transpiled sources, including JavaScript sources (.js), type definition files (.d.ts) and sourcemap files (.js.map and .d.ts.map).
  • A package.json.
  • A tsconfig.json.

The generation always includes the TypeScript sources. All other files can be excluded from the generation - see the options below.

Options of the OpenAPI CLI

Run openapi-generator --help for additional options.

Options
Description
-i,--input (required)Specify the path to the directory or file containing the OpenAPI service definition(s) to generate clients for. Accepts Swagger and OpenAPI definitions as YAML and JSON files. Throws an error if the path does not exist.
-o,--outputDir (required)Specify the path to the directory to generate the client(s) in. Each client is generated into a subdirectory within the given output directory. Creates the directory if it does not exist. Customize subdirectory naming through --optionsPerService.
-t, --transpile,Transpile the generated TypeScript code. When enabled a default tsconfig.json will be generated and used. It emits .js, .js.map, .d.ts and .d.ts.map files. To configure transpilation set --tsconfig.
--clearOutputDirRemove all files in the output directory before generation. Be cautious when using this option, as it really removes EVERYTHING in the output directory.
--includeInclude files matching the given glob into the root of each generated client directory.
--optionsPerServiceSet the path to a file containing the options per service. The configuration allows to set a directoryName and packageName for every service, identified by the path to the original file. It also makes sure that names do not change between generator runs. If a directory is passed, a options-per-service.json file is read/created in this directory.
--overwriteAllow overwriting files, that already exist. This is useful, when running the generation regularly.
--packageJsonWhen enabled, a package.json, that specifies dependencies and scripts for transpilation and documentation generation is generated.
--skipValidationBy default, the generation fails, when there are duplicate or invalid names for operations and/or path parameters after transforming them to camel case. Set this to true to enable unique and valid name generation. The names will then be generated by appending numbers and prepending prefixes.
--tsConfigReplace the default tsconfig.json by passing a path to a custom configuration. By default, a tsconfig.json is only generated, when transpilation is enabled (--transpile). If a directory is passed, a tsconfig.json file is read from this directory.
--verboseTurn on verbose logging.
-c, --configSet the path to the file containing the options for generation. If other flags are used, they overwrite the options set in the configuration file. If a directory is passed, a config.json file is read from this directory.

Configuration File Schema

{
input: string;
outputDir: string;
transpile?: boolean;
include?: string;
clearOutputDir?: boolean;
skipValidation?: boolean;
tsConfig?: string;
packageJson?: boolean;
optionsPerService?: string;
packageVersion?: string;
readme?: boolean;
metadata?: boolean;
verbose?: boolean;
overwrite?: boolean;
}

Generate a Type-safe Client Programmatically

The generator can also be executed programmatically in JavaScript or TypeScript code. Add the @sap-cloud-sdk/openapi-generator package to your project:

npm i @sap-cloud-sdk/openapi-generator

This package exports the generate function. It takes the same options as the command-line tool and generates the same files:

import { generate } from '@sap-cloud-sdk/openapi-generator'

const generatorOptions = {
inputDir: 'directoryWithOpenApiFiles';
outputDir: 'myOutputDirectory';
}

await generate(generatorOptions);

How the API Code is Generated

By default, the generator produces one service directory for every OpenAPI specification. The directory name is based on the file name of the specification and is transformed to kebab case, e.g. my-service.

APIs

All operations of the service are grouped into APIs based on their tags. A service can consist of multiple APIs. If multiple tags are specified for an operation, only the first one is considered. If no tags are specified, "default" is used.

The API names are transformed by appending "Api" and transforming them to pascal case, e.g. 'my-tag' results in MyTagApi. In case the tag already ends with "api" (case independent), one "Api" will be removed, e.g. myapi results in MyApi. If your tags end with "api", but this is part of the word, e.g. "okapi", we recommend the OpenAPI vendor extensions and provide an explicit API name ending with "Api", e.g. "OkapiApi". Note, that operations are grouped into APIs based on their transformed names, not the original names. Therefore, tags like "my-tag" and "MyTag" are treated as the same API, "MyTagApi".

Operations

Every operation in the specification is reflected as a function of a generated API. The function names are based on the operationId property in the specification of the operation. If no operationId is given, the name is derived from the method and the path pattern, examples:

  • 'resource' with post would result in createResource
  • 'resource/{id}' with get would result in getResourceById

The function names are transformed to camel case, e.g. 'myFunction'. Duplicates within an API are handled by adding an index at the end of the name. In cases where we have duplicate names, but one of the names is in camel case, this name remains as is. Example:

Original operationIdsGenerated function names
my-functionmyFunction2
myFunctionmyFunction
other_functionotherFunction

Configure Generated Client Structure and Naming

In case you need more flexibility when generating clients, you can use the SAP Cloud SDK's vendor extensions for OpenAPI. We provide two extensions:

You can set those on different levels of the specification. They take precedence before the default behavior.

x-sap-cloud-sdk-api-name

Use this extension to configure the structure of your generated APIs. Setting x-sap-cloud-sdk-api-name as a property determines which operations are grouped into one API. Note, that the name will be transformed to pascal case with an "Api" ending, same as in the default behavior, e.g. "MyApi". When referring to the "API name", the transformed name is meant.

This extension can be set on the following levels:

  • Operations - Operations that have the same API name are grouped into one API.
  • On the path definitions - All operations below paths with the same API name are grouped into one API.
  • Root of the specification - All operations in the specification belong to the specified API. You can think of this as the custom default name for an API.

This extension can be set on all these levels in the same document. In these cases the most specific use of the extension takes precedence.

x-sap-cloud-sdk-operation-name

Use this extension to overwrite the default names for the generated functions. As of the OpenAPI specification, this is the intent of the operationId field. However, the value of this property has to be unique throughout a specification file. Many OpenAPI validators fail if there are duplicate operationIds. With the approach of the SAP Cloud SDK OpenAPI generator this restriction might make the resulting clients more complicated than necessary. Given that you have multiple APIs, it can make sense to have the same function names in different APIs, e.g. MyResource1Api.getAll() and MyResource2Api.getAll(). The purpose of the x-sap-cloud-sdk-operation-name is to allow using duplicate names across APIs, while complying with the OpenAPI specification.

Rate this page