@sap/cds 6.8.4 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/CHANGELOG.md +58 -5
  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 +1 -1
  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 +1 -1
  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/srv-api.js +9 -3
  45. package/lib/srv/srv-dispatch.js +12 -9
  46. package/lib/srv/srv-models.js +4 -21
  47. package/lib/srv/srv-tx.js +15 -12
  48. package/lib/utils/cds-test.js +14 -9
  49. package/lib/utils/cds-utils.js +2 -12
  50. package/lib/utils/check-version.js +17 -0
  51. package/{bin/build → lib/utils}/csv-reader.js +23 -24
  52. package/libx/_runtime/auth/index.js +27 -23
  53. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +15 -72
  54. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -1
  55. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +0 -2
  56. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +33 -63
  57. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +14 -18
  58. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +15 -5
  59. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +5 -4
  60. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +37 -40
  61. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/updateToCQN.js +7 -1
  62. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +101 -38
  63. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/errors/AbstractError.js +5 -1
  64. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/ValueConverter.js +2 -1
  65. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/ResourceJsonDeserializer.js +9 -8
  66. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -1
  67. package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +15 -11
  68. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +4 -0
  69. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +5 -2
  70. package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +1 -123
  71. package/libx/_runtime/cds-services/services/Service.js +79 -107
  72. package/libx/_runtime/cds-services/services/utils/columns.js +23 -19
  73. package/libx/_runtime/cds-services/services/utils/compareJson.js +11 -1
  74. package/libx/_runtime/cds-services/services/utils/differ.js +7 -2
  75. package/libx/_runtime/cds-services/util/assert.js +65 -2
  76. package/libx/_runtime/common/composition/data.js +1 -0
  77. package/libx/_runtime/common/generic/auth/expand.js +1 -1
  78. package/libx/_runtime/common/generic/auth/restrict.js +5 -10
  79. package/libx/_runtime/common/generic/auth/restrictions.js +40 -0
  80. package/libx/_runtime/common/generic/auth/utils.js +1 -2
  81. package/libx/_runtime/common/generic/crud.js +32 -16
  82. package/libx/_runtime/common/generic/etag.js +133 -104
  83. package/libx/_runtime/common/generic/input.js +6 -21
  84. package/libx/_runtime/common/generic/put.js +1 -1
  85. package/libx/_runtime/common/generic/stream.js +52 -0
  86. package/libx/_runtime/common/generic/temporal.js +25 -8
  87. package/libx/_runtime/common/i18n/messages.properties +0 -2
  88. package/libx/_runtime/common/utils/cqn.js +1 -1
  89. package/libx/_runtime/common/utils/cqn2cqn4sql.js +5 -2
  90. package/libx/_runtime/common/utils/csn.js +0 -51
  91. package/libx/_runtime/common/utils/etag.js +30 -0
  92. package/libx/_runtime/common/utils/keys.js +1 -1
  93. package/libx/_runtime/common/utils/normalizeTimestamp.js +25 -0
  94. package/libx/_runtime/common/utils/path.js +1 -1
  95. package/libx/_runtime/common/utils/resolveView.js +2 -1
  96. package/libx/_runtime/common/utils/rewriteAsterisks.js +6 -4
  97. package/libx/_runtime/common/utils/search2cqn4sql.js +12 -16
  98. package/libx/_runtime/common/utils/stream.js +140 -0
  99. package/libx/_runtime/common/utils/streamProp.js +29 -12
  100. package/libx/_runtime/common/utils/templateProcessorPathSerializer.js +0 -2
  101. package/libx/_runtime/db/generic/index.js +0 -2
  102. package/libx/_runtime/db/query/delete.js +2 -2
  103. package/libx/_runtime/db/query/insert.js +2 -2
  104. package/libx/_runtime/db/query/read.js +2 -2
  105. package/libx/_runtime/db/query/run.js +2 -2
  106. package/libx/_runtime/db/query/update.js +2 -2
  107. package/libx/_runtime/db/sql-builder/BaseBuilder.js +0 -6
  108. package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +23 -12
  109. package/libx/_runtime/db/sql-builder/FunctionBuilder.js +18 -6
  110. package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -0
  111. package/libx/_runtime/db/sql-builder/SelectBuilder.js +3 -7
  112. package/libx/_runtime/db/sql-builder/UpsertBuilder.js +1 -0
  113. package/libx/_runtime/db/utils/normalizeTimeData.js +7 -3
  114. package/libx/_runtime/fiori/draft.js +2 -0
  115. package/libx/_runtime/fiori/generic/activate.js +8 -9
  116. package/libx/_runtime/fiori/generic/before.js +30 -20
  117. package/libx/_runtime/fiori/generic/cancel.js +5 -3
  118. package/libx/_runtime/fiori/generic/delete.js +5 -3
  119. package/libx/_runtime/fiori/generic/edit.js +7 -7
  120. package/libx/_runtime/fiori/generic/index.js +10 -16
  121. package/libx/_runtime/fiori/generic/new.js +5 -3
  122. package/libx/_runtime/fiori/generic/patch.js +11 -8
  123. package/libx/_runtime/fiori/generic/prepare.js +13 -6
  124. package/libx/_runtime/fiori/generic/read.js +12 -6
  125. package/libx/_runtime/fiori/lean-draft.js +207 -152
  126. package/libx/_runtime/fiori/utils/delete.js +10 -5
  127. package/libx/_runtime/fiori/utils/req.js +17 -5
  128. package/libx/_runtime/fiori/utils/stream.js +36 -0
  129. package/libx/_runtime/hana/Service.js +12 -9
  130. package/libx/_runtime/hana/conversion.js +10 -15
  131. package/libx/_runtime/hana/driver.js +2 -0
  132. package/libx/_runtime/hana/execute.js +28 -6
  133. package/libx/_runtime/hana/pool.js +36 -122
  134. package/libx/_runtime/hana/search2cqn4sql.js +34 -36
  135. package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +2 -6
  136. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +3 -1
  137. package/libx/_runtime/messaging/enterprise-messaging.js +10 -58
  138. package/libx/_runtime/messaging/outbox/utils.js +1 -1
  139. package/libx/_runtime/remote/Service.js +20 -1
  140. package/libx/_runtime/remote/utils/client.js +3 -5
  141. package/libx/_runtime/sqlite/Service.js +4 -6
  142. package/libx/_runtime/sqlite/conversion.js +3 -13
  143. package/libx/_runtime/sqlite/customBuilder/CustomFunctionBuilder.js +9 -6
  144. package/libx/_runtime/sqlite/customBuilder/CustomUpsertBuilder.js +6 -1
  145. package/libx/_runtime/sqlite/execute.js +5 -16
  146. package/libx/odata/afterburner.js +22 -6
  147. package/libx/odata/grammar.pegjs +6 -1
  148. package/libx/odata/parser.js +1 -1
  149. package/libx/rest/RestAdapter.js +16 -9
  150. package/libx/rest/RestRequest.js +1 -1
  151. package/libx/rest/middleware/input.js +2 -1
  152. package/libx/rest/middleware/operation.js +1 -0
  153. package/libx/rest/middleware/parse.js +3 -2
  154. package/libx/rest/middleware/payload.js +9 -8
  155. package/libx/rest/middleware/read.js +1 -0
  156. package/package.json +9 -16
  157. package/app/fiori/preview.js +0 -270
  158. package/app/fiori/routes.js +0 -59
  159. package/bin/build/buildTaskEngine.js +0 -360
  160. package/bin/build/buildTaskFactory.js +0 -283
  161. package/bin/build/buildTaskHandler.js +0 -241
  162. package/bin/build/buildTaskProvider.js +0 -22
  163. package/bin/build/buildTaskProviderFactory.js +0 -175
  164. package/bin/build/cds.js +0 -5
  165. package/bin/build/constants.js +0 -66
  166. package/bin/build/index.js +0 -58
  167. package/bin/build/provider/buildTaskHandlerEdmx.js +0 -82
  168. package/bin/build/provider/buildTaskHandlerFeatureToggles.js +0 -131
  169. package/bin/build/provider/buildTaskHandlerInternal.js +0 -254
  170. package/bin/build/provider/buildTaskProviderInternal.js +0 -383
  171. package/bin/build/provider/fiori/index.js +0 -171
  172. package/bin/build/provider/hana/2migration.js +0 -179
  173. package/bin/build/provider/hana/index.js +0 -505
  174. package/bin/build/provider/hana/migrationtable.js +0 -472
  175. package/bin/build/provider/hana/template/.hdiconfig-haas +0 -163
  176. package/bin/build/provider/hana/template/.hdiconfig-hanacloud +0 -137
  177. package/bin/build/provider/hana/template/.hdinamespace +0 -4
  178. package/bin/build/provider/hana/template/package.json +0 -12
  179. package/bin/build/provider/hana/template/undeploy.json +0 -5
  180. package/bin/build/provider/java/index.js +0 -111
  181. package/bin/build/provider/java-cf/index.js +0 -1
  182. package/bin/build/provider/mtx/index.js +0 -268
  183. package/bin/build/provider/mtx/resourcesTarBuilder.js +0 -95
  184. package/bin/build/provider/mtx-extension/index.js +0 -131
  185. package/bin/build/provider/mtx-sidecar/index.js +0 -137
  186. package/bin/build/provider/node-cf/index.js +0 -1
  187. package/bin/build/provider/nodejs/index.js +0 -192
  188. package/bin/build/util.js +0 -299
  189. package/bin/cds.js +0 -125
  190. package/bin/deploy/to-hana/cfUtil.js +0 -355
  191. package/bin/deploy/to-hana/gitUtil.js +0 -57
  192. package/bin/deploy/to-hana/hana.js +0 -306
  193. package/bin/deploy/to-hana/hdiDeployUtil.js +0 -153
  194. package/bin/deploy/to-hana/index.js +0 -16
  195. package/bin/deploy/to-hana/mtaUtil.js +0 -170
  196. package/bin/mtx/in-cds.js +0 -17
  197. package/bin/plugins.js +0 -32
  198. package/bin/run.js +0 -24
  199. package/bin/utils/log.js +0 -24
  200. package/bin/version.js +0 -178
  201. package/libx/_runtime/audit/Service.js +0 -222
  202. package/libx/_runtime/audit/generic/personal/access.js +0 -61
  203. package/libx/_runtime/audit/generic/personal/index.js +0 -56
  204. package/libx/_runtime/audit/generic/personal/modification.js +0 -132
  205. package/libx/_runtime/audit/generic/personal/utils.js +0 -186
  206. package/libx/_runtime/audit/utils/log.js +0 -23
  207. package/libx/_runtime/audit/utils/v2.js +0 -176
  208. package/libx/_runtime/db/data-conversion/timestamp.js +0 -9
  209. package/libx/_runtime/db/generic/integrity.js +0 -455
  210. package/srv/audit-log.cds +0 -87
  211. package/srv/mtx.cds +0 -2
  212. package/srv/mtx.js +0 -8
  213. /package/lib/{core → linked}/classes.js +0 -0
  214. /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,7 +1,7 @@
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')
@@ -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
  }
