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.
Check this guide for downloading a specification from SAP Business Accelerator Hub.
Installation
Run the command below to install the OpenAPI generator as a devDependency
:
npm install -D @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:
npx 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
). - 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.
The generator should be installed as a local dependency, because global installations hide the used generator version and cause problems when transpiling to JavaScript.
If you must use a globally installed generator, install the @types/node
and @sap-cloud-sdk/openapi
package in your project to make the transpilation work.
If you need to transpile sources without any local node_modules
, you must manually execute the tsc
compiler on your own with a custom path mapping.
See transpile for more details in the options below.
Options
Run openapi-generator --help
for additional options.
Option | Default | 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 . |
--optionsPerService | - | Set 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, an options-per-service.json file is read/created in this directory. |
--overwrite | false | Allow overwriting files, that already exist. This is useful, when running the generation regularly. |
--clearOutputDir | false | Remove all files in the output directory before generation. Be cautious when using this option, as it really removes EVERYTHING in the output directory. |
--packageJson | false | When enabled, a package.json , that specifies dependencies and scripts for transpilation and documentation generation is generated. |
--include | '' | Include files matching the given glob into the root of each generated client directory. |
-t , --transpile , | false | Transpile the generated TypeScript code. When enabled a default tsconfig.json will be generated and used. It emits .js , .js.map and .d.ts files. To configure transpilation set --tsconfig . |
--tsconfig | default tsconfig | Replace 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. |
-p , --prettierConfig | default prettier config | Configuration file for prettier if you want to change the default value. |
--verbose | false | Turn on verbose logging. |
--skipValidation | false | By 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. |
-c , --config | - | Set 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. |
--generateESM | false | Generate ESM compatible code. |
Generate a 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 = {
input: '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", you can use 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'
withPOST
would result increateResource
'resource/{id}'
withGET
would result ingetResourceById
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 there are duplicate names, but one of the names is in camel case, this name remains as is. Example:
Original operationId s | Generated function names |
---|---|
my-function | myFunction2 |
myFunction | myFunction |
other_function | otherFunction |