@sap/cds 6.8.4 → 7.0.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 (217) hide show
  1. package/CHANGELOG.md +66 -4
  2. package/README.md +0 -1
  3. package/bin/cds-serve.js +50 -3
  4. package/bin/deploy/to-hana.js +1 -0
  5. package/bin/serve.js +16 -20
  6. package/lib/auth/basic-auth.js +6 -4
  7. package/lib/auth/index.js +4 -3
  8. package/lib/auth/jwt-auth.js +2 -5
  9. package/lib/compile/cds-compile.js +34 -89
  10. package/lib/compile/cdsc.js +11 -0
  11. package/lib/compile/etc/properties.js +2 -2
  12. package/lib/compile/for/lean_drafts.js +36 -69
  13. package/lib/compile/for/nodejs.js +2 -1
  14. package/lib/compile/load.js +3 -3
  15. package/lib/compile/minify.js +2 -0
  16. package/lib/compile/to/csn.js +74 -0
  17. package/{bin/build/provider/hana/2tabledata.js → lib/compile/to/hdbtabledata.js} +4 -6
  18. package/lib/compile/to/json.js +1 -1
  19. package/lib/compile/to/sql.js +8 -6
  20. package/lib/dbs/cds-deploy.js +174 -114
  21. package/lib/env/cds-env.js +64 -79
  22. package/lib/env/cds-requires.js +11 -28
  23. package/lib/env/defaults.js +13 -3
  24. package/lib/env/plugins.js +1 -12
  25. package/lib/env/presets.js +25 -21
  26. package/lib/index.js +121 -147
  27. package/lib/{core/reflect.js → linked/models.js} +2 -2
  28. package/lib/{core/infer.js → linked/queries.js} +2 -0
  29. package/lib/{core/index.js → linked/types.js} +2 -1
  30. package/lib/log/cds-error.js +13 -7
  31. package/lib/log/format/cf.js +1 -1
  32. package/lib/plugins.js +49 -0
  33. package/lib/ql/Query.js +0 -9
  34. package/lib/ql/STREAM.js +0 -1
  35. package/lib/req/context.js +2 -7
  36. package/lib/req/request.js +6 -2
  37. package/lib/req/response.js +23 -10
  38. package/lib/srv/middlewares/ctx-model.js +2 -2
  39. package/lib/srv/middlewares/errors.js +1 -1
  40. package/lib/srv/protocols/_legacy.js +1 -0
  41. package/lib/srv/protocols/graphql.js +7 -16
  42. package/lib/srv/protocols/index.js +59 -45
  43. package/lib/srv/protocols/odata-v2-proxy.js +2 -70
  44. package/lib/srv/protocols/odata-v4.js +9 -4
  45. package/lib/srv/srv-api.js +9 -3
  46. package/lib/srv/srv-dispatch.js +12 -9
  47. package/lib/srv/srv-models.js +4 -21
  48. package/lib/srv/srv-tx.js +15 -12
  49. package/lib/utils/cds-test.js +14 -9
  50. package/lib/utils/cds-utils.js +2 -12
  51. package/lib/utils/check-version.js +17 -0
  52. package/{bin/build → lib/utils}/csv-reader.js +23 -24
  53. package/libx/_runtime/auth/index.js +27 -23
  54. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +15 -72
  55. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -1
  56. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +0 -2
  57. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +33 -63
  58. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +14 -18
  59. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +15 -5
  60. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +5 -4
  61. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +37 -40
  62. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/updateToCQN.js +7 -1
  63. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +101 -38
  64. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/errors/AbstractError.js +5 -1
  65. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriTokenizer.js +5 -8
  66. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/ValueConverter.js +2 -1
  67. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/ResourceJsonDeserializer.js +9 -8
  68. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -1
  69. package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +15 -11
  70. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +4 -0
  71. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +5 -2
  72. package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +1 -123
  73. package/libx/_runtime/cds-services/services/Service.js +79 -107
  74. package/libx/_runtime/cds-services/services/utils/columns.js +23 -19
  75. package/libx/_runtime/cds-services/services/utils/compareJson.js +11 -1
  76. package/libx/_runtime/cds-services/services/utils/differ.js +7 -2
  77. package/libx/_runtime/cds-services/util/assert.js +65 -2
  78. package/libx/_runtime/common/composition/data.js +1 -0
  79. package/libx/_runtime/common/generic/auth/expand.js +1 -1
  80. package/libx/_runtime/common/generic/auth/restrict.js +5 -10
  81. package/libx/_runtime/common/generic/auth/restrictions.js +40 -0
  82. package/libx/_runtime/common/generic/auth/utils.js +1 -2
  83. package/libx/_runtime/common/generic/crud.js +32 -16
  84. package/libx/_runtime/common/generic/etag.js +133 -104
  85. package/libx/_runtime/common/generic/input.js +6 -21
  86. package/libx/_runtime/common/generic/put.js +1 -1
  87. package/libx/_runtime/common/generic/stream.js +52 -0
  88. package/libx/_runtime/common/generic/temporal.js +25 -8
  89. package/libx/_runtime/common/i18n/messages.properties +0 -2
  90. package/libx/_runtime/common/utils/cqn.js +1 -1
  91. package/libx/_runtime/common/utils/cqn2cqn4sql.js +5 -2
  92. package/libx/_runtime/common/utils/csn.js +0 -51
  93. package/libx/_runtime/common/utils/etag.js +30 -0
  94. package/libx/_runtime/common/utils/keys.js +1 -1
  95. package/libx/_runtime/common/utils/normalizeTimestamp.js +25 -0
  96. package/libx/_runtime/common/utils/path.js +1 -1
  97. package/libx/_runtime/common/utils/resolveView.js +2 -1
  98. package/libx/_runtime/common/utils/rewriteAsterisks.js +6 -4
  99. package/libx/_runtime/common/utils/search2cqn4sql.js +12 -16
  100. package/libx/_runtime/common/utils/stream.js +140 -0
  101. package/libx/_runtime/common/utils/streamProp.js +29 -12
  102. package/libx/_runtime/common/utils/templateProcessorPathSerializer.js +0 -2
  103. package/libx/_runtime/db/generic/index.js +0 -2
  104. package/libx/_runtime/db/query/delete.js +2 -2
  105. package/libx/_runtime/db/query/insert.js +2 -2
  106. package/libx/_runtime/db/query/read.js +2 -2
  107. package/libx/_runtime/db/query/run.js +2 -2
  108. package/libx/_runtime/db/query/update.js +2 -2
  109. package/libx/_runtime/db/sql-builder/BaseBuilder.js +0 -6
  110. package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +23 -12
  111. package/libx/_runtime/db/sql-builder/FunctionBuilder.js +18 -6
  112. package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -0
  113. package/libx/_runtime/db/sql-builder/SelectBuilder.js +3 -7
  114. package/libx/_runtime/db/sql-builder/UpsertBuilder.js +1 -0
  115. package/libx/_runtime/db/utils/normalizeTimeData.js +7 -3
  116. package/libx/_runtime/fiori/draft.js +2 -0
  117. package/libx/_runtime/fiori/generic/activate.js +8 -9
  118. package/libx/_runtime/fiori/generic/before.js +30 -20
  119. package/libx/_runtime/fiori/generic/cancel.js +5 -3
  120. package/libx/_runtime/fiori/generic/delete.js +5 -3
  121. package/libx/_runtime/fiori/generic/edit.js +7 -7
  122. package/libx/_runtime/fiori/generic/index.js +10 -16
  123. package/libx/_runtime/fiori/generic/new.js +5 -3
  124. package/libx/_runtime/fiori/generic/patch.js +11 -8
  125. package/libx/_runtime/fiori/generic/prepare.js +13 -6
  126. package/libx/_runtime/fiori/generic/read.js +12 -6
  127. package/libx/_runtime/fiori/lean-draft.js +207 -152
  128. package/libx/_runtime/fiori/utils/delete.js +10 -5
  129. package/libx/_runtime/fiori/utils/req.js +17 -5
  130. package/libx/_runtime/fiori/utils/stream.js +36 -0
  131. package/libx/_runtime/hana/Service.js +12 -9
  132. package/libx/_runtime/hana/conversion.js +10 -15
  133. package/libx/_runtime/hana/driver.js +2 -0
  134. package/libx/_runtime/hana/execute.js +28 -6
  135. package/libx/_runtime/hana/pool.js +36 -122
  136. package/libx/_runtime/hana/search2cqn4sql.js +34 -36
  137. package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +2 -6
  138. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +3 -1
  139. package/libx/_runtime/messaging/enterprise-messaging.js +10 -58
  140. package/libx/_runtime/messaging/outbox/utils.js +1 -1
  141. package/libx/_runtime/remote/Service.js +20 -1
  142. package/libx/_runtime/remote/utils/client.js +3 -5
  143. package/libx/_runtime/sqlite/Service.js +4 -6
  144. package/libx/_runtime/sqlite/conversion.js +3 -13
  145. package/libx/_runtime/sqlite/customBuilder/CustomFunctionBuilder.js +9 -6
  146. package/libx/_runtime/sqlite/customBuilder/CustomUpsertBuilder.js +6 -1
  147. package/libx/_runtime/sqlite/execute.js +5 -16
  148. package/libx/odata/afterburner.js +22 -6
  149. package/libx/odata/grammar.pegjs +6 -1
  150. package/libx/odata/parser.js +1 -1
  151. package/libx/rest/RestAdapter.js +16 -9
  152. package/libx/rest/RestRequest.js +1 -1
  153. package/libx/rest/middleware/input.js +2 -1
  154. package/libx/rest/middleware/operation.js +1 -0
  155. package/libx/rest/middleware/parse.js +3 -2
  156. package/libx/rest/middleware/payload.js +9 -8
  157. package/libx/rest/middleware/read.js +1 -0
  158. package/package.json +9 -16
  159. package/server.js +1 -1
  160. package/app/fiori/preview.js +0 -270
  161. package/app/fiori/routes.js +0 -59
  162. package/bin/build/buildTaskEngine.js +0 -360
  163. package/bin/build/buildTaskFactory.js +0 -283
  164. package/bin/build/buildTaskHandler.js +0 -241
  165. package/bin/build/buildTaskProvider.js +0 -22
  166. package/bin/build/buildTaskProviderFactory.js +0 -175
  167. package/bin/build/cds.js +0 -5
  168. package/bin/build/constants.js +0 -66
  169. package/bin/build/index.js +0 -58
  170. package/bin/build/provider/buildTaskHandlerEdmx.js +0 -82
  171. package/bin/build/provider/buildTaskHandlerFeatureToggles.js +0 -131
  172. package/bin/build/provider/buildTaskHandlerInternal.js +0 -254
  173. package/bin/build/provider/buildTaskProviderInternal.js +0 -383
  174. package/bin/build/provider/fiori/index.js +0 -171
  175. package/bin/build/provider/hana/2migration.js +0 -179
  176. package/bin/build/provider/hana/index.js +0 -505
  177. package/bin/build/provider/hana/migrationtable.js +0 -472
  178. package/bin/build/provider/hana/template/.hdiconfig-haas +0 -163
  179. package/bin/build/provider/hana/template/.hdiconfig-hanacloud +0 -137
  180. package/bin/build/provider/hana/template/.hdinamespace +0 -4
  181. package/bin/build/provider/hana/template/package.json +0 -12
  182. package/bin/build/provider/hana/template/undeploy.json +0 -5
  183. package/bin/build/provider/java/index.js +0 -111
  184. package/bin/build/provider/java-cf/index.js +0 -1
  185. package/bin/build/provider/mtx/index.js +0 -268
  186. package/bin/build/provider/mtx/resourcesTarBuilder.js +0 -95
  187. package/bin/build/provider/mtx-extension/index.js +0 -131
  188. package/bin/build/provider/mtx-sidecar/index.js +0 -137
  189. package/bin/build/provider/node-cf/index.js +0 -1
  190. package/bin/build/provider/nodejs/index.js +0 -192
  191. package/bin/build/util.js +0 -299
  192. package/bin/cds.js +0 -125
  193. package/bin/deploy/to-hana/cfUtil.js +0 -355
  194. package/bin/deploy/to-hana/gitUtil.js +0 -57
  195. package/bin/deploy/to-hana/hana.js +0 -306
  196. package/bin/deploy/to-hana/hdiDeployUtil.js +0 -153
  197. package/bin/deploy/to-hana/index.js +0 -16
  198. package/bin/deploy/to-hana/mtaUtil.js +0 -170
  199. package/bin/mtx/in-cds.js +0 -17
  200. package/bin/plugins.js +0 -32
  201. package/bin/run.js +0 -24
  202. package/bin/utils/log.js +0 -24
  203. package/bin/version.js +0 -178
  204. package/libx/_runtime/audit/Service.js +0 -222
  205. package/libx/_runtime/audit/generic/personal/access.js +0 -61
  206. package/libx/_runtime/audit/generic/personal/index.js +0 -56
  207. package/libx/_runtime/audit/generic/personal/modification.js +0 -132
  208. package/libx/_runtime/audit/generic/personal/utils.js +0 -186
  209. package/libx/_runtime/audit/utils/log.js +0 -23
  210. package/libx/_runtime/audit/utils/v2.js +0 -176
  211. package/libx/_runtime/db/data-conversion/timestamp.js +0 -9
  212. package/libx/_runtime/db/generic/integrity.js +0 -455
  213. package/srv/audit-log.cds +0 -87
  214. package/srv/mtx.cds +0 -2
  215. package/srv/mtx.js +0 -8
  216. /package/lib/{core → linked}/classes.js +0 -0
  217. /package/lib/{core → linked}/entities.js +0 -0