@@ -1,38 +1,29 @@
1
- const cds = require ('../../index'), { decodeURIComponent } = cds.utils
2
- const LOG = cds.log('graphql')
3
-
4
1
  const GraphQLAdapter = require('@cap-js/graphql') // eslint-disable-line cds/no-missing-dependencies
5
2
  const express = require ('express') // eslint-disable-line cds/no-missing-dependencies
6
3
 
7
4
  function CDSGraphQLAdapter (options) {
8
-
9
- const {services} = options
5
+ const { services } = options
10
6
 
11
7
  return express.Router()
12
8
  .use (express.json()) //> required in the slug handlers and logger below
13
9
 
14
- /** Convenience slug route for /graphql/srv/entity/id */
15
- .use ('/:path/:entity/:id?(%20:query)?', (req,_,next) => {
10
+ // convenience slug route for /graphql/srv/entity/id
11
+ .use ('/:path/:entity/:id?(%20:query)?', (req, _, next) => {
16
12
  // TODO: add filter by id -> then remove the // eslint-disable-line
17
- let { entity, id, query } = req.params // eslint-disable-line no-unused-vars
13
+ const { entity, query } = req.params // eslint-disable-line no-unused-vars
18
14
  if (query) req.body = { query }
19
15
  if (entity) req.body.query = req.body.query.replace(/{/, `{ ${entity} {`) +'}'
20
16
  next() //> goes on below
21
17
  })
22
18
 
23
- /** Convenience slug route for /graphql/srv */
19
+ // convenience slug route for /graphql/srv
24
20
  .use ('/:path', (req, res, next) => {
25
- let srv = services [req.params.path]
21
+ const srv = services [req.params.path]
26
22
  if (req.body) req.body.query = req.body.query.replace(/{/, `{ ${srv.name} {`) +'}'
27
23
  next() //> goes on below
28
24
  })
29
25
 
30
- .use ((req,_,next)=>{
31
- LOG.info (req.method, req.body?.query || decodeURIComponent(req.query.query))
32
- next()
33
- })
34
-
35
- /** The global /graphql route */
26
+ // the global /graphql route
36
27
  .use (new GraphQLAdapter (options))
37
28
  }
38
29