@sap/cds-dk 9.2.0 → 9.3.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 (67) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/bin/bind.js +7 -8
  3. package/bin/up.js +13 -9
  4. package/lib/bind/cf.js +4 -0
  5. package/lib/bind/k8s.js +21 -0
  6. package/lib/bind/plugin.js +9 -0
  7. package/lib/bind/shared.js +4 -2
  8. package/lib/build/buildTaskProviderFactory.js +8 -14
  9. package/lib/build/constants.js +1 -0
  10. package/lib/build/index.js +17 -2
  11. package/lib/build/plugin.js +5 -7
  12. package/lib/build/provider/hana/index.js +4 -4
  13. package/lib/compile/to-xsuaa.js +11 -2
  14. package/lib/deploy/to-hana/hana.js +1 -1
  15. package/lib/deploy/to-hana/hdiDeployUtil.js +1 -1
  16. package/lib/env/schemas/cds-rc.js +2 -2
  17. package/lib/init/constants.js +3 -2
  18. package/lib/init/projectReader.js +5 -5
  19. package/lib/init/template/ams/index.js +1 -2
  20. package/lib/init/template/approuter/files/containerize.yaml.hbs +1 -1
  21. package/lib/init/template/approuter/index.js +1 -1
  22. package/lib/init/template/attachments/index.js +1 -1
  23. package/lib/init/template/audit-logging/index.js +1 -1
  24. package/lib/init/template/extension/files/.base/index.cds +6 -6
  25. package/lib/init/template/extension/index.js +5 -5
  26. package/lib/init/template/github-actions/files/{cf-github-deploy → github-deployment}/action.yaml +7 -5
  27. package/lib/init/template/github-actions/files/kyma-info/action.yaml +1 -1
  28. package/lib/init/template/github-actions/files/workflows/cf.yaml.hbs +14 -7
  29. package/lib/init/template/github-actions/files/workflows/kyma.yaml.hbs +6 -3
  30. package/lib/init/template/github-actions/files/workflows/test.yaml.hbs +5 -2
  31. package/lib/init/template/github-actions/index.js +8 -13
  32. package/lib/init/template/hana/index.js +2 -1
  33. package/lib/init/template/html5-repo/files/mta.yaml.hbs +5 -1
  34. package/lib/init/template/html5-repo/files/package.json.hbs +1 -1
  35. package/lib/init/template/html5-repo/index.js +24 -19
  36. package/lib/init/template/ias/files/mta.yaml.hbs +4 -3
  37. package/lib/init/template/ias/files/values.yaml.hbs +41 -40
  38. package/lib/init/template/lint/index.js +6 -11
  39. package/lib/init/template/mta/files/package.json +1 -1
  40. package/lib/init/template/nodejs/files/.vscode/extensions.json +0 -1
  41. package/lib/init/template/nodejs/files/.vscode/settings.json +2 -2
  42. package/lib/init/template/nodejs/files/package.json.hbs +3 -9
  43. package/lib/init/template/notifications/index.js +1 -1
  44. package/lib/init/template/portal/files/mta.yaml.hbs +5 -1
  45. package/lib/init/template/portal/index.js +0 -1
  46. package/lib/init/template/postgres/index.js +1 -1
  47. package/lib/init/template/sample/files/app/_i18n/i18n.properties +15 -0
  48. package/lib/init/template/sample/files/app/_i18n/i18n_de.properties +15 -0
  49. package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +14 -15
  50. package/lib/init/template/sample/files/app/browse/fiori-service.cds +44 -44
  51. package/lib/init/template/sample/files/app/common.cds +99 -84
  52. package/lib/init/template/sample/files/db/schema.cds +22 -17
  53. package/lib/init/template/sample/files/package.json.hbs +1 -3
  54. package/lib/init/template/sample/files/srv/admin-service.cds +4 -3
  55. package/lib/init/template/sample/files/srv/cat-service.cds +28 -11
  56. package/lib/init/template/tiny-sample/files/nodejs/db/schema.cds +3 -3
  57. package/lib/init/template/typescript/files/package.json +1 -1
  58. package/lib/init/template/ui5/index.js +22 -0
  59. package/lib/init/template/workzone-standard/index.js +1 -1
  60. package/lib/lint/eslintHelp.json +5 -3
  61. package/lib/util/cf.js +7 -7
  62. package/npm-shrinkwrap.json +17 -17
  63. package/package.json +1 -1
  64. package/lib/init/template/sample/files/javascript/admin-service.js.hbs +0 -24
  65. package/lib/init/template/sample/files/javascript/cat-service.js.hbs +0 -43
  66. package/lib/init/template/sample/files/typescript/admin-service.ts.hbs +0 -16
  67. package/lib/init/template/sample/files/typescript/cat-service.ts.hbs +0 -38
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "9.32.0",
3
- "help": "\n# SYNOPSIS\n\n *cds lint* [options] file.js [file.js] [dir]\n\n Runs environment checks and/or checks the specified models\n based on the ESLint framework\n\n# OPTIONS\n \n Basic configuration:\n --no-config-lookup Disable look up for eslint.config.js\n -c, --config path::String Use this configuration instead of eslint.config.js, eslint.config.mjs, or eslint.config.cjs\n --inspect-config Open the config inspector with the current configuration\n --ext [String] Specify additional file extensions to lint\n --global [String] Define global variables\n --parser String Specify the parser to be used\n --parser-options Object Specify parser options\n \n Specify Rules and Plugins:\n --plugin [String] Specify plugins\n --rule Object Specify rules\n \n Fix Problems:\n --fix Automatically fix problems\n --fix-dry-run Automatically fix problems without saving the changes to the file system\n --fix-type Array Specify the types of fixes to apply (directive, problem, suggestion, layout)\n \n Ignore Files:\n --no-ignore Disable use of ignore files and patterns\n --ignore-pattern [String] Patterns of files to ignore\n \n Use stdin:\n --stdin Lint code provided on <STDIN> - default: false\n --stdin-filename String Specify filename to process STDIN as\n \n Handle Warnings:\n --quiet Report errors only - default: false\n --max-warnings Int Number of warnings to trigger nonzero exit code - default: -1\n \n Output:\n -o, --output-file path::String Specify file to write report to\n -f, --format String Use a specific output format - default: stylish\n --color, --no-color Force enabling/disabling of color\n \n Inline configuration comments:\n --no-inline-config Prevent comments from changing config or rules\n --report-unused-disable-directives Adds reported errors for unused eslint-disable and eslint-enable directives\n --report-unused-disable-directives-severity String Chooses severity level for reporting unused eslint-disable and eslint-enable directives - either: off, warn, error, 0, 1, or 2\n --report-unused-inline-configs String Adds reported errors for unused eslint inline config comments - either: off, warn, error, 0, 1, or 2\n \n Caching:\n --cache Only check changed files - default: false\n --cache-file path::String Path to the cache file. Deprecated: use --cache-location - default: .eslintcache\n --cache-location path::String Path to the cache file or directory\n --cache-strategy String Strategy to use for detecting changed files in the cache - either: metadata or content - default: metadata\n \n Suppressing Violations:\n --suppress-all Suppress all violations - default: false\n --suppress-rule [String] Suppress specific rules\n --suppressions-location path::String Specify the location of the suppressions file\n --prune-suppressions Prune unused suppressions - default: false\n --pass-on-unpruned-suppressions Ignore unused suppressions - default: false\n \n Miscellaneous:\n --init Run config initialization wizard - default: false\n --env-info Output execution environment information - default: false\n --no-error-on-unmatched-pattern Prevent errors when pattern is unmatched\n --exit-on-fatal-error Exit with exit code 2 in case of fatal error - default: false\n --no-warn-ignored Suppress warnings when the file list includes ignored files\n --pass-on-no-patterns Exit with exit code 0 in case no file patterns are passed\n --debug Output debugging information\n -h, --help Show help\n -v, --version Output the version number\n --print-config path::String Print the configuration for the given file\n --stats Add statistics to the lint report - default: false\n --flag [String] Enable a feature flag\n --mcp Start the ESLint MCP server\n \n",
2
+ "version": "9.34.0",
3
+ "help": "\n# SYNOPSIS\n\n *cds lint* [options] file.js [file.js] [dir]\n\n Runs environment checks and/or checks the specified models\n based on the ESLint framework\n\n# OPTIONS\n \n Basic configuration:\n --no-config-lookup Disable look up for eslint.config.js\n -c, --config path::String Use this configuration instead of eslint.config.js, eslint.config.mjs, or eslint.config.cjs\n --inspect-config Open the config inspector with the current configuration\n --ext [String] Specify additional file extensions to lint\n --global [String] Define global variables\n --parser String Specify the parser to be used\n --parser-options Object Specify parser options\n \n Specify Rules and Plugins:\n --plugin [String] Specify plugins\n --rule Object Specify rules\n \n Fix Problems:\n --fix Automatically fix problems\n --fix-dry-run Automatically fix problems without saving the changes to the file system\n --fix-type Array Specify the types of fixes to apply (directive, problem, suggestion, layout)\n \n Ignore Files:\n --no-ignore Disable use of ignore files and patterns\n --ignore-pattern [String] Patterns of files to ignore\n \n Use stdin:\n --stdin Lint code provided on <STDIN> - default: false\n --stdin-filename String Specify filename to process STDIN as\n \n Handle Warnings:\n --quiet Report errors only - default: false\n --max-warnings Int Number of warnings to trigger nonzero exit code - default: -1\n \n Output:\n -o, --output-file path::String Specify file to write report to\n -f, --format String Use a specific output format - default: stylish\n --color, --no-color Force enabling/disabling of color\n \n Inline configuration comments:\n --no-inline-config Prevent comments from changing config or rules\n --report-unused-disable-directives Adds reported errors for unused eslint-disable and eslint-enable directives\n --report-unused-disable-directives-severity String Chooses severity level for reporting unused eslint-disable and eslint-enable directives - either: off, warn, error, 0, 1, or 2\n --report-unused-inline-configs String Adds reported errors for unused eslint inline config comments - either: off, warn, error, 0, 1, or 2\n \n Caching:\n --cache Only check changed files - default: false\n --cache-file path::String Path to the cache file. Deprecated: use --cache-location - default: .eslintcache\n --cache-location path::String Path to the cache file or directory\n --cache-strategy String Strategy to use for detecting changed files in the cache - either: metadata or content - default: metadata\n \n Suppressing Violations:\n --suppress-all Suppress all violations - default: false\n --suppress-rule [String] Suppress specific rules\n --suppressions-location path::String Specify the location of the suppressions file\n --prune-suppressions Prune unused suppressions - default: false\n --pass-on-unpruned-suppressions Ignore unused suppressions - default: false\n \n Miscellaneous:\n --init Run config initialization wizard - default: false\n --env-info Output execution environment information - default: false\n --no-error-on-unmatched-pattern Prevent errors when pattern is unmatched\n --exit-on-fatal-error Exit with exit code 2 in case of fatal error - default: false\n --no-warn-ignored Suppress warnings when the file list includes ignored files\n --pass-on-no-patterns Exit with exit code 0 in case no file patterns are passed\n --debug Output debugging information\n -h, --help Show help\n -v, --version Output the version number\n --print-config path::String Print the configuration for the given file\n --stats Add statistics to the lint report - default: false\n --flag [String] Enable a feature flag\n --mcp Start the ESLint MCP server\n --concurrency Int|String Number of linting threads, auto to choose automatically, off for no multithreading - default: off\n \n",
4
4
  "options": [
5
5
  "--config",
6
6
  "--output-file",
@@ -24,7 +24,8 @@
24
24
  "--suppress-rule",
25
25
  "--suppressions-location",
26
26
  "--print-config",
27
- "--flag"
27
+ "--flag",
28
+ "--concurrency"
28
29
  ],
