Skip to content

04. Bound actions

Nick Josipovic edited this page Jul 8, 2025 · 8 revisions

Implementing the first action

In an existing extension project, code extensions can be created within the srv folder following a strict naming convention, with the service name as top level folder and service entity name as second level folder. The filename must follow the format of WHEN-dash-WHAT.js.

In our case, we need to create an empty file with the name on-promoteIncident.js in the folder srv/ProcesorService/Incidents.

The entire content of the file will be this:

module.exports = async function (req) {

    await UPDATE.entity(req.subject).with({ urgency_code: 'H' })

}

What are we doing here?

Just like in a normal CAP application, CDS-Oyster provides the typical API (with limitations) for standard CAP Events:

subject: req.subject,
data: req.data,
target: req.target,
results: req.results,
errors: req.errors,
messages: req.messages

In addition, a subset of the CDS QL is supported, as well as calling existing actions and emitting events.

This first event handler is using req.subject (which represents a valid CQN snippet to identify a single entity instance) to update precisely one entry in the Incidents table. This is a nice convenience to avoid constructing where clauses using req.data.Incidents_ID and less error prone.

Notice the general nature of CDS-Oyster event handlers:

  • Each file needs to export a single asynchronous function
  • Depending on the event, the function will be called with req or req, res (e.g. after read handlers)
  • All code needs to be synchronoues, await statements are forbidden
  • Exception are the CDS QL callbacks, which require asynchronous calls

Please us cds watch to test whether the action implementation works. By selecting one or more incidents, the promote Incident should now change the urgency to high.

Troubleshooting

If this does not work as expected, please check the following:

  • CDS-Oyster is installed in node_modules
  • Sandbox is enabled in package.json
  • Extension project runs with the data model changes visible
  • Folder names for event handlers are correct
  • File name has no typo

Playing around

You are not limited to the specific syntax of the example event handler, so the following example works as well:

async function promoteIncident(req) {
      await UPDATE.entity(req.subject).with({ urgency_code: 'H' })
}

module.exports = promoteIncident 

You could try debugging the whole thing. Please make sure, that the debug runtime is set in package.json

"code-extensibility": {
        "runtime": "debug",
        ...

so that the event handlers are not executed within WASM, but within the V8 runtime of node.js directly. If you are using VSCode, simply open an additional debug terminal, set a breakpoint within the event handler, and execute the action from the UI. You will be able to introspect the local variables and see also, what you can do with the this object. Please note, how the local environment is significantly smaller than in a normal CAP event handler. In the global environment you will also find all callbacks like the SDC QL, or the console object.

In the Fith exercise — Creating the extension, we will implement the second action

Clone this wiki locally