@linkup-ai/abap-ai 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +384 -0
  2. package/dist/adt-client.js +364 -0
  3. package/dist/cli/activate.js +113 -0
  4. package/dist/cli/init.js +333 -0
  5. package/dist/cli/remove.js +80 -0
  6. package/dist/cli/status.js +229 -0
  7. package/dist/cli/systems.js +68 -0
  8. package/dist/cli.js +81 -0
  9. package/dist/index.js +1318 -0
  10. package/dist/knowledge/abap/abap-dictionary.md +199 -0
  11. package/dist/knowledge/abap/abap-sql.md +296 -0
  12. package/dist/knowledge/abap/amdp.md +273 -0
  13. package/dist/knowledge/abap/clean-code.md +293 -0
  14. package/dist/knowledge/abap/cloud-background-processing.md +250 -0
  15. package/dist/knowledge/abap/cloud-communication.md +265 -0
  16. package/dist/knowledge/abap/cloud-development.md +176 -0
  17. package/dist/knowledge/abap/cloud-extensibility.md +252 -0
  18. package/dist/knowledge/abap/cloud-released-apis.md +261 -0
  19. package/dist/knowledge/abap/constructor-expressions.md +289 -0
  20. package/dist/knowledge/abap/enhancements.md +232 -0
  21. package/dist/knowledge/abap/exceptions.md +271 -0
  22. package/dist/knowledge/abap/internal-tables.md +205 -0
  23. package/dist/knowledge/abap/object-orientation.md +298 -0
  24. package/dist/knowledge/abap/performance.md +216 -0
  25. package/dist/knowledge/abap/rap-abstract-entities.md +206 -0
  26. package/dist/knowledge/abap/rap-business-events.md +216 -0
  27. package/dist/knowledge/abap/rap-draft.md +191 -0
  28. package/dist/knowledge/abap/rap-eml.md +453 -0
  29. package/dist/knowledge/abap/rap-end-to-end.md +486 -0
  30. package/dist/knowledge/abap/rap-feature-control.md +185 -0
  31. package/dist/knowledge/abap/rap-numbering.md +280 -0
  32. package/dist/knowledge/abap/rap-service-exposure.md +163 -0
  33. package/dist/knowledge/abap/rap-unmanaged.md +468 -0
  34. package/dist/knowledge/abap/string-processing.md +180 -0
  35. package/dist/knowledge/abap/unit-testing.md +303 -0
  36. package/dist/knowledge/abap-cds/access-control.md +241 -0
  37. package/dist/knowledge/abap-cds/annotations.md +331 -0
  38. package/dist/knowledge/abap-cds/associations.md +254 -0
  39. package/dist/knowledge/abap-cds/expressions.md +230 -0
  40. package/dist/knowledge/abap-cds/functions.md +245 -0
  41. package/dist/knowledge/abap-cds/metadata-extensions.md +294 -0
  42. package/dist/knowledge/cap/authentication.md +278 -0
  43. package/dist/knowledge/cap/cdl-syntax.md +247 -0
  44. package/dist/knowledge/cap/cql-queries.md +266 -0
  45. package/dist/knowledge/cap/deployment.md +343 -0
  46. package/dist/knowledge/cap/event-handlers.md +287 -0
  47. package/dist/knowledge/cap/fiori-integration.md +303 -0
  48. package/dist/knowledge/cap/service-definitions.md +287 -0
  49. package/dist/knowledge/fiori/annotations.md +347 -0
  50. package/dist/knowledge/fiori/deployment.md +340 -0
  51. package/dist/knowledge/fiori/fiori-elements.md +332 -0
  52. package/dist/knowledge/fiori/fiori-side-effects.md +107 -0
  53. package/dist/knowledge/fiori/fiori-valuelist.md +144 -0
  54. package/dist/knowledge/fiori/ui5-controllers.md +358 -0
  55. package/dist/knowledge/fiori/ui5-data-binding.md +311 -0
  56. package/dist/knowledge/fiori/ui5-fragments-dialogs.md +330 -0
  57. package/dist/knowledge/fiori/ui5-manifest.md +411 -0
  58. package/dist/knowledge/fiori/ui5-routing.md +303 -0
  59. package/dist/knowledge/fiori/ui5-xml-views.md +294 -0
  60. package/dist/logger.js +114 -0
  61. package/dist/system-profile.js +207 -0
  62. package/dist/tools/abap-doc.js +72 -0
  63. package/dist/tools/abapgit.js +161 -0
  64. package/dist/tools/activate.js +68 -0
  65. package/dist/tools/atc-check.js +117 -0
  66. package/dist/tools/auth-object.js +56 -0
  67. package/dist/tools/breakpoints.js +76 -0
  68. package/dist/tools/call-hierarchy.js +84 -0
  69. package/dist/tools/cds-annotations.js +98 -0
  70. package/dist/tools/cds-dependencies.js +65 -0
  71. package/dist/tools/check.js +47 -0
  72. package/dist/tools/code-completion.js +70 -0
  73. package/dist/tools/code-coverage.js +111 -0
  74. package/dist/tools/create-amdp.js +111 -0
  75. package/dist/tools/create-dcl.js +81 -0
  76. package/dist/tools/create-transport.js +38 -0
  77. package/dist/tools/create.js +285 -0
  78. package/dist/tools/data-preview.js +37 -0
  79. package/dist/tools/delete.js +45 -0
  80. package/dist/tools/deploy-bsp.js +298 -0
  81. package/dist/tools/discovery.js +59 -0
  82. package/dist/tools/element-info.js +93 -0
  83. package/dist/tools/enhancements.js +186 -0
  84. package/dist/tools/extract-method.js +44 -0
  85. package/dist/tools/function-group.js +59 -0
  86. package/dist/tools/knowledge.js +275 -0
  87. package/dist/tools/lock-object.js +75 -0
  88. package/dist/tools/message-class.js +67 -0
  89. package/dist/tools/navigate.js +80 -0
  90. package/dist/tools/number-range.js +57 -0
  91. package/dist/tools/object-documentation.js +43 -0
  92. package/dist/tools/object-structure.js +78 -0
  93. package/dist/tools/object-versions.js +57 -0
  94. package/dist/tools/package-contents.js +60 -0
  95. package/dist/tools/pretty-printer.js +35 -0
  96. package/dist/tools/publish-binding.js +49 -0
  97. package/dist/tools/quick-fix.js +69 -0
  98. package/dist/tools/read.js +167 -0
  99. package/dist/tools/refactor-rename.js +60 -0
  100. package/dist/tools/release-transport.js +24 -0
  101. package/dist/tools/released-apis.js +51 -0
  102. package/dist/tools/repository-tree.js +90 -0
  103. package/dist/tools/scaffold-rap.js +642 -0
  104. package/dist/tools/search.js +73 -0
  105. package/dist/tools/shared/data-format.js +101 -0
  106. package/dist/tools/sql-console.js +17 -0
  107. package/dist/tools/system-info.js +270 -0
  108. package/dist/tools/traces.js +66 -0
  109. package/dist/tools/transport-contents.js +83 -0
  110. package/dist/tools/transports.js +67 -0
  111. package/dist/tools/unit-test.js +135 -0
  112. package/dist/tools/where-used.js +59 -0
  113. package/dist/tools/write.js +101 -0
  114. package/package.json +49 -0