29
30
  "shortcuts": [
30
31
  "-c",
@@ -50,6 +51,7 @@
50
51
  null,
51
52
  null,
52
53
  null,
54
+ null,
53
55
  "-v",
54
56
  "-h"
55
57
  ],
package/lib/util/cf.js CHANGED
@@ -223,7 +223,7 @@ module.exports = new class CfUtil {
223
223
  async env(app) {
224
224
  const { spaceGuid: space_guids, orgGuid: organization_guids } = await this.target();
225
225
  const apps = await this.curl('/v3/apps', { space_guids, organization_guids, names: app });
226
- if (apps.resources.length < 1) throw `Cannot find app with name '${app}'`
226
+ if (apps.resources.length < 1) throw `cannot find app with name '${app}'`
227
227
  const guid = apps.resources[0].guid;
228
228
  return await this.curl('/v3/apps/' + guid + '/env', { space_guids, organization_guids, names: app });
229
229
  }
@@ -257,15 +257,15 @@ module.exports = new class CfUtil {
257
257
  if (!LOG._debug && serviceInstance?.last_operation?.description) {
258
258
  throw serviceInstance.last_operation.description;
259
259
  }
260
- throw `The returned service reported state '${OPERATION_STATE_FAILED}'.\n${JSON.stringify(serviceInstance, null, 4)}`;
260
+ throw `the returned service reported state '${OPERATION_STATE_FAILED}'.\n${JSON.stringify(serviceInstance, null, 4)}`;
261
261
 
262
262
  default:
263
- console.error(`Unsupported server response state '${serviceInstance?.last_operation?.state}'. Waiting for next response.`);
263
+ console.error(`unsupported server response state '${serviceInstance?.last_operation?.state}' – waiting for next response`);
264
264
  break;
265
265
  }
266
266
  }
