@sap/cds 7.5.2 → 7.6.1

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 (95) hide show
  1. package/CHANGELOG.md +79 -22
  2. package/app/index.js +1 -1
  3. package/lib/auth/index.js +3 -0
  4. package/lib/compile/extend.js +9 -4
  5. package/lib/compile/for/lean_drafts.js +3 -4
  6. package/lib/compile/load.js +11 -15
  7. package/lib/compile/minify.js +2 -4
  8. package/lib/compile/to/sql.js +6 -4
  9. package/lib/compile/to/srvinfo.js +25 -3
  10. package/lib/compile/to/yaml.js +1 -1
  11. package/lib/dbs/cds-deploy.js +7 -13
  12. package/lib/env/defaults.js +1 -10
  13. package/lib/env/schemas/cds-package.js +27 -0
  14. package/lib/env/schemas/cds-rc.js +693 -0
  15. package/lib/env/schemas/index.js +6 -4
  16. package/lib/i18n/localize.js +15 -1
  17. package/lib/index.js +40 -47
  18. package/lib/log/cds-error.js +6 -0
  19. package/lib/ql/Query.js +2 -1
  20. package/lib/ql/cds-ql.js +1 -2
  21. package/lib/ql/infer.js +0 -2
  22. package/lib/req/request.js +3 -6
  23. package/lib/srv/middlewares/trace.js +2 -2
  24. package/lib/srv/protocols/hcql.js +44 -30
  25. package/lib/srv/protocols/http.js +60 -0
  26. package/lib/srv/protocols/index.js +0 -7
  27. package/lib/srv/protocols/odata-v4.js +8 -2
  28. package/lib/srv/srv-api.js +129 -62
  29. package/lib/srv/srv-handlers.js +0 -1
  30. package/lib/srv/srv-models.js +1 -0
  31. package/lib/utils/cds-test.js +1 -1
  32. package/lib/utils/cds-utils.js +26 -0
  33. package/lib/utils/check-version.js +10 -13
  34. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +22 -6
  35. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +3 -4
  36. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +89 -21
  37. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/boundToCQN.js +4 -2
  38. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +1 -24
  39. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/updateToCQN.js +1 -7
  40. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/ApplyParser.js +3 -3
  41. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/TrustedResourceJsonSerializer.js +7 -0
  42. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +0 -5
  43. package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +2 -0
  44. package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +17 -1
  45. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +22 -2
  46. package/libx/_runtime/cds-services/services/utils/columns.js +1 -2
  47. package/libx/_runtime/common/aspects/Association.js +17 -9
  48. package/libx/_runtime/common/generic/crud.js +13 -22
  49. package/libx/_runtime/common/generic/etag.js +1 -1
  50. package/libx/_runtime/common/generic/input.js +9 -1
  51. package/libx/_runtime/common/generic/paging.js +3 -3
  52. package/libx/_runtime/common/generic/sorting.js +25 -15
  53. package/libx/_runtime/common/generic/stream.js +2 -16
  54. package/libx/_runtime/common/utils/copy.js +5 -0
  55. package/libx/_runtime/common/utils/cqn.js +1 -1
  56. package/libx/_runtime/common/utils/cqn2cqn4sql.js +4 -3
  57. package/libx/_runtime/common/utils/csn.js +0 -49
  58. package/libx/_runtime/common/utils/foreignKeyPropagations.js +5 -5
  59. package/libx/_runtime/common/utils/generateOnCond.js +50 -25
  60. package/libx/_runtime/common/utils/resolveView.js +5 -44
  61. package/libx/_runtime/common/utils/rewriteAsterisks.js +17 -4
  62. package/libx/_runtime/common/utils/stream.js +16 -15
  63. package/libx/_runtime/common/utils/streamProp.js +25 -22
  64. package/libx/_runtime/db/Service.js +27 -8
  65. package/libx/_runtime/db/generic/input.js +6 -1
  66. package/libx/_runtime/db/generic/rewrite.js +3 -2
  67. package/libx/_runtime/db/query/read.js +15 -5
  68. package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +0 -11
  69. package/libx/_runtime/db/utils/columns.js +1 -0
  70. package/libx/_runtime/db/utils/stream.js +41 -0
  71. package/libx/_runtime/fiori/generic/read.js +2 -1
  72. package/libx/_runtime/fiori/generic/readOverDraft.js +1 -1
  73. package/libx/_runtime/fiori/lean-draft.js +216 -59
  74. package/libx/_runtime/hana/Service.js +1 -1
  75. package/libx/_runtime/hana/execute.js +53 -14
  76. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +34 -15
  77. package/libx/_runtime/remote/Service.js +2 -1
  78. package/libx/_runtime/remote/utils/client.js +1 -1
  79. package/libx/_runtime/sqlite/Service.js +1 -1
  80. package/libx/_runtime/sqlite/execute.js +17 -5
  81. package/libx/odata/afterburner.js +58 -19
  82. package/libx/odata/cqn2odata.js +6 -8
  83. package/libx/odata/create.js +44 -0
  84. package/libx/odata/delete.js +25 -0
  85. package/libx/odata/error.js +8 -3
  86. package/libx/odata/metadata.js +6 -8
  87. package/libx/odata/service-document.js +1 -1
  88. package/libx/odata/update.js +110 -0
  89. package/libx/odata/utils.js +9 -6
  90. package/libx/outbox/index.js +48 -78
  91. package/libx/rest/RestAdapter.js +0 -3
  92. package/package.json +1 -1
  93. package/lib/env/schemas/cds-package.json +0 -17
  94. package/lib/env/schemas/cds-rc.json +0 -740
  95. package/lib/ql/STREAM.js +0 -90
