@sap/cds 7.9.2 → 8.0.3

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 (279) hide show
  1. package/CHANGELOG.md +139 -3656
  2. package/_i18n/i18n_en_US_saptrc.properties +113 -0
  3. package/_i18n/i18n_zh_CN.properties +7 -4
  4. package/app/index.css +129 -0
  5. package/app/index.html +16 -64
  6. package/app/index.js +14 -9
  7. package/bin/args.js +34 -0
  8. package/bin/serve.js +18 -24
  9. package/bin/test.js +97 -0
  10. package/common.cds +5 -12
  11. package/eslint.config.mjs +133 -0
  12. package/lib/auth/basic-auth.js +16 -20
  13. package/lib/auth/dummy-auth.js +1 -1
  14. package/lib/auth/ias-auth.js +12 -30
  15. package/lib/auth/index.js +1 -14
  16. package/lib/auth/jwt-auth.js +14 -30
  17. package/lib/compile/cds-compile.js +1 -2
  18. package/lib/compile/cdsc.js +21 -26
  19. package/lib/compile/etc/_localized.js +1 -6
  20. package/lib/compile/etc/csv.js +1 -1
  21. package/lib/compile/etc/properties.js +1 -1
  22. package/lib/compile/for/java.js +1 -1
  23. package/lib/compile/for/lean_drafts.js +4 -6
  24. package/lib/compile/for/nodejs.js +1 -1
  25. package/lib/compile/parse.js +4 -0
  26. package/lib/compile/resolve.js +4 -4
  27. package/lib/compile/to/edm-files.js +16 -23
  28. package/lib/compile/to/hana.js +27 -0
  29. package/lib/compile/to/json.js +1 -1
  30. package/lib/compile/to/sql.js +5 -1
  31. package/lib/compile/to/srvinfo.js +1 -1
  32. package/lib/compile/to/yaml.js +3 -3
  33. package/lib/dbs/cds-deploy.js +4 -2
  34. package/lib/env/cds-env.js +10 -14
  35. package/lib/env/cds-requires.js +29 -13
  36. package/lib/env/defaults.js +46 -16
  37. package/lib/env/plugins.js +1 -1
  38. package/lib/env/schemas/cds-rc.js +8 -4
  39. package/lib/env/schemas/index.js +7 -7
  40. package/lib/env/serviceBindings.js +1 -1
  41. package/lib/index.js +12 -10
  42. package/lib/lazy.js +1 -1
  43. package/lib/linked/classes.js +36 -8
  44. package/lib/linked/entities.js +2 -10
  45. package/lib/linked/models.js +2 -1
  46. package/lib/linked/validate.js +292 -0
  47. package/lib/log/cds-error.js +0 -6
  48. package/lib/log/cds-log.js +3 -3
  49. package/lib/log/format/json.js +1 -1
  50. package/lib/log/service/index.js +0 -1
  51. package/lib/plugins.js +3 -3
  52. package/lib/ql/Query.js +2 -10
  53. package/lib/ql/SELECT.js +1 -1
  54. package/lib/ql/Whereable.js +3 -2
  55. package/lib/req/cds-context.js +14 -25
  56. package/lib/req/context.js +23 -25
  57. package/lib/req/request.js +1 -34
  58. package/lib/req/user.js +47 -35
  59. package/lib/srv/bindings.js +1 -1
  60. package/lib/srv/cds-connect.js +4 -4
  61. package/lib/srv/cds-serve.js +2 -2
  62. package/lib/srv/factory.js +1 -1
  63. package/lib/srv/middlewares/cds-context.js +11 -22
  64. package/lib/srv/middlewares/ctx-model.js +2 -3
  65. package/lib/srv/middlewares/errors.js +41 -8
  66. package/lib/srv/middlewares/index.js +3 -3
  67. package/lib/srv/middlewares/trace.js +0 -2
  68. package/lib/srv/protocols/hcql.js +15 -10
  69. package/lib/srv/protocols/http.js +44 -49
  70. package/lib/srv/protocols/index.js +1 -23
  71. package/lib/srv/protocols/odata-v4.js +12 -74
  72. package/lib/srv/protocols/rest.js +1 -13
  73. package/lib/srv/srv-api.js +0 -20
  74. package/lib/srv/srv-dispatch.js +3 -2
  75. package/lib/srv/srv-handlers.js +22 -11
  76. package/lib/srv/srv-methods.js +2 -2
  77. package/lib/srv/srv-models.js +3 -36
  78. package/lib/test/expect.js +343 -0
  79. package/lib/test/index.js +2 -0
  80. package/lib/test/reporter.js +176 -0
  81. package/lib/utils/axios.js +10 -9
  82. package/lib/utils/cds-test.js +86 -37
  83. package/lib/utils/cds-utils.js +54 -7
  84. package/lib/utils/check-version.js +0 -4
  85. package/lib/utils/colors.js +49 -0
  86. package/lib/utils/data.js +5 -4
  87. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +2 -7
  88. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +3 -30
  89. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +6 -12
  90. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +1 -3
  91. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +0 -1
  92. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +4 -7
  93. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +12 -6
  94. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +2 -4
  95. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/applyToCQN.js +1 -0
  96. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +1 -1
  97. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +0 -1
  98. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +1 -3
  99. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +1 -1
  100. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/edm/AbstractEdmStructuredType.js +1 -2
  101. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/ResourceJsonDeserializer.js +5 -0
  102. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/serializer/ContextURLFactory.js +1 -1
  103. package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +9 -43
  104. package/libx/_runtime/cds-services/adapter/odata-v4/utils/metaInfo.js +0 -1
  105. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +8 -3
  106. package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +4 -2
  107. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +1 -3
  108. package/libx/_runtime/cds-services/util/assert.js +1 -1
  109. package/libx/_runtime/cds.js +10 -3
  110. package/libx/_runtime/common/Service.js +12 -32
  111. package/libx/_runtime/common/aspects/any.js +1 -0
  112. package/libx/_runtime/common/code-ext/execute.js +1 -1
  113. package/libx/_runtime/common/code-ext/worker.js +0 -1
  114. package/libx/_runtime/common/composition/data.js +0 -1
  115. package/libx/_runtime/common/composition/delete.js +0 -1
  116. package/libx/_runtime/common/composition/insert.js +2 -2
  117. package/libx/_runtime/common/composition/tree.js +0 -1
  118. package/libx/_runtime/common/composition/update.js +3 -3
  119. package/libx/_runtime/common/error/frontend.js +21 -12
  120. package/libx/_runtime/common/error/log.js +36 -0
  121. package/libx/_runtime/common/error/utils.js +2 -5
  122. package/libx/_runtime/common/generic/auth/autoexpose.js +18 -17
  123. package/libx/_runtime/common/generic/auth/expand.js +1 -1
  124. package/libx/_runtime/common/generic/auth/readOnly.js +1 -2
  125. package/libx/_runtime/common/generic/auth/restrict.js +23 -42
  126. package/libx/_runtime/common/generic/auth/restrictions.js +2 -7
  127. package/libx/_runtime/common/generic/auth/utils.js +91 -88
  128. package/libx/_runtime/common/generic/crud.js +6 -5
  129. package/libx/_runtime/common/generic/etag.js +7 -12
  130. package/libx/_runtime/common/generic/input.js +70 -68
  131. package/libx/_runtime/common/generic/paging.js +1 -0
  132. package/libx/_runtime/common/generic/sorting.js +1 -0
  133. package/libx/_runtime/common/generic/temporal.js +8 -2
  134. package/libx/_runtime/common/i18n/index.js +1 -1
  135. package/libx/_runtime/common/i18n/messages.properties +3 -1
  136. package/libx/_runtime/common/utils/binary.js +8 -2
  137. package/libx/_runtime/common/utils/compareJson.js +5 -1
  138. package/libx/_runtime/common/utils/copy.js +6 -11
  139. package/libx/_runtime/common/utils/cqn2cqn4sql.js +16 -14
  140. package/libx/_runtime/common/utils/differ.js +3 -6
  141. package/libx/_runtime/common/utils/keys.js +77 -18
  142. package/libx/_runtime/common/utils/postProcess.js +12 -15
  143. package/libx/_runtime/common/utils/propagateForeignKeys.js +0 -1
  144. package/libx/_runtime/common/utils/resolveView.js +2 -3
  145. package/libx/_runtime/common/utils/restrictions.js +45 -17
  146. package/libx/_runtime/common/utils/rewriteAsterisks.js +1 -8
  147. package/libx/_runtime/common/utils/stream.js +3 -16
  148. package/libx/_runtime/common/utils/streamProp.js +8 -18
  149. package/libx/_runtime/common/utils/structured.js +1 -1
  150. package/libx/_runtime/common/utils/ucsn.js +0 -2
  151. package/libx/_runtime/db/Service.js +0 -72
  152. package/libx/_runtime/db/data-conversion/post-processing.js +0 -1
  153. package/libx/_runtime/db/expand/expandCQNToJoin.js +9 -9
  154. package/libx/_runtime/db/expand/rawToExpanded.js +0 -8
  155. package/libx/_runtime/db/generic/input.js +3 -8
  156. package/libx/_runtime/db/generic/rewrite.js +27 -4
  157. package/libx/_runtime/db/query/read.js +2 -2
  158. package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +0 -1
  159. package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -1
  160. package/libx/_runtime/db/utils/columns.js +2 -6
  161. package/libx/_runtime/fiori/lean-draft.js +138 -56
  162. package/libx/_runtime/hana/Service.js +0 -1
  163. package/libx/_runtime/hana/driver.js +1 -1
  164. package/libx/_runtime/hana/dynatrace.js +1 -2
  165. package/libx/_runtime/hana/pool.js +11 -21
  166. package/libx/_runtime/hana/streaming.js +0 -1
  167. package/libx/_runtime/messaging/common-utils/AMQPClient.js +0 -1
  168. package/libx/_runtime/messaging/common-utils/authorizedRequest.js +1 -1
  169. package/libx/_runtime/messaging/common-utils/normalizeIncomingMessage.js +1 -1
  170. package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +1 -1
  171. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +19 -33
  172. package/libx/_runtime/messaging/event-broker.js +0 -12
  173. package/libx/_runtime/messaging/file-based.js +3 -3
  174. package/libx/_runtime/messaging/http-utils/token.js +1 -1
  175. package/libx/_runtime/messaging/kafka.js +2 -2
  176. package/libx/_runtime/messaging/redis-messaging.js +0 -1
  177. package/libx/_runtime/remote/Service.js +25 -25
  178. package/libx/_runtime/remote/utils/client.js +4 -5
  179. package/libx/_runtime/remote/utils/cloudSdkProvider.js +0 -3
  180. package/libx/_runtime/remote/utils/data.js +0 -1
  181. package/libx/_runtime/sqlite/Service.js +1 -2
  182. package/libx/_runtime/ucl/Service.js +37 -78
  183. package/libx/common/assert/index.js +22 -21
  184. package/libx/common/assert/type-relaxed.js +39 -0
  185. package/libx/common/assert/utils.js +3 -2
  186. package/libx/common/assert/validation.js +3 -8
  187. package/libx/common/utils/index.js +5 -0
  188. package/libx/common/utils/path.js +51 -0
  189. package/libx/odata/ODataAdapter.js +126 -0
  190. package/libx/odata/index.js +15 -2
  191. package/libx/odata/middleware/batch.js +261 -72
  192. package/libx/odata/middleware/body-parser.js +33 -0
  193. package/libx/odata/middleware/create.js +44 -59
  194. package/libx/odata/middleware/delete.js +23 -12
  195. package/libx/odata/middleware/error.js +30 -6
  196. package/libx/odata/middleware/metadata.js +38 -26
  197. package/libx/odata/middleware/operation.js +93 -69
  198. package/libx/odata/middleware/parse.js +6 -8
  199. package/libx/odata/middleware/read.js +117 -93
  200. package/libx/odata/middleware/service-document.js +22 -19
  201. package/libx/odata/middleware/stream.js +54 -56
  202. package/libx/odata/middleware/update.js +79 -87
  203. package/libx/odata/parse/afterburner.js +191 -175
  204. package/libx/odata/parse/cqn2odata.js +8 -8
  205. package/libx/odata/parse/grammar.peggy +27 -20
  206. package/libx/odata/parse/multipartToJson.js +17 -9
  207. package/libx/odata/parse/parser.js +1 -1
  208. package/libx/odata/utils/etag.js +14 -6
  209. package/libx/odata/utils/index.js +84 -12
  210. package/libx/odata/utils/metadata.js +161 -0
  211. package/libx/odata/utils/postProcess.js +89 -0
  212. package/libx/odata/utils/readAfterWrite.js +134 -17
  213. package/libx/odata/utils/result.js +36 -142
  214. package/libx/outbox/index.js +5 -4
  215. package/libx/rest/RestAdapter.js +115 -182
  216. package/libx/rest/middleware/create.js +28 -24
  217. package/libx/rest/middleware/delete.js +7 -10
  218. package/libx/rest/middleware/error.js +19 -16
  219. package/libx/rest/middleware/operation.js +48 -41
  220. package/libx/rest/middleware/parse.js +128 -126
  221. package/libx/rest/middleware/read.js +20 -27
  222. package/libx/rest/middleware/update.js +26 -31
  223. package/package.json +16 -12
  224. package/server.js +4 -2
  225. package/tasks/enterprise-messaging-deploy.js +1 -1
  226. package/apis/cds.d.ts +0 -3
  227. package/apis/core.d.ts +0 -21
  228. package/apis/cqn.d.ts +0 -18
  229. package/apis/csn.d.ts +0 -21
  230. package/apis/events.d.ts +0 -18
  231. package/apis/internal/inference.d.ts +0 -18
  232. package/apis/linked.d.ts +0 -18
  233. package/apis/log.d.ts +0 -20
  234. package/apis/models.d.ts +0 -18
  235. package/apis/ql.d.ts +0 -18
  236. package/apis/reflect.d.ts +0 -32
  237. package/apis/server.d.ts +0 -18
  238. package/apis/services.d.ts +0 -22
  239. package/bin/cds-serve.js +0 -56
  240. package/lib/compile/to/gql.js +0 -15
  241. package/lib/srv/protocols/_legacy.js +0 -44
  242. package/lib/utils/jest.js +0 -43
  243. package/libx/_runtime/auth/index.js +0 -193
  244. package/libx/_runtime/auth/strategies/JWT.js +0 -37
  245. package/libx/_runtime/auth/strategies/basic.js +0 -20
  246. package/libx/_runtime/auth/strategies/dummy.js +0 -14
  247. package/libx/_runtime/auth/strategies/ias-auth.js +0 -1
  248. package/libx/_runtime/auth/strategies/mock.js +0 -77
  249. package/libx/_runtime/auth/strategies/xssecUtils.js +0 -93
  250. package/libx/_runtime/auth/strategies/xsuaa.js +0 -38
  251. package/libx/_runtime/common/perf/index.js +0 -19
  252. package/libx/_runtime/common/utils/ensureIEEE754.js +0 -29
  253. package/libx/_runtime/fiori/draft.js +0 -2
  254. package/libx/_runtime/fiori/generic/activate.js +0 -190
  255. package/libx/_runtime/fiori/generic/before.js +0 -201
  256. package/libx/_runtime/fiori/generic/cancel.js +0 -19
  257. package/libx/_runtime/fiori/generic/delete.js +0 -21
  258. package/libx/_runtime/fiori/generic/edit.js +0 -157
  259. package/libx/_runtime/fiori/generic/index.js +0 -25
  260. package/libx/_runtime/fiori/generic/new.js +0 -82
  261. package/libx/_runtime/fiori/generic/patch.js +0 -101
  262. package/libx/_runtime/fiori/generic/prepare.js +0 -57
  263. package/libx/_runtime/fiori/generic/read.js +0 -1340
  264. package/libx/_runtime/fiori/generic/readOverDraft.js +0 -146
  265. package/libx/_runtime/fiori/utils/csn.js +0 -13
  266. package/libx/_runtime/fiori/utils/delete.js +0 -114
  267. package/libx/_runtime/fiori/utils/handler.js +0 -264
  268. package/libx/_runtime/fiori/utils/lockInfo.js +0 -27
  269. package/libx/_runtime/fiori/utils/req.js +0 -23
  270. package/libx/_runtime/fiori/utils/stream.js +0 -36
  271. package/libx/_runtime/fiori/utils/where.js +0 -254
  272. package/libx/_runtime/index.js +0 -22
  273. package/libx/odata/utils/handler.js +0 -120
  274. package/libx/odata/utils/metaInfo.js +0 -410
  275. package/libx/odata/utils/path.js +0 -75
  276. package/libx/rest/RestRequest.js +0 -32
  277. package/libx/rest/index.js +0 -3
  278. package/libx/rest/readme.md +0 -1
  279. /package/libx/common/assert/{type.js → type-strict.js} +0 -0