267
267
 
268
- throw `Timeout occurred while getting service ${bold(serviceName)}`;
268
+ throw `timeout occurred while getting service ${bold(serviceName)}`;
269
269
  }
270
270
 
271
271
  async getOrCreateService(serviceOfferingName, planName, serviceName, options) {
@@ -275,7 +275,7 @@ module.exports = new class CfUtil {
275
275
  return probeService;
276
276
  }
277
277
 
278
- console.log(`Creating service ${bold(serviceName)} - please be patient...`);
278
+ console.log(`creating service ${bold(serviceName)} - please be patient...`);
279
279
 
280
280
  const target = await this.target();
281
281
 
@@ -287,7 +287,7 @@ module.exports = new class CfUtil {
287
287
  });
288
288
 
289
289
  if (!servicePlan?.resources?.length) {
290
- throw `No service plans found for ${planName} in service offering ${serviceOfferingName}.`;
290
+ throw `no service plans found for ${planName} in service offering ${serviceOfferingName}`;
291
291
  }
292
292
 
293
293
  const body = {
@@ -353,7 +353,7 @@ module.exports = new class CfUtil {
353
353
  throw `The returned binding reported state '${OPERATION_STATE_FAILED}'.\n${JSON.stringify(binding, null, 4)}`;
354
354
 
355
355
  default:
356
- console.error(`Unsupported server response state '${binding?.last_operation?.state}'. Waiting for next response.`);
356
+ console.error(`unsupported server response state '${binding?.last_operation?.state}'. Waiting for next response.`);
357
357
  break;
358
358
  }
359
359
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@sap/cds-dk",
3
- "version": "9.2.0",
3
+ "version": "9.3.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@sap/cds-dk",
9
- "version": "9.2.0",
9
+ "version": "9.3.0",
10
10
  "license": "SEE LICENSE IN LICENSE",
11
11
  "dependencies": {
12
12
  "@cap-js/asyncapi": "^1.0.0",
@@ -42,8 +42,8 @@
42
42
  }
43
43
  },
