How to Upgrade to Version 3 of the SAP Cloud SDK for JavaScript
Overview
This document will guide you through the steps necessary to upgrade to version 3 of the SAP Cloud SDK. Depending on your project, some steps might not be applicable. The To-Do list is:
- Update Your Project Dependencies
- Update to Node 18 or Newer
- Replace Removed Functionality
- Switch to Middlewares for Timeouts
- Update Transpilation Options in OData Client Generator
- Use Service Function instead of API Constructor
- Adjust Operation Names Starting With
_in Generated OData Clients - Adjust Conflict Resolution in OData Client Generation
- Use
optionsPerServicein OData Client generator - Set
basePathinoptions-per-service.json - Use
operationsinstead ofactionImportsandfunctionImports
Update Your Project Dependencies
Search for occurrences of @sap-cloud-sdk/[some module] in your package.json files.
Replace the version numbers with ^3.
Depending on if you're using npm or yarn, run npm install or yarn in the directories of your package.json files to update the package-lock.json or yarn.lock file.
Running your tests or deploying your application might fail at this point in time if you need to adapt to any breaking changes. We recommend updating your applications in one commit or pull request and making sure everything still works using your existing test suite.
Important Dependency Updates
The axios HTTP client has been updated from version 0.27 to 1.2.
Update to Node 18 or Newer
All SAP Cloud SDK for JavaScript libraries now support node 18 (LTS) as the minimum node version.
If you are using a node version older than 18, update your runtime environment to a newer version.
On Cloud Foundry you can do this by setting the node engine in your package.json.
Note, that the transpilation target of the SDK changed from es2019 to es2021.
Replace Removed Functionality
Most of the removed functionality had been deprecated in version 2. The following sub-sections describe affected modules, functions and interfaces with instructions on how to replace them.
Package @sap-cloud-sdk/http-client
- The
executeHttpRequest()function overload, that acceptedHttpRequestConfigWithOriginas a parameter, is removed. UseexecuteHttpRequestWithOrigin()instead.
Package @sap-cloud-sdk/util
- The field
loggeron the interfaceLoggerOptionswas not used and is removed from the interface. There is no replacement. - The function
variadicArgumentToArrayis replaced by the functiontransformVariadicArgumentToArray.
Package @sap-cloud-sdk/connectivity
-
The generic type parameter
JwtKeysTinJwtKeyMappingis now narrowed to extendstring. -
The property
urlon theDestinationinterface is now optional. It is only present for HTTP destinations and not for Mail destinations. -
The
IsolationStrategyenum is replaced by a union type of the same name.Make changes to your tenant isolation strategy like in this example:
.execute({
destinationName: 'DESTINATION',
useCache: true,
isolationStrategy: IsolationStrategy.Tenant
})to
.execute({
destinationName: 'DESTINATION',
useCache: true,
isolationStrategy: 'tenant'
})
Package @sap-cloud-sdk/generator
The deprecated option generateCSN is removed.
If you need a schema notation (CSN) of your service use the cds import command directly.
The options versionInPackageJson and licenseInPackageJson, that allowed setting custom values in generated package.json files are removed.
When the packageJson option is enabled, a package.json file with version 1.0.0 and license UNLICENSED is created.
Use the include option to add a package.json with custom values.
The following deprecated options were renamed:
forceOverwritebecomesoverwritegeneratePackageJsonbecomespackageJsonwriteReadmebecomesreadmeprocessesJsGenerationbecomestranspilationProcessesinputDirbecomesinput
The new input option now also accepts file paths and glob patterns.
The deprecated generateNpmrc option of the generator is removed.
Use the include option to add a .npmrc to the generated code if needed.
The internal options sdkAfterVersionScript, s4HanaCloud and packageVersion of the generator are removed.
These were hidden options never meant for external usage and there is no replacement.
The types for paths in the GeneratorOptions are changed from fs.PathLike to string.
In case you passed a buffer object please resolve it to a string before passing it to the SAP Cloud SDK.
Package @sap-cloud-sdk/openapi-generator
The deprecated generator options versionInPackageJson, packageVersion and licenseInPackageJson are removed.
When the packageJson option is enabled, a package.json file with version 1.0.0 and license UNLICENSED is created.
Use the include option to add a package.json with custom values.
The OpenAPI generator now uses the same code as the OData generator to resolve paths.
In case you experience problems with the new implementation enable the verbose flag to investigate what the paths resolve to now.
Package @sap-cloud-sdk/odata-common
- When creating entities with the
fromJson()method, the_customFieldsproperty is no longer considered. Add custom properties as root level properties in your object instead.
Old example, not working anymore:
{
"_customFields": {
"myCustomField": "myCustomValue"
}
}
New example:
{
"myCustomField": "myCustomValue"
}
- "Content-type" HTTP headers cannot be passed as a string in the constructor of the
ODataRequestConfiganymore. Instead, pass an object to the constructor with "content-type" as a key and the header value as a value, e.g.{ 'content-type': 'some-value' }.
Switch to Middlewares for Timeouts
The timeout() method was removed from the request builder and the timeout option was removed from the executeHttpRequest() function.
If you want to set a timeout for a request, use the new timeout middleware:
import { timeout } from '@sap-cloud-sdk/resilience';
executeHttpRequest(myDestination, {
method: 'get',
middleware: [timeout()]
});
myRequestBuilder.getAll().middleware([timeout()]).execute(myDestination);
You find a detailed guide on the general middleware concept and the resilience middlewares in particular on the documentation portal.
Update Transpilation Options in OData Client Generator
By default, the OData generator will only generate TypeScript code.
The generateJs option has been replaced with the transpile option.
To generate JavaScript code, enable transpilation by using the transpile option.
A new option, tsconfig, can be used to either pass a custom tsconfig.json configuration file or use a default config from the SDK.
This flag should be used together with transpile.
Use Service Function instead of API Constructor
You should use the service function to get an instance of your API object:
import { myEntityService } from './outputDir/my-service';
const { myEntityApi } = myEntityService();
return myEntityApi.requestBuilder().getAll().execute(destination);
This way, a getter initializes references to navigation properties of the API. If you call the API constructor directly like the following:
const myEntityApi = new MyEntityApi();
the navigation properties are not correctly initialized, leading to potential errors.
The visibility of the constructor is now changed to private to avoid its unintended usage.
If you used the constructor directly change your code to use the service function e.g. myEntityService() in the example above.
Adjust Operation Names Starting With _ in Generated OData Clients
Rules for naming OData operations (actions or functions) when generating clients have changed slightly.
If an operation begins with an underscore symbol(_), it is removed in the generated client's code.
To adjust the names for unbound operations, search in function-import.ts and action-import.ts files in your generated client's code for operations starting with an _.
Similarly, to adjust the names of bound operations of an entity, search in the respective entity's .ts file, e.g., BusinessPartner.ts.
Adjust Conflict Resolution in OData Client Generation
In the past, object names changed to resolve conflicts with protected JavaScript keywords or non-unique names.
This has changed and the generation process will now fail with an error message indicating the changed name.
You can still generate in such a case by enabling the skipValidation option.
The generator will add postfixes like _1 to resolve the conflict if the option is enabled.
Use optionsPerService in OData Client Generator
The serviceMapping option in the OData generator has been renamed to optionsPerService, addtionally its alias -s has been removed.
The service-mapping.json file is now named options-per-service.json.
The file will no longer be generated into the input directory by default, unlike previous versions.
If the generator should consider options, it is mandatory to set the optionsPerService argument.
You can set the value to either:
- The file path containing the options per service (e.g.
options.json). If the file does not exist, it will be created and initialized. If the file exists, missing or partial service options will be added with the default values. - The directory from which the file is read/created (e.g.
someDir. This will read/create a file namedoptions-per-service.jsoninsomeDir)
Also, the properties in the configuration have changed:
- The option
serviceNameis removed. A value for the documentation header is derived from the directory name. - The
npmPackageNameis renamed topackageNameto align with the OpenApi generator. Note that the default values for thedirectoryNameandpackageNamehave changed. - The keys change to the relative paths of the service specifications.
Here is an example how the options change:
//Old Format
{
"API-TEST_SRV": {
"directoryName": "test-service",
"basePath": "/odata/test-service",
"npmPackageName": "npm-package-test-service",
"serviceName": "some-text-used-in-documentation-service"
}
}
//New Format
{
"../test-resources/odata-spec/API-TEST_SRV.edmx": {
"packageName": "npm-package-test-service",
"directoryName": "test-service",
"basePath": "/odata/test-service"
}
}
In case you have problems finding the relative path or adjusting the property names please do the following:
- Remove the exising
options-per-service.jsonfile. - Re-run the generator. This will generate a fresh file with the new relative paths and new property names with default values.
- Adjust the default values for packageName, directoryName and basePath with values fitting your needs.
Set basePath in options-per-service.json
By default, generation of OData clients will fail if the basePath cannot be determined at the time of generation.
The generator will determine the path from the:
basePathproperty in theoptions-per-service.json.edmxservice specification, or- swagger file
in the above mentioned order.
To allow generation in spite of missing basePath, set the skipValidation option to true.
This will generate the client successfully with basePath set to /.
Use operations instead of actionImports and functionImports
Unbound actions and functions, were previously represented as separate service properties, actionImports and functionImports, of generated clients.
They are now represented by one common property, operations.
Instead of:
import { myService } from './generated/my-service';
// Operations are split into functions and actions
const { functionImports, actionImports } = myService();
const { myFunction } = functionImports;
const { myAction } = actionImports;
Use
import { myService } from './generated/my-service';
// Operations are merged in one property
const { operations } = myService();
const { myFunction, myAction } = operations;
To allow generation in spite of a missing basePath, set the skipValidation option to true.
This will generate the client successfuly with the basePath set to /.