@@ -38,56 +38,6 @@ const hasPersistentOutbox = tenant => {
38
38
  return true
39
39
  }
40
40
 
41
- const isUnrecoverable = (service, error) => {
42
- let unrecoverable = service.isUnrecoverableError && service.isUnrecoverableError(error)
43
- if (unrecoverable === undefined) unrecoverable = error.unrecoverable
44
- return unrecoverable || isStandardError(error)
45
- }
46
-
47
- const processDefault = async (messages, { toBeDeleted, toBeUpdated, options, service }) => {
48
- /** throws if an emit failed due to a programming error
49
- * returns false if an emit failed due to temporary issues **/
50
- const run = async ({ ID, process }) => {
51
- try {
52
- await process()
53
- toBeDeleted.push(ID)
54
- } catch (e) {
55
- if (isStandardError(e)) {
56
- LOG.error(`${service.name}: Programming error detected:`, e)
57
- toBeDeleted.push(ID)
58
- throw new Error(`${service.name}: Programming error detected.`)
59
- }
60
- if (e.unrecoverable) {
61
- LOG.error(`${service.name}: Unrecoverable error:`, e)
62
- if (options.maxAttempts) {
63
- const _msg = { ID, attempts: options.maxAttempts }
64
- if (options.storeLastError !== false) _msg.lastError = e
65
- toBeUpdated.push(_msg)
66
- } else toBeDeleted.push(ID)
67
- } else {
68
- LOG.error(`${service.name}: Emit failed:`, e)
69
- const _msg = { ID }
70
- if (options.storeLastError !== false) _msg.lastError = e
71
- toBeUpdated.push(_msg)
72
- return false
73
- }
74
- }
75
- }
76
- if (options.parallel) {
77
- const first = messages.next()?.value // First try to see if message can be emitted
78
- if (first && (await run(first)) === false) return // No need to process the rest if the emit failed
79
- const res = await Promise.allSettled([...messages].map(run))
80
- const errors = res.filter(r => r.status === 'rejected').map(r => r.reason)
81
- if (errors.length) {
82
- throw new Error(`${service.name}: Programming errors detected.`)
83
- }
84
- } else {
85
- for (const msg of messages) {
86
- if ((await run(msg)) === false) break
87
- }
88
- }
89
- }
90
-
91
41
  const _safeJSONParse = string => {
92
42
  try {
93
43
  return string && JSON.parse(string)
@@ -142,36 +92,64 @@ const processMessages = async (service, tenant, _opts = {}) => {
142
92
  const user = new cds.User.Privileged(userId)
143
93
  if (!msg) continue
144
94
  const res = {
145
- process: () =>
146
- cds._context.run({ user, tenant }, async () => {
147
- try {
148
- return await service.handle(msg)
149
- } catch (e) {
150
- if (isUnrecoverable(service, e)) e.unrecoverable = true
151
- throw e
152
- }
153
- }),
154
95
  ID: _message.ID,
155
96
  msg,
156
- user,
157
- opts
97
+ user
158
98
  }
159
99
  yield res
160
100
  }
161
101
  }
162
102
 
163
- const process = service.options.outbox?.process || this.process || processDefault
164
103
  const toBeDeleted = []
165
104
  const toBeUpdated = []
166
105
  try {
167
- await process(messagesGen(), {
168
- toBeDeleted,
169
- toBeUpdated,
170
- service,
171
- options: opts
172
- })
106
+ const _handleWithErr = async ({ msg, user, ID }) => {
107
+ try {
108
+ await cds._context.run({ user, tenant }, async () => {
109
+ if (opts.handle) await opts.handle.call(service, msg)
110
+ else await service.handle(msg)
111
+ })
112
+ toBeDeleted.push(ID)
113
+ } catch (e) {
114
+ if (isStandardError(e)) {
115
+ LOG.error(`${service.name}: Programming error detected:`, e)
116
+ toBeDeleted.push(ID)
117
+ throw new Error(`${service.name}: Programming error detected.`)
118
+ }
119
+ if (e.unrecoverable) {
120
+ LOG.error(`${service.name}: Unrecoverable error:`, e)
121
+ if (opts.maxAttempts) {
122
+ const _msg = { ID, attempts: opts.maxAttempts }
123
+ if (opts.storeLastError !== false) _msg.lastError = e
124
+ toBeUpdated.push(_msg)
125
+ } else toBeDeleted.push(ID)
126
+ } else {
127
+ LOG.error(`${service.name}: Emit failed:`, e)
128
+ const _msg = { ID }
129
+ if (opts.storeLastError !== false) _msg.lastError = e
130
+ toBeUpdated.push(_msg)
131
+ return false
132
+ }
133
+ }
134
+ }
135
+ const messages = messagesGen()
136
+ // REVISIT: Maybe we can also support handleMany and provide the iterator (for batch processing)
137
+ if (opts.parallel) {
138
+ const first = messages.next()?.value // First try to see if message can be emitted
139
+ if (!(first && (await _handleWithErr(first)) === false)) { // No need to process the rest if the first emit failed
140
+ const res = await Promise.allSettled([...messages].map(_handleWithErr))
141
+ const errors = res.filter(r => r.status === 'rejected').map(r => r.reason)
142
+ if (errors.length) {
143
+ throw new Error(`${service.name}: Programming errors detected.`)
144
+ }
145
+ }
146
+ } else {
147
+ for (const msg of messages) {
148
+ if ((await _handleWithErr(msg)) === false) break
149
+ }
150
+ }
173
151
  } catch (e) {
174
- if (opts.crashOnError !== false) letAppCrash = true
152
+ letAppCrash = true
175
153
  }
176
154
 
177
155
  const queries = []
@@ -250,13 +228,6 @@ const writeInOutbox = async (name, msg, context) => {
250
228
  return cds.tx(context).run(INSERT.into(messagesEntity).entries(outboxMsg))
251
229
  }
252
230
 
253
- // REVIST: Should we also support the following API?
254
- // cds.outboxed(srv, {
255
- // onInsert(msg){ ... }
256
- // onForward(msg){ ... }
257
- // onProcess(msgs){ ... }
258
- // })
259
-
260
231
  function unboxed(srv) {
261
232
  return srv[$unboxed] || srv
262
233
  }
@@ -303,8 +274,7 @@ function outboxed(srv, customOpts) {
303
274
  else await originalSrv.emit(req)
304
275
  } catch (e) {
305
276
  LOG.error('Emit failed', { event: req.event, cause: e })
306
- // opts.crashOnError is not official!!!
307
- if (isUnrecoverable(originalSrv, e) && outboxOpts.crashOnError !== false) cds.exit(1)
277
+ if (isStandardError(e)) cds.exit(1)
308
278
  }
309
279
  })