@@ -0,0 +1,176 @@
1
+ const { BRIGHT, BOLD, INVERT, GRAY, GREEN, RESET, LF='\n', DIMMED } = require('../utils/colors')
2
+ const YELLOW = '\x1b[38;5;220m'
3
+ const RED = '\x1b[38;5;160m'
4
+ const PASS = '\x1b[38;5;244m'
5
+ const FAIL = '\x1b[38;5;244m' // '\x1b[38;5;124m'
6
+ const SKIP = RESET+DIMMED // '\x1b[38;5;244m' // '\x1b[38;5;124m'
7
+ const { inspect } = require('node:util')
8
+ /* eslint-disable no-console */
9
+
10
+ module.exports = function report_on (test,o) {
11
+
12
+ const files = o.files
13
+ const suites = { passed:[], failed:[] }
14
+ const tests = { passed:0, failed:0, todo:0, skipped:0, recent:null }
15
+
16
+ // monkey-patch test.on to support filter functions like root, leaf, any
17
+ const {on} = test; test.on = (eve,filter,fn) => on.call (test, 'test:'+eve, !fn ? fn = filter : x => filter(x) && fn(x))
18
+ const root = x => !x.nesting && x.name.endsWith('.js')
19
+ const leaf = x => x.name[0] !== '<' && x.details?.type !== 'suite'
20
+ const any = x => x.name[0] !== '<'
21
+ const _indent4 = x => ' '.repeat (x.nesting + root(x))
22
+
23
+ // add handlers according to options
24
+ if (o.debug ??= process.env.debug) return debug(o.debug) // eslint-disable-line no-cond-assign
25
+ if (o.verbose || !o.silent && files.length < 2) verbose(); else silent()
26
+ if (o.unmute) unmute()
27
+ common()
28
+ return test
29
+
30
+
31
+ /**
32
+ * Adds common handlers to report test results.
33
+ * Used in silent mode as well as verbose mode.
34
+ */
35
+ function common() {
36
+
37
+ test.on ('pass', leaf, x => {
38
+ x.skip ? tests.skipped++ : x.todo ? tests.todo++ : tests.passed++
39
+ })
40
+
41
+ test.on ('fail', x => {
42
+ if (x.details.error.failureType in { subtestsFailed:1, cancelledByParent: 2 }) return
43
+ tests.failed++
44
+ if (o.silent) console.log(_indent4(x), BOLD + RED, 'X' + RESET+GRAY, x.name, RESET)
45
+ if (o.quiet) return
46
+ let err = x.details.error.cause || x.details.error
47
+ let msg = typeof err === 'string' ? err : inspect (err, { colors:true, depth:11 })
48
+ console.log(RESET)
49
+ console.log(msg
50
+ .replace(/\n.*cds\/lib\/test\/expect.js:.*\)/g,'')
51
+ .replace(/\n.*\(node:.*/g,'')
52
+ .replace(/^/gm, _indent4(x)+' ')
53
+ )
54
+ if (!err.message && !o.unmute)
55
+ console.log(' ', INVERT+YELLOW, 'NOTE', RESET+YELLOW, '--unmute app log output to see error details.', RESET )
56
+ console.log(RESET)
57
+ })
58
+
59
+ test.on ('complete', root, x => {
60
+ (x.details.passed ? suites.passed : suites.failed) .push (x.file)
61
+ })
62
+
63
+ test.once ('fail', ()=> process.exitCode = 1)
64
+ process.on('exit', summary)
65
+ }
66
+
67
+
68
+ /**
69
+ * Adds handlers to report test results on root-level only,
70
+ * i.e., on test file level.
71
+ */
72
+ function silent() {
73
+ console.log() // start with an initial blank line
74
+ test.on ('complete', root, x => {
75
+ if (x.details.passed) console.log (GREEN,' ✔', RESET+PASS, x.name)
76
+ else console.log (BRIGHT+RED,' X', RESET+RED, x.name, RESET)
77
+ })
78
+ }
79
+
80
+
81
+ /**
82
+ * Adds handlers to report test results in detail,
83
+ * i.e., on nested tests level.
84
+ */
85
+ function verbose() {
86
+
87
+ // report tests on file level
88
+ let i=0
89
+ if (files.length > 1 || files[0] !== process.argv[2] && files[0] !== process.argv[3]) // if not only one completely specified test file
90
+ test.on ('dequeue', x => x.name === '<next>' && console.log (LF+GRAY+'—'.repeat(77)+BRIGHT, LF+ files[i++], RESET))
91
+
92
+ // report test suites (i.e, describe/suite/test with subtests)
93
+ let _recent = null, _recent_nesting = 0 // to add newlines before outer leaf tests following a suite
94
+ test.on ('start', any, x => {
95
+ if (_recent) {
96
+ console.log(LF+_indent4(_recent), '', _recent.name)
97
+ _recent_nesting = x.nesting
98
+ }
99
+ _recent = x
100
+ })
101
+
102
+ // report passed tests on leaf level
103
+ test.on ('pass', leaf, x => {
104
+ if (_recent_nesting > x.nesting && leaf(x)) console.log()
105
+ x.skip ? console.log(_indent4(x), YELLOW, '○' + SKIP, x.name, RESET) :
106
+ x.todo ? console.log(_indent4(x), YELLOW, '+' + SKIP, x.name, RESET) :
107
+ /*pass*/ console.log(_indent4(x), GREEN, '✔' + PASS, x.name, RESET)
108
+ _recent_nesting = _recent?.nesting
109
+ _recent = null
110
+ })
111
+
112
+ // report failed tests on leaf level
113
+ test.on ('fail', leaf, x => {
114
+ if (_recent_nesting > x.nesting && leaf(x)) console.log()
115
+ console.log(_indent4(x), BOLD+RED, 'X' + RESET+FAIL, x.name, RESET)
116
+ _recent_nesting = _recent?.nesting
117
+ _recent = null
118
+ })
119
+ }
120
+
121
+
122
+ /**
123
+ * Adds handlers to pipe stdout and stderr of the tests themselves
124
+ * or the app servers started in there.
125
+ */
126
+ function unmute() {
127
+ test.on ('stdout', x => process.stdout.write(x.message))
128
+ test.on ('stderr', x => process.stderr.write(x.message))
129
+ }
130
+
131
+
132
+ /**
133
+ * Adds handlers to debug test stream events.
134
+ */
135
+ function debug (events) {
136
+ inspect.defaultOptions.depth = 11
137
+ if (events === 'all') events = 'enqueue,dequeue,start,pass,fail,complete,error'
138
+ for (let eve of events.split(',')) test.on (eve, x => {
139
+ if (x.details) x.details = { ...x.details }
140
+ // delete x.testNumber
141
+ // delete x.details
142
+ // delete x.file
143
+ // delete x.line
144
+ // delete x.column
145
+ console.log(INVERT + YELLOW, eve, RESET, { ...x })
146
+ })
147
+ }
148
+
149
+
150
+ /**
151
+ * Prints the summary of passed, skipped, failed tests.
152
+ */
153
+ function summary () {
154
+ const time = (performance.now() / 1000).toFixed(3)
155
+ console.log(
156
+ report ('passed', BOLD+GREEN) +
157
+ report ('failed', BOLD+RED) +
158
+ report ('skipped', YELLOW) +
159
+ report ('todo', YELLOW) +
160
+ `\n${PASS} ${time}s ${RESET}\n`
161
+ )
162
+ function report (kind, color) {
163
+ const t = tests[kind], s = suites[kind]?.length || 0
164
+ if (t == 0) return ''
165
+ if (s == 0 || files.length == 1) return LF+`${color} ${t} ${kind} ${RESET}`
166
+ else return LF+`${color} ${t} in ${s} suite${s==1?'':'s'} ${kind} ${RESET}`
167
+ }
168
+ const _recent = require('os').userInfo().homedir + '/.cds-test-recent.json'
169
+ const recent = require('fs').existsSync(_recent) ? require(_recent) : {}
170
+ if (!o.recent && !o.passed && !o.failed) recent.options = {...o, argv:process.argv.slice(2) }
171
+ if (!o.failed) recent.passed = suites.passed // only update recent.passed if not called w/ --failed
172
+ if (!o.passed) recent.failed = suites.failed // only update recent.failed if not called w/ --passed
173
+ require('fs').writeFileSync(_recent, JSON.stringify(recent,null,2))
174
+ }
175
+
176
+ }
@@ -1,7 +1,6 @@
1
1
  const http = require('http')
