September Release
Welcome to the September 2024 release of CAP. Find the most noteworthy news and changes in the following sections.Analytics for cap≽ire
With this release, we start using Matomo to collect anonymized usage data for cap≽ire. This helps us understand, for example, key topics and prioritize areas for improvement. If you want to change your decision, visit our Cookie Statement page.
Node.js
Top Level Imports of Typed Models beta
You can now import type definitions generated by cds-typer on top-level, even in test code:
import { Books } from '#cds-models/sap/capire/bookshop' // static import
describe("My Tests", () => {
cds.test(...)
test ("first test", () => {
const { Books } = await import('#cds-models/sap/capire/bookshop')
await SELECT.from(Books)
})
})
Use option cds.typer.use_entities_proxy:true
in package.json
to opt-in to this behavior. Version 0.26.0 of cds-typer
is required at the minimum.
We would like to thank user stockbal for this contribution to cds-typer
.
Richer JS/TS Snippets
In cap≽ire, JavaScript and Typescript documentation snippets can now carry type information, allowing you to get better insights in the APIs used there.
The example from cds-typer highlights the generated model-specific types in a popover and a code completion box:
import { Books } from '#cds-models/sap/capire/bookshop'
service.before('CREATE', Books, ({ data }) => {
/* data is of type Books */
data.t
})
In this example from cds-server, hover over express
or app
objects to explore express
APIs:
const cds = require('@sap/cds')
const express = require('express')
cds.on('bootstrap', app => {
// serve static resources incl. index.html
app.use(express.static(__dirname+'/srv/public'))
})
Let us know which snippets you think would benefit from type information.
Instance-based Restrictions for Bound Actions and Functions
Instance-based restrictions for bound actions and functions are now enforced.
@restrict : [
{grant: 'approve', to: 'Employee', where: ($user.role = 'manager') },
{grant: 'revoke', to: 'Employee', where: (createdBy = $user) },
]
entity Travel {
key ID: UUID;
createdBy: String;
} actions {
action approve();
action revoke();
}
In this example, revoke
can only be called by the employee who created it and approve
when the user attribute 'role' equals 'manager'. If the action or function is bound against the collection and includes any property reference, like createdBy = $user
, it is not being enforced.
Learn more about Authorization
SAP Cloud Application Event Hub for Stand-alone Apps beta
SAP Cloud Application Event Hub is the new default offering for messaging in SAP Business Technology Platform (SAP BTP). Integration with SAP Cloud Application Event Hub is provided via CDS plugin @cap-js/event-broker
. See Using SAP Cloud Application Event Hub in Cloud Foundry for how to consume events emitted by SAP S/4 HANA Cloud in your CAP application.
Java
Enhancements to Code Generator
Stricter Setters in Accessor Interfaces
The generate goal of the CDS Maven Plugin got a new parameter strictSetters
, which controls wether to generate strict type-safe setter methods for associations in the accessor interfaces. Strict type-safe setters accept only collections of accessor interfaces corresponding to the target type of the association.
Let's have a look at the following model:
entity Books : cuid {
title : String;
author : Association to Authors;
}
entity Authors : cuid {
name : String;
books : Association to many Books on books.author = $self;
}
The following table shows generated accessors, based on the strictSetters
parameter.
mode | false | true |
---|---|---|
to one | setAuthor(Map<String, ?> a) | setAuthor(Author a) |
to many | setBooks(List<? extends Map<String, ?>> bs) | setBooks(List<Books> bs) |
New Factory Method
Accessor interfaces now offer the new factory method of(Map<String, Object> map)
to access the data in a given map. The method statement Books.of(map)
is a shortcut for Struct.access(map).as(Books.class)
.
var map = Map.of("title", "CAP Rules", "year", 2024);
Books book = Books.of(map);
book.getTitle(); // CAP Rules
book.getYear(); // 2024
Learn more about Working with Data
Monitor Health Status of MTX Sidecar
A new health indicator modelProvider
includes the health status of the MTX sidecar, which serves the Model Provider Service, into the application's actuator/health endpoint.
Parameters Aliases in OData v4
In OData v4, you may now use parameter aliases for key values as well as for parameters in function calls. Parameters aliases are names beginning with an at sign (@
).
Special characters
Using parameter aliases allows to use special characters like slash (/
) in values, which is not possible otherwise.
Parameter Aliases for Entity Key Values
In the URL, you may use parameter aliases in place of literal entity keys values. Examples:
GET MyService/Orders(ID=@id)?@id=ec806c06-abfe-40c0-b096-c8749aa120f0
GET MyService/Orders(ID=@order, IsActiveEntity=@active)/items(@ID=@item)?@order=ec806c06-abfe-40c0-b096-c8749aa120f0&@active=true&@item=3
Not within system query parameters
Such aliases can't be used within system query parameters like $filter
or $orderby
.
Parameter Aliases for Function Parameter Values
In function calls, you can now use parameter aliases in the inline parameter syntax as placeholders for parameter values. Examples:
GET MyService/EmployeesByManager(ManagerID=@p1)?@p1=3
GET MyService/EmployeesByManager(ManagerID=@p1)?@p1=3
This syntax is especially useful to supply values to function parameters with structured or arrayed type.
Considering the following CDS model:
service MyService {
function EmployeesByIDs(IDs : many Int32) returns Employee;
function EmployeesByName(name : { first : String; last : String; })
returns Employee;
}
These are parameter aliases you can use:
GET MyService/EmployeesByIDs(IDS=@ids)?@ids=[1, 5, 8]
GET MyService/EmployeesByName(name=@name)?@name={ "first" : "Sam", "last" : "Smith" }
Add Handler Stubs
With the new cds add handler
CLI command, it is now possible to generate handler stubs for actions and functions in Java projects. The feature helps you get your project up and running even quicker.
cds add handler
The feature is currently available for Java projects only.
Learn more about handler generation.
Miscellaneous
- A new CDS property
cds.odata-v4.fiori-preview.ui5.version
allows to configure the UI5 version used by the Fiori Preview.
Tools
Visualize Deployment Descriptor beta
The CDS Preview as diagram command in VS Code can visualize an mta.yaml:
This feature requires the Markdown Preview Mermaid Support extension
This helps you get a graphical overview of your microservices architecture and the interplay between applications and services.
The sample rendered here was created using the following command:
cds init bookshop --add hana,xsuaa,portal,multitenancy,mta
This also works as a visual linter...
Missing required resources or unused provided ones are highlighted in red.
This is a malformed mta.yaml and its output:
ID: bookshop
modules:
- name: bookshop-srv
type: nodejs
path: gen/srv
requires:
- name: my-service
provides:
- name: srv-api
properties:
srv-url: ${default-url}
- name: unused-api # not used
resources:
- name: my-service
type: org.cloudfoundry.managed-service
requires:
- name: srv-api
- name: incorrect-srv-api # not defined
New Checks in CDS Lint
There are two new experimental CDS Lint checks:
@sap/cds/sql-null-comparison
checks your model for comparisons against SQL'sNULL
value and proposes to useIS NULL
andIS NOT NULL
instead.@sap/cds/no-java-keywords
helps you identify CDS identifiers that may clash with CAP Java's code generation, such as Java keywords.
Enable these rules by adding them to your eslint.config.js
or .eslintrc.json
.
Furthermore, authentication checks for @restrict
have been reworked and improved and should no longer report false positives.
Last but not least, we have fixed bugs that prevented the CDS ESLint plugin from reporting issues in your model, meaning running eslint
on your command line will now work as expected.