The purpose of this document is to collect information on the Cloud SDK version 2 to version 3 migration. It should include information on all steps a user needs to take when updating the SDK version from 2 to 3.
This document should be written in a style which addresses the consumer of the SDK. It will eventually end up in the SDK docs portal and release notes for version 3.
Please add your items below when creating a change which will involve manual tasks for the user when performing the upgrade. Add sections to the document as you see fit.
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
optionsPerService
in OData Client generator - Set
basePath
inoptions-per-service.json
- Use
operations
instead ofactionImports
andfunctionImports
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.
The axios HTTP client has been updated from version 0.27 to 1.2.
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
.
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.
- The
executeHttpRequest()
function overload, that acceptedHttpRequestConfigWithOrigin
as a parameter, is removed. UseexecuteHttpRequestWithOrigin()
instead.
- The field
logger
on the interfaceLoggerOptions
was not used and is removed from the interface. There is no replacement. - The function
variadicArgumentToArray
is replaced by the functiontransformVariadicArgumentToArray
.
-
The generic type parameter
JwtKeysT
inJwtKeyMapping
is now narrowed to extendstring
. -
The property
url
on theDestination
interface is now optional. It is only present for HTTP destinations and not for Mail destinations. -
The
IsolationStrategy
enum 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' })
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:
forceOverwrite
becomesoverwrite
generatePackageJson
becomespackageJson
writeReadme
becomesreadme
processesJsGeneration
becomestranspilationProcesses
inputDir
becomesinput
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.
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.
- When creating entities with the
fromJson()
method, the_customFields
property 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
ODataRequestConfig
anymore. 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' }
.
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.
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
.
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.
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
.
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.
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.json
insomeDir
)
Also, the properties in the configuration have changed:
- The option
serviceName
is removed. A value for the documentation header is derived from the directory name. - The
npmPackageName
is renamed topackageName
to align with the OpenApi generator. Note that the default values for thedirectoryName
andpackageName
have 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.json
file. - 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.
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:
basePath
property in theoptions-per-service.json
.edmx
service 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 /
.
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 /
.