package/lib/index.js CHANGED
@@ -1,167 +1,141 @@
1
- /** @typedef {import './serve/Service-api'} Service */
1
+ if (process.env.CDS_STRICT_NODE_VERSION !== 'false') require('./utils/check-version')
2
2
 
3
- const facade = class cds extends require('events') {
3
+ const { extend, lazify, lazified } = require('./lazy')
4
+ const { EventEmitter } = require('node:events')
4
5
 
5
- get env() { return super.env = require('./env/cds-env').for('cds',cds.root) }
6
+ const cds = module.exports = new class cds extends EventEmitter {
7
+
8
+ // Configuration & Information
6
9
  get requires() { return super.requires = this.env.requires._resolved() }
10
+ get plugins() { return super.plugins = require('./plugins') }
7
11
  get version() { return super.version = require('../package.json').version }
8
- get builtin() { return super.builtin = require('./core') }
9
- get service() { return super.service = extend(this.builtin.classes.service) .with (_service) }
10
- get _context() { return super._context = require('./req/cds-context') }
11
- get context() { return this._context._for(this) }
12
- set context(_){ this._context._for(this,_) }
13
- get spawn() { return super.spawn = this._context.spawn }
12
+ get env() { return super.env = require('./env/cds-env').for('cds',this.root) }
13
+ get home() { return super.home = __dirname.slice(0,-4) }
14
+ cli = { command:'', options:{}, argv:[] }
15
+ root = process.cwd()
14
16
 
17
+ // Loading and Compiling Models
18
+ get compiler() { return super.compiler = require('./compile/cdsc') }
19
+ get compile() { return super.compile = require('./compile/cds-compile') }
20
+ get resolve() { return super.resolve = require('./compile/resolve') }
21
+ get load() { return super.load = require('./compile/load') }
22
+ get get() { return super.get = this.load.parsed }
23
+ get parse() { return super.parse = require('./compile/parse') }
24
+ get minify() { return super.minify = require('./compile/minify') }
25
+ get extend() { return super.extend = require('./compile/extend') }
26
+ get deploy() { return super.deploy = require('./dbs/cds-deploy') }
27
+ get localize() { return super.localize = require('./i18n/localize') }
28
+ get build() { return () => { throw new Error('This application uses @sap/cds version >= 7, which is not compatible with the installed @sap/cds-dk version 6. Either update @sap/cds-dk to version 7 or downgrade @sap/cds to version 6 instead.') } }
29
+ /** @type {{definitions:{},extensions:[]}} */ model = undefined
30
+ /** @type Service */ db = undefined
31
+
32
+ // Model Reflection, Builtin types and classes
33
+ get reflect() { return super.reflect = this.linked }
34
+ get linked() { return super.linked = require('./linked/models') }
35
+ get infer() { return super.infer = require('./linked/queries') }
36
+ get builtin() { return super.builtin = require('./linked/types') }
37
+ get Association() { return super.Association = this.builtin.classes.Association }
38
+ get Composition() { return super.Composition = this.builtin.classes.Composition }
39
+ get entity() { return super.entity = this.builtin.classes.entity }
40
+ get event() { return super.event = this.builtin.classes.event }
41
+ get type() { return super.type = this.builtin.classes.type }
42
+ get array() { return super.array = this.builtin.classes.array }
43
+ get struct() { return super.struct = this.builtin.classes.struct }
44
+ get service() { return super.service = extend (this.builtin.classes.service) .with (lazified({
45
+ impl: (/** @type {(this:Service, srv:Service, ...etc) => any} */ srv) => srv,
46
+ protocols: lazy => require('./srv/protocols'),
47
+ bindings: lazy => require('./srv/bindings'),
48
+ factory: lazy => require('./srv/factory'),
49
+ /** @type Service[] */ providers: []
50
+ }))}
51
+
52
+ // Providing and Consuming Services
53
+ /** @type {{ [name:string]: Service }} */
54
+ services = Object.defineProperties (new class { *[Symbol.iterator](){ for (let e in this) yield this[e] } },{
55
+ _pending: {value:{}}
56
+ })
57
+ get server() { return super.server = require('../server') }
58
+ get serve() { return super.serve = require('./srv/cds-serve') }
59
+ get connect() { return super.connect = require('./srv/cds-connect') }
60
+ get middlewares() { return super.middlewares = require('./srv/middlewares') }
61
+ get odata() { return super.odata = require('../libx/odata') }
62
+ get auth() { return super.auth = require('./auth') }
63
+
64
+ // awaiting async functions for some events
15
65
  async emit (eve, ...args) {
16
- // if (eve === 'served') return Promise.all (this.listeners(eve).map (l => l.call(this,...args)))
17
66
  if (eve === 'served') for (let l of this.listeners(eve)) await l.call(this,...args)
18
67
  else return super.emit (eve, ...args)
19
68
  }
20
- }
21
-
22
- const { extend, lazify, lazified } = require ('./lazy')
23
- const _class = lazy => cds.builtin.classes [lazy]
24
- const _require = require; require = lazified (module) // eslint-disable-line
25
- const _service = lazified ({ // nested facade for service-related modules
26
- /** @param x {(this:Service, srv:Service, ...etc) => any} */ impl: x=>x,
27
- /** @type Service[] */ providers: [],
28
- factory: require ('./srv/factory'),
29
- protocols: require ('./srv/protocols'),
30
- bindings: require ('./srv/bindings'),
31
- })
32
-
33
- /** cds is the central facade to all cds functions */
34
- const cds = module.exports = extend (new facade) .with ({
35
-
36
- // Builtin types and classes
37
- Association:_class,
38
- Composition:_class,
39
- entity:_class,
40
- event:_class,
41
- type:_class,
42
- array:_class,
43
- struct:_class,
44
-
45
- // Model Reflection
46
- reflect: require ('./core/reflect'),
47
- linked: require ('./core/reflect'),
48
- infer: require ('./core/infer'),
49
-
50
- // Loading and Compiling Models
51
- model: undefined,
52
- compiler: require ('./compile/cdsc'),
53
- compile: require ('./compile/cds-compile'),
54
- resolve: require ('./compile/resolve'),
55
- load: require ('./compile/load'), get: lazy => cds.load.parsed,
56
- parse: require ('./compile/parse'),
57
- minify: require ('./compile/minify'),
58
- extend: require ('./compile/extend'),
59
- deploy: require ('./dbs/cds-deploy'),
60
-
61
- // Providing and Consuming Services
62
- connect: require ('./srv/cds-connect'),
63
- serve: require ('./srv/cds-serve'),
64
- server: require ('../server'),
65
- services: new class IterableServices {
66
- *[Symbol.iterator]() {for (let e in this) yield this[e]}
67
- get _pending(){ let p={}; Object.defineProperty(this,'_pending',{value:p}); return p }
68
- },
69
- middlewares: require('./srv/middlewares'),
70
- auth: require ('./auth'),
71
69
 
72
70
  // Core Services API
73
- Service: require ('./srv/srv-api'),
74
- EventContext: require ('./req/context'),
75
- Request: require ('./req/request'),
76
- Event: require ('./req/event'),
77
- User: require ('./req/user'),
78
- ql: lazy => require ('./ql/cds-ql'),
79
- tx: (..._) => (cds.db || cds.Service.prototype) .tx (..._),
80
- inferred: lazy => require('@cap-js/sqlite/lib/ql/cds.infer'), // eslint-disable-line cds/no-missing-dependencies
81
- cqn2sql: lazy => require('@cap-js/sqlite/lib/db/sql/cqn2sql'), // eslint-disable-line cds/no-missing-dependencies
82
- cqn4sql: lazy => require('@cap-js/sqlite/lib/db/sql/cqn4sql'), // eslint-disable-line cds/no-missing-dependencies
83
- /** @type Service */ db: undefined,
84
-
85
- // Protocols and Periphery
86
- ApplicationService: lazy => require('../libx/_runtime/cds-services/services/Service.js'),
87
- MessagingService: lazy => require('../libx/_runtime/messaging/service.js'),
88
- DatabaseService: lazy => require('../libx/_runtime/db/Service.js'),
89
- RemoteService: lazy => require('../libx/_runtime/remote/Service.js'),
90
- AuditLogService: lazy => require('../libx/_runtime/audit/Service.js'),
91
- odata: require('../libx/odata'),
71
+ /** @typedef {import './srv/srv-api'} Service */
72
+ get Service() { return super.Service = require('./srv/srv-api') }
73
+ get EventContext() { return super.EventContext = require('./req/context') }
74
+ get Request() { return super.Request = require('./req/request') }
75
+ get Event() { return super.Event = require('./req/event') }
76
+ get User() { return super.User = require('./req/user') }
77
+
78
+ // Services, Protocols and Periphery
79
+ get ApplicationService() { return super.ApplicationService = require('../libx/_runtime/cds-services/services/Service.js') }
80
+ get MessagingService() { return super.MessagingService = require('../libx/_runtime/messaging/service.js') }
81
+ get DatabaseService() { return super.DatabaseService = require('../libx/_runtime/db/Service.js') }
82
+ get RemoteService() { return super.RemoteService = require('../libx/_runtime/remote/Service.js') }
83
+
84
+ // Contexts and Transactions
85
+ get _context() { return super._context = require('./req/cds-context') }
86
+ get context() { return this._context._for(this) }
87
+ set context(_) { this._context._for(this,_) }
88
+ get spawn() { return super.spawn = this._context.spawn }
89
+ tx(..._) { return (this.db || this.Service.prototype) .tx (..._) }
92
90
 
93
91
  // Helpers
94
- localize: require ('./i18n/localize'),
95
- error: require ('./log/cds-error'),
96
- utils: require ('./utils/cds-utils'),
97
- test: require ('./utils/cds-test'),
98
- log: require ('./log/cds-log'), debug: lazy => cds.log.debug,
99
- exec: require ('../bin/cds'),
100
- exit: (code) => cds.shutdown ? cds.shutdown() : process.exit(code),
101
- clone: m => JSON.parse (JSON.stringify(m)),
102
- lazified, lazify,
103
-
104
- // Configuration & Information
105
- home: __dirname.slice(0,-4),
106
- root: lazy => process.cwd(),
107
-
108
- })
109
-
110
-
111
- // cds as shortcut to cds.db -> for compatibility only
112
- extend (cds.__proto__) .with ({
113
- get entities(){ return (cds.db||_missing).entities },
114
- transaction: (..._) => (cds.db||_missing).transaction(..._),
115
- run: (..._) => (cds.db||_missing).run(..._),
116
- foreach: (..._) => (cds.db||_missing).foreach(..._),
117
- stream: (..._) => (cds.db||_missing).stream(..._),
118
- read: (..._) => (cds.db||_missing).read(..._),
119
- create: (..._) => (cds.db||_missing).create(..._),
120
- insert: (..._) => (cds.db||_missing).insert(..._),
121
- update: (..._) => (cds.db||_missing).update(..._),
122
- delete: (..._) => (cds.db||_missing).delete(..._),
123
- disconnect: (..._) => (cds.db||_missing).disconnect(..._),
124
- })
125
- /** @type Service */ const _missing = new Proxy ({},{
126
- get:function fn(_,p){ cds.error._no_primary_db(p,fn) }
127
- })
128
-
129
- // legacy and to be moved stuff -> hidden for tools in cds.__proto__
130
- extend (cds.__proto__) .with (lazified ({
131
- /** @deprecated */ in: (cwd) => !cwd ? cds : {__proto__:cds, cwd, env: cds.env.for('cds',cwd) },
132
- mtx: lazy => require('../bin/mtx/in-cds'),
133
- build: lazy => require('../bin/build')
134
- }))
135
-
136
- // Add global forwards to cds.ql and cds.parse
137
- const odp = Object.defineProperty, _global = (_,...pp) => pp.forEach (p => odp(global,p,{
138
- configurable:true, get:()=>{ let v=cds[_][p]; odp(this,p,{value:v}); return v }
139
- }))
140
- _global ('ql','SELECT','INSERT','UPSERT','UPDATE','DELETE','CREATE','DROP','STREAM')
141
- _global ('parse','CDL','CQL','CXL')
142
-
143
- // Check Node.js version
144
- if (process.env.CDS_STRICT_NODE_VERSION !== 'false') {
145
- const v = version => { let vv = version.split('.'); return { version, major: +vv[0], minor: +vv[1] }}
146
- const required = v(_require('../package.json').engines.node.match(/>=(.*)/)[1])
147
- const given = v(process.version.match(/^v(\d+\.\d+)/)[1])
148
- if (given.major < required.major || given.major === required.major && given.minor < required.minor) process.exit (process.stderr.write (`
149
- Node.js v${required.version} or higher is required for @sap/cds.
150
- Current v${given.version} does not satisfy this.
151
- \n`) || 1)
92
+ get utils() { return super.utils = require('./utils/cds-utils') }
93
+ get error() { return super.error = require('./log/cds-error') }
94
+ get exec() { return super.exec = require('../bin/cds-serve') }
95
+ get test() { return super.test = require('./utils/cds-test') }
96
+ get log() { return super.log = require('./log/cds-log') }
97
+ get debug() { return super.debug = this.log.debug }
98
+ get lazify(){ return lazify }
99
+ get lazified(){ return lazify }
100
+ clone(m) { return JSON.parse (JSON.stringify(m)) }
101
+ exit(code){ return cds.shutdown ? cds.shutdown() : process.exit(code) }
102
+
103
+ // Querying and Databases
104
+ get ql() { return super.ql = require('./ql/cds-ql') }
105
+ get entities() { return this.db?.entities || this.model?.entities }
106
+ run (..._) { return (this.db||this.error._no_primary_db).run(..._) }
107
+ foreach (..._) { return (this.db||this.error._no_primary_db).foreach(..._) }
108
+ stream (..._) { return (this.db||this.error._no_primary_db).stream(..._) }
109
+ read (..._) { return (this.db||this.error._no_primary_db).read(..._) }
110
+ create (..._) { return (this.db||this.error._no_primary_db).create(..._) }
111
+ insert (..._) { return (this.db||this.error._no_primary_db).insert(..._) }
112
+ update (..._) { return (this.db||this.error._no_primary_db).update(..._) }
113
+ delete (..._) { return (this.db||this.error._no_primary_db).delete(..._) }
114
+ disconnect (..._) { return (this.db||this.error._no_primary_db).disconnect(..._) }
115
+ transaction (..._) { return (this.db||this.error._no_primary_db).transaction(..._) }
116
+
117
+ // legacy and to be moved stuff -> hidden for tools in cds.__proto__
118
+ /** @deprecated */ in (cwd) { return !cwd ? this : {__proto__:this, cwd, env: this.env.for('cds',cwd) } }
152
119
  }
153
120
 
154
- // restore require for subsequent uses in lazy getters
155
- require = _require // eslint-disable-line
121
+ // add global cds.ql commands
122
+ extend (global) .with (class {
123
+ static get SELECT() { return cds.ql.SELECT }
124
+ static get INSERT() { return cds.ql.INSERT }
125
+ static get UPSERT() { return cds.ql.UPSERT }
126
+ static get UPDATE() { return cds.ql.UPDATE }
127
+ static get DELETE() { return cds.ql.DELETE }
128
+ static get STREAM() { return cds.ql.STREAM }
129
+ static get CREATE() { return cds.ql.CREATE }
130
+ static get DROP() { return cds.ql.DROP }
131
+ static get CDL() { return cds.parse.CDL }
132
+ static get CQL() { return cds.parse.CQL }
133
+ static get CXL() { return cds.parse.CXL }
134
+ })
156
135
 
157
136
  // can be used to later check that one has only one cds object
158
- if (!global.__cds_loaded_from) global.__cds_loaded_from = new Set
159
- global.__cds_loaded_from.add(__filename)
160
-
161
- if (process.env.CDS_GLOBAL) // TODO for stakeholder-tests only. Remove after cds 6.
162
- Object.assign(module,{ exports: global.cds || (global.cds = cds)})
163
- else
164
- global.cds = cds
137
+ ;(global.__cds_loaded_from ??= new Set).add(__filename)
138
+ global.cds = cds // REVISIT: using global.cds seems wrong
165
139
 
166
140
  // install jest util if jest is defined
167
141
  if (process.env.CDS_JEST_MEM_FIX && typeof jest !== 'undefined') require('./utils/jest.js')
@@ -1,4 +1,4 @@
1
- const { types, classes:{ service, entity, action, event, any, struct, array, context, annotation } } = require('.')
1
+ const { types, classes:{ service, entity, action, event, any, struct, array, context, annotation } } = require('./types')
2
2
  const _kinds = { annotation, context, service, action, event, entity, view:entity }
3
3
 
4
4
  class LinkedCSN extends any {
@@ -98,7 +98,7 @@ class LinkedCSN extends any {
98
98
 
99
99
  const _unresolved = (x,unknown=any) => ({ name:x, __proto__:unknown.prototype, _unresolved:true })
100
100
  const _builtin = x => types[x] || typeof x === 'string' && x.startsWith('cds.hana.') && any.prototype
101
- const _infer = require('./infer'), _not_inferred = _unresolved('<query>',entity)
101
+ const _infer = require('./queries'), _not_inferred = _unresolved('<query>',entity)
102
102
  const _set = (o,p,v) => Object.defineProperty (o,p,{value:v,enumerable:false,configurable:1,writable:1})
103
103
  const _own = (o,p) => { const pd = Reflect.getOwnPropertyDescriptor(o,p); return pd && pd.value }
104
104
  const _is = x => {
@@ -8,6 +8,8 @@ module.exports = (q,defs) => {
8
8
  q.UPSERT ? _resolve (q.UPSERT.into, defs) :
9
9
  q.UPDATE ? _resolve (q.UPDATE.entity, defs) :
10
10
  q.DELETE ? _resolve (q.DELETE.from, defs) :
11
+ q.STREAM?.from ? _resolve (q.STREAM.from, defs) :
12
+ q.STREAM?.into ? _resolve (q.STREAM.into, defs) :
11
13
  _resolve (undefined)
12
14
  ), configurable:true, writable:true })
13
15
  return q._target
@@ -11,7 +11,7 @@ const classes = Object.assign (
11
11
 
12
12
  /** Type system roots -> can be used with instanceof */
13
13
  const roots = _roots ({
14
- context: {},
14
+ any: classes.any.prototype,
15
15
  type: {},
16
16
  scalar: {type:'type'},
17
17
  string: {type:'scalar'},
@@ -25,6 +25,7 @@ const roots = _roots ({
25
25
  event: {type:'struct'},
26
26
  Association: {type:'type'},
27
27
  Composition: {type:'Association'},
28
+ context: {},
28
29
  service: {type:'context'},
29
30
  $self: {}, //> to support polymorphic self links like in: action foo( self: [many] $self, ...)
30
31
  })
@@ -16,11 +16,17 @@ const { format } = require('util'), _formatted = v => format(v)
16
16
  *
17
17
  * let x = y || cds.error `Argument 'y' must not be null`
18
18
  */
19
- const error = exports = module.exports = function cds_error (msg, _details, _base) {
20
- if (msg.raw) [ msg, _details, _base ] = [ error.message(...arguments) ]
21
- const e = msg.stack ? msg : typeof msg === 'string' ? new Error(msg) : Object.assign(new Error,msg)
22
- Error.captureStackTrace (e,_base||error)
23
- if (_details) Object.assign (e,_details)
19
+ const error = exports = module.exports = function cds_error ( message, details, caller ) {
20
+ let e
21
+ if (message.raw) [ message, details, caller ] = [ error.message(...arguments) ]
22
+ if (typeof message === 'string') {
23
+ e = new Error(message)
24
+ } else {
25
+ e = message.stack ? message : Object.assign(new Error,message)
26
+ ;[ caller, details ] = [ details ]
27
+ }
28
+ Error.captureStackTrace (e,caller||error)
29
+ if (details) Object.assign (e,details)
24
30
  if (new.target) return e; else throw e
25
31
  }
26
32
 
@@ -70,7 +76,7 @@ exports._duplicate_cds = (...locations) => {
70
76
  `
71
77
  }
72
78
 
73
- exports._no_primary_db = (p,_base) => error (`Not connected to primary datasource!
79
+ exports._no_primary_db = new Proxy ({},{ get: function fn(_,p) { error (`Not connected to primary datasource!
74
80
 
75
81
  Attempt to use 'cds.${p}' without prior connect to primary datasource,
76
82
  i.e. cds.connect.to('db').
@@ -78,4 +84,4 @@ exports._no_primary_db = (p,_base) => error (`Not connected to primary datasourc
78
84
  Please configure one thru 'cds.requires.db' or use in-memory db:
79
85
  cds ${process.argv[2]} --in-memory` : ''}`
80
86
 
81
- ,{},_base)
87
+ ,{},fn) }})
@@ -10,7 +10,7 @@ module.exports = (module, level, ...args) => {
10
10
  toLog.layer = 'cds'
11
11
 
12
12
  // cds.context._ instead of cds.context.http because of messaging
13
- toLog.tenant_subdomain = cds.context?._?.req?.authInfo?.getSubdomain()
13
+ toLog.tenant_subdomain = cds.context?._?.req?.authInfo?.getSubdomain?.()
14
14
 
15
15
  return kibana.format(toLog)
16
16
  }
package/lib/plugins.js ADDED
@@ -0,0 +1,49 @@
1
+ // IMPORTANT We must not use cds.debug/log/env here to allow plugins to change env.defaults
2
+ const DEBUG = /\by|all|plugins\b/.test(process.env.DEBUG)
3
+ const cds = require('.'), { local } = cds.utils
4
+
5
+ module.exports = (async function load_plugins (log = console.log) {
6
+
7
+ if (DEBUG) console.time('[cds] - loaded plugins in')
8
+ const plugins = {}
9
+
10
+ load_from(cds.home) // load well-known plugins from our dependencies
11
+ load_from(cds.root)
12
+
13
+ global._plugins = Object.keys(plugins) // used in cds.env
14
+ await Promise.all(Object.values(plugins).map(load => load()))
15
+ if (DEBUG) console.timeEnd('[cds] - loaded plugins in')
16
+
17
+ return plugins
18
+
19
+ function load_from(pkg_path) {
20
+ let pkg; try { pkg = require(pkg_path + '/package.json') } catch { return }
21
+
22
+ if (pkg.cds?.plugins) {
23
+ for (let each of pkg.cds.plugins) {
24
+ let plugin = typeof each === 'string' ? each : each.impl
25
+ if (plugin.startsWith('.'))
26
+ plugin = require.resolve(pkg_path + '/' + plugin)
27
+ _load_plugin(plugin, plugin, each)
28
+ }
29
+ } else {
30
+ const deps = { ...pkg.dependencies, ...(process.env.NODE_ENV !== 'production' && pkg.devDependencies) }
31
+ const plugins = []
32
+ for (let each in deps) try {
33
+ let plugin = require.resolve(each + '/cds-plugin', {paths:[pkg_path]})
34
+ plugins.push (()=>_load_plugin(each, plugin))
35
+ } catch { /* no plugin */ }
36
+ for (let each of plugins) each()
37
+ }
38
+
39
+ function _load_plugin (name, impl, conf) {
40
+ plugins[name] = async() => {
41
+ // TODO support ESM plugins. But see cap/cds/pull/1838#issuecomment-1177200 !
42
+ const plugin = plugins[name] = require(impl)
43
+ if (DEBUG) log('[cds] - loaded plugin:', { impl: local(impl) })
44
+ if (plugin.activate) await plugin.activate(conf)
45
+ }
46
+ }
47
+ }
48
+
49
+ })()
package/lib/ql/Query.js CHANGED
@@ -65,17 +65,8 @@ class Query {
65
65
  valueOf (cmd=this.cmd) {
66
66
  return `${cmd} ${_name(this._target.name)} `
67
67
  }
68
-
69
- forSQL (db = cds.db || cds) { return _flat(db.cqn4sql(this)) }
70
- toSQL (db = cds.db || cds) { return _2sql(db.cqn2sql(this)) }
71
- toSql (db = cds.db || cds) { return this.toSQL(db).sql }
72
-
73
68
  }
74
69
 
75
- // skip .cqn property when in repl
76
- const _2sql = cds.repl ? ({sql,values}) => ({sql,values}) : (x => x)
77
- const _flat = Query.prototype.flat
78
-
79
70
  const _target4 = (target, arg2) => target && (
80
71
  typeof target === 'string' ? { name: target } :
81
72
  target.name ? target : //> assumed to be a linked csn definition
package/lib/ql/STREAM.js CHANGED
@@ -35,7 +35,6 @@ module.exports = class Query extends Whereable {
35
35
 
36
36
  // return a proxy assuming it's a from and switching to
37
37
  // column on a subsequent call of .from, if any.
38
- const {STREAM:_} = this
39
38
  return Object.defineProperties (this.from (col, ...more), {
40
39
  from: { configurable:true, value:(...args) => { delete this.from
41
40
  return this.from (...args) .column (col, ...more)
@@ -1,4 +1,4 @@
1
- const cds = require ('../index'), { features } = cds.env, { uuid } = cds.utils
1
+ const cds = require ('../index'), { uuid } = cds.utils
2
2
  const async_events = { succeeded:1, failed:1, done:1, commit:1 }
3
3
  const req_locale = require('./locale')
4
4
  const { EventEmitter } = require('events')
@@ -158,7 +158,7 @@ class EventContext {
158
158
  super.http = rr
159
159
  }
160
160
  get http() {
161
- return this._propagated.http || this._.req && this._.res && { req:this._.req, res:this._.res }
161
+ return super.http = this._propagated.http || this._.req && this._.res && { req:this._.req, res:this._.res }
162
162
  }
163
163
 
164
164
 
@@ -173,11 +173,6 @@ class EventContext {
173
173
  const root = tx.context?.context
174
174
  if (root && root !== this) {
175
175
  if (!this.hasOwnProperty('context')) this.context = root // eslint-disable-line no-prototype-builtins
176
- if (features.assert_integrity && features.assert_integrity_type == 'RT') {
177
- const reqs = root._children || root._set('_children', {})
178
- const all = reqs[tx.name] || (reqs[tx.name] = [])
179
- all.push(this)
180
- }
181
176
  }
182
177
  }
183
178
  get _tx() { return this.tx } // REVISIT: for compatibility to bade usages of req._tx
@@ -53,7 +53,7 @@ class Request extends require('./event') {
53
53
  set data(d) { if (d) super.data = d }
54
54
  get data() {
55
55
  const q = this.query; if (!q) return this._set ('data', undefined)
56
- const I = q.INSERT; if (I) return this._set ('data', I.rows || I.values || I.entries && (I.entries.length > 1 ? I.entries : I.entries[0]) ||{})
56
+ const I = q.INSERT || q.UPSERT; if (I) return this._set ('data', I.rows || I.values || I.entries && (I.entries.length > 1 ? I.entries : I.entries[0]) ||{})
57
57
  const U = q.UPDATE; if (U) return this._set ('data', U.data ||{})
58
58
  return this._set ('data', {})
59
59
  }
@@ -127,7 +127,11 @@ class Request extends require('./event') {
127
127
  warn (...args) { return this._messages.add (3, ...args) }
128
128
  error (...args) { return this._errors.add (4, ...args) }
129
129
  reject (...args) {
130
- if (args[0] === 401 && this._.req?.login && !this._.req?.logIn) return this._.req.login()
130
+ if (args.length === 0 && this.errors) {
131
+ let errs = this.errors
132
+ throw errs.length === 1 ? errs[0] : new cds.error ('MULTIPLE_ERRORS', { details: errs }, this.reject)
133
+ }
134
+ if (args[0] === 401 && this._.req?._login) this._.req._login()
131
135
  let e = this.error(...args)
132
136
  if (!e.stack) Error.captureStackTrace (e = Object.assign(new Error,e), this.reject)
133
137
  throw e
@@ -1,19 +1,33 @@
1
1
  const cds = require ('../index')
2
+ const placeholders = [...'x'.repeat(9)].map((x,i) => `{${i+1}}`)
2
3
 
3
4
  /**
4
5
  * Messages Collector, used for `req.errors` and `req.messages`
5
6
  */
6
7
  class Responses extends Array {
7
- static get (severity, code, message, target, args, ...more) {
8
- if (code?.raw) [ message, code ] = [ String.raw (code, message, target, args, ...more) ]
8
+ static get (severity, code, message, target, args) {
9
9
  let e // be filled in below...
10
- if (typeof code === 'object') e = code; else {
11
- if (typeof code === 'number') e = { code }; else [ code, message, target, args, e ] = [ undefined, code, message, target, {} ]
12
- if (typeof message === 'object') e = Object.assign(message,e); else {
13
- if (typeof target === 'object') [ target, args ] = [ undefined, target ]
14
- if (message) e.message = message //; else if (code) e.message = String(code)
15
- if (target) e.target = target
16
- if (args) e.args = args
10
+ if (code?.raw) {
11
+ if (typeof message === 'object') {
12
+ target = Object.keys(message)[0]
13
+ args = [ ...arguments ].slice(3)
14
+ e = {
15
+ message: String.raw (code, target, ...args),
16
+ target, text: '{0} '+ String.raw (code,'', ...placeholders.slice(0,args.length)).trim(),
17
+ args,
18
+ }
19
+ } else e = {
20
+ message: String.raw (code, ...[...arguments].slice(2))
21
+ }
22
+ } else {
23
+ if (typeof code === 'object') e = code; else {
24
+ if (typeof code === 'number') e = { code }; else [ code, message, target, args, e ] = [ undefined, code, message, target, {} ]
25
+ if (typeof message === 'object') e = Object.assign(message,e); else {
26
+ if (typeof target === 'object') [ target, args ] = [ undefined, target ]
27
+ if (message) e.message = message //; else if (code) e.message = String(code)
28
+ if (target) e.target = target
29
+ if (args) e.args = args
30
+ }
17
31
  }
18
32
  }
19
33
  if (!e.numericSeverity) e.numericSeverity = severity
@@ -32,7 +46,6 @@ class Errors extends Responses {
32
46
  'stack' in e || Error.captureStackTrace (e = Object.assign(new Error,e), cds.Request.prototype.error)
33
47
  return super.push(e)
34
48
  }
35
- throwable() { return this.length > 1 ? Object.assign(new Error('MULTIPLE_ERRORS'), { details: this }) : this[0] }
36
49
  }
37
50
 
38
51
  module.exports = { Responses, Errors }
@@ -1,14 +1,14 @@
1
1
  module.exports = ()=> {
2
2
 
3
3
  const cds = require ('../../index')
4
- const context_model_required = cds.requires.extensibility || cds.requires.toggles || cds.mtx
4
+ const context_model_required = cds.requires.extensibility || cds.requires.toggles
5
5
  if (!context_model_required) return []
6
6
 
7
7
  const { model4 } = require('../srv-models')
8
8
  return async function cds_context_model (req,res, next) {
9
9
  if (req.baseUrl.startsWith('/-/')) return next() //> our own tech services cannot be extended
10
10
  const ctx = cds.context
11
- if (ctx.tenant) try {
11
+ if (ctx.tenant || ctx.features) try {
12
12
  // if (req.headers.features) ctx.user.features = req.headers.features //> currently done in basic-auth only
13
13
  ctx.model = req.__model = await model4 (ctx.tenant, ctx.features) // REVISIT: req.__model is because of Okra
14
14
  } catch (e) {
@@ -4,6 +4,6 @@ module.exports = ()=> function cds_error_handler (err, req, res, next) {
4
4
  // res.status (n >= 400 && n < 600 ? n : 500)
5
5
  // err.status = 400
6
6
  // res.json ({ ...err, message: err.message, stack: err.stack })
7
- // if (err.status === 401 && req.login) return req.login()
7
+ // if (err.status === 401 && req._login) return req._login()
8
8
  next (err)
9
9
  }
@@ -8,6 +8,7 @@ class LegacyProtocolAdapter extends ProtocolAdapter {
8
8
 
9
9
  static init() {
10
10
  return this.protocols = {
11
+ "odata-v4": { get impl() { return libx.to.odata_v4 } },
11
12
  "odata": { get impl() { return libx.to.odata_v4 } },
12
13
  "rest": { get impl() { return libx.to.rest } },
13
14
  }