44
44
  "node_modules/@cap-js/db-service": {
45
- "version": "2.3.0",
46
- "integrity": "sha512-KkYrnI05bx0PvwP5jxEUos8UQ+XYPucUMQt3i0muQXWJw3rEkWvEArvOwCYjTNnjzHqtVQfpPXsy1+ehkHUrWg==",
45
+ "version": "2.4.0",
46
+ "integrity": "sha512-tWZUkgAPgZQIVu3xownD9cA9joXPI84KDstx3ZezOxXJuRsapgM2QEs0TXwQK5XLG43FUAsGO7wVJPoZ29ZH2Q==",
47
47
  "devOptional": true,
48
48
  "license": "Apache-2.0",
49
49
  "dependencies": {
@@ -78,8 +78,8 @@
78
78
  }
79
79
  },
80
80
  "node_modules/@eslint/js": {
81
- "version": "9.32.0",
82
- "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==",
81
+ "version": "9.34.0",
82
+ "integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==",
83
83
  "license": "MIT",
84
84
  "peer": true,
85
85
  "engines": {
@@ -90,11 +90,11 @@
90
90
  }
91
91
  },
92
92
  "node_modules/@sap/cds": {
93
- "version": "9.2.0",
94
- "integrity": "sha512-u/R+Bzz8RsiL4JINwwmbPFmSD8Y10PGpXetGHYvUyefUG/V/S8OBAWy/elu4FmTr1X8J4+kuynCgoETaWRveKw==",
93
+ "version": "9.3.0",
94
+ "integrity": "sha512-2JaY4AlYvDP88DpZj5vo7B+9+r2ICmY5ktcCxHpnPoC9cmauYmXQtSn6gfuDwuBAWnFMSQEMu6qXz+7Yt8o7mQ==",
95
95
  "license": "SEE LICENSE IN LICENSE",
96
96
  "dependencies": {
97
- "@sap/cds-compiler": "^6",
97
+ "@sap/cds-compiler": "^6.1",
98
98
  "@sap/cds-fiori": "^2",
99
99
  "js-yaml": "^4.1.0"
100
100
  },
@@ -120,8 +120,8 @@
120
120
  }