2
2
  class Axios {
3
3
  get axios() {
4
- // eslint-disable-next-line cds/no-missing-dependencies
5
4
  const axios = require('axios').create ({
6
5
  headers: { 'Content-Type': 'application/json' },
7
6
  httpAgent: new http.Agent({ keepAlive: false}),
@@ -44,18 +43,20 @@ const _args = (args) => {
44
43
  }
45
44
 
46
45
  const _error = (e) => {
47
- Error.captureStackTrace (e,_error) //> adds the stack trace from caller code
48
- if (e.errors) e = e.errors[0] // Node 20 sends AggregationErros
46
+ if (e.errors) e = e.errors[0] // Node 20 sends AggregationErrors
49
47
  if (e.code && e.port === 80 /* default port */) throw Object.assign (e, {
50
48
  message: e.message + '\nIt seems that the server was not started. Make sure to call \'cds.test(...)\' or \'cds.test.run(...)\'.',
51
49
  stack: null // stack is just clutter here
52
50
  })
53
- const { code, message } = e.response && e.response.data && e.response.data.error || {}
54
- if (message) e.message = code && code !== 'null' ? `${code} - ${message}` : message
55
- // Promote toJSON from prototype to own property to make it iterable
56
- // eslint-disable-next-line no-self-assign
57
- if (typeof jest !== 'undefined') e.toJSON = e.toJSON // REVISIT: what is this for?
58
- throw e
51
+ // Create new instance of Error to overcome AxiosError's inferior and cluttered output
52
+ const err = new Error (e.message); err.code = e.code
53
+ Object.defineProperty (err, 'response', { value: e.response, enumerable:false })
54
+ // Add original error thrown by the service, if exists
55
+ const o = err.response?.data?.error ; if (!o) throw err
56
+ err.message = !o.code || o.code == 'null' ? o.message : `${o.code} - ${o.message}`
57
+ err.cause = o instanceof Error ? o : Object.assign (new Error, o)
58
+ // Object.defineProperty (o, 'stack', { enumerable:false }) //> allow strict equal checks against {code,message}
59
+ throw err
59
60
  }
60
61
 
61
62
  const _ = Axios.prototype // eslint-disable-line no-unused-vars
@@ -1,29 +1,3 @@
1
- // Provide same global functions for jest and mocha
2
- ;(function _support_jest_and_mocha() {
3
- const is_jest = !!global.beforeAll
4
- const is_mocha = !!global.before
5
- if (is_mocha) {
6
- global.beforeAll = global.before
7
- global.afterAll = global.after
8
- global.test = global.it
9
- // Adding test.each() and describe.each() to mocha
10
- const { format } = require('util')
11
- for (let td of [ 'test', 'describe' ]) global[td].each = function(table) {
12
- return (msg,fn) => Promise.all (table.map (each => {
13
- if (!Array.isArray(each)) each = [each]
14
- return this (format(msg,...each), ()=> fn(...each))
15
- }))
16
- }
17
- } else if (is_jest) { // it's jest
18
- global.before = (msg,fn) => global.beforeAll(fn||msg)
19
- global.after = (msg,fn) => global.afterAll(fn||msg)
20
- } else { // it's none of both
21
- global.beforeAll = global.before = (msg,fn) => (fn||msg)()
22
- global.afterAll = global.after = (msg,fn) => global.cds?.repl?.on('exit',fn||msg)
23
- global.beforeEach = global.afterEach = ()=>{}
24
- }
25
- })()
26
-
27
1
  /**
28
2
  * Instances of this class are constructed and returned by cds.test().
29
3
  */
@@ -86,7 +60,7 @@ class Test extends require('./axios') {
86
60
  const path = require('path')
87
61
  folder = isdir (path.resolve (cds.root, folder, ...paths))
88
62
  || path.join (require.resolve (folder+'/package.json').slice(0,-13), ...paths)
89
- } catch(e) {
63
+ } catch {
90
64
  throw cds.error (`No such folder or package '${process.cwd()}' -> '${folder}'`)
91
65
  }
92
66
  // Check if cds.env was loaded before running cds.test in different folder
@@ -135,7 +109,7 @@ class Test extends require('./axios') {
135
109
  /**
136
110
  * Captures console.log output.
137
111
  */
138
- log (_capture, afterEach = global.afterEach) {
112
+ log (_capture) {
139
113
  const {console} = global, {format} = require('util')
140
114
  const log = { output: '' }
141
115
  beforeAll(()=> global.console = { __proto__: console,
@@ -155,7 +129,19 @@ class Test extends require('./axios') {
155
129
  /**
156
130
  * Silences all console log output, e.g.: CDS_TEST_SILENT=y jest/mocha ...
157
131
  */
158
- silent(){ this.log(()=>{},()=>{}); return this }
132
+ silent(){
133
+ global.console = { __proto__: console,
134
+ log: ()=>{},
135
+ info: ()=>{},
136
+ warn: ()=>{},
137
+ debug: ()=>{},
138
+ trace: ()=>{},
139
+ error: ()=>{},
140
+ time: ()=>{},
141
+ timeEnd: ()=>{},
142
+ }
143
+ return this
144
+ }
159
145
  /** @deprecated */ verbose(){ return this }
160
146
 
161
147
 
@@ -163,25 +149,88 @@ class Test extends require('./axios') {
163
149
  * Lazily loads and returns an instance of chai
164
150
  */
165
151
  get chai() {
166
- let chai = require('chai') // eslint-disable-line cds/no-missing-dependencies
167
- chai.use (require('chai-subset')) // eslint-disable-line cds/no-missing-dependencies
168
- chai.use (require('chai-as-promised')) // eslint-disable-line cds/no-missing-dependencies
152
+ let chai = require('chai')
153
+ chai.use (require('chai-subset'))
154
+ chai.use (require('chai-as-promised'))
169
155
  return chai
170
156
  function require (mod) { try { return module.require(mod) } catch(e) {
171
157
  if (e.code === 'MODULE_NOT_FOUND') throw new Error (`
172
158
  Failed to load required package '${mod}'. Please add it thru:
173
- npm add -D chai@4 chai-as-promised chai-subset
159
+ npm add -D chai@4 chai-as-promised@7 chai-subset
174
160
  `)}}
175
161
  }
176
- get assert() { return this.chai.assert }
162
+ set expect(x) { super.expect = x }
177
163
  get expect() { return this.chai.expect }
164
+ get assert() { return this.chai.assert }
178
165
  get should() { return this.chai.should() }
179
166
  }
180
167
 
181
168
 
182
169
  /** @type Test & ()=>Test */
183
- const cds_test = module.exports = Object.assign ((..._) => (new Test).run(..._), { Test })
170
+ module.exports = exports = Object.assign ((..._) => (new Test).run(..._), { Test })
184
171
 
185
172
  // Set prototype to allow usages like cds.test.in(), cds.test.log(), ...
186
- Object.setPrototypeOf (cds_test, Test.prototype)
187
- if (process.env.CDS_TEST_SILENT) cds_test.silent()
173
+ Object.setPrototypeOf (exports, Test.prototype)
174
+
175
+
176
+ // Provide same global functions for jest and mocha
177
+ ;(function _support_jest_and_mocha() {
178
+ const _global = p => Object.getOwnPropertyDescriptor(global,p)?.value
179
+ const is_jest = _global('beforeAll')
180
+ const is_mocha = _global('before')
181
+ const repl = global.cds?.repl || process.env.CDS_TEST_FAKE // for crazy forks in some cds-dk and mtxs tests ;)
182
+ if (repl) { // it's cds repl
183
+
184
+ global.beforeAll = global.before = (msg,fn) => (fn||msg)()
185
+ global.afterAll = global.after = (msg,fn) => repl.on?.('exit',fn||msg)
186
+ global.beforeEach = global.afterEach = ()=>{}
187
+ global.describe = ()=>{}
188
+ exports.expect = global.expect = require('../test/expect')
189
+
190
+ } else if (is_mocha) { // it's mocha
191
+
192
+ global.describe.each = global.it.each = each
193
+ global.beforeAll = before
194
+ global.afterAll = after
195
+ global.test = it
196
+ global.xtest = test.skip
197
+ global.xdescribe = describe.skip
198
+ process.env.CDS_TEST_SILENT == 'false' || exports.silent()
199
+
200
+ } else if (is_jest) { // it's jest
201
+
202
+ global.before = (msg,fn) => global.beforeAll(fn||msg)
203
+ global.after = (msg,fn) => global.afterAll(fn||msg)
204
+
205
+ } else { // it's node --test
206
+
207
+ const { describe, suite, test, before, after, beforeEach, afterEach } = require('node:test')
208
+ describe.each = test.each = describe.skip.each = test.skip.each = each
209
+ global.describe = describe; global.xdescribe = describe.skip
210
+ global.test = global.it = test; global.xtest = test.skip
211
+ global.beforeAll = global.before = (msg,fn=msg) => {
212
+ if (fn.length > 0) { const f = fn; fn = (_,done)=>f(done) }
213
+ return before(fn) // doesn't work for some reason
214
+ }
215
+ // global.beforeAll = global.before = (msg,fn) => {
216
+ // if (!fn) [msg,fn] = ['',msg]
217
+ // return test('<before> '+ msg, (_,done) => fn(done))
218
+ // }
219
+ global.afterAll = global.after = (msg,fn) => after(fn||msg)
220
+ global.beforeEach = beforeEach
221
+ global.afterEach = afterEach
222
+ global.expect = require('../test/expect')
223
+ exports.expect = global.expect
224
+ suite ('<next>', ()=>{}) //> to signal the start of a test file
225
+
226
+ }
227
+
228
+ // required for test.each in mocha and node --test
229
+ function each (table) {
230
+ const {format} = require('util')
231
+ return (msg,fn) => Promise.all (table.map (each => {
232
+ if (!Array.isArray(each)) each = [each]
233
+ return this (format(msg,...each), ()=> fn(...each))
234
+ }))
235
+ }
236
+ })()
@@ -56,7 +56,54 @@ const chimera = Object.getOwnPropertyDescriptors (class Chimera {
56
56
  exports.decodeURIComponent = s => { try { return decodeURIComponent(s) } catch { return s } }
57
57
  exports.decodeURI = s => { try { return decodeURI(s) } catch { return s } }
58
58
 
59
- exports.local = (file) => relative(cwd,file)
59
+ exports.local = (file) => file && relative(cwd,file)
60
+
61
+ const { prepareStackTrace, stackTraceLimit } = Error
62
+
63
+ /**
64
+ * Use this utility to get a stack trace from the current position in the code.
65
+ * For example, try this in your code, or in cds repl:
66
+ *
67
+ * cds.utils.stack(22) .forEach (each => console.log (
68
+ * each.getTypeName()||'<anonymous>',
69
+ * each.getMethodName()||'—',
70
+ * each.getFunctionName(),
71
+ * '(' + cds.utils.local (each.getFileName())
72
+ * + ':' + each.getLineNumber()
73
+ * + ':' + each.getColumnNumber()
74
+ * + ')'
75
+ * ))
76
+ *
77
+ * **WARNING:** This is an **expensive** function → handle with care!
78
+ * @param {number} [depth] - the number of stack frames to return (default: 11)
79
+ * @returns {NodeJS.CallSite[]} - an array of CallSite objects, as returned by [`Error.prepareStackTrace`](https://v8.dev/docs/stack-trace-api)
80
+ */
81
+ exports.stack = (depth=11) => {
82
+ Error.prepareStackTrace = (_,stack) => stack
83
+ Error.stackTraceLimit = depth
84
+ const stack = (new Error).stack
85
+ Error.stackTraceLimit = stackTraceLimit
86
+ Error.prepareStackTrace = prepareStackTrace
87
+ return stack
88
+ }
89
+
90
+ /**
91
+ * Use this utility to get the location of the caller in the code.
92
+ * For example:
93
+ *
94
+ * let [file,line,col] = cds.utils.location()
95
+ *
96
+ * Basically a shortcut for `cds.utils.stack(3)[2]`,
97
+ * with filename, line number, and column number returned in an array.
98
+ *
99
+ * **WARNING:** This is an **expensive** function → handle with care!
100
+ * @returns {[ filename:string, line:number, column:number ]}
101
+ */
102
+ exports.location = function (){
103
+ const l = this.stack(3)[2]
104
+ return [ l.getFileName(), l.getLineNumber(), l.getColumnNumber() ]
105
+ }
106
+
60
107
 
61
108
  exports.exists = function exists (x) {
62
109
  if (x) {
@@ -72,7 +119,7 @@ exports.isdir = function isdir (...args) {
72
119
  const ls = fs.lstatSync(y)
73
120
  if (ls.isDirectory()) return y
74
121
  if (ls.isSymbolicLink()) return isdir (join (dirname(y), fs.readlinkSync(y)))
75
- } catch(e){/* ignore */}
122
+ } catch {/* ignore */}
76
123
  }
77
124
 
78
125
  // REVISIT naming: doesn't return boolean
@@ -82,7 +129,7 @@ exports.isfile = function isfile (...args) {
82
129
  const ls = fs.lstatSync(y)
83
130
  if (ls.isFile()) return y
84
131
  if (ls.isSymbolicLink()) return isfile (join (dirname(y), fs.readlinkSync(y)))
85
- } catch(e){/* ignore */}
132
+ } catch {/* ignore */}
86
133
  }
87
134
 
88
135
  exports.stat = async function (x) {
@@ -176,7 +223,7 @@ exports.find = function find (base, patterns='*', filter=()=>true) {
176
223
  if (tail) for (let _files of paths.map (e=>find (e,tail,filter))) files.push (..._files)
177
224
  else files.push (...paths)
178
225
  }
179
- } catch(e) {/* ignore */}
226
+ } catch {/* ignore */}
180
227
  } else {
181
228
  const file = join (base, pattern)
182
229
  if (fs.existsSync(file)) files.push (file)
@@ -189,11 +236,11 @@ exports.deprecated = (fn, { kind = 'Method', old = fn.name+'()', use } = {}) =>
189
236
  const yellow = '\x1b[33m'
190
237
  const reset = '\x1b[0m'
191
238
  // use cds.log in production for custom logger
192
- const log = cds.env.production ? cds.log().warn: console.log
239
+ const {warn} = cds.env.production ? cds.log() : console
193
240
  if(typeof fn !== 'function') {
194
241
  if (cds.env.features.deprecated === 'off') return
195
242
  [kind,old,use] = [fn.kind || 'Configuration',fn.old,fn.use]
196
- log (
243
+ warn (
197
244
  yellow,
198
245
  '\n------------------------------------------------------------------------------',
199
246
  '\nDEPRECATED:', old, '\n',
@@ -205,7 +252,7 @@ exports.deprecated = (fn, { kind = 'Method', old = fn.name+'()', use } = {}) =>
205
252
  } else return function() {
206
253
  if (cds.env.features.deprecated !== 'off' && !fn.warned) {
207
254
  let o={}; Error.captureStackTrace(o)
208
- log (
255
+ warn (
209
256
  yellow,
210
257
  '\n------------------------------------------------------------------------------',
211
258
  '\nDEPRECATED:', old, '\n',
@@ -10,10 +10,6 @@ if (given.major < required.major || given.major === required.major && given.mino
10
10
  Current v${given.version} does not satisfy this.
11
11
  \n`) || 1)
12
12
 
13
- if (given.major < 18) process.stderr.write (`WARNING: \n
14
- Node.js v${given.major} has reached end of life. Please upgrade to v18 or higher.
15
- \n`)
16
-
17
13
  function _major_minor (version) {
18
14
  let [ major, minor ] = version.split('.').map(x => +x)
19
15
  return { version, major, minor }
@@ -0,0 +1,49 @@
1
+ const none = process.stdout.isTTY && !process.env.NO_COLOR || process.env.FORCE_COLOR ? null : ''
2
+ const colors = {
3
+ RESET: none ?? '\x1b[0m',
4
+ BOLD: none ?? '\x1b[1m',
5
+ BRIGHT: none ?? '\x1b[1m',
6
+ DIMMED: none ?? '\x1b[2m',
7
+ ITALIC: none ?? '\x1b[3m',
8
+ UNDER: none ?? '\x1b[4m',
9
+ BLINK: none ?? '\x1b[5m',
10
+ FLASH: none ?? '\x1b[6m',
11
+ INVERT: none ?? '\x1b[7m',
12
+ BLACK: none ?? '\x1b[30m',
13
+ RED: none ?? '\x1b[31m',
14
+ GREEN: none ?? '\x1b[32m',
15
+ YELLOW: none ?? '\x1b[33m',
16
+ BLUE: none ?? '\x1b[34m',
17
+ PINK: none ?? '\x1b[35m',
18
+ CYAN: none ?? '\x1b[36m',
19
+ LIGHT_GRAY: none ?? '\x1b[37m',
20
+ DEFAULT: none ?? '\x1b[39m',
21
+ GRAY: none ?? '\x1b[90m',
22
+ LIGHT_RED: none ?? '\x1b[91m',
23
+ LIGHT_GREEN: none ?? '\x1b[92m',
24
+ LIGHT_YELLOW: none ?? '\x1b[93m',
25
+ LIGHT_BLUE: none ?? '\x1b[94m',
26
+ LIGHT_PINK: none ?? '\x1b[95m',
27
+ LIGHT_CYAN: none ?? '\x1b[96m',
28
+ WHITE: none ?? '\x1b[97m',
29
+ bg: {
30
+ BLACK: none ?? '\x1b[40m',
31
+ RED: none ?? '\x1b[41m',
32
+ GREEN: none ?? '\x1b[42m',
33
+ YELLOW: none ?? '\x1b[43m',
34
+ BLUE: none ?? '\x1b[44m',
35
+ PINK: none ?? '\x1b[45m',
36
+ CYAN: none ?? '\x1b[46m',
37
+ WHITE: none ?? '\x1b[47m',
38
+ DEFAULT: none ?? '\x1b[49m',
39
+ LIGHT_GRAY: none ?? '\x1b[100m',
40
+ LIGHT_RED: none ?? '\x1b[101m',
41
+ LIGHT_GREEN: none ?? '\x1b[102m',
42
+ LIGHT_YELLOW: none ?? '\x1b[103m',
43
+ LIGHT_BLUE: none ?? '\x1b[104m',
44
+ LIGHT_PINK: none ?? '\x1b[105m',
45
+ LIGHT_CYAN: none ?? '\x1b[106m',
46
+ LIGHT_WHITE: none ?? '\x1b[107m',
47
+ },
48
+ }
49
+ module.exports = colors
package/lib/utils/data.js CHANGED
@@ -4,9 +4,10 @@ class DataUtil {
4
4
 
5
5
  constructor() {
6
6
  // This is to support simplified usage like that: beforeEach(test.data.reset)
7
- this.reset = (fn) => {
8
- if (typeof fn === 'function') this.__proto__.reset().then(fn)
9
- else return this.__proto__.reset(fn)
7
+ const {reset} = this; this.reset = (x) => {
8
+ if (typeof x === 'function') reset.call(this).then(x) // x is the done callback of jest -> no return
9
+ else if (x?.assert) return reset.call(this) // x is a node --test TestContext object -> ignore
10
+ else return reset.call(this,x) // x is a db service instance
10
11
  }
11
12
  }
12
13
 
@@ -39,7 +40,7 @@ class DataUtil {
39
40
 
40
41
  /* delete + new deploy from csv */
41
42
  async reset(db) {
42
- if (!db) db = await cds.connect.to('db')
43
+ if (!db) db = await cds.connect.to('db')
43
44
  await this.delete(db)
44
45
  await this.deploy(db)
45
46
  }
@@ -29,7 +29,6 @@ const _action = require('./handlers/action')
29
29
  const { normalizeError, isClientError } = require('../../../common/error/frontend')
30
30
  const { getErrorMessage } = require('../../../common/error/utils')
31
31
 
32
- // eslint-disable-next-line complexity
33
32
  function _log(level, arg) {
34
33
  const { params } = arg
35
34
 
@@ -169,12 +168,8 @@ class OData {
169
168
 
170
169
  // start tx
171
170
  const txs = (data.txs = data.txs || {})
172
- const {
173
- req: { user },
174
- req,
175
- res
176
- } = data
177
- const tx = (txs[odataContext.id] = cdsService.tx({ user, req, res }))
171
+ const { req, res } = data
172
+ const tx = (txs[odataContext.id] = cdsService.tx({ req, res }))
178
173
  cds.context = tx.context
179
174
  // for collecting results and errors
180
175
  data.results = data.results || {}
@@ -1,4 +1,3 @@
1
- /* eslint-disable complexity */
2
1
  const cds = require('../../../cds')
3
2
 
4
3
  const {
@@ -17,15 +16,6 @@ const { isCustomOperation } = require('./utils/request')
17
16
  const { isStreaming } = require('./utils/stream')
18
17
  const { handleStreamProperties } = require('../../../common/utils/streamProp')
19
18
 
20
- // getter functions extracted to show deprecation warning only once
21
- const _getAttr = attr => attr
22
- const _getShared = (oReq, req, res) => {
23
- if (oReq.context) oReq._shared = oReq.context._shared = oReq.context._shared || { req, res }
24
- else oReq._shared = oReq._shared || { req, res }
25
-
26
- return oReq._shared
27
- }
28
-
29
19
  function _isCorrectCallToViewWithParams(csdlStructuredType) {
30
20
  return (
31
21
  csdlStructuredType.navigationProperties &&
@@ -116,8 +106,7 @@ class ODataRequest extends cds.Request {
116
106
  const headers = Object.assign({}, req.headers, odataReq.getHeaders())
117
107
  // REVISIT needed in case of $batch, replace after removing okra
118
108
  const method = odataReq.getIncomingRequest().method
119
- const { user } = req
120
- const tenant = req.tenant || user?.tenant
109
+ const { user, tenant } = cds.context
121
110
  const info = metaInfo(query, type, service, data, req, upsert)
122
111
  const { event, unbound } = info
123
112
  if (event === 'READ') {
@@ -196,8 +185,7 @@ class ODataRequest extends cds.Request {
196
185
  /*
197
186
  * super
198
187
  */
199
- const { user } = req
200
- const tenant = req.tenant || user?.tenant
188
+ const { user, tenant } = cds.context
201
189
  // REVISIT: public API for query options (express style req.query already in use)?
202
190
  const _queryOptions = odataReq.getQueryOptions()
203
191
  super({ event, target, data, query, user, method, headers, req, res, _queryOptions, tenant })
@@ -220,23 +208,8 @@ class ODataRequest extends cds.Request {
220
208
  // odataReq and odataRes
221
209
  this._.odataReq = odataReq
222
210
  this._.odataRes = odataRes
223
- // req._.shared
224
- const that = this
225
- Object.defineProperty(this._, 'shared', {
226
- get() {
227
- return cds.utils.deprecated(_getShared, { kind: 'Property', old: 'req._.shared' })(that, req, res)
228
- }
229
- })
230
-
231
- // req.attr
232
- const attr = { identityZone: this.tenant }
233
- Object.defineProperty(this, 'attr', {
234
- get() {
235
- return cds.utils.deprecated(_getAttr, { kind: 'Property', old: 'req.attr' })(attr)
236
- }
237
- })
238
211
 
239
- Object.defineProperty(this, 'protocol', { value: 'odata-v4' })
212
+ Object.defineProperty(this, 'protocol', { value: 'odata' })
240
213
  }
241
214
  }
242
215