310
280
  }
@@ -16,7 +16,6 @@ const payload_factory = require('./middleware/payload')
16
16
  const error_factory = require('./middleware/error')
17
17
 
18
18
  const { bufferToBase64 } = require('../_runtime/common/utils/binary')
19
- const { alias2ref } = require('../_runtime/common/utils/csn')
20
19
  const { getAccessRestrictions } = require('../_runtime/common/utils/restrictions')
21
20
 
22
21
  const RestAdapter = function (srv) {
@@ -24,8 +23,6 @@ const RestAdapter = function (srv) {
24
23
  const input = input_factory(srv)
25
24
  const payload = payload_factory(srv)
26
25
 
27
- alias2ref(srv)
28
-
29
26
  const router = express.Router()
30
27
 
31
28
  // -----------------------------------------------------------------------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/cds",
3
- "version": "7.5.2",
3
+ "version": "7.6.1",
4
4
  "description": "SAP Cloud Application Programming Model - CDS for Node.js",
5
5
  "homepage": "https://cap.cloud.sap/",
6
6
  "keywords": [
@@ -1,17 +0,0 @@
1
- {
2
- "title": "JSON schema for CDS configuration in package.json",
3
- "$schema": "https://json-schema.org/draft/2020-12/schema",
4
- "description": "This is a JSON schema representation of the CDS project configuration inside a project root level package.json",
5
- "type": "object",
6
- "properties": {
7
- "extends": {
8
- "description": "Name of the application that shall be extended",
9
- "type": "string"
10
- },
11
- "cds": {
12
- "$ref": "cdsJsonSchema://schemas/cds-rc.json",
13
- "description": "CDS configuration",
14
- "default": {}
15
- }
16
- }
17
- }