121
121
  },
122
122
  "node_modules/@sap/cds-compiler": {
123
- "version": "6.2.2",
124
- "integrity": "sha512-LqRNfBsWnEJpXVJ6/v52VqAdelWoETLbECMPcy7BfoHE63DGBpKA/ZIgoH11t7vUm7GYQDcSfR7ryy02Q/fP7A==",
123
+ "version": "6.3.0",
124
+ "integrity": "sha512-4HhZuiKa8SztqtjfM9Iey7yb2U6xQGzUbjib3JXcSSP6AJ6Bz0gViliTwf8dASPTLRtv7HU82277m4uqxU2qjw==",
125
125
  "license": "SEE LICENSE IN LICENSE",
126
126
  "bin": {
127
127
  "cdsc": "bin/cdsc.js",
@@ -142,8 +142,8 @@
142
142
  }
143
143
  },
144
144
  "node_modules/@sap/cds-mtxs": {
145
- "version": "3.2.0",
146
- "integrity": "sha512-8X+fK0rsnOaKZpettVAXuzCJT9MRebpuzN1JjNEWPiYVafvIjXIQc2diYgq8rtzhfdFWk6QNlZUjMM7jLgNfsw==",
145
+ "version": "3.3.0",
146
+ "integrity": "sha512-udIzKk+qUoYWLJKbGUJm0csuZP5r54msnTNy11bFDsuESio07ppgDkCIk+oGXCjsJLeoLZULCGgFvifLRi0ATg==",
147
147
  "license": "SEE LICENSE IN LICENSE",
148
148
  "dependencies": {
149
149
  "@sap/hdi-deploy": "^5"
@@ -789,8 +789,8 @@
789
789
  "license": "MIT"
790
790
  },
791
791
  "node_modules/follow-redirects": {
792
- "version": "1.15.10",
793
- "integrity": "sha512-V7O/fFKM539IC2bweloFWuoiJ9OtI3W2uIqJPWM8IT5xxNyt73QtvVqmSpcDmk07ivmmlKB+rRY0vpQjIYNtKw==",
792
+ "version": "1.15.11",
793
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
794
794
  "funding": [
795
795
  {
796
796
  "type": "individual",
@@ -1833,8 +1833,8 @@
1833
1833
  }
1834
1834
  },
1835
1835
  "node_modules/yaml": {
1836
- "version": "2.8.0",
1837
- "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
1836
+ "version": "2.8.1",
1837
+ "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
1838
1838
  "license": "ISC",
1839
1839
  "bin": {
1840
1840
  "yaml": "bin.mjs"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/cds-dk",
3
- "version": "9.2.0",
3
+ "version": "9.3.0",
4
4
  "description": "Command line client and development toolkit for the SAP Cloud Application Programming Model",
5
5
  "homepage": "https://cap.cloud.sap/",
6
6
  "keywords": [
@@ -1,24 +0,0 @@
1
- {{#isESM}}
2
- import cds from '@sap/cds'
3
-
4
- export class AdminService extends cds.ApplicationService { init() {
5
- {{/isESM}}
6
- {{^isESM}}
7
- const cds = require('@sap/cds')
8
-
9
- module.exports = class AdminService extends cds.ApplicationService { init() {
10
- {{/isESM}}
11
-
12
- const { Books } = this.entities
13
-
14
- /**
15
- * Generate IDs for new Books drafts
16
- */
17
- this.before ('NEW', Books.drafts, async (req) => {
18
- if (req.data.ID) return
19
- const { ID:id1 } = await SELECT.one.from(Books).columns('max(ID) as ID')
20
- const { ID:id2 } = await SELECT.one.from(Books.drafts).columns('max(ID) as ID')
21
- req.data.ID = Math.max(id1||0, id2||0) + 1
22
- })
23
- return super.init()
24
- }}
@@ -1,43 +0,0 @@
1
- {{#isESM}}
2
- import cds from '@sap/cds'
3
-
4
- export class CatalogService extends cds.ApplicationService { init() {
5
- {{/isESM}}
6
- {{^isESM}}
7
- const cds = require('@sap/cds')
8
-
9
- module.exports = class CatalogService extends cds.ApplicationService { init() {
10
- {{/isESM}}
11
-
12
- const { Books } = cds.entities('sap.capire.bookshop')
13
- const { ListOfBooks } = this.entities
14
-
15
- // Add some discount for overstocked books
16
- this.after('each', ListOfBooks, book => {
17
- if (book.stock > 111) book.title += ` -- 11% discount!`
18
- })
19
-
20
- // Reduce stock of ordered books if available stock suffices
21
- this.on('submitOrder', async req => {
22
- let { book:id, quantity } = req.data
23
- let book = await SELECT.one.from (Books, id, b => b.stock)
24
-
25
- // Validate input data
26
- if (!book) return req.error (404, `Book #${id} doesn't exist`)
27
- if (quantity < 1) return req.error (400, `quantity has to be 1 or more`)
28
- if (!book.stock || quantity > book.stock) return req.error (409, `${quantity} exceeds stock for book #${id}`)
29
-
30
- // Reduce stock in database and return updated stock value
31
- await UPDATE (Books, id) .with ({ stock: book.stock -= quantity })
32
- return book
33
- })
34
-
35
- // Emit event when an order has been submitted
36
- this.after('submitOrder', async (_,req) => {
37
- let { book, quantity } = req.data
38
- await this.emit('OrderedBook', { book, quantity, buyer: req.user.id })
39
- })
40
-
41
- // Delegate requests to the underlying generic service
42
- return super.init()
43
- }}
@@ -1,16 +0,0 @@
1
- import cds from '@sap/cds'
2
-
3
- import { Books } from '#cds-models/AdminService'
4
-
5
- export class AdminService extends cds.ApplicationService { async init() {
6
-
7
- /**
8
- * Generate primary keys for target entity in request
9
- */
10
- this.before ('NEW', Books.drafts, async req => {
11
- if (req.data.ID) return
12
- const { ID } = await SELECT.one.from(Books).columns('max(ID) as ID') ?? { ID: 0 }
13
- req.data.ID = ID! - ID! % 100 + 100 + 1
14
- })
15
- return super.init()
16
- }}
@@ -1,38 +0,0 @@
1
- import cds from '@sap/cds'
2
-
3
- import { Books } from '#cds-models/sap/capire/bookshop'
4
- import { submitOrder, OrderedBook, ListOfBooks } from '#cds-models/CatalogService'
5
-
6
- export class CatalogService extends cds.ApplicationService { async init() {
7
-
8
- // Add some discount for overstocked books
9
- this.after('each', ListOfBooks, book => {
10
- if (book?.stock === undefined || book.stock === null) return
11
- if (book?.stock > 111) book.title += ` -- 11% discount!`
12
- })
13
-
14
- // Reduce stock of ordered books if available stock suffices
15
- this.on(submitOrder, async req => {
16
- let { book:id, quantity } = req.data
17
- if(!id) return req.error (400, `Book ID missing`) // FIXED
18
- let book = await SELECT.from (Books, id, b => b.stock)
19
-
20
- // Validate input data
21
- if (!book) return req.error (404, `Book #${id} doesn't exist`)
22
- if (!quantity || quantity < 1) return req.error (400, `quantity has to be 1 or more`)
23
- if (quantity > book.stock!) return req.error (409, `${quantity} exceeds stock for book #${id}`)
24
-
25
- // Reduce stock in database and return updated stock value
26
- await UPDATE (Books, id) .with ({ stock: book.stock! -= quantity })
27
- return book
28
- })
29
-
30
- // Emit event when an order has been submitted
31
- this.after(submitOrder, async (_,req) => {
32
- let { book, quantity } = req.data
33
- await this.emit(OrderedBook, { book, quantity, buyer: req.user.id })
34
- })
35
-
36
- // Delegate requests to the underlying generic service
37
- return super.init()
38
- }}