@@ -0,0 +1,343 @@
1
+ # CAP Deployment — Cloud Foundry, mta.yaml, XSUAA, HDI
2
+
3
+ ## mta.yaml — Complete Example
4
+
5
+ ```yaml
6
+ _schema-version: '3.1'
7
+ ID: bookshop
8
+ description: CAP Bookshop Application
9
+ version: 1.0.0
10
+ modules:
11
+
12
+ # CAP Server (Node.js)
13
+ - name: bookshop-srv
14
+ type: nodejs
15
+ path: gen/srv
16
+ parameters:
17
+ buildpack: nodejs_buildpack
18
+ memory: 256M
19
+ disk-quota: 512M
20
+ build-parameters:
21
+ builder: npm
22
+ provides:
23
+ - name: srv-api
24
+ properties:
25
+ srv-url: ${default-url}
26
+ requires:
27
+ - name: bookshop-db
28
+ - name: bookshop-auth
29
+
30
+ # HANA DB Deployer
31
+ - name: bookshop-db-deployer
32
+ type: hdb
33
+ path: gen/db
34
+ parameters:
35
+ buildpack: nodejs_buildpack
36
+ requires:
37
+ - name: bookshop-db
38
+
39
+ # App Router (UI)
40
+ - name: bookshop-app
41
+ type: approuter.nodejs
42
+ path: app/router
43
+ parameters:
44
+ keep-existing-routes: true
45
+ disk-quota: 256M
46
+ memory: 256M
47
+ requires:
48
+ - name: srv-api
49
+ group: destinations
50
+ properties:
51
+ name: srv-api
52
+ url: ~{srv-url}
53
+ forwardAuthToken: true
54
+ - name: bookshop-auth
55
+ build-parameters:
56
+ requires:
57
+ - name: bookshop-ui
58
+ artifacts:
59
+ - ./*
60
+ target-path: resources
61
+
62
+ # UI Build
63
+ - name: bookshop-ui
64
+ type: html5
65
+ path: app/browse
66
+ build-parameters:
67
+ build-result: dist
68
+ builder: custom
69
+ commands:
70
+ - npm install
71
+ - npm run build
72
+
73
+ resources:
74
+
75
+ # HDI Container (HANA)
76
+ - name: bookshop-db
77
+ type: com.sap.xs.hdi-container
78
+ parameters:
79
+ service: hana
80
+ service-plan: hdi-shared
81
+
82
+ # XSUAA (Authentication)
83
+ - name: bookshop-auth
84
+ type: org.cloudfoundry.managed-service
85
+ parameters:
86
+ service: xsuaa
87
+ service-plan: application
88
+ path: ./xs-security.json
89
+ ```
90
+
91
+ ## xs-security.json — Authentication Config
92
+
93
+ ```json
94
+ {
95
+ "xsappname": "bookshop",
96
+ "tenant-mode": "dedicated",
97
+ "scopes": [
98
+ {
99
+ "name": "$XSAPPNAME.admin",
100
+ "description": "Admin access"
101
+ },
102
+ {
103
+ "name": "$XSAPPNAME.viewer",
104
+ "description": "Read-only access"
105
+ }
106
+ ],
107
+ "attributes": [
108
+ {
109
+ "name": "Country",
110
+ "description": "Country for data access",
111
+ "valueType": "string"
112
+ }
113
+ ],
114
+ "role-templates": [
115
+ {
116
+ "name": "Admin",
117
+ "description": "Administrator",
118
+ "scope-references": ["$XSAPPNAME.admin"],
119
+ "attribute-references": ["Country"]
120
+ },
121
+ {
122
+ "name": "Viewer",
123
+ "description": "Read-only user",
124
+ "scope-references": ["$XSAPPNAME.viewer"]
125
+ }
126
+ ],
127
+ "role-collections": [
128
+ {
129
+ "name": "BookshopAdmin",
130
+ "description": "Bookshop Administrators",
131
+ "role-template-references": ["$XSAPPNAME.Admin"]
132
+ },
133
+ {
134
+ "name": "BookshopViewer",
135
+ "description": "Bookshop Viewers",
136
+ "role-template-references": ["$XSAPPNAME.Viewer"]
137
+ }
138
+ ]
139
+ }
140
+ ```
141
+
142
+ ## xs-app.json — App Router
143
+
144
+ ```json
145
+ {
146
+ "welcomeFile": "/index.html",
147
+ "authenticationMethod": "route",
148
+ "routes": [
149
+ {
150
+ "source": "^/browse/(.*)$",
151
+ "target": "/browse/$1",
152
+ "destination": "srv-api",
153
+ "authenticationType": "xsuaa",
154
+ "csrfProtection": true
155
+ },
156
+ {
157
+ "source": "^/admin/(.*)$",
158
+ "target": "/admin/$1",
159
+ "destination": "srv-api",
160
+ "authenticationType": "xsuaa",
161
+ "csrfProtection": true
162
+ },
163
+ {
164
+ "source": "^(.*)$",
165
+ "target": "$1",
166
+ "service": "html5-apps-repo-rt",
167
+ "authenticationType": "xsuaa"
168
+ }
169
+ ]
170
+ }
171
+ ```
172
+
173
+ ## CDS Service — Access Control
174
+
175
+ ```cds
176
+ // Link CDS @requires to xs-security.json scopes
177
+ service AdminService @(requires: 'admin') {
178
+ entity Books as projection on my.Books;
179
+ }
180
+
181
+ service CatalogService @(requires: 'authenticated-user') {
182
+ @readonly
183
+ entity Books as projection on my.Books;
184
+ }
185
+
186
+ // Entity-level restrictions
187
+ service OrderService {
188
+ @requires: 'admin'
189
+ entity Orders as projection on my.Orders;
190
+
191
+ @requires: ['admin', 'support']
192
+ action cancelOrder(orderID: UUID);
193
+ }
194
+
195
+ // Instance-level (attribute-based)
196
+ annotate OrderService.Orders with @(restrict: [
197
+ { grant: 'READ', to: 'viewer' },
198
+ { grant: ['CREATE', 'UPDATE', 'DELETE'], to: 'admin' },
199
+ { grant: 'READ', where: 'country = $user.Country' }
200
+ ]);
201
+ ```
202
+
203
+ ## Build & Deploy Commands
204
+
205
+ ```bash
206
+ # Install dependencies
207
+ npm install
208
+
209
+ # Build for production (generates gen/ folder)
210
+ cds build --production
211
+
212
+ # Build MTA archive
213
+ mbt build
214
+
215
+ # Deploy to Cloud Foundry
216
+ cf login -a https://api.cf.eu10.hana.ondemand.com
217
+ cf deploy mta_archives/bookshop_1.0.0.mtar
218
+
219
+ # Check deployment
220
+ cf apps
221
+ cf services
222
+
223
+ # View logs
224
+ cf logs bookshop-srv --recent
225
+
226
+ # Undeploy (removes all modules + services)
227
+ cf undeploy bookshop --delete-services
228
+ ```
229
+
230
+ ## HANA Configuration
231
+
232
+ ```json
233
+ // package.json — database config
234
+ {
235
+ "cds": {
236
+ "requires": {
237
+ "db": {
238
+ "kind": "hana",
239
+ "[development]": {
240
+ "kind": "sqlite",
241
+ "credentials": { "database": ":memory:" }
242
+ },
243
+ "[production]": {
244
+ "kind": "hana"
245
+ }
246
+ }
247
+ },
248
+ "hana": {
249
+ "deploy-format": "hdbtable"
250
+ }
251
+ }
252
+ }
253
+ ```
254
+
255
+ ## Hybrid Development (Local + HANA)
256
+
257
+ ```bash
258
+ # Bind to remote HANA service
259
+ cf create-service-key bookshop-db bookshop-db-key
260
+ cds bind --to bookshop-db:bookshop-db-key
261
+
262
+ # Run locally with remote HANA
263
+ cds watch --profile hybrid
264
+ ```
265
+
266
+ ## .cdsrc.json — Project Config
267
+
268
+ ```json
269
+ {
270
+ "build": {
271
+ "target": "gen",
272
+ "tasks": [
273
+ { "for": "hana", "src": "db", "options": { "model": ["db", "srv"] } },
274
+ { "for": "node-cf", "src": "srv", "options": { "model": ["db", "srv"] } }
275
+ ]
276
+ },
277
+ "odata": {
278
+ "version": "v4"
279
+ }
280
+ }
281
+ ```
282
+
283
+ ## Project Structure (Production)
284
+
285
+ ```
286
+ project/
287
+ ├── app/
288
+ │ ├── browse/ # UI module (Fiori)
289
+ │ │ ├── webapp/
290
+ │ │ └── package.json
291
+ │ ├── router/ # App Router
292
+ │ │ ├── xs-app.json
293
+ │ │ └── package.json
294
+ │ └── common.cds # Shared annotations
295
+ ├── db/
296
+ │ ├── schema.cds # Data model
297
+ │ ├── data/ # CSV seed data
298
+ │ │ └── my.bookshop-Books.csv
299
+ │ └── undeploy.json
300
+ ├── srv/
301
+ │ ├── catalog-service.cds
302
+ │ ├── catalog-service.js
303
+ │ ├── admin-service.cds
304
+ │ └── admin-service.js
305
+ ├── mta.yaml
306
+ ├── xs-security.json
307
+ ├── package.json
308
+ └── .cdsrc.json
309
+ ```
310
+
311
+ ## CSV Seed Data
312
+
313
+ ```
314
+ # db/data/my.bookshop-Books.csv
315
+ ID;title;author_ID;stock;price;currency_code
316
+ 1;Wuthering Heights;101;12;11.11;EUR
317
+ 2;Jane Eyre;107;11;12.34;EUR
318
+ 3;The Raven;150;333;13.13;USD
319
+ ```
320
+
321
+ File naming: `<namespace>-<Entity>.csv` with semicolon separator.
322
+
323
+ ## Rules
324
+ - `cds build --production` before `mbt build` (generates gen/ folder)
325
+ - xs-security.json `xsappname` must match MTA ID
326
+ - `$XSAPPNAME` prefix auto-resolves to the app name at deploy time
327
+ - HDI container: `hdi-shared` plan for shared HANA, `hdi-dynamic` for multi-tenant
328
+ - App Router routes: order matters — first match wins
329
+ - `@requires: 'authenticated-user'` for any logged-in user (no specific role)
330
+ - CSV seed data: deployed with `hdb` deployer, semicolon separated
331
+ - `[development]` / `[production]` profiles in package.json for env-specific config
332
+
333
+ ## Anti-Patterns
334
+ | Anti-Pattern | Correct |
335
+ |---|---|
336
+ | Deploying without `cds build --production` | Build generates optimized gen/ folder |
337
+ | Missing xs-security.json in mta.yaml | `path: ./xs-security.json` in auth resource |
338
+ | Hardcoded credentials in code | Use XSUAA + destination service |
339
+ | `tenant-mode: shared` for single-tenant | Use `dedicated` unless multi-tenant SaaS |
340
+ | Missing CSRF protection on routes | `csrfProtection: true` in xs-app.json |
341
+ | App Router without `forwardAuthToken` | Required for auth propagation to srv |
342
+ | Deploying test data to production | Use `[development]` profile for seed data |
343
+ | `cf push` instead of `cf deploy` | Use MTA deployment for multi-module apps |
@@ -0,0 +1,287 @@
1
+ # Event Handlers — CAP Node.js Service Implementation
2
+
3
+ ## Handler Registration (Class-Based)
4
+
5
+ ```js
6
+ const cds = require('@sap/cds');
7
+
8
+ module.exports = class CatalogService extends cds.ApplicationService {
9
+ async init() {
10
+ const { Books, Authors } = this.entities;
11
+
12
+ this.before('CREATE', Books, this.validateBook);
13
+ this.on('READ', Books, this.onReadBooks);
14
+ this.after('READ', Books, this.enrichBooks);
15
+ this.on('submitOrder', this.onSubmitOrder);
16
+
17
+ return super.init();
18
+ }
19
+
20
+ validateBook(req) { /* ... */ }
21
+ async onReadBooks(req) { /* ... */ }
22
+ enrichBooks(books, req) { /* ... */ }
23
+ async onSubmitOrder(req) { /* ... */ }
24
+ }
25
+ ```
26
+
27
+ ## Handler Registration (Functional)
28
+
29
+ ```js
30
+ module.exports = function() {
31
+ const { Books } = this.entities;
32
+
33
+ this.before('CREATE', Books, validateBook);
34
+ this.on('READ', Books, onReadBooks);
35
+ this.after('READ', Books, enrichBooks);
36
+
37
+ function validateBook(req) { /* ... */ }
38
+ async function onReadBooks(req) { /* ... */ }
39
+ function enrichBooks(books, req) { /* ... */ }
40
+ }
41
+ ```
42
+
43
+ ## before Handlers — Validation and Enrichment
44
+
45
+ ```js
46
+ // Validation (collect multiple errors)
47
+ this.before('CREATE', 'Books', (req) => {
48
+ const { title, price } = req.data;
49
+ if (!title) req.error(400, 'Title is required', 'title');
50
+ if (price < 0) req.error(400, 'Price must be positive', 'price');
51
+ });
52
+
53
+ // Enrichment
54
+ this.before('CREATE', 'Orders', (req) => {
55
+ req.data.status = 'draft';
56
+ req.data.createdAt = new Date();
57
+ });
58
+
59
+ // Authorization
60
+ this.before('UPDATE', 'Books', async (req) => {
61
+ const book = await SELECT.one.from('Books', req.data.ID);
62
+ if (book.createdBy !== req.user.id && !req.user.is('admin')) {
63
+ req.reject(403, 'Not authorized');
64
+ }
65
+ });
66
+ ```
67
+
68
+ ## on Handlers — Custom Implementation
69
+
70
+ ```js
71
+ // Custom READ
72
+ this.on('READ', 'Books', async (req) => {
73
+ return await cds.db.run(req.query);
74
+ });
75
+
76
+ // Delegate to default + post-process
77
+ this.on('READ', 'Books', async (req, next) => {
78
+ const result = await next();
79
+ return result.filter(b => b.stock > 0);
80
+ });
81
+
82
+ // Action handler
83
+ this.on('submitOrder', async (req) => {
84
+ const { book, quantity } = req.data;
85
+ const b = await SELECT.one.from('Books', book);
86
+ if (!b) return req.reject(404, 'Book not found');
87
+ if (b.stock < quantity) return req.reject(409, 'Insufficient stock');
88
+ await UPDATE('Books', book).set({ stock: { '-=': quantity } });
89
+ return { success: true };
90
+ });
91
+
92
+ // Bound action
93
+ this.on('confirm', 'Orders', async (req) => {
94
+ const { ID } = req.params[0];
95
+ await UPDATE('Orders', ID).set({ status: 'confirmed' });
96
+ });
97
+ ```
98
+
99
+ ## after Handlers — Post-Processing
100
+
101
+ ```js
102
+ // Enrich results (first param is result data)
103
+ this.after('READ', 'Books', (books, req) => {
104
+ for (const book of books) {
105
+ book.discount = book.stock > 100 ? '10%' : null;
106
+ book.available = book.stock > 0;
107
+ }
108
+ });
109
+
110
+ // Emit event after creation
111
+ this.after('CREATE', 'Orders', async (order, req) => {
112
+ await this.emit('OrderCreated', { orderID: order.ID });
113
+ });
114
+ ```
115
+
116
+ ## Request Object (req)
117
+
118
+ ```js
119
+ this.on('CREATE', 'Books', (req) => {
120
+ req.event; // 'CREATE', 'READ', 'UPDATE', 'DELETE', or action name
121
+ req.target; // Entity definition (CSN)
122
+ req.entity; // Entity name string
123
+ req.data; // Request payload
124
+ req.params; // URL parameters [{ID: '123'}]
125
+ req.query; // CQN query object
126
+ req.user.id; // User ID
127
+ req.user.is('admin'); // Role check
128
+ req.user.attr.country; // User attribute
129
+ req.tenant; // Tenant ID
130
+ req.locale; // User locale
131
+ req.timestamp; // Request timestamp
132
+ });
133
+ ```
134
+
135
+ ## Error Handling
136
+
137
+ ```js
138
+ // Immediate rejection (stops processing)
139
+ req.reject(400, 'Bad request');
140
+ req.reject(404, 'Not found');
141
+
142
+ // Collect errors (continues, rejects at end of phase)
143
+ req.error(400, 'Title required', 'title');
144
+ req.error(400, 'Price required', 'price');
145
+
146
+ // Warnings and info (returned in response headers, no rejection)
147
+ req.warn(200, 'Stock is low');
148
+ req.info(200, 'Price updated');
149
+
150
+ // Standard CAP error classes
151
+ const { errors } = require('@sap/cds');
152
+ throw new errors.NotFound('Book not found');
153
+ throw new errors.Unauthorized('Login required');
154
+ throw new errors.Forbidden('Access denied');
155
+ ```
156
+
157
+ ## Wildcard Handlers
158
+
159
+ ```js
160
+ this.before('*', 'Books', handler); // All events on Books
161
+ this.before('CREATE', '*', handler); // CREATE on all entities
162
+ this.before('*', handler); // All events on all entities
163
+ ```
164
+
165
+ ## Draft Events
166
+
167
+ ```js
168
+ this.on('NEW', 'Books', handler); // Create draft
169
+ this.on('EDIT', 'Books', handler); // Edit existing as draft
170
+ this.on('PATCH', 'Books', handler); // Update draft fields
171
+ this.on('SAVE', 'Books', handler); // Activate/save draft
172
+ this.on('CANCEL', 'Books', handler); // Discard draft
173
+ ```
174
+
175
+ ## Database Operations in Handlers
176
+
177
+ ```js
178
+ const { Books } = cds.entities;
179
+
180
+ const books = await SELECT.from(Books).where({ stock: { '>': 0 } });
181
+ const book = await SELECT.one.from(Books, bookId);
182
+ await INSERT.into(Books).entries({ title: 'New', stock: 10 });
183
+ await UPDATE(Books, bookId).set({ stock: 50 });
184
+ await DELETE.from(Books, bookId);
185
+ await UPSERT.into(Books).entries({ ID: bookId, title: 'Updated' });
186
+ ```
187
+
188
+ ## Transactions
189
+
190
+ ```js
191
+ this.on('transferStock', async (req) => {
192
+ const { from, to, amount } = req.data;
193
+
194
+ // Handlers run inside automatic transaction
195
+ await UPDATE(Books, from).set({ stock: { '-=': amount } });
196
+ await UPDATE(Books, to).set({ stock: { '+=': amount } });
197
+
198
+ // Explicit transaction (when needed)
199
+ return cds.tx(async (tx) => {
200
+ await tx.run(UPDATE(Books, from).set({ stock: { '-=': amount } }));
201
+ await tx.run(UPDATE(Books, to).set({ stock: { '+=': amount } }));
202
+ return { success: true };
203
+ });
204
+ });
205
+ ```
206
+
207
+ ## Service-to-Service Communication
208
+
209
+ ```js
210
+ const adminSrv = await cds.connect.to('AdminService');
211
+ const books = await adminSrv.read('Books');
212
+ await adminSrv.send('updateStock', { book: bookId, delta: 10 });
213
+
214
+ const externalApi = await cds.connect.to('ExternalAPI');
215
+ const result = await externalApi.run(SELECT.from('Products'));
216
+ ```
217
+
218
+ ## Event Emission and Subscription
219
+
220
+ ```js
221
+ // Emit
222
+ this.emit('OrderCreated', { orderID: order.ID });
223
+
224
+ // Subscribe
225
+ const messaging = await cds.connect.to('messaging');
226
+ messaging.on('OrderCreated', async (msg) => {
227
+ const { orderID } = msg.data;
228
+ });
229
+ ```
230
+
231
+ ## Lifecycle Hooks
232
+
233
+ ```js
234
+ req.before('commit', async () => { /* before transaction commit */ });
235
+ req.on('succeeded', async () => { /* after successful commit (outside tx) */ });
236
+ req.on('failed', async () => { /* after rollback */ });
237
+ req.on('done', async () => { /* always — cleanup */ });
238
+ ```
239
+
240
+ ## Context Access
241
+
242
+ ```js
243
+ // Available anywhere in async call chain
244
+ const { user, tenant, locale } = cds.context;
245
+
246
+ // Set context for background jobs
247
+ cds.context = { user: new cds.User('system'), tenant: 't1' };
248
+ ```
249
+
250
+ ## TypeScript
251
+
252
+ ```ts
253
+ import cds from '@sap/cds';
254
+ import { Request } from '@sap/cds';
255
+
256
+ export default class CatalogService extends cds.ApplicationService {
257
+ async init() {
258
+ this.on('READ', 'Books', this.readBooks);
259
+ return super.init();
260
+ }
261
+ private async readBooks(req: Request) {
262
+ return await cds.db.run(req.query);
263
+ }
264
+ }
265
+ ```
266
+
267
+ ## Rules
268
+
269
+ - `before` handlers: validation and enrichment; `on` handlers: replace default logic; `after` handlers: post-process results
270
+ - `req.reject()` stops immediately; `req.error()` collects and rejects at end of phase
271
+ - `after('READ')` callback signature is `(results, req)` — results first
272
+ - Handlers run inside automatic transactions; explicit `cds.tx()` rarely needed
273
+ - Always call `return super.init()` at end of class-based `init()`
274
+ - Use `next()` in `on` handlers to delegate to the default/next handler in chain
275
+ - Bound action params accessed via `req.params[0]` for the entity key, `req.data` for action params
276
+
277
+ ## Anti-Patterns
278
+
279
+ | Anti-Pattern | Correct Pattern |
280
+ |---|---|
281
+ | Forgetting `return super.init()` in class-based handler | Always end `init()` with `return super.init()` |
282
+ | Using `req.reject()` for multiple validation errors | Use `req.error()` to collect, framework rejects if errors exist |
283
+ | `after('READ')` with `(req, books)` param order | Correct order: `(books, req)` |
284
+ | Business logic in `before` that should be in `on` | `before` = validate/enrich; `on` = business logic |
285
+ | Direct DB writes without considering CAP transactions | Use CQL APIs; handlers auto-manage transactions |
286
+ | Forgetting `async` on handlers that use `await` | Always mark handlers as `async` when using `await` |
287
+ | Not calling `next()` when extending default READ | Without `next()`, default query is skipped entirely |