Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions node.js/app-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,31 @@ cds.ApplicationService.handle_log_events = cds.service.impl (function(){
this.on('*', req => console.log(req.event))
})
```


## Results of Generic CRUD Handlers

Custom `.on` handlers can return any value. When no custom handler provides a result — that is, when CAP's built-in generic handler runs the CRUD operation — the result follows a consistent shape:

| Operation | Return value |
|-----------|-------------|
| **READ** | `object[]` — the matching records, or a single `object \| null` for singleton requests |
| **INSERT** / **CREATE** | An array of primary-key objects of the inserted rows, with `.affected` set to the number of rows written |
| **UPDATE** / **UPSERT** / **DELETE** | An empty array with `.affected` set to the number of rows changed or deleted |

The `.affected` count is a property directly on the returned array:

```js
const inserted = await srv.create(Books).entries({title:'Catweazle'})
inserted[0] // { ID: '...' } — primary key of the inserted row
inserted.affected // 1

const updated = await srv.update(Books).set({discount:'10%'}).where({stock:{'>':111}})
updated.affected // number of rows updated
```

When a write targets a **specific subject** (for example, `srv.update(Books, 201)` or `srv.delete(Books, '1')`) and no row is matched, the handler throws a `404` error. A query using only a `where` clause with zero matches returns `{ affected: 0 }` without throwing.

::: tip Consistent results across local and remote services
This return shape was introduced in **cds 10** to make results from local services, HCQL-proxied remote services, and database services consistent. To restore the previous behavior, set `{ "features": { "legacy_srv_results": true } }` in your project configuration.
:::
6 changes: 3 additions & 3 deletions node.js/core-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ function srv.after (event, entity?, handler: (

Use this method to register handlers to run *after* the `.on` handlers, frequently used to enrich outbound data. The handlers receive two arguments:

- `results` — the outcomes of the `.on` handler which ran before
- `results` — the outcomes of the `.on` handler which ran before; see [Results of Generic CRUD Handlers](app-services#results-of-generic-crud-handlers) for the shape returned by the built-in handler
- `req` — an instance of [`cds.Request`](./events.md#cds-request)

::: warning
Expand Down Expand Up @@ -1035,7 +1035,7 @@ async function srv.handle (
return : result of executed .on handlers
```

This is the internal method called by [`this.dispatch()`](#srv-dispatch-event) to actually process requests or events by executing registered event handlers. Argument `event` is expected to be an instance of [`cds.Event`](./events.md#cds-event) or [`cds.Request`](./events.md#cds-request).
This is the internal method called by [`this.dispatch()`](#srv-dispatch-event) to actually process requests or events by executing registered event handlers. See [Results of Generic CRUD Handlers](app-services#results-of-generic-crud-handlers) for the return value shape of the built-in handler. Argument `event` is expected to be an instance of [`cds.Event`](./events.md#cds-event) or [`cds.Request`](./events.md#cds-request).

The implementation basically works like that:

Expand Down Expand Up @@ -1156,7 +1156,7 @@ srv.update('Books',...)... --> UPDATE.entity ('Books',...)...
srv.delete('Books',...)... --> DELETE.from ('Books',...)...
```

You can further construct the queries using the `cds.ql` fluent APIs, and then `await` them for execution thru `this.run()`. Here are some examples:
You can further construct the queries using the `cds.ql` fluent APIs, and then `await` them for execution thru `this.run()`. See [Results of Generic CRUD Handlers](app-services#results-of-generic-crud-handlers) for the return value shape. Here are some examples:

```js
await srv.read(Books,201)
Expand